Developer documentation
Running tests
The tests will automatically include multithreading and/or GPU tests if multiple threads and/or a CUDA-enabled GPU are available. Errors appearing at the start of the test run due to unavailable backends is expected. test/runtests.jl does not include all the tests, see the test directory for more, though these extra tests do not need to be run for every change. Various environmental variables can be set to modify the tests:
VISTESTSdetermines whether to run the GLMakie.jl plotting tests which will error on remote systems where a display is not available, defaultVISTESTS=1.GPUTESTSdetermines whether to run the GPU tests, defaultGPUTESTS=1.DEVICEdetermines which GPU to run the GPU tests on, defaultDEVICE=0.GROUPcan be used to run a subset of the tests, optionsAll/Protein/Gradients/NotGradients, defaultGROUP=All.
The CI run does not carry out all tests - for example the GPU tests are not run - and this is reflected in the code coverage.
Periodic boundary conditions
Molly uses the minimum image convention when applying periodic boundary conditions, meaning that of all the periodic copies of an interacting atom, only the closest is considered. This means that the cutoff distance should not be greater than half of any of the periodic box dimensions, otherwise interactions within the cutoff distance will be missed.
Molly generally keeps all atoms within the "main" periodic box, even when that means splitting molecules over the boundary. This is different to some other software, where molecules are kept whole. In practice this doesn't make too much difference since specific interactions like bonds use the nearest periodic image of an atom. This could lead to issues if a different copy of the atom is the intended interacting atom, but for most molecular systems this is not a problem. It does lead to some complexity in scale_coords!, as molecules have to be made whole before scaling. When writing out files, the default (correction=:pbc) is to move atoms such that molecules are whole. The case where all atoms are in one periodic box can be accessed with correction=:wrap. For more discussion, see the OpenMM FAQs.
Custom neighbor finders
To define your own neighbor finder, first define the struct:
struct MyNeighborFinder
eligible::BitArray{2}
special::BitArray{2}
n_steps::Int
# Any other properties, e.g. a distance cutoff
endExamples of three useful properties are given here: a matrix indicating atom pairs eligible for pairwise interactions, a matrix indicating atoms in a special arrangement such as 1-4 bonding, and a value determining how many time steps occur between each evaluation of the neighbor finder. Then, define the neighbor finding function that is called every step by the simulator:
function Molly.find_neighbors(sys,
nf::MyNeighborFinder,
current_neighbors=nothing,
step_n::Integer=0,
force_recompute::Bool=false;
n_threads::Integer=Threads.nthreads())
if force_recompute || step_n % nf.n_steps == 0
if isnothing(current_neighbors)
neighbors = NeighborList()
else
neighbors = current_neighbors
end
empty!(neighbors)
# Add to neighbors, for example
push!(neighbors, (1, 2, false)) # atom i, atom j and whether they are in a special interaction
return neighbors
else
return current_neighbors
end
endTo use your custom neighbor finder, give it as the neighbor_finder argument when creating the System.
Benchmarks
The benchmark directory contains some benchmarks for the package.