Interface Definition

The AtomsCalculator interface is designed to provide easy to use and easy to read high level functions for standard molecular mechanics, while at the same time being flexible and extensible. Moreover the flexible low-level interface is designed to be compatible with Lux.jl to enable training of parameterized models. Due to this tension (ease of use vs flexibility) there are two alternative ways to call and implement the interface, which are described in separate sections below.

A new calculator need not implement the entire interface, or indeed both interfaces to be useful. Moreover, AtomsCalculators provides various utilities to help with the implementation.

Most interface functions have two common inputs: an AtomsBase.AbstractSystem{D} compatible structure and a "calculator" that specifies details of the calculation method. Throughout this documentation:

  • sys : always specifies a system, usually an AtomsBase.AbstractSystem{D}
  • calc : always specifies a calculator implementing (part of) the AtomsCalculators interface.

High-Level Interface

The high-level interface provides function prototypes for potential energy, forces and virial calculations.

Minimal high-level interface

A minimal implementation of an AtomsCalculators calculator should provide (however, see alternatives below)

Remarks

  • Methods must accept keyword arguments, but they can be ignored. For a discussion of some standard keyword arguments that a calculator may wish to support see Reserved Keyword Arguments.
  • If a calculator does not implement a function, then it can simply choose not to provide that method. A simulator that relies on that function will then simply fail. For example a QM/MM force mixing scheme may be unable to provide potential_energy.

Extended high-level interface

The extended interface can be automatically generated from the minimal interface, but for various reasons (in particular performance), some calculators may prefer to implement their own methods for the following functions.

Several utility functions are derived from energy_unit and length_unit which can be overloaded by a calculator implementation:

A calculator may provide non-allocating and or combined calculations that can sometimes be preferred for performance reasons. All of these return results as a NamedTuple.

To avoid writing too much boiler-plate code to support the full interface, see the utilities section of the docs.

Low-Level Interface

All high-level functionality listed above can also be accessed via "low-level" calls with user-specifiable parameters through calculate methods. The low-level calculate interface follows the Lux model for parameters and state. This means that when calculations are performed with the calculate interface calculators must act as immutable structs that are passed to the calculate function together with parameters and state. All calculations then return an output and a state. Note, we only require calculators act immutable but not to be technically immutable. For example the same calculator can implement the high-level interface and then mutate an internal state.

General structure of the low-level interface

The low level interface is built around a calculate function

where,

  • property is the property to be computed e.g. PotentialEnergy(),
  • sys is an system,
  • calc is a calculator,
  • ps either nothing or a nested NamedTuple storing the calculator parameters,
  • st either nothing or a nested NamedTuple storing the calculator state
  • kwargs... must be allowed but can be ignored; with caveats - see Reserved Keyword Arguments

Irrespective of which property is required, the return type is always a NamedTuple with keys indicating the name of properties being computed. The content of this NamedTuple is not required to be restricted to the requested property (or, properties - more on this below).

Calculator State and Parameters

To manage parameters and state, AtomsCalculators provides prototypes that can be overloaded:

This functionality is somewhat separate from Lux

ps, st = Lux.setup(rng, model)
ps = LuxCore.initparameters(rng, model)

The difference is that Lux.setup initializes parameters, whereas, *_state and *_parameters is intended to read and write existing (already fitted) parameters. In addition, a calculator need not implement LuxCore.initparams and LuxCore.initstate, but it has the option to do so.

The default implementations for *_state and *_parameters assume a stateless and parameter-free calculator.

The calls set_state! and set_parameters! may be mutating (hence the !) but need not be mutating. The correct usage is therefore

new_calc = set_state!(calc, st) 
new_calc = set_parameters!(calc, ps)

In general, the caller should not assume that new_calc and calc are references to the same object.

Molecular mechanics with the low-level interface

The three basic properties to perform molecular mechanics simulations are energy, forces and virials, defined through

With these properties, the following calling conventions are analogous:

  • calculate(Energy(), sys, calc, ps, st) is analogous to potential_energy(sys, calc)
  • calculate(Forces(), sys, calc, ps, st) is analogous to forces(sys, calc)
  • calculate(Virial(), sys, calc, ps, st) is analogous to virial(sys, calc)

Energies, forces and virials can be obtained from the output NamedTuple via

out = calculate(Energy(), sys, calc, ps, st)
out.energy 
out = calculate(Forces(), sys, calc, ps, st)
out.forces
out = calculate(Virial(), sys, calc, ps, st)
out.virial 

Multiple properties

Multiple properties can be requested from a calculator by bundling them into a tuple. For example,

efv = calculate( (Energy(), Forces(), Virial()), sys, calc, ps, st)
efv.energy 
efv.forces 
efv.virial 

Extensions

A calculator can extend the calculate interface without having to make a pull request to AtomsCalculators. For example, a site potential could supply the possibility of returning site energies, which could be implemented as follows.

struct SiteEnergies end 
out = calculate(SiteEnergies(), sys, calc, ps, st)
out.siteenergies::AbstractVector{<: Unitful.Energy}

If such an extension could be of value to a broader developer or user base, then an issue and/or PR to AtomsCalculators would be very welcome.

Recommended Keyword Arguments

The following keyword arguments are used consistently throughout the AtomsBase / AtomsCalculators ecosystem.

  • domain : the domain over which to evaluate an energy, normally used for site potentials where partial energies can be evaluated. Calculators that do not provide this functionality may wish to throw an error is a partial energy is requested to avoid silent bugs.
  • executor : a label or type specifying how to execute the calculator (e.g. in serial, multi-threaded, distributed)
  • nlist : a possibly precomputed neighbourlist