Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analysis functions for diatomic molecules. #329

Merged
merged 32 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
85c0ae0
Add Analysis submodule and diatomic molecule analysis functions.
Alexsp32 Jan 4, 2024
c354fc7
Add Structure submodule from NQCBase
Alexsp32 Jan 5, 2024
66761d8
Forgot to export some DynamicsOutputs
Alexsp32 Jan 5, 2024
522a879
Fixed a few self-references
Alexsp32 Jan 5, 2024
3f13330
Analysis should load properly now
Alexsp32 Jan 5, 2024
1f42249
Cleanup
Alexsp32 Jan 5, 2024
b964431
Update docs for Analysis module
Alexsp32 Jan 11, 2024
61e8710
Possible fix for OutputDesorptionTrajectory
Alexsp32 Jan 11, 2024
54f50e4
Update docstrings, fix a type issue
Alexsp32 Jan 11, 2024
799620e
Made another mistake in struct definition
Alexsp32 Jan 11, 2024
342861c
Updated OutputDesorptionAngle, OutputDesorptionTrajectory
Alexsp32 Jan 11, 2024
b0f73e3
Updated Docs for additions
Alexsp32 Jan 11, 2024
4bdbdb0
Add rudimentary tests for NQCDynamics.Structure
Alexsp32 Jan 11, 2024
91b21e9
Fixed issue with new Outputs
Alexsp32 Jan 11, 2024
367c264
Simulation is in under Solution.prob, not under Solution
Alexsp32 Jan 11, 2024
f51aa95
Another attempt at fixing docs
Alexsp32 Jan 11, 2024
58f38ed
Logic error in tests
Alexsp32 Jan 11, 2024
3fb6fcb
Another mistake in tests and hopefully fixed docs refs
Alexsp32 Jan 12, 2024
d7f16e2
I am very confused by Documenter.jl
Alexsp32 Jan 12, 2024
b0cbc0c
Another test for cross-references
Alexsp32 Jan 12, 2024
379bf2e
Prevent BoundsError in OutputDesorptionTrajectory
Alexsp32 Jan 30, 2024
27268e6
Replaced explicit DynamicsVariables array types with AbstractVector
Alexsp32 Apr 8, 2024
e6b22f7
Improved method definitions, possible efficiency gain by using views
Alexsp32 Apr 8, 2024
a0ffb6b
This was a major memory hog - using views and pre-allocating v_com ar…
Alexsp32 Apr 8, 2024
3349b33
New desorption detection function from DiatomicBasics.jl
Alexsp32 Apr 8, 2024
292e746
Add unit tests for diatomic analysis functions for desorption
Alexsp32 Apr 8, 2024
e5678a7
And now the unit test works
Alexsp32 Apr 8, 2024
ea22d44
Add "Analysis" group to unit testing
Alexsp32 Apr 8, 2024
1bbd0d1
Version bump for merge
Alexsp32 Apr 13, 2024
0b9c69e
Added explanation for Structure module scope
Alexsp32 Apr 13, 2024
44780cd
Fixed wrong function name in docstring
Alexsp32 Apr 13, 2024
a347cdb
Merge branch 'main' into diatomicbasics
Alexsp32 Apr 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ end
"dynamicssimulations/dynamicssimulations.md"
find_all_files("dynamicssimulations/dynamicsmethods")
]
"Outputs and Analysis" => find_all_files("output_and_analysis")
"Examples" => find_all_files("examples")
"integration_algorithms.md"
"Developer documentation" => find_all_files("devdocs")
Expand Down
14 changes: 14 additions & 0 deletions docs/src/api/NQCDynamics/analysis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```@setup logging
@info "Expanding src/api/NQCDynamics/analysis.md..."
start_time = time()
```
# Analysis

```@autodocs
Modules=[NQCDynamics.Analysis, NQCDynamics.Analysis.Diatomic]
```

```@setup logging
runtime = round(time() - start_time; digits=2)
@info "...done after $runtime s."
```
14 changes: 14 additions & 0 deletions docs/src/api/NQCDynamics/structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```@setup logging
@info "Expanding src/api/NQCDynamics/structure.md..."
start_time = time()
```
# Structure

```@autodocs
Modules=[NQCDynamics.Structure]
```

```@setup logging
runtime = round(time() - start_time; digits=2)
@info "...done after $runtime s."
```
2 changes: 1 addition & 1 deletion docs/src/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ For classical dynamics we also provide a timestep `dt` since we're using the

The final keyword argument `output` is used to specify the quantities we want
to save during the dynamics.
A list of the available quantities can be found [here](@ref DynamicsOutputs).
A list of the available quantities can be found [here](@ref NQCDynamics.DynamicsOutputs).

!!! tip "Output format"

Expand Down
42 changes: 42 additions & 0 deletions docs/src/output_and_analysis/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# [Simulations outputs and analysis functions](@id output_and_analysis)

NQCDynamics.jl is able to output a variety of common observables when running simulations with the `run_dynamics` function. Further output functions can be implemented easily as well.

In this section you will find an overview of all available output types, as well as explanations of some common analysis functions in the realm of surface chemistry which we have implemented in the package.

## DynamicsOutputs

In many examples within this documentation, you have seen calls to `run_dynamics`:

```julia
ensemble = run_dynamics(sim, tspan, distribution;selection=1:20,
dt=0.1u"fs", output=OutputPosition, trajectories=20, callback=terminate)
```

Within `run_dynamics`, the `output` argument specifies the desired output values for each trajectory. `output` can either be given as a single function, or as a tuple of multiple output functions, for example:

```julia
output=OutputPosition # or
output=(OutputPosition, OutputVelocity, OutputKineticEnergy)

ensemble[3][:OutputPosition] # will output the positions at all timesteps in trajectory 3
```

Every output type is a function which can use the [`DynamicsVariables`](@ref) and [`Simulation`](@ref) values of the respective trajectory, allowing you to create custom output types of any kind. See the [developer documentation] for more information on how to implement a custom output type.

You can find an overview of all available output types in the [`DynamicsOutputs`](@ref NQCDynamics.DynamicsOutputs) API.

## Analysis functions

The [Analysis](@ref Analysis) submodule in NQCDynamics contains functions commonly used in the analysis of trajectories to make the analysis of existing trajectories easier.
Ideally, most observable quantities could be implemented with a combination of [`DynamicsOutputs`](@ref NQCDynamics.DynamicsOutputs) and `Reduction` types, however we might want to data from existing ensemble simulations where re-running the entire set of trajectories is impractical.

As a result, most functions in the `Analysis` submodule are also implemented as a `DynamicsOutput`.

### Convenient functions for periodic structures
[`NQCDynamics.Structure`](@ref Structure) contains several useful functions for periodic structures, such as `pbc_distance, pbc_center_of_mass`.

These functions take into account periodic copies of the atoms in question, returning the respective values for the closest set of periodic copies.

### Analysis of diatomic molecules
[`NQCDynamics.Analysis.Diatomic`](@ref Analysis)
18 changes: 18 additions & 0 deletions src/Analysis/Analysis.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
Analysis functions common enough to be included in the main package.
"""
module Analysis
using Reexport: @reexport

# Diatomic analysis functions @alexsp32
include("diatomic.jl")
export Diatomic

# Rebinding of quantise_diatomic under Analysis.
using NQCDynamics: InitialConditions
function quantise_diatomic(sim, v, r; args...)
InitialConditions.QuantisedDiatomic.quantise_diatomic(sim, v, r; args...)

Check warning on line 14 in src/Analysis/Analysis.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/Analysis.jl#L13-L14

Added lines #L13 - L14 were not covered by tests
end
export quantise_diatomic

end
125 changes: 125 additions & 0 deletions src/Analysis/diatomic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
"""
Analysis functions for surface chemistry of diatomic molecules.
"""
module Diatomic
using NQCDynamics: AbstractSimulation, Simulation, get_positions, Structure
using NQCBase
using Unitful, UnitfulAtomic
using LinearAlgebra

"""
get_desorption_frame(trajectory::Vector, diatomic_indices::Vector{Int}, simulation::AbstractSimulation;surface_normal::Vector=[0,0,1], surface_distance_threshold=5.0*u"Å")

Determines the index in a trajectory where surface desorption begins.

This is evaluated using two conditions:

1. In the trajectory, the diatomic must be `surface_distance_threshold` or further away from the highest other atom. (In `surface_normal` direction).

2. Desorption begins at the turning point of the centre of mass velocity component along `surface_normal`, indicating overall movement away from the surface.
"""
function get_desorption_frame(trajectory::Vector, diatomic_indices::Vector{Int}, simulation::AbstractSimulation;surface_normal::Vector = [0,0,1], surface_distance_threshold = 5.0*u"Å")

Check warning on line 21 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L21

Added line #L21 was not covered by tests
# Two criteria: Distance between two atoms (wrt PBC) must be below `distance_threshold` and CoM velocity must be positive wrt surface normal vector.
function surface_distance_condition(x)
highest_z = max(get_positions(x)[3, symdiff(1:end, diatomic_indices)]...)
if abs(au_to_ang(Structure.pbc_center_of_mass(x, diatomic_indices..., simulation)[3] - highest_z)) * u"Å" ≥ surface_distance_threshold
@debug "Surface distance condition evaluated true"
return true

Check warning on line 27 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L23-L27

Added lines #L23 - L27 were not covered by tests
else
return false

Check warning on line 29 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L29

Added line #L29 was not covered by tests
end
end
function com_velocity_condition(x)
if dot(Structure.velocity_center_of_mass(x, diatomic_indices..., simulation), normalize(surface_normal)) > 0
@debug "Normal velocity condition evaluated true"
return true

Check warning on line 35 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L32-L35

Added lines #L32 - L35 were not covered by tests
else
return false

Check warning on line 37 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L37

Added line #L37 was not covered by tests
end
end
desorbed_frame = findfirst(surface_distance_condition, trajectory)
if isa(desorbed_frame, Nothing)
@debug "No desorption event found. "
return nothing

Check warning on line 43 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L40-L43

Added lines #L40 - L43 were not covered by tests
else
@debug "Found desorption event in frame $(desorbed_frame)"
leaving_surface_frame = findfirst(!com_velocity_condition, reverse(trajectory[1:desorbed_frame]))
if isa(leaving_surface_frame, Nothing)
@debug "Couldn't find a sub-zero CoM velocity component relative to surface normal."
return nothing

Check warning on line 49 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L45-L49

Added lines #L45 - L49 were not covered by tests
else
return desorbed_frame - leaving_surface_frame

Check warning on line 51 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L51

Added line #L51 was not covered by tests
end
end
end

function get_desorption_angle(trajectory::Vector, indices::Vector{Int}, simulation::AbstractSimulation; surface_normal = [0,0,1], surface_distance_threshold = 5.0*u"Å")

Check warning on line 56 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L56

Added line #L56 was not covered by tests
# First determine where the reaction occurred on the surface.
desorption_frame = get_desorption_frame(trajectory, indices, simulation;surface_distance_threshold = surface_distance_threshold, surface_normal = surface_normal)
if isa(desorption_frame, Nothing)
@debug "No desorption event detected in trajectory"
return nothing

Check warning on line 61 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L58-L61

Added lines #L58 - L61 were not covered by tests
end
@debug "Desorption frame: $(desorption_frame)"

Check warning on line 63 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L63

Added line #L63 was not covered by tests
# Determine the average centre of mass velocity to decrease error due to vibration and rotation orthogonal to true translational component.
com_velocities = map(x -> Structure.velocity_center_of_mass(x, indices[1], indices[2], simulation), trajectory[desorption_frame:end])
average_velocity = mean(cat(com_velocities...;dims=2);dims=2)

Check warning on line 66 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L65-L66

Added lines #L65 - L66 were not covered by tests
# Now convert into an angle by arccos((a•b)/(|a|*|b|))
return Structure.angle_between(vec(average_velocity), surface_normal)

Check warning on line 68 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L68

Added line #L68 was not covered by tests
end

# 6✖6 Cartesian to internal coordinate transformation.
function transform_to_internal_coordinates(to_transform::Matrix, config::Matrix, index1::Int, index2::Int, sim::Simulation)
U = transform_U(config, index1, index2, sim) # Generate transformation matrix
return transpose(U) * to_transform * U

Check warning on line 74 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L72-L74

Added lines #L72 - L74 were not covered by tests
end

function transform_from_internal_coordinates(to_transform::Matrix, config::Matrix, index1::Int, index2::Int, sim::Simulation)
U_inv = inv(transform_U(config, index1, index2, sim))
return transpose(U_inv) * to_transform * U_inv

Check warning on line 79 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L77-L79

Added lines #L77 - L79 were not covered by tests
end

function transform_r(config, index1::Int, index2::Int)
return sqrt(sum(mapslices(x->(x[2]-x[1])^2, config[:, [index1, index2]];dims=2)))

Check warning on line 83 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L82-L83

Added lines #L82 - L83 were not covered by tests
end

function transform_r1(config, index1::Int, index2::Int)
return transform_r(config[1:2, :], index1, index2)

Check warning on line 87 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L86-L87

Added lines #L86 - L87 were not covered by tests
end


"""
transform_U(config::Matrix, index1::Int, index2::Int, sim::Simulation)

Builds diatomic Cartesian to internal coordinate transformation matrix as described in the SI of `10.1021/jacsau.0c00066`
"""
function transform_U(config::Matrix, index1::Int, index2::Int, sim::Simulation)
masses = Structure.fractional_mass(sim, index1, index2)
config[:,index2] .+= Structure.minimum_distance_translation(config, index1, index2, sim) # PBC wrap positions for correct transformation.
r = transform_r(config, index1, index2)
r1 = transform_r1(config, index1, index2)
unity = LinearAlgebra.I(3)
U_i1 = vcat(
mapslices(x->(x[1]-x[2])/r, config[:, [index1, index2]]; dims=2),
mapslices(x->(x[2]-x[1])/r, config[:, [index2, index1]]; dims=2),

Check warning on line 104 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L96-L104

Added lines #L96 - L104 were not covered by tests
)
U_i2 = vcat(
mapslices(x->(x[2]-x[1])*(config[3, index2]-config[3, index1])/(r^2*r1), config[1:2, [index1, index2]]; dims=2),

Check warning on line 107 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L106-L107

Added lines #L106 - L107 were not covered by tests
-r1/r^2,
mapslices(x->(x[1]-x[2])*(config[3, index2]-config[3, index1])/(r^2*r1), config[1:2, [index2, index1]]; dims=2),

Check warning on line 109 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L109

Added line #L109 was not covered by tests
r1/r^2,
)
U_i3 = [

Check warning on line 112 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L112

Added line #L112 was not covered by tests
-(config[2, index1]-config[2, index2]),
(config[1, index2]-config[1, index1]),
0.0,
-(config[2, index2]-config[2, index1]),
(config[1, index1]-config[1, index2]),
0.0,
] ./ (r1^2)
return hcat(U_i1, U_i2, U_i3, vcat(unity.*masses[1], unity.*masses[2]))

Check warning on line 120 in src/Analysis/diatomic.jl

View check run for this annotation

Codecov / codecov/patch

src/Analysis/diatomic.jl#L120

Added line #L120 was not covered by tests
end

export get_desorption_frame, get_desorption_angle, transform_from_internal_coordinates, transform_to_internal_coordinates, transform_U

end
81 changes: 80 additions & 1 deletion src/DynamicsOutputs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
module DynamicsOutputs

using RingPolymerArrays: get_centroid
using Unitful: @u_str
using UnitfulAtomic: austrip
using LinearAlgebra: norm
using ComponentArrays: ComponentVector

using NQCDynamics:
Estimators,
DynamicsUtils
DynamicsUtils,
Analysis

using NQCModels: NQCModels

Expand All @@ -24,6 +26,9 @@

using ..InitialConditions: QuantisedDiatomic

using NQCBase
using Statistics

"""
OutputVelocity(sol, i)

Expand Down Expand Up @@ -91,6 +96,21 @@
OutputKineticEnergy(sol, i) = DynamicsUtils.classical_kinetic_energy.(sol.prob.p, sol.u)
export OutputKineticEnergy

"""
OutputCentroidKineticEnergy(sol, i)
Alexsp32 marked this conversation as resolved.
Show resolved Hide resolved

Evaluate the classical kinetic energy of a subset of the entire system at each save step.

The subset is defined by `OutputSubsetKineticEnergy(indices)`.
"""
struct OutputSubsetKineticEnergy{T}
indices::T
end
function (output::OutputSubsetKineticEnergy)(sol, i)
return map(x->DynamicsUtils.classical_kinetic_energy(sol.prob.p.atoms.masses[output.indices], x[:, output.indices]), [DynamicsUtils.get_velocities(i) for i in sol.u])

Check warning on line 110 in src/DynamicsOutputs.jl

View check run for this annotation

Codecov / codecov/patch

src/DynamicsOutputs.jl#L109-L110

Added lines #L109 - L110 were not covered by tests
end
export OutputSubsetKineticEnergy

OutputSpringEnergy(sol, i) = DynamicsUtils.classical_spring_energy.(sol.prob.p, sol.u)
export OutputSpringEnergy

Expand Down Expand Up @@ -262,4 +282,63 @@
end
export OutputStateResolvedScattering1D

"""
Outputs the desorption angle in degrees (relative to the surface normal) if a desorption event is detected.
"""
struct OutputDesorptionAngle{I<:Vector{Int},S<:Vector{Float64},D}
indices::I
surface_normal::S
surface_distance_threshold::D
end
"""
OutputDesorptionAngle(indices; surface_normal = [0,0,1], surface_distance_threshold = 5.0u"Å")

Outputs the desorption angle in degrees (relative to the surface normal) if a desorption event is detected.
Use `surface_normal` to define the direction "away" from the surface. Most commonly, this would be in positive z direction.

A desorption is detected if the centre of mass of the molecule defined with `indices` is above `surface_distance_threshold` from the closest surface atom.
This is calculated with respect to `surface_normal` and will take into account periodic boundary conditions.
"""
OutputDesorptionAngle(indices; surface_normal = [0,0,1], surface_distance_threshold = 5.0u"Å") = OutputDesorptionAngle(indices, convert(Vector{Float64},surface_normal), surface_distance_threshold)

Check warning on line 302 in src/DynamicsOutputs.jl

View check run for this annotation

Codecov / codecov/patch

src/DynamicsOutputs.jl#L302

Added line #L302 was not covered by tests
export OutputDesorptionAngle

"""
(output::OutputDesorptionAngle)(sol, i)

Outputs the desorption angle in degrees (relative to the surface normal) if a desorption event was detected.
"""
function (output::OutputDesorptionAngle)(sol, i)
return Analysis.Diatomic.get_desorption_angle(sol.u, output.indices, sol.prob.p; surface_normal=output.surface_normal, surface_distance_threshold=output.surface_distance_threshold)

Check warning on line 311 in src/DynamicsOutputs.jl

View check run for this annotation

Codecov / codecov/patch

src/DynamicsOutputs.jl#L310-L311

Added lines #L310 - L311 were not covered by tests
end

struct OutputDesorptionTrajectory{I<:Vector{Int}, N<:Vector{Float64}, D, F<:Int}
indices::I
surface_normal::N
surface_distance_threshold::D
extra_frames::F
end
"""
`OutputDesorptionTrajectory(indices; surface_normal = [0,0,1], surface_distance_threshold = 5.0u"Å", extra_frames = 0)`

Like OutputDynamicsVariables, but only saves parts of the trajectory where desorption is occurring.

Use `surface_normal` to define the direction "away" from the surface. Most commonly, this would be in positive z direction.

Use `extra_frames` to save additional steps before the desorption event begins.

A desorption is detected if the centre of mass of the molecule defined with `indices` is above `surface_distance_threshold` from the closest surface atom.
This is calculated with respect to `surface_normal` and will take into account periodic boundary conditions.
"""
OutputDesorptionTrajectory(indices; surface_normal = [0,0,1], surface_distance_threshold = 5.0u"Å", extra_frames = 0) = OutputDesorptionTrajectory(indices, convert(Vector{Float64},surface_normal), surface_distance_threshold, extra_frames)

Check warning on line 332 in src/DynamicsOutputs.jl

View check run for this annotation

Codecov / codecov/patch

src/DynamicsOutputs.jl#L332

Added line #L332 was not covered by tests
"""
(output::OutputDesorptionTrajectory)(sol, i)

Only output parts of the trajectory where desorption is occurring.
"""
function (output::OutputDesorptionTrajectory)(sol, i)
desorption_frame = Analysis.Diatomic.get_desorption_frame(sol.u, output.indices, sol.prob.p; surface_distance_threshold=output.surface_distance_threshold, surface_normal=output.surface_normal)
return isa(desorption_frame, Int) ? sol.u[desorption_frame-output.extra_frames:end] : nothing

Check warning on line 340 in src/DynamicsOutputs.jl

View check run for this annotation

Codecov / codecov/patch

src/DynamicsOutputs.jl#L338-L340

Added lines #L338 - L340 were not covered by tests
end
export OutputDesorptionTrajectory

end # module
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const TIMER = TimerOutputs.TimerOutput()
include("energy_evaluation.jl")
include("binding_curve.jl")
include("random_configuration.jl")
include("rigid_rotator.jl")

struct EffectivePotential{JType,T,B,F}
μ::T
Expand Down
29 changes: 29 additions & 0 deletions src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
classical_translational_energy(config::Any, ind1::Union{Int, CartesianIndex}, ind2::Union{Int, CartesianIndex}, sim::Simulation)

Returns the classical translational energy in Hartree
"""
function classical_translational_energy(config::Any, ind1::Union{Int, CartesianIndex}, ind2::Union{Int, CartesianIndex}, sim::Simulation)
return sum(sim.atoms.masses[[ind1, ind2]])/2*norm(velocity_center_of_mass(config, ind1, ind2, sim))^2

Check warning on line 7 in src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl

View check run for this annotation

Codecov / codecov/patch

src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl#L6-L7

Added lines #L6 - L7 were not covered by tests
end

"""
classical_rotation_energy(J::Union{Int, CartesianIndex}, config::Any, ind1::Union{Int, CartesianIndex}, ind2::Union{Int, CartesianIndex}, sim::Simulation)

Classical rotation energy of a rigid diatomic rotor in Hartree
"""
function classical_rotation_energy(J::Union{Int, CartesianIndex}, config::Any, ind1::Union{Int, CartesianIndex}, ind2::Union{Int, CartesianIndex}, sim::Simulation)
I = reduced_mass(sim, ind1, ind2) * austrip(pbc_distance(config, ind1, ind2, sim))^2 # Classical moment of inertia in atomic units.
return J * (J+1) / (2*I)

Check warning on line 17 in src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl

View check run for this annotation

Codecov / codecov/patch

src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl#L15-L17

Added lines #L15 - L17 were not covered by tests
end

"""
harmonic_vibration_energy(ν::Union{Int, CartesianIndex}, k::Float, ind1::Union{Int, CartesianIndex}=1, ind2::Union{Int, CartesianIndex}=2, sim::Simulation)

Vibrational energy of a harmonic oscillator with the force constant k and vibrational level ν.
"""
function harmonic_vibration_energy(ν::Union{Int, CartesianIndex}, k::Float64, ind1::Union{Int, CartesianIndex}, ind2::Union{Int, CartesianIndex}, sim::Simulation)
return (ν + 1/2)*sqrt(k/reduced_mass(sim, ind1, ind2))

Check warning on line 26 in src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl

View check run for this annotation

Codecov / codecov/patch

src/InitialConditions/QuantisedDiatomic/rigid_rotator.jl#L25-L26

Added lines #L25 - L26 were not covered by tests
end

export classical_translational_energy, classical_rotation_energy, harmonic_vibration_energy
Loading
Loading