NQCModels.jl
To perform nonadiabatic molecular dynamics simulations, it is necessary to define the system Hamiltonian. For simple models, this often comes in the form of small matrix in the diabatic representation but equally the electronic Hamiltonian could be obtained directly from ab initio electronic structure theory.
NQCModels.jl
is a package that aims to provide a common interface for defining these models that is flexible enough to allow for a wide range of specifications and requirements. NQCDynamics.jl
uses this interface to obtain the potentials and couplings necessary to perform the dynamics simulations. Along with the minimal interface, NQCModels.jl
also provides a small set of popular models often used in the field of nonadiabatic dynamics.
Taking advantages of Julia's seamless modularity, NQCModels.jl
is designed as a separate package so that it can also be used independently from the main package.
Depending on the quantities provided by the Model
, we use Julia's abstract type system to group models that provide the same quantities. Currently, there are two top-level abstract types: AdiabaticModel
and DiabaticModel
. The AdiabaticModel
is used for adiabatic dynamics, providing only the potential and force used in classical mechanics. The DiabaticModel
is used for nonadiabatic dynamics, where the potential is instead a Hermitian
matrix.
In the Getting started section we briefly touched on how the AdiabaticModel
works and introduced one of the included models. Here let's take a look at a DiabaticModel
, which is more appropriate for nonadiabatic dynamics.
The DoubleWell
is a two state, 1 dimensional model where each state is harmonic with linear coupling to the single degree of freedom.
using NQCModels
model = DoubleWell()
DoubleWell{Int64, Int64, Int64, Int64}
mass: Int64 1
ω: Int64 1
γ: Int64 1
Δ: Int64 1
Our DoubleWell
implements the functions potential
, derivative
, nstates
and ndofs
that return the potential, the derivative of the potential, the number of states, and the number of degrees of freedom, respectively.
julia> potential(model, 0.2)
2×2 LinearAlgebra.Hermitian{Float64, StaticArraysCore.SMatrix{2, 2, Float64, 4}} with indices SOneTo(2)×SOneTo(2): 0.302843 0.5 0.5 -0.262843
julia> derivative(model, 0.2)
2×2 LinearAlgebra.Hermitian{Float64, StaticArraysCore.SMatrix{2, 2, Float64, 4}} with indices SOneTo(2)×SOneTo(2): 1.61421 0.0 0.0 -1.21421
julia> nstates(model)
2
julia> ndofs(model)
1
Since this is a 1D model, the position argument that appears in the derivative and the potential is a real number. For higher dimensional models with multiple atoms, the position will need to be provided as an AbstractMatrix
.
To understand how this can extend to another dimension, we can take a quick look at the GatesHollowayElbow
model which is another two state diabatic model, but this one uses two dimensions to model a diatomic molecule interacting with a surface. The two coordinates are the molecular bond length and the distance from the surface. Technically, the model has been defined such that there are two atoms, each with only a single degree of freedom. This allows us to use different masses for each of the coordinates when performing dynamics.
julia> model = GatesHollowayElbow()
GatesHollowayElbow λ₁: Float64 3.5 λ₂: Float64 3.5 z₀: Float64 1.4 x₀: Float64 0.6 α: Float64 1.028 d: Float64 0.17161933455967182 z12: Float64 0.5 c: Float64 0.018374661087759297 γ: Float64 1.0
julia> potential(model, [1.0 1.0])
2×2 LinearAlgebra.Hermitian{Float64, StaticArraysCore.SMatrix{2, 2, Float64, 4}} with indices SOneTo(2)×SOneTo(2): 0.0710215 0.0111448 0.0111448 0.0744945
julia> derivative(model, [1.0 1.0])
1×2 Matrix{LinearAlgebra.Hermitian{Float64, StaticArraysCore.SMatrix{2, 2, Float64, 4}}}: [0.0810696 0.0; 0.0 -0.0129425] … [-0.000787036 -0.0111448; -0.0111448 0.0810696]
julia> nstates(model)
2
julia> ndofs(model)
1
Here we see how the derivative now becomes a Matrix
with size matching our input, but each entry is a Hermitian
containing the elementwise derivative of the potential with respect to each degree of freedom. In this case, the Matrix
has size = (1, 2)
, but it should be clear how this can extend to arbitrary numbers of atoms and degrees of freedom for complex models.
The models currently available can be seen in type tree of the Model
below. The leaves of the tree are the concrete models, whereas each branch is one of the abstract types. Each of these models can be seen in the Analytic model library and many shall return later when we investigate the dynamics methods.
Model
├─ AdiabaticModel
│ ├─ AdiabaticASEModel
│ ├─ AdiabaticStateSelector
│ ├─ AveragedPotential
│ ├─ BosonBath
│ ├─ DarlingHollowayElbow
│ ├─ DiatomicHarmonic
│ ├─ Free
│ ├─ Harmonic
│ ├─ Morse
│ └─ AdiabaticFrictionModel
│ ├─ CompositeFrictionModel
│ ├─ H2AgModel
│ └─ LDFAModel
└─ DiabaticModel
├─ DoubleWell
├─ ErpenbeckThoss
├─ GatesHollowayElbow
├─ MiaoSubotnik
├─ AnanthModel
│ ├─ AnanthModelOne
│ └─ AnanthModelTwo
├─ LargeDiabaticModel
│ ├─ AndersonHolstein
│ └─ DiabaticFrictionModel
│ ├─ OuyangModelOne
│ ├─ Scattering1D
│ └─ WideBandBath
├─ TullyModel
│ ├─ TullyModelOne
│ ├─ TullyModelThree
│ └─ TullyModelTwo
├─ SpinBoson
└─ ThreeStateMorse
To learn more about NQCModels.jl and learn how to implement new models, visit the developer documentation.