kim-api  2.3.1-git+v2.3.0-git-2-g378406f9.GNU.GNU. An Application Programming Interface (API) for the Knowledgebase of Interatomic Models (KIM).
Implementation

Previous Section: Theory for the Portable Model Interface.

## The KIM API Portable Model Interface (KIM API/PMI)

In code, Portable Models (PMs) and Model Drivers (MDs) consist of up to eight routines which perform specific tasks.

1. The ModelCreate (or ModelDriverCreate ) routine (required), which performs initialization tasks for the KIM::Model object.
2. The ModelComputeArgumentsCreate routine (required), which performs initialization tasks for a KIM::ComputeArguments object.
3. The ModelCompute routine (required), which uses the configuration information stored in a KIM::ComputeArguments object to perform the PM's core computational tasks.
4. The ModelExtension routine (optional), which provides a mechanism for creating and using non-standard extensions to the KIM API.
5. The ModelRefresh routine (required if parameter pointers are set, otherwise should not be provided), which performs updates after a simulator makes changes to the PM's parameters (if this is supported).
6. The ModelWriteParameterizedModel (optional) routine, which can be used to write the parameter files and CMake file necessary to create a new parameterized PM from the current set of in-memory parameters.
7. The ModelComputeArgumentsDestroy routine (required), which performs finalization tasks for a KIM::ComputeArguments object.
8. The ModelDestroy routine (required), which performs finalization tasks for the KIM::Model object.

The KIM API/PMI provides a separate interface to be used by the PM or MD. For each of the routines itemized above, the following table lists (i) the associated KIM::ModelRoutineName extensible enumeration constant, (ii) links to the associated KIM API/PMI interface(s) available within the routine, (iii) links to the routine's prototype (in C++, C, and Fortran), and (iv) whether the KIM API/PMI requires a PM or MD to provide the routine, or if it is optional.

Model Routine Name constant KIM API/PMI Interface Routine prototype (C++; C; Fortran) KIM API/PMI Required / Optional
KIM::MODEL_ROUTINE_NAME::Create KIM::ModelCreate or
KIM::ModelDriverCreate
KIM::ModelCreateFunction,
KIM::ModelDriverCreateFunction;
KIM_ModelCreateFunction,
KIM_ModelDriverCreateFunction;
kim_model_module::kim_model_create
required
KIM::MODEL_ROUTINE_NAME::ComputeArgumentsCreate KIM::ModelComputeArgumentsCreate KIM::ModelComputeArgumentsCreateFunction;
KIM_ModelComputeArgumentsCreateFunction;
kim_model_module::kim_model_compute_arguments_create
required
KIM::MODEL_ROUTINE_NAME::Compute KIM::ModelCompute and
KIM::ModelComputeArguments
KIM::ModelComputeFunction;
KIM_ModelComputeFunction;
kim_model_module::kim_model_compute
required
KIM::MODEL_ROUTINE_NAME::Extension KIM::ModelExtension KIM::ModelExtensionFunction;
KIM_ModelExtensionFunction;
kim_model_module::kim_model_extension
optional
KIM::MODEL_ROUTINE_NAME::Refresh KIM::ModelRefresh KIM::ModelRefreshFunction;
KIM_ModelRefreshFunction;
kim_model_module::kim_model_clear_then_refresh
required if one or more parameter pointers set, otherwise should not be provided
KIM::MODEL_ROUTINE_NAME::WriteParameterizedModel KIM::ModelWriteParameterizedModel KIM::ModelWriteParameterizedModelFunction;
KIM_ModelWriteParameterizedModelFunction;
kim_model_module::kim_model_write_parameterized_model
optional
KIM::MODEL_ROUTINE_NAME::ComputeArgumentsDestroy KIM::ModelComputeArgumentsDestroy KIM::ModelComputeArgumentsDestroyFunction;
KIM_ModelComputeArgumentsDestroyFunction;
kim_model_module::kim_model_compute_arguments_destroy
required
KIM::MODEL_ROUTINE_NAME::Destroy KIM::ModelDestroy KIM::ModelDestroyFunction;
KIM_ModelDestroyFunction;
kim_model_module::kim_model_destroy
required

The above table also indicates which routines must be provided by a PM. For optional routines, each PM must indicate that the routine is required or optional for use by the simulator, as described below.

Note
Language restrictions implied by the KIM API/PMI:
The KIM API/PMI implements a cross-language object-oriented-like framework. All persistent data (analogous to member variables) needed by a PM or MD object must be stored using the Caching Capabilities of the KIM API. For the framework to operate correctly, without surprising behavior, PM and MD implementations must obey certain restrictions as described below.
• C++

The use of static and/or global variables within PM and MD code must be avoided.

• C

The use of static and/or global variables within PM and MD code must be avoided.

• Fortran

The use of COMMON blocks must be avoided. The use of the SAVE attribute must be avoided. Thus, variables should not be initialized when they are declared (as this implies the SAVE attribute). Further, the use of module variables, except for those defined with the PARAMETER attribute, must be avoided. (The Fortran 2008 standard requires that all module variables, implicitly, have the SAVE attribute; that is, they are stored in static memory.) Similarly, all Fortran subroutines and functions should have the RECURSIVE attribute (this is the default starting only with the Fortran 2015 standard). This is because without the RECURSIVE attribute compilers are allowed to use static memory for a subroutine's/function's local variables (effectively giving them the SAVE attribute).

These restrictions are even more important if thread-safety is required. The use of RECURSIVE subroutines/functions and avoidance of using the SAVE attribute help to assure that memory access conflicts are averted.

The KIM API/PMI provides two interfaces to be used by the Simulator, KIM::Model and KIM::ComputeArguments, for interacting with a PM. The interaction between the simulator and a PM involves the following steps:

• A simulator creates a Portable Model object, by calling KIM::Model::Create, that will be used to exchange pointers to data and functions related to the PM between the simulator and PM. Creating this object includes the specification of how the simulator will number particles (zero-based or one-based), determination of the physical base units that the PM will use, and execution of the PM's ModelCreate routine.

When calling KIM::Model::Create to create a PM object, the simulator provides a set of "requested" base units that it would prefer to use. The KIM API/PMI gives the PM final authority to decide on the base units it will use. Best practice for PMs is to respect the request of the simulator and to use the requested base units by converting its parameters appropriately. The requestedUnitsAccepted output argument of the KIM::Model::Create routine is a convenience that allows the simulator a short-cut to determine if its request for base units was accepted. (The alternative is for the simulator to call to KIM::Model::GetUnits and compare the results to the requested units.)

If a base unit is not relevant to the simulator (e.g., a unit of time is not necessary for static equilibrium computations), then the simulator should specify that the corresponding requested base unit(s) is/are "unused". Similarly, if a base unit is irrelevant to the PM (e.g., many models only require units of length and energy; Thus, units of charge, temperature, and time are irrelevant), then the PM should specify that the corresponding base unit(s) is/are "unused" (regardless of the simulator's requested values) when calling KIM::ModelCreate::SetUnits within its ModelCreate routine. Additionally, the PM should select its preferred (non-"unused") base unit value when the simulator provides a request of "unused" for a relevant base unit.

The KIM API/PMI supports "Toy Models", which are a deliberately simplistic model with many details removed so that it can be used to explain a mechanism concisely. Toy models do not model a real material, but are rather associated with a class of materials (e.g., glasses). Toy PMs should use the "user" species values (KIM::SPECIES_NAME::user01 through KIM::SPECIES_NAME::user20). Some toy models are formulated to be nondimensional. Rather than introducing a new type of nondimensional units to the KIM API/PMI with accompanying requirements for simulators to support this, toy PMs should define their length base unit as KIM::LENGTH_UNIT::A and their energy base unit as KIM::ENERGY_UNIT::eV. From the perspective of the toy PM these can be considered proxy units (similar to Lennard-Jones units). (See also Toy Model support within openkim.org.)

• Once a PM object is obtained, the simulator should use KIM::Model::IsRoutinePresent to determine which routines the PM has provided and if they are required or optional. From this information the simulator should determine if it can proceed to work with the PM, or if the PM requires the use of routines that are not supported by the simulator it should exit.
• Next, the simulator creates a KIM::ComputeArguments object, by calling KIM::Model::ComputeArgumentsCreate, that will be used to exchange pointers to data and functions related to the atomic configuration and values being computed for it. Creating this object includes execution of the PM's ModelComputeArgumentsCreate routine.
• Then, to perform a computation, the simulator provides a compute-arguments object to the KIM::Model::Compute routine (which, in part, executes the PM's ModelCompute function).
• There are input compute-arguments that include the various components that make up a configuration (number of particles, particle position vectors, etc.).
• There are output compute-arguments that include the quantities (like partial energy and partial forces), defined in Section Theory for the Portable Model Interface, associated with the configuration.
• There are also compute-callback functions (such as a function to get a particle's neighbor list) that the simulator provides for use by the PM.
• When a simulator is finished working with a PM, it needs to clean up by calling KIM::Model::ComputeArgumentsDestroy (which, in part, executes the PM's ModelComputeArgumentsDestroy routine) to delete each of the compute-arguments objects that were created, and finally calling KIM::Model::Destroy (which, in part, executes the PM's ModelDestroy routine) to delete the KIM::Model object.

The KIM API/PMI provides a list of all compute-arguments and compute-callbacks defined as part of the official API. Each argument and callback has a "Support Status" that can be one of four values: requiredByAPI, notSupported, required, or optional. A PM specifies a support status value, as part of its ModelComputeArgumentsCreate routine, for every compute-argument and compute-callback defined by the KIM API/PMI. Some arguments and callbacks are required by the KIM API and can only have a support status of requiredByAPI. All other arguments and callbacks are not required by the KIM API/PMI, and therefore the PM may set their support status to any one of the three remaining options: required, optional, or notSupported. Just before the PM's ModelComputeArgumentsCreate routine is executed, the KIM API/PMI initializes the support status of all arguments and callbacks to either requiredByAPI or notSupported, as indicated in the below tables. It is the responsibility of the simulator to use the KIM::ComputeArguments object interface to determine the support status of each compute-argument and compute-callback and to use this information to determine if the PM is capable of performing the desired computation.

Below, lists of each input compute-argument, output compute-argument, and compute-callback are provided. To be explicit, zero-based particle numbering is used where necessary.

Input compute-argument table:

Compute Argument Name Unit Data Type Extent Memory Layout Valid Support Statuses (bold – default)
numberOfParticles N/A integer 1 requiredByAPI
particleSpeciesCodes N/A integer numberOfParticles $$sc^{(0)}, sc^{(1)}, \dots$$ requiredByAPI
particleContributing N/A integer numberOfParticles $$c^{(0)}, c^{(1)}, \dots$$ requiredByAPI
coordinates length double numberOfParticles * 3 $$r^{(0)}_1, r^{(0)}_2, r^{(0)}_3, r^{(1)}_1, r^{(1)}_2, \dots$$ requiredByAPI
• numberOfParticles is the number of particles (contributing and non-contributing) in the configuration.
• particleSpeciesCodes contains integer codes (as defined by the PM) specifying the species of each particle. For example, if the PM defines the mapping Cu $$\leftrightarrow 1$$, Al $$\leftrightarrow 2$$, and Ni $$\leftrightarrow 3$$, then $$sc^{(0)} = 3, sc^{(1)} = 1, sc^{(2)} = 2, \dots$$ means that particle 0 is a nickel atom, particle 1 is a copper atom, particle 2 is an aluminum atom.
• particleContributing contains the contributing/non-contributing status of each particle. Particle $$i$$ is contributing if $$c^{(i)} = 1$$ and non-contributing if $$c^{(i)} = 0$$.
• coordinates contains the Cartesian components of the particles' position vectors, $$\mathbf{r}^{(i)} = r^{(i)}_1 \mathbf{e}_1 + r^{(i)}_2 \mathbf{e}_2 + r^{(i)}_3 \mathbf{e}_3$$.

Output compute-argument table:

Compute Argument Name Unit Data Type Extent Memory Layout Valid Support Statuses (bold – default)
partialEnergy energy double 1 required, optional, notSupported
partialForces force double numberOfParticles * 3 $$f^{\mathcal{C}(0)}_1, f^{\mathcal{C}(0)}_2, f^{\mathcal{C}(0)}_3, f^{\mathcal{C}(1)}_1, f^{\mathcal{C}(1)}_2\dots$$ required, optional, notSupported
partialParticleEnergy energy double numberOfParticles $$E^{\mathcal{C}}_0, E^{\mathcal{C}}_1, E^{\mathcal{C}}_2, \dots$$ required, optional, notSupported
partialVirial energy double 6 $$V^{\mathcal{C}}_{11}, V^{\mathcal{C}}_{22}, V^{\mathcal{C}}_{33}, V^{\mathcal{C}}_{23}, V^{\mathcal{C}}_{31}, V^{\mathcal{C}}_{12}$$ required, optional, notSupported
partialParticleVirial energy double numberOfParticles * 6 $$\mathbf{V}^{\mathcal{C}(0)}, \mathbf{V}^{\mathcal{C}(1)}, \mathbf{V}^{\mathcal{C}(2)}, \dots$$ required, optional, notSupported
• partialEnergy is the configuration's partial energy $$E^{\mathcal{C}}$$.
• partialForces contains the partial force vector for each particle, $$\mathbf{f}^{\mathcal{C}(i)} = f^{\mathcal{C}(i)}_1 \mathbf{e}_1 + f^{\mathcal{C}(i)}_2 \mathbf{e}_2 + f^{\mathcal{C}(i)}_3 \mathbf{e}_3$$.
• partialParticleEnergy contains the partial particle energy for each particle, $$E^{\mathcal{C}}_i$$.
• partialVirial is the configuration's partial virial tensor, $$\mathbf{V}^{\mathcal{C}}$$.
• partialParticleVirial contains the partial particle virial tensor for each particle, $$\mathbf{V}^{\mathcal{C}(i)}$$.

Compute-callback table:

Compute Callback Name Valid Support Statuses (bold – default)
GetNeighborList requiredByAPI
ProcessDEDrTerm required, optional, notSupported
ProcessD2EDr2Term required, optional, notSupported
• GetNeighborList is a callback function that allows a PM to obtain the list of neighbors of a particle. The PM may request any number ( $$\ge1$$) of neighbor lists with different (or equal) cutoff distances. The GetNeighborList callback function must support the return of the appropriate list of neighbors. The returned list of neighbors consists of a contiguous-in-memory list of integers corresponding to an unordered full list of a particle's neighbors (not including itself). Each such neighbor list must contain at least all particles within the corresponding cutoff distance of the specified particle. (However, the returned list may contain particles beyond the cutoff distance.) Neighbor lists provided by the simulator must be consistent with the configuration coordinates and the PM's cutoff values. In particular, the PM must, in principle, be able to independently construct its own equivalent neighbor list using just the particle coordinates. Further, the GetNeighborList callback routine must check to ensure that the neighbor list data (provided, via the simulator, by the compute-arguments object) is consistent with the PM's cutoff values.

CAUTION - SIMULATOR DEVELOPERS: In general, it is important that neighbor lists provided by a simulator are "efficient" in the sense that the list contains only a small number of particles that are located outside the cutoff distance. If the lists are not efficient, then the PM computational time may be severely impacted. This is especially true for PMs that request multiple neighbor lists with a wide range of cutoff distances.

Neighbor List Hint: The above describes the default behavior and all PMs must work correctly when provided with neighbor lists of this type. However, based on the neighbor list hint provided by the PM a simulator may provide the PM with a modified neighbor list that is more efficient. If the PM sets its "modelWillNotRequestNeighborsOfNoncontributingParticles" value to 1 (true), it is guaranteeing that it will not request the neighbors of non-contributing particles. In this case, the simulator does not need to generate a neighbor list for such particles. The PM has no way of knowing if the simulator is taking advantage of its hint, so it must work correctly for all types of neighbor lists consistent with its provided hint.

• ProcessDEDrTerm is a callback function that allows for access to the derivatives of the configuration's partial energy, $$E^{\mathcal{C}}$$, with respect to all pair-distances, $$r^{(i,j)}, i,j \in C_{p}$$. That is, it allows the PM to communicate the values of $$\frac{\partial E^{\mathcal{C}}}{\partial r^{(i,j)}}$$ to the simulator. Recall that $$r^{(i,j)}$$ and $$r^{(j,i)}$$ are just two different notations for the same quantity. Thus, there are only $$\frac{\text{numberOfParticles} \cdot (\text{numberOfParticles} + 1)}{2}$$ quantities (as opposed to $$(\text{numberOfParticles})^2$$) referred to by the notation $$\frac{\partial E^{\mathcal{C}}}{\partial r^{(i,j)}}$$.

These quantities can be used to compute many quantities of interest associated with the configuration. For example, it is possible to independently compute the partial virial from this information using the formula

$\mathbf{V}^{\mathcal{C}} = \sum_{i \in C_p} \sum_{j \in \mathcal{N}^{(i)}_{r_{\text{infl}}}} \;\; \sum_{k \not= j; \; k \in \bar{\mathcal{N}}^{(i)}_{r_{\text{infl}}}} \left(\frac{1}{2 r^{(j,k)}} \frac{\partial \tilde{E}_i}{\partial r^{(j,k)}} \right) \mathbf{r}^{(j,k)} \otimes \mathbf{r}^{(j,k)}.$

• ProcessD2EDr2Term is a callback function that allows for access to the second derivatives of the configuration's partial energy, $$E^{\mathcal{C}}$$, with respect to all pair-distances, $$r^{(i,j)}, i,j \in C_{p}$$. That is, it allows the PM to communicate the values of $$\frac{\partial^2 E^{\mathcal{C}}}{\partial r^{(i,j)} \partial r^{(m,n)}}$$ to the simulator.

See the documentation of the KIM::Model and KIM::ComputeArguments interfaces for more details of the KIM API/PMI from the simulator's perspective.

See the documentation of the KIM::ModelCompute, KIM::ModelComputeArguments, KIM::ModelComputeArgumentsCreate, KIM::ModelComputeArgumentsDestroy, KIM::ModelCreate, KIM::ModelDestroy, KIM::ModelDriverCreate, KIM::ModelExtension, KIM::ModelRefresh, and KIM::ModelWriteParameterizedModel interfaces for more details of the KIM API/PMI from the PM's perspective.

## The KIM API Simulator Model Interface (KIM API/SMI)

In code, Simulator Models (SMs) are simply a set of parameter files and a specification file which contains simulator input commands and metadata (supported species, units, etc.) needed to run the model in its native simulator.

The KIM API/SMI consists of the KIM::SimulatorModel interface which provides programatic access to the SM's parameter files and the contents of its specification file. Conceptually, an SM specification file contains a series of key-value pairs. Some key-value pairs are defined and required by the KIM API/SMI. All other key-value pairs are called "Simulator Fields". For flexibility and generality, the content and meaning of the simulator fields is not defined by the KIM API/SMI. Instead, each simulator is free to create and define its own set of specifications. The value part of a simulator field key-value pair is one or more strings called "Simulator Field Lines". These strings may contain template tags (of the form "@<template-tag-key>@") which the KIM::SimulatorModel object will replace by performing template substitution using the "Template Map". The KIM API/SMI defines a small set of template mappings which facilitate providing copies of the SM's parameter files to the simulator. Additionally, simulators may define their own template mappings and add these to the KIM API/SMI's set to be used for template substitution.

Although the KIM API/SMI is designed for maximum flexibility, an example of one way it can be used by a simulator to support SMs is helpful. In particular, for the LAMMPS simulator, performing a simulation with a specific model typically involves three separate parts: (1) specifying the physical units in which the model's parameters are given and therefore the units in which the simulation will be performed; (2) specifying other default properties needed by the model which must be set before the LAMMPS simulation box is defined, such as the LAMMPS atom style; and (3) specifying the pair_style or other style commands that define the model's interactions and read in the model's parameter files. Here is an example LAMMPS input file for the ReaxFF potential, similar to the CHO example included in the LAMMPS distribution.

# REAX potential for CHO system
units real
atom_style charge
neigh_modify every 10 delay 0 check no
neighbor 2 bin
pair_style reax/c lmp_control
pair_coeff * * ffield.reax.cho H C O
fix reaxqeq all qeq/reax 1 0.0 10.0 1e-6 param.qeq
fix 1 all nve
fix 2 all temp/berendsen 500.0 500.0 100.0
timestep 0.25
run 100

In this case, the units line corresponds to (1) above. The atom_style and neigh_modify lines correspond to (2) above. And, the pair_style, pair_coeff, and fix reaxqeq lines correspond to (3) above. The strings "lmp_control", "ffield.reax.cho", and "param.qeq" are parameter file names (which are expected to be in the current working directory, since the names do not start with a '/'). Also of note is the string of parameters "H C O" on the pair_coeff line, which specifies a mapping between the species names "H", "C", and "O" used by the ReaxFF model and the LAMMPS atom type numbers 1, 2, and 3, respectively. The number of atom types and their species mapping are part of the simulation, not part of the model. In this case these values are specified within the "data.CHO" input file listed on the read_data line. Since the number of atom types and the species map can change from simulation to simulation, any LAMMPS KIM SM implementation will need a way of specifying the atom type mapping on the pair_coeff line.

The LAMMPS SM implementation accommodates all of these needs by defining three Simulator Fields, corresponding to the three parts of a LAMMPS model specification discussed above. (1) A "units" field, with a single line containing the LAMMPS unit system string required by the model. (2) A "model-init" field, with zero or more lines containing, in this case, the atom_style and neigh_modify commands. And (3) a "model-defn" field, with zero or more lines containing, in this case, the pair_style, pair_coeff, and fix reaxqeq commands. In the latter field lines, the correct parameter file names are obtained through the KIM API/SMI's template substitution mechanism, using the standard template keys for the SM's parameter files. The correct atom type mapping is obtained through a special, LAMMPS defined, template map with key "atom-type-sym-list". The result of all of these considerations and definitions is the following SM specification file (see the KIM API/SMI Specification File Schema for details of the file format) for the LAMMPS ReaxFF model.

{
"kim-api-sm-schema-version" 1
"model-name" "Sim_LAMMPS_ReaxFF_ChenowethVanDuinGoddard_2008_CHO__SM_584143153761_000"
"simulator-name" "LAMMPS"
"simulator-version" "28 Feb 2019"
"supported-species" "C H O"
"units" "real"
"model-init" [ "atom_style charge"
"neigh_modify one 4000"
]
"model-defn" [ "pair_style reax/c @<parameter-file-2>@ safezone 2.0 mincap 100"
"pair_coeff * * @<parameter-file-1>@ @<atom-type-sym-list>@"
"fix reaxqeq all qeq/reax 1 0.0 10.0 1.0e-6 @<parameter-file-3>@"
]
}

The ordering of the SM's parameter files is specified in the SM's CMakeLists.txt configuration file. With this SM defined and installed in one of the KIM API collections, the following is equivalent to the above LAMMPS input script.

# REAX potential for CHO system
kim_init Sim_LAMMPS_ReaxFF_ChenowethVanDuinGoddard_2008_CHO__SM_584143153761_000 real
neighbor 2 bin