Tutorial on Developing KIM tests using LAMMPS

Test | Example calculation


Test

Here, we describe a basic test using the LAMMPS Molecular Dynamics Simulator named LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005. This test is designed to (1) retrieve the equilibrium FCC lattice constant for argon for whichever model it is being run against by querying the OpenKIM repository and (2) calculate the cohesive energy corresponding to this lattice constant for that model.


List of files

All KIM tests are required to have the following files:

  • Makefile - trivial makefile (does nothing since no compilation is needed)
  • kimspec.edn - metadata file that describes our test (used by the OpenKIM system)
  • pipeline.stdin.tpl - Jinja-formatted template file to provide input on stdin
  • runner - the main executable used to run the test

In addition to the required files above, this test also contains:

  • LICENSE.CDDL - a copy of the CDDL license
  • in.lammps - a LAMMPS input script to perform the calculation
  • dependencies.edn - specifies other tests whose results this test uses

runner

This is the main executable of the test. In this case, it so happens to be a bash script that takes the name of a KIM model as input, performs a query to the OpenKIM repository to retrieve the fcc lattice constant for argon predicted by that model, and computes the cohesive energy at that lattice geometry.

NOTE Every KIM test and test-driver is required to have a primary executable named runner, although this executable is free to call other executables, etc. Here, runner is a bash script that calls LAMMPS.

#!/usr/bin/env bash
#
# LAMMPS cohesive energy example test with dependencies
#

# Grab the model name from standard input stream (stdin)
echo "Enter a KIM model name:"
read modelname
echo ${modelname}
echo

# Run LAMMPS using the in.lammps input file
lammps -var modelname ${modelname} -in in.lammps

The test begins by grabbing a KIM model name from the standard input (stdin) stream (cf. the section for pipeline.stdin.tpl below). It then calls LAMMPS using in.lammps as an input script, passing the model name as an input variable. The majority of the actual work performed by the test is actually done by LAMMPS when it processes in.lammps.


in.lammps

# Set up logging
log output/lammps.log

# Set the OpenKIM model and units that will be used
kim_init ${modelname} metal

# Query for the fcc lattice constant
kim_query lattice_constant get_lattice_constant_cubic crystal=["fcc"] species=["Ar"] units=["angstrom"]

# Periodic boundary conditions along all three dimensions
boundary p p p

# Create an FCC lattice with the lattice spacing
# using a single conventional (orthogonal) unit cell
lattice fcc ${lattice_constant}
region box block 0 1 0 1 0 1 units lattice
create_box 1 box
create_atoms 1 box
mass 1 39.948

# Specify the KIM interactions
kim_interactions Ar

# Compute total potential energy
run 0

# Compute cohesive energy (and make positive to conform to sign convention in
# property definition 'cohesive-potential-energy-cubic-crystal')
variable natoms       equal "count(all)"
variable ecohesive    equal "-pe/v_natoms"

# Create a property instance
kim_property create 1 cohesive-potential-energy-cubic-crystal

# Set all the key-value pairs for this property instance
kim_property modify 1 key short-name source-value 1 fcc                          &
                      key species source-value 1 Ar                              &
                      key a source-value ${lattice_constant}                     &
                            source-unit angstrom                                 &
                      key basis-atom-coordinates source-value 1 1:3 0.0 0.0 0.0  &
                                                 source-value 2 1:3 0.0 0.5 0.5  &
                                                 source-value 3 1:3 0.5 0.0 0.5  &
                                                 source-value 4 1:3 0.5 0.5 0.0  &
                      key space-group source-value Fm-3m                         &
                      key cohesive-potential-energy source-value ${ecohesive}    &
                                                    source-unit eV

# Dump the results in a file
kim_property dump "output/results.edn"

# Print cohesive energy and equilibrium lattice constant
print "Cohesive energy = ${ecohesive} eV/atom"

The first thing we see in this script is that output/lammps.log is set as the log file. The output directory is a convention used by the KIM processing pipeline, and is automatically created when a test is run. In order to prevent a KIM test from inadvertently including artifacts and other unnecessary files in the test result it generates, all files that are to be retained as part of the test result must be explicitly written or copied to this subdirectory. Thus, since we want to retain our log file as part of the test result, we write it into output.

The remainder of the script makes use of various kim-specific commands in LAMMPS; see the lammps kim_commands docs for more information.

First, the kim_init command is used to set the OpenKIM model and the units that will be used throughout the script. Next, the kim_query command is called with the get_lattice_constant_cubic function from the kim-query package, which provides a convenient way to look up already-computed test results from the OpenKIM repository.1 With the arguments provided, this specific function looks up the lattice constant computed by the latest version of a test named LatticeConstantCubicEnergy_fcc_Ar__TE_206669103745 when it was run against the current model (the latest version is currently LatticeConstantCubicEnergy_fcc_Ar__TE_206669103745_007). The result returned by the query is stored in the variable lattice_constant, which is used to construct the simulation domain and populate it with atoms. In this case, the simulation consists of a single conventional FCC unit cell of Ar atoms. The next command given is kim_interactions. This command is used to define a mapping between the atomic species strings, e.g. "Ar", that are used by a KIM model and the integer indices used to represent atom types in LAMMPS. After this has been done, the total potential energy is computed.

In order for the results produced by a test to be useful, the relevant physical information must be recorded in a specific format whose pieces have well-defined meaning. To this end, every test is required to report instances of KIM property definitions. In LAMMPS, this can be done directly using the using the kim_property command. Here, the kim_property create command is used to initialize a property instance corresponding to the cohesive-potential-energy-cubic-crystal property definition.2 Next, the kim_property modify command is used to fill in the property instance with the relevant quantities including the atomic species, specific cubic lattice type, the cohesive energy computed, etc. Note the sign reversal in the definition of the variable ecohesive. Each property definition generally has its own conventions for how physical information is reported; the property definition reported by this test follows the convention that stable lattices have positive cohesive energy.

Finally, the property instance is written to a file named results.edn in the output directory using the kim_property dump command. Beyond the convention of the output directory mentioned at the beginning of this section, a second convention of the KIM processing pipeline is that the results of a test must be written into a file specifically named results.edn.

1 For a detailed listing of query functions with examples, see here.
2 To see a list of all current KIM property definitions, click here.


pipeline.stdin.tpl

This is a Jinja2-formatted template file that the OpenKIM processing pipeline will fill in and provide to the test on stdin when it is run against a model.

@< MODELNAME >@

The pipeline's custom Jinja environment features the notation @<…>@ for enclosing python code you wish to execute, while @[…]@ denotes code blocks and @#…#@ denotes comments. Many standard Python functions can thus be used inside of @<…>@ delimiters, as well as a few special functions and keywords specific to KIM. Here, the special keyword MODELNAME will be replaced by the name of the model that the pipeline is currently running the test against.

NOTE Every KIM test requires a file named pipeline.stdin.tpl which, if nothing else, is used to input the name of the KIM model currently being run against.


dependencies.edn

This file is used internally by the pipeline to ensure that tests are run in the appropriate order. If your test performs queries to retrieve the results of other tests, they should be recorded here (if your test does perform any such queries, this file should be omitted). At the moment, determining the specific dependencies of your test must currently be done manually. In this case, if we consult the documentation for the get_lattice_constant_cubic function used to perform the query, we can see that it queries for results produced by tests that use the test driver family with code TD_475411767977. On the page for the latest version of this driver, LatticeConstantCubicEnergy__TD_475411767977_007, we can see that its test that computes the fcc Ar lattice constant is LatticeConstantCubicEnergy_fcc_Ar__TE_206669103745_007. Because a test is only allowed to query for results produced by the latest versions of other tests (as of the time it is run), the 3-digit version extension is omitted when it's listed in dependencies.edn. In fact, the human-readable prefix can be omitted as well, as in the case of the current test:

[ "TE_206669103745" ]

Tests that have multiple dependencies should separate them by spaces, in accorance with the EDN format (see About the EDN data format).


kimspec.edn

This is a metadata file that describes the test.

{
  "title" "Lammps cohesive energy example test v005"
  "extended-id" "LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005"
  "species" [
    "Ar"
  ]
  "properties" [
    "tag:staff@noreply.openkim.org,2014-04-15:property/cohesive-potential-energy-cubic-crystal"
  ]
  "author" "Daniel S. Karls"
  "description" "Tutorial test using the LAMMPS molecular dynamics simulator.  Given a model for Ar, it performs a query to retrieve the FCC lattice constant and computes the cohesive energy.\n\n\nHISTORY:\n\nChanges in version 005:\n* Use kim_init and kim_interactions to initialize model\n* Use kim_query command to query instead of putting it in pipeline.stdin.tpl\n* Use kim_property command to write property instance"
  "contributor-id" "4d62befd-21c4-42b8-a472-86132e6591f3"
  "maintainer-id" "4d62befd-21c4-42b8-a472-86132e6591f3"
  "publication-year" "2020"
  "kim-api-version" "2.0"
  "executables" [
    "runner"
  ]
  "domain" "openkim.org"
}

NOTE When working on a test inside the OpenKIM user container, you must create a kimspec.edn file for your test that lists its "extended-id" and, if the test uses a test driver, the "test-driver" field. It must also list the "species" supported by your test (in the form of an EDN array, e.g. [ "Ni" "Al" ]) and the minimum KIM API version your test is compatible with. The other fields aren't necessary until you're ready to upload your test (and can actually be filled in automatically for you as you complete the upload forms).


Makefile

In this example, the Makefile does nothing since no compilation is needed

all:
	@echo "Nothing to make"

clean:
	@echo "Nothing to clean"

Example Calculation

On the OpenKIM user container (available on openkim.org soon), this test can be installed using the kimitems utility:

kimitems install LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005

which will download a tarball of the test from openkim.org, decompress it into ~/tests/, and attempt to build it.

Suppose we now wish to run this test against LJ_Shifted_Bernardes_1958MedCutoff_Ar__MO_126566794224_004 model. After installing the model via

kimitems install LJ_Shifted_Bernardes_1958MedCutoff_Ar__MO_126566794224_004

where, we can run this specific test–model pair by issuing

pipeline-run-pair LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005 LJ_Shifted_Bernardes_1958MedCutoff_Ar__MO_126566794224_004

This will result in an output like this:

+ Running pair (LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005, LJ_Shifted_Bernardes_1958MedCutoff_Ar__MO_126566794224_004)

  Pair produced Test Result TE_565333229701_005-and-MO_126566794224_004-1583952576-tr in 0.20717191696166992 seconds

This indicates that our test–model pair produced a test result (as opposed to an error), and that the corresponding directory was placed in ~/test-results/TE_565333229701_005-and-MO_126566794224_004-1583952576-tr. Let's go to this folder and inspect its contents:

~/test-results/TE_565333229701_006-and-MO_126566794224_004-1583952576-tr/
├── kim.log - log file created by the KIM API
├── kimspec.edn - metadata for the test result
├── lammps.log - LAMMPS output log
├── pipeline.stderr - stderr output from the test
├── pipeline.stdin - final stdin that was fed to the test
├── pipeline.stdout - stdout output from the test
├── pipelinespec.edn - profiling information, including runtime
└── results.edn - final property instance results file output by the test

If we take a look at the pipeline.stdin file, we can see that the MODELNAME in the pipeline.stdin.tpl input template was successfully rendered to the name of the model we ran the test against:

LJ_Shifted_Bernardes_1958MedCutoff_Ar__MO_126566794224_003

and from results.edn, we can see that the cohesive energy computed by the test was approximately 0.0865 eV:

{
    "property-id" "tag:staff@noreply.openkim.org,2014-04-15:property/cohesive-potential-energy-cubic-crystal"
    "instance-id" 1
    "short-name" {
        "source-value" [
            "fcc"
        ]
    }
    "species" {
        "source-value" [
            "Ar"
        ]
    }
    "a" {
        "source-value" 5.24850905686617
        "source-unit" "angstrom"
        "si-unit" "m"
        "si-value" 5.24850905686617e-10
    }
    "basis-atom-coordinates" {
        "source-value" [
            [
                0.0
                0.0
                0.0
            ]
            [
                0.0
                0.5
                0.5
            ]
            [
                0.5
                0.0
                0.5
            ]
            [
                0.5
                0.5
                0.0
            ]
        ]
    }
    "space-group" {
        "source-value" "Fm-3m"
    }
    "cohesive-potential-energy" {
        "source-value" 0.0865055084950546
        "source-unit" "eV"
        "si-unit" "kg m^2 / s^2"
        "si-value" 1.385971032811923e-20
    }
}

Note

  • Don't waste your time typing when you don't have to! Tab-completion is supported over the KIM VM command-line utility names, their options, and currently installed KIM tests, models, and verification checks, etc.

  • To run this test against all compatible models currently installed on your KIM VM, you can issue pipeline-run-matches LammpsCohesiveEnergyFromQueryExample_fcc_Ar__TE_565333229701_005.

  • Although not so useful here, the -v/--verbose flag to pipeline-run-pair and pipeline-run-matches prints the stdout and stderr streams of the test to the terminal while it is running.