diff --git a/cmake/Modules/Packages/KIM.cmake b/cmake/Modules/Packages/KIM.cmake index 8815f73881..d9d028f6dc 100644 --- a/cmake/Modules/Packages/KIM.cmake +++ b/cmake/Modules/Packages/KIM.cmake @@ -9,6 +9,9 @@ if(PKG_KIM) if(KIM-API_FOUND) set(DOWNLOAD_KIM_DEFAULT OFF) else() + if (NOT DOWNLOAD_KIM) + message(WARNING "KIM-API package not found. We will download and build our own") + endif() set(DOWNLOAD_KIM_DEFAULT ON) endif() option(DOWNLOAD_KIM "Download KIM-API from OpenKIM instead of using an already installed one" ${DOWNLOAD_KIM_DEFAULT}) @@ -21,8 +24,8 @@ if(PKG_KIM) enable_language(Fortran) include(ExternalProject) ExternalProject_Add(kim_build - URL https://s3.openkim.org/kim-api/kim-api-2.0.2.txz - URL_MD5 537d9c0abd30f85b875ebb584f9143fa + URL https://s3.openkim.org/kim-api/kim-api-2.1.2.txz + URL_MD5 6ac52e14ef52967fc7858220b208cba5 BINARY_DIR build CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} diff --git a/doc/src/Build_extras.txt b/doc/src/Build_extras.txt index 3fc23c5618..e6791de21b 100644 --- a/doc/src/Build_extras.txt +++ b/doc/src/Build_extras.txt @@ -172,22 +172,17 @@ KIM package :h4,link(kim) To build with this package, the KIM library with API v2 must be downloaded and built on your system. It must include the KIM models that you want to -use with LAMMPS. If you want to use the "kim_query"_kim_query.html +use with LAMMPS. If you want to use the "kim_query"_kim_commands.html command, you also need to have libcurl installed with the matching development headers and the curl-config tool. -Note that in LAMMPS lingo, a KIM model driver is a pair style -(e.g. EAM or Tersoff). A KIM model is a pair style for a particular -element or alloy and set of parameters, e.g. EAM for Cu with a -specific EAM potential file. Also note that downloading and installing -the KIM API library with all its models, may take a long time (10s of -minutes to hours) to build. Of course you only need to do that once. +See "Obtaining KIM Models"_http://openkim.org/doc/usage/obtaining-models to +learn how to install a pre-build binary of the OpenKIM Repository of Models. +See the list of all KIM models here: https://openkim.org/browse/models -See the list of KIM model drivers here: -https://openkim.org/browse/model-drivers/alphabetical - -See the list of all KIM models here: -https://openkim.org/browse/models/by-model-drivers +(Also note that when downloading and installing from source +the KIM API library with all its models, may take a long time (tens of +minutes to hours) to build. Of course you only need to do that once.) [CMake build]: diff --git a/doc/src/Commands_all.txt b/doc/src/Commands_all.txt index 80f91d5291..d0d7657c07 100644 --- a/doc/src/Commands_all.txt +++ b/doc/src/Commands_all.txt @@ -68,7 +68,9 @@ An alphabetic list of all general LAMMPS commands. "improper_style"_improper_style.html, "include"_include.html, "jump"_jump.html, -"kim_query"_kim_query.html, +"kim_init"_kim_commands.html, +"kim_interactions"_kim_commands.html, +"kim_query"_kim_commands.html, "kspace_modify"_kspace_modify.html, "kspace_style"_kspace_style.html, "label"_label.html, diff --git a/doc/src/Errors_messages.txt b/doc/src/Errors_messages.txt index ddf7629782..c131b10ec6 100644 --- a/doc/src/Errors_messages.txt +++ b/doc/src/Errors_messages.txt @@ -5785,6 +5785,16 @@ definitions. :dd The data file header lists improper but no improper types. :dd +{Incompatible KIM Simulator Model} :dt + +The requested KIM Simulator Model was defined for a different MD code +and thus is not compatible with LAMMPS. :dd + +{Incompatible units for KIM Simulator Model} :dt + +The selected unit style is not compatible with the requested KIM +Simulator Model. :dd + {Incomplete use of variables in create_atoms command} :dt The var and set options must be used together. :dd @@ -7055,6 +7065,12 @@ The atom style defined does not have this attribute. :dd The atom style defined does not have these attributes. :dd +{KIM Simulator Model has no Model definition} :dt + +There is no model definition (key: model-defn) in the KIM Simulator +Model. Please contact the OpenKIM database maintainers to verify +and potentially correct this. :dd + {KOKKOS package does not yet support comm_style tiled} :dt Self-explanatory. :dd @@ -7559,6 +7575,18 @@ Self-explanatory. :dd Self-explanatory. :dd +{Must use 'kim_style init' command before simulation box is defined} :dt + +Self-explanatory. :dd + +{Must use 'kim_style define' command after simulation box is defined} :dt + +Self-explanatory. :dd + +{Must use 'kim_style init' command before 'kim_style define'} :dt + +Self-explanatory. :dd + {Must use 'kspace_modify pressure/scalar no' for rRESPA with kspace_style MSM} :dt The kspace scalar pressure option cannot (yet) be used with rRESPA. :dd @@ -9502,6 +9530,11 @@ See the "read_data extra/special/per/atom" command for info on how to leave space in the special bonds list to allow for additional bonds to be formed. :dd +{Species XXX is not supported by this KIM Simulator Model} :dt + +The kim_style define command was referencing a species that is not +present in the requested KIM Simulator Model. :dd + {Specified processors != physical processors} :dt The 3d grid of processors defined by the processors command does not diff --git a/doc/src/Examples.txt b/doc/src/Examples.txt index fcf01de383..36d0ac86f9 100644 --- a/doc/src/Examples.txt +++ b/doc/src/Examples.txt @@ -73,7 +73,7 @@ granregion: use of fix wall/region/gran as boundary on granular particles hugoniostat: Hugoniostat shock dynamics hyper: global and local hyperdynamics of diffusion on Pt surface indent: spherical indenter into a 2d solid -kim: use of potentials in Knowledge Base for Interatomic Models (KIM) +kim: use of potentials from the "OpenKIM Repository"_openkim latte: examples for using fix latte for DFTB via the LATTE library meam: MEAM test for SiC and shear (same as shear examples) melt: rapid melt of 3d LJ system @@ -153,3 +153,5 @@ illustrate how to use the command(s) provided in that package. Many of the sub-directories have their own README files which give further instructions. See the "Packages_details"_Packages_details.html doc page for more info on specific USER packages. + +:link(openkim,https://openkim.org) diff --git a/doc/src/Install_mac.txt b/doc/src/Install_mac.txt index 3ab119522c..773c9ec93a 100644 --- a/doc/src/Install_mac.txt +++ b/doc/src/Install_mac.txt @@ -10,47 +10,34 @@ Documentation"_ld - "LAMMPS Commands"_lc :c Download an executable for Mac :h3 LAMMPS can be downloaded, built, and configured for OS X on a Mac with -"Homebrew"_homebrew. Only four of the LAMMPS packages are unavailable -at this time because of additional needs not yet met: KIM, GPU, -USER-INTEL, USER-ATC. +"Homebrew"_homebrew. The following LAMMPS packages are unavailable at this +time because of additional needs not yet met: GPU, KOKKOS, LATTE, MSCG, +MESSAGE, MPIIO POEMS VORONOI. After installing Homebrew, you can install LAMMPS on your system with the following commands: -% brew tap homebrew/science -% brew install lammps # serial version -% brew install lammps --with-mpi # mpi support :pre +% brew install lammps :pre -This will install the executable "lammps", a python module named -"lammps", and additional resources with all the standard packages. To -get the location of the additional resources type this: - -% brew info lammps :pre - -This command also tells you additional installation options available. -The user-packages are available as options, just install them like -this example for the USER-OMP package: - -% brew install lammps --enable-user-omp :pre - -It is usually best to install LAMMPS with the most up to date source -files, which can be done with the "--HEAD" option: - -% brew install lammps --HEAD :pre - -To re-install the LAMMPS HEAD, run this command occasionally (make sure -to use the desired options). - -% brew install --force lammps --HEAD $\{options\} :pre +This will install the executables "lammps_serial" and "lammps_mpi", as well as +the LAMMPS "doc", "potentials", "tools", "bench", and "examples" directories. Once LAMMPS is installed, you can test the installation with the Lennard-Jones benchmark file: % brew test lammps -v :pre +The LAMMPS binary is built with the "KIM package"_Build_extras#kim which +results in Homebrew also installing the `kim-api` binaries when LAMMPS is +installed. In order to use potentials from "openkim.org"_openkim, you can +install the `openkim-models` package + +% brew install openkim-models :pre + If you have problems with the installation you can post issues to "this link"_homebrew. Thanks to Derek Thomas (derekt at cello.t.u-tokyo.ac.jp) for setting up the Homebrew capability. -:link(homebrew,https://github.com/Homebrew/homebrew-science/issues) +:link(homebrew,https://github.com/Homebrew/homebrew-core/issues) +:link(openkim,https://openkim.org) diff --git a/doc/src/Intro_features.txt b/doc/src/Intro_features.txt index 629e8210b7..d133fd8064 100644 --- a/doc/src/Intro_features.txt +++ b/doc/src/Intro_features.txt @@ -92,8 +92,8 @@ commands) implicit solvent potentials: hydrodynamic lubrication, Debye force-field compatibility with common CHARMM, AMBER, DREIDING, \ OPLS, GROMACS, COMPASS options - access to "KIM archive"_http://openkim.org of potentials via \ - "pair kim"_pair_kim.html + access to the "OpenKIM Repository"_http://openkim.org of potentials via \ + "kim_init, kim_interactions, and kim_query"_kim_commands.html commands hybrid potentials: multiple pair, bond, angle, dihedral, improper \ potentials can be used in one simulation overlaid potentials: superposition of multiple pair potentials :ul diff --git a/doc/src/Packages_details.txt b/doc/src/Packages_details.txt index bd5addda6f..43274a9606 100644 --- a/doc/src/Packages_details.txt +++ b/doc/src/Packages_details.txt @@ -338,22 +338,37 @@ KIM package :link(PKG-KIM),h4 [Contents:] -A "pair_style kim"_pair_kim.html command which is a wrapper on the -Knowledge Base for Interatomic Models (KIM) repository of interatomic -potentials, enabling any of them to be used in LAMMPS simulations. -Also a "kim_query"_kim_query.html command, which allows to query -the OpenKIM database for stored properties. +This package contains a set of commands that serve as a wrapper on the +"Open Knowledgebase of Interatomic Models (OpenKIM)"_https://openkim.org +repository of interatomic models (IMs) +enabling compatible ones to be used in LAMMPS simulations. +This includes "kim_init and kim_interactions"_kim_commands.html +commands to select, initialize and instantiate the IM, and a +"kim_query"_kim_commands.html command to perform web queries +for material property predictions of OpenKIM IMs. +Support for KIM IMs that conform to the +"KIM Application Programming Interface (API)"_https://openkim.org/kim-api/ +is provided by the "pair_style kim"_pair_kim.html command. -To use this package you must have the KIM library available on your -system. +NOTE: The command {pair_style kim} is called by {kim_interactions} and +is not recommended to be directly used in input scripts. + +To use this package you must have the KIM API library available on your +system. The KIM API is available for download on the +"OpenKIM website"_https://openkim.org/kim-api/. +When installing LAMMPS from binary, the kim-api package +is a dependency that is automatically downloaded and installed. Information about the KIM project can be found at its website: -https://openkim.org. The KIM project is led by Ellad Tadmor and Ryan -Elliott (U Minnesota). +"https://openkim.org"_https://openkim.org. +The KIM project is led by Ellad Tadmor and Ryan Elliott (U Minnesota) +and is funded by the "National Science Foundation"_https://www.nsf.gov/. [Authors:] Ryan Elliott (U Minnesota) is the main developer for the KIM -API which the "pair_style kim"_pair_kim.html command uses. He -developed the pair style. +API and the {pair_style kim} command. Axel Kohlmeyer (Temple U) and +Ellad Tadmor (U Minnesota) contributed to the "kim_commands"_kim_commands.html +interface in close collaboration with Ryan Elliott. + [Install:] @@ -363,10 +378,11 @@ extras"_Build_extras.html doc page. [Supporting info:] +"kim_commands"_kim_commands.html +"pair_style kim"_pair_kim.html src/KIM: filenames -> commands src/KIM/README lib/kim/README -"pair_style kim"_pair_kim.html examples/kim :ul :line @@ -984,9 +1000,9 @@ USER-ADIOS package :link(PKG-USER-ADIOS),h4 [Contents:] -ADIOS is a high-performance I/O library. This package implements the +ADIOS is a high-performance I/O library. This package implements the dump "atom/adios" and dump "custom/adios" commands to write data using -the ADIOS library. +the ADIOS library. [Authors:] Norbert Podhorszki (ORNL) from the ADIOS developer team. diff --git a/doc/src/commands_list.txt b/doc/src/commands_list.txt index cf716df9ac..a5c9b568ed 100644 --- a/doc/src/commands_list.txt +++ b/doc/src/commands_list.txt @@ -53,7 +53,7 @@ Commands :h1 include info jump - kim_query + kim_commands kspace_modify kspace_style label diff --git a/doc/src/compute.txt b/doc/src/compute.txt index 0cdc922506..2a9b2b82f7 100644 --- a/doc/src/compute.txt +++ b/doc/src/compute.txt @@ -177,7 +177,7 @@ compute"_Commands_compute.html doc page are followed by one or more of "angle"_compute_angle.html - energy of each angle sub-style "angle/local"_compute_angle_local.html - theta and energy of each angle "angmom/chunk"_compute_angmom_chunk.html - angular momentum for each chunk -"basal/atom"_compute_basal_atom.html - calculates the hexagonal close-packed ā€œcā€ lattice vector of each atom +"basal/atom"_compute_basal_atom.html - calculates the hexagonal close-packed "c" lattice vector of each atom "body/local"_compute_body_local.html - attributes of body sub-particles "bond"_compute_bond.html - energy of each bond sub-style "bond/local"_compute_bond_local.html - distance and energy of each bond diff --git a/doc/src/fix_adapt.txt b/doc/src/fix_adapt.txt index 0d862a890d..4f047ec42d 100644 --- a/doc/src/fix_adapt.txt +++ b/doc/src/fix_adapt.txt @@ -149,8 +149,7 @@ meaning of these parameters: "spin/neel"_pair_spin_neel.html: coulombic_cutoff: type global: "table"_pair_table.html: table_cutoff: type pairs: "ufm"_pair_ufm.html: epsilon,sigma: type pairs: -"soft"_pair_soft.html: a: type pairs: -"kim"_pair_kim.html: PARAM_FREE_*:i,j,...: global :tb(c=3,s=:) +"soft"_pair_soft.html: a: type pairs: :tb(c=3,s=:) NOTE: It is easy to add new pairwise potentials and their parameters to this list. All it typically takes is adding an extract() method to diff --git a/doc/src/kim_commands.txt b/doc/src/kim_commands.txt new file mode 100644 index 0000000000..93c4e8c4a8 --- /dev/null +++ b/doc/src/kim_commands.txt @@ -0,0 +1,522 @@ +"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c + +:link(lws,http://lammps.sandia.gov) +:link(ld,Manual.html) +:link(lc,Commands_all.html) + +:line + +kim_init command :h3 +kim_interactions command :h3 +kim_query command :h3 + +[Syntax:] + +kim_init model user_units unitarg +kim_interactions typeargs +kim_query variable formatarg query_function queryargs :pre + +model = name of the KIM interatomic model (the KIM ID for models archived in OpenKIM) +user_units = the LAMMPS "units"_units.html style assumed in the LAMMPS input script +unitarg = {unit_conversion_mode} (optional) +typeargs = atom type to species mapping (one entry per atom type) or {fixed_types} for models with a preset fixed mapping +variable = name of a (string style) variable where the result of the query is stored +formatarg = {split} (optional) +query_function = name of the OpenKIM web API query function to be used +queryargs = a series of {keyword=value} pairs that represent the web query; supported keywords depend on the query function :ul + + +[Examples:] + +kim_init SW_StillingerWeber_1985_Si__MO_405512056662_005 metal +kim_interactions Si +kim_init Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 real +kim_init Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 metal unit_conversion_mode +kim_interactions C H O +Sim_LAMMPS_IFF_PCFF_HeinzMishraLinEmami_2015Ver1v5_FccmetalsMineralsSolvents Polymers__SM_039297821658_000 real +kim_interactions fixed_types +kim_query a0 get_lattice_constant_cubic crystal=\["fcc"\] species=\["Al"\] units=\["angstrom"\] :pre + +[Description:] + +The set of {kim_commands} provide a high-level wrapper around the +"Open Knowledgebase of Interatomic Models (OpenKIM)"_https://openkim.org +repository of interatomic models (IMs) (potentials and force fields), +so that they can be used by LAMMPS scripts. These commands do not implement +any computations directly, but rather generate LAMMPS input commands based +on the information retrieved from the OpenKIM repository to initialize and +activate OpenKIM IMs and query their predictions for use in the LAMMPS script. +All LAMMPS input commands generated and executed by {kim_commands} are +echoed to the LAMMPS log file. + +Benefits of Using OpenKIM IMs :h4 + +Employing OpenKIM IMs provides LAMMPS users with multiple benefits: + +Reliability :h5 + +All content archived in OpenKIM is reviewed by the "KIM Editor"_https://openkim.org/governance/ for quality. +IMs in OpenKIM are archived with full provenance control. Each is associated with a maintainer responsible for the integrity of the content. All changes are tracked and recorded. +IMs in OpenKIM are exhaustively tested using "KIM Tests"_https://openkim.org/doc/evaluation/kim-tests/ that compute a host of material properties, and "KIM Verification Checks"_https://openkim.org/doc/evaluation/kim-verification-checks/ that provide the user with information on various aspects of the IM behavior and coding correctness. This information is displayed on the IM's page accessible through the "OpenKIM browse interface"_https://openkim.org/browse. :ul + +Reproducibility :h5 + +Each IM in OpenKIM is issued a unique identifier ("KIM ID"_https://openkim.org/doc/schema/kim-ids/), which includes a version number (last three digits). Any changes that can result in different numerical values lead to a version increment in the KIM ID. This makes it possible to reproduce simulations since the specific version of a specific IM used can be retrieved using its KIM ID. +OpenKIM is a member organization of "DataCite"_https://datacite.org/ and issues digital object identifiers (DOIs) to all IMs archived in OpenKIM. This makes it possible to cite the IM code used in a simulation in a publications to give credit to the developers and further facilitate reproducibility. :ul + +Convenience :h5 + +IMs in OpenKIM are distributed in binary form along with LAMMPS and can be used in a LAMMPS input script simply by providing their KIM ID in the {kim_init} command documented on this page. +The {kim_query} web query tool provides the ability to use the predictions of IMs for supported material properties (computed via "KIM Tests"_https://openkim.org/doc/evaluation/kim-tests/) as part of a LAMMPS input script setup and analysis. +Support is provided for unit conversion between the "unit style"_units.html used in the LAMMPS input script and the units required by the OpenKIM IM. This makes it possible to use a single input script with IMs using different units without change and minimizes the likelihood of errors due to incompatible units. :ul + +:link(IM_types) +Types of IMs in OpenKIM :h4 + +There are two types of IMs archived in OpenKIM: + +The first type is called a {KIM Portable Model} (PM). A KIM PM is an independent computer implementation of an IM written in one of the languages supported by KIM (C, C++, Fortran) that conforms to the KIM Application Programming Interface ("KIM API"_https://openkim.org/kim-api/) Portable Model Interface (PMI) standard. A KIM PM will work seamlessly with any simulation code that supports the KIM API/PMI standard (including LAMMPS; see "complete list of supported codes"_https://openkim.org/projects-using-kim/). +The second type is called a {KIM Simulator Model} (SM). A KIM SM is an IM that is implemented natively within a simulation code ({simulator}) that supports the KIM API Simulator Model Interface (SMI); in this case LAMMPS. A separate SM package is archived in OpenKIM for each parameterization of the IM, which includes all of the necessary parameter files, LAMMPS commands, and metadata (supported species, units, etc.) needed to run the IM in LAMMPS. :ol + +With these two IM types, OpenKIM can archive and test almost all IMs that +can be used by LAMMPS. (It is easy to contribute new IMs to OpenKIM, see +the "upload instructions"_https://openkim.org/doc/repository/adding-content/.) + +OpenKIM IMs are uniquely identified by a +"KIM ID"_https://openkim.org/doc/schema/kim-ids/. +The extended KIM ID consists of +a human-readable prefix identifying the type of IM, authors, publication year, +and supported species, separated by two underscores from the KIM ID itself, +which begins with an IM code +({MO} for a KIM Portable Model, and {SM} for a KIM Simulator Model) +followed by a unique 12-digit code and a 3-digit version identifier. +By convention SM prefixes begin with {Sim_} to readily identify them. + +SW_StillingerWeber_1985_Si__MO_405512056662_005 +Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 :pre + +Each OpenKIM IM has a dedicated "Model Page" on "OpenKIM"_https://openkim.org +providing all the information on the IM including a title, description, +authorship and citation information, test and verification check results, +visualizations of results, a wiki with documentation and user comments, and +access to raw files, and other information. +The URL for the Model Page is constructed from the +"extended KIM ID"_https://openkim.org/doc/schema/kim-ids/ of the IM: + +https://openkim.org/id/extended_KIM_ID +:pre + +For example for the Stillinger-Weber potential +listed above the Model Page is located at: + +"https://openkim.org/id/SW_StillingerWeber_1985_Si__MO_405512056662_005"_https://openkim.org/id/SW_StillingerWeber_1985_Si__MO_405512056662_005 +:pre + +See the "current list of KIM PMs and SMs archived in OpenKIM"_https://openkim.org/browse/models/by-species. +This list is sorted by species and can be filtered to display only +IMs for certain species combinations. + +See "Obtaining KIM Models"_http://openkim.org/doc/usage/obtaining-models to +learn how to install a pre-build binary of the OpenKIM Repository of Models. + +NOTE: It is also possible to locally install IMs not archived in OpenKIM, +in which case their names do not have to conform to the KIM ID format. + +Using OpenKIM IMs with LAMMPS :h4 + +Two commands are employed when using OpenKIM IMs, one to select the +IM and perform necessary initialization ({kim_init}), and the second +to set up the IM for use by executing any necessary LAMMPS commands +({kim_interactions}). Both are required. + +See the {examples/kim} directory for example input scripts that use KIM PMs +and KIM SMs. + +OpenKIM IM Initialization ({kim_init}) :h5 + +The {kim_init} mode command must be issued [before] +the simulation box is created (normally at the top of the file). +This command sets the OpenKIM IM that will be used and may issue +additional commands changing LAMMPS default settings that are required +for using the selected IM (such as "units"_units.html or +"atom_style"_atom_style.html). If needed, those settings can be overridden, +however, typically a script containing a {kim_init} command +would not include {units} and {atom_style} commands. + +The required arguments of {kim_init} are the {model} name of the +IM to be used in the simulation (for an IM archived in OpenKIM this is +its "extended KIM ID"_https://openkim.org/doc/schema/kim-ids/, and +the {user_units}, which are the LAMMPS "units style"_units.html used +in the input script. (Any dimensioned numerical values in the input +script and values read in from files are expected to be in the +{user_units} system.) + +The selected IM can be either a "KIM PM or a KIM SM"_#IM_types. +For a KIM SM, the {kim_init} command verifies that the SM is designed +to work with LAMMPS (and not another simulation code). +In addition, the LAMMPS version used for defining +the SM and the LAMMPS version being currently run are +printed to help diagnose any incompatible changes to input script or +command syntax between the two LAMMPS versions. + +Based on the selected model {kim_init} may modify the +"atom_style"_atom_style.html. +Some SMs have requirements for this setting. If this is the case, then +{atom_style} will be set to the required style. Otherwise, the value is left +unchanged (which in the absence of an {atom_style} command in the input script +is the "default atom_style value"_atom_style.html). + +Regarding units, the {kim_init} command behaves in different ways depending +on whether or not {unit conversion mode} is activated as indicated by the +optional {unitarg} argument. +If unit conversion mode is [not] active, then {user_units} must +either match the required units of the IM or the IM must be able +to adjust its units to match. (The latter is only possible with some KIM PMs; +SMs can never adjust their units.) If a match is possible, the LAMMPS +"units"_units.html command is called to set the units to +{user_units}. If the match fails, the simulation is terminated with +an error. + +Here is an example of a LAMMPS script to compute the cohesive energy +of a face-centered cubic (fcc) lattice for the Ercolessi and Adams (1994) +potential for Al: + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal +boundary p p p +lattice fcc 4.032 +region simbox block 0 1 0 1 0 1 units lattice +create_box 1 simbox +create_atoms 1 box +mass 1 26.981539 +kim_interactions Al +run 0 +variable Ec equal (pe/count(all))/$\{_u_energy\} +print "Cohesive Energy = $\{EcJ\} eV" +:pre + +The above script will end with an error in the {kim_init} line if the +IM is changed to another potential for Al that does not work with {metal} +units. To address this {kim_init} offers the {unit_conversion_mode}. +If unit conversion mode {is} active, then {kim_init} calls the LAMMPS +"units"_units.html command to set the units to the IM's required or +preferred units. Conversion factors between the IM's units and the {user_units} +are defined for all "physical quantities"_units.html (mass, distance, etc.). +(Note that converting to or from the "lj" unit style is not supported.) +These factors are stored as "internal style variables"_variable.html with +the following standard names: + +_u_mass +_u_distance +_u_time +_u_energy +_u_velocity +_u_force +_u_torque +_u_temperature +_u_pressure +_u_viscosity +_u_charge +_u_dipole +_u_efield +_u_density :pre + +If desired, the input script can be designed to work with these conversion +factors so that the script will work without change with any OpenKIM IM. +(This approach is used in the +"OpenKIM Testing Framework"_https://openkim.org/doc/evaluation/kim-tests/.) +For example, the script given above for the cohesive energy of fcc Al +can be rewritten to work with any IM regardless of units. The following +script constructs an fcc lattice with a lattice parameter defined in +meters, computes the total energy, and prints the cohesive energy in +Joules regardless of the units of the IM. + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 si unit_conversion_mode +boundary p p p +lattice fcc 4.032e-10*$\{_u_distance\} +region simbox block 0 1 0 1 0 1 units lattice +create_box 1 simbox +create_atoms 1 box +mass 1 4.480134e-26*$\{_u_mass\} +kim_interactions Al +run 0 +variable Ec_in_J equal (pe/count(all))/$\{_u_energy\} +print "Cohesive Energy = $\{Ec_in_J\} J" :pre + +Note the multiplication by $\{_u_distance\} and $\{_u_mass\} to convert +from SI units (specified in the {kim_init} command) to whatever units the +IM uses (metal in this case), and the division by $\{_u_energy\} +to convert from the IM's energy units to SI units (Joule). This script +will work correctly for any IM for Al (KIM PM or SM) selected by the +{kim_init} command. + +Care must be taken to apply unit conversion to dimensional variables read in +from a file. For example if a configuration of atoms is read in from a +dump file using the "read_dump"_read_dump.html command, the following can +be done to convert the box and all atomic positions to the correct units: + +variable xyfinal equal xy*$\{_u_distance\} +variable xzfinal equal xz*$\{_u_distance\} +variable yzfinal equal yz*$\{_u_distance\} +change_box all x scale $\{_u_distance\} & + y scale $\{_u_distance\} & + z scale $\{_u_distance\} & + xy final $\{xyfinal\} & + xz final $\{xzfinal\} & + yz final $\{yzfinal\} & + remap :pre + +NOTE: Unit conversion will only work if the conversion factors are placed in +all appropriate places in the input script. It is up to the user to do this +correctly. + +OpenKIM IM Execution ({kim_interactions}) :h5 + +The second and final step in using an OpenKIM IM is to execute the +{kim_interactions} command. This command must be preceded by a {kim_init} +command and a command that defines the number of atom types {N} (such as +"create_box"_create_box.html). +The {kim_interactions} command has one argument {typeargs}. This argument +contains either a list of {N} chemical species, which defines a mapping between +atom types in LAMMPS to the available species in the OpenKIM IM, or the +keyword {fixed_types} for models that have a preset fixed mapping (i.e. +the mapping between LAMMPS atom types and chemical species is defined by +the model and cannot be changed). In the latter case, the user must consult +the model documentation to see how many atom types there are and how they +map to the chemical species. + +For example, consider an OpenKIM IM that supports Si and C species. +If the LAMMPS simulation has four atom types, where the first three are Si, +and the fourth is C, the following {kim_interactions} command would be used: + +kim_interactions Si Si Si C +:pre + +Alternatively, for a model with a fixed mapping the command would be: + +kim_interactions fixed_types +:pre + +The {kim_interactions} command performs all the necessary steps to set up +the OpenKIM IM selected in the {kim_init} command. The specific actions depend +on whether the IM is a KIM PM or a KIM SM. For a KIM PM, +a "pair_style kim"_pair_kim.html command is executed followed by +the appropriate {pair_coeff} command. For example, for the +Ercolessi and Adams (1994) KIM PM for Al set by the following commands: + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal +... +... box specification lines skipped +... +kim_interactions Al :pre + +the {kim_interactions} command executes the following LAMMPS input commands: + +pair_style kim EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 +pair_coeff * * Al :pre + +For a KIM SM, the generated input commands may be more complex +and require that LAMMPS is built with the required packages included +for the type of potential being used. The set of commands to be executed +is defined in the SM specification file, which is part of the SM package. +For example, for the Strachan et al. (2003) ReaxFF SM +set by the following commands: + +kim_init Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 real +... +... box specification lines skipped +... +kim_interactions C H N O :pre + +the {kim_interactions} command executes the following LAMMPS input commands: + +pair_style reax/c lmp_control safezone 2.0 mincap 100 +pair_coeff * * ffield.reax.rdx C H N O +fix reaxqeq all qeq/reax 1 0.0 10.0 1.0e-6 param.qeq :pre + +Note that the files {lmp_control}, {ffield.reax.rdx} and {param.qeq} +are specific to the Strachan et al. (2003) ReaxFF parameterization +and are archived as part of the SM package in OpenKIM. +Note also that parameters like cutoff radii and charge tolerances, +which have an effect on IM predictions, are also included in the +SM definition ensuring reproducibility. + +NOTE: When using {kim_init} and {kim_interactions} to select +and set up an OpenKIM IM, other LAMMPS commands +for the same functions (such as pair_style, pair_coeff, bond_style, +bond_coeff, fixes related to charge equilibration, etc.) should normally +not appear in the input script. + +Using OpenKIM Web Queries in LAMMPS ({kim_query}) :h5 + +The {kim_query} command performs a web query to retrieve the predictions +of the IM set by {kim_init} for material properties archived in +"OpenKIM"_https://openkim.org. The {kim_query} command must be preceded +by a {kim_init} command. The result of the query is stored in a +"string style variable"_variable.html, the name of which is given as the first +argument of the {kim_query command}. (For the case of multiple +return values, the optional {split} keyword can be used after the +variable name to separate the results into multiple variables; see +the "example"_#split_example below.) +The second required argument {query_function} is the name of the +query function to be called (e.g. {get_lattice_constant_cubic}). +All following "arguments"_Commands_parse.html are parameters handed over to +the web query in the format {keyword=value}, where {value} is always +an array of one or more comma-separated items in brackets. +The list of supported keywords and the type and format of their values +depend on the query function used. The current list of query functions +is available on the OpenKIM webpage at +"https://openkim.org/doc/repository/kim-query"_https://openkim.org/doc/repository/kim-query. + +NOTE: All query functions require the {model} keyword, which identifies +the IM whose predictions are being queried. This keyword is automatically +generated by {kim_query} based on the IM set in {kim_init} and must not +be specified as an argument to {kim_query}. + +NOTE: Each {query_function} is associated with a default method (implemented +as a "KIM Test"_https://openkim.org/doc/evaluation/kim-tests/) +used to compute this property. In cases where there are multiple +methods in OpenKIM for computing a property, a {method} keyword can +be provided to select the method of choice. See the +"query documentation"_https://openkim.org/doc/repository/kim-query +to see which methods are available for a given {query function}. + +{kim_query} Usage Examples and Further Clarifications: :h6 + +The data obtained by {kim_query} commands can be used as part of the setup +or analysis phases of LAMMPS simulations. Some examples are given below. + +[Define an equilibrium fcc crystal] + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal +boundary p p p +kim_query a0 get_lattice_constant_cubic crystal=\["fcc"\] species=\["Al"\] units=\["angstrom"\] +lattice fcc $\{a0\} +... :pre + +The {kim_query} command retrieves from "OpenKIM"_https://openkim.org +the equilibrium lattice constant predicted by the Ercolessi and Adams (1994) +potential for the fcc structure and places it in +variable {a0}. This variable is then used on the next line to set up the +crystal. By using {kim_query}, the user is saved the trouble and possible +error of tracking this value down, or of having to perform an energy +minimization to find the equilibrium lattice constant. + +Note that in {unit_conversion_mode} the results obtained from a +{kim_query} would need to be converted to the appropriate units system. +For example, in the above script, the lattice command would need to be +changed to: "lattice fcc $\{a0\}*$\{_u_distance\}". + +:link(split_example) +[Define an equilibrium hcp crystal] + +kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal +boundary p p p +kim_query latconst split get_lattice_constant_hexagonal crystal=\["hcp"\] species=\["Zr"\] units=\["angstrom"\] +variable a0 equal latconst_1 +variable c0 equal latconst_2 +variable c_to_a equal $\{c0\}/$\{a0\} +lattice custom $\{a0\} a1 0.5 -0.866025 0 a2 0.5 0.866025 0 a3 0 0 $\{c_to_a\} & + basis 0.333333 0.666666 0.25 basis 0.666666 0.333333 0.75 +... :pre + +In this case the {kim_query} returns two arguments (since the hexagonal +close packed (hcp) structure has two independent lattice constants). +The default behavior of {kim_query} returns the result as a string +with the values separated by commas. The optional keyword {split} +separates the result values into individual variables of the form +{prefix_I}, where {prefix} is set to the the {kim_query} {variable} argument +and {I} ranges from 1 to the number of returned values. The number and order of +the returned values is determined by the type of query performed. + +[Define a crystal at finite temperature accounting for thermal expansion] + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal +boundary p p p +kim_query a0 get_lattice_constant_cubic crystal=\["fcc"\] species=\["Al"\] units=\["angstrom"\] +kim_query alpha get_linear_thermal_expansion_coefficient_cubic crystal=\["fcc"\] species=\["Al"\] units=\["1/K"\] temperature=\[293.15\] temperature_units=\["K"\] +variable DeltaT equal 300 +lattice fcc $\{a0\}*$\{alpha\}*$\{DeltaT\} +... :pre + +As in the previous example, the equilibrium lattice constant is obtained +for the Ercolessi and Adams (1994) potential. However, in this case the +crystal is scaled to the appropriate lattice constant at room temperature +(293.15 K) by using the linear thermal expansion constant predicted by the +potential. + +NOTE: When passing numerical values as arguments (as in the case +of the temperature in the above example) it is also possible to pass a +tolerance indicating how close to the value is considered a match. +If no tolerance is passed a default value is used. If multiple results +are returned (indicating that the tolerance is too large), {kim_query} +will return an error. See the +"query documentation"_https://openkim.org/doc/repository/kim-query +to see which numerical arguments and tolerances are available for a +given {query function}. + +[Compute defect formation energy] + +kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal +... +... Build fcc crystal containing some defect and compute the total energy +... which is stored in the variable {Etot} +... +kim_query Ec get_cohesive_energy_cubic crystal=\["fcc"\] species=\["Al"\] units=\["eV"\] +variable Eform equal $\{Etot\} - count(all)*$\{Ec\} +... :pre + +The defect formation energy {Eform} is computed by subtracting from {Etot} the +ideal fcc cohesive energy of the atoms in the system obtained from +"OpenKIM"_https://openkim.org for the Ercolessi and Adams (1994) potential. + +NOTE: {kim_query} commands return results archived in +"OpenKIM"_https://openkim.org. These results are obtained +using programs for computing material properties +(KIM Tests and KIM Test Drivers) that were contributed to OpenKIM. +In order to give credit to Test developers, the number of times results +from these programs are queried is tracked. No other information about +the nature of the query or its source is recorded. + + +Citation of OpenKIM IMs :h4 + +When publishing results obtained using OpenKIM IMs researchers are requested +to cite the OpenKIM project "(Tadmor)"_#kim-mainpaper, KIM API +"(Elliott)"_#kim-api, and the specific IM codes used in the simulations, +in addition to the relevant scientific references for the IM. +The citation format for an IM is displayed on its page on +"OpenKIM"_https://openkim.org along with the corresponding BibTex file, +and is automatically added to the LAMMPS {log.cite} file. + +Citing the IM software (KIM infrastructure and specific PM or SM codes) +used in the simulation gives credit to the researchers who developed them +and enables open source efforts like OpenKIM to function. + + +[Restrictions:] + +The set of {kim_commands} is part of the KIM package. It is only enabled if +LAMMPS is built with that package. A requirement for the KIM package, +is the KIM API library that must be downloaded from the +"OpenKIM website"_https://openkim.org/kim-api/ and installed before +LAMMPS is compiled. When installing LAMMPS from binary, the kim-api package +is a dependency that is automatically downloaded and installed. See the KIM +section of the "Packages details"_Packages_details.html for details. + +Furthermore, when using {kim_commands} to run KIM SMs, any packages required +by the native potential being used or other commands or fixes that it invokes +must be installed. + +[Related commands:] + +"pair_style kim"_pair_kim.html + +:line + +:link(kim-mainpaper) +[(Tadmor)] Tadmor, Elliott, Sethna, Miller and Becker, JOM, 63, 17 (2011). +doi: "https://doi.org/10.1007/s11837-011-0102-6"_https://doi.org/10.1007/s11837-011-0102-6 + +:link(kim-api) +[(Elliott)] Elliott, Tadmor and Bernstein, "https://openkim.org/kim-api"_https://openkim.org/kim-api (2011) +doi: "https://doi.org/10.25950/FF8F563A"_https://doi.org/10.25950/FF8F563A diff --git a/doc/src/kim_query.txt b/doc/src/kim_query.txt deleted file mode 100644 index c581de0ebb..0000000000 --- a/doc/src/kim_query.txt +++ /dev/null @@ -1,46 +0,0 @@ -"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c - -:link(lws,http://lammps.sandia.gov) -:link(ld,Manual.html) -:link(lc,Commands_all.html) - -:line - -kim_query command :h3 - -[Syntax:] - -kim_query variable query_function web_query_flags :pre - -variable = name of a (string style) variable where the result of the query is stored -query_function = name of the OpenKIM web API query function to be used -web_query_flags = a series of keyword=value pairs that represent the web query; supported keywords depend on query function :ul - -[Examples:] - -kim_query latconst get_test_result test=TE_156715955670 model=MO_800509458712 & - prop=structure-cubic-crystal-npt species=\["Al"\] keys=\["a"\] units=\["angstrom"\] :pre - -[Description:] - -The kim_query command allows to retrieve properties from the OpenKIM -through a web query. The result is stored in a string style -"variable"_variable.html, the name of which must be given as the first -argument of the kim_query command. The second required argument is the -name of the actual query function (e.g. {get_test_result}). All following -arguments are parameters handed over to the web query in the format -{keyword=value}. The list of supported keywords and the type of how -the value has to be encoded depends on the query function used. This -mirrors the functionality available on the OpenKIM webpage at -"https://query.openkim.org"_https://query.openkim.org/ - -[Restrictions:] - -This command is part of the KIM package. It is only enabled if -LAMMPS was built with that package. Furthermore, its correct -functioning depends on compiling LAMMPS with libcurl support. -See the "Build package"_Build_package.html doc page for more info. - -[Related commands:] - -"pair_style kim"_pair_kim.html, "variable"_variable.html diff --git a/doc/src/lammps.book b/doc/src/lammps.book index 763441662a..ef5a4275df 100644 --- a/doc/src/lammps.book +++ b/doc/src/lammps.book @@ -42,6 +42,7 @@ Commands_compute.html Commands_pair.html Commands_bond.html Commands_kspace.html +Commands_removed.html Packages.html Packages_standard.html Packages_user.html @@ -167,7 +168,7 @@ if.html include.html info.html jump.html -kim_query.html +kim_commands.html label.html lattice.html log.html diff --git a/doc/src/pair_adp.txt b/doc/src/pair_adp.txt index fc888ffbff..de6717a6c3 100644 --- a/doc/src/pair_adp.txt +++ b/doc/src/pair_adp.txt @@ -42,16 +42,17 @@ the ADP potential files themselves. Likewise, the ADP potential files list atomic masses; thus you do not need to use the "mass"_mass.html command to specify them. -The NIST WWW site distributes and documents ADP potentials: +[ADP potentials are available from:] -http://www.ctcms.nist.gov/potentials :pre +The NIST WWW site at http://www.ctcms.nist.gov/potentials. +Note that ADP potentials obtained from NIST must be converted +into the extended DYNAMO {setfl} format discussed below. +:l -Note that these must be converted into the extended DYNAMO {setfl} -format discussed below. - -The NIST site is maintained by Chandler Becker (cbecker at nist.gov) -who is good resource for info on interatomic potentials and file -formats. +The OpenKIM Project at https://openkim.org/browse/models/by-type provides +ADP potentials that can be used directly in LAMMPS with the "kim_commands +interface"_kim_commands.html. +:l :line diff --git a/doc/src/pair_kim.txt b/doc/src/pair_kim.txt index a415ac606b..41593675ba 100644 --- a/doc/src/pair_kim.txt +++ b/doc/src/pair_kim.txt @@ -12,76 +12,72 @@ pair_style kim command :h3 pair_style kim model :pre -model = name of KIM model (potential) +model = name of a KIM model (the KIM ID for models archived in OpenKIM) [Examples:] -pair_style kim ex_model_Ar_P_LJ -pair_coeff * * Ar Ar :pre +pair_style kim SW_StillingerWeber_1985_Si__MO_405512056662_005 +pair_coeff * * Si :pre [Description:] -This pair style is a wrapper on the "Knowledge Base for Interatomic +This pair style is a wrapper on the "Open Knowledgebase of Interatomic Models (OpenKIM)"_https://openkim.org repository of interatomic -potentials, so that they can be used by LAMMPS scripts. +potentials to enable their use in LAMMPS scripts. -Note that in LAMMPS lingo, a KIM model driver is a pair style -(e.g. EAM or Tersoff). A KIM model is a pair style for a particular -element or alloy and set of parameters, e.g. EAM for Cu with a -specific EAM potential file. +The preferred interface for using interatomic models archived in +OpenKIM is the "kim_commands interface"_kim_commands.html. That +interface supports both "KIM Portable Models" (PMs) that conform to the +KIM API Portable Model Interface (PMI) and can be used by any +simulation code that conforms to the KIM API/PMI, and +"KIM Simulator Models" that are natively implemented within a single +simulation code (like LAMMPS) and can only be used with it. +The {pair_style kim} command is limited to KIM PMs. It is +used by the "kim_commands interface"_kim_commands.html as needed. -See the current list of "KIM model -drivers"_https://openkim.org/browse/model-drivers/alphabetical. +NOTE: Since {pair_style kim} is called by {kim_interactions} as needed, +is not recommended to be directly used in input scripts. -See the current list of all "KIM -models"_https://openkim.org/browse/models/by-model-drivers - -To use this pair style, you must first download and install the KIM -API library from the "OpenKIM website"_https://openkim.org. The KIM -section of the "Packages details"_Packages_details.html doc page has -instructions on how to do this with a simple make command, when -building LAMMPS. - -See the examples/kim dir for an input script that uses a KIM model -(potential) for Lennard-Jones. - :line -The argument {model} is the name of the KIM model for a specific -potential as KIM defines it. In principle, LAMMPS can invoke any KIM -model. You should get an error or warning message from either LAMMPS -or KIM if there is an incompatibility. +The argument {model} is the name of the KIM PM. +For potentials archived in OpenKIM +this is the extended KIM ID (see "kim_commands"_kim_commands.html +for details). LAMMPS can invoke any KIM PM, however there can +be incompatibilities (for example due to unit matching issues). +In the event of an incompatibility, the code will terminate with +an error message. Check both the LAMMPS and KIM log files for details. -Only a single pair_coeff command is used with the {kim} style which -specifies the mapping of LAMMPS atom types to KIM elements. This is -done by specifying N additional arguments after the * * in the -pair_coeff command, where N is the number of LAMMPS atom types: +Only a single {pair_coeff} command is used with the {kim} style, which +specifies the mapping of LAMMPS atom types to the species supported by +the KIM PM. This is done by specifying {N} additional arguments +after the * * in the {pair_coeff} command, where {N} is the number of +LAMMPS atom types: N element names = mapping of KIM elements to atom types :ul -As an example, imagine the KIM model supports Si and C atoms. If your -LAMMPS simulation has 4 atom types and you want the 1st 3 to be Si, -and the 4th to be C, you would use the following pair_coeff command: +For example, consider a KIM PM that supports Si and C species. +If the LAMMPS simulation has four atom types, where the first three are Si, +and the fourth is C, the following {pair_coeff} command would be used: pair_coeff * * Si Si Si C :pre -The 1st 2 arguments must be * * so as to span all LAMMPS atom types. -The first three Si arguments map LAMMPS atom types 1,2,3 to Si as -defined within KIM. The final C argument maps LAMMPS atom type 4 to C -as defined within KIM. +The first two arguments must be * * so as to span all LAMMPS atom types. +The first three Si arguments map LAMMPS atom types 1, 2, and 3 to Si as +defined within KIM PM. The final C argument maps LAMMPS atom type 4 to C. :line In addition to the usual LAMMPS error messages, the KIM library itself may generate errors, which should be printed to the screen. In this -case it is also useful to check the kim.log file for additional error -information. The file kim.log should be generated in the same +case it is also useful to check the {kim.log} file for additional error +information. The file {kim.log} should be generated in the same directory where LAMMPS is running. To download, build, and install the KIM library on your system, see -the lib/kim/README file. Once you have done this and built LAMMPS +the {lib/kim/README} file. Once you have done this and built LAMMPS with the KIM package installed you can run the example input scripts -in examples/kim. +in {examples/kim}. :line @@ -103,15 +99,14 @@ This pair style can only be used via the {pair} keyword of the [Restrictions:] -This pair style is part of the KIM package. It is only enabled if -LAMMPS was built with that package. See the "Build -package"_Build_package.html doc page for more info. +This pair style is part of the KIM package. See details on +restrictions in "kim_commands"_kim_commands.html. This current version of pair_style kim is compatible with the kim-api package version 2.0.0 and higher. [Related commands:] -"pair_coeff"_pair_coeff.html +"pair_coeff"_pair_coeff.html, "kim_commands"_kim_commands.html [Default:] none diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index a171e01b77..1dea229393 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -529,6 +529,7 @@ decrementing deeppink deepskyblue defgrad +defn deformable del deleteIDs @@ -577,6 +578,7 @@ Dihedrals dihydride Dij dimdim +dimensioned dimensionality dimgray dipolar @@ -606,6 +608,7 @@ Dobson Dodds dodgerblue dof +doi Donadio dotc Doty @@ -757,6 +760,7 @@ equilibrating equilibration Equilibria equilization +Ercolessi eradius erate erc @@ -883,6 +887,7 @@ Fogarty Foiles fopenmp forestgreen +formatarg formulae Forschungszentrum Fortran @@ -1624,6 +1629,7 @@ meso mesoparticle mesoscale mesoscopic +metadata metadynamics Metadynamics Methfessel @@ -2262,6 +2268,7 @@ quati quatj quatk quatw +queryargs Queteschiner qw qx @@ -2291,6 +2298,7 @@ rcutfac rdc rdf RDideal +rdx README realtime reamin @@ -2317,6 +2325,8 @@ Rensselaer reparameterizing repo representable +Reproducibility +reproducibility repuls rescale rescaled @@ -2607,6 +2617,7 @@ Stoll stopstep Stouch Straatsma +Strachan Stratford Strathclyde Straub @@ -2819,6 +2830,7 @@ txt typeI typeJ typeN +typeargs Tz Tzou ub @@ -2847,6 +2859,7 @@ undump uniaxial uniaxially unimodal +unitarg unitless Universite unix diff --git a/examples/kim/.gitignore b/examples/kim/.gitignore new file mode 100644 index 0000000000..63421e4217 --- /dev/null +++ b/examples/kim/.gitignore @@ -0,0 +1 @@ +/kim.log diff --git a/examples/kim/in.kim.lj.newton-on b/examples/kim/in.kim-ex.melt similarity index 79% rename from examples/kim/in.kim.lj.newton-on rename to examples/kim/in.kim-ex.melt index 3a95f1dbb0..5cc3dbc61b 100644 --- a/examples/kim/in.kim.lj.newton-on +++ b/examples/kim/in.kim-ex.melt @@ -14,20 +14,14 @@ variable xx equal 20*$x variable yy equal 20*$y variable zz equal 20*$z -units metal -atom_style atomic -newton on +kim_init LennardJones_Ar real lattice fcc 4.4300 region box block 0 ${xx} 0 ${yy} 0 ${zz} create_box 1 box create_atoms 1 box -#pair_style lj/cut 8.1500 -#pair_coeff 1 1 0.0104 3.4000 - -pair_style kim LennardJones_Ar -pair_coeff * * Ar +kim_interactions Ar mass 1 39.95 velocity all create 200.0 232345 loop geom diff --git a/examples/kim/in.kim-pm-query.melt b/examples/kim/in.kim-pm-query.melt new file mode 100644 index 0000000000..fa04d90436 --- /dev/null +++ b/examples/kim/in.kim-pm-query.melt @@ -0,0 +1,46 @@ +# 3d Lennard-Jones melt +# +# This example requires that the KIM Portable Model (PM) +# SW_StillingerWeber_1985_Si__MO_405512056662_005 +# is installed. This can be done with the command +# kim-api-collections-management install user SW_StillingerWeber_1985_Si__MO_405512056662_005 +# If this command does not work, you may need to setup your PATH to find the utility. +# If you installed the kim-api using the LAMMPS CMake build, you can do the following +# (where the current working directory is assumed to be the LAMMPS build directory) +# source ./kim_build-prefix/bin/kim-api-activate +# If you installed the kim-api using the LAMMPS Make build, you can do the following +# (where the current working directory is assumed to be the LAMMPS src directory) +# source ../lib/kim/installed-kim-api-X.Y.Z/bin/kim-api-activate +# (where you should relplace X.Y.Z with the appropriate kim-api version number). +# +# Or, see https://openkim.org/doc/obtaining-models for alternative options. +# + +variable x index 1 +variable y index 1 +variable z index 1 + +variable xx equal 20*$x +variable yy equal 20*$y +variable zz equal 20*$z + +kim_init SW_StillingerWeber_1985_Si__MO_405512056662_005 real +kim_query a0 get_lattice_constant_cubic crystal=["fcc"] species=["Si"] units=["angstrom"] + +lattice fcc ${a0} +region box block 0 ${xx} 0 ${yy} 0 ${zz} +create_box 1 box +create_atoms 1 box + +kim_interactions Si + +mass 1 39.95 +velocity all create 200.0 232345 loop geom + +neighbor 0.3 bin +neigh_modify delay 0 every 1 check yes + +fix 1 all nve +#fix 1 all npt temp 1.0 1.0 1.0 iso 1.0 1.0 3.0 + +run 100 diff --git a/examples/kim/in.kim-pm.melt b/examples/kim/in.kim-pm.melt new file mode 100644 index 0000000000..9959a66793 --- /dev/null +++ b/examples/kim/in.kim-pm.melt @@ -0,0 +1,45 @@ +# 3d Lennard-Jones melt +# +# This example requires that the KIM Portable Model (PM) +# SW_StillingerWeber_1985_Si__MO_405512056662_005 +# is installed. This can be done with the command +# kim-api-collections-management install user SW_StillingerWeber_1985_Si__MO_405512056662_005 +# If this command does not work, you may need to setup your PATH to find the utility. +# If you installed the kim-api using the LAMMPS CMake build, you can do the following +# (where the current working directory is assumed to be the LAMMPS build directory) +# source ./kim_build-prefix/bin/kim-api-activate +# If you installed the kim-api using the LAMMPS Make build, you can do the following +# (where the current working directory is assumed to be the LAMMPS src directory) +# source ../lib/kim/installed-kim-api-X.Y.Z/bin/kim-api-activate +# (where you should relplace X.Y.Z with the appropriate kim-api version number). +# +# Or, see https://openkim.org/doc/obtaining-models for alternative options. +# + +variable x index 1 +variable y index 1 +variable z index 1 + +variable xx equal 20*$x +variable yy equal 20*$y +variable zz equal 20*$z + +kim_init SW_StillingerWeber_1985_Si__MO_405512056662_005 real + +lattice fcc 4.4300 +region box block 0 ${xx} 0 ${yy} 0 ${zz} +create_box 1 box +create_atoms 1 box + +kim_interactions Si + +mass 1 39.95 +velocity all create 200.0 232345 loop geom + +neighbor 0.3 bin +neigh_modify delay 0 every 1 check yes + +fix 1 all nve +#fix 1 all npt temp 1.0 1.0 1.0 iso 1.0 1.0 3.0 + +run 100 diff --git a/examples/kim/in.kim-sm.melt b/examples/kim/in.kim-sm.melt new file mode 100644 index 0000000000..0ee8e9a857 --- /dev/null +++ b/examples/kim/in.kim-sm.melt @@ -0,0 +1,45 @@ +# 3d Lennard-Jones melt +# +# This example requires that the KIM Simulator Model (PM) +# Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 +# is installed. This can be done with the command +# kim-api-collections-management install user Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 +# If this command does not work, you may need to setup your PATH to find the utility. +# If you installed the kim-api using the LAMMPS CMake build, you can do the following +# (where the current working directory is assumed to be the LAMMPS build directory) +# source ./kim_build-prefix/bin/kim-api-activate +# If you installed the kim-api using the LAMMPS Make build, you can do the following +# (where the current working directory is assumed to be the LAMMPS src directory) +# source ../lib/kim/installed-kim-api-X.Y.Z/bin/kim-api-activate +# (where you should relplace X.Y.Z with the appropriate kim-api version number). +# +# See https://openkim.org/doc/obtaining-models for alternative options. +# + +variable x index 1 +variable y index 1 +variable z index 1 + +variable xx equal 20*$x +variable yy equal 20*$y +variable zz equal 20*$z + +kim_init Sim_LAMMPS_ReaxFF_StrachanVanDuinChakraborty_2003_CHNO__SM_107643900657_000 real + +lattice fcc 4.4300 +region box block 0 ${xx} 0 ${yy} 0 ${zz} +create_box 1 box +create_atoms 1 box + +kim_interactions O + +mass 1 39.95 +velocity all create 200.0 232345 loop geom + +neighbor 0.3 bin +neigh_modify delay 0 every 1 check yes + +fix 1 all nve +#fix 1 all npt temp 1.0 1.0 1.0 iso 1.0 1.0 3.0 + +run 100 diff --git a/examples/kim/in.kim.lj.lmp.newton-off b/examples/kim/in.kim.lj.lmp.newton-off deleted file mode 100644 index 197755294a..0000000000 --- a/examples/kim/in.kim.lj.lmp.newton-off +++ /dev/null @@ -1,35 +0,0 @@ -# 3d Lennard-Jones melt - -variable x index 1 -variable y index 1 -variable z index 1 - -variable xx equal 20*$x -variable yy equal 20*$y -variable zz equal 20*$z - -units metal -atom_style atomic -newton off - -lattice fcc 4.4300 -region box block 0 ${xx} 0 ${yy} 0 ${zz} -create_box 1 box -create_atoms 1 box - -pair_style lj/cut 8.1500 -pair_coeff 1 1 0.0104 3.4000 - -#pair_style kim LennardJones_Ar -#pair_coeff * * Ar - -mass 1 39.95 -velocity all create 200.0 232345 loop geom - -neighbor 0.3 bin -neigh_modify delay 0 every 1 check yes - -fix 1 all nve -#fix 1 all npt temp 1.0 1.0 1.0 iso 1.0 1.0 3.0 - -run 100 diff --git a/examples/kim/in.kim.lj.newton-off b/examples/kim/in.kim.lj.newton-off deleted file mode 100644 index 82cf5ba602..0000000000 --- a/examples/kim/in.kim.lj.newton-off +++ /dev/null @@ -1,41 +0,0 @@ -# 3d Lennard-Jones melt -# -# This example requires that the example models provided with -# the kim-api package are installed. see the ./lib/kim/README or -# ./lib/kim/Install.py files for details on how to install these -# example models. -# - -variable x index 1 -variable y index 1 -variable z index 1 - -variable xx equal 20*$x -variable yy equal 20*$y -variable zz equal 20*$z - -units metal -atom_style atomic -newton off - -lattice fcc 4.4300 -region box block 0 ${xx} 0 ${yy} 0 ${zz} -create_box 1 box -create_atoms 1 box - -#pair_style lj/cut 8.1500 -#pair_coeff 1 1 0.0104 3.4000 - -pair_style kim LennardJones_Ar -pair_coeff * * Ar - -mass 1 39.95 -velocity all create 200.0 232345 loop geom - -neighbor 0.3 bin -neigh_modify delay 0 every 1 check yes - -fix 1 all nve -#fix 1 all npt temp 1.0 1.0 1.0 iso 1.0 1.0 3.0 - -run 100 diff --git a/examples/kim/in.kim.lj.lmp.newton-on b/examples/kim/in.lammps.melt similarity index 91% rename from examples/kim/in.kim.lj.lmp.newton-on rename to examples/kim/in.lammps.melt index f9f79e2bb2..5792f3a5db 100644 --- a/examples/kim/in.kim.lj.lmp.newton-on +++ b/examples/kim/in.lammps.melt @@ -8,9 +8,7 @@ variable xx equal 20*$x variable yy equal 20*$y variable zz equal 20*$z -units metal -atom_style atomic -newton on +units real lattice fcc 4.4300 region box block 0 ${xx} 0 ${yy} 0 ${zz} diff --git a/examples/kim/in.query b/examples/kim/in.query deleted file mode 100644 index 33272dc298..0000000000 --- a/examples/kim/in.query +++ /dev/null @@ -1,11 +0,0 @@ - -# example for performing a query to the OpenKIM test database to retrieve -# a parameter to be used in the input. here it requests the aluminium -# lattice constant for a specific test used for a specific model and then -# assigns it to the variable 'latconst' - -units metal -info variables out log -kim_query latconst get_test_result test=TE_156715955670 species=["Al"] model=MO_800509458712 prop=structure-cubic-crystal-npt keys=["a"] units=["angstrom"] -info variables out log -lattice fcc ${latconst} diff --git a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.1 b/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.1 deleted file mode 100644 index 5925fd750d..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.1 +++ /dev/null @@ -1,55 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 1 by 1 MPI processor grid -Created 32000 atoms - Time spent = 0.004499 secs -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cut, perpetual - attributes: half, newton off - pair build: half/bin/newtoff - stencil: half/bin/3d/newtoff - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 20.37 | 20.37 | 20.37 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 2.92885 on 1 procs for 100 steps with 32000 atoms - -Performance: 2.950 ns/day, 8.136 hours/ns, 34.143 timesteps/s -99.1% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 2.5638 | 2.5638 | 2.5638 | 0.0 | 87.54 -Neigh | 0.31935 | 0.31935 | 0.31935 | 0.0 | 10.90 -Comm | 0.006833 | 0.006833 | 0.006833 | 0.0 | 0.23 -Output | 0.000107 | 0.000107 | 0.000107 | 0.0 | 0.00 -Modify | 0.027806 | 0.027806 | 0.027806 | 0.0 | 0.95 -Other | | 0.01091 | | | 0.37 - -Nlocal: 32000 ave 32000 max 32000 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 19911 ave 19911 max 19911 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 2.3705e+06 ave 2.3705e+06 max 2.3705e+06 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 2370499 -Ave neighs/atom = 74.0781 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:03 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.4 b/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.4 deleted file mode 100644 index c1ca108c7b..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-off.4 +++ /dev/null @@ -1,55 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 2 by 2 MPI processor grid -Created 32000 atoms - Time spent = 0.001039 secs -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cut, perpetual - attributes: half, newton off - pair build: half/bin/newtoff - stencil: half/bin/3d/newtoff - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 8.013 | 8.013 | 8.013 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 0.778581 on 4 procs for 100 steps with 32000 atoms - -Performance: 11.097 ns/day, 2.163 hours/ns, 128.439 timesteps/s -99.8% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.65171 | 0.65891 | 0.67656 | 1.3 | 84.63 -Neigh | 0.07924 | 0.079548 | 0.07997 | 0.1 | 10.22 -Comm | 0.006755 | 0.0069015 | 0.007072 | 0.2 | 0.89 -Output | 4.6e-05 | 9.725e-05 | 0.000203 | 0.0 | 0.01 -Modify | 0.006841 | 0.006941 | 0.007015 | 0.1 | 0.89 -Other | | 0.02618 | | | 3.36 - -Nlocal: 8000 ave 8018 max 7967 min -Histogram: 1 0 0 0 0 0 1 0 0 2 -Nghost: 9131 ave 9164 max 9113 min -Histogram: 2 0 0 1 0 0 0 0 0 1 -Neighs: 630904 ave 632094 max 628209 min -Histogram: 1 0 0 0 0 0 0 1 0 2 - -Total # of neighbors = 2523614 -Ave neighs/atom = 78.8629 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:00 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.1 b/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.1 deleted file mode 100644 index 53555743d7..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.1 +++ /dev/null @@ -1,55 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 1 by 1 MPI processor grid -Created 32000 atoms - Time spent = 0.003479 secs -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cut, perpetual - attributes: half, newton on - pair build: half/bin/atomonly/newton - stencil: half/bin/3d/newton - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 19.23 | 19.23 | 19.23 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 2.17978 on 1 procs for 100 steps with 32000 atoms - -Performance: 3.964 ns/day, 6.055 hours/ns, 45.876 timesteps/s -99.9% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 1.9892 | 1.9892 | 1.9892 | 0.0 | 91.26 -Neigh | 0.14506 | 0.14506 | 0.14506 | 0.0 | 6.65 -Comm | 0.011049 | 0.011049 | 0.011049 | 0.0 | 0.51 -Output | 9.1e-05 | 9.1e-05 | 9.1e-05 | 0.0 | 0.00 -Modify | 0.02347 | 0.02347 | 0.02347 | 0.0 | 1.08 -Other | | 0.01094 | | | 0.50 - -Nlocal: 32000 ave 32000 max 32000 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 19911 ave 19911 max 19911 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 2.12688e+06 ave 2.12688e+06 max 2.12688e+06 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 2126875 -Ave neighs/atom = 66.4648 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:02 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.4 b/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.4 deleted file mode 100644 index f0fdf66193..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.lmp.newton-on.4 +++ /dev/null @@ -1,55 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 2 by 2 MPI processor grid -Created 32000 atoms - Time spent = 0.000919 secs -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cut, perpetual - attributes: half, newton on - pair build: half/bin/atomonly/newton - stencil: half/bin/3d/newton - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 7.632 | 7.632 | 7.632 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 0.63515 on 4 procs for 100 steps with 32000 atoms - -Performance: 13.603 ns/day, 1.764 hours/ns, 157.443 timesteps/s -99.8% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.55365 | 0.5566 | 0.55868 | 0.2 | 87.63 -Neigh | 0.041495 | 0.0418 | 0.04211 | 0.1 | 6.58 -Comm | 0.019086 | 0.021075 | 0.023898 | 1.2 | 3.32 -Output | 4.4e-05 | 5.025e-05 | 6e-05 | 0.0 | 0.01 -Modify | 0.009315 | 0.0093595 | 0.009422 | 0.0 | 1.47 -Other | | 0.006263 | | | 0.99 - -Nlocal: 8000 ave 8018 max 7967 min -Histogram: 1 0 0 0 0 0 1 0 0 2 -Nghost: 9131 ave 9164 max 9113 min -Histogram: 2 0 0 1 0 0 0 0 0 1 -Neighs: 531719 ave 533273 max 529395 min -Histogram: 1 0 0 0 1 0 0 0 0 2 - -Total # of neighbors = 2126875 -Ave neighs/atom = 66.4648 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:00 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.newton-off.1 b/examples/kim/log.06Feb2019.in.kim.lj.newton-off.1 deleted file mode 100644 index 0ab258fe0d..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.newton-off.1 +++ /dev/null @@ -1,59 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 1 by 1 MPI processor grid -Created 32000 atoms - Time spent = 0.003446 secs -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair kim, perpetual - attributes: full, newton off, cut 8.45 - pair build: full/bin/atomonly - stencil: full/bin/3d - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 28.51 | 28.51 | 28.51 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 3.01669 on 1 procs for 100 steps with 32000 atoms - -Performance: 2.864 ns/day, 8.380 hours/ns, 33.149 timesteps/s -99.8% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 2.6562 | 2.6562 | 2.6562 | 0.0 | 88.05 -Neigh | 0.31903 | 0.31903 | 0.31903 | 0.0 | 10.58 -Comm | 0.00634 | 0.00634 | 0.00634 | 0.0 | 0.21 -Output | 9.1e-05 | 9.1e-05 | 9.1e-05 | 0.0 | 0.00 -Modify | 0.024723 | 0.024723 | 0.024723 | 0.0 | 0.82 -Other | | 0.01032 | | | 0.34 - -Nlocal: 32000 ave 32000 max 32000 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 19911 ave 19911 max 19911 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 0 ave 0 max 0 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -FullNghs: 4.25375e+06 ave 4.25375e+06 max 4.25375e+06 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 4253750 -Ave neighs/atom = 132.93 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:03 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.newton-off.4 b/examples/kim/log.06Feb2019.in.kim.lj.newton-off.4 deleted file mode 100644 index c17ea6afb7..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.newton-off.4 +++ /dev/null @@ -1,65 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 2 by 2 MPI processor grid -Created 32000 atoms - Time spent = 0.000921 secs -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair kim, perpetual - attributes: full, newton off, cut 8.45 - pair build: full/bin/atomonly - stencil: full/bin/3d - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 10.05 | 10.05 | 10.05 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 0.890192 on 4 procs for 100 steps with 32000 atoms - -Performance: 9.706 ns/day, 2.473 hours/ns, 112.335 timesteps/s -99.7% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.77867 | 0.77906 | 0.7794 | 0.0 | 87.52 -Neigh | 0.087831 | 0.088176 | 0.088805 | 0.1 | 9.91 -Comm | 0.006358 | 0.0065898 | 0.006815 | 0.3 | 0.74 -Output | 4.9e-05 | 5.975e-05 | 6.8e-05 | 0.0 | 0.01 -Modify | 0.010265 | 0.010429 | 0.010678 | 0.2 | 1.17 -Other | | 0.005874 | | | 0.66 - -Nlocal: 8000 ave 8018 max 7967 min -Histogram: 1 0 0 0 0 0 1 0 0 2 -Nghost: 9131 ave 9164 max 9113 min -Histogram: 2 0 0 1 0 0 0 0 0 1 -Neighs: 0 ave 0 max 0 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -FullNghs: 1.06344e+06 ave 1.06594e+06 max 1.05881e+06 min -Histogram: 1 0 0 0 0 0 1 0 0 2 - -Total # of neighbors = 4253750 -Ave neighs/atom = 132.93 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:00 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.newton-on.1 b/examples/kim/log.06Feb2019.in.kim.lj.newton-on.1 deleted file mode 100644 index 59d018e12a..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.newton-on.1 +++ /dev/null @@ -1,59 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 1 by 1 MPI processor grid -Created 32000 atoms - Time spent = 0.003089 secs -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair kim, perpetual - attributes: full, newton off, cut 8.45 - pair build: full/bin/atomonly - stencil: full/bin/3d - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 28.12 | 28.12 | 28.12 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 3.05849 on 1 procs for 100 steps with 32000 atoms - -Performance: 2.825 ns/day, 8.496 hours/ns, 32.696 timesteps/s -99.6% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 2.6786 | 2.6786 | 2.6786 | 0.0 | 87.58 -Neigh | 0.33105 | 0.33105 | 0.33105 | 0.0 | 10.82 -Comm | 0.012602 | 0.012602 | 0.012602 | 0.0 | 0.41 -Output | 9.5e-05 | 9.5e-05 | 9.5e-05 | 0.0 | 0.00 -Modify | 0.024858 | 0.024858 | 0.024858 | 0.0 | 0.81 -Other | | 0.01132 | | | 0.37 - -Nlocal: 32000 ave 32000 max 32000 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 19911 ave 19911 max 19911 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 0 ave 0 max 0 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -FullNghs: 4.25375e+06 ave 4.25375e+06 max 4.25375e+06 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 4253750 -Ave neighs/atom = 132.93 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:03 diff --git a/examples/kim/log.06Feb2019.in.kim.lj.newton-on.4 b/examples/kim/log.06Feb2019.in.kim.lj.newton-on.4 deleted file mode 100644 index da8c9f0faa..0000000000 --- a/examples/kim/log.06Feb2019.in.kim.lj.newton-on.4 +++ /dev/null @@ -1,65 +0,0 @@ -LAMMPS (1 Feb 2019) -OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:87) - using 1 OpenMP thread(s) per MPI task -Lattice spacing in x,y,z = 4.43 4.43 4.43 -Created orthogonal box = (0 0 0) to (88.6 88.6 88.6) - 1 by 2 by 2 MPI processor grid -Created 32000 atoms - Time spent = 0.000893 secs -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -WARNING: KIM Model does not provide `partialParticleEnergy'; energy per atom will be zero (src/KIM/pair_kim.cpp:1097) -WARNING: KIM Model does not provide `partialParticleVirial'; virial per atom will be zero (src/KIM/pair_kim.cpp:1102) -Neighbor list info ... - update every 1 steps, delay 0 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 8.45 - ghost atom cutoff = 8.45 - binsize = 4.225, bins = 21 21 21 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair kim, perpetual - attributes: full, newton off, cut 8.45 - pair build: full/bin/atomonly - stencil: full/bin/3d - bin: standard -Setting up Verlet run ... - Unit style : metal - Current step : 0 - Time step : 0.001 -Per MPI rank memory allocation (min/avg/max) = 9.789 | 9.789 | 9.789 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 200 6290.8194 0 7118.0584 129712.25 - 100 95.179725 6718.814 0 7112.496 133346.59 -Loop time of 0.903182 on 4 procs for 100 steps with 32000 atoms - -Performance: 9.566 ns/day, 2.509 hours/ns, 110.720 timesteps/s -99.6% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.76173 | 0.76349 | 0.76597 | 0.2 | 84.53 -Neigh | 0.088773 | 0.088938 | 0.089074 | 0.0 | 9.85 -Comm | 0.032018 | 0.03452 | 0.03638 | 0.9 | 3.82 -Output | 4e-05 | 4.425e-05 | 5.2e-05 | 0.0 | 0.00 -Modify | 0.009278 | 0.0093917 | 0.009528 | 0.1 | 1.04 -Other | | 0.006797 | | | 0.75 - -Nlocal: 8000 ave 8018 max 7967 min -Histogram: 1 0 0 0 0 0 1 0 0 2 -Nghost: 9131 ave 9164 max 9113 min -Histogram: 2 0 0 1 0 0 0 0 0 1 -Neighs: 0 ave 0 max 0 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -FullNghs: 1.06344e+06 ave 1.06594e+06 max 1.05881e+06 min -Histogram: 1 0 0 0 0 0 1 0 0 2 - -Total # of neighbors = 4253750 -Ave neighs/atom = 132.93 -Neighbor list builds = 3 -Dangerous builds = 0 -Total wall time: 0:00:00 diff --git a/examples/kim/log.22Mar2019.query.g++.1 b/examples/kim/log.22Mar2019.query.g++.1 deleted file mode 100644 index 034bb13bba..0000000000 --- a/examples/kim/log.22Mar2019.query.g++.1 +++ /dev/null @@ -1,34 +0,0 @@ -LAMMPS (28 Feb 2019) - -# example for performing a query to the OpenKIM test database to retrieve -# a parameter to be used in the input. here it requests the aluminium -# lattice constant for a specific test used for a specific model and then -# assigns it to the variable 'latconst' - -units metal -info variables out log - -Info-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info -Printed on Fri Mar 22 20:00:56 2019 - - -Variable information: - -Info-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info - -kim_query latconst get_test_result test=TE_156715955670 species=["Al"] model=MO_800509458712 prop=structure-cubic-crystal-npt keys=["a"] units=["angstrom"] -info variables out log - -Info-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info -Printed on Fri Mar 22 20:00:57 2019 - - -Variable information: -Variable[ 0]: latconst , style = string , def = 4.03208274841 - -Info-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info - -lattice fcc ${latconst} -lattice fcc 4.03208274841 -Lattice spacing in x,y,z = 4.03208 4.03208 4.03208 -Total wall time: 0:00:00 diff --git a/lib/kim/Install.py b/lib/kim/Install.py index c3588241c4..de22950639 100644 --- a/lib/kim/Install.py +++ b/lib/kim/Install.py @@ -18,7 +18,7 @@ parser = ArgumentParser(prog='Install.py', # settings thisdir = fullpath('.') -version = "kim-api-2.0.2" +version = "kim-api-2.1.1" # help message @@ -39,11 +39,8 @@ make lib-kim args="-b -a EAM_ErcolessiAdams_1994_Al__MO_324507536345_002" # Ditt make lib-kim args="-b -a everything" # install KIM API lib with all models make lib-kim args="-n -a EAM_Dynamo_Ackland_2003_W__MO_141627196590_005" # only add one model or model driver -See the list of KIM model drivers here: -https://openkim.org/browse/model-drivers/alphabetical - See the list of all KIM models here: -https://openkim.org/browse/models/by-model-drivers +https://openkim.org/browse/models """ pgroup = parser.add_mutually_exclusive_group() @@ -132,7 +129,7 @@ if buildflag: # build kim-api print("Building kim-api ...") - cmd = 'cd "%s/%s/build" && make' % (thisdir, version) + cmd = 'cd "%s/%s/build" && make -j2' % (thisdir, version) txt = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) if verboseflag: print(txt.decode("UTF-8")) @@ -140,7 +137,7 @@ if buildflag: # install kim-api print("Installing kim-api ...") - cmd = 'cd "%s/%s/build" && make install' % (thisdir, version) + cmd = 'cd "%s/%s/build" && make -j2 install' % (thisdir, version) txt = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) if verboseflag: print(txt.decode("UTF-8")) diff --git a/lib/kim/README b/lib/kim/README index d3327537b6..3cba4a4597 100644 --- a/lib/kim/README +++ b/lib/kim/README @@ -1,11 +1,11 @@ -This directory contains build settings for the KIM API library which -is required to use the KIM package and its pair_style kim command in a -LAMMPS input script. +This directory contains build settings for the KIM API library which is +required to use the KIM package and its kim_init, kim_interactions, kim_query, +and pair_kim commands in a LAMMPS input script. Information about the KIM project can be found at https://openkim.org. The KIM project is lead by Ellad Tadmor and Ryan Elliott (U Minn). Ryan Elliott is the main developer for the KIM API and he also -maintains the code that implements the pair_style kim command. +maintains the code that implements the KIM commands. You can type "make lib-kim" from the src directory to see help on how to download and build this library via make commands, or you can @@ -13,11 +13,9 @@ do the same thing by typing "python Install.py" from within this directory, or you can do it manually by following the instructions below. -As of KIM API version 2, the KIM package also provides a LAMMPS command -to perform queries through the OpenKIM web API. This feature requires -that the CURL library (libcurl) development package and its configuration -query tool, curl-config, are installed. The provided Makefile.lammps -is set up to automatically detect this. +Use of the kim_query command requires that the CURL library (libcurl) +development package and its configuration query tool, curl-config, are +installed. The provided Makefile.lammps is set up to automatically detect this. ----------------- @@ -40,8 +38,8 @@ $ cmake .. -DCMAKE_INSTALL_PREFIX=${PWD}/../../installed-kim-api-X.Y.Z 3. Build and install the kim-api and model -$ make -$ make install +$ make -j2 +$ make -j2 install 4. Remove source and build files @@ -53,7 +51,7 @@ $ rm -rf kim-api-X.Y.Z.txz desired value) $ source ${PWD}/kim-api-X.Y.Z/bin/kim-api-activate -$ kim-api-collections-management install system Pair_Johnson_Fe__MO_857282754307_002 +$ kim-api-collections-management install system EAM_ErcolessiAdams_1994_Al__MO_324507536345_002 ----------------- diff --git a/src/KIM/README b/src/KIM/README index a69206596f..e61f47426f 100644 --- a/src/KIM/README +++ b/src/KIM/README @@ -1,29 +1,30 @@ -This package provides a pair_style kim command which is a wrapper on -the Knowledge Base for Interatomic Models (KIM) repository of -interatomic potentials, so that they can be used by LAMMPS scripts. +This package provides the kim_init, kim_query, kim_interactions, and +the pair_style kim command which are wrappers on the Knowledgebase of +Interatomic Models (KIM) repository of interatomic potentials, so that +they can be used by LAMMPS scripts. Information about the KIM project can be found at https://openkim.org. -The KIM project is lead by Ellad Tadmor and Ryan Elliott (U Minn) and -James Sethna (Cornell U). Ryan Elliott is the main developer for the -KIM API and he also maintains the code that implements the pair_style -kim command. +The KIM project is lead by Ellad B. Tadmor and Ryan S. Elliott (UMN). +Ryan Elliott is the main developer for the KIM API and he also +maintains the code that implements these commands. -Using this package requires the KIM library and its models +Using this package requires the KIM-API library and its models (interatomic potentials) to be downloaded and installed on your system. The library can be downloaded and built in lib/kim or elsewhere on your system, which must be done before bulding LAMMPS with this package. Details of the download, build, and install -process for KIM are given in the lib/kim/README file, and scripts will -soon be provided to help automate the process. Also see the LAMMPS -manual for general information on building LAMMPS with external +process for the KIM-API are given in the lib/kim/README file, and +scripts are provided to help automate the process. Also see the +LAMMPS manual for general information on building LAMMPS with external libraries. The settings in the Makefile.lammps file in lib/kim must be correct for LAMMPS to build correctly with this package installed. However, the default settings should be correct in most cases and the Makefile.lammps file usually will not need to be changed. Once you have successfully built LAMMPS with this package and the KIM -library you can test it using an input file from the examples dir: +library you can test it using an input files in the examples dir: -./lmp_serial < lammps/examples/kim/in.kim.lj +./lmp_serial -in lammps/examples/kim/in.kim.lj -This pair_style was written by Ryan S. Elliott (U Minn). +These commands were written by Ryan S. Elliott (UMN), Ellad B. Tadmor +(UMN) and Axel Kohlmeyer (Temple U). diff --git a/src/KIM/fix_store_kim.cpp b/src/KIM/fix_store_kim.cpp new file mode 100644 index 0000000000..16d606d2ed --- /dev/null +++ b/src/KIM/fix_store_kim.cpp @@ -0,0 +1,155 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +#include "fix_store_kim.h" +#include +extern "C" { +#include "KIM_SimulatorModel.h" +} +#include "error.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +/* ---------------------------------------------------------------------- */ + +FixStoreKIM::FixStoreKIM(LAMMPS *lmp, int narg, char **arg) + : Fix(lmp, narg, arg), simulator_model(NULL), model_name(NULL), + model_units(NULL), user_units(NULL) +{ + if (narg != 3) error->all(FLERR,"Illegal fix STORE/KIM command"); +} + +/* ---------------------------------------------------------------------- */ + +FixStoreKIM::~FixStoreKIM() +{ + // free associated storage + + if (simulator_model) { + KIM_SimulatorModel *sm = (KIM_SimulatorModel *)simulator_model; + KIM_SimulatorModel_Destroy(&sm); + simulator_model = NULL; + } + + if (model_name) { + char *mn = (char *)model_name; + delete[] mn; + model_name = NULL; + } + + if (model_units) { + char *mu = (char *)model_units; + delete[] mu; + model_units = NULL; + } + if (user_units) { + char *uu = (char *)user_units; + delete[] uu; + user_units = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +int FixStoreKIM::setmask() +{ + int mask = 0; + return mask; +} + + +/* ---------------------------------------------------------------------- */ + +void FixStoreKIM::setptr(const char *name, void *ptr) +{ + if (strcmp(name,"simulator_model") == 0) { + if (simulator_model) { + KIM_SimulatorModel *sm = (KIM_SimulatorModel *)simulator_model; + KIM_SimulatorModel_Destroy(&sm); + } + simulator_model = ptr; + } else if (strcmp(name,"model_name") == 0) { + if (model_name) { + char *mn = (char *)model_name; + delete[] mn; + } + model_name = ptr; + } else if (strcmp(name,"model_units") == 0) { + if (model_units) { + char *mu = (char *)model_units; + delete[] mu; + } + model_units = ptr; + } else if (strcmp(name,"user_units") == 0) { + if (user_units) { + char *uu = (char *)user_units; + delete[] uu; + } + user_units = ptr; + } else error->all(FLERR,"Unknown property in fix STORE/KIM"); +} + +/* ---------------------------------------------------------------------- */ + +void *FixStoreKIM::getptr(const char *name) +{ + if (strcmp(name,"simulator_model") == 0) return simulator_model; + else if (strcmp(name,"model_name") == 0) return model_name; + else if (strcmp(name,"model_units") == 0) return model_units; + else if (strcmp(name,"user_units") == 0) return user_units; + else return NULL; +} diff --git a/src/KIM/fix_store_kim.h b/src/KIM/fix_store_kim.h new file mode 100644 index 0000000000..6baf480993 --- /dev/null +++ b/src/KIM/fix_store_kim.h @@ -0,0 +1,99 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS + +FixStyle(STORE/KIM,FixStoreKIM) + +#else + +#ifndef LMP_FIX_STORE_KIM_H +#define LMP_FIX_STORE_KIM_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixStoreKIM : public Fix { + public: + FixStoreKIM(class LAMMPS *, int, char **); + ~FixStoreKIM(); + int setmask(); + + void setptr(const char *, void *); + void *getptr(const char *); + + private: + void *simulator_model; // pointer to KIM simulator model class + void *model_name; // string of KIM model name + void *model_units; // string of unit conversion origin or NULL + void *user_units; // string of unit conversion target or NULL +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +*/ diff --git a/src/KIM/kim_init.cpp b/src/KIM/kim_init.cpp new file mode 100644 index 0000000000..a4272caa01 --- /dev/null +++ b/src/KIM/kim_init.cpp @@ -0,0 +1,508 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) + Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.1.0 (and newer) package +------------------------------------------------------------------------- */ + +#include "kim_init.h" +#include +#include +#include +#include +#include "error.h" +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "modify.h" +#include "update.h" +#include "universe.h" +#include "input.h" +#include "variable.h" +#include "citeme.h" +#include "fix_store_kim.h" +#include "kim_units.h" + +extern "C" { +#include "KIM_SimulatorHeaders.h" +} + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +void KimInit::command(int narg, char **arg) +{ + if ((narg < 2) || (narg > 3)) error->all(FLERR,"Illegal kim_init command"); + + if (domain->box_exist) + error->all(FLERR,"Must use 'kim_init' command before " + "simulation box is defined"); + char *model_name = new char[strlen(arg[0])+1]; + strcpy(model_name,arg[0]); + char *user_units = new char[strlen(arg[1])+1]; + strcpy(user_units,arg[1]); + if (narg == 3) { + if (strcmp(arg[2],"unit_conversion_mode")==0) unit_conversion_mode = true; + else { error->all(FLERR,"Illegal kim_init command"); } + } else unit_conversion_mode = false; + + char *model_units; + determine_model_type_and_units(model_name, user_units, &model_units); + + write_log_cite(model_name); + + do_init(model_name, user_units, model_units); +} + + +/* ---------------------------------------------------------------------- */ +namespace { +void get_kim_unit_names( + char const * const system, + KIM_LengthUnit & lengthUnit, + KIM_EnergyUnit & energyUnit, + KIM_ChargeUnit & chargeUnit, + KIM_TemperatureUnit & temperatureUnit, + KIM_TimeUnit & timeUnit, + Error * error) +{ + if ((strcmp(system,"real")==0)) { + lengthUnit = KIM_LENGTH_UNIT_A; + energyUnit = KIM_ENERGY_UNIT_kcal_mol; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_fs; + } else if ((strcmp(system,"metal")==0)) { + lengthUnit = KIM_LENGTH_UNIT_A; + energyUnit = KIM_ENERGY_UNIT_eV; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_ps; + } else if ((strcmp(system,"si")==0)) { + lengthUnit = KIM_LENGTH_UNIT_m; + energyUnit = KIM_ENERGY_UNIT_J; + chargeUnit = KIM_CHARGE_UNIT_C; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_s; + } else if ((strcmp(system,"cgs")==0)) { + lengthUnit = KIM_LENGTH_UNIT_cm; + energyUnit = KIM_ENERGY_UNIT_erg; + chargeUnit = KIM_CHARGE_UNIT_statC; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_s; + } else if ((strcmp(system,"electron")==0)) { + lengthUnit = KIM_LENGTH_UNIT_Bohr; + energyUnit = KIM_ENERGY_UNIT_Hartree; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_fs; + } else if ((strcmp(system,"lj")==0)) { + error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); + } else { + error->all(FLERR,"Unknown unit_style"); + } +} +} // namespace +void KimInit::determine_model_type_and_units(char * model_name, + char * user_units, + char ** model_units) +{ + KIM_LengthUnit lengthUnit; + KIM_EnergyUnit energyUnit; + KIM_ChargeUnit chargeUnit; + KIM_TemperatureUnit temperatureUnit; + KIM_TimeUnit timeUnit; + int units_accepted; + KIM_Collections * kim_Coll; + KIM_CollectionItemType itemType; + + int kim_error = KIM_Collections_Create(&kim_Coll); + if (kim_error) { + error->all(FLERR,"Unable to access KIM Collections to find Model."); + } + + kim_error = KIM_Collections_GetItemType(kim_Coll, model_name, &itemType); + if (kim_error) { + error->all(FLERR,"KIM Model name not found."); + } + KIM_Collections_Destroy(&kim_Coll); + + if (KIM_CollectionItemType_Equal(itemType, + KIM_COLLECTION_ITEM_TYPE_portableModel)) + { + get_kim_unit_names(user_units, lengthUnit, energyUnit, + chargeUnit, temperatureUnit, timeUnit, error); + KIM_Model * kim_MO; + int kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, + lengthUnit, + energyUnit, + chargeUnit, + temperatureUnit, + timeUnit, + model_name, + &units_accepted, + &kim_MO); + + if (kim_error) + error->all(FLERR,"Unable to load KIM Simulator Model."); + + model_type = MO; + KIM_Model_Destroy(&kim_MO); + + if (units_accepted) { + *model_units = new char[strlen(user_units)+1]; + strcpy(*model_units,user_units); + return; + } else if (unit_conversion_mode) { + int const num_systems = 5; + char const * const systems[num_systems] + = {"metal", "real", "si", "cgs", "electron"}; + for (int i=0; i < num_systems; ++i) { + get_kim_unit_names(systems[i], lengthUnit, energyUnit, + chargeUnit, temperatureUnit, timeUnit, error); + kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, + lengthUnit, + energyUnit, + chargeUnit, + temperatureUnit, + timeUnit, + model_name, + &units_accepted, + &kim_MO); + KIM_Model_Destroy(&kim_MO); + if (units_accepted) { + *model_units = new char[strlen(systems[i])+1]; + strcpy(*model_units,systems[i]); + return; + } + } error->all(FLERR,"KIM Model does not support any lammps unit system"); + } else { + error->all(FLERR,"KIM Model does not support the requested unit system"); + } + } + else if (KIM_CollectionItemType_Equal( + itemType, KIM_COLLECTION_ITEM_TYPE_simulatorModel)) { + KIM_SimulatorModel * kim_SM; + kim_error = KIM_SimulatorModel_Create(model_name, &kim_SM); + if (kim_error) + error->all(FLERR,"Unable to load KIM Simulator Model."); + model_type = SM; + + int sim_fields; + int sim_lines; + char const * sim_field; + char const * sim_value; + KIM_SimulatorModel_GetNumberOfSimulatorFields(kim_SM, &sim_fields); + KIM_SimulatorModel_CloseTemplateMap(kim_SM); + for (int i=0; i < sim_fields; ++i) { + KIM_SimulatorModel_GetSimulatorFieldMetadata( + kim_SM,i,&sim_lines,&sim_field); + + if (0 == strcmp(sim_field,"units")) { + KIM_SimulatorModel_GetSimulatorFieldLine(kim_SM,i,0,&sim_value); + int len=strlen(sim_value)+1; + *model_units = new char[len]; strcpy(*model_units,sim_value); + break; + } + } + KIM_SimulatorModel_Destroy(&kim_SM); + + if ((! unit_conversion_mode) && (strcmp(*model_units, user_units)!=0)) { + std::string mesg("Incompatible units for KIM Simulator Model, " + "required units = "); + mesg += *model_units; + error->all(FLERR,mesg.c_str()); + } + } +} + + +/* ---------------------------------------------------------------------- */ + +void KimInit::do_init(char *model_name, char *user_units, char *model_units) +{ + // create storage proxy fix. delete existing fix, if needed. + + int ifix = modify->find_fix("KIM_MODEL_STORE"); + if (ifix >= 0) modify->delete_fix(ifix); + char *fixarg[3]; + fixarg[0] = (char *)"KIM_MODEL_STORE"; + fixarg[1] = (char *)"all"; + fixarg[2] = (char *)"STORE/KIM"; + modify->add_fix(3,fixarg); + ifix = modify->find_fix("KIM_MODEL_STORE"); + + FixStoreKIM *fix_store = (FixStoreKIM *) modify->fix[ifix]; + fix_store->setptr("model_name", (void *) model_name); + fix_store->setptr("user_units", (void *) user_units); + fix_store->setptr("model_units", (void *) model_units); + + // Begin output to log file + kim_init_log_delimiter("begin"); + + int kimerror; + KIM_SimulatorModel * simulatorModel; + if (model_type == SM) + { + kimerror = KIM_SimulatorModel_Create(model_name,&simulatorModel); + + char const *sim_name, *sim_version; + KIM_SimulatorModel_GetSimulatorNameAndVersion( + simulatorModel,&sim_name, &sim_version); + + if (0 != strcmp(sim_name,"LAMMPS")) + error->all(FLERR,"Incompatible KIM Simulator Model"); + + if (comm->me == 0) { + std::string mesg("# Using KIM Simulator Model : "); + mesg += model_name; + mesg += "\n"; + mesg += "# For Simulator : "; + mesg += std::string(sim_name) + " " + sim_version + "\n"; + mesg += "# Running on : LAMMPS "; + mesg += universe->version; + mesg += "\n"; + mesg += "#\n"; + + if (screen) fputs(mesg.c_str(),screen); + if (logfile) fputs(mesg.c_str(),logfile); + } + + fix_store->setptr("simulator_model", (void *) simulatorModel); + + // need to call this to have access to (some) simulator model init data. + + KIM_SimulatorModel_CloseTemplateMap(simulatorModel); + } + + // Define unit conversion factor variables and print to log + if (unit_conversion_mode) do_variables(user_units, model_units); + + // set units + + std::string cmd("units "); + cmd += model_units; + input->one(cmd.c_str()); + + if (model_type == SM) { + int sim_fields, sim_lines; + char const *sim_field, *sim_value; + KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields); + + // init model + + for (int i=0; i < sim_fields; ++i) { + KIM_SimulatorModel_GetSimulatorFieldMetadata( + simulatorModel,i,&sim_lines,&sim_field); + if (0 == strcmp(sim_field,"model-init")) { + for (int j=0; j < sim_lines; ++j) { + KIM_SimulatorModel_GetSimulatorFieldLine( + simulatorModel,i,j,&sim_value); + input->one(sim_value); + } + break; + } + } + + // reset template map. + KIM_SimulatorModel_OpenAndInitializeTemplateMap(simulatorModel); + } + + // End output to log file + kim_init_log_delimiter("end"); + +} + +/* ---------------------------------------------------------------------- */ + +void KimInit::kim_init_log_delimiter(std::string const begin_end) const +{ + if (comm->me == 0) { + std::string mesg; + if (begin_end == "begin") + mesg = + "#=== BEGIN kim-init ==========================================\n"; + else if (begin_end == "end") + mesg = + "#=== END kim-init ============================================\n\n"; + + input->write_echo(mesg.c_str()); + } +} + +/* ---------------------------------------------------------------------- */ + +void KimInit::do_variables(char *user_units, char *model_units) +{ + char *from = user_units, *to = model_units; + Variable *variable = input->variable; + + // refuse conversion from or to reduced units + + if ((strcmp(from,"lj") == 0) || (strcmp(to,"lj") == 0)) + error->all(FLERR,"Cannot set up conversion variables for 'lj' units"); + + // get index to internal style variables. create, if needed. + // set conversion factors for newly created variables. + double conversion_factor; + int ier; + char *args[3]; + std::string var_str; + args[1] = (char *)"internal"; + args[2] = (char *)"1.0"; + int v_unit; + int const nunits = 14; + char *units[nunits] = {(char *)"mass", + (char *)"distance", + (char *)"time", + (char *)"energy", + (char *)"velocity", + (char *)"force", + (char *)"torque", + (char *)"temperature", + (char *)"pressure", + (char *)"viscosity", + (char *)"charge", + (char *)"dipole", + (char *)"efield", + (char *)"density"}; + + if (comm->me == 0) { + std::string mesg("# Conversion factors from "); + mesg += from; + mesg += " to "; + mesg += to; + mesg += ":\n"; + input->write_echo(mesg.c_str()); + } + + for (int i = 0; i < nunits; i++) { + var_str = std::string("_u_") + std::string(units[i]); + args[0] = (char *)var_str.c_str(); + v_unit = variable->find(args[0]); + if (v_unit < 0) { + variable->set(3,args); + v_unit = variable->find(args[0]); + } + ier = lammps_unit_conversion(units[i], + from, + to, + conversion_factor); + if (ier != 0) { + std::string err = std::string("Unable to obtain conversion factor: ") + + "unit = " + units[i] + "; " + "from = " + from + "; " + "to = " + to + "."; + error->all(FLERR,err.c_str()); + } + variable->internal_set(v_unit,conversion_factor); + if (comm->me == 0) { + std::stringstream mesg; + mesg << "variable " << std::setw(15) << std::left << var_str + << " internal " + << std::setprecision(12) << std::scientific << conversion_factor + << std::endl; + input->write_echo(mesg.str().c_str()); + } + } + if (comm->me == 0) input->write_echo("#\n"); +} + +/* ---------------------------------------------------------------------- */ + +void KimInit::write_log_cite(char * model_name) +{ + KIM_Collections * coll; + int err = KIM_Collections_Create(&coll); + if (err) return; + + int extent; + if (model_type == MO) + { + err = KIM_Collections_CacheListOfItemMetadataFiles( + coll,KIM_COLLECTION_ITEM_TYPE_portableModel,model_name,&extent); + } + else if (model_type == SM) + { + err = KIM_Collections_CacheListOfItemMetadataFiles( + coll,KIM_COLLECTION_ITEM_TYPE_simulatorModel,model_name,&extent); + } + else + { + error->all(FLERR,"Unknown model type."); + } + + if (err) + { + KIM_Collections_Destroy(&coll); + return; + } + + for (int i = 0; i < extent;++i) + { + char const * fileName; + int availableAsString; + char const * fileString; + err = KIM_Collections_GetItemMetadataFile( + coll,i,&fileName,NULL,NULL,&availableAsString,&fileString); + if (err) continue; + + if (0 == strncmp("kimcite",fileName,7)) + { + if ((lmp->citeme) && (availableAsString)) lmp->citeme->add(fileString); + } + } + + KIM_Collections_Destroy(&coll); +} diff --git a/src/KIM/kim_init.h b/src/KIM/kim_init.h new file mode 100644 index 0000000000..2b5dc520c7 --- /dev/null +++ b/src/KIM/kim_init.h @@ -0,0 +1,131 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) + Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.1.0 (and newer) package +------------------------------------------------------------------------- */ + +#ifdef COMMAND_CLASS + +CommandStyle(kim_init,KimInit) + +#else + +#ifndef LMP_KIM_INIT_H +#define LMP_KIM_INIT_H + +#include "pointers.h" +#include + +namespace LAMMPS_NS { + +class KimInit : protected Pointers { + public: + KimInit(class LAMMPS *lmp) : Pointers(lmp) {}; + void command(int, char **); + private: + enum model_type_enum {MO, SM}; + model_type_enum model_type; + bool unit_conversion_mode; + + void determine_model_type_and_units(char *, char *, char **); + void write_log_cite(char *); + void do_init(char *, char *, char *); + void do_variables(char*, char*); + void kim_init_log_delimiter(std::string const begin_end) const; +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal kim_init command + +Incorrect number or kind of arguments to kim_init. + +E: Must use 'kim_init' command before simulation box is defined + +Self-explanatory. + +E: KIM Model does not support the requested unit system + +Self-explanatory. + +E: KIM Model does not support any lammps unit system + +Self-explanatory. + +E: KIM model name not found + +Self-explanatory. + +E: Incompatible KIM Simulator Model + +The requested KIM Simulator Model was defined for a different MD code +and thus is not compatible with LAMMPS. + +E: Incompatible units for KIM Simulator Model + +The selected unit style is not compatible with the requested KIM +Simulator Model. + +E: KIM Simulator Model has no Model definition + +There is no model definition (key: model-defn) in the KIM Simulator +Model. Please contact the OpenKIM database maintainers to verify +and potentially correct this. + +*/ diff --git a/src/KIM/kim_interactions.cpp b/src/KIM/kim_interactions.cpp new file mode 100644 index 0000000000..7dbe523033 --- /dev/null +++ b/src/KIM/kim_interactions.cpp @@ -0,0 +1,387 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) + Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.1.0 (and newer) package +------------------------------------------------------------------------- */ + +#include "kim_interactions.h" +#include +#include +#include +#include "error.h" +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "modify.h" +#include "update.h" +#include "universe.h" +#include "input.h" +#include "variable.h" +#include "fix_store_kim.h" + +extern "C" { +#include "KIM_SimulatorHeaders.h" +} + +#define SNUM(x) \ + static_cast(std::ostringstream() \ + << std::dec << x).str() + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +void KimInteractions::command(int narg, char **arg) +{ + if (narg < 1) error->all(FLERR,"Illegal kim_interactions command"); + + if (!domain->box_exist) + error->all(FLERR,"Must use 'kim_interactions' command after " + "simulation box is defined"); + do_setup(narg,arg); +} + +/* ---------------------------------------------------------------------- */ + +void KimInteractions::kim_interactions_log_delimiter( + std::string const begin_end) const +{ + if (comm->me == 0) { + std::string mesg; + if (begin_end == "begin") + mesg = + "#=== BEGIN kim_interactions ==================================\n"; + else if (begin_end == "end") + mesg = + "#=== END kim_interactions ====================================\n\n"; + + input->write_echo(mesg.c_str()); + } +} + +/* ---------------------------------------------------------------------- */ + +void KimInteractions::do_setup(int narg, char **arg) +{ + bool fixed_types; + if ((narg == 1) && (0 == strcmp("fixed_types",arg[0]))) { + fixed_types = true; + } + else if (narg != atom->ntypes) { + error->all(FLERR,"Illegal kim_interactions command"); + } + else { + fixed_types = false; + } + + char *model_name = NULL; + KIM_SimulatorModel *simulatorModel(NULL); + + // check if we had a kim_init command by finding fix STORE/KIM + // retrieve model name and pointer to simulator model class instance. + // validate model name if not given as NULL. + + int ifix = modify->find_fix("KIM_MODEL_STORE"); + if (ifix >= 0) { + FixStoreKIM *fix_store = (FixStoreKIM *) modify->fix[ifix]; + model_name = (char *)fix_store->getptr("model_name"); + simulatorModel = (KIM_SimulatorModel *)fix_store->getptr("simulator_model"); + } else error->all(FLERR,"Must use 'kim_init' before 'kim_interactions'"); + + // Begin output to log file + kim_interactions_log_delimiter("begin"); + + if (simulatorModel) { + + if (!fixed_types) { + std::string delimiter(""); + std::string atom_type_sym_list; + std::string atom_type_num_list; + + for (int i = 0; i < narg; i++) + { + atom_type_sym_list += delimiter + arg[i]; + atom_type_num_list += delimiter + SNUM(species_to_atomic_no(arg[i])); + delimiter = " "; + } + + KIM_SimulatorModel_AddTemplateMap( + simulatorModel,"atom-type-sym-list",atom_type_sym_list.c_str()); + KIM_SimulatorModel_AddTemplateMap( + simulatorModel,"atom-type-num-list",atom_type_num_list.c_str()); + KIM_SimulatorModel_CloseTemplateMap(simulatorModel); + + int len = strlen(atom_type_sym_list.c_str())+1; + char *strbuf = new char[len]; + char *strword; + + // validate species selection + + int sim_num_species; + bool species_is_supported; + char const *sim_species; + KIM_SimulatorModel_GetNumberOfSupportedSpecies( + simulatorModel,&sim_num_species); + strcpy(strbuf,atom_type_sym_list.c_str()); + strword = strtok(strbuf," \t"); + while (strword) { + species_is_supported = false; + if (strcmp(strword,"NULL") == 0) continue; + for (int i=0; i < sim_num_species; ++i) { + KIM_SimulatorModel_GetSupportedSpecies(simulatorModel,i,&sim_species); + if (strcmp(sim_species,strword) == 0) + species_is_supported = true; + } + if (!species_is_supported) { + std::string msg("Species '"); + msg += strword; + msg += "' is not supported by this KIM Simulator Model"; + error->all(FLERR,msg.c_str()); + } + strword = strtok(NULL," \t"); + } + delete[] strbuf; + } + else + { + KIM_SimulatorModel_CloseTemplateMap(simulatorModel); + } + + // check if units are unchanged + + int sim_fields, sim_lines; + const char *sim_field, *sim_value; + KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields); + for (int i=0; i < sim_fields; ++i) { + KIM_SimulatorModel_GetSimulatorFieldMetadata( + simulatorModel,i,&sim_lines,&sim_field); + + if (0 == strcmp(sim_field,"units")) { + KIM_SimulatorModel_GetSimulatorFieldLine(simulatorModel,i,0,&sim_value); + if (0 != strcmp(sim_value,update->unit_style)) + error->all(FLERR,"Incompatible units for KIM Simulator Model"); + } + } + + int sim_model_idx=-1; + for (int i=0; i < sim_fields; ++i) { + KIM_SimulatorModel_GetSimulatorFieldMetadata( + simulatorModel,i,&sim_lines,&sim_field); + if (0 == strcmp(sim_field,"model-defn")) { + sim_model_idx = i; + for (int j=0; j < sim_lines; ++j) { + KIM_SimulatorModel_GetSimulatorFieldLine( + simulatorModel,sim_model_idx,j,&sim_value); + input->one(sim_value); + } + } + } + + if (sim_model_idx < 0) + error->all(FLERR,"KIM Simulator Model has no Model definition"); + + KIM_SimulatorModel_OpenAndInitializeTemplateMap(simulatorModel); + + } else { + + // not a simulator model. issue pair_style and pair_coeff commands. + + if (fixed_types) + error->all(FLERR,"fixed_types cannot be used with a KIM Portable Model"); + + // NOTE: all references to arg must appear before calls to input->one() + // as that will reset the argument vector. + + std::string cmd1("pair_style kim "); + cmd1 += model_name; + + std::string cmd2("pair_coeff * * "); + for (int i=0; i < narg; ++i) { + cmd2 += arg[i]; + cmd2 += " "; + } + + input->one(cmd1.c_str()); + input->one(cmd2.c_str()); + } + + // End output to log file + kim_interactions_log_delimiter("end"); + +} + +/* ---------------------------------------------------------------------- */ + +int KimInteractions::species_to_atomic_no(std::string const species) const +{ + if (species == "H") return 1; + else if (species == "He") return 2; + else if (species == "Li") return 3; + else if (species == "Be") return 4; + else if (species == "B") return 5; + else if (species == "C") return 6; + else if (species == "N") return 7; + else if (species == "O") return 8; + else if (species == "F") return 9; + else if (species == "Ne") return 10; + else if (species == "Na") return 11; + else if (species == "Mg") return 12; + else if (species == "Al") return 13; + else if (species == "Si") return 14; + else if (species == "P") return 15; + else if (species == "S") return 16; + else if (species == "Cl") return 17; + else if (species == "Ar") return 18; + else if (species == "K") return 19; + else if (species == "Ca") return 20; + else if (species == "Sc") return 21; + else if (species == "Ti") return 22; + else if (species == "V") return 23; + else if (species == "Cr") return 24; + else if (species == "Mn") return 25; + else if (species == "Fe") return 26; + else if (species == "Co") return 27; + else if (species == "Ni") return 28; + else if (species == "Cu") return 29; + else if (species == "Zn") return 30; + else if (species == "Ga") return 31; + else if (species == "Ge") return 32; + else if (species == "As") return 33; + else if (species == "Se") return 34; + else if (species == "Br") return 35; + else if (species == "Kr") return 36; + else if (species == "Rb") return 37; + else if (species == "Sr") return 38; + else if (species == "Y") return 39; + else if (species == "Zr") return 40; + else if (species == "Nb") return 41; + else if (species == "Mo") return 42; + else if (species == "Tc") return 43; + else if (species == "Ru") return 44; + else if (species == "Rh") return 45; + else if (species == "Pd") return 46; + else if (species == "Ag") return 47; + else if (species == "Cd") return 48; + else if (species == "In") return 49; + else if (species == "Sn") return 50; + else if (species == "Sb") return 51; + else if (species == "Te") return 52; + else if (species == "I") return 53; + else if (species == "Xe") return 54; + else if (species == "Cs") return 55; + else if (species == "Ba") return 56; + else if (species == "La") return 57; + else if (species == "Ce") return 58; + else if (species == "Pr") return 59; + else if (species == "Nd") return 60; + else if (species == "Pm") return 61; + else if (species == "Sm") return 62; + else if (species == "Eu") return 63; + else if (species == "Gd") return 64; + else if (species == "Tb") return 65; + else if (species == "Dy") return 66; + else if (species == "Ho") return 67; + else if (species == "Er") return 68; + else if (species == "Tm") return 69; + else if (species == "Yb") return 70; + else if (species == "Lu") return 71; + else if (species == "Hf") return 72; + else if (species == "Ta") return 73; + else if (species == "W") return 74; + else if (species == "Re") return 75; + else if (species == "Os") return 76; + else if (species == "Ir") return 77; + else if (species == "Pt") return 78; + else if (species == "Au") return 79; + else if (species == "Hg") return 80; + else if (species == "Tl") return 81; + else if (species == "Pb") return 82; + else if (species == "Bi") return 83; + else if (species == "Po") return 84; + else if (species == "At") return 85; + else if (species == "Rn") return 86; + else if (species == "Fr") return 87; + else if (species == "Ra") return 88; + else if (species == "Ac") return 89; + else if (species == "Th") return 90; + else if (species == "Pa") return 91; + else if (species == "U") return 92; + else if (species == "Np") return 93; + else if (species == "Pu") return 94; + else if (species == "Am") return 95; + else if (species == "Cm") return 96; + else if (species == "Bk") return 97; + else if (species == "Cf") return 98; + else if (species == "Es") return 99; + else if (species == "Fm") return 100; + else if (species == "Md") return 101; + else if (species == "No") return 102; + else if (species == "Lr") return 103; + else if (species == "Rf") return 104; + else if (species == "Db") return 105; + else if (species == "Sg") return 106; + else if (species == "Bh") return 107; + else if (species == "Hs") return 108; + else if (species == "Mt") return 109; + else if (species == "Ds") return 110; + else if (species == "Rg") return 111; + else if (species == "Cn") return 112; + else if (species == "Nh") return 113; + else if (species == "Fl") return 114; + else if (species == "Mc") return 115; + else if (species == "Lv") return 116; + else if (species == "Ts") return 117; + else if (species == "Og") return 118; + else return -1; +} diff --git a/src/KIM/kim_interactions.h b/src/KIM/kim_interactions.h new file mode 100644 index 0000000000..8172004d53 --- /dev/null +++ b/src/KIM/kim_interactions.h @@ -0,0 +1,117 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Axel Kohlmeyer (Temple U), + Ryan S. Elliott (UMN) + Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.1.0 (and newer) package +------------------------------------------------------------------------- */ + +#ifdef COMMAND_CLASS + +CommandStyle(kim_interactions,KimInteractions) + +#else + +#ifndef LMP_KIM_INTERACTIONS_H +#define LMP_KIM_INTERACTIONS_H + +#include "pointers.h" +#include + +namespace LAMMPS_NS { + +class KimInteractions : protected Pointers { + public: + KimInteractions(class LAMMPS *lmp) : Pointers(lmp) {}; + void command(int, char **); + private: + void do_setup(int, char **); + int species_to_atomic_no(std::string const species) const; + void kim_interactions_log_delimiter(std::string const begin_end) const; +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal kim_interactions command + +Incorrect number or kind of arguments to kim_interactions. + +E: Must use 'kim_interactions' command after simulation box is defined + +Self-explanatory. + +E: Must use 'kim_init' command before 'kim_interactions' + +Self-explanatory. + +E: Species XXX is not supported by this KIM Simulator Model + +The kim_interactions command was referencing a species that is not +present in the requested KIM Simulator Model. + +E: Incompatible units for KIM Simulator Model + +The selected unit style is not compatible with the requested KIM +Simulator Model. + +E: KIM Simulator Model has no Model definition + +There is no model definition (key: model-defn) in the KIM Simulator +Model. Please contact the OpenKIM database maintainers to verify +and potentially correct this. + +*/ diff --git a/src/KIM/kim_query.cpp b/src/KIM/kim_query.cpp index dce9c8761a..cddc81c333 100644 --- a/src/KIM/kim_query.cpp +++ b/src/KIM/kim_query.cpp @@ -11,7 +11,6 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ - /* ---------------------------------------------------------------------- Contributing authors: Axel Kohlmeyer (Temple U), Ryan S. Elliott (UMN) @@ -52,17 +51,20 @@ ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- - Designed for use with the kim-api-2.0.2 (and newer) package + Designed for use with the kim-api-2.1.0 (and newer) package ------------------------------------------------------------------------- */ #include "kim_query.h" #include #include #include +#include #include "comm.h" #include "error.h" #include "input.h" +#include "modify.h" #include "variable.h" +#include "fix_store_kim.h" #if defined(LMP_KIM_CURL) #include @@ -78,7 +80,7 @@ struct WriteBuf { size_t sizeleft; }; -static char *do_query(char *, int, char **, int, MPI_Comm); +static char *do_query(char *, char *, int, char **, int, MPI_Comm); static size_t write_callback(void *, size_t, size_t, void *); #endif @@ -91,31 +93,79 @@ void KimQuery::command(int narg, char **arg) if (narg < 2) error->all(FLERR,"Illegal kim_query command"); + // check if we had a kim_init command by finding fix STORE/KIM + // retrieve model name. + char * model_name; + + int ifix = modify->find_fix("KIM_MODEL_STORE"); + if (ifix >= 0) { + FixStoreKIM *fix_store = (FixStoreKIM *) modify->fix[ifix]; + model_name = (char *)fix_store->getptr("model_name"); + } else error->all(FLERR,"Must use 'kim_init' before 'kim_query'"); + + varname = arg[0]; + bool split = false; + if (0 == strcmp("split",arg[1])) { + if (narg == 2) error->all(FLERR,"Illegal kim_query command"); + split = true; + arg++; + narg--; + } function = arg[1]; + for (int i = 2; i < narg; ++i) + { + if (0 == strncmp("model=",arg[i], 6)) { + error->all(FLERR,"Illegal 'model' key in kim_query command"); + } + } + #if defined(LMP_KIM_CURL) - value = do_query(function, narg-2, arg+2, comm->me, world); + value = do_query(function, model_name, narg-2, arg+2, comm->me, world); // check for valid result // on error the content of "value" is a '\0' byte // as the first element, and then the error message // that was returned by the web server + char errmsg[1024]; if (0 == strlen(value)) { - char errmsg[512]; - sprintf(errmsg,"OpenKIM query failed: %s",value+1); - error->all(FLERR,errmsg); + error->all(FLERR,errmsg); + } else if (0 == strcmp(value,"EMPTY")) { + sprintf(errmsg,"OpenKIM query returned no results"); + error->all(FLERR,errmsg); } + kim_query_log_delimiter("begin"); char **varcmd = new char*[3]; - varcmd[0] = varname; - varcmd[1] = (char *) "string"; - varcmd[2] = value; + if (split) { + int counter = 1; + std::stringstream ss(value); + std::string token; + varcmd[1] = (char *) "string"; - input->variable->set(3,varcmd); + while(std::getline(ss, token, ',')) { + token.erase(0,token.find_first_not_of(" \n\r\t")); // ltrim + token.erase(token.find_last_not_of(" \n\r\t") + 1); // rtrim + std::stringstream splitname; + splitname << varname << "_" << counter++; + varcmd[0] = const_cast(splitname.str().c_str()); + varcmd[2] = const_cast(token.c_str()); + input->variable->set(3,varcmd); + echo_var_assign(splitname.str(), varcmd[2]); + } + } else { + varcmd[0] = varname; + varcmd[1] = (char *) "string"; + varcmd[2] = value; + input->variable->set(3,varcmd); + + echo_var_assign(varname, value); + } + kim_query_log_delimiter("end"); delete[] varcmd; delete[] value; @@ -148,7 +198,8 @@ size_t write_callback(void *data, size_t size, size_t nmemb, void *userp) return 0; // done } -char *do_query(char *qfunction, int narg, char **arg, int rank, MPI_Comm comm) +char *do_query(char *qfunction, char * model_name, int narg, char **arg, + int rank, MPI_Comm comm) { char value[512], *retval; @@ -174,6 +225,9 @@ char *do_query(char *qfunction, int narg, char **arg, int rank, MPI_Comm comm) url += qfunction; std::string query(arg[0]); + query += "&model=[\""; + query += model_name; + query += "\"]"; for (int i=1; i < narg; ++i) { query += '&'; query += arg[i]; @@ -217,9 +271,19 @@ char *do_query(char *qfunction, int narg, char **arg, int rank, MPI_Comm comm) if (value[0] == '[') { int len = strlen(value)-1; - retval = new char[len]; - value[len] = '\0'; - strcpy(retval,value+1); + if (value[len] == ']') { + retval = new char[len]; + value[len] = '\0'; + if (0 == strcmp(value+1, "")) { + strcpy(retval,"EMPTY"); + } + else + strcpy(retval,value+1); + } else { + retval = new char[len+2]; + retval[0] = '\0'; + strcpy(retval+1,value); + } } else if (value[0] == '\0') { int len = strlen(value+1)+2; retval = new char[len]; @@ -227,11 +291,41 @@ char *do_query(char *qfunction, int narg, char **arg, int rank, MPI_Comm comm) strcpy(retval+1,value+1); } else { // unknown response type. we should not get here. - // copy response without modifications. - int len = strlen(value)+1; + // we return an "empty" string but add error message after it + int len = strlen(value)+2; retval = new char[len]; - strcpy(retval,value); + retval[0] = '\0'; + strcpy(retval+1,value); } return retval; } #endif + +/* ---------------------------------------------------------------------- */ + +void KimQuery::kim_query_log_delimiter(std::string const begin_end) const +{ + if (comm->me == 0) { + std::string mesg; + if (begin_end == "begin") + mesg = + "#=== BEGIN kim-query =========================================\n"; + else if (begin_end == "end") + mesg = + "#=== END kim-query ===========================================\n\n"; + + input->write_echo(mesg.c_str()); + } +} + +/* ---------------------------------------------------------------------- */ + +void KimQuery::echo_var_assign(std::string const & name, + std::string const & value) const +{ + if (comm->me == 0) { + std::string mesg; + mesg += "variable " + name + " string " + value + "\n"; + input->write_echo(mesg.c_str()); + } +} diff --git a/src/KIM/kim_query.h b/src/KIM/kim_query.h index 3644e4519b..33a37f5131 100644 --- a/src/KIM/kim_query.h +++ b/src/KIM/kim_query.h @@ -51,7 +51,7 @@ ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- - Designed for use with the kim-api-2.0.2 (and newer) package + Designed for use with the kim-api-2.1.0 (and newer) package ------------------------------------------------------------------------- */ #ifdef COMMAND_CLASS @@ -64,6 +64,7 @@ CommandStyle(kim_query,KimQuery) #define LMP_KIM_QUERY_H #include "pointers.h" +#include namespace LAMMPS_NS { @@ -71,7 +72,10 @@ class KimQuery : protected Pointers { public: KimQuery(class LAMMPS *lmp) : Pointers(lmp) {}; void command(int, char **); - + private: + void kim_query_log_delimiter(std::string const begin_end) const; + void echo_var_assign(std::string const & name, std::string const & value) + const; }; } diff --git a/src/KIM/kim_units.cpp b/src/KIM/kim_units.cpp new file mode 100644 index 0000000000..45f9b81a35 --- /dev/null +++ b/src/KIM/kim_units.cpp @@ -0,0 +1,1411 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +#include +#include +#include +#include +using namespace std; + +namespace +{ + +// Constants of nature and basic conversion factors +// Source: https://physics.nist.gov/cuu/Constants/Table/allascii.txt +// Working with NIST values even when there are newer values for +// compatibility with LAMMPS + +/*---------------------- + Fundamental constants +------------------------ */ +double const boltz_si = 1.38064852e-23; // [J K^-1] Boltzmann's factor + // (NIST value) +double const Nav = 6.022140857e23; // [unitless] Avogadro's number + // (NIST value) +// double const Nav = 6.02214076e23; // [unitless] Avogadro's number + // (official value May 2019) +double const me_si = 9.10938356e-31; // [kg] electron rest mass + // (NIST value) +// double me_si = 9.10938291e-31; // [kg] electron rest mass +double const e_si = 1.6021766208e-19; // [C] elementary charge + // (charge of an electron/proton) + // (NIST value) + +/*---------------------- + Distance units +------------------------ */ +double const bohr_si = 5.2917721067e-11; // [m] Bohr unit (distance between + // nucleus and electron in H) + // (NIST value) +double const angstrom_si = 1e-10; // [m] Angstrom +double const centimeter_si = 1e-2; // [m] centimeter +double const micrometer_si = 1e-6; // [m] micrometer (micron) +double const nanometer_si = 1e-9; // [m] nanometer + +/*---------------------- + Mass units +------------------------ */ +double const gram_per_mole_si = 1e-3/Nav; // [kg] gram per mole +double const amu_si = 1e-3/Nav; // [kg] atomic mass unit (molecular + // weight) For example, the mean + // molecular weight of water + // is 18.015 atomic mass units + // (amu), so one mole of water + // weight 18.015 grams. +double const gram_si = 1e-3; // [kg] gram +double const picogram_si = 1e-15; // [kg] picogram +double const attogram_si = 1e-21; // [kg[ attogram + +/*---------------------- + Time units +------------------------ */ +double const atu_si = 2.418884326509e-17; // [s] atomic time unit + // ( = hbar/E_h where E_h is the + // Hartree energy) (NIST value) +double const atu_electron_si = atu_si*sqrt(amu_si/me_si); + // [s] atomic time unit + // used in electron system (see https://sourceforge.net/p/lammps/mailman/lammps-users/thread/BCA2BDB2-BA03-4280-896F-1E6120EF47B2%40caltech.edu/) +double const microsecond_si = 1e-6; // [s] microsecond +double const nanosecond_si = 1e-9; // [s] nanosecond +double const picosecond_si = 1e-12; // [s] picosecond +double const femtosecond_si = 1e-15; // [s] femtosecond + +/*---------------------- + Density units +------------------------ */ +double const gram_per_centimetercu_si = + gram_si/pow(centimeter_si,3); // [kg/m^3] gram/centimeter^3 +double const amu_per_bohrcu_si = amu_si/pow(bohr_si,3); // [kg/m^3] amu/bohr^3 +double const picogram_per_micrometercu_si = + picogram_si/pow(micrometer_si,3); // [kg/m^3] picogram/micrometer^3 +double const attogram_per_nanometercu_si = + attogram_si/pow(nanometer_si,3); // [kg/m^3] attogram/nanometer^3 + +/*---------------------- + Energy/torque units +------------------------ */ +double const kcal_si = 4184.0; // [J] kilocalorie (heat energy + // involved in warming up one + // kilogram of water by one + // degree Kelvin) +double const ev_si = 1.6021766208e-19; // [J] electon volt (amount of + // energy gained or lost by the + // charge of a single electron + // moving across an electric + // potential difference of one + // volt.) (NIST value) +double const hartree_si = 4.359744650e-18; // [J] Hartree (approximately the + // electric potential energy of + // the hydrogen atom in its + // ground state) (NIST value) +double const kcal_per_mole_si = kcal_si/Nav;// [J] kcal/mole +double const erg_si = 1e-7; // [J] erg +double const dyne_centimeter_si = 1e-7; // [J[ dyne*centimeter +double const picogram_micrometersq_per_microsecondsq_si = + picogram_si*pow(micrometer_si,2)/pow(microsecond_si,2); + // [J] picogram*micrometer^2/ + // microsecond^2 +double const attogram_nanometersq_per_nanosecondsq_si = + attogram_si*pow(nanometer_si,2)/pow(nanosecond_si,2); + // [J] attogram*nanometer^2/ + // nanosecond^2 + +/*---------------------- + Velocity units +------------------------ */ +double const angstrom_per_femtosecond_si = + angstrom_si/femtosecond_si; // [m/s] Angstrom/femtosecond +double const angstrom_per_picosecond_si = + angstrom_si/picosecond_si; // [m/s] Angstrom/picosecond +double const micrometer_per_microsecond_si = + micrometer_si/microsecond_si; // [m/s] micrometer/microsecond +double const nanometer_per_nanosecond_si = + nanometer_si/nanosecond_si; // [m/s] nanometer/nanosecond +double const centimeter_per_second_si = + centimeter_si; // [m/s] centimeter/second +double const bohr_per_atu_electron_si = + bohr_si/atu_electron_si; // [m/s] bohr/atu + +/*---------------------- + Force units +------------------------ */ +double const kcal_per_mole_angstrom_si = + kcal_per_mole_si/angstrom_si; // [N] kcal/(mole*Angstrom) +double const ev_per_angstrom_si = + ev_si/angstrom_si; // [N] eV/Angstrom +double const dyne_si = + dyne_centimeter_si/centimeter_si; // [N] dyne +double const hartree_per_bohr_si = + hartree_si/bohr_si; // [N] hartree/bohr +double const picogram_micrometer_per_microsecondsq_si = + picogram_si*micrometer_si/pow(microsecond_si,2); + // [N] picogram*micrometer/ + // microsecond^2 +double const attogram_nanometer_per_nanosecondsq_si = + attogram_si*nanometer_si/pow(nanosecond_si,2); + // [N] attogram*nanometer/ + // nanosecond^2 + +/*---------------------- + Pressure units +------------------------ */ +double const atmosphere_si = 101325.0; // [Pa] standard atmosphere (NIST value) +double const bar_si = 1e5; // [Pa] bar +double const dyne_per_centimetersq_si = + dyne_centimeter_si/pow(centimeter_si,3); + // [Pa] dyne/centimeter^2 +double const picogram_per_micrometer_microsecondsq_si = + picogram_si/(micrometer_si*pow(microsecond_si,2)); + // [Pa] picogram/(micrometer* + // microsecond^2) +double const attogram_per_nanometer_nanosecondsq_si = + attogram_si/(nanometer_si*pow(nanosecond_si,2)); + // [Pa] attogram/(nanometer*nanosecond^2) + +/*---------------------- + Viscosity units +------------------------ */ +double const poise_si = 0.1; // [Pa*s] Poise +double const amu_per_bohr_femtosecond_si = + amu_si/(bohr_si*femtosecond_si); // [Pa*s] amu/(bohr*femtosecond) +double const picogram_per_micrometer_microsecond_si = + picogram_si/(micrometer_si*microsecond_si); + // [Pa*s] picogram/(micrometer* + // microsecond) +double const attogram_per_nanometer_nanosecond_si = + attogram_si/(nanometer_si*nanosecond_si); + // [Pa*s] attogram/(nanometer* + // nanosecond) + +/*---------------------- + Charge units +------------------------ */ +double const echarge_si = e_si; // [C] electron charge unit +double const statcoulomb_si = e_si/4.8032044e-10; // [C] Statcoulomb or esu + // (value from LAMMPS units + // documentation) +double const picocoulomb_si = 1e-12; // [C] picocoulomb + +/*---------------------- + Dipole units +------------------------ */ +double const electron_angstrom_si = echarge_si*angstrom_si; + // [C*m] electron*angstrom +double const statcoulomb_centimeter_si = statcoulomb_si*centimeter_si; + // [C*m] statcoulomb*centimeter +double const debye_si = 1e-18*statcoulomb_centimeter_si; + // [C*m] Debye +double const picocoulomb_micrometer_si = picocoulomb_si*micrometer_si; + // [C*m] picocoulomb*micrometer +double const electron_nanometer_si = echarge_si*nanometer_si; + // [C*m] electron*nanometer + +/*---------------------- + Electric field units +------------------------ */ +double const volt_per_angstrom_si = 1.0/angstrom_si;// [V/m] volt/angstrom +double const statvolt_per_centimeter_si = + erg_si/(statcoulomb_si*centimeter_si); // [V/m] statvolt/centimeter +double const volt_per_centimeter_si = + 1.0/centimeter_si; // [V/m] volt/centimeter +double const volt_per_micrometer_si = + 1.0/micrometer_si; // [V/m] volt/micrometer +double const volt_per_nanometer_si = + 1.0/nanometer_si; // [V/m] volt/nanometer + +// Define enumerations +enum sys_type +{ + real = 1, + metal = 2, + si = 3, + cgs = 4, + electron = 5, + micro = 6, + nano = 7 +}; + +enum unit_type +{ + mass = 1, + distance = 2, + time = 3, + energy = 4, + velocity = 5, + force = 6, + torque = 7, + temperature = 8, + pressure = 9, + viscosity = 10, + charge = 11, + dipole = 12, + efield = 13, + density = 14 +}; + +enum units +{ + // mass + gram_per_mole = 101, + kilogram = 102, + gram = 103, + amu = 104, + picogram = 105, + attogram = 106, + // distance + angstrom = 201, + meter = 202, + centimeter = 203, + bohr = 204, + micrometer = 205, + nanometer = 206, + // time + femtosecond = 301, + picosecond = 302, + second = 303, + microsecond = 304, + nanosecond = 305, + // energy + kcal_per_mole = 401, + ev = 402, + joule = 403, + erg = 404, + hartree = 405, + picogram_micrometersq_per_microsecondsq = 406, + attogram_nanometersq_per_nanosecondsq = 407, + // velocity + angstrom_per_femtosecond = 501, + angstrom_per_picosecond = 502, + meter_per_second = 503, + centimeter_per_second = 504, + bohr_per_atu = 505, + micrometer_per_microsecond = 506, + nanometer_per_nanosecond = 507, + // force + kcal_per_mole_angstrom = 601, + ev_per_angstrom = 602, + newton = 603, + dyne = 604, + hartree_per_bohr = 605, + picogram_micrometer_per_microsecondsq = 606, + attogram_nanometer_per_nanosecondsq = 607, + // torque + newton_meter = 701, + dyne_centimeter = 702, + // temperature + kelvin = 801, + // pressure + atmosphere = 901, + bar = 902, + pascal = 903, + dyne_per_centimetersq = 904, + picogram_per_micrometer_microsecondsq = 905, + attogram_per_nanometer_nanosecondsq = 906, + // viscosity + poise = 1001, + pascal_second = 1002, + amu_per_bohr_femtosecond = 1003, // electron system, not in docs, GUESSED + picogram_per_micrometer_microsecond = 1004, + attogram_per_nanometer_nanosecond = 1005, + // charge + echarge = 1101, + coulomb = 1102, + statcoulomb = 1103, + picocoulomb = 1104, + // dipole + electron_angstrom = 1201, + coulomb_meter = 1202, + statcoulomb_centimeter = 1203, + debye = 1204, + picocoulomb_micrometer = 1205, + electron_nanometer = 1206, + // electric field + volt_per_angstrom = 1301, + volt_per_meter = 1302, + statvolt_per_centimeter = 1303, + volt_per_centimeter = 1304, + volt_per_micrometer = 1305, + volt_per_nanometer = 1306, + // density + gram_per_centimetercu = 1401, + kilogram_per_metercu = 1402, + amu_per_bohrcu = 1403, // electron system, not in docs, GUESSED + picogram_per_micrometercu = 1404, + attogram_per_nanometercu = 1405 +}; + +// Define dictionaries +map system_dic; +map unit_dic; +map units_real_dic; +map units_metal_dic; +map units_si_dic; +map units_cgs_dic; +map units_electron_dic; +map units_micro_dic; +map units_nano_dic; + +/* ---------------------------------------------------------------------- */ + +void initialize_dictionaries() +{ + system_dic["real"] = real; + system_dic["metal"] = metal; + system_dic["si"] = si; + system_dic["cgs"] = cgs; + system_dic["electron"] = electron; + system_dic["micro"] = micro; + system_dic["nano"] = nano; + + unit_dic["mass"] = mass; + unit_dic["distance"] = distance; + unit_dic["time"] = time; + unit_dic["energy"] = energy; + unit_dic["velocity"] = velocity; + unit_dic["force"] = force; + unit_dic["torque"] = torque; + unit_dic["temperature"]= temperature; + unit_dic["pressure"] = pressure; + unit_dic["viscosity"] = viscosity; + unit_dic["charge"] = charge; + unit_dic["dipole"] = dipole; + unit_dic["efield"] = efield; + unit_dic["density"] = density; + + units_real_dic[mass] = gram_per_mole; + units_real_dic[distance] = angstrom; + units_real_dic[time] = femtosecond; + units_real_dic[energy] = kcal_per_mole; + units_real_dic[velocity] = angstrom_per_femtosecond; + units_real_dic[force] = kcal_per_mole_angstrom; + units_real_dic[torque] = kcal_per_mole; + units_real_dic[temperature]= kelvin; + units_real_dic[pressure] = atmosphere; + units_real_dic[viscosity] = poise; + units_real_dic[charge] = echarge; + units_real_dic[dipole] = electron_angstrom; + units_real_dic[efield] = volt_per_angstrom; + units_real_dic[density] = gram_per_centimetercu; + + units_metal_dic[mass] = gram_per_mole; + units_metal_dic[distance] = angstrom; + units_metal_dic[time] = picosecond; + units_metal_dic[energy] = ev; + units_metal_dic[velocity] = angstrom_per_picosecond; + units_metal_dic[force] = ev_per_angstrom; + units_metal_dic[torque] = ev; + units_metal_dic[temperature]= kelvin; + units_metal_dic[pressure] = bar; + units_metal_dic[viscosity] = poise; + units_metal_dic[charge] = echarge; + units_metal_dic[dipole] = electron_angstrom; + units_metal_dic[efield] = volt_per_angstrom; + units_metal_dic[density] = gram_per_centimetercu; + + units_si_dic[mass] = kilogram; + units_si_dic[distance] = meter; + units_si_dic[time] = second; + units_si_dic[energy] = joule; + units_si_dic[velocity] = meter_per_second; + units_si_dic[force] = newton; + units_si_dic[torque] = newton_meter; + units_si_dic[temperature]= kelvin; + units_si_dic[pressure] = pascal; + units_si_dic[viscosity] = pascal_second; + units_si_dic[charge] = coulomb; + units_si_dic[dipole] = coulomb_meter; + units_si_dic[efield] = volt_per_meter; + units_si_dic[density] = kilogram_per_metercu; + + units_cgs_dic[mass] = gram; + units_cgs_dic[distance] = centimeter; + units_cgs_dic[time] = second; + units_cgs_dic[energy] = erg; + units_cgs_dic[velocity] = centimeter_per_second; + units_cgs_dic[force] = dyne; + units_cgs_dic[torque] = dyne_centimeter; + units_cgs_dic[temperature]= kelvin; + units_cgs_dic[pressure] = dyne_per_centimetersq; + units_cgs_dic[viscosity] = poise; + units_cgs_dic[charge] = statcoulomb; + units_cgs_dic[dipole] = statcoulomb_centimeter; + units_cgs_dic[efield] = statvolt_per_centimeter; + units_cgs_dic[density] = gram_per_centimetercu; + + units_electron_dic[mass] = amu; + units_electron_dic[distance] = bohr; + units_electron_dic[time] = femtosecond; + units_electron_dic[energy] = hartree; + units_electron_dic[velocity] = bohr_per_atu; + units_electron_dic[force] = hartree_per_bohr; + units_electron_dic[torque] = hartree; // unknown, GUESSED + units_electron_dic[temperature]= kelvin; + units_electron_dic[pressure] = pascal; + units_electron_dic[viscosity] = pascal_second; // unknown, GUESSED + units_electron_dic[charge] = echarge; + units_electron_dic[dipole] = debye; + units_electron_dic[efield] = volt_per_centimeter; + units_electron_dic[density] = amu_per_bohrcu; // unknown, GUESSED + + units_micro_dic[mass] = picogram; + units_micro_dic[distance] = micrometer; + units_micro_dic[time] = microsecond; + units_micro_dic[energy] = picogram_micrometersq_per_microsecondsq; + units_micro_dic[velocity] = micrometer_per_microsecond; + units_micro_dic[force] = picogram_micrometer_per_microsecondsq; + units_micro_dic[torque] = picogram_micrometersq_per_microsecondsq; + units_micro_dic[temperature]= kelvin; + units_micro_dic[pressure] = picogram_per_micrometer_microsecondsq; + units_micro_dic[viscosity] = picogram_per_micrometer_microsecond; + units_micro_dic[charge] = picocoulomb; + units_micro_dic[dipole] = picocoulomb_micrometer; + units_micro_dic[efield] = volt_per_micrometer; + units_micro_dic[density] = picogram_per_micrometercu; + + units_nano_dic[mass] = attogram; + units_nano_dic[distance] = nanometer; + units_nano_dic[time] = nanosecond; + units_nano_dic[energy] = attogram_nanometersq_per_nanosecondsq; + units_nano_dic[velocity] = nanometer_per_nanosecond; + units_nano_dic[force] = attogram_nanometer_per_nanosecondsq; + units_nano_dic[torque] = attogram_nanometersq_per_nanosecondsq; + units_nano_dic[temperature]= kelvin; + units_nano_dic[pressure] = attogram_per_nanometer_nanosecondsq; + units_nano_dic[viscosity] = attogram_per_nanometer_nanosecond; + units_nano_dic[charge] = echarge; + units_nano_dic[dipole] = electron_nanometer; + units_nano_dic[efield] = volt_per_nanometer; + units_nano_dic[density] = attogram_per_nanometercu; + +} + +/* ---------------------------------------------------------------------- */ + +// Get the enumeration for the unit of type `unit_type_enum` +// for LAMMPS system `system_enum`. +units get_lammps_system_unit(sys_type system_enum, unit_type unit_type_enum) +{ + switch(system_enum) { + case real : + return units_real_dic[unit_type_enum]; + case metal : + return units_metal_dic[unit_type_enum]; + case si : + return units_si_dic[unit_type_enum]; + case cgs : + return units_cgs_dic[unit_type_enum]; + case electron : + return units_electron_dic[unit_type_enum]; + case micro : + return units_micro_dic[unit_type_enum]; + case nano : + default : // This is here to a prevent a compiler warning + return units_nano_dic[unit_type_enum]; + } +} + +/* ---------------------------------------------------------------------- */ + +// Mass conversion +double get_mass_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kilogram][kilogram] = 1.0; + conv[kilogram][gram_per_mole] = 1.0/gram_per_mole_si; + conv[kilogram][gram] = 1.0/gram_si; + conv[kilogram][amu] = 1.0/amu_si; + conv[kilogram][picogram] = 1.0/picogram_si; + conv[kilogram][attogram] = 1.0/attogram_si; + + to_si = 1.0/conv[kilogram][gram_per_mole]; + conv[gram_per_mole][kilogram] = to_si*conv[kilogram][kilogram]; + conv[gram_per_mole][gram_per_mole] = 1.0; + conv[gram_per_mole][gram] = to_si*conv[kilogram][gram]; + conv[gram_per_mole][amu] = to_si*conv[kilogram][amu]; + conv[gram_per_mole][picogram] = to_si*conv[kilogram][picogram]; + conv[gram_per_mole][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][gram]; + conv[gram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[gram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[gram][gram] = 1.0; + conv[gram][amu] = to_si*conv[kilogram][amu]; + conv[gram][picogram] = to_si*conv[kilogram][picogram]; + conv[gram][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][amu]; + conv[amu][kilogram] = to_si*conv[kilogram][kilogram]; + conv[amu][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[amu][gram] = to_si*conv[kilogram][gram]; + conv[amu][amu] = 1.0; + conv[amu][picogram] = to_si*conv[kilogram][picogram]; + conv[amu][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][picogram]; + conv[picogram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[picogram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[picogram][gram] = to_si*conv[kilogram][gram]; + conv[picogram][amu] = to_si*conv[kilogram][amu]; + conv[picogram][picogram] = 1.0; + conv[picogram][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][attogram]; + conv[attogram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[attogram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[attogram][gram] = to_si*conv[kilogram][gram]; + conv[attogram][amu] = to_si*conv[kilogram][amu]; + conv[attogram][picogram] = to_si*conv[kilogram][picogram]; + conv[attogram][attogram] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Distance conversion +double get_distance_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[meter][meter] = 1.0; + conv[meter][angstrom] = 1.0/angstrom_si; + conv[meter][centimeter] = 1.0/centimeter_si; + conv[meter][bohr] = 1.0/bohr_si; + conv[meter][micrometer] = 1.0/micrometer_si; + conv[meter][nanometer] = 1.0/nanometer_si; + + to_si = 1.0/conv[meter][angstrom]; + conv[angstrom][meter] = to_si*conv[meter][meter]; + conv[angstrom][angstrom] = 1.0; + conv[angstrom][centimeter] = to_si*conv[meter][centimeter]; + conv[angstrom][bohr] = to_si*conv[meter][bohr]; + conv[angstrom][micrometer] = to_si*conv[meter][micrometer]; + conv[angstrom][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][centimeter]; + conv[centimeter][meter] = to_si*conv[meter][meter]; + conv[centimeter][angstrom] = to_si*conv[meter][angstrom]; + conv[centimeter][centimeter] = 1.0; + conv[centimeter][bohr] = to_si*conv[meter][bohr]; + conv[centimeter][micrometer] = to_si*conv[meter][micrometer]; + conv[centimeter][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][bohr]; + conv[bohr][meter] = to_si*conv[meter][meter]; + conv[bohr][angstrom] = to_si*conv[meter][angstrom]; + conv[bohr][centimeter] = to_si*conv[meter][centimeter]; + conv[bohr][bohr] = 1.0; + conv[bohr][micrometer] = to_si*conv[meter][micrometer]; + conv[bohr][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][micrometer]; + conv[micrometer][meter] = to_si*conv[meter][meter]; + conv[micrometer][angstrom] = to_si*conv[meter][angstrom]; + conv[micrometer][centimeter] = to_si*conv[meter][centimeter]; + conv[micrometer][bohr] = to_si*conv[meter][bohr]; + conv[micrometer][micrometer] = 1.0; + conv[micrometer][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][nanometer]; + conv[nanometer][meter] = to_si*conv[meter][meter]; + conv[nanometer][angstrom] = to_si*conv[meter][angstrom]; + conv[nanometer][centimeter] = to_si*conv[meter][centimeter]; + conv[nanometer][bohr] = to_si*conv[meter][bohr]; + conv[nanometer][micrometer] = to_si*conv[meter][micrometer]; + conv[nanometer][nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Time conversion +double get_time_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[second][second] = 1.0; + conv[second][femtosecond] = 1.0/femtosecond_si; + conv[second][picosecond] = 1.0/picosecond_si; + conv[second][microsecond] = 1.0/microsecond_si; + conv[second][nanosecond] = 1.0/nanosecond_si; + + to_si = 1.0/conv[second][femtosecond]; + conv[femtosecond][second] = to_si*conv[second][second]; + conv[femtosecond][femtosecond] = 1.0; + conv[femtosecond][picosecond] = to_si*conv[second][picosecond]; + conv[femtosecond][microsecond] = to_si*conv[second][microsecond]; + conv[femtosecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][picosecond]; + conv[picosecond][second] = to_si*conv[second][second]; + conv[picosecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[picosecond][picosecond] = 1.0; + conv[picosecond][microsecond] = to_si*conv[second][microsecond]; + conv[picosecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][microsecond]; + conv[microsecond][second] = to_si*conv[second][second]; + conv[microsecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[microsecond][picosecond] = to_si*conv[second][picosecond]; + conv[microsecond][microsecond] = 1.0; + conv[microsecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][nanosecond]; + conv[nanosecond][second] = to_si*conv[second][second]; + conv[nanosecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[nanosecond][picosecond] = to_si*conv[second][picosecond]; + conv[nanosecond][microsecond] = to_si*conv[second][microsecond]; + conv[nanosecond][nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Energy conversion +double get_energy_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + + map > conv; + double to_si; + + conv[joule][joule] = 1.0; + conv[joule][kcal_per_mole] = 1.0/kcal_per_mole_si; + conv[joule][ev] = 1.0/ev_si; + conv[joule][erg] = 1.0/erg_si; + conv[joule][hartree] = 1.0/hartree_si; + conv[joule][picogram_micrometersq_per_microsecondsq] = 1.0/picogram_micrometersq_per_microsecondsq_si; + conv[joule][attogram_nanometersq_per_nanosecondsq] = 1.0/attogram_nanometersq_per_nanosecondsq_si; + + to_si = 1.0/conv[joule][kcal_per_mole]; + conv[kcal_per_mole][joule] = to_si*conv[joule][joule]; + conv[kcal_per_mole][kcal_per_mole] = 1.0; + conv[kcal_per_mole][ev] = to_si*conv[joule][ev]; + conv[kcal_per_mole][erg] = to_si*conv[joule][erg]; + conv[kcal_per_mole][hartree] = to_si*conv[joule][hartree]; + conv[kcal_per_mole][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[kcal_per_mole][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][ev]; + conv[ev][joule] = to_si*conv[joule][joule]; + conv[ev][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[ev][ev] = 1.0; + conv[ev][erg] = to_si*conv[joule][erg]; + conv[ev][hartree] = to_si*conv[joule][hartree]; + conv[ev][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[ev][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][erg]; + conv[erg][joule] = to_si*conv[joule][joule]; + conv[erg][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[erg][ev] = to_si*conv[joule][ev]; + conv[erg][erg] = 1.0; + conv[erg][hartree] = to_si*conv[joule][hartree]; + conv[erg][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[erg][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][hartree]; + conv[hartree][joule] = to_si*conv[joule][joule]; + conv[hartree][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[hartree][ev] = to_si*conv[joule][ev]; + conv[hartree][erg] = to_si*conv[joule][erg]; + conv[hartree][hartree] = 1.0; + conv[hartree][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[hartree][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[picogram_micrometersq_per_microsecondsq][joule] = to_si*conv[joule][joule]; + conv[picogram_micrometersq_per_microsecondsq][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[picogram_micrometersq_per_microsecondsq][ev] = to_si*conv[joule][ev]; + conv[picogram_micrometersq_per_microsecondsq][erg] = to_si*conv[joule][erg]; + conv[picogram_micrometersq_per_microsecondsq][hartree] = to_si*conv[joule][hartree]; + conv[picogram_micrometersq_per_microsecondsq][picogram_micrometersq_per_microsecondsq] = 1.0; + conv[picogram_micrometersq_per_microsecondsq][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][attogram_nanometersq_per_nanosecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][joule] = to_si*conv[joule][joule]; + conv[attogram_nanometersq_per_nanosecondsq][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[attogram_nanometersq_per_nanosecondsq][ev] = to_si*conv[joule][ev]; + conv[attogram_nanometersq_per_nanosecondsq][erg] = to_si*conv[joule][erg]; + conv[attogram_nanometersq_per_nanosecondsq][hartree] = to_si*conv[joule][hartree]; + conv[attogram_nanometersq_per_nanosecondsq][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][attogram_nanometersq_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Velocity conversion +double get_velocity_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[meter_per_second][meter_per_second] = 1.0; + conv[meter_per_second][angstrom_per_femtosecond] = 1.0/angstrom_per_femtosecond_si; + conv[meter_per_second][angstrom_per_picosecond] = 1.0/angstrom_per_picosecond_si; + conv[meter_per_second][centimeter_per_second] = 1.0/centimeter_per_second_si; + conv[meter_per_second][bohr_per_atu] = 1.0/bohr_per_atu_electron_si; + conv[meter_per_second][micrometer_per_microsecond] = 1.0/micrometer_per_microsecond_si; + conv[meter_per_second][nanometer_per_nanosecond] = 1.0/nanometer_per_nanosecond_si; + + to_si = 1.0/conv[meter_per_second][angstrom_per_femtosecond]; + conv[angstrom_per_femtosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[angstrom_per_femtosecond][angstrom_per_femtosecond] = 1.0; + conv[angstrom_per_femtosecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[angstrom_per_femtosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[angstrom_per_femtosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[angstrom_per_femtosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[angstrom_per_femtosecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][angstrom_per_picosecond]; + conv[angstrom_per_picosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[angstrom_per_picosecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[angstrom_per_picosecond][angstrom_per_picosecond] = 1.0; + conv[angstrom_per_picosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[angstrom_per_picosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[angstrom_per_picosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[angstrom_per_picosecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][centimeter_per_second]; + conv[centimeter_per_second][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[centimeter_per_second][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[centimeter_per_second][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[centimeter_per_second][centimeter_per_second] = 1.0; + conv[centimeter_per_second][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[centimeter_per_second][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[centimeter_per_second][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][bohr_per_atu]; + conv[bohr_per_atu][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[bohr_per_atu][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[bohr_per_atu][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[bohr_per_atu][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[bohr_per_atu][bohr_per_atu] = 1.0; + conv[bohr_per_atu][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[bohr_per_atu][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][micrometer_per_microsecond]; + conv[micrometer_per_microsecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[micrometer_per_microsecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[micrometer_per_microsecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[micrometer_per_microsecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[micrometer_per_microsecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[micrometer_per_microsecond][micrometer_per_microsecond] = 1.0; + conv[micrometer_per_microsecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][nanometer_per_nanosecond]; + conv[nanometer_per_nanosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[nanometer_per_nanosecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[nanometer_per_nanosecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[nanometer_per_nanosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[nanometer_per_nanosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[nanometer_per_nanosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[nanometer_per_nanosecond][nanometer_per_nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Force conversion +double get_force_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[newton][newton] = 1.0; + conv[newton][kcal_per_mole_angstrom] = 1.0/kcal_per_mole_angstrom_si; + conv[newton][ev_per_angstrom] = 1.0/ev_per_angstrom_si; + conv[newton][dyne] = 1.0/dyne_si; + conv[newton][hartree_per_bohr] = 1.0/hartree_per_bohr_si; + conv[newton][picogram_micrometer_per_microsecondsq] = 1.0/picogram_micrometer_per_microsecondsq_si; + conv[newton][attogram_nanometer_per_nanosecondsq] = 1.0/attogram_nanometer_per_nanosecondsq_si; + + to_si = 1.0/conv[newton][kcal_per_mole_angstrom]; + conv[kcal_per_mole_angstrom][newton] = to_si*conv[newton][newton]; + conv[kcal_per_mole_angstrom][kcal_per_mole_angstrom] = 1.0; + conv[kcal_per_mole_angstrom][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[kcal_per_mole_angstrom][dyne] = to_si*conv[newton][dyne]; + conv[kcal_per_mole_angstrom][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[kcal_per_mole_angstrom][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[kcal_per_mole_angstrom][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][ev_per_angstrom]; + conv[ev_per_angstrom][newton] = to_si*conv[newton][newton]; + conv[ev_per_angstrom][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[ev_per_angstrom][ev_per_angstrom] = 1.0; + conv[ev_per_angstrom][dyne] = to_si*conv[newton][dyne]; + conv[ev_per_angstrom][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[ev_per_angstrom][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[ev_per_angstrom][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][dyne]; + conv[dyne][newton] = to_si*conv[newton][newton]; + conv[dyne][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[dyne][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[dyne][dyne] = 1.0; + conv[dyne][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[dyne][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[dyne][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][hartree_per_bohr]; + conv[hartree_per_bohr][newton] = to_si*conv[newton][newton]; + conv[hartree_per_bohr][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[hartree_per_bohr][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[hartree_per_bohr][dyne] = to_si*conv[newton][dyne]; + conv[hartree_per_bohr][hartree_per_bohr] = 1.0; + conv[hartree_per_bohr][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[hartree_per_bohr][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][picogram_micrometer_per_microsecondsq]; + conv[picogram_micrometer_per_microsecondsq][newton] = to_si*conv[newton][newton]; + conv[picogram_micrometer_per_microsecondsq][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[picogram_micrometer_per_microsecondsq][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[picogram_micrometer_per_microsecondsq][dyne] = to_si*conv[newton][dyne]; + conv[picogram_micrometer_per_microsecondsq][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[picogram_micrometer_per_microsecondsq][picogram_micrometer_per_microsecondsq] = 1.0; + conv[picogram_micrometer_per_microsecondsq][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][attogram_nanometer_per_nanosecondsq]; + conv[attogram_nanometer_per_nanosecondsq][newton] = to_si*conv[newton][newton]; + conv[attogram_nanometer_per_nanosecondsq][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[attogram_nanometer_per_nanosecondsq][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[attogram_nanometer_per_nanosecondsq][dyne] = to_si*conv[newton][dyne]; + conv[attogram_nanometer_per_nanosecondsq][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[attogram_nanometer_per_nanosecondsq][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[attogram_nanometer_per_nanosecondsq][attogram_nanometer_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Torque conversion +double get_torque_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[newton_meter][newton_meter] = 1.0; + conv[newton_meter][kcal_per_mole] = 1.0/kcal_per_mole_si; + conv[newton_meter][ev] = 1.0/ev_si; + conv[newton_meter][dyne_centimeter] = 1.0/dyne_centimeter_si; + conv[newton_meter][hartree] = 1.0/hartree_si; + conv[newton_meter][picogram_micrometersq_per_microsecondsq] = 1.0/picogram_micrometersq_per_microsecondsq_si; + conv[newton_meter][attogram_nanometersq_per_nanosecondsq] = 1.0/attogram_nanometersq_per_nanosecondsq_si; + + to_si = 1.0/conv[newton_meter][kcal_per_mole]; + conv[kcal_per_mole][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[kcal_per_mole][kcal_per_mole] = 1.0; + conv[kcal_per_mole][ev] = to_si*conv[newton_meter][ev]; + conv[kcal_per_mole][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[kcal_per_mole][hartree] = to_si*conv[newton_meter][hartree]; + conv[kcal_per_mole][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[kcal_per_mole][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][ev]; + conv[ev][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[ev][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[ev][ev] = 1.0; + conv[ev][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[ev][hartree] = to_si*conv[newton_meter][hartree]; + conv[ev][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[ev][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][dyne_centimeter]; + conv[dyne_centimeter][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[dyne_centimeter][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[dyne_centimeter][ev] = to_si*conv[newton_meter][ev]; + conv[dyne_centimeter][dyne_centimeter] = 1.0; + conv[dyne_centimeter][hartree] = to_si*conv[newton_meter][hartree]; + conv[dyne_centimeter][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[dyne_centimeter][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][hartree]; + conv[hartree][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[hartree][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[hartree][ev] = to_si*conv[newton_meter][ev]; + conv[hartree][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[hartree][hartree] = 1.0; + conv[hartree][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[hartree][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[picogram_micrometersq_per_microsecondsq][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[picogram_micrometersq_per_microsecondsq][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[picogram_micrometersq_per_microsecondsq][ev] = to_si*conv[newton_meter][ev]; + conv[picogram_micrometersq_per_microsecondsq][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[picogram_micrometersq_per_microsecondsq][hartree] = to_si*conv[newton_meter][hartree]; + conv[picogram_micrometersq_per_microsecondsq][picogram_micrometersq_per_microsecondsq] = 1.0; + conv[picogram_micrometersq_per_microsecondsq][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[attogram_nanometersq_per_nanosecondsq][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[attogram_nanometersq_per_nanosecondsq][ev] = to_si*conv[newton_meter][ev]; + conv[attogram_nanometersq_per_nanosecondsq][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[attogram_nanometersq_per_nanosecondsq][hartree] = to_si*conv[newton_meter][hartree]; + conv[attogram_nanometersq_per_nanosecondsq][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][attogram_nanometersq_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Temperature conversion +double get_temperature_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kelvin][kelvin] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Pressure conversion +double get_pressure_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[pascal][pascal] = 1.0; + conv[pascal][atmosphere] = 1.0/atmosphere_si; + conv[pascal][bar] = 1.0/bar_si; + conv[pascal][dyne_per_centimetersq] = 1.0/dyne_per_centimetersq_si; + conv[pascal][picogram_per_micrometer_microsecondsq] = 1.0/picogram_per_micrometer_microsecondsq_si; + conv[pascal][attogram_per_nanometer_nanosecondsq] = 1.0/attogram_per_nanometer_nanosecondsq_si; + + to_si = 1.0/conv[pascal][atmosphere]; + conv[atmosphere][pascal] = to_si*conv[pascal][pascal]; + conv[atmosphere][atmosphere] = 1.0; + conv[atmosphere][bar] = to_si*conv[pascal][bar]; + conv[atmosphere][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[atmosphere][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[atmosphere][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][bar]; + conv[bar][pascal] = to_si*conv[pascal][pascal]; + conv[bar][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[bar][bar] = 1.0; + conv[bar][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[bar][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[bar][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][dyne_per_centimetersq]; + conv[dyne_per_centimetersq][pascal] = to_si*conv[pascal][pascal]; + conv[dyne_per_centimetersq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[dyne_per_centimetersq][bar] = to_si*conv[pascal][bar]; + conv[dyne_per_centimetersq][dyne_per_centimetersq] = 1.0; + conv[dyne_per_centimetersq][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[dyne_per_centimetersq][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[picogram_per_micrometer_microsecondsq][pascal] = to_si*conv[pascal][pascal]; + conv[picogram_per_micrometer_microsecondsq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[picogram_per_micrometer_microsecondsq][bar] = to_si*conv[pascal][bar]; + conv[picogram_per_micrometer_microsecondsq][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[picogram_per_micrometer_microsecondsq][picogram_per_micrometer_microsecondsq] = 1.0; + conv[picogram_per_micrometer_microsecondsq][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][attogram_per_nanometer_nanosecondsq]; + conv[attogram_per_nanometer_nanosecondsq][pascal] = to_si*conv[pascal][pascal]; + conv[attogram_per_nanometer_nanosecondsq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[attogram_per_nanometer_nanosecondsq][bar] = to_si*conv[pascal][bar]; + conv[attogram_per_nanometer_nanosecondsq][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[attogram_per_nanometer_nanosecondsq][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[attogram_per_nanometer_nanosecondsq][attogram_per_nanometer_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Viscosity conversion +double get_viscosity_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[pascal_second][pascal_second] = 1.0; + conv[pascal_second][poise] = 1.0/poise_si; + conv[pascal_second][amu_per_bohr_femtosecond] = 1.0/amu_per_bohr_femtosecond_si; + conv[pascal_second][picogram_per_micrometer_microsecond] = 1.0/picogram_per_micrometer_microsecond_si; + conv[pascal_second][attogram_per_nanometer_nanosecond] = 1.0/attogram_per_nanometer_nanosecond_si; + + to_si = 1.0/conv[pascal_second][poise]; + conv[poise][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[poise][poise] = 1.0; + conv[poise][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[poise][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[poise][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][amu_per_bohr_femtosecond]; + conv[amu_per_bohr_femtosecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[amu_per_bohr_femtosecond][poise] = to_si*conv[pascal_second][poise]; + conv[amu_per_bohr_femtosecond][amu_per_bohr_femtosecond] = 1.0; + conv[amu_per_bohr_femtosecond][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[amu_per_bohr_femtosecond][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[picogram_per_micrometer_microsecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[picogram_per_micrometer_microsecond][poise] = to_si*conv[pascal_second][poise]; + conv[picogram_per_micrometer_microsecond][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[picogram_per_micrometer_microsecond][picogram_per_micrometer_microsecond] = 1.0; + conv[picogram_per_micrometer_microsecond][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][attogram_per_nanometer_nanosecond]; + conv[attogram_per_nanometer_nanosecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[attogram_per_nanometer_nanosecond][poise] = to_si*conv[pascal_second][poise]; + conv[attogram_per_nanometer_nanosecond][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[attogram_per_nanometer_nanosecond][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[attogram_per_nanometer_nanosecond][attogram_per_nanometer_nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Charge conversion +double get_charge_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[coulomb][coulomb] = 1.0; + conv[coulomb][echarge] = 1.0/echarge_si; + conv[coulomb][statcoulomb] = 1.0/statcoulomb_si; + conv[coulomb][picocoulomb] = 1.0/picocoulomb_si; + + to_si = 1.0/conv[coulomb][echarge]; + conv[echarge][coulomb] = to_si*conv[coulomb][coulomb]; + conv[echarge][echarge] = 1.0; + conv[echarge][statcoulomb] = to_si*conv[coulomb][statcoulomb]; + conv[echarge][picocoulomb] = to_si*conv[coulomb][picocoulomb]; + + to_si = 1.0/conv[coulomb][statcoulomb]; + conv[statcoulomb][coulomb] = to_si*conv[coulomb][coulomb]; + conv[statcoulomb][echarge] = to_si*conv[coulomb][echarge]; + conv[statcoulomb][statcoulomb] = 1.0; + conv[statcoulomb][picocoulomb] = to_si*conv[coulomb][picocoulomb]; + + to_si = 1.0/conv[coulomb][picocoulomb]; + conv[picocoulomb][coulomb] = to_si*conv[coulomb][coulomb]; + conv[picocoulomb][echarge] = to_si*conv[coulomb][echarge]; + conv[picocoulomb][statcoulomb] = to_si*conv[coulomb][statcoulomb]; + conv[picocoulomb][picocoulomb] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Dipole conversion +double get_dipole_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[coulomb_meter][coulomb_meter] = 1.0; + conv[coulomb_meter][electron_angstrom] = 1.0/electron_angstrom_si; + conv[coulomb_meter][statcoulomb_centimeter] = 1.0/statcoulomb_centimeter_si; + conv[coulomb_meter][debye] = 1.0/debye_si; + conv[coulomb_meter][picocoulomb_micrometer] = 1.0/picocoulomb_micrometer_si; + conv[coulomb_meter][electron_nanometer] = 1.0/electron_nanometer_si; + + to_si = 1.0/conv[coulomb_meter][electron_angstrom]; + conv[electron_angstrom][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[electron_angstrom][electron_angstrom] = 1.0; + conv[electron_angstrom][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[electron_angstrom][debye] = to_si*conv[coulomb_meter][debye]; + conv[electron_angstrom][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[electron_angstrom][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][statcoulomb_centimeter]; + conv[statcoulomb_centimeter][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[statcoulomb_centimeter][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[statcoulomb_centimeter][statcoulomb_centimeter] = 1.0; + conv[statcoulomb_centimeter][debye] = to_si*conv[coulomb_meter][debye]; + conv[statcoulomb_centimeter][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[statcoulomb_centimeter][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][debye]; + conv[debye][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[debye][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[debye][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[debye][debye] = 1.0; + conv[debye][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[debye][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][picocoulomb_micrometer]; + conv[picocoulomb_micrometer][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[picocoulomb_micrometer][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[picocoulomb_micrometer][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[picocoulomb_micrometer][debye] = to_si*conv[coulomb_meter][debye]; + conv[picocoulomb_micrometer][picocoulomb_micrometer] = 1.0; + conv[picocoulomb_micrometer][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][electron_nanometer]; + conv[electron_nanometer][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[electron_nanometer][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[electron_nanometer][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[electron_nanometer][debye] = to_si*conv[coulomb_meter][debye]; + conv[electron_nanometer][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[electron_nanometer][electron_nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Electric field conversion +double get_efield_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[volt_per_meter][volt_per_meter] = 1.0; + conv[volt_per_meter][volt_per_angstrom] = 1.0/volt_per_angstrom_si; + conv[volt_per_meter][statvolt_per_centimeter] = 1.0/statvolt_per_centimeter_si; + conv[volt_per_meter][volt_per_centimeter] = 1.0/volt_per_centimeter_si; + conv[volt_per_meter][volt_per_micrometer] = 1.0/volt_per_micrometer_si; + conv[volt_per_meter][volt_per_nanometer] = 1.0/volt_per_nanometer_si; + + to_si = 1.0/conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_angstrom][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_angstrom][volt_per_angstrom] = 1.0; + conv[volt_per_angstrom][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_angstrom][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_angstrom][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_angstrom][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][statvolt_per_centimeter]; + conv[statvolt_per_centimeter][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[statvolt_per_centimeter][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[statvolt_per_centimeter][statvolt_per_centimeter] = 1.0; + conv[statvolt_per_centimeter][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[statvolt_per_centimeter][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[statvolt_per_centimeter][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_centimeter][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_centimeter][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_centimeter][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_centimeter][volt_per_centimeter] = 1.0; + conv[volt_per_centimeter][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_centimeter][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_micrometer][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_micrometer][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_micrometer][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_micrometer][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_micrometer][volt_per_micrometer] = 1.0; + conv[volt_per_micrometer][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_nanometer]; + conv[volt_per_nanometer][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_nanometer][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_nanometer][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_nanometer][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_nanometer][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_nanometer][volt_per_nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Demsity conversion +double get_density_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kilogram_per_metercu][kilogram_per_metercu] = 1.0; + conv[kilogram_per_metercu][gram_per_centimetercu] = 1.0/gram_per_centimetercu_si; + conv[kilogram_per_metercu][amu_per_bohrcu] = 1.0/amu_per_bohrcu_si; + conv[kilogram_per_metercu][picogram_per_micrometercu] = 1.0/picogram_per_micrometercu_si; + conv[kilogram_per_metercu][attogram_per_nanometercu] = 1.0/attogram_per_nanometercu_si; + + to_si = 1.0/conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[gram_per_centimetercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[gram_per_centimetercu][gram_per_centimetercu] = 1.0; + conv[gram_per_centimetercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[gram_per_centimetercu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[gram_per_centimetercu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[amu_per_bohrcu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[amu_per_bohrcu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[amu_per_bohrcu][amu_per_bohrcu] = 1.0; + conv[amu_per_bohrcu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[amu_per_bohrcu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[picogram_per_micrometercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[picogram_per_micrometercu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[picogram_per_micrometercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[picogram_per_micrometercu][picogram_per_micrometercu] = 1.0; + conv[picogram_per_micrometercu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][attogram_per_nanometercu]; + conv[attogram_per_nanometercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[attogram_per_nanometercu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[attogram_per_nanometercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[attogram_per_nanometercu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[attogram_per_nanometercu][attogram_per_nanometercu] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// This routine returns the unit conversion factor between the +// `from_system_enum` to the `to_system_enum` for the `unit_type_enum`. +double get_unit_conversion_factor(unit_type &unit_type_enum, + sys_type from_system_enum, + sys_type to_system_enum) +{ + units from_unit = get_lammps_system_unit(from_system_enum, unit_type_enum); + units to_unit = get_lammps_system_unit(to_system_enum, unit_type_enum); + switch(unit_type_enum) { + case mass : + return get_mass_conversion_factor(from_unit, to_unit); + case distance : + return get_distance_conversion_factor(from_unit, to_unit); + case time : + return get_time_conversion_factor(from_unit, to_unit); + case energy : + return get_energy_conversion_factor(from_unit, to_unit); + case velocity : + return get_velocity_conversion_factor(from_unit, to_unit); + case force : + return get_force_conversion_factor(from_unit, to_unit); + case torque : + return get_torque_conversion_factor(from_unit, to_unit); + case temperature : + return get_temperature_conversion_factor(from_unit, to_unit); + case pressure : + return get_pressure_conversion_factor(from_unit, to_unit); + case viscosity : + return get_viscosity_conversion_factor(from_unit, to_unit); + case charge : + return get_charge_conversion_factor(from_unit, to_unit); + case dipole : + return get_dipole_conversion_factor(from_unit, to_unit); + case efield : + return get_efield_conversion_factor(from_unit, to_unit); + case density : + default : // This is here to a prevent a compiler warning + return get_density_conversion_factor(from_unit, to_unit); + } +} + +} // end of anonymous name space + +/* ---------------------------------------------------------------------- */ + +// Wrapper to the routine that gets the unit conversion. Translates strings +// to enumerations and then call get_unit_conversion_factor() +int lammps_unit_conversion(string const &unit_type_str, + string const &from_system_str, + string const &to_system_str, + double &conversion_factor) +{ + // initialize + conversion_factor = 0.0; + initialize_dictionaries(); + + // convert input to enumeration + unit_type unit_type_enum; + { + map::const_iterator itr = unit_dic.find(unit_type_str); + if (itr != unit_dic.end()) unit_type_enum = itr->second; + else return 1; // error + } + sys_type from_system_enum; + { + map::const_iterator + itr = system_dic.find(from_system_str); + if (itr != system_dic.end()) from_system_enum = itr->second; + else return 1; // error + } + sys_type to_system_enum; + { + map::const_iterator + itr = system_dic.find(to_system_str); + if (itr != system_dic.end()) to_system_enum = itr->second; + else return 1; + } + + // process unit conversions + conversion_factor = get_unit_conversion_factor(unit_type_enum, + from_system_enum, + to_system_enum); + return 0; +} + + diff --git a/src/KIM/kim_units.h b/src/KIM/kim_units.h new file mode 100644 index 0000000000..97e81a6222 --- /dev/null +++ b/src/KIM/kim_units.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +int lammps_unit_conversion(std::string const &unit_type_str, + std::string const &from_system_str, + std::string const &to_system_str, + double &conversion_factor); diff --git a/src/KIM/pair_kim.cpp b/src/KIM/pair_kim.cpp index e107e4276f..d935d994bd 100644 --- a/src/KIM/pair_kim.cpp +++ b/src/KIM/pair_kim.cpp @@ -13,6 +13,7 @@ /* ---------------------------------------------------------------------- Contributing authors: Ryan S. Elliott (UMinn) + Axel Kohlmeyer (Temple U) ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- @@ -52,10 +53,10 @@ /* ---------------------------------------------------------------------- Designed for use with the kim-api-2.0.2 (and newer) package ------------------------------------------------------------------------- */ - #include "pair_kim.h" #include #include +#include #include "atom.h" #include "comm.h" #include "force.h" @@ -72,200 +73,184 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ PairKIM::PairKIM(LAMMPS *lmp) : - Pair(lmp), - settings_call_count(0), - init_style_call_count(0), - kim_modelname(NULL), - lmps_map_species_to_unique(NULL), - lmps_unique_elements(NULL), - lmps_num_unique_elements(0), - lmps_units(METAL), - lengthUnit(KIM_LENGTH_UNIT_unused), - energyUnit(KIM_ENERGY_UNIT_unused), - chargeUnit(KIM_CHARGE_UNIT_unused), - temperatureUnit(KIM_TEMPERATURE_UNIT_unused), - timeUnit(KIM_TIME_UNIT_unused), - pkim(NULL), - pargs(NULL), - kim_model_support_for_energy(KIM_SUPPORT_STATUS_notSupported), - kim_model_support_for_forces(KIM_SUPPORT_STATUS_notSupported), - kim_model_support_for_particleEnergy(KIM_SUPPORT_STATUS_notSupported), - kim_model_support_for_particleVirial(KIM_SUPPORT_STATUS_notSupported), - lmps_local_tot_num_atoms(0), - kim_global_influence_distance(0.0), - kim_number_of_neighbor_lists(0), - kim_cutoff_values(NULL), - modelWillNotRequestNeighborsOfNoncontributingParticles(NULL), - neighborLists(NULL), - kim_particle_codes(NULL), - lmps_maxalloc(0), - kim_particleSpecies(NULL), - kim_particleContributing(NULL), - lmps_stripped_neigh_list(NULL), - lmps_stripped_neigh_ptr(NULL) + Pair(lmp), + settings_call_count(0), + init_style_call_count(0), + kim_modelname(NULL), + lmps_map_species_to_unique(NULL), + lmps_unique_elements(NULL), + lmps_num_unique_elements(0), + lmps_units(METAL), + lengthUnit(KIM_LENGTH_UNIT_unused), + energyUnit(KIM_ENERGY_UNIT_unused), + chargeUnit(KIM_CHARGE_UNIT_unused), + temperatureUnit(KIM_TEMPERATURE_UNIT_unused), + timeUnit(KIM_TIME_UNIT_unused), + pkim(NULL), + pargs(NULL), + kim_model_support_for_energy(KIM_SUPPORT_STATUS_notSupported), + kim_model_support_for_forces(KIM_SUPPORT_STATUS_notSupported), + kim_model_support_for_particleEnergy(KIM_SUPPORT_STATUS_notSupported), + kim_model_support_for_particleVirial(KIM_SUPPORT_STATUS_notSupported), + lmps_local_tot_num_atoms(0), + kim_global_influence_distance(0.0), + kim_number_of_neighbor_lists(0), + kim_cutoff_values(NULL), + modelWillNotRequestNeighborsOfNoncontributingParticles(NULL), + neighborLists(NULL), + kim_particle_codes(NULL), + lmps_maxalloc(0), + kim_particleSpecies(NULL), + kim_particleContributing(NULL), + lmps_stripped_neigh_list(NULL), + lmps_stripped_neigh_ptr(NULL) { - // Initialize Pair data members to appropriate values - single_enable = 0; // We do not provide the Single() function - restartinfo = 0; // We do not write any restart info - one_coeff = 1; // We only allow one coeff * * call - // set to 1, regardless use of fdotr, to avoid ev_set()'s futzing with - // vflag_global - no_virial_fdotr_compute = 1; + // Initialize Pair data members to appropriate values + single_enable = 0; // We do not provide the Single() function + restartinfo = 0; // We do not write any restart info + one_coeff = 1; // We only allow one coeff * * call + // set to 1, regardless use of fdotr, to avoid ev_set()'s futzing with + // vflag_global + no_virial_fdotr_compute = 1; - // BEGIN: initial values that determine the KIM state - // (used by kim_free(), etc.) - kim_init_ok = false; - kim_particle_codes_ok = false; - // END - - return; + // BEGIN: initial values that determine the KIM state + // (used by kim_free(), etc.) + kim_init_ok = false; + kim_particle_codes_ok = false; + // END } /* ---------------------------------------------------------------------- */ PairKIM::~PairKIM() { - // clean up kim_modelname - if (kim_modelname != 0) delete [] kim_modelname; + // clean up kim_modelname + if (kim_modelname != 0) delete [] kim_modelname; - // clean up lammps atom species number to unique particle names mapping - if (lmps_unique_elements) - for (int i = 0; i < lmps_num_unique_elements; i++) - delete [] lmps_unique_elements[i]; - delete [] lmps_unique_elements; + // clean up lammps atom species number to unique particle names mapping + if (lmps_unique_elements) + for (int i = 0; i < lmps_num_unique_elements; i++) + delete [] lmps_unique_elements[i]; + delete [] lmps_unique_elements; - if (kim_particle_codes_ok) - { - delete [] kim_particle_codes; - kim_particle_codes = NULL; - kim_particle_codes_ok = false; - } + if (kim_particle_codes_ok) { + delete [] kim_particle_codes; + kim_particle_codes = NULL; + kim_particle_codes_ok = false; + } - // clean up local memory used to support KIM interface - memory->destroy(kim_particleSpecies); - memory->destroy(kim_particleContributing); - memory->destroy(lmps_stripped_neigh_list); - // clean up lmps_stripped_neigh_ptr - if (lmps_stripped_neigh_ptr) - { - delete [] lmps_stripped_neigh_ptr; - lmps_stripped_neigh_ptr = 0; - } + // clean up local memory used to support KIM interface + memory->destroy(kim_particleSpecies); + memory->destroy(kim_particleContributing); + memory->destroy(lmps_stripped_neigh_list); + // clean up lmps_stripped_neigh_ptr + if (lmps_stripped_neigh_ptr) { + delete [] lmps_stripped_neigh_ptr; + lmps_stripped_neigh_ptr = 0; + } - // clean up allocated memory for standard Pair class usage - // also, we allocate lmps_map_species_to_uniuqe in the allocate() function - if (allocated) { - memory->destroy(setflag); - memory->destroy(cutsq); - delete [] lmps_map_species_to_unique; - } + // clean up allocated memory for standard Pair class usage + // also, we allocate lmps_map_species_to_uniuqe in the allocate() function + if (allocated) { + memory->destroy(setflag); + memory->destroy(cutsq); + delete [] lmps_map_species_to_unique; + } - // clean up neighborlist pointers - if (neighborLists) - { - delete [] neighborLists; - neighborLists = 0; - } + // clean up neighborlist pointers + if (neighborLists) { + delete [] neighborLists; + neighborLists = 0; + } - // clean up KIM interface (if necessary) - kim_free(); - - return; + // clean up KIM interface (if necessary) + kim_free(); } /* ---------------------------------------------------------------------- */ + void PairKIM::set_contributing() { int const nall = atom->nlocal + atom->nghost; for (int i = 0; i < nall; ++i) - { kim_particleContributing[i] = ( (i < atom->nlocal) ? 1 : 0 ); - } } /* ---------------------------------------------------------------------- */ -void PairKIM::compute(int eflag , int vflag) +void PairKIM::compute(int eflag, int vflag) { - ev_init(eflag,vflag); + ev_init(eflag,vflag); - // grow kim_particleSpecies and kim_particleContributing array if necessary - // needs to be atom->nmax in length - if (atom->nmax > lmps_maxalloc) { - memory->destroy(kim_particleSpecies); - memory->destroy(kim_particleContributing); + // grow kim_particleSpecies and kim_particleContributing array if necessary + // needs to be atom->nmax in length + if (atom->nmax > lmps_maxalloc) { + memory->destroy(kim_particleSpecies); + memory->destroy(kim_particleContributing); - lmps_maxalloc = atom->nmax; - memory->create(kim_particleSpecies,lmps_maxalloc, - "pair:kim_particleSpecies"); - int kimerror = KIM_ComputeArguments_SetArgumentPointerInteger(pargs, - KIM_COMPUTE_ARGUMENT_NAME_particleSpeciesCodes, - kim_particleSpecies); - memory->create(kim_particleContributing,lmps_maxalloc, - "pair:kim_particleContributing"); - kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerInteger( - pargs, - KIM_COMPUTE_ARGUMENT_NAME_particleContributing, - kim_particleContributing); - if (kimerror) - error->all( - FLERR, - "Unable to set KIM particle species codes and/or contributing"); - } + lmps_maxalloc = atom->nmax; + memory->create(kim_particleSpecies,lmps_maxalloc, + "pair:kim_particleSpecies"); + int kimerror = KIM_ComputeArguments_SetArgumentPointerInteger(pargs, + KIM_COMPUTE_ARGUMENT_NAME_particleSpeciesCodes, + kim_particleSpecies); + memory->create(kim_particleContributing,lmps_maxalloc, + "pair:kim_particleContributing"); + kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerInteger( + pargs, + KIM_COMPUTE_ARGUMENT_NAME_particleContributing, + kim_particleContributing); + if (kimerror) + error->all(FLERR, + "Unable to set KIM particle species codes and/or contributing"); + } - // kim_particleSpecies = KIM atom species for each LAMMPS atom + // kim_particleSpecies = KIM atom species for each LAMMPS atom - int *species = atom->type; - int nall = atom->nlocal + atom->nghost; - int ielement; + int *species = atom->type; + int nall = atom->nlocal + atom->nghost; + int ielement; - for (int i = 0; i < nall; i++) { - ielement = lmps_map_species_to_unique[species[i]]; - kim_particleSpecies[i] = kim_particle_codes[ielement]; - } + for (int i = 0; i < nall; i++) { + ielement = lmps_map_species_to_unique[species[i]]; + kim_particleSpecies[i] = kim_particle_codes[ielement]; + } - // Set kim contributing flags - set_contributing(); + // Set kim contributing flags + set_contributing(); - // pass current atom pointers to KIM - set_argument_pointers(); + // pass current atom pointers to KIM + set_argument_pointers(); - // set number of particles - lmps_local_tot_num_atoms = (int) nall; + // set number of particles + lmps_local_tot_num_atoms = (int) nall; - // compute via KIM model - int kimerror = KIM_Model_Compute(pkim, pargs); - if (kimerror) error->all(FLERR,"KIM Compute returned error"); + // compute via KIM model + int kimerror = KIM_Model_Compute(pkim, pargs); + if (kimerror) error->all(FLERR,"KIM Compute returned error"); - // compute virial before reverse comm! - if (vflag_global) - { - virial_fdotr_compute(); - } + // compute virial before reverse comm! + if (vflag_global) + virial_fdotr_compute(); - // if newton is off, perform reverse comm - if (!lmps_using_newton) - { - comm->reverse_comm_pair(this); - } + // if newton is off, perform reverse comm + if (!lmps_using_newton) { + comm->reverse_comm_pair(this); + } - if ((vflag_atom) && - KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported) - ) - { // flip sign and order of virial if KIM is computing it - double tmp; - for (int i = 0; i < nall; ++i) - { - for (int j = 0; j < 3; ++j) vatom[i][j] = -1.0*vatom[i][j]; - tmp = vatom[i][3]; - vatom[i][3] = -vatom[i][5]; - vatom[i][4] = -vatom[i][4]; - vatom[i][5] = -tmp; - } - } - - return; + if ((vflag_atom) && + KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { + // flip sign and order of virial if KIM is computing it + double tmp; + for (int i = 0; i < nall; ++i) { + for (int j = 0; j < 3; ++j) vatom[i][j] = -1.0*vatom[i][j]; + tmp = vatom[i][3]; + vatom[i][3] = -vatom[i][5]; + vatom[i][4] = -vatom[i][4]; + vatom[i][5] = -tmp; + } + } } /* ---------------------------------------------------------------------- @@ -274,22 +259,20 @@ void PairKIM::compute(int eflag , int vflag) void PairKIM::allocate() { - int n = atom->ntypes; + int n = atom->ntypes; - // allocate standard Pair class arrays - memory->create(setflag,n+1,n+1,"pair:setflag"); - for (int i = 1; i <= n; i++) - for (int j = i; j <= n; j++) - setflag[i][j] = 0; + // allocate standard Pair class arrays + memory->create(setflag,n+1,n+1,"pair:setflag"); + for (int i = 1; i <= n; i++) + for (int j = i; j <= n; j++) + setflag[i][j] = 0; - memory->create(cutsq,n+1,n+1,"pair:cutsq"); + memory->create(cutsq,n+1,n+1,"pair:cutsq"); - // allocate mapping array - lmps_map_species_to_unique = new int[n+1]; + // allocate mapping array + lmps_map_species_to_unique = new int[n+1]; - allocated = 1; - - return; + allocated = 1; } /* ---------------------------------------------------------------------- @@ -298,56 +281,49 @@ void PairKIM::allocate() void PairKIM::settings(int narg, char **arg) { - // This is called when "pair_style kim ..." is read from input - // may be called multiple times - ++settings_call_count; - init_style_call_count = 0; + // This is called when "pair_style kim ..." is read from input + // may be called multiple times + ++settings_call_count; + init_style_call_count = 0; - if (narg != 1) - { - if ((narg > 0) && ((0 == strcmp("KIMvirial", arg[0])) || - (0 == strcmp("LAMMPSvirial", arg[0])))) - { - error->all(FLERR,"'KIMvirial' or 'LAMMPSvirial' not supported with " - "kim-api."); - } - else - error->all(FLERR,"Illegal pair_style command"); - } - // arg[0] is the KIM Model name + if (narg != 1) { + if ((narg > 0) && ((0 == strcmp("KIMvirial", arg[0])) || + (0 == strcmp("LAMMPSvirial", arg[0])))) { + error->all(FLERR,"'KIMvirial' or 'LAMMPSvirial' not supported with " + "kim-api."); + } else error->all(FLERR,"Illegal pair_style command"); + } + // arg[0] is the KIM Model name - lmps_using_molecular = (atom->molecular > 0); + lmps_using_molecular = (atom->molecular > 0); - // ensure we are in a clean state for KIM (needed on repeated call) - // first time called will do nothing... - kim_free(); + // ensure we are in a clean state for KIM (needed on repeated call) + // first time called will do nothing... + kim_free(); - // make sure things are allocated - if (allocated != 1) allocate(); + // make sure things are allocated + if (allocated != 1) allocate(); - // clear setflag to ensure coeff() is called after settings() - int n = atom->ntypes; - for (int i = 1; i <= n; i++) - for (int j = i; j <= n; j++) - setflag[i][j] = 0; + // clear setflag to ensure coeff() is called after settings() + int n = atom->ntypes; + for (int i = 1; i <= n; i++) + for (int j = i; j <= n; j++) + setflag[i][j] = 0; - // set lmps_* bool flags - set_lmps_flags(); + // set lmps_* bool flags + set_lmps_flags(); - // set KIM Model name - int nmlen = strlen(arg[0]); - if (kim_modelname != 0) - { - delete [] kim_modelname; - kim_modelname = 0; - } - kim_modelname = new char[nmlen+1]; - strcpy(kim_modelname, arg[0]); + // set KIM Model name + int nmlen = strlen(arg[0]); + if (kim_modelname != 0) { + delete [] kim_modelname; + kim_modelname = 0; + } + kim_modelname = new char[nmlen+1]; + strcpy(kim_modelname, arg[0]); - // initialize KIM Model - kim_init(); - - return; + // initialize KIM Model + kim_init(); } /* ---------------------------------------------------------------------- @@ -356,99 +332,95 @@ void PairKIM::settings(int narg, char **arg) void PairKIM::coeff(int narg, char **arg) { - // This is called when "pair_coeff ..." is read from input - // may be called multiple times + // This is called when "pair_coeff ..." is read from input + // may be called multiple times - int i,j,n; + int i,j,n; - if (!allocated) allocate(); + if (!allocated) allocate(); - if (narg != 2 + atom->ntypes) - error->all(FLERR,"Incorrect args for pair coefficients"); + if (narg != 2 + atom->ntypes) + error->all(FLERR,"Incorrect args for pair coefficients"); - // insure I,J args are * * + // insure I,J args are * * - if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0) - error->all(FLERR,"Incorrect args for pair coefficients"); + if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0) + error->all(FLERR,"Incorrect args for pair coefficients"); + int ilo,ihi,jlo,jhi; + force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); + force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); - int ilo,ihi,jlo,jhi; - force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); - force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); + // read args that map atom species to KIM elements + // lmps_map_species_to_unique[i] = + // which element the Ith atom type is + // lmps_num_unique_elements = # of unique elements + // lmps_unique_elements = list of element names - // read args that map atom species to KIM elements - // lmps_map_species_to_unique[i] = - // which element the Ith atom type is - // lmps_num_unique_elements = # of unique elements - // lmps_unique_elements = list of element names + // if called multiple times: update lmps_unique_elements + if (lmps_unique_elements) { + for (i = 0; i < lmps_num_unique_elements; i++) + delete [] lmps_unique_elements[i]; + delete [] lmps_unique_elements; + } + lmps_unique_elements = new char*[atom->ntypes]; + for (i = 0; i < atom->ntypes; i++) lmps_unique_elements[i] = 0; - // if called multiple times: update lmps_unique_elements - if (lmps_unique_elements) { - for (i = 0; i < lmps_num_unique_elements; i++) - delete [] lmps_unique_elements[i]; - delete [] lmps_unique_elements; - } - lmps_unique_elements = new char*[atom->ntypes]; - for (i = 0; i < atom->ntypes; i++) lmps_unique_elements[i] = 0; + // Assume all species arguments are valid + // errors will be detected by below + std::string atom_type_sym_list; + lmps_num_unique_elements = 0; + for (i = 2; i < narg; i++) { + atom_type_sym_list += std::string(" ") + arg[i]; + for (j = 0; j < lmps_num_unique_elements; j++) + if (strcmp(arg[i],lmps_unique_elements[j]) == 0) break; + lmps_map_species_to_unique[i-1] = j; + if (j == lmps_num_unique_elements) { + n = strlen(arg[i]) + 1; + lmps_unique_elements[j] = new char[n]; + strcpy(lmps_unique_elements[j],arg[i]); + lmps_num_unique_elements++; + } + } - - // Assume all species arguments are valid - // errors will be detected by below - lmps_num_unique_elements = 0; - for (i = 2; i < narg; i++) { - for (j = 0; j < lmps_num_unique_elements; j++) - if (strcmp(arg[i],lmps_unique_elements[j]) == 0) break; - lmps_map_species_to_unique[i-1] = j; - if (j == lmps_num_unique_elements) { - n = strlen(arg[i]) + 1; - lmps_unique_elements[j] = new char[n]; - strcpy(lmps_unique_elements[j],arg[i]); - lmps_num_unique_elements++; - } - } - - int count = 0; - for (int i = ilo; i <= ihi; i++) { - for (int j = MAX(jlo,i); j <= jhi; j++) { - if (lmps_map_species_to_unique[i] >= 0 && - lmps_map_species_to_unique[j] >= 0) { - setflag[i][j] = 1; - count++; - } - } - } - - if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); - - // setup mapping between LAMMPS unique elements and KIM species codes - if (kim_particle_codes_ok) - { - delete [] kim_particle_codes; - kim_particle_codes = NULL; - kim_particle_codes_ok = false; - } - kim_particle_codes = new int[lmps_num_unique_elements]; - kim_particle_codes_ok = true; - for(int i = 0; i < lmps_num_unique_elements; i++){ - int supported; - int code; - KIM_Model_GetSpeciesSupportAndCode( - pkim, - KIM_SpeciesName_FromString(lmps_unique_elements[i]), - &supported, - &code); - if (supported) - kim_particle_codes[i] = code; - else - { - std::stringstream msg; - msg << "create_kim_particle_codes: symbol not found: " - << lmps_unique_elements[i]; - error->all(FLERR, msg.str().c_str()); + int count = 0; + for (int i = ilo; i <= ihi; i++) { + for (int j = MAX(jlo,i); j <= jhi; j++) { + if (lmps_map_species_to_unique[i] >= 0 && + lmps_map_species_to_unique[j] >= 0) { + setflag[i][j] = 1; + count++; } - } + } + } - return; + if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); + + // setup mapping between LAMMPS unique elements and KIM species codes + if (kim_particle_codes_ok) { + delete [] kim_particle_codes; + kim_particle_codes = NULL; + kim_particle_codes_ok = false; + } + kim_particle_codes = new int[lmps_num_unique_elements]; + kim_particle_codes_ok = true; + + for(int i = 0; i < lmps_num_unique_elements; i++) { + int supported; + int code; + KIM_Model_GetSpeciesSupportAndCode( + pkim, + KIM_SpeciesName_FromString(lmps_unique_elements[i]), + &supported, + &code); + if (supported) { + kim_particle_codes[i] = code; + } else { + std::string msg("create_kim_particle_codes: symbol not found: "); + msg += lmps_unique_elements[i]; + error->all(FLERR, msg.c_str()); + } + } } /* ---------------------------------------------------------------------- @@ -457,57 +429,48 @@ void PairKIM::coeff(int narg, char **arg) void PairKIM::init_style() { - // This is called for each "run ...", "minimize ...", etc. read from input - ++init_style_call_count; + // This is called for each "run ...", "minimize ...", etc. read from input + ++init_style_call_count; - if (domain->dimension != 3) - error->all(FLERR,"PairKIM only works with 3D problems"); + if (domain->dimension != 3) + error->all(FLERR,"PairKIM only works with 3D problems"); - // setup lmps_stripped_neigh_list for neighbors of one atom, if needed - if (lmps_using_molecular) { - memory->destroy(lmps_stripped_neigh_list); - memory->create(lmps_stripped_neigh_list, - kim_number_of_neighbor_lists*neighbor->oneatom, - "pair:lmps_stripped_neigh_list"); - delete [] lmps_stripped_neigh_ptr; - lmps_stripped_neigh_ptr = new int*[kim_number_of_neighbor_lists]; - for (int i = 0; i < kim_number_of_neighbor_lists; ++i) - { - lmps_stripped_neigh_ptr[i] - = &(lmps_stripped_neigh_list[i*(neighbor->oneatom)]); - } + // setup lmps_stripped_neigh_list for neighbors of one atom, if needed + if (lmps_using_molecular) { + memory->destroy(lmps_stripped_neigh_list); + memory->create(lmps_stripped_neigh_list, + kim_number_of_neighbor_lists*neighbor->oneatom, + "pair:lmps_stripped_neigh_list"); + delete [] lmps_stripped_neigh_ptr; + lmps_stripped_neigh_ptr = new int*[kim_number_of_neighbor_lists]; + for (int i = 0; i < kim_number_of_neighbor_lists; ++i) + lmps_stripped_neigh_ptr[i] + = &(lmps_stripped_neigh_list[i*(neighbor->oneatom)]); + } - } + // make sure comm_reverse expects (at most) 9 values when newton is off + if (!lmps_using_newton) comm_reverse_off = 9; - // make sure comm_reverse expects (at most) 9 values when newton is off - if (!lmps_using_newton) comm_reverse_off = 9; + // request full neighbor + for (int i = 0; i < kim_number_of_neighbor_lists; ++i) { + int irequest = neighbor->request(this,instance_me); + neighbor->requests[irequest]->id = i; + neighbor->requests[irequest]->half = 0; + neighbor->requests[irequest]->full = 1; - // request full neighbor - for (int i = 0; i < kim_number_of_neighbor_lists; ++i) - { - int irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = i; - neighbor->requests[irequest]->half = 0; - neighbor->requests[irequest]->full = 1; + if (modelWillNotRequestNeighborsOfNoncontributingParticles[i]) + neighbor->requests[irequest]->ghost = 0; + else + neighbor->requests[irequest]->ghost = 1; - if (modelWillNotRequestNeighborsOfNoncontributingParticles[i]) - { - neighbor->requests[irequest]->ghost = 0; - } - else - { - neighbor->requests[irequest]->ghost = 1; + // always want all owned/ghost pairs + neighbor->requests[irequest]->newton = 2; - } - // always want all owned/ghost pairs - neighbor->requests[irequest]->newton = 2; - // set cutoff - neighbor->requests[irequest]->cut = 1; - neighbor->requests[irequest]->cutoff - = kim_cutoff_values[i] + neighbor->skin; - } - - return; + // set cutoff + neighbor->requests[irequest]->cut = 1; + neighbor->requests[irequest]->cutoff + = kim_cutoff_values[i] + neighbor->skin; + } } /* ---------------------------------------------------------------------- @@ -526,154 +489,134 @@ void PairKIM::init_list(int id, NeighList *ptr) double PairKIM::init_one(int i, int j) { - // This is called once of each (unordered) i,j pair for each - // "run ...", "minimize ...", etc. read from input + // This is called once of each (unordered) i,j pair for each + // "run ...", "minimize ...", etc. read from input - if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); + if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); - return kim_global_influence_distance; + return kim_global_influence_distance; } /* ---------------------------------------------------------------------- */ int PairKIM::pack_reverse_comm(int n, int first, double *buf) { - int i,m,last; - double *fp; - fp = &(atom->f[0][0]); + int i,m,last; + double *fp; + fp = &(atom->f[0][0]); - m = 0; - last = first + n; - if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) - && - ((vflag_atom == 0) || - KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported))) - { - for (i = first; i < last; i++) - { - buf[m++] = fp[3*i+0]; - buf[m++] = fp[3*i+1]; - buf[m++] = fp[3*i+2]; - } - return m; - } - else if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) && - (vflag_atom == 1) && - KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported)) - { - double *va=&(vatom[0][0]); - for (i = first; i < last; i++) - { - buf[m++] = fp[3*i+0]; - buf[m++] = fp[3*i+1]; - buf[m++] = fp[3*i+2]; + m = 0; + last = first + n; + if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) + && + ((vflag_atom == 0) || + KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported))) { + for (i = first; i < last; i++) { + buf[m++] = fp[3*i+0]; + buf[m++] = fp[3*i+1]; + buf[m++] = fp[3*i+2]; + } + return m; + } else if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) && + (vflag_atom == 1) && + KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { + double *va=&(vatom[0][0]); + for (i = first; i < last; i++) { + buf[m++] = fp[3*i+0]; + buf[m++] = fp[3*i+1]; + buf[m++] = fp[3*i+2]; - buf[m++] = va[6*i+0]; - buf[m++] = va[6*i+1]; - buf[m++] = va[6*i+2]; - buf[m++] = va[6*i+3]; - buf[m++] = va[6*i+4]; - buf[m++] = va[6*i+5]; - } - return m; - } - else if (KIM_SupportStatus_Equal(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) - && - (vflag_atom == 1) && - KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported)) - { - double *va=&(vatom[0][0]); - for (i = first; i < last; i++) - { - buf[m++] = va[6*i+0]; - buf[m++] = va[6*i+1]; - buf[m++] = va[6*i+2]; - buf[m++] = va[6*i+3]; - buf[m++] = va[6*i+4]; - buf[m++] = va[6*i+5]; - } - return m; - } - else - return 0; + buf[m++] = va[6*i+0]; + buf[m++] = va[6*i+1]; + buf[m++] = va[6*i+2]; + buf[m++] = va[6*i+3]; + buf[m++] = va[6*i+4]; + buf[m++] = va[6*i+5]; + } + return m; + } else if (KIM_SupportStatus_Equal(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) + && + (vflag_atom == 1) && + KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { + double *va=&(vatom[0][0]); + for (i = first; i < last; i++) { + buf[m++] = va[6*i+0]; + buf[m++] = va[6*i+1]; + buf[m++] = va[6*i+2]; + buf[m++] = va[6*i+3]; + buf[m++] = va[6*i+4]; + buf[m++] = va[6*i+5]; + } + return m; + } else return 0; } /* ---------------------------------------------------------------------- */ void PairKIM::unpack_reverse_comm(int n, int *list, double *buf) { - int i,j,m; - double *fp; - fp = &(atom->f[0][0]); + int i,j,m; + double *fp; + fp = &(atom->f[0][0]); - m = 0; - if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) - && - ((vflag_atom == 0) || - KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported))) - { - for (i = 0; i < n; i++) - { - j = list[i]; - fp[3*j+0]+= buf[m++]; - fp[3*j+1]+= buf[m++]; - fp[3*j+2]+= buf[m++]; - } - } - else if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) - && - (vflag_atom == 1) && - KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported)) - { - double *va=&(vatom[0][0]); - for (i = 0; i < n; i++) - { - j = list[i]; - fp[3*j+0]+= buf[m++]; - fp[3*j+1]+= buf[m++]; - fp[3*j+2]+= buf[m++]; + m = 0; + if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) + && + ((vflag_atom == 0) || + KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported))) { + for (i = 0; i < n; i++) { + j = list[i]; + fp[3*j+0]+= buf[m++]; + fp[3*j+1]+= buf[m++]; + fp[3*j+2]+= buf[m++]; + } + } else if (KIM_SupportStatus_NotEqual(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) + && + (vflag_atom == 1) && + KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { + double *va=&(vatom[0][0]); + for (i = 0; i < n; i++) { + j = list[i]; + fp[3*j+0]+= buf[m++]; + fp[3*j+1]+= buf[m++]; + fp[3*j+2]+= buf[m++]; - va[j*6+0]+=buf[m++]; - va[j*6+1]+=buf[m++]; - va[j*6+2]+=buf[m++]; - va[j*6+3]+=buf[m++]; - va[j*6+4]+=buf[m++]; - va[j*6+5]+=buf[m++]; - } - } - else if (KIM_SupportStatus_Equal(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported) - && - (vflag_atom == 1) && - KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported)) - { - double *va=&(vatom[0][0]); - for (i = 0; i < n; i++) - { - j = list[i]; - va[j*6+0]+=buf[m++]; - va[j*6+1]+=buf[m++]; - va[j*6+2]+=buf[m++]; - va[j*6+3]+=buf[m++]; - va[j*6+4]+=buf[m++]; - va[j*6+5]+=buf[m++]; - } - } else { - ; // do nothing - } - - return; + va[j*6+0]+=buf[m++]; + va[j*6+1]+=buf[m++]; + va[j*6+2]+=buf[m++]; + va[j*6+3]+=buf[m++]; + va[j*6+4]+=buf[m++]; + va[j*6+5]+=buf[m++]; + } + } else if (KIM_SupportStatus_Equal(kim_model_support_for_forces, + KIM_SUPPORT_STATUS_notSupported) + && + (vflag_atom == 1) && + KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { + double *va=&(vatom[0][0]); + for (i = 0; i < n; i++) { + j = list[i]; + va[j*6+0]+=buf[m++]; + va[j*6+1]+=buf[m++]; + va[j*6+2]+=buf[m++]; + va[j*6+3]+=buf[m++]; + va[j*6+4]+=buf[m++]; + va[j*6+5]+=buf[m++]; + } + } else { + ; // do nothing + } } /* ---------------------------------------------------------------------- @@ -682,8 +625,8 @@ void PairKIM::unpack_reverse_comm(int n, int *list, double *buf) double PairKIM::memory_usage() { - double bytes = 2 * lmps_maxalloc * sizeof(int); - return bytes; + double bytes = 2 * lmps_maxalloc * sizeof(int); + return bytes; } /* ---------------------------------------------------------------------- @@ -693,142 +636,123 @@ double PairKIM::memory_usage() int PairKIM::get_neigh(void const * const dataObject, int const numberOfNeighborLists, double const * const cutoffs, - int const neighborListIndex, int const particleNumber, + int const neighborListIndex, + int const particleNumber, int * const numberOfNeighbors, int const ** const neighborsOfParticle) { - PairKIM const * const Model - = reinterpret_cast(dataObject); + PairKIM const * const Model + = reinterpret_cast(dataObject); - if (numberOfNeighborLists != Model->kim_number_of_neighbor_lists) - return true; - for (int i = 0; i < numberOfNeighborLists; ++i) - { - if (Model->kim_cutoff_values[i] < cutoffs[i]) return true; - } + if (numberOfNeighborLists != Model->kim_number_of_neighbor_lists) + return true; + for (int i = 0; i < numberOfNeighborLists; ++i) { + if (Model->kim_cutoff_values[i] < cutoffs[i]) return true; + } - // neighborListIndex and particleNumber are validated by KIM API + // neighborListIndex and particleNumber are validated by KIM API - // initialize numNeigh - *numberOfNeighbors = 0; + // initialize numNeigh + *numberOfNeighbors = 0; - NeighList * neiobj = Model->neighborLists[neighborListIndex]; + NeighList * neiobj = Model->neighborLists[neighborListIndex]; - int *numneigh, **firstneigh; - numneigh = neiobj->numneigh; // # of J neighbors for each I atom - firstneigh = neiobj->firstneigh; // ptr to 1st J int value of each I atom + int *numneigh, **firstneigh; + numneigh = neiobj->numneigh; // # of J neighbors for each I atom + firstneigh = neiobj->firstneigh; // ptr to 1st J int value of each I atom - *numberOfNeighbors = numneigh[particleNumber]; + *numberOfNeighbors = numneigh[particleNumber]; - // strip off neighbor mask for molecular systems - if (!Model->lmps_using_molecular) - *neighborsOfParticle = firstneigh[particleNumber]; - else - { - int n = *numberOfNeighbors; - int *ptr = firstneigh[particleNumber]; - int *lmps_stripped_neigh_list - = Model->lmps_stripped_neigh_ptr[neighborListIndex]; - for (int i = 0; i < n; i++) - lmps_stripped_neigh_list[i] = *(ptr++) & NEIGHMASK; - *neighborsOfParticle = lmps_stripped_neigh_list; - } - return false; + // strip off neighbor mask for molecular systems + if (!Model->lmps_using_molecular) + *neighborsOfParticle = firstneigh[particleNumber]; + else { + int n = *numberOfNeighbors; + int *ptr = firstneigh[particleNumber]; + int *lmps_stripped_neigh_list + = Model->lmps_stripped_neigh_ptr[neighborListIndex]; + for (int i = 0; i < n; i++) + lmps_stripped_neigh_list[i] = *(ptr++) & NEIGHMASK; + *neighborsOfParticle = lmps_stripped_neigh_list; + } + return false; } /* ---------------------------------------------------------------------- */ void PairKIM::kim_free() { - if (kim_init_ok) - { - int kimerror = KIM_Model_ComputeArgumentsDestroy(pkim, &pargs); - if (kimerror) - error->all(FLERR,"Unable to destroy Compute Arguments Object"); + if (kim_init_ok) { + int kimerror = KIM_Model_ComputeArgumentsDestroy(pkim, &pargs); + if (kimerror) + error->all(FLERR,"Unable to destroy Compute Arguments Object"); - KIM_Model_Destroy(&pkim); - } - kim_init_ok = false; - - return; + KIM_Model_Destroy(&pkim); + } + kim_init_ok = false; } /* ---------------------------------------------------------------------- */ void PairKIM::kim_init() { - int kimerror; + int kimerror; - // initialize KIM model - int requestedUnitsAccepted; - kimerror = KIM_Model_Create( - KIM_NUMBERING_zeroBased, - lengthUnit, energyUnit, chargeUnit, temperatureUnit, timeUnit, - kim_modelname, - &requestedUnitsAccepted, - &pkim); - if (kimerror) - error->all(FLERR,"KIM ModelCreate failed"); - else { - if (!requestedUnitsAccepted) { - error->all(FLERR,"KIM Model did not accept the requested unit system"); - } + // initialize KIM model + int requestedUnitsAccepted; + kimerror = KIM_Model_Create( + KIM_NUMBERING_zeroBased, + lengthUnit, energyUnit, chargeUnit, temperatureUnit, timeUnit, + kim_modelname, + &requestedUnitsAccepted, + &pkim); + if (kimerror) error->all(FLERR,"KIM ModelCreate failed"); + else if (!requestedUnitsAccepted) + error->all(FLERR,"KIM Model did not accept the requested unit system"); - // check that the model does not require unknown capabilities - kimerror = check_for_routine_compatibility(); - if (kimerror) - { - error->all(FLERR, - "KIM Model requires unknown Routines. Unable to proceed."); - } + // check that the model does not require unknown capabilities + kimerror = check_for_routine_compatibility(); + if (kimerror) + error->all(FLERR, + "KIM Model requires unknown Routines. Unable to proceed."); - kimerror = KIM_Model_ComputeArgumentsCreate(pkim, &pargs); - if (kimerror) - { - KIM_Model_Destroy(&pkim); - error->all(FLERR,"KIM ComputeArgumentsCreate failed"); - } - else - { - kim_init_ok = true; - } - } + kimerror = KIM_Model_ComputeArgumentsCreate(pkim, &pargs); + if (kimerror) { + KIM_Model_Destroy(&pkim); + error->all(FLERR,"KIM ComputeArgumentsCreate failed"); + } else kim_init_ok = true; - // determine KIM Model capabilities (used in this function below) - set_kim_model_has_flags(); + // determine KIM Model capabilities (used in this function below) + set_kim_model_has_flags(); - KIM_Model_GetInfluenceDistance(pkim, &kim_global_influence_distance); - KIM_Model_GetNeighborListPointers( - pkim, - &kim_number_of_neighbor_lists, - &kim_cutoff_values, - &modelWillNotRequestNeighborsOfNoncontributingParticles); - if (neighborLists) - { - delete [] neighborLists; - neighborLists = 0; - } - neighborLists = new NeighList*[kim_number_of_neighbor_lists]; + KIM_Model_GetInfluenceDistance(pkim, &kim_global_influence_distance); + KIM_Model_GetNeighborListPointers( + pkim, + &kim_number_of_neighbor_lists, + &kim_cutoff_values, + &modelWillNotRequestNeighborsOfNoncontributingParticles); + if (neighborLists) { + delete [] neighborLists; + neighborLists = 0; + } + neighborLists = new NeighList*[kim_number_of_neighbor_lists]; - kimerror = KIM_ComputeArguments_SetArgumentPointerInteger(pargs, - KIM_COMPUTE_ARGUMENT_NAME_numberOfParticles, - &lmps_local_tot_num_atoms); - if (KIM_SupportStatus_NotEqual(kim_model_support_for_energy, - KIM_SUPPORT_STATUS_notSupported)) - kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble(pargs, - KIM_COMPUTE_ARGUMENT_NAME_partialEnergy, - &(eng_vdwl)); + kimerror = KIM_ComputeArguments_SetArgumentPointerInteger(pargs, + KIM_COMPUTE_ARGUMENT_NAME_numberOfParticles, + &lmps_local_tot_num_atoms); + if (KIM_SupportStatus_NotEqual(kim_model_support_for_energy, + KIM_SUPPORT_STATUS_notSupported)) + kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble(pargs, + KIM_COMPUTE_ARGUMENT_NAME_partialEnergy, + &(eng_vdwl)); - kimerror = KIM_ComputeArguments_SetCallbackPointer(pargs, - KIM_COMPUTE_CALLBACK_NAME_GetNeighborList, - KIM_LANGUAGE_NAME_cpp, - reinterpret_cast(get_neigh), - reinterpret_cast(this)); + kimerror = KIM_ComputeArguments_SetCallbackPointer(pargs, + KIM_COMPUTE_CALLBACK_NAME_GetNeighborList, + KIM_LANGUAGE_NAME_cpp, + reinterpret_cast(get_neigh), + reinterpret_cast(this)); - if (kimerror) - error->all(FLERR,"Unable to register KIM pointers"); - - return; + if (kimerror) error->all(FLERR,"Unable to register KIM pointers"); } /* ---------------------------------------------------------------------- */ @@ -837,16 +761,14 @@ void PairKIM::set_argument_pointers() { int kimerror; kimerror = KIM_ComputeArguments_SetArgumentPointerDouble( - pargs, KIM_COMPUTE_ARGUMENT_NAME_coordinates, &(atom->x[0][0])); + pargs, KIM_COMPUTE_ARGUMENT_NAME_coordinates, &(atom->x[0][0])); // Set KIM pointer appropriately for particalEnergy if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy, KIM_SUPPORT_STATUS_required) - && (eflag_atom != 1)) - { + && (eflag_atom != 1)) { // reallocate per-atom energy array if necessary - if (atom->nmax > maxeatom) - { + if (atom->nmax > maxeatom) { maxeatom = atom->nmax; memory->destroy(eatom); memory->create(eatom,comm->nthreads*maxeatom,"pair:eatom"); @@ -854,31 +776,25 @@ void PairKIM::set_argument_pointers() } if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy, KIM_SUPPORT_STATUS_optional) - && (eflag_atom != 1)) - { + && (eflag_atom != 1)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( - pargs, - KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, - reinterpret_cast(NULL)); - } - else if (KIM_SupportStatus_NotEqual(kim_model_support_for_particleEnergy, - KIM_SUPPORT_STATUS_notSupported)) - { + pargs, + KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, + reinterpret_cast(NULL)); + } else if (KIM_SupportStatus_NotEqual(kim_model_support_for_particleEnergy, + KIM_SUPPORT_STATUS_notSupported)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, eatom); } // Set KIM pointer appropriately for forces if (KIM_SupportStatus_Equal(kim_model_support_for_forces, - KIM_SUPPORT_STATUS_notSupported)) - { + KIM_SUPPORT_STATUS_notSupported)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( - pargs, - KIM_COMPUTE_ARGUMENT_NAME_partialForces, - reinterpret_cast(NULL)); - } - else - { + pargs, + KIM_COMPUTE_ARGUMENT_NAME_partialForces, + reinterpret_cast(NULL)); + } else { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs, KIM_COMPUTE_ARGUMENT_NAME_partialForces, &(atom->f[0][0])); } @@ -886,11 +802,9 @@ void PairKIM::set_argument_pointers() // Set KIM pointer appropriately for particleVirial if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, KIM_SUPPORT_STATUS_required) - && (vflag_atom != 1)) - { + && (vflag_atom != 1)) { // reallocate per-atom virial array if necessary - if (atom->nmax > maxeatom) - { + if (atom->nmax > maxeatom) { maxvatom = atom->nmax; memory->destroy(vatom); memory->create(vatom,comm->nthreads*maxvatom,6,"pair:vatom"); @@ -898,84 +812,72 @@ void PairKIM::set_argument_pointers() } if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, KIM_SUPPORT_STATUS_optional) - && (vflag_atom != 1)) - { + && (vflag_atom != 1)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( - pargs, - KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial, - reinterpret_cast(NULL)); - } - else if (KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_notSupported)) - { + pargs, + KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial, + reinterpret_cast(NULL)); + } else if (KIM_SupportStatus_NotEqual(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_notSupported)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( - pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, &(vatom[0][0])); + pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial, &(vatom[0][0])); } - if (kimerror) - { - error->all(FLERR,"Unable to set KIM argument pointers"); - } - - return; + if (kimerror) error->all(FLERR,"Unable to set KIM argument pointers"); } /* ---------------------------------------------------------------------- */ void PairKIM::set_lmps_flags() { - // determint if newton is on or off - lmps_using_newton = (force->newton_pair == 1); + // determint if newton is on or off + lmps_using_newton = (force->newton_pair == 1); - // determine if running with pair hybrid - if (force->pair_match("hybrid",0)) - { - error->all(FLERR,"pair_kim does not support hybrid"); - } + // determine if running with pair hybrid + if (force->pair_match("hybrid",0)) + error->all(FLERR,"pair_kim does not support hybrid"); - // determine unit system and set lmps_units flag - if ((strcmp(update->unit_style,"real")==0)) { - lmps_units = REAL; - lengthUnit = KIM_LENGTH_UNIT_A; - energyUnit = KIM_ENERGY_UNIT_kcal_mol; - chargeUnit = KIM_CHARGE_UNIT_e; - temperatureUnit = KIM_TEMPERATURE_UNIT_K; - timeUnit = KIM_TIME_UNIT_fs; - } else if ((strcmp(update->unit_style,"metal")==0)) { - lmps_units = METAL; - lengthUnit = KIM_LENGTH_UNIT_A; - energyUnit = KIM_ENERGY_UNIT_eV; - chargeUnit = KIM_CHARGE_UNIT_e; - temperatureUnit = KIM_TEMPERATURE_UNIT_K; - timeUnit = KIM_TIME_UNIT_ps; - } else if ((strcmp(update->unit_style,"si")==0)) { - lmps_units = SI; - lengthUnit = KIM_LENGTH_UNIT_m; - energyUnit = KIM_ENERGY_UNIT_J; - chargeUnit = KIM_CHARGE_UNIT_C; - temperatureUnit = KIM_TEMPERATURE_UNIT_K; - timeUnit = KIM_TIME_UNIT_s; - } else if ((strcmp(update->unit_style,"cgs")==0)) { - lmps_units = CGS; - lengthUnit = KIM_LENGTH_UNIT_cm; - energyUnit = KIM_ENERGY_UNIT_erg; - chargeUnit = KIM_CHARGE_UNIT_statC; - temperatureUnit = KIM_TEMPERATURE_UNIT_K; - timeUnit = KIM_TIME_UNIT_s; - } else if ((strcmp(update->unit_style,"electron")==0)) { - lmps_units = ELECTRON; - lengthUnit = KIM_LENGTH_UNIT_Bohr; - energyUnit = KIM_ENERGY_UNIT_Hartree; - chargeUnit = KIM_CHARGE_UNIT_e; - temperatureUnit = KIM_TEMPERATURE_UNIT_K; - timeUnit = KIM_TIME_UNIT_fs; - } else if ((strcmp(update->unit_style,"lj")==0)) { - error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); - } else { - error->all(FLERR,"Unknown unit_style"); - } - - return; + // determine unit system and set lmps_units flag + if ((strcmp(update->unit_style,"real")==0)) { + lmps_units = REAL; + lengthUnit = KIM_LENGTH_UNIT_A; + energyUnit = KIM_ENERGY_UNIT_kcal_mol; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_fs; + } else if ((strcmp(update->unit_style,"metal")==0)) { + lmps_units = METAL; + lengthUnit = KIM_LENGTH_UNIT_A; + energyUnit = KIM_ENERGY_UNIT_eV; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_ps; + } else if ((strcmp(update->unit_style,"si")==0)) { + lmps_units = SI; + lengthUnit = KIM_LENGTH_UNIT_m; + energyUnit = KIM_ENERGY_UNIT_J; + chargeUnit = KIM_CHARGE_UNIT_C; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_s; + } else if ((strcmp(update->unit_style,"cgs")==0)) { + lmps_units = CGS; + lengthUnit = KIM_LENGTH_UNIT_cm; + energyUnit = KIM_ENERGY_UNIT_erg; + chargeUnit = KIM_CHARGE_UNIT_statC; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_s; + } else if ((strcmp(update->unit_style,"electron")==0)) { + lmps_units = ELECTRON; + lengthUnit = KIM_LENGTH_UNIT_Bohr; + energyUnit = KIM_ENERGY_UNIT_Hartree; + chargeUnit = KIM_CHARGE_UNIT_e; + temperatureUnit = KIM_TEMPERATURE_UNIT_K; + timeUnit = KIM_TIME_UNIT_fs; + } else if ((strcmp(update->unit_style,"lj")==0)) { + error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); + } else { + error->all(FLERR,"Unknown unit_style"); + } } /* ---------------------------------------------------------------------- */ @@ -986,8 +888,7 @@ int PairKIM::check_for_routine_compatibility() int numberOfModelRoutineNames; KIM_MODEL_ROUTINE_NAME_GetNumberOfModelRoutineNames( &numberOfModelRoutineNames); - for (int i = 0; i < numberOfModelRoutineNames; ++i) - { + for (int i = 0; i < numberOfModelRoutineNames; ++i) { KIM_ModelRoutineName modelRoutineName; KIM_MODEL_ROUTINE_NAME_GetModelRoutineName(i, &modelRoutineName); @@ -995,10 +896,9 @@ int PairKIM::check_for_routine_compatibility() int required; int error = KIM_Model_IsRoutinePresent( pkim, modelRoutineName, &present, &required); - if (error) { return true; } + if (error) return true; - if ((present == true) && (required == true)) - { + if ((present == true) && (required == true)) { if (!(KIM_ModelRoutineName_Equal(modelRoutineName, KIM_MODEL_ROUTINE_NAME_Create) || KIM_ModelRoutineName_Equal( @@ -1012,8 +912,9 @@ int PairKIM::check_for_routine_compatibility() modelRoutineName, KIM_MODEL_ROUTINE_NAME_ComputeArgumentsDestroy) || KIM_ModelRoutineName_Equal(modelRoutineName, - KIM_MODEL_ROUTINE_NAME_Destroy))) - { return true; } + KIM_MODEL_ROUTINE_NAME_Destroy))) { + return true; + } } } @@ -1028,8 +929,7 @@ void PairKIM::set_kim_model_has_flags() int numberOfComputeArgumentNames; KIM_COMPUTE_ARGUMENT_NAME_GetNumberOfComputeArgumentNames( &numberOfComputeArgumentNames); - for (int i = 0; i < numberOfComputeArgumentNames; ++i) - { + for (int i = 0; i < numberOfComputeArgumentNames; ++i) { KIM_ComputeArgumentName computeArgumentName; KIM_COMPUTE_ARGUMENT_NAME_GetComputeArgumentName( i, &computeArgumentName); @@ -1038,32 +938,24 @@ void PairKIM::set_kim_model_has_flags() pargs, computeArgumentName, &supportStatus); if (KIM_ComputeArgumentName_Equal(computeArgumentName, - KIM_COMPUTE_ARGUMENT_NAME_partialEnergy) - ) + KIM_COMPUTE_ARGUMENT_NAME_partialEnergy)) kim_model_support_for_energy = supportStatus; else if (KIM_ComputeArgumentName_Equal( - computeArgumentName, KIM_COMPUTE_ARGUMENT_NAME_partialForces) - ) + computeArgumentName, KIM_COMPUTE_ARGUMENT_NAME_partialForces)) kim_model_support_for_forces = supportStatus; - else if - (KIM_ComputeArgumentName_Equal( - computeArgumentName, - KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy)\ - ) + else if (KIM_ComputeArgumentName_Equal( + computeArgumentName, + KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy)) kim_model_support_for_particleEnergy = supportStatus; - else if - (KIM_ComputeArgumentName_Equal( - computeArgumentName, - KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial) - ) + else if (KIM_ComputeArgumentName_Equal( + computeArgumentName, + KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial)) kim_model_support_for_particleVirial = supportStatus; - else if (KIM_SupportStatus_Equal(supportStatus, KIM_SUPPORT_STATUS_required) - ) - { - std::stringstream msg; - msg << "KIM Model requires unsupported compute argument: " - << KIM_ComputeArgumentName_ToString(computeArgumentName); - error->all(FLERR, msg.str().c_str()); + else if (KIM_SupportStatus_Equal(supportStatus, + KIM_SUPPORT_STATUS_required)) { + std::string msg("KIM Model requires unsupported compute argument: "); + msg += KIM_ComputeArgumentName_ToString(computeArgumentName); + error->all(FLERR, msg.c_str()); } } @@ -1090,20 +982,15 @@ void PairKIM::set_kim_model_has_flags() int numberOfComputeCallbackNames; KIM_COMPUTE_CALLBACK_NAME_GetNumberOfComputeCallbackNames( &numberOfComputeCallbackNames); - for (int i = 0; i < numberOfComputeCallbackNames; ++i) - { + for (int i = 0; i < numberOfComputeCallbackNames; ++i) { KIM_ComputeCallbackName computeCallbackName; - KIM_COMPUTE_CALLBACK_NAME_GetComputeCallbackName( - i, &computeCallbackName); + KIM_COMPUTE_CALLBACK_NAME_GetComputeCallbackName(i, &computeCallbackName); KIM_SupportStatus supportStatus; - KIM_ComputeArguments_GetCallbackSupportStatus( - pargs, computeCallbackName, &supportStatus); + KIM_ComputeArguments_GetCallbackSupportStatus(pargs, + computeCallbackName, + &supportStatus); if (KIM_SupportStatus_Equal(supportStatus, KIM_SUPPORT_STATUS_required)) - { error->all(FLERR,"KIM Model requires unsupported compute callback"); - } } - - return; } diff --git a/src/KIM/pair_kim.h b/src/KIM/pair_kim.h index 27bab6c687..aa33b9b271 100644 --- a/src/KIM/pair_kim.h +++ b/src/KIM/pair_kim.h @@ -12,7 +12,7 @@ ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- - Contributing authors: Ryan S. Elliott (UMinn) + Contributing authors: Ryan S. Elliott (UMinn), Axel Kohlmeyer (Temple U) ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- @@ -65,108 +65,107 @@ PairStyle(kim,PairKIM) // includes from KIM & LAMMPS class KIM_API_model; #include "pair.h" + extern "C" { #include "KIM_SimulatorHeaders.h" } -#include - namespace LAMMPS_NS { - class PairKIM : public Pair { - public: - PairKIM(class LAMMPS*); - ~PairKIM(); +class PairKIM : public Pair { + public: + PairKIM(class LAMMPS*); + ~PairKIM(); - // LAMMPS Pair class virtual function prototypes - virtual void compute(int, int); - virtual void settings(int, char**); - virtual void coeff(int, char**); - virtual void init_style(); - virtual void init_list(int id, NeighList *ptr); - virtual double init_one(int, int); - virtual int pack_reverse_comm(int, int, double*); - virtual void unpack_reverse_comm(int, int*, double*); - virtual double memory_usage(); + // LAMMPS Pair class virtual function prototypes + virtual void compute(int, int); + virtual void settings(int, char**); + virtual void coeff(int, char**); + virtual void init_style(); + virtual void init_list(int id, NeighList *ptr); + virtual double init_one(int, int); + virtual int pack_reverse_comm(int, int, double*); + virtual void unpack_reverse_comm(int, int*, double*); + virtual double memory_usage(); - protected: - // (nearly) all bool flags are not initialized in constructor, but set - // explicitly in the indicated function. All other data members are - // initialized in constructor - int settings_call_count; - int init_style_call_count; + protected: + // (nearly) all bool flags are not initialized in constructor, but set + // explicitly in the indicated function. All other data members are + // initialized in constructor + int settings_call_count; + int init_style_call_count; - // values set in settings() - char* kim_modelname; + // values set in settings() + char* kim_modelname; - // values set in coeff() + // values set in coeff() - // values set in allocate(), called by coeff() - virtual void allocate(); - int* lmps_map_species_to_unique; + // values set in allocate(), called by coeff() + virtual void allocate(); + int* lmps_map_species_to_unique; - // values set in coeff(), after calling allocate() - char** lmps_unique_elements; // names of unique elements given - // in pair_coeff command - int lmps_num_unique_elements; + // values set in coeff(), after calling allocate() + char** lmps_unique_elements; // names of unique elements given + // in pair_coeff command + int lmps_num_unique_elements; - // values set in set_lmps_flags(), called from init_style() - bool lmps_using_newton; - bool lmps_using_molecular; - enum unit_sys {REAL, METAL, SI, CGS, ELECTRON}; - unit_sys lmps_units; - KIM_LengthUnit lengthUnit; - KIM_EnergyUnit energyUnit; - KIM_ChargeUnit chargeUnit; - KIM_TemperatureUnit temperatureUnit; - KIM_TimeUnit timeUnit; + // values set in set_lmps_flags(), called from init_style() + bool lmps_using_newton; + bool lmps_using_molecular; + enum unit_sys {REAL, METAL, SI, CGS, ELECTRON}; + unit_sys lmps_units; + KIM_LengthUnit lengthUnit; + KIM_EnergyUnit energyUnit; + KIM_ChargeUnit chargeUnit; + KIM_TemperatureUnit temperatureUnit; + KIM_TimeUnit timeUnit; - KIM_Model * pkim; - KIM_ComputeArguments * pargs; + KIM_Model * pkim; + KIM_ComputeArguments * pargs; - // values set in set_kim_model_has_flags(), called by kim_init() - KIM_SupportStatus kim_model_support_for_energy; - KIM_SupportStatus kim_model_support_for_forces; - KIM_SupportStatus kim_model_support_for_particleEnergy; - KIM_SupportStatus kim_model_support_for_particleVirial; + // values set in set_kim_model_has_flags(), called by kim_init() + KIM_SupportStatus kim_model_support_for_energy; + KIM_SupportStatus kim_model_support_for_forces; + KIM_SupportStatus kim_model_support_for_particleEnergy; + KIM_SupportStatus kim_model_support_for_particleVirial; - // values set in kim_init() - bool kim_init_ok; - int lmps_local_tot_num_atoms; - double kim_global_influence_distance; // KIM Model cutoff value - int kim_number_of_neighbor_lists; - double const * kim_cutoff_values; - int const * modelWillNotRequestNeighborsOfNoncontributingParticles; - class NeighList ** neighborLists; + // values set in kim_init() + bool kim_init_ok; + int lmps_local_tot_num_atoms; + double kim_global_influence_distance; // KIM Model cutoff value + int kim_number_of_neighbor_lists; + double const * kim_cutoff_values; + int const * modelWillNotRequestNeighborsOfNoncontributingParticles; + class NeighList ** neighborLists; - // values set in init_style() - bool kim_particle_codes_ok; - int *kim_particle_codes; + // values set in init_style() + bool kim_particle_codes_ok; + int *kim_particle_codes; - // values set in compute() - int lmps_maxalloc; // max allocated memory value - int* kim_particleSpecies; // array of KIM particle species - int* kim_particleContributing; // array of KIM particle contributing - int* lmps_stripped_neigh_list; // neighbors of one atom, used when LAMMPS - // is in molecular mode - int** lmps_stripped_neigh_ptr; // pointer into lists + // values set in compute() + int lmps_maxalloc; // max allocated memory value + int* kim_particleSpecies; // array of KIM particle species + int* kim_particleContributing; // array of KIM particle contributing + int* lmps_stripped_neigh_list; // neighbors of one atom, used when LAMMPS + // is in molecular mode + int** lmps_stripped_neigh_ptr; // pointer into lists - // KIM specific helper functions - virtual void set_contributing(); - virtual void kim_init(); - virtual void kim_free(); - virtual void set_argument_pointers(); - virtual void set_lmps_flags(); - virtual void set_kim_model_has_flags(); - virtual int check_for_routine_compatibility(); - // static methods used as callbacks from KIM - static int get_neigh( - void const * const dataObject, - int const numberOfCutoffs, double const * const cutoffs, - int const neighborListIndex, int const particleNumber, - int * const numberOfNeighbors, - int const ** const neighborsOfParticle); - }; + // KIM specific helper functions + virtual void set_contributing(); + virtual void kim_init(); + virtual void kim_free(); + virtual void set_argument_pointers(); + virtual void set_lmps_flags(); + virtual void set_kim_model_has_flags(); + virtual int check_for_routine_compatibility(); + // static methods used as callbacks from KIM + static int get_neigh( + void const * const dataObject, + int const numberOfCutoffs, double const * const cutoffs, + int const neighborListIndex, int const particleNumber, + int * const numberOfNeighbors, + int const ** const neighborsOfParticle); +}; } #endif @@ -184,7 +183,10 @@ The KIM model was unable, for some reason, to complete the computation. E: 'KIMvirial' or 'LAMMPSvirial' not supported with kim-api. -"KIMvirial or "LAMMPSvirial" found on the pair_style line. These keys are not supported kim-api. (The virial computation is always performed by LAMMPS.) Please remove these keys, make sure the KIM model you are using supports kim-api, and rerun. +"KIMvirial or "LAMMPSvirial" found on the pair_style line. These keys +are not supported kim-api. (The virial computation is always performed +by LAMMPS.) Please remove these keys, make sure the KIM model you are +using supports kim-api, and rerun. E: Illegal pair_style command diff --git a/src/input.cpp b/src/input.cpp index a51426c53e..6871ee23f5 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -309,6 +309,17 @@ char *Input::one(const char *single) return command; } +/* ---------------------------------------------------------------------- + Send text to active echo file pointers +------------------------------------------------------------------------- */ +void Input::write_echo(const char *txt) +{ + if (me == 0) { + if (echo_screen && screen) fputs(txt,screen); + if (echo_log && logfile) fputs(txt,logfile); + } +} + /* ---------------------------------------------------------------------- parse copy of command line by inserting string terminators strip comment = all chars from # on diff --git a/src/input.h b/src/input.h index bda4a3c806..4b274c17a9 100644 --- a/src/input.h +++ b/src/input.h @@ -38,17 +38,18 @@ class Input : protected Pointers { void substitute(char *&, char *&, int &, int &, int); // substitute for variables in a string int expand_args(int, char **, int, char **&); // expand args due to wildcard - + void write_echo(const char *); // send text to active echo file pointers + protected: char *command; // ptr to current command + int echo_screen; // 0 = no, 1 = yes + int echo_log; // 0 = no, 1 = yes private: int me; // proc ID int maxarg; // max # of args in arg char *line,*copy,*work; // input line & copy and work string int maxline,maxcopy,maxwork; // max lengths of char strings - int echo_screen; // 0 = no, 1 = yes - int echo_log; // 0 = no, 1 = yes int nfile,maxfile; // current # and max # of open input files int label_active; // 0 = no label, 1 = looking for label char *labelstr; // label string being looked for diff --git a/src/modify.cpp b/src/modify.cpp index a9b8817aed..109571d531 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -797,7 +797,7 @@ void Modify::add_fix(int narg, char **arg, int trysuffix) const char *exceptions[] = {"GPU", "OMP", "INTEL", "property/atom", "cmap", "cmap3", "rx", - "deprecated", NULL}; + "deprecated", "STORE/KIM", NULL}; if (domain->box_exist == 0) { int m;