This is a simple package that provides utility functions to compute normal modes from a Hessian matrix.
Additionally, this package gives me a space to ramble about normal modes and I am shamelessly use this README for this purpose.
I find the subject confusing and the introductions describing the problem were of little help to me. Therefore, I think it is worth laying down the basics here.
We are interested in the ground state of an equilibrium Hamiltonian
Then we do a Taylor expansion of the potential, leading to
where
With this potential the Hamiltonian becomes
where
This is the Hamiltionian of a system of coupled harmonic oscillators. The standard procedure is here to change basis and rewrite it as a system of uncoupled harmonic oscillators.
To this end, we introduce the diagonal mass weighting matrix
where
Using
Inserting it in the Hamiltonian we get the following decoupled system of harmonic oscillators (see the annex for the derivation)
From this expression, we can get the normal modes and all associated quantities.
The package aims at providing an interface to normal modes, but what do we mean by normal modes exactly? There are unfortunately multiple reasonnable candidates, namely
- The eigen vectors
${\rm \bf u}_j$ which are the columns of$\rm \bf U$ . They are normed and orthogonal, but live in the mass weighted space. - The columns of
$\rm \bf MU$ . They live in real space, but they are neither normed nor orthogonal. - The columns of
$\rm \bf MU$ normalized. They are still not orthogonal, but at least they have norm 1. In addition, all information about$\rm \bf M$ is removed, which is often needed for further calculations. So those are ofter return together with so-called mode masses, the norm of the columns of$\rm \bf MU$ 5.
As far as I understand, the last ones are the quantities known as normal modes.
Thankfully, to avoid users a slow descent into madness, the package provides a specific object type NormalDecomposition(hessian), that stores the useful information and encapsulate the inner confusing parts.
The available methods acting on a NormalDecompoisition are
normal_modes: The normal modes (in real space). They are useful to see the effect off the vibration on the geometry, for example when plotting them.frequencies: Frequencies of the modes (in GHz).wave_numbers: Wave numbers of the modes (in inverse cm). Sometimes those are also called "frequencies", as they are directly proportional to each other.reduced_mass: Reduced masses of the modes (in AMU), following this question and (I believe) similar to what Gamess does.sample: Perform Wigner sampling, and get the displacements from the mean for positions and momenta.
All the values are given as Unitful quantities.
Data can be loaded from an ORCA hess file, using load_orca(filename, NormalDecomposition).
We want to substitute
By the definition of the diagonal matrix
where
For the other term, we use Leibnitz chain rule, starting with the first derivative only
Next we use
where
Now it would be really beautiful if
as it would make everything collapse. Thankfully with our choice of
Putting it in and using the fact that
Footnotes
-
I am indeed using the julia function
vcatto describe this mathematical operation, I have never found a better way to express it. ↩ -
Which is well defined because in the position representation the potential is just a scalar (and not an operator). ↩
-
Which is the mass of the atom from which this component comes from. In other words, in the mass vector, each mass is repeated 3 times, once for each spatial dimension. ↩
-
Eigenvalue are in theory positive or zero, because the Hamiltonian is semi-positive definite and symmetric. Numerically the smallest eigenvalues can be negative instead of exactly zero. ↩
-
Which is pure lunacy if you ask me. ↩
-
We transpose a scalar, which is a trick I like very much and which is surprisingly useful. ↩