From 280e98b0743a6d15a5a79a5e0f25d09e1f15528d Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Tue, 3 Nov 2020 20:26:34 -0700 Subject: [PATCH 01/39] Added explicit energy updates --- src/MLIAP/mliap_data.cpp | 6 +++++- src/MLIAP/mliap_data.h | 4 +++- src/MLIAP/mliap_model_linear.cpp | 6 ++++-- src/MLIAP/mliap_model_quadratic.cpp | 6 ++++-- src/MLIAP/pair_mliap.cpp | 14 ++++++++++---- src/MLIAP/pair_mliap.h | 2 +- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/MLIAP/mliap_data.cpp b/src/MLIAP/mliap_data.cpp index e6502d001a..3ada98e8c0 100644 --- a/src/MLIAP/mliap_data.cpp +++ b/src/MLIAP/mliap_data.cpp @@ -25,7 +25,8 @@ MLIAPData::MLIAPData(LAMMPS *lmp, int gradgradflag_in, int *map_in, class MLIAPModel* model_in, class MLIAPDescriptor* descriptor_in, class PairMLIAP* pairmliap_in) : - Pointers(lmp), gradforce(nullptr), betas(nullptr), descriptors(nullptr), gamma(nullptr), + Pointers(lmp), gradforce(nullptr), betas(nullptr), + descriptors(nullptr), eatoms(nullptr), gamma(nullptr), gamma_row_index(nullptr), gamma_col_index(nullptr), egradient(nullptr), numneighs(nullptr), iatoms(nullptr), ielems(nullptr), jatoms(nullptr), jelems(nullptr), rij(nullptr), graddesc(nullptr), model(nullptr), descriptor(nullptr), list(nullptr) @@ -64,6 +65,7 @@ MLIAPData::~MLIAPData() { memory->destroy(betas); memory->destroy(descriptors); + memory->destroy(eatoms); memory->destroy(gamma_row_index); memory->destroy(gamma_col_index); memory->destroy(gamma); @@ -133,6 +135,7 @@ void MLIAPData::generate_neighdata(NeighList* list_in, int eflag_in, int vflag_i if (natoms_max < natoms) { memory->grow(betas,natoms,ndescriptors,"MLIAPData:betas"); memory->grow(descriptors,natoms,ndescriptors,"MLIAPData:descriptors"); + memory->grow(eatoms,natoms,"MLIAPData:eatoms"); natoms_max = natoms; } @@ -267,6 +270,7 @@ double MLIAPData::memory_usage() bytes += natoms*ndescriptors*sizeof(int); // betas bytes += natoms*ndescriptors*sizeof(int); // descriptors + bytes += natoms*sizeof(double); // eatoms bytes += natomneigh_max*sizeof(int); // iatoms bytes += natomneigh_max*sizeof(int); // ielems diff --git a/src/MLIAP/mliap_data.h b/src/MLIAP/mliap_data.h index ffac9ccd4c..7fb60bd723 100644 --- a/src/MLIAP/mliap_data.h +++ b/src/MLIAP/mliap_data.h @@ -34,8 +34,10 @@ class MLIAPData : protected Pointers { int yoffset, zoffset; int ndims_force, ndims_virial; double **gradforce; - double** betas; // betas for all atoms in list + double** betas; // betas for all atoms in list double** descriptors; // descriptors for all atoms in list + double* eatoms; // energies for all atoms in list + double energy; // energy int ndescriptors; // number of descriptors int nparams; // number of model parameters per element int nelements; // number of elements diff --git a/src/MLIAP/mliap_model_linear.cpp b/src/MLIAP/mliap_model_linear.cpp index b3224284e5..d3c8373708 100644 --- a/src/MLIAP/mliap_model_linear.cpp +++ b/src/MLIAP/mliap_model_linear.cpp @@ -51,8 +51,9 @@ int MLIAPModelLinear::get_nparams() void MLIAPModelLinear::compute_gradients(MLIAPData* data) { + data->energy = 0.0; + for (int ii = 0; ii < data->natoms; ii++) { - const int i = data->iatoms[ii]; const int ielem = data->ielems[ii]; double* coeffi = coeffelem[ielem]; @@ -74,7 +75,8 @@ void MLIAPModelLinear::compute_gradients(MLIAPData* data) for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++) etmp += coeffi[icoeff+1]*data->descriptors[ii][icoeff]; - data->pairmliap->e_tally(i,etmp); + data->energy += etmp; + data->eatoms[ii] = etmp; } } } diff --git a/src/MLIAP/mliap_model_quadratic.cpp b/src/MLIAP/mliap_model_quadratic.cpp index 481417078a..36642c1a87 100644 --- a/src/MLIAP/mliap_model_quadratic.cpp +++ b/src/MLIAP/mliap_model_quadratic.cpp @@ -52,8 +52,9 @@ int MLIAPModelQuadratic::get_nparams() void MLIAPModelQuadratic::compute_gradients(MLIAPData* data) { + data->energy = 0.0; + for (int ii = 0; ii < data->natoms; ii++) { - const int i = data->iatoms[ii]; const int ielem = data->ielems[ii]; double* coeffi = coeffelem[ielem]; @@ -99,7 +100,8 @@ void MLIAPModelQuadratic::compute_gradients(MLIAPData* data) etmp += coeffi[k++]*bveci*bvecj; } } - data->pairmliap->e_tally(i,etmp); + data->energy += etmp; + data->eatoms[ii] = etmp; } } } diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index f5895d6e5d..ef3ff40da5 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -78,6 +78,8 @@ void PairMLIAP::compute(int eflag, int vflag) model->compute_gradients(data); + e_tally(data); + // calculate force contributions beta_i*dB_i/dR_j descriptor->compute_forces(data); @@ -220,13 +222,17 @@ void PairMLIAP::coeff(int narg, char **arg) } /* ---------------------------------------------------------------------- - add energy of atom i to global and per-atom energy + add energies to eng_vdwl and per-atom energy ------------------------------------------------------------------------- */ -void PairMLIAP::e_tally(int i, double ei) +void PairMLIAP::e_tally(MLIAPData* data) { - if (eflag_global) eng_vdwl += ei; - if (eflag_atom) eatom[i] += ei; + if (eflag_global) eng_vdwl += data->energy; + if (eflag_atom) + for (int ii = 0; ii < data->natoms; ii++) { + const int i = data->iatoms[ii]; + eatom[i] += data->eatoms[ii]; + } } /* ---------------------------------------------------------------------- diff --git a/src/MLIAP/pair_mliap.h b/src/MLIAP/pair_mliap.h index 61acbbb278..c31634e923 100644 --- a/src/MLIAP/pair_mliap.h +++ b/src/MLIAP/pair_mliap.h @@ -31,7 +31,7 @@ public: virtual void compute(int, int); void settings(int, char **); virtual void coeff(int, char **); - void e_tally(int, double); + void e_tally(class MLIAPData*); void v_tally(int, int, double*, double*); virtual void init_style(); virtual double init_one(int, int); From 7c1634e57f0927f7ac09653dea8fb73ed07a40df Mon Sep 17 00:00:00 2001 From: Nicholas Lubbers Date: Fri, 6 Nov 2020 13:12:25 -0700 Subject: [PATCH 02/39] Squashed commit for MLIAPPY package Includes CMAKE install, doc updates, example files. --- .gitignore | 1 + cmake/CMakeLists.txt | 6 +- cmake/Modules/Packages/MLIAPPY.cmake | 12 ++ doc/src/Packages_details.rst | 32 +++++ doc/src/Packages_standard.rst | 2 + doc/src/compute_mliap.rst | 7 +- doc/src/pair_mliap.rst | 12 +- examples/mliappy/README.txt | 11 ++ examples/mliappy/Ta06A.mliap.descriptor | 21 +++ examples/mliappy/Ta06A.mliap.pytorch | 18 +++ examples/mliappy/convert_mliap_Ta06A.py | 33 +++++ examples/mliappy/in.mliap.pytorch.Ta06A | 67 +++++++++ src/MLIAP/compute_mliap.cpp | 13 +- src/MLIAP/mliap_model.cpp | 31 ++-- src/MLIAP/mliap_model.h | 17 ++- src/MLIAP/mliap_model_linear.cpp | 2 +- src/MLIAP/mliap_model_linear.h | 2 +- src/MLIAP/mliap_model_quadratic.cpp | 3 +- src/MLIAP/mliap_model_quadratic.h | 2 +- src/MLIAP/pair_mliap.cpp | 23 ++- src/MLIAPPY/mliap_model_python.cpp | 163 ++++++++++++++++++++++ src/MLIAPPY/mliap_model_python.h | 42 ++++++ src/MLIAPPY/mliap_model_python_couple.pyx | 85 +++++++++++ src/MLIAPPY/mliappy_pytorch.py | 46 ++++++ src/Makefile | 2 +- src/PYTHON/python_impl.cpp | 14 +- 26 files changed, 635 insertions(+), 32 deletions(-) create mode 100644 cmake/Modules/Packages/MLIAPPY.cmake create mode 100644 examples/mliappy/README.txt create mode 100644 examples/mliappy/Ta06A.mliap.descriptor create mode 100644 examples/mliappy/Ta06A.mliap.pytorch create mode 100644 examples/mliappy/convert_mliap_Ta06A.py create mode 100644 examples/mliappy/in.mliap.pytorch.Ta06A create mode 100644 src/MLIAPPY/mliap_model_python.cpp create mode 100644 src/MLIAPPY/mliap_model_python.h create mode 100644 src/MLIAPPY/mliap_model_python_couple.pyx create mode 100644 src/MLIAPPY/mliappy_pytorch.py diff --git a/.gitignore b/.gitignore index 0f1b01775d..92fae19766 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ Thumbs.db /Makefile /cmake_install.cmake /lmp + diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 42e6d12ffb..fab10bfdef 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -105,7 +105,7 @@ install(TARGETS lmp EXPORT LAMMPS_Targets DESTINATION ${CMAKE_INSTALL_BINDIR}) option(CMAKE_VERBOSE_MAKEFILE "Generate verbose Makefiles" OFF) set(STANDARD_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS DIPOLE - GRANULAR KSPACE LATTE MANYBODY MC MESSAGE MISC MLIAP MOLECULE PERI POEMS + GRANULAR KSPACE LATTE MANYBODY MC MESSAGE MISC MLIAP MLIAPPY MOLECULE PERI POEMS QEQ REPLICA RIGID SHOCK SPIN SNAP SRD KIM PYTHON MSCG MPIIO VORONOI USER-ATC USER-AWPMD USER-BOCS USER-CGDNA USER-MESODPD USER-CGSDK USER-COLVARS USER-DIFFRACTION USER-DPD USER-DRUDE USER-EFF USER-FEP USER-H5MD USER-LB @@ -194,6 +194,8 @@ endif() # "hard" dependencies between packages resulting # in an error instead of skipping over files pkg_depends(MLIAP SNAP) +pkg_depends(MLIAPPY MLIAP) +pkg_depends(MLIAPPY PYTHON) pkg_depends(MPIIO MPI) pkg_depends(USER-ATC MANYBODY) pkg_depends(USER-LB MPI) @@ -372,7 +374,7 @@ else() set(CUDA_REQUEST_PIC) endif() -foreach(PKG_WITH_INCL KSPACE PYTHON VORONOI USER-COLVARS USER-MOLFILE USER-NETCDF USER-PLUMED USER-QMMM +foreach(PKG_WITH_INCL KSPACE PYTHON MLIAPPY VORONOI USER-COLVARS USER-MOLFILE USER-NETCDF USER-PLUMED USER-QMMM USER-QUIP USER-SCAFACOS USER-SMD USER-VTK KIM LATTE MESSAGE MSCG COMPRESS) if(PKG_${PKG_WITH_INCL}) include(Packages/${PKG_WITH_INCL}) diff --git a/cmake/Modules/Packages/MLIAPPY.cmake b/cmake/Modules/Packages/MLIAPPY.cmake new file mode 100644 index 0000000000..842c43bd96 --- /dev/null +++ b/cmake/Modules/Packages/MLIAPPY.cmake @@ -0,0 +1,12 @@ +if(CMAKE_VERSION VERSION_LESS 3.12) + #This block was not tested, mimmicks PYTHON.cmake. + find_package(PythonLibs REQUIRED) # Deprecated since version 3.12 + target_include_directories(lammps PRIVATE ${PYTHON_INCLUDE_DIR}) + target_link_libraries(lammps PRIVATE ${PYTHON_LIBRARY}) + target_include_directories(lammps PRIVATE ${Python_NumPy_INCLUDE_DIRS}) +else() + find_package(Python REQUIRED COMPONENTS NumPy) + target_include_directories(lammps PRIVATE ${Python_NumPy_INCLUDE_DIRS}) +endif() +target_compile_definitions(lammps PRIVATE -DLMP_MLIAPPY) + diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index 74214e2e0e..edce17b9ab 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -45,6 +45,7 @@ page gives those details. * :ref:`MESSAGE ` * :ref:`MISC ` * :ref:`MLIAP ` + * :ref:`MLIAPPY ` * :ref:`MOLECULE ` * :ref:`MPIIO ` * :ref:`MSCG ` @@ -678,6 +679,37 @@ To use this package, also the :ref:`SNAP package ` needs to be install ---------- +.. _PKG-MLIAPPY: + +MLIAPPY package +------------- + +**Contents:** + +Extension to the MLIAP package for coupling with python models. + +**Install:** + +To use this package, also the :ref:`MLIAP package ` needs to be installed. +To use this package, also the :ref:`PYTHON package ` needs to be installed. +The version of python must be >3.5, and has been tested only with 3.8. +Compiling this package has only been tested using CMake, not with pure makefiles.s +The python interpreter linked to LAMMPS will need cython and numpy installed. + +Before compiling, run cythonize on /src/MLIAPPY/mliap_model_python_couple.pyx. +This will produce /src/MLIAPPY/mliap_model_python_couple.cpp and /src/MLIAPPY/mliap_model_python_couple.h files. + +This package includes more options for the mliap compute and pair style. + +**Author:** Nicholas Lubbers (LANL). + +**Supporting info:** + +* src/MLIAPPY: filenames -> commands +* :doc:`pair_style mliap ` +* examples/mliappy (see README) +---------- + .. _PKG-MOLECULE: MOLECULE package diff --git a/doc/src/Packages_standard.rst b/doc/src/Packages_standard.rst index ab9be69ab3..800fd3c501 100644 --- a/doc/src/Packages_standard.rst +++ b/doc/src/Packages_standard.rst @@ -61,6 +61,8 @@ package: +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MLIAP ` | multiple machine learning potentials | :doc:`pair_style mliap ` | mliap | no | +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ +| :ref:`MLIAPPY ` | enable python ML models for mliap | :doc:`pair_style mliap ` | mliap | no | ++----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MOLECULE ` | molecular system force fields | :doc:`Howto bioFF ` | peptide | no | +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MPIIO ` | MPI parallel I/O dump and restart | :doc:`dump ` | n/a | no | diff --git a/doc/src/compute_mliap.rst b/doc/src/compute_mliap.rst index fcc336e682..e4e6603cdc 100644 --- a/doc/src/compute_mliap.rst +++ b/doc/src/compute_mliap.rst @@ -18,7 +18,7 @@ Syntax .. parsed-literal:: *model* values = style - style = *linear* or *quadratic* + style = *linear* or *quadratic* or *mliappy* *descriptor* values = style filename style = *sna* filename = name of file containing descriptor definitions @@ -57,7 +57,8 @@ The compute *mliap* command must be followed by two keywords *model* and *descriptor* in either order. The *model* keyword is followed by a model style, currently limited to -either *linear* or *quadratic*. +either *linear* or *quadratic*. The *mliappy* model is only available +if lammps is built with MLIAPPY package. The *descriptor* keyword is followed by a descriptor style, and additional arguments. Currently the only descriptor style is *sna*, indicating the bispectrum component @@ -167,6 +168,8 @@ LAMMPS was built with that package. In addition, building LAMMPS with the MLIAP requires building LAMMPS with the SNAP package. See the :doc:`Build package ` doc page for more info. +Python models such as neural networks can be used if the MLIAPPY package is built. + Related commands """""""""""""""" diff --git a/doc/src/pair_mliap.rst b/doc/src/pair_mliap.rst index 09295cd8be..aeba2d9fd2 100644 --- a/doc/src/pair_mliap.rst +++ b/doc/src/pair_mliap.rst @@ -16,7 +16,7 @@ Syntax .. parsed-literal:: *model* values = style filename - style = *linear* or *quadratic* + style = *linear* or *quadratic* or *mliappy* filename = name of file containing model definitions *descriptor* values = style filename style = *sna* @@ -43,9 +43,10 @@ it is possible to use many different models with a given descriptor, or many different descriptors with a given model. Currently, the pair_style supports just two models, *linear* and *quadratic*, and one descriptor, *sna*, the SNAP descriptor used by :doc:`pair_style snap `, including the linear, quadratic, -and chem variants. Work is currently underway to extend -the interface to handle neural network energy models, -and it is also straightforward to add new descriptor styles. +and chem variants. With the MLIAPPY package installed, the *mliappy* model +is available which can be used to couple python models such as neural network +energy models. +It is also straightforward to add new descriptor styles. In order to train a model, it is useful to know the gradient or derivative of energy, force, and stress w.r.t. model parameters. This information can be accessed using the related :doc:`compute mliap ` command. @@ -143,6 +144,9 @@ was built with that package. In addition, building LAMMPS with the MLIAP package requires building LAMMPS with the SNAP package. See the :doc:`Build package ` doc page for more info. +Python models such as neural networks can be used if the MLIAPPY package is built. + + Related commands """""""""""""""" diff --git a/examples/mliappy/README.txt b/examples/mliappy/README.txt new file mode 100644 index 0000000000..f624acd657 --- /dev/null +++ b/examples/mliappy/README.txt @@ -0,0 +1,11 @@ +README for MLIAPPY Example + +This example runs the Ta06 example from the MLIAP example, but using the python coupling. + +To run this, first run convert_mliap_Ta06A.py, which will convert the Ta06 potential into a pytorch model. +It will be saved as "Ta06A.mliap.pytorch.model.pkl". + +It will also copy the "torchlink.py" file into the current working directory. torchlink.py contains +class definitions suitable for wrapping an arbitrary energy model MLIAPPY. + +From that point you can run the example lmp -in in.mliap.snap.Ta06A -echo both \ No newline at end of file diff --git a/examples/mliappy/Ta06A.mliap.descriptor b/examples/mliappy/Ta06A.mliap.descriptor new file mode 100644 index 0000000000..481ebf7e44 --- /dev/null +++ b/examples/mliappy/Ta06A.mliap.descriptor @@ -0,0 +1,21 @@ +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# LAMMPS SNAP parameters for Ta_Cand06A + +# required +rcutfac 4.67637 +twojmax 6 + +# elements + +nelems 1 +elems Ta +radelems 0.5 +welems 1 + +# optional + +rfac0 0.99363 +rmin0 0 +bzeroflag 0 + diff --git a/examples/mliappy/Ta06A.mliap.pytorch b/examples/mliappy/Ta06A.mliap.pytorch new file mode 100644 index 0000000000..c6c6bc653d --- /dev/null +++ b/examples/mliappy/Ta06A.mliap.pytorch @@ -0,0 +1,18 @@ +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# Definition of SNAP potential Ta_Cand06A +# Assumes 1 LAMMPS atom type + +variable zblcutinner equal 4 +variable zblcutouter equal 4.8 +variable zblz equal 73 + +# Specify hybrid with SNAP, ZBL + +pair_style hybrid/overlay & +zbl ${zblcutinner} ${zblcutouter} & +mliap model mliappy Ta06A.mliap.pytorch.model.pkl & +descriptor sna Ta06A.mliap.descriptor +pair_coeff 1 1 zbl ${zblz} ${zblz} +pair_coeff * * mliap Ta + diff --git a/examples/mliappy/convert_mliap_Ta06A.py b/examples/mliappy/convert_mliap_Ta06A.py new file mode 100644 index 0000000000..bdc3887282 --- /dev/null +++ b/examples/mliappy/convert_mliap_Ta06A.py @@ -0,0 +1,33 @@ +import sys +import numpy as np +import torch +import pickle +import os +import shutil + +shutil.copyfile('../../src/MLIAPPY/mliappy_pytorch.py','./mliappy_pytorch.py') + +import mliappy_pytorch + +# Read coefficients +coeffs = np.genfromtxt("../mliap/Ta06A.mliap.model",skip_header=6) + +# Write coefficiets to a pytorch linear model +bias = coeffs[0] +weights = coeffs[1:] +lin = torch.nn.Linear(weights.shape[0],1) +lin.to(torch.float64) +with torch.autograd.no_grad(): + lin.weight.set_(torch.from_numpy(weights).unsqueeze(0)) + lin.bias.set_(torch.as_tensor(bias,dtype=torch.float64).unsqueeze(0)) + +# Wrap the pytorch model for usage with MLIAPPY +model = mliappy_pytorch.IgnoreTypes(lin) +n_descriptors = lin.weight.shape[1] +n_params = mliappy_pytorch.calc_n_params(model) +n_types = 1 +linked_model = mliappy_pytorch.TorchWrapper64(model,n_descriptors=n_descriptors,n_elements=n_types) + +# Save the result. +with open("Ta06A.mliap.pytorch.model.pkl",'wb') as pfile: + pickle.dump(linked_model,pfile) \ No newline at end of file diff --git a/examples/mliappy/in.mliap.pytorch.Ta06A b/examples/mliappy/in.mliap.pytorch.Ta06A new file mode 100644 index 0000000000..526c24ab23 --- /dev/null +++ b/examples/mliappy/in.mliap.pytorch.Ta06A @@ -0,0 +1,67 @@ +# Demonstrate MLIAP interface to kinear SNAP potential + +# Initialize simulation + +variable nsteps index 100 +variable nrep equal 4 +variable a equal 3.316 +units metal + +# generate the box and atom positions using a BCC lattice + +variable nx equal ${nrep} +variable ny equal ${nrep} +variable nz equal ${nrep} + +boundary p p p + +lattice bcc $a +region box block 0 ${nx} 0 ${ny} 0 ${nz} +create_box 1 box +create_atoms 1 box + +mass 1 180.88 + +python simple here """ +from __future__ import print_function + +def simple(): + foo = 0 + print("Inside simple function") + try: + foo += 1 + except Exception as e: + print("FOO error:", e) +""" + +python simple invoke + +# choose potential + +include Ta06A.mliap.pytorch + +# Setup output + +compute eatom all pe/atom +compute energy all reduce sum c_eatom + +compute satom all stress/atom NULL +compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] +variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + +thermo_style custom step temp epair c_energy etotal press v_press +thermo 10 +thermo_modify norm yes + +# Set up NVE run + +timestep 0.5e-3 +neighbor 1.0 bin +neigh_modify once no every 1 delay 0 check yes + +# Run MD + +velocity all create 300.0 4928459 loop geom +fix 1 all nve +run ${nsteps} + diff --git a/src/MLIAP/compute_mliap.cpp b/src/MLIAP/compute_mliap.cpp index 34d086462f..64753fe64f 100644 --- a/src/MLIAP/compute_mliap.cpp +++ b/src/MLIAP/compute_mliap.cpp @@ -17,6 +17,10 @@ #include "mliap_model_linear.h" #include "mliap_model_quadratic.h" #include "mliap_descriptor_snap.h" +#ifdef LMP_MLIAPPY +#include "mliap_model_python.h" +#endif + #include "compute_mliap.h" #include "atom.h" #include "update.h" @@ -65,7 +69,14 @@ ComputeMLIAP::ComputeMLIAP(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg+1],"quadratic") == 0) { model = new MLIAPModelQuadratic(lmp); iarg += 2; - } else error->all(FLERR,"Illegal compute mliap command"); + } + #ifdef LMP_MLIAPPY + else if (strcmp(arg[iarg+1],"mliappy") == 0) { + model = new MLIAPModelPython(lmp); + iarg += 2; + } + #endif + else error->all(FLERR,"Illegal compute mliap command"); modelflag = 1; } else if (strcmp(arg[iarg],"descriptor") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute mliap command"); diff --git a/src/MLIAP/mliap_model.cpp b/src/MLIAP/mliap_model.cpp index 04b2ac663a..a4f5cdc86c 100644 --- a/src/MLIAP/mliap_model.cpp +++ b/src/MLIAP/mliap_model.cpp @@ -28,13 +28,9 @@ using namespace LAMMPS_NS; MLIAPModel::MLIAPModel(LAMMPS* lmp, char* coefffilename) : Pointers(lmp) { - coeffelem = nullptr; - if (coefffilename) read_coeffs(coefffilename); - else { - nparams = 0; - nelements = 0; - ndescriptors = 0; - } + nparams = 0; + nelements = 0; + ndescriptors = 0; nonlinearflag = 0; } @@ -42,9 +38,9 @@ MLIAPModel::MLIAPModel(LAMMPS* lmp, char* coefffilename) : Pointers(lmp) MLIAPModel::~MLIAPModel() { - memory->destroy(coeffelem); } + /* ---------------------------------------------------------------------- placeholder ------------------------------------------------------------------------- */ @@ -73,7 +69,22 @@ void MLIAPModel::set_ndescriptors(int ndescriptors_in) /* ---------------------------------------------------------------------- */ -void MLIAPModel::read_coeffs(char *coefffilename) + +MLIAPModelSimple::MLIAPModelSimple(LAMMPS* lmp, char* coefffilename) : MLIAPModel(lmp, coefffilename) +{ + coeffelem = nullptr; + if (coefffilename) read_coeffs(coefffilename); +} + +/* ---------------------------------------------------------------------- */ + +MLIAPModelSimple::~MLIAPModelSimple() +{ + memory->destroy(coeffelem); +} + + +void MLIAPModelSimple::read_coeffs(char *coefffilename) { // open coefficient file on proc 0 @@ -165,7 +176,7 @@ void MLIAPModel::read_coeffs(char *coefffilename) memory usage ------------------------------------------------------------------------- */ -double MLIAPModel::memory_usage() +double MLIAPModelSimple::memory_usage() { double bytes = 0; diff --git a/src/MLIAP/mliap_model.h b/src/MLIAP/mliap_model.h index b2f7312897..96cfff0a3d 100644 --- a/src/MLIAP/mliap_model.h +++ b/src/MLIAP/mliap_model.h @@ -30,15 +30,26 @@ public: virtual void compute_gradgrads(class MLIAPData*)=0; virtual void compute_force_gradients(class MLIAPData*)=0; virtual void init(); - virtual double memory_usage(); + virtual double memory_usage()=0; int nelements; // # of unique elements - int nonlinearflag; // 1 if gradient() requires escriptors + int nonlinearflag; // 1 if gradient() requires descriptors int ndescriptors; // number of descriptors int nparams; // number of parameters per element protected: - void read_coeffs(char *); + virtual void read_coeffs(char *)=0; +}; + +class MLIAPModelSimple : public MLIAPModel { +public: + MLIAPModelSimple(LAMMPS*, char*); + ~MLIAPModelSimple(); + virtual double memory_usage(); + +protected: double **coeffelem; // element coefficients + virtual void read_coeffs(char *); + }; } diff --git a/src/MLIAP/mliap_model_linear.cpp b/src/MLIAP/mliap_model_linear.cpp index d3c8373708..428d163166 100644 --- a/src/MLIAP/mliap_model_linear.cpp +++ b/src/MLIAP/mliap_model_linear.cpp @@ -21,7 +21,7 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ MLIAPModelLinear::MLIAPModelLinear(LAMMPS* lmp, char* coefffilename) : - MLIAPModel(lmp, coefffilename) + MLIAPModelSimple(lmp, coefffilename) { if (nparams > 0) ndescriptors = nparams - 1; } diff --git a/src/MLIAP/mliap_model_linear.h b/src/MLIAP/mliap_model_linear.h index 326407faa8..89c69d3537 100644 --- a/src/MLIAP/mliap_model_linear.h +++ b/src/MLIAP/mliap_model_linear.h @@ -18,7 +18,7 @@ namespace LAMMPS_NS { -class MLIAPModelLinear : public MLIAPModel { +class MLIAPModelLinear : public MLIAPModelSimple { public: MLIAPModelLinear(LAMMPS*, char* = nullptr); ~MLIAPModelLinear(); diff --git a/src/MLIAP/mliap_model_quadratic.cpp b/src/MLIAP/mliap_model_quadratic.cpp index 36642c1a87..222f6ad0ae 100644 --- a/src/MLIAP/mliap_model_quadratic.cpp +++ b/src/MLIAP/mliap_model_quadratic.cpp @@ -22,8 +22,9 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ MLIAPModelQuadratic::MLIAPModelQuadratic(LAMMPS* lmp, char* coefffilename) : - MLIAPModel(lmp, coefffilename) + MLIAPModelSimple(lmp, coefffilename) { + if (coefffilename) read_coeffs(coefffilename); if (nparams > 0) ndescriptors = sqrt(2*nparams)-1; nonlinearflag = 1; } diff --git a/src/MLIAP/mliap_model_quadratic.h b/src/MLIAP/mliap_model_quadratic.h index b41df18a07..28f1732f9b 100644 --- a/src/MLIAP/mliap_model_quadratic.h +++ b/src/MLIAP/mliap_model_quadratic.h @@ -18,7 +18,7 @@ namespace LAMMPS_NS { -class MLIAPModelQuadratic : public MLIAPModel { +class MLIAPModelQuadratic : public MLIAPModelSimple { public: MLIAPModelQuadratic(LAMMPS*, char* = nullptr); ~MLIAPModelQuadratic(); diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index ef3ff40da5..9fd7b483af 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -17,6 +17,9 @@ #include "mliap_model_linear.h" #include "mliap_model_quadratic.h" #include "mliap_descriptor_snap.h" +#ifdef LMP_MLIAPPY +#include "mliap_model_python.h" +#endif #include "atom.h" #include "error.h" @@ -27,6 +30,7 @@ #include #include +#include "error.h" using namespace LAMMPS_NS; @@ -109,6 +113,7 @@ void PairMLIAP::allocate() void PairMLIAP::settings(int narg, char ** arg) { + if (narg < 4) error->all(FLERR,"Illegal pair_style command"); @@ -132,6 +137,13 @@ void PairMLIAP::settings(int narg, char ** arg) if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); model = new MLIAPModelQuadratic(lmp,arg[iarg+2]); iarg += 3; + } + #ifdef LMP_MLIAPPY + else if (strcmp(arg[iarg+1],"mliappy") == 0) { + if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); + model = new MLIAPModelPython(lmp,arg[iarg+2]); + iarg += 3; + #endif } else error->all(FLERR,"Illegal pair_style mliap command"); modelflag = 1; } else if (strcmp(arg[iarg],"descriptor") == 0) { @@ -215,10 +227,13 @@ void PairMLIAP::coeff(int narg, char **arg) // consistency checks - if (data->ndescriptors != model->ndescriptors) - error->all(FLERR,"Incompatible model and descriptor definitions"); - if (data->nelements != model->nelements) - error->all(FLERR,"Incompatible model and descriptor definitions"); + if (data->ndescriptors != model->ndescriptors) { + error->all(FLERR,"Incompatible model and descriptor definitions (different number of descriptors)"); + }; + + if (data->nelements != model->nelements) { + error->all(FLERR,"Incompatible model and descriptor definitions (different number of elements)"); + }; } /* ---------------------------------------------------------------------- diff --git a/src/MLIAPPY/mliap_model_python.cpp b/src/MLIAPPY/mliap_model_python.cpp new file mode 100644 index 0000000000..13e5a85e83 --- /dev/null +++ b/src/MLIAPPY/mliap_model_python.cpp @@ -0,0 +1,163 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#include +#include "mliap_model_python.h" +#include "mliap_model_python_couple.h" +#include "pair_mliap.h" +#include "mliap_data.h" +#include "error.h" +#include "utils.h" +#include "lmppython.h" +#include "python_compat.h" + + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +MLIAPModelPython::MLIAPModelPython(LAMMPS* lmp, char* coefffilename) : + MLIAPModel(lmp, coefffilename) +{ + int err; + + python->init(); + + PyGILState_STATE gstate = PyGILState_Ensure(); + + PyObject * pyMain = PyImport_AddModule("__main__"); + + PyImport_ImportModule("mliap_model_python_couple"); + if (!pyMain) { + PyGILState_Release(gstate); + error->all(FLERR,"Could not initialize embedded Python"); + } + + PyObject* coupling_module = PyImport_ImportModule("mliap_model_python_couple"); + if (!coupling_module) { + PyErr_Print(); + PyErr_Clear(); + PyGILState_Release(gstate); + error->all(FLERR,"Loading MLIAPPY coupling module failure."); + } + + // Recipe from lammps/src/pair_python.cpp : + // add current directory to PYTHONPATH + PyObject * py_path = PySys_GetObject((char *)"path"); + PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + + // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well + const char * potentials_path = getenv("LAMMPS_POTENTIALS"); + if (potentials_path != NULL) { + PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); + } + + PyGILState_Release(gstate); + + if (coefffilename) read_coeffs(coefffilename); + + nonlinearflag=1; +} + +/* ---------------------------------------------------------------------- */ + +MLIAPModelPython::~MLIAPModelPython(){ + MLIAPPY_unload_model(this); +} + +/* ---------------------------------------------------------------------- + get number of parameters + ---------------------------------------------------------------------- */ + + +int MLIAPModelPython::get_nparams() +{ + if (nparams == 0) { + if (ndescriptors == 0) error->all(FLERR,"ndescriptors not defined"); + else nparams = ndescriptors + 1; + } + return nparams; +} + + +void MLIAPModelPython::read_coeffs(char * fname) +{ + PyGILState_STATE gstate = PyGILState_Ensure(); + int err = MLIAPPY_load_model(this, fname); + if (err) { + PyErr_Print(); + PyErr_Clear(); + PyGILState_Release(gstate); + error->all(FLERR,"Loading python model failure."); + } + nelements = MLIAPPY_nelements(this); + nparams = MLIAPPY_nparams(this); + ndescriptors = MLIAPPY_ndescriptors(this); +} + +/* ---------------------------------------------------------------------- + Calculate model gradients w.r.t descriptors + for each atom beta_i = dE(B_i)/dB_i + ---------------------------------------------------------------------- */ + +void MLIAPModelPython::compute_gradients(MLIAPData* data) +{ + MLIAPPY_model_callback(this, data); +} + +/* ---------------------------------------------------------------------- + Calculate model double gradients w.r.t descriptors and parameters + for each atom energy gamma_lk = d2E(B)/dB_k/dsigma_l, + where sigma_l is a parameter, B_k a descriptor, + and atom subscript i is omitted + + gamma is in CSR format: + nnz = number of non-zero values + gamma_row_index[inz] = l indices, 0 <= l < nparams + gamma_col_indexiinz] = k indices, 0 <= k < ndescriptors + gamma[i][inz] = non-zero values, 0 <= inz < nnz + + egradient is derivative of energy w.r.t. parameters + ---------------------------------------------------------------------- */ + +void MLIAPModelPython::compute_gradgrads(class MLIAPData* data) +{ + error->all(FLERR,"compute_gradgrads not implemented"); +} + +/* ---------------------------------------------------------------------- + calculate gradients of forces w.r.t. parameters + egradient is derivative of energy w.r.t. parameters + ---------------------------------------------------------------------- */ + +void MLIAPModelPython::compute_force_gradients(class MLIAPData* data) +{ + error->all(FLERR,"compute_force_gradients not implemented"); +} + +/* ---------------------------------------------------------------------- + count the number of non-zero entries in gamma matrix + ---------------------------------------------------------------------- */ + +int MLIAPModelPython::get_gamma_nnz(class MLIAPData* data) +{ + // todo: get_gamma_nnz + return 0; +} + + +double MLIAPModelPython::memory_usage() +{ + // todo: get approximate memory usage in coupling code. + return 0; +} diff --git a/src/MLIAPPY/mliap_model_python.h b/src/MLIAPPY/mliap_model_python.h new file mode 100644 index 0000000000..3b162509f7 --- /dev/null +++ b/src/MLIAPPY/mliap_model_python.h @@ -0,0 +1,42 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifndef LMP_MLIAP_MODEL_PYTHON_H +#define LMP_MLIAP_MODEL_PYTHON_H + +#include "mliap_model.h" + +namespace LAMMPS_NS { + + +class MLIAPModelPython : public MLIAPModel { +public: + MLIAPModelPython(LAMMPS*, char* = NULL); + ~MLIAPModelPython(); + virtual int get_nparams(); + virtual int get_gamma_nnz(class MLIAPData*); + virtual void compute_gradients(class MLIAPData*); + virtual void compute_gradgrads(class MLIAPData*); + virtual void compute_force_gradients(class MLIAPData*); + virtual double memory_usage(); +protected: + virtual void read_coeffs(char *); + +private: + +}; + +} + +#endif + diff --git a/src/MLIAPPY/mliap_model_python_couple.pyx b/src/MLIAPPY/mliap_model_python_couple.pyx new file mode 100644 index 0000000000..3e03247fa7 --- /dev/null +++ b/src/MLIAPPY/mliap_model_python_couple.pyx @@ -0,0 +1,85 @@ +# cython: language_level=3 +# distutils: language = c++ + +cimport cython + +import pickle + +# For converting C arrays to numpy arrays +import numpy as np +cimport numpy as cnp + +# For converting void * to integer for tracking object identity +from libc.stdint cimport uintptr_t + +from libcpp.string cimport string + + +cdef extern from "mliap_data.h" namespace "LAMMPS_NS": + cdef cppclass MLIAPData: + # Array shapes + int natoms + int ndescriptors + + # Input data + int * ielems # types for all atoms in list + double ** descriptors # descriptors for all atoms in list + + # Output data to write to + double ** betas # betas for all atoms in list + double * eatoms # energy for all atoms in list + double energy + +cdef extern from "mliap_model_python.h" namespace "LAMMPS_NS": + cdef cppclass MLIAPModelPython: + ctypedef void (*CBPtr)(void * , MLIAPData); + void set_model(CBPtr, void *); + + +LOADED_MODELS = {} +cdef public int MLIAPPY_load_model(MLIAPModelPython * c_model, char* fname) except 1 with gil: + str_fname = fname.decode('utf-8') # Python 3 only; not Python 2 not supported. + + with open(str_fname,'rb') as pfile: + model = pickle.load(pfile) + + LOADED_MODELS[int( c_model)] = model + return 0 + +cdef public void MLIAPPY_unload_model(MLIAPModelPython * c_model) with gil: + del LOADED_MODELS[int( c_model)] + +cdef public int MLIAPPY_nparams(MLIAPModelPython * c_model) with gil: + model = LOADED_MODELS[int( c_model)] + n_params = int(model.n_params) + return n_params + +cdef public int MLIAPPY_nelements(MLIAPModelPython * c_model) with gil: + model = LOADED_MODELS[int( c_model)] + n_elements = int(model.n_elements) + return n_elements + +cdef public int MLIAPPY_ndescriptors(MLIAPModelPython * c_model) with gil: + model = LOADED_MODELS[int( c_model)] + n_descriptors = int(model.n_descriptors) + return n_descriptors + +cdef public MLIAPPY_model_callback(MLIAPModelPython * c_model, MLIAPData * data) with gil: + model = LOADED_MODELS[int( c_model)] + + n_d = data.ndescriptors + n_a = data.natoms + + # Make numpy arrays from pointers + beta_np = np.asarray( &data.betas[0][0]) + desc_np = np.asarray( &data.descriptors[0][0]) + type_np = np.asarray( &data.ielems[0]) + en_np = np.asarray( &data.eatoms[0]) + + # Invoke python model on numpy arrays. + model(type_np,desc_np,beta_np,en_np) + + # Get the total energy from the atom energy. + energy = np.sum(en_np) + data.energy = energy + return diff --git a/src/MLIAPPY/mliappy_pytorch.py b/src/MLIAPPY/mliappy_pytorch.py new file mode 100644 index 0000000000..b9f7ac3dcc --- /dev/null +++ b/src/MLIAPPY/mliappy_pytorch.py @@ -0,0 +1,46 @@ +import numpy as np +import torch + +def calc_n_params(model): + return sum(p.nelement() for p in model.parameters()) + +class TorchWrapper(torch.nn.Module): + def __init__(self, model,n_descriptors,n_elements,n_params=None): + super().__init__() + self.model = model + self.model.to(self.dtype) + if n_params is None: + n_params = calc_n_params(model) + self.n_params = n_params + self.n_descriptors = n_descriptors + self.n_elements = n_elements + + def __call__(self, types, bispectrum, beta, energy): + + bispectrum = torch.from_numpy(bispectrum).to(self.dtype).requires_grad_(True) + types = torch.from_numpy(types).to(torch.long) - 1 + + with torch.autograd.enable_grad(): + + energy_nn = self.model(bispectrum, types) + if energy_nn.ndim > 1: + energy_nn = energy_nn.flatten() + + beta_nn = torch.autograd.grad(energy_nn.sum(), bispectrum)[0] + + beta[:] = beta_nn.detach().cpu().numpy().astype(np.float64) + energy[:] = energy_nn.detach().cpu().numpy().astype(np.float64) + +class TorchWrapper32(TorchWrapper): + dtype = torch.float32 + +class TorchWrapper64(TorchWrapper): + dtype = torch.float64 + +class IgnoreTypes(torch.nn.Module): + def __init__(self,subnet): + super().__init__() + self.subnet = subnet + + def forward(self,bispectrum,types): + return self.subnet(bispectrum) diff --git a/src/Makefile b/src/Makefile index 149dedd35b..8667f3f725 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,7 +48,7 @@ endif PACKAGE = asphere body class2 colloid compress coreshell dipole gpu \ granular kim kokkos kspace latte manybody mc message misc \ - mliap molecule mpiio mscg opt peri poems \ + mliap mliappy molecule mpiio mscg opt peri poems \ python qeq replica rigid shock snap spin srd voronoi PACKUSER = user-adios user-atc user-awpmd user-bocs user-cgdna user-cgsdk user-colvars \ diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 22bf8e77fb..9f54822c47 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -26,6 +26,11 @@ #include #include // IWYU pragma: export +#ifdef LMP_MLIAPPY +#include "mliap_model_python.h" +#include "mliap_model_python_couple.h" +#endif + using namespace LAMMPS_NS; enum{NONE,INT,DOUBLE,STRING,PTR}; @@ -51,7 +56,14 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp) // one-time initialization of Python interpreter // pyMain stores pointer to main module external_interpreter = Py_IsInitialized(); - + + #ifdef LMP_MLIAPPY + // Inform python intialization scheme of the mliappy module. + // This -must- happen before python is initialized. + int err = PyImport_AppendInittab("mliap_model_python_couple", PyInit_mliap_model_python_couple); + // todo: catch if error and report problem. + #endif + Py_Initialize(); PyEval_InitThreads(); From 4de5b1b61240ab531b459249b0c4ca6844b03714 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 13 Nov 2020 16:30:05 -0700 Subject: [PATCH 03/39] Added README explaining how to run cythonize --- src/MLIAPPY/README | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/MLIAPPY/README diff --git a/src/MLIAPPY/README b/src/MLIAPPY/README new file mode 100644 index 0000000000..12f162da5a --- /dev/null +++ b/src/MLIAPPY/README @@ -0,0 +1,9 @@ +This package provides a coupling to PyTorch energy models +via the MLIAP package. + +Before compiling LAMMPS with either make or cmake, you have +to run cythoniz to create the coupling source files +in the src/MLIAPPY directory e.g. + +cd MLIAPPY +~/anaconda3/bin/cythonize mliap_model_python_couple.pyx From 0623817afea8a695772b85d3e3dd8c9540c87d28 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 20 Nov 2020 11:47:31 -0700 Subject: [PATCH 04/39] Updated README --- src/MLIAPPY/README | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/MLIAPPY/README b/src/MLIAPPY/README index 12f162da5a..ba15d6eb51 100644 --- a/src/MLIAPPY/README +++ b/src/MLIAPPY/README @@ -2,8 +2,23 @@ This package provides a coupling to PyTorch energy models via the MLIAP package. Before compiling LAMMPS with either make or cmake, you have -to run cythoniz to create the coupling source files +to run cythonize to create the coupling source files in the src/MLIAPPY directory e.g. cd MLIAPPY -~/anaconda3/bin/cythonize mliap_model_python_couple.pyx +cythonize mliap_model_python_couple.pyx + +When building with make, you will have to add this +compiler option, suitably modified for your NumPy: + +-I/home/athomps/anaconda3/lib/python3.7/site-packages/numpy/core/include + +When bulding with cmake, it should just work, but if you have +cmake version older than 3.14, you will have to edit +this file accordingly: +more ../../cmake/Modules/Packages/MLIAPPY.cmake +if(CMAKE_VERSION VERSION_LESS 3.14) +: + target_include_directories(lammps PRIVATE /home/athomps/anaconda3/lib/python3.7/site-packages/numpy/core/include) +: + From 35f2c9bdf2298c33b036e2eab1011b45bf60c2da Mon Sep 17 00:00:00 2001 From: Nicholas Lubbers Date: Thu, 26 Nov 2020 12:40:28 -0700 Subject: [PATCH 05/39] Several improvements to capabilities and build. - cmake fixed, no longer needs numpy headers. - models can be loaded from an external interepreter. --- cmake/Modules/Packages/MLIAPPY.cmake | 13 +-- cmake/Modules/Packages/PYTHON.cmake | 3 +- doc/src/Packages_details.rst | 9 +- examples/mliappy/README | 26 ++++++ examples/mliappy/README.txt | 11 --- examples/mliappy/convert_mliap_Ta06A.py | 4 +- examples/mliappy/in.mliap.pytorch.Ta06A | 2 +- examples/mliappy/load_external.py | 104 ++++++++++++++++++++++ examples/mliappy/test_pylibs.py | 12 +++ python/lammps.py | 42 +++++++++ src/MLIAP/pair_mliap.cpp | 22 ++--- src/MLIAPPY/Makefile.lammps | 1 + src/MLIAPPY/README | 37 ++++++++ src/MLIAPPY/mliap_model_python.cpp | 61 +++++++++---- src/MLIAPPY/mliap_model_python.h | 7 +- src/MLIAPPY/mliap_model_python_couple.pyx | 88 ++++++++++++------ src/MLIAPPY/mliappy_pytorch.py | 10 +-- src/PYTHON/python_impl.cpp | 6 +- 18 files changed, 369 insertions(+), 89 deletions(-) create mode 100644 examples/mliappy/README delete mode 100644 examples/mliappy/README.txt create mode 100644 examples/mliappy/load_external.py create mode 100644 examples/mliappy/test_pylibs.py create mode 100644 src/MLIAPPY/Makefile.lammps create mode 100644 src/MLIAPPY/README diff --git a/cmake/Modules/Packages/MLIAPPY.cmake b/cmake/Modules/Packages/MLIAPPY.cmake index 842c43bd96..73ce83361c 100644 --- a/cmake/Modules/Packages/MLIAPPY.cmake +++ b/cmake/Modules/Packages/MLIAPPY.cmake @@ -1,12 +1,3 @@ -if(CMAKE_VERSION VERSION_LESS 3.12) - #This block was not tested, mimmicks PYTHON.cmake. - find_package(PythonLibs REQUIRED) # Deprecated since version 3.12 - target_include_directories(lammps PRIVATE ${PYTHON_INCLUDE_DIR}) - target_link_libraries(lammps PRIVATE ${PYTHON_LIBRARY}) - target_include_directories(lammps PRIVATE ${Python_NumPy_INCLUDE_DIRS}) -else() - find_package(Python REQUIRED COMPONENTS NumPy) - target_include_directories(lammps PRIVATE ${Python_NumPy_INCLUDE_DIRS}) -endif() -target_compile_definitions(lammps PRIVATE -DLMP_MLIAPPY) +execute_process(COMMAND cythonize mliap_model_python_couple.pyx WORKING_DIRECTORY ../src/MLIAPPY) +target_compile_definitions(lammps PRIVATE -DLMP_MLIAPPY) diff --git a/cmake/Modules/Packages/PYTHON.cmake b/cmake/Modules/Packages/PYTHON.cmake index 7be25a6b05..e3158dc509 100644 --- a/cmake/Modules/Packages/PYTHON.cmake +++ b/cmake/Modules/Packages/PYTHON.cmake @@ -3,7 +3,8 @@ if(CMAKE_VERSION VERSION_LESS 3.12) target_include_directories(lammps PRIVATE ${PYTHON_INCLUDE_DIRS}) target_link_libraries(lammps PRIVATE ${PYTHON_LIBRARIES}) else() - find_package(Python REQUIRED COMPONENTS Development) + find_package(Python REQUIRED COMPONENTS Development Interpreter) + target_include_directories(lammps PRIVATE ${Python_INCLUDE_DIRS}) target_link_libraries(lammps PRIVATE Python::Python) endif() target_compile_definitions(lammps PRIVATE -DLMP_PYTHON) diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index edce17b9ab..7c9e8b8eb8 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -692,12 +692,10 @@ Extension to the MLIAP package for coupling with python models. To use this package, also the :ref:`MLIAP package ` needs to be installed. To use this package, also the :ref:`PYTHON package ` needs to be installed. -The version of python must be >3.5, and has been tested only with 3.8. -Compiling this package has only been tested using CMake, not with pure makefiles.s -The python interpreter linked to LAMMPS will need cython and numpy installed. +The version of python must be >3.5. -Before compiling, run cythonize on /src/MLIAPPY/mliap_model_python_couple.pyx. -This will produce /src/MLIAPPY/mliap_model_python_couple.cpp and /src/MLIAPPY/mliap_model_python_couple.h files. +The python interpreter linked to LAMMPS will need cython and numpy installed. +The examples build models with pytorch, which would thus need to be installed. This package includes more options for the mliap compute and pair style. @@ -706,6 +704,7 @@ This package includes more options for the mliap compute and pair style. **Supporting info:** * src/MLIAPPY: filenames -> commands +* src/MLIAPPY/README * :doc:`pair_style mliap ` * examples/mliappy (see README) ---------- diff --git a/examples/mliappy/README b/examples/mliappy/README new file mode 100644 index 0000000000..d61972afcf --- /dev/null +++ b/examples/mliappy/README @@ -0,0 +1,26 @@ +README for MLIAPPY Example + +These examples run the Ta06 example from the MLIAP package, but using the python coupling. + +1: Running models using LAMMPS executable: in.mliap.snap.Ta06A. + +To run this, first run convert_mliap_Ta06A.py, which will convert the Ta06 potential into a pytorch model. +It will be saved as "Ta06A.mliap.pytorch.model.pkl". + +It will also copy the "mliappy_pytorch.py" file into the current working directory. mliappy_pytorch.py contains +class definitions suitable for wrapping an arbitrary energy model MLIAPPY. It must be available to python when +creating or unpicking a pytorch model for MLIAPPY. + +From that point you can run the example lmp -in in.mliap.snap.Ta06A -echo both + +2: Running models from python with LAMMPS in library mode: load_external.py + +Before testing this, ensure that the first example (using LAMMPS executable) works. + +Not all python installations support this mode of operation. +Too test if your interpreter supports this, run: +`python test_pylibs.py` + and examine the output. + +If this succeeds, you should be able to run: +`python load_external.py` diff --git a/examples/mliappy/README.txt b/examples/mliappy/README.txt deleted file mode 100644 index f624acd657..0000000000 --- a/examples/mliappy/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -README for MLIAPPY Example - -This example runs the Ta06 example from the MLIAP example, but using the python coupling. - -To run this, first run convert_mliap_Ta06A.py, which will convert the Ta06 potential into a pytorch model. -It will be saved as "Ta06A.mliap.pytorch.model.pkl". - -It will also copy the "torchlink.py" file into the current working directory. torchlink.py contains -class definitions suitable for wrapping an arbitrary energy model MLIAPPY. - -From that point you can run the example lmp -in in.mliap.snap.Ta06A -echo both \ No newline at end of file diff --git a/examples/mliappy/convert_mliap_Ta06A.py b/examples/mliappy/convert_mliap_Ta06A.py index bdc3887282..371139481d 100644 --- a/examples/mliappy/convert_mliap_Ta06A.py +++ b/examples/mliappy/convert_mliap_Ta06A.py @@ -22,7 +22,7 @@ with torch.autograd.no_grad(): lin.bias.set_(torch.as_tensor(bias,dtype=torch.float64).unsqueeze(0)) # Wrap the pytorch model for usage with MLIAPPY -model = mliappy_pytorch.IgnoreTypes(lin) +model = mliappy_pytorch.IgnoreElems(lin) n_descriptors = lin.weight.shape[1] n_params = mliappy_pytorch.calc_n_params(model) n_types = 1 @@ -30,4 +30,4 @@ linked_model = mliappy_pytorch.TorchWrapper64(model,n_descriptors=n_descriptors, # Save the result. with open("Ta06A.mliap.pytorch.model.pkl",'wb') as pfile: - pickle.dump(linked_model,pfile) \ No newline at end of file + pickle.dump(linked_model,pfile) diff --git a/examples/mliappy/in.mliap.pytorch.Ta06A b/examples/mliappy/in.mliap.pytorch.Ta06A index 526c24ab23..e44b4352e7 100644 --- a/examples/mliappy/in.mliap.pytorch.Ta06A +++ b/examples/mliappy/in.mliap.pytorch.Ta06A @@ -1,4 +1,4 @@ -# Demonstrate MLIAP interface to kinear SNAP potential +# Demonstrate MLIAP interface to linear SNAP potential # Initialize simulation diff --git a/examples/mliappy/load_external.py b/examples/mliappy/load_external.py new file mode 100644 index 0000000000..606ee8f940 --- /dev/null +++ b/examples/mliappy/load_external.py @@ -0,0 +1,104 @@ + +# Demonstrate how to load a model from the python side. +# This is essentially the same as in.mliap.pytorch.Ta06A-- +# except that python is the driving program, and lammps +# is in library mode. + +before_loading =\ +""" + # Demonstrate MLIAP interface to linear SNAP potential + + # Initialize simulation + + variable nsteps index 100 + variable nrep equal 4 + variable a equal 3.316 + units metal + + # generate the box and atom positions using a BCC lattice + + variable nx equal ${nrep} + variable ny equal ${nrep} + variable nz equal ${nrep} + + boundary p p p + + lattice bcc $a + region box block 0 ${nx} 0 ${ny} 0 ${nz} + create_box 1 box + create_atoms 1 box + + mass 1 180.88 + + # choose potential + # DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + + # Definition of SNAP potential Ta_Cand06A + # Assumes 1 LAMMPS atom type + + variable zblcutinner equal 4 + variable zblcutouter equal 4.8 + variable zblz equal 73 + + # Specify hybrid with SNAP, ZBL + + pair_style hybrid/overlay & + zbl ${zblcutinner} ${zblcutouter} & + mliap model mliappy LATER & + descriptor sna Ta06A.mliap.descriptor + pair_coeff 1 1 zbl ${zblz} ${zblz} + pair_coeff * * mliap Ta +""" +after_loading =\ +""" + + # Setup output + + compute eatom all pe/atom + compute energy all reduce sum c_eatom + + compute satom all stress/atom NULL + compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] + variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + + thermo_style custom step temp epair c_energy etotal press v_press + thermo 10 + thermo_modify norm yes + + # Set up NVE run + + timestep 0.5e-3 + neighbor 1.0 bin + neigh_modify once no every 1 delay 0 check yes + + # Run MD + + velocity all create 300.0 4928459 loop geom + fix 1 all nve + run ${nsteps} +""" + + +import lammps + +lmp = lammps.lammps(cmdargs=['-echo','both']) +# This commmand must be run before the MLIAP object is declared in lammps. +lmp.mliappy.activate() + +lmp.commands_string(before_loading) + +# Now the model is declared, but empty -- because the model filename +# was given as "LATER". + +# Load the python module, construct on the fly, do whatever, here: +import pickle +with open('Ta06A.mliap.pytorch.model.pkl','rb') as pfile: + model = pickle.load(pfile) + +# Now that you have a model, connect it to the pairstyle +lmp.mliappy.load_model(model) + +# Proceed with whatever calculations you like. +lmp.commands_string(after_loading) + + diff --git a/examples/mliappy/test_pylibs.py b/examples/mliappy/test_pylibs.py new file mode 100644 index 0000000000..c5dcab75cf --- /dev/null +++ b/examples/mliappy/test_pylibs.py @@ -0,0 +1,12 @@ +import sysconfig, os,ctypes + +library = sysconfig.get_config_vars('INSTSONAME')[0] + +pylib = ctypes.CDLL(library) + +connected = pylib.Py_IsInitialized() + +if not connected: + print("FAILURE: This interpreter is not compatible with python-driven mliappy.") +else: + print("SUCCESS: This interpreter is compatible with python-driven MLIAPPY") diff --git a/python/lammps.py b/python/lammps.py index 4be2f48b0d..df37e50ee1 100644 --- a/python/lammps.py +++ b/python/lammps.py @@ -505,6 +505,8 @@ class lammps(object): self.FIX_EXTERNAL_CALLBACK_FUNC = CFUNCTYPE(None, py_object, self.c_bigint, c_int, POINTER(self.c_tagint), POINTER(POINTER(c_double)), POINTER(POINTER(c_double))) self.lib.lammps_set_fix_external_callback.argtypes = [c_void_p, c_char_p, self.FIX_EXTERNAL_CALLBACK_FUNC, py_object] self.lib.lammps_set_fix_external_callback.restype = None + + self.mliappy = MLIAPPY(self) # ------------------------------------------------------------------------- # shut-down LAMMPS instance @@ -2924,3 +2926,43 @@ class IPyLammps(PyLammps): """ from IPython.display import HTML return HTML("") + +class MLIAPPY(): + def __init__(self,lammps): + self._module = None + self.lammps = lammps + + @property + def module(self): + if self._module: + return self._module + + try: + # Begin Importlib magic to find the embedded python module + # This is needed because the filename for liblammps does not + # match the spec for normal python modules, wherein + # file names match with PyInit function names. + # Also, python normally doesn't look for extensions besides '.so' + # We fix both of these problems by providing an explict + # path to the extension module 'mliap_model_python_couple' in + import sys + import importlib.util + import importlib.machinery + + path = self.lammps.lib._name + loader = importlib.machinery.ExtensionFileLoader('mliap_model_python_couple',path) + spec = importlib.util.spec_from_loader('mliap_model_python_couple',loader) + module = importlib.util.module_from_spec(spec) + sys.modules['mliap_model_python_couple']=module + spec.loader.exec_module(module) + self._module = module + # End Importlib magic to find the embedded python module + except: + raise ImportError("Could not load MLIAPPY coupling module") + + def activate(self): + self.module + + def load_model(self,model): + self.module.load_from_python(model) + diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index 9fd7b483af..5dd891e21f 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -69,6 +69,17 @@ PairMLIAP::~PairMLIAP() void PairMLIAP::compute(int eflag, int vflag) { + + // consistency checks + + if (data->ndescriptors != model->ndescriptors) { + error->all(FLERR,"Incompatible model and descriptor descriptor count"); + }; + + if (data->nelements != model->nelements) { + error->all(FLERR,"Incompatible model and descriptor element count"); + }; + ev_init(eflag,vflag); data->generate_neighdata(list, eflag, vflag); @@ -137,9 +148,8 @@ void PairMLIAP::settings(int narg, char ** arg) if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); model = new MLIAPModelQuadratic(lmp,arg[iarg+2]); iarg += 3; - } #ifdef LMP_MLIAPPY - else if (strcmp(arg[iarg+1],"mliappy") == 0) { + } else if (strcmp(arg[iarg+1],"mliappy") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); model = new MLIAPModelPython(lmp,arg[iarg+2]); iarg += 3; @@ -225,15 +235,7 @@ void PairMLIAP::coeff(int narg, char **arg) data = new MLIAPData(lmp, gradgradflag, map, model, descriptor, this); data->init(); - // consistency checks - if (data->ndescriptors != model->ndescriptors) { - error->all(FLERR,"Incompatible model and descriptor definitions (different number of descriptors)"); - }; - - if (data->nelements != model->nelements) { - error->all(FLERR,"Incompatible model and descriptor definitions (different number of elements)"); - }; } /* ---------------------------------------------------------------------- diff --git a/src/MLIAPPY/Makefile.lammps b/src/MLIAPPY/Makefile.lammps new file mode 100644 index 0000000000..f9bf1abc13 --- /dev/null +++ b/src/MLIAPPY/Makefile.lammps @@ -0,0 +1 @@ +#TODO diff --git a/src/MLIAPPY/README b/src/MLIAPPY/README new file mode 100644 index 0000000000..44b454bba1 --- /dev/null +++ b/src/MLIAPPY/README @@ -0,0 +1,37 @@ +README for MLIAPPY source files. + +MLIAPPY requires python 3 with cython, numpy, and optionally pytorch installed. +One could build compatible python models without pytorch, with a bit of work by hand. +You can get these via standard procedures (pip, conda, or similar) + +MLIAPPY also requires the LAMMPS packages MLIAP and PYTHON be enabled. + +MLIAPPY can be built with cmake -- a pure make version is forthcoming. + +If you are building LAMMPS manually (no cmake/make), the process works roughly as possible: + +First run cythonize on mliap_model_python_couple.pyx. This will generate: + +(1) mliap_model_python_couple.h +(2) mliap_model_python_couple.cpp + +File (1) is a roughly human readable header file, (2) is a large source file, +and navigating it is not for the faint of heart. These files are used in mliap_model_python.cpp. + +Then use compiler options to define the macro LMP_MLIAPPY during compilation. + +Other information: + +The "mliap_model_python.cpp" files and "mliap_model_python.h" files cover the +definitions of the LAMMPS object MLIAPModelPython. + +How does this all work? + +Roughly: A python extension module called "mliap_model_python_couple" is built in to LAMMPS. This holds a dictionary of currently defined MLIAPModelPython objects and +the equivalent python models. It also converts the data needed by the model from +C arrays to numpy arrays before passing them to the python model. + +The last file is mliappy_pytorch.py. This contains some simple utility classes +for taking an energy model in pytorch, and wrapping it for compatibily with MLIAP. + +For more information on MLIAPPY, see the examples in examples/mliappy. \ No newline at end of file diff --git a/src/MLIAPPY/mliap_model_python.cpp b/src/MLIAPPY/mliap_model_python.cpp index 13e5a85e83..1ac61f08b0 100644 --- a/src/MLIAPPY/mliap_model_python.cpp +++ b/src/MLIAPPY/mliap_model_python.cpp @@ -29,28 +29,25 @@ using namespace LAMMPS_NS; MLIAPModelPython::MLIAPModelPython(LAMMPS* lmp, char* coefffilename) : MLIAPModel(lmp, coefffilename) { - int err; - + model_loaded = 0; python->init(); - PyGILState_STATE gstate = PyGILState_Ensure(); PyObject * pyMain = PyImport_AddModule("__main__"); - PyImport_ImportModule("mliap_model_python_couple"); if (!pyMain) { PyGILState_Release(gstate); error->all(FLERR,"Could not initialize embedded Python"); } - + PyObject* coupling_module = PyImport_ImportModule("mliap_model_python_couple"); + if (!coupling_module) { PyErr_Print(); PyErr_Clear(); PyGILState_Release(gstate); error->all(FLERR,"Loading MLIAPPY coupling module failure."); } - // Recipe from lammps/src/pair_python.cpp : // add current directory to PYTHONPATH PyObject * py_path = PySys_GetObject((char *)"path"); @@ -61,7 +58,6 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS* lmp, char* coefffilename) : if (potentials_path != NULL) { PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); } - PyGILState_Release(gstate); if (coefffilename) read_coeffs(coefffilename); @@ -82,29 +78,51 @@ MLIAPModelPython::~MLIAPModelPython(){ int MLIAPModelPython::get_nparams() { - if (nparams == 0) { - if (ndescriptors == 0) error->all(FLERR,"ndescriptors not defined"); - else nparams = ndescriptors + 1; - } return nparams; } - void MLIAPModelPython::read_coeffs(char * fname) { PyGILState_STATE gstate = PyGILState_Ensure(); - int err = MLIAPPY_load_model(this, fname); - if (err) { + + int loaded = MLIAPPY_load_model(this, fname); + if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); PyGILState_Release(gstate); error->all(FLERR,"Loading python model failure."); } + PyGILState_Release(gstate); + + if (loaded) { + this->connect_param_counts(); + } + else { + utils::logmesg(lmp,"Loading python model deferred.\n"); + } +} + +// Finalize loading of the model. +void MLIAPModelPython::connect_param_counts() +{ + PyGILState_STATE gstate = PyGILState_Ensure(); nelements = MLIAPPY_nelements(this); nparams = MLIAPPY_nparams(this); ndescriptors = MLIAPPY_ndescriptors(this); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + PyGILState_Release(gstate); + error->all(FLERR,"Loading python model failure."); + } + PyGILState_Release(gstate); + model_loaded = 1; + utils::logmesg(lmp,"Loading python model complete.\n"); + } + /* ---------------------------------------------------------------------- Calculate model gradients w.r.t descriptors for each atom beta_i = dE(B_i)/dB_i @@ -112,7 +130,20 @@ void MLIAPModelPython::read_coeffs(char * fname) void MLIAPModelPython::compute_gradients(MLIAPData* data) { - MLIAPPY_model_callback(this, data); + if (not model_loaded) { + error->all(FLERR,"Model not loaded."); + } + + PyGILState_STATE gstate = PyGILState_Ensure(); + MLIAPPY_compute_gradients(this, data); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + PyGILState_Release(gstate); + error->all(FLERR,"Running python model failure."); + } + PyGILState_Release(gstate); + } /* ---------------------------------------------------------------------- diff --git a/src/MLIAPPY/mliap_model_python.h b/src/MLIAPPY/mliap_model_python.h index 3b162509f7..0ef87f86fd 100644 --- a/src/MLIAPPY/mliap_model_python.h +++ b/src/MLIAPPY/mliap_model_python.h @@ -29,9 +29,14 @@ public: virtual void compute_gradgrads(class MLIAPData*); virtual void compute_force_gradients(class MLIAPData*); virtual double memory_usage(); + void connect_param_counts(); // If possible convert this to protected/private and + // and figure out how to declare cython fn + // load_from_python as a friend. + int model_loaded; + protected: virtual void read_coeffs(char *); - + private: }; diff --git a/src/MLIAPPY/mliap_model_python_couple.pyx b/src/MLIAPPY/mliap_model_python_couple.pyx index 3e03247fa7..ad95ea2c48 100644 --- a/src/MLIAPPY/mliap_model_python_couple.pyx +++ b/src/MLIAPPY/mliap_model_python_couple.pyx @@ -1,5 +1,12 @@ # cython: language_level=3 # distutils: language = c++ +# distutils: define_macros="LMP_MLIAPPY" +# distutils: extra_compile_args= -stdlib=libc++ -std=c++11 +# distutils: include_dirs = ../STUBS .. ../MLIAP +# distutils: extra_link_args= -stdlib=libc++ +# Note: only the language_level and language commands are needed, the rest pertain +# to building mliap_model_python_couple as a standalone python extension, which +# is experimental. cimport cython @@ -7,7 +14,6 @@ import pickle # For converting C arrays to numpy arrays import numpy as np -cimport numpy as cnp # For converting void * to integer for tracking object identity from libc.stdint cimport uintptr_t @@ -32,40 +38,72 @@ cdef extern from "mliap_data.h" namespace "LAMMPS_NS": cdef extern from "mliap_model_python.h" namespace "LAMMPS_NS": cdef cppclass MLIAPModelPython: - ctypedef void (*CBPtr)(void * , MLIAPData); - void set_model(CBPtr, void *); - + void connect_param_counts() + + +class MLIAPPYModelNotLinked(Exception): pass + LOADED_MODELS = {} -cdef public int MLIAPPY_load_model(MLIAPModelPython * c_model, char* fname) except 1 with gil: - str_fname = fname.decode('utf-8') # Python 3 only; not Python 2 not supported. - - with open(str_fname,'rb') as pfile: - model = pickle.load(pfile) - LOADED_MODELS[int( c_model)] = model - return 0 +cdef object c_id(MLIAPModelPython * c_model): + """ + Use python-style id of object to keep track of identity. + Note, this is probably not a perfect general strategy but it should work fine with LAMMPS pair styles. + """ + return int( c_model) + +cdef object retrieve(MLIAPModelPython * c_model): + try: + model = LOADED_MODELS[c_id(c_model)] + except KeyError as ke: + raise KeyError("Model has not been loaded.") from ke + if model is None: + raise MLIAPPYModelNotLinked("Model not linked, connect the model from the python side.") + return model + +cdef public int MLIAPPY_load_model(MLIAPModelPython * c_model, char* fname) with gil: + str_fname = fname.decode('utf-8') # Python 3 only; not Python 2 not supported. + if str_fname == "LATER": + model = None + returnval = 0 + else: + with open(str_fname,'rb') as pfile: + model = pickle.load(pfile) + returnval = 1 + LOADED_MODELS[c_id(c_model)] = model + return returnval + +def load_from_python(model): + unloaded_models = [k for k, v in LOADED_MODELS.items() if v is None] + num_models = len(unloaded_models) + cdef MLIAPModelPython * lmp_model + + if num_models == 0: + raise ValueError("No model in the waiting area.") + elif num_models > 1: + raise ValueError("Model is amibguous, more than one model in waiting area.") + else: + c_id = unloaded_models[0] + LOADED_MODELS[c_id]=model + lmp_model = c_id + lmp_model.connect_param_counts() + cdef public void MLIAPPY_unload_model(MLIAPModelPython * c_model) with gil: - del LOADED_MODELS[int( c_model)] + del LOADED_MODELS[c_id(c_model)] cdef public int MLIAPPY_nparams(MLIAPModelPython * c_model) with gil: - model = LOADED_MODELS[int( c_model)] - n_params = int(model.n_params) - return n_params + return int(retrieve(c_model).n_params) cdef public int MLIAPPY_nelements(MLIAPModelPython * c_model) with gil: - model = LOADED_MODELS[int( c_model)] - n_elements = int(model.n_elements) - return n_elements + return int(retrieve(c_model).n_elements) cdef public int MLIAPPY_ndescriptors(MLIAPModelPython * c_model) with gil: - model = LOADED_MODELS[int( c_model)] - n_descriptors = int(model.n_descriptors) - return n_descriptors + return int(retrieve(c_model).n_descriptors) -cdef public MLIAPPY_model_callback(MLIAPModelPython * c_model, MLIAPData * data) with gil: - model = LOADED_MODELS[int( c_model)] +cdef public void MLIAPPY_compute_gradients(MLIAPModelPython * c_model, MLIAPData * data) with gil: + model = retrieve(c_model) n_d = data.ndescriptors n_a = data.natoms @@ -73,11 +111,11 @@ cdef public MLIAPPY_model_callback(MLIAPModelPython * c_model, MLIAPData * data) # Make numpy arrays from pointers beta_np = np.asarray( &data.betas[0][0]) desc_np = np.asarray( &data.descriptors[0][0]) - type_np = np.asarray( &data.ielems[0]) + elem_np = np.asarray( &data.ielems[0]) en_np = np.asarray( &data.eatoms[0]) # Invoke python model on numpy arrays. - model(type_np,desc_np,beta_np,en_np) + model(elem_np,desc_np,beta_np,en_np) # Get the total energy from the atom energy. energy = np.sum(en_np) diff --git a/src/MLIAPPY/mliappy_pytorch.py b/src/MLIAPPY/mliappy_pytorch.py index b9f7ac3dcc..5294344c10 100644 --- a/src/MLIAPPY/mliappy_pytorch.py +++ b/src/MLIAPPY/mliappy_pytorch.py @@ -15,14 +15,14 @@ class TorchWrapper(torch.nn.Module): self.n_descriptors = n_descriptors self.n_elements = n_elements - def __call__(self, types, bispectrum, beta, energy): + def __call__(self, elems, bispectrum, beta, energy): bispectrum = torch.from_numpy(bispectrum).to(self.dtype).requires_grad_(True) - types = torch.from_numpy(types).to(torch.long) - 1 + elems = torch.from_numpy(elems).to(torch.long) - 1 with torch.autograd.enable_grad(): - energy_nn = self.model(bispectrum, types) + energy_nn = self.model(bispectrum, elems) if energy_nn.ndim > 1: energy_nn = energy_nn.flatten() @@ -37,10 +37,10 @@ class TorchWrapper32(TorchWrapper): class TorchWrapper64(TorchWrapper): dtype = torch.float64 -class IgnoreTypes(torch.nn.Module): +class IgnoreElems(torch.nn.Module): def __init__(self,subnet): super().__init__() self.subnet = subnet - def forward(self,bispectrum,types): + def forward(self,bispectrum,elems): return self.subnet(bispectrum) diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 9f54822c47..62f19d0f12 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -28,6 +28,9 @@ #ifdef LMP_MLIAPPY #include "mliap_model_python.h" +// The above should somehow really be included in the next file. +// We could get around this with cython --capi-reexport-cincludes +// However, that exposes -too many- headers. #include "mliap_model_python_couple.h" #endif @@ -52,7 +55,6 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp) nfunc = 0; pfuncs = nullptr; - // one-time initialization of Python interpreter // pyMain stores pointer to main module external_interpreter = Py_IsInitialized(); @@ -61,7 +63,7 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp) // Inform python intialization scheme of the mliappy module. // This -must- happen before python is initialized. int err = PyImport_AppendInittab("mliap_model_python_couple", PyInit_mliap_model_python_couple); - // todo: catch if error and report problem. + if (err) error->all(FLERR,"Could not register MLIAPPY embedded python module."); #endif Py_Initialize(); From 97b77e0f138413162b3d51a6e784ad28517f91eb Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Mon, 30 Nov 2020 19:29:28 -0700 Subject: [PATCH 06/39] Added preprocessor flag --- src/MLIAPPY/Install.sh | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 src/MLIAPPY/Install.sh diff --git a/src/MLIAPPY/Install.sh b/src/MLIAPPY/Install.sh new file mode 100755 index 0000000000..8fccbc2a9c --- /dev/null +++ b/src/MLIAPPY/Install.sh @@ -0,0 +1,53 @@ +# Install/unInstall package files in LAMMPS +# mode = 0/1/2 for uninstall/install/update + +mode=$1 + +# arg1 = file, arg2 = file it depends on + +# enforce using portable C locale +LC_ALL=C +export LC_ALL + +action () { + if (test $mode = 0) then + rm -f ../$1 + elif (! cmp -s $1 ../$1) then + if (test -z "$2" || test -e ../$2) then + cp $1 .. + if (test $mode = 2) then + echo " updating src/$1" + fi + fi + elif (test -n "$2") then + if (test ! -e ../$2) then + rm -f ../$1 + fi + fi +} + +# force rebuild of files using python header + +touch ../lmppython.h + +# all package files with no dependencies + +for file in *.cpp *.h; do + test -f ${file} && action $file +done + +# edit 2 Makefile.package files to include/exclude package info + +if (test $1 = 1) then + + if (test -e ../Makefile.package) then + sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_MLIAPPY |' ../Makefile.package + fi + +elif (test $1 = 0) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*MLIAPPY[^ \t]* //g' ../Makefile.package + fi + +fi From 973382295b1439897e5869ff37cf5ff9915a9c54 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 16:47:27 -0700 Subject: [PATCH 07/39] Clean up file --- examples/mliappy/in.mliap.pytorch.Ta06A | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/examples/mliappy/in.mliap.pytorch.Ta06A b/examples/mliappy/in.mliap.pytorch.Ta06A index e44b4352e7..1d93d6a424 100644 --- a/examples/mliappy/in.mliap.pytorch.Ta06A +++ b/examples/mliappy/in.mliap.pytorch.Ta06A @@ -22,20 +22,6 @@ create_atoms 1 box mass 1 180.88 -python simple here """ -from __future__ import print_function - -def simple(): - foo = 0 - print("Inside simple function") - try: - foo += 1 - except Exception as e: - print("FOO error:", e) -""" - -python simple invoke - # choose potential include Ta06A.mliap.pytorch From 16f11f3421b4d14fb00e6faab7c3b5f7f4b10224 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 18:40:01 -0700 Subject: [PATCH 08/39] Moved all mliappy files in to src/MLIAP and examples/mliap --- .../{mliappy/README => mliap/README.pytorch} | 10 ++++----- .../{mliappy => mliap}/Ta06A.mliap.pytorch | 0 .../{mliappy => mliap}/convert_mliap_Ta06A.py | 6 +++--- .../{mliappy => mliap}/in.mliap.pytorch.Ta06A | 0 examples/{mliappy => mliap}/load_external.py | 0 examples/mliappy/Ta06A.mliap.descriptor | 21 ------------------- examples/mliappy/test_pylibs.py | 12 ----------- src/{MLIAPPY => MLIAP}/Install.sh | 0 src/MLIAP/README | 15 +++++++++++++ src/{MLIAPPY => MLIAP}/mliap_model_python.cpp | 0 src/{MLIAPPY => MLIAP}/mliap_model_python.h | 0 .../mliap_model_python_couple.pyx | 0 src/{MLIAPPY => MLIAP}/mliappy_pytorch.py | 0 src/MLIAPPY/Makefile.lammps | 1 - 14 files changed, 23 insertions(+), 42 deletions(-) rename examples/{mliappy/README => mliap/README.pytorch} (68%) rename examples/{mliappy => mliap}/Ta06A.mliap.pytorch (100%) rename examples/{mliappy => mliap}/convert_mliap_Ta06A.py (80%) rename examples/{mliappy => mliap}/in.mliap.pytorch.Ta06A (100%) rename examples/{mliappy => mliap}/load_external.py (100%) delete mode 100644 examples/mliappy/Ta06A.mliap.descriptor delete mode 100644 examples/mliappy/test_pylibs.py rename src/{MLIAPPY => MLIAP}/Install.sh (100%) rename src/{MLIAPPY => MLIAP}/mliap_model_python.cpp (100%) rename src/{MLIAPPY => MLIAP}/mliap_model_python.h (100%) rename src/{MLIAPPY => MLIAP}/mliap_model_python_couple.pyx (100%) rename src/{MLIAPPY => MLIAP}/mliappy_pytorch.py (100%) delete mode 100644 src/MLIAPPY/Makefile.lammps diff --git a/examples/mliappy/README b/examples/mliap/README.pytorch similarity index 68% rename from examples/mliappy/README rename to examples/mliap/README.pytorch index d61972afcf..642b39b842 100644 --- a/examples/mliappy/README +++ b/examples/mliap/README.pytorch @@ -1,17 +1,17 @@ -README for MLIAPPY Example +README for the PyTorch energy model example These examples run the Ta06 example from the MLIAP package, but using the python coupling. -1: Running models using LAMMPS executable: in.mliap.snap.Ta06A. +1: Running models using LAMMPS executable: in.mliap.pytorch.Ta06A To run this, first run convert_mliap_Ta06A.py, which will convert the Ta06 potential into a pytorch model. It will be saved as "Ta06A.mliap.pytorch.model.pkl". It will also copy the "mliappy_pytorch.py" file into the current working directory. mliappy_pytorch.py contains -class definitions suitable for wrapping an arbitrary energy model MLIAPPY. It must be available to python when -creating or unpicking a pytorch model for MLIAPPY. +class definitions suitable for wrapping an arbitrary PyTorch energy model. It must be available to python when +creating or unpicking a PyTorch energy model. -From that point you can run the example lmp -in in.mliap.snap.Ta06A -echo both +From that point you can run the example lmp -in in.mliap.pytorch.Ta06A -echo both 2: Running models from python with LAMMPS in library mode: load_external.py diff --git a/examples/mliappy/Ta06A.mliap.pytorch b/examples/mliap/Ta06A.mliap.pytorch similarity index 100% rename from examples/mliappy/Ta06A.mliap.pytorch rename to examples/mliap/Ta06A.mliap.pytorch diff --git a/examples/mliappy/convert_mliap_Ta06A.py b/examples/mliap/convert_mliap_Ta06A.py similarity index 80% rename from examples/mliappy/convert_mliap_Ta06A.py rename to examples/mliap/convert_mliap_Ta06A.py index 371139481d..6f10f8303c 100644 --- a/examples/mliappy/convert_mliap_Ta06A.py +++ b/examples/mliap/convert_mliap_Ta06A.py @@ -5,14 +5,14 @@ import pickle import os import shutil -shutil.copyfile('../../src/MLIAPPY/mliappy_pytorch.py','./mliappy_pytorch.py') +shutil.copyfile('../../src/MLIAP/mliappy_pytorch.py','./mliappy_pytorch.py') import mliappy_pytorch # Read coefficients -coeffs = np.genfromtxt("../mliap/Ta06A.mliap.model",skip_header=6) +coeffs = np.genfromtxt("Ta06A.mliap.model",skip_header=6) -# Write coefficiets to a pytorch linear model +# Write coefficients to a pytorch linear model bias = coeffs[0] weights = coeffs[1:] lin = torch.nn.Linear(weights.shape[0],1) diff --git a/examples/mliappy/in.mliap.pytorch.Ta06A b/examples/mliap/in.mliap.pytorch.Ta06A similarity index 100% rename from examples/mliappy/in.mliap.pytorch.Ta06A rename to examples/mliap/in.mliap.pytorch.Ta06A diff --git a/examples/mliappy/load_external.py b/examples/mliap/load_external.py similarity index 100% rename from examples/mliappy/load_external.py rename to examples/mliap/load_external.py diff --git a/examples/mliappy/Ta06A.mliap.descriptor b/examples/mliappy/Ta06A.mliap.descriptor deleted file mode 100644 index 481ebf7e44..0000000000 --- a/examples/mliappy/Ta06A.mliap.descriptor +++ /dev/null @@ -1,21 +0,0 @@ -# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) - -# LAMMPS SNAP parameters for Ta_Cand06A - -# required -rcutfac 4.67637 -twojmax 6 - -# elements - -nelems 1 -elems Ta -radelems 0.5 -welems 1 - -# optional - -rfac0 0.99363 -rmin0 0 -bzeroflag 0 - diff --git a/examples/mliappy/test_pylibs.py b/examples/mliappy/test_pylibs.py deleted file mode 100644 index c5dcab75cf..0000000000 --- a/examples/mliappy/test_pylibs.py +++ /dev/null @@ -1,12 +0,0 @@ -import sysconfig, os,ctypes - -library = sysconfig.get_config_vars('INSTSONAME')[0] - -pylib = ctypes.CDLL(library) - -connected = pylib.Py_IsInitialized() - -if not connected: - print("FAILURE: This interpreter is not compatible with python-driven mliappy.") -else: - print("SUCCESS: This interpreter is compatible with python-driven MLIAPPY") diff --git a/src/MLIAPPY/Install.sh b/src/MLIAP/Install.sh similarity index 100% rename from src/MLIAPPY/Install.sh rename to src/MLIAP/Install.sh diff --git a/src/MLIAP/README b/src/MLIAP/README index 18ce3297e6..4cb197826e 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -28,3 +28,18 @@ reference potential. To see how this command can be used within a Python workflow to train machine-learning interatomic potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP>. + +*Additional instructions for compiling PyTorch energy models* + +The *MLIAPPY* extension written by Nick Lubers (LANL) +provides a coupling to PyTorch energy models. + +Before compiling LAMMPS with either make or cmake, you have +to run cythonize to create the coupling source files +in the src/MLIAP directory e.g. + +cd MLIAP +cythonize mliap_model_python_couple.pyx + +After that, install the MLIAP package with make or cmake +and build LAMMPS. diff --git a/src/MLIAPPY/mliap_model_python.cpp b/src/MLIAP/mliap_model_python.cpp similarity index 100% rename from src/MLIAPPY/mliap_model_python.cpp rename to src/MLIAP/mliap_model_python.cpp diff --git a/src/MLIAPPY/mliap_model_python.h b/src/MLIAP/mliap_model_python.h similarity index 100% rename from src/MLIAPPY/mliap_model_python.h rename to src/MLIAP/mliap_model_python.h diff --git a/src/MLIAPPY/mliap_model_python_couple.pyx b/src/MLIAP/mliap_model_python_couple.pyx similarity index 100% rename from src/MLIAPPY/mliap_model_python_couple.pyx rename to src/MLIAP/mliap_model_python_couple.pyx diff --git a/src/MLIAPPY/mliappy_pytorch.py b/src/MLIAP/mliappy_pytorch.py similarity index 100% rename from src/MLIAPPY/mliappy_pytorch.py rename to src/MLIAP/mliappy_pytorch.py diff --git a/src/MLIAPPY/Makefile.lammps b/src/MLIAPPY/Makefile.lammps deleted file mode 100644 index f9bf1abc13..0000000000 --- a/src/MLIAPPY/Makefile.lammps +++ /dev/null @@ -1 +0,0 @@ -#TODO From 3c34bdfdeddcee09134cb2be69c6377e02b7a798 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 19:04:53 -0700 Subject: [PATCH 09/39] Updated the build files --- cmake/CMakeLists.txt | 7 +++---- cmake/Modules/Packages/{MLIAPPY.cmake => MLIAP.cmake} | 2 +- src/Makefile | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) rename cmake/Modules/Packages/{MLIAPPY.cmake => MLIAP.cmake} (78%) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index fab10bfdef..a034cf6d17 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -105,7 +105,7 @@ install(TARGETS lmp EXPORT LAMMPS_Targets DESTINATION ${CMAKE_INSTALL_BINDIR}) option(CMAKE_VERBOSE_MAKEFILE "Generate verbose Makefiles" OFF) set(STANDARD_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS DIPOLE - GRANULAR KSPACE LATTE MANYBODY MC MESSAGE MISC MLIAP MLIAPPY MOLECULE PERI POEMS + GRANULAR KSPACE LATTE MANYBODY MC MESSAGE MISC MLIAP MOLECULE PERI POEMS QEQ REPLICA RIGID SHOCK SPIN SNAP SRD KIM PYTHON MSCG MPIIO VORONOI USER-ATC USER-AWPMD USER-BOCS USER-CGDNA USER-MESODPD USER-CGSDK USER-COLVARS USER-DIFFRACTION USER-DPD USER-DRUDE USER-EFF USER-FEP USER-H5MD USER-LB @@ -194,8 +194,7 @@ endif() # "hard" dependencies between packages resulting # in an error instead of skipping over files pkg_depends(MLIAP SNAP) -pkg_depends(MLIAPPY MLIAP) -pkg_depends(MLIAPPY PYTHON) +pkg_depends(MLIAP PYTHON) pkg_depends(MPIIO MPI) pkg_depends(USER-ATC MANYBODY) pkg_depends(USER-LB MPI) @@ -374,7 +373,7 @@ else() set(CUDA_REQUEST_PIC) endif() -foreach(PKG_WITH_INCL KSPACE PYTHON MLIAPPY VORONOI USER-COLVARS USER-MOLFILE USER-NETCDF USER-PLUMED USER-QMMM +foreach(PKG_WITH_INCL KSPACE PYTHON MLIAP VORONOI USER-COLVARS USER-MOLFILE USER-NETCDF USER-PLUMED USER-QMMM USER-QUIP USER-SCAFACOS USER-SMD USER-VTK KIM LATTE MESSAGE MSCG COMPRESS) if(PKG_${PKG_WITH_INCL}) include(Packages/${PKG_WITH_INCL}) diff --git a/cmake/Modules/Packages/MLIAPPY.cmake b/cmake/Modules/Packages/MLIAP.cmake similarity index 78% rename from cmake/Modules/Packages/MLIAPPY.cmake rename to cmake/Modules/Packages/MLIAP.cmake index 73ce83361c..e877d072b6 100644 --- a/cmake/Modules/Packages/MLIAPPY.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -1,3 +1,3 @@ -execute_process(COMMAND cythonize mliap_model_python_couple.pyx WORKING_DIRECTORY ../src/MLIAPPY) +execute_process(COMMAND cythonize mliap_model_python_couple.pyx WORKING_DIRECTORY ../src/MLIAP) target_compile_definitions(lammps PRIVATE -DLMP_MLIAPPY) diff --git a/src/Makefile b/src/Makefile index 8667f3f725..149dedd35b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,7 +48,7 @@ endif PACKAGE = asphere body class2 colloid compress coreshell dipole gpu \ granular kim kokkos kspace latte manybody mc message misc \ - mliap mliappy molecule mpiio mscg opt peri poems \ + mliap molecule mpiio mscg opt peri poems \ python qeq replica rigid shock snap spin srd voronoi PACKUSER = user-adios user-atc user-awpmd user-bocs user-cgdna user-cgsdk user-colvars \ From 36a5e9d20edb35dc2e4bfa2a363ea6f4dcef8e38 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 19:36:52 -0700 Subject: [PATCH 10/39] Added some author credits --- src/MLIAP/compute_mliap.cpp | 4 ++++ src/MLIAP/mliap_data.cpp | 4 ++++ src/MLIAP/mliap_descriptor.cpp | 4 ++++ src/MLIAP/mliap_descriptor_snap.cpp | 4 ++++ src/MLIAP/mliap_model.cpp | 4 ++++ src/MLIAP/mliap_model_linear.cpp | 4 ++++ src/MLIAP/mliap_model_python.cpp | 4 ++++ src/MLIAP/mliap_model_quadratic.cpp | 4 ++++ src/MLIAP/mliappy_pytorch.py | 17 +++++++++++++++++ src/MLIAP/pair_mliap.cpp | 4 ++++ 10 files changed, 53 insertions(+) diff --git a/src/MLIAP/compute_mliap.cpp b/src/MLIAP/compute_mliap.cpp index 64753fe64f..72fb63ecda 100644 --- a/src/MLIAP/compute_mliap.cpp +++ b/src/MLIAP/compute_mliap.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include #include "mliap_data.h" diff --git a/src/MLIAP/mliap_data.cpp b/src/MLIAP/mliap_data.cpp index 3ada98e8c0..2559f5330d 100644 --- a/src/MLIAP/mliap_data.cpp +++ b/src/MLIAP/mliap_data.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_data.h" #include "atom.h" diff --git a/src/MLIAP/mliap_descriptor.cpp b/src/MLIAP/mliap_descriptor.cpp index b3e0cebd2e..ac168dc94b 100644 --- a/src/MLIAP/mliap_descriptor.cpp +++ b/src/MLIAP/mliap_descriptor.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_descriptor.h" using namespace LAMMPS_NS; diff --git a/src/MLIAP/mliap_descriptor_snap.cpp b/src/MLIAP/mliap_descriptor_snap.cpp index cfbc51cb5c..2cb88de6b4 100644 --- a/src/MLIAP/mliap_descriptor_snap.cpp +++ b/src/MLIAP/mliap_descriptor_snap.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_descriptor_snap.h" #include "atom.h" diff --git a/src/MLIAP/mliap_model.cpp b/src/MLIAP/mliap_model.cpp index a4f5cdc86c..aa198e6085 100644 --- a/src/MLIAP/mliap_model.cpp +++ b/src/MLIAP/mliap_model.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_model.h" #include "comm.h" diff --git a/src/MLIAP/mliap_model_linear.cpp b/src/MLIAP/mliap_model_linear.cpp index 428d163166..3c8f9aa39a 100644 --- a/src/MLIAP/mliap_model_linear.cpp +++ b/src/MLIAP/mliap_model_linear.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_model_linear.h" #include "pair_mliap.h" #include "mliap_data.h" diff --git a/src/MLIAP/mliap_model_python.cpp b/src/MLIAP/mliap_model_python.cpp index 1ac61f08b0..2aa588ff32 100644 --- a/src/MLIAP/mliap_model_python.cpp +++ b/src/MLIAP/mliap_model_python.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Nicholas Lubbers (LANL) +------------------------------------------------------------------------- */ + #include #include "mliap_model_python.h" #include "mliap_model_python_couple.h" diff --git a/src/MLIAP/mliap_model_quadratic.cpp b/src/MLIAP/mliap_model_quadratic.cpp index 222f6ad0ae..915ec30435 100644 --- a/src/MLIAP/mliap_model_quadratic.cpp +++ b/src/MLIAP/mliap_model_quadratic.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "mliap_model_quadratic.h" #include "pair_mliap.h" #include "mliap_data.h" diff --git a/src/MLIAP/mliappy_pytorch.py b/src/MLIAP/mliappy_pytorch.py index 5294344c10..ff80720ffa 100644 --- a/src/MLIAP/mliappy_pytorch.py +++ b/src/MLIAP/mliappy_pytorch.py @@ -1,3 +1,20 @@ +# ---------------------------------------------------------------------- +# 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 author: Nicholas Lubbers (LANL) +# ------------------------------------------------------------------------- + import numpy as np import torch diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index 7a2d5b14b5..5c0474d2ca 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -11,6 +11,10 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing author: Aidan Thompson (SNL) +------------------------------------------------------------------------- */ + #include "pair_mliap.h" #include "mliap_data.h" From 05bd2c5375b93ca59c5f1e0f4fe774e13c44d27f Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 19:37:07 -0700 Subject: [PATCH 11/39] Added some author credits --- doc/src/Packages_details.rst | 48 ++++++++++-------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index f8e18dafbc..ebbd6dd0b4 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -45,7 +45,6 @@ page gives those details. * :ref:`MESSAGE ` * :ref:`MISC ` * :ref:`MLIAP ` - * :ref:`MLIAPPY ` * :ref:`MOLECULE ` * :ref:`MPIIO ` * :ref:`MSCG ` @@ -663,50 +662,29 @@ MLIAP package **Contents:** -A general interface for machine-learning interatomic potentials. +A general interface for machine-learning interatomic potentials, including PyTorch. **Install:** -To use this package, also the :ref:`SNAP package ` needs to be installed. +To use this package, also the :ref:`SNAP package ` and +:ref:`PYTHON package ` packages need to be installed. +The version of python must be >3.5. -**Author:** Aidan Thompson (Sandia). +**Author:** Aidan Thompson (Sandia), Nicholas Lubbers (LANL). **Supporting info:** * src/MLIAP: filenames -> commands -* :doc:`pair_style mliap ` -* examples/mliap - ----------- - -.. _PKG-MLIAPPY: - -MLIAPPY package -------------- - -**Contents:** - -Extension to the MLIAP package for coupling with python models. - -**Install:** - -To use this package, also the :ref:`MLIAP package ` needs to be installed. -To use this package, also the :ref:`PYTHON package ` needs to be installed. -The version of python must be >3.5. - -The python interpreter linked to LAMMPS will need cython and numpy installed. -The examples build models with pytorch, which would thus need to be installed. - -This package includes more options for the mliap compute and pair style. - -**Author:** Nicholas Lubbers (LANL). - -**Supporting info:** - -* src/MLIAPPY: filenames -> commands * src/MLIAPPY/README * :doc:`pair_style mliap ` -* examples/mliappy (see README) +* examples/mliap (see README) + +When compiled with the LMP_MLIAPPY option, this package +includes an extension for coupling with python models, incuding PyTorch + +The python interpreter linked to LAMMPS will need cython and numpy installed. +The examples build models with PyTorch, which would thus need to be installed. + ---------- .. _PKG-MOLECULE: From d1422aa1097ed2ea6f4a20d34912e18a3b958b33 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Thu, 3 Dec 2020 19:46:19 -0700 Subject: [PATCH 12/39] Removed MLIAPPY package from docs --- doc/src/Packages_details.rst | 4 ++-- doc/src/Packages_standard.rst | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index ebbd6dd0b4..e04013915f 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -675,11 +675,11 @@ The version of python must be >3.5. **Supporting info:** * src/MLIAP: filenames -> commands -* src/MLIAPPY/README +* src/MLIAP/README * :doc:`pair_style mliap ` * examples/mliap (see README) -When compiled with the LMP_MLIAPPY option, this package +When compiled with the -DLMP_MLIAPPY flag, this package includes an extension for coupling with python models, incuding PyTorch The python interpreter linked to LAMMPS will need cython and numpy installed. diff --git a/doc/src/Packages_standard.rst b/doc/src/Packages_standard.rst index 800fd3c501..ab9be69ab3 100644 --- a/doc/src/Packages_standard.rst +++ b/doc/src/Packages_standard.rst @@ -61,8 +61,6 @@ package: +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MLIAP ` | multiple machine learning potentials | :doc:`pair_style mliap ` | mliap | no | +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ -| :ref:`MLIAPPY ` | enable python ML models for mliap | :doc:`pair_style mliap ` | mliap | no | -+----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MOLECULE ` | molecular system force fields | :doc:`Howto bioFF ` | peptide | no | +----------------------------------+--------------------------------------+----------------------------------------------------+------------------------------------------------------+---------+ | :ref:`MPIIO ` | MPI parallel I/O dump and restart | :doc:`dump ` | n/a | no | From 851f0775f1f9678fc97e2e7c912544ae563df4d0 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 4 Dec 2020 11:59:01 -0700 Subject: [PATCH 13/39] Fixed spelling errors --- doc/src/Packages_details.rst | 15 ++++++------ doc/src/compute_mliap.rst | 18 +++++++------- doc/src/pair_mliap.rst | 26 ++++++++++----------- doc/utils/sphinx-config/false_positives.txt | 1 + 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index e04013915f..3ed5cabe37 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -666,9 +666,10 @@ A general interface for machine-learning interatomic potentials, including PyTor **Install:** -To use this package, also the :ref:`SNAP package ` and -:ref:`PYTHON package ` packages need to be installed. -The version of python must be >3.5. +To use this package, also the :ref:`SNAP package ` +package needs to be installed. If building the *mliappy* model, +use -DLMP_MLIAPPY and the :ref:`PYTHON package ` +package needs to be installed. The version of python must be >3.5. **Author:** Aidan Thompson (Sandia), Nicholas Lubbers (LANL). @@ -677,12 +678,12 @@ The version of python must be >3.5. * src/MLIAP: filenames -> commands * src/MLIAP/README * :doc:`pair_style mliap ` +* :doc:`compute_style mliap ` * examples/mliap (see README) -When compiled with the -DLMP_MLIAPPY flag, this package -includes an extension for coupling with python models, incuding PyTorch - -The python interpreter linked to LAMMPS will need cython and numpy installed. +When built with the *mliappy* model using -DLMP_MLIAPPY, this package +includes an extension for coupling with python models, including PyTorch. +In this case, the python interpreter linked to LAMMPS will need cython and numpy installed. The examples build models with PyTorch, which would thus need to be installed. ---------- diff --git a/doc/src/compute_mliap.rst b/doc/src/compute_mliap.rst index e4e6603cdc..66bf868e0d 100644 --- a/doc/src/compute_mliap.rst +++ b/doc/src/compute_mliap.rst @@ -56,14 +56,15 @@ and it is also straightforward to add new descriptor styles. The compute *mliap* command must be followed by two keywords *model* and *descriptor* in either order. -The *model* keyword is followed by a model style, currently limited to -either *linear* or *quadratic*. The *mliappy* model is only available +The *model* keyword is followed by the model style (*linear*, *quadratic* or *mliappy*). +The *mliappy* model is only available if lammps is built with MLIAPPY package. The *descriptor* keyword is followed by a descriptor style, and additional arguments. -Currently the only descriptor style is *sna*, indicating the bispectrum component -descriptors used by the Spectral Neighbor Analysis Potential (SNAP) potentials of -:doc:`pair_style snap `. +The compute currently supports just one descriptor style, but it is +is straightforward to add new descriptor styles. +The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, +including the linear, quadratic, and chem variants. A single additional argument specifies the descriptor filename containing the parameters and setting used by the SNAP descriptor. The descriptor filename usually ends in the *.mliap.descriptor* extension. @@ -163,13 +164,12 @@ potentials, see the examples in `FitSNAP `_. Restrictions """""""""""" -This compute is part of the MLIAP package. It is only enabled if -LAMMPS was built with that package. In addition, building LAMMPS with the MLIAP package +This compute is part of the MLIAP package. It is only enabled if LAMMPS +was built with that package. In addition, building LAMMPS with the MLIAP package requires building LAMMPS with the SNAP package. +The *mliappy* model requires building LAMMPS with the PYTHON package. See the :doc:`Build package ` doc page for more info. -Python models such as neural networks can be used if the MLIAPPY package is built. - Related commands """""""""""""""" diff --git a/doc/src/pair_mliap.rst b/doc/src/pair_mliap.rst index aeba2d9fd2..4c1845d514 100644 --- a/doc/src/pair_mliap.rst +++ b/doc/src/pair_mliap.rst @@ -40,13 +40,15 @@ definitions of the interatomic potential functional form (*model*) and the geometric quantities that characterize the atomic positions (*descriptor*). By defining *model* and *descriptor* separately, it is possible to use many different models with a given descriptor, -or many different descriptors with a given model. Currently, the pair_style -supports just two models, *linear* and *quadratic*, -and one descriptor, *sna*, the SNAP descriptor used by :doc:`pair_style snap `, including the linear, quadratic, -and chem variants. With the MLIAPPY package installed, the *mliappy* model -is available which can be used to couple python models such as neural network -energy models. -It is also straightforward to add new descriptor styles. +or many different descriptors with a given model. The +pair style currently supports just one descriptor style, but it is +is straightforward to add new descriptor styles. +The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, +including the linear, quadratic, and chem variants. +The available models are *linear*, *quadratic*, and *mliappy*. +The *mliappy* style can be used to couple python models, +e.g. PyTorch neural network energy models, and requires building +LAMMPS with the PYTHON package (see below). In order to train a model, it is useful to know the gradient or derivative of energy, force, and stress w.r.t. model parameters. This information can be accessed using the related :doc:`compute mliap ` command. @@ -60,9 +62,8 @@ that specify the mapping of MLIAP element names to LAMMPS atom types, where N is the number of LAMMPS atom types. -The *model* keyword is followed by a model style, currently limited to -either *linear* or *quadratic*. In both cases, -this is followed by a single argument specifying the model filename containing the +The *model* keyword is followed by the model style. This is followed +by a single argument specifying the model filename containing the parameters for a set of elements. The model filename usually ends in the *.mliap.model* extension. It may contain parameters for many elements. The only requirement is that it @@ -139,13 +140,12 @@ This pair style can only be used via the *pair* keyword of the Restrictions """""""""""" -This style is part of the MLIAP package. It is only enabled if LAMMPS +This pair style is part of the MLIAP package. It is only enabled if LAMMPS was built with that package. In addition, building LAMMPS with the MLIAP package requires building LAMMPS with the SNAP package. +The *mliappy* model requires building LAMMPS with the PYTHON package. See the :doc:`Build package ` doc page for more info. -Python models such as neural networks can be used if the MLIAPPY package is built. - Related commands """""""""""""""" diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 3fd204ceb8..ca1e0adb34 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -557,6 +557,7 @@ Cygwin cylindrically Cyrot cyrstals +cython Daivis Dammak dampflag From 2654aca6588c2ba4bf958551637d9615f720b1d5 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 4 Dec 2020 14:04:35 -0700 Subject: [PATCH 14/39] Added blessed examples --- examples/mliap/in.mliap.pytorch.Ta06A | 2 +- .../log.04Dec20.mliap.pytorch.Ta06A.g++.1 | 157 ++++++++++++++++++ .../log.04Dec20.mliap.pytorch.Ta06A.g++.4 | 157 ++++++++++++++++++ ...oad_external.py => mliap.pytorch.Ta06A.py} | 26 +-- 4 files changed, 329 insertions(+), 13 deletions(-) create mode 100644 examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.1 create mode 100644 examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.4 rename examples/mliap/{load_external.py => mliap.pytorch.Ta06A.py} (81%) diff --git a/examples/mliap/in.mliap.pytorch.Ta06A b/examples/mliap/in.mliap.pytorch.Ta06A index 1d93d6a424..59cdcc8c81 100644 --- a/examples/mliap/in.mliap.pytorch.Ta06A +++ b/examples/mliap/in.mliap.pytorch.Ta06A @@ -1,4 +1,4 @@ -# Demonstrate MLIAP interface to linear SNAP potential +# Demonstrate MLIAP/PyTorch interface to linear SNAP potential # Initialize simulation diff --git a/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.1 b/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.1 new file mode 100644 index 0000000000..f56a79650e --- /dev/null +++ b/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.1 @@ -0,0 +1,157 @@ +LAMMPS (30 Nov 2020) + using 48 OpenMP thread(s) per MPI task +# Demonstrate MLIAP/PyTorch interface to linear SNAP potential + +# Initialize simulation + +variable nsteps index 100 +variable nrep equal 4 +variable a equal 3.316 +units metal + +# generate the box and atom positions using a BCC lattice + +variable nx equal ${nrep} +variable nx equal 4 +variable ny equal ${nrep} +variable ny equal 4 +variable nz equal ${nrep} +variable nz equal 4 + +boundary p p p + +lattice bcc $a +lattice bcc 3.316 +Lattice spacing in x,y,z = 3.3160000 3.3160000 3.3160000 +region box block 0 ${nx} 0 ${ny} 0 ${nz} +region box block 0 4 0 ${ny} 0 ${nz} +region box block 0 4 0 4 0 ${nz} +region box block 0 4 0 4 0 4 +create_box 1 box +Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (13.264000 13.264000 13.264000) + 1 by 1 by 1 MPI processor grid +create_atoms 1 box +Created 128 atoms + create_atoms CPU = 0.002 seconds + +mass 1 180.88 + +# choose potential + +include Ta06A.mliap.pytorch +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# Definition of SNAP potential Ta_Cand06A +# Assumes 1 LAMMPS atom type + +variable zblcutinner equal 4 +variable zblcutouter equal 4.8 +variable zblz equal 73 + +# Specify hybrid with SNAP, ZBL + +pair_style hybrid/overlay zbl ${zblcutinner} ${zblcutouter} mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +pair_style hybrid/overlay zbl 4 ${zblcutouter} mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +pair_style hybrid/overlay zbl 4 4.8 mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +Loading python model complete. +Reading potential file Ta06A.mliap.descriptor with DATE: 2014-09-05 +SNAP keyword rcutfac 4.67637 +SNAP keyword twojmax 6 +SNAP keyword nelems 1 +SNAP keyword elems Ta +SNAP keyword radelems 0.5 +SNAP keyword welems 1 +SNAP keyword rfac0 0.99363 +SNAP keyword rmin0 0 +SNAP keyword bzeroflag 0 +pair_coeff 1 1 zbl ${zblz} ${zblz} +pair_coeff 1 1 zbl 73 ${zblz} +pair_coeff 1 1 zbl 73 73 +pair_coeff * * mliap Ta + + +# Setup output + +compute eatom all pe/atom +compute energy all reduce sum c_eatom + +compute satom all stress/atom NULL +compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] +variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + +thermo_style custom step temp epair c_energy etotal press v_press +thermo 10 +thermo_modify norm yes + +# Set up NVE run + +timestep 0.5e-3 +neighbor 1.0 bin +neigh_modify once no every 1 delay 0 check yes + +# Run MD + +velocity all create 300.0 4928459 loop geom +fix 1 all nve +run ${nsteps} +run 100 +Neighbor list info ... + update every 1 steps, delay 0 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 5.8 + ghost atom cutoff = 5.8 + binsize = 2.9, bins = 5 5 5 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair zbl, perpetual, half/full from (2) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none + (2) pair mliap, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 159.8 | 159.8 | 159.8 Mbytes +Step Temp E_pair c_energy TotEng Press v_press + 0 300 -11.85157 -11.85157 -11.813095 2717.1661 -2717.1661 + 10 296.01467 -11.851059 -11.851059 -11.813095 2697.4796 -2697.4796 + 20 284.53666 -11.849587 -11.849587 -11.813095 2289.1527 -2289.1527 + 30 266.51577 -11.847275 -11.847275 -11.813095 1851.7131 -1851.7131 + 40 243.05007 -11.844266 -11.844266 -11.813095 1570.684 -1570.684 + 50 215.51032 -11.840734 -11.840734 -11.813094 1468.1899 -1468.1899 + 60 185.48331 -11.836883 -11.836883 -11.813094 1524.8757 -1524.8757 + 70 154.6736 -11.832931 -11.832931 -11.813094 1698.3351 -1698.3351 + 80 124.79303 -11.829099 -11.829099 -11.813094 1947.0715 -1947.0715 + 90 97.448054 -11.825592 -11.825592 -11.813094 2231.9563 -2231.9563 + 100 74.035418 -11.822589 -11.822589 -11.813094 2515.8526 -2515.8526 +Loop time of 2.00236 on 48 procs for 100 steps with 128 atoms + +Performance: 2.157 ns/day, 11.124 hours/ns, 49.941 timesteps/s +288.8% CPU use with 1 MPI tasks x 48 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.9998 | 1.9998 | 1.9998 | 0.0 | 99.87 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0.0011814 | 0.0011814 | 0.0011814 | 0.0 | 0.06 +Output | 0.00059724 | 0.00059724 | 0.00059724 | 0.0 | 0.03 +Modify | 0.00047352 | 0.00047352 | 0.00047352 | 0.0 | 0.02 +Other | | 0.0003468 | | | 0.02 + +Nlocal: 128.000 ave 128 max 128 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 727.000 ave 727 max 727 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 3712.00 ave 3712 max 3712 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 7424.00 ave 7424 max 7424 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 7424 +Ave neighs/atom = 58.000000 +Neighbor list builds = 0 +Dangerous builds = 0 + +Total wall time: 0:00:03 diff --git a/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.4 b/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.4 new file mode 100644 index 0000000000..7f1bc818d1 --- /dev/null +++ b/examples/mliap/log.04Dec20.mliap.pytorch.Ta06A.g++.4 @@ -0,0 +1,157 @@ +LAMMPS (30 Nov 2020) + using 48 OpenMP thread(s) per MPI task +# Demonstrate MLIAP/PyTorch interface to linear SNAP potential + +# Initialize simulation + +variable nsteps index 100 +variable nrep equal 4 +variable a equal 3.316 +units metal + +# generate the box and atom positions using a BCC lattice + +variable nx equal ${nrep} +variable nx equal 4 +variable ny equal ${nrep} +variable ny equal 4 +variable nz equal ${nrep} +variable nz equal 4 + +boundary p p p + +lattice bcc $a +lattice bcc 3.316 +Lattice spacing in x,y,z = 3.3160000 3.3160000 3.3160000 +region box block 0 ${nx} 0 ${ny} 0 ${nz} +region box block 0 4 0 ${ny} 0 ${nz} +region box block 0 4 0 4 0 ${nz} +region box block 0 4 0 4 0 4 +create_box 1 box +Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (13.264000 13.264000 13.264000) + 1 by 2 by 2 MPI processor grid +create_atoms 1 box +Created 128 atoms + create_atoms CPU = 0.002 seconds + +mass 1 180.88 + +# choose potential + +include Ta06A.mliap.pytorch +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# Definition of SNAP potential Ta_Cand06A +# Assumes 1 LAMMPS atom type + +variable zblcutinner equal 4 +variable zblcutouter equal 4.8 +variable zblz equal 73 + +# Specify hybrid with SNAP, ZBL + +pair_style hybrid/overlay zbl ${zblcutinner} ${zblcutouter} mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +pair_style hybrid/overlay zbl 4 ${zblcutouter} mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +pair_style hybrid/overlay zbl 4 4.8 mliap model mliappy Ta06A.mliap.pytorch.model.pkl descriptor sna Ta06A.mliap.descriptor +Loading python model complete. +Reading potential file Ta06A.mliap.descriptor with DATE: 2014-09-05 +SNAP keyword rcutfac 4.67637 +SNAP keyword twojmax 6 +SNAP keyword nelems 1 +SNAP keyword elems Ta +SNAP keyword radelems 0.5 +SNAP keyword welems 1 +SNAP keyword rfac0 0.99363 +SNAP keyword rmin0 0 +SNAP keyword bzeroflag 0 +pair_coeff 1 1 zbl ${zblz} ${zblz} +pair_coeff 1 1 zbl 73 ${zblz} +pair_coeff 1 1 zbl 73 73 +pair_coeff * * mliap Ta + + +# Setup output + +compute eatom all pe/atom +compute energy all reduce sum c_eatom + +compute satom all stress/atom NULL +compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] +variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + +thermo_style custom step temp epair c_energy etotal press v_press +thermo 10 +thermo_modify norm yes + +# Set up NVE run + +timestep 0.5e-3 +neighbor 1.0 bin +neigh_modify once no every 1 delay 0 check yes + +# Run MD + +velocity all create 300.0 4928459 loop geom +fix 1 all nve +run ${nsteps} +run 100 +Neighbor list info ... + update every 1 steps, delay 0 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 5.8 + ghost atom cutoff = 5.8 + binsize = 2.9, bins = 5 5 5 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair zbl, perpetual, half/full from (2) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none + (2) pair mliap, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 159.7 | 159.7 | 159.7 Mbytes +Step Temp E_pair c_energy TotEng Press v_press + 0 300 -11.85157 -11.85157 -11.813095 2717.1661 -2717.1661 + 10 296.01467 -11.851059 -11.851059 -11.813095 2697.4796 -2697.4796 + 20 284.53666 -11.849587 -11.849587 -11.813095 2289.1527 -2289.1527 + 30 266.51577 -11.847275 -11.847275 -11.813095 1851.7131 -1851.7131 + 40 243.05007 -11.844266 -11.844266 -11.813095 1570.684 -1570.684 + 50 215.51032 -11.840734 -11.840734 -11.813094 1468.1899 -1468.1899 + 60 185.48331 -11.836883 -11.836883 -11.813094 1524.8757 -1524.8757 + 70 154.6736 -11.832931 -11.832931 -11.813094 1698.3351 -1698.3351 + 80 124.79303 -11.829099 -11.829099 -11.813094 1947.0715 -1947.0715 + 90 97.448054 -11.825592 -11.825592 -11.813094 2231.9563 -2231.9563 + 100 74.035418 -11.822589 -11.822589 -11.813094 2515.8526 -2515.8526 +Loop time of 0.562802 on 192 procs for 100 steps with 128 atoms + +Performance: 7.676 ns/day, 3.127 hours/ns, 177.682 timesteps/s +99.7% CPU use with 4 MPI tasks x 48 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.53583 | 0.54622 | 0.55401 | 0.9 | 97.05 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0.0071442 | 0.01491 | 0.025289 | 5.4 | 2.65 +Output | 0.00092525 | 0.00095771 | 0.0010166 | 0.0 | 0.17 +Modify | 0.00014479 | 0.00015043 | 0.00015893 | 0.0 | 0.03 +Other | | 0.0005624 | | | 0.10 + +Nlocal: 32.0000 ave 32 max 32 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 431.000 ave 431 max 431 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Neighs: 928.000 ave 928 max 928 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +FullNghs: 1856.00 ave 1856 max 1856 min +Histogram: 4 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 7424 +Ave neighs/atom = 58.000000 +Neighbor list builds = 0 +Dangerous builds = 0 + +Total wall time: 0:00:02 diff --git a/examples/mliap/load_external.py b/examples/mliap/mliap.pytorch.Ta06A.py similarity index 81% rename from examples/mliap/load_external.py rename to examples/mliap/mliap.pytorch.Ta06A.py index 606ee8f940..5f3ecaadc8 100644 --- a/examples/mliap/load_external.py +++ b/examples/mliap/mliap.pytorch.Ta06A.py @@ -1,12 +1,11 @@ - # Demonstrate how to load a model from the python side. -# This is essentially the same as in.mliap.pytorch.Ta06A-- +# This is essentially the same as in.mliap.pytorch.Ta06A # except that python is the driving program, and lammps # is in library mode. before_loading =\ """ - # Demonstrate MLIAP interface to linear SNAP potential + # Demonstrate MLIAP/PyTorch interface to linear SNAP potential # Initialize simulation @@ -78,27 +77,30 @@ after_loading =\ run ${nsteps} """ - import lammps lmp = lammps.lammps(cmdargs=['-echo','both']) -# This commmand must be run before the MLIAP object is declared in lammps. + +# this commmand must be run before the MLIAP object is declared in lammps. + lmp.mliappy.activate() +# setup the simulation and declare an empty model +# by specifying model filename as "LATER" + lmp.commands_string(before_loading) -# Now the model is declared, but empty -- because the model filename -# was given as "LATER". +# define the PyTorch model by loading a pkl file. +# this could also be done in other ways. -# Load the python module, construct on the fly, do whatever, here: import pickle with open('Ta06A.mliap.pytorch.model.pkl','rb') as pfile: model = pickle.load(pfile) -# Now that you have a model, connect it to the pairstyle +# connect the PyTorch model to the mliap pair style + lmp.mliappy.load_model(model) -# Proceed with whatever calculations you like. +# run the simulation with the mliap pair style + lmp.commands_string(after_loading) - - From ed7775f083f19b406c174875c7ca0f517a4702d5 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 4 Dec 2020 14:48:02 -0700 Subject: [PATCH 15/39] Added blessed log files --- examples/mliap/README.pytorch | 25 ++++-- examples/mliap/mliap.pytorch.Ta06A.py | 106 -------------------------- examples/mliap/mliap_pytorch_Ta06A.py | 106 ++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 114 deletions(-) delete mode 100644 examples/mliap/mliap.pytorch.Ta06A.py create mode 100644 examples/mliap/mliap_pytorch_Ta06A.py diff --git a/examples/mliap/README.pytorch b/examples/mliap/README.pytorch index 642b39b842..7f511168a7 100644 --- a/examples/mliap/README.pytorch +++ b/examples/mliap/README.pytorch @@ -1,6 +1,7 @@ README for the PyTorch energy model example -These examples run the Ta06 example from the MLIAP package, but using the python coupling. +These two examples run the Ta06 example from the MLIAP package, but using the python coupling. +The differ only in how the coupling is constructed. 1: Running models using LAMMPS executable: in.mliap.pytorch.Ta06A @@ -13,14 +14,22 @@ creating or unpicking a PyTorch energy model. From that point you can run the example lmp -in in.mliap.pytorch.Ta06A -echo both -2: Running models from python with LAMMPS in library mode: load_external.py +2: Running models from python with LAMMPS in library mode: mliap_pytorch_Ta06A.py Before testing this, ensure that the first example (using LAMMPS executable) works. +Also, not all python installations support this mode of operation. +It requires that the Python interpreter be initialized. +To check this for your Python library, +run the Py_IsInitialized() method. +If the return value is True, you should be able to run the example, +as follows: -Not all python installations support this mode of operation. -Too test if your interpreter supports this, run: -`python test_pylibs.py` - and examine the output. +`python mliap_pytorch_Ta06A.py` + +or + +`mpirun -np 4 python mliap_pytorch_Ta06A.py` + +The resultant log.lammps output should be identical to that generated +by in.mliap.snap.Ta06A and in.mliap.pytorch.Ta06A -If this succeeds, you should be able to run: -`python load_external.py` diff --git a/examples/mliap/mliap.pytorch.Ta06A.py b/examples/mliap/mliap.pytorch.Ta06A.py deleted file mode 100644 index 5f3ecaadc8..0000000000 --- a/examples/mliap/mliap.pytorch.Ta06A.py +++ /dev/null @@ -1,106 +0,0 @@ -# Demonstrate how to load a model from the python side. -# This is essentially the same as in.mliap.pytorch.Ta06A -# except that python is the driving program, and lammps -# is in library mode. - -before_loading =\ -""" - # Demonstrate MLIAP/PyTorch interface to linear SNAP potential - - # Initialize simulation - - variable nsteps index 100 - variable nrep equal 4 - variable a equal 3.316 - units metal - - # generate the box and atom positions using a BCC lattice - - variable nx equal ${nrep} - variable ny equal ${nrep} - variable nz equal ${nrep} - - boundary p p p - - lattice bcc $a - region box block 0 ${nx} 0 ${ny} 0 ${nz} - create_box 1 box - create_atoms 1 box - - mass 1 180.88 - - # choose potential - # DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) - - # Definition of SNAP potential Ta_Cand06A - # Assumes 1 LAMMPS atom type - - variable zblcutinner equal 4 - variable zblcutouter equal 4.8 - variable zblz equal 73 - - # Specify hybrid with SNAP, ZBL - - pair_style hybrid/overlay & - zbl ${zblcutinner} ${zblcutouter} & - mliap model mliappy LATER & - descriptor sna Ta06A.mliap.descriptor - pair_coeff 1 1 zbl ${zblz} ${zblz} - pair_coeff * * mliap Ta -""" -after_loading =\ -""" - - # Setup output - - compute eatom all pe/atom - compute energy all reduce sum c_eatom - - compute satom all stress/atom NULL - compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] - variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) - - thermo_style custom step temp epair c_energy etotal press v_press - thermo 10 - thermo_modify norm yes - - # Set up NVE run - - timestep 0.5e-3 - neighbor 1.0 bin - neigh_modify once no every 1 delay 0 check yes - - # Run MD - - velocity all create 300.0 4928459 loop geom - fix 1 all nve - run ${nsteps} -""" - -import lammps - -lmp = lammps.lammps(cmdargs=['-echo','both']) - -# this commmand must be run before the MLIAP object is declared in lammps. - -lmp.mliappy.activate() - -# setup the simulation and declare an empty model -# by specifying model filename as "LATER" - -lmp.commands_string(before_loading) - -# define the PyTorch model by loading a pkl file. -# this could also be done in other ways. - -import pickle -with open('Ta06A.mliap.pytorch.model.pkl','rb') as pfile: - model = pickle.load(pfile) - -# connect the PyTorch model to the mliap pair style - -lmp.mliappy.load_model(model) - -# run the simulation with the mliap pair style - -lmp.commands_string(after_loading) diff --git a/examples/mliap/mliap_pytorch_Ta06A.py b/examples/mliap/mliap_pytorch_Ta06A.py new file mode 100644 index 0000000000..71c89f112e --- /dev/null +++ b/examples/mliap/mliap_pytorch_Ta06A.py @@ -0,0 +1,106 @@ +# Demonstrate how to load a model from the python side. +# This is essentially the same as in.mliap.pytorch.Ta06A +# except that python is the driving program, and lammps +# is in library mode. + +before_loading =\ +"""# Demonstrate MLIAP/PyTorch interface to linear SNAP potential + +# Initialize simulation + +variable nsteps index 100 +variable nrep equal 4 +variable a equal 3.316 +units metal + +# generate the box and atom positions using a BCC lattice + +variable nx equal ${nrep} +variable ny equal ${nrep} +variable nz equal ${nrep} + +boundary p p p + +lattice bcc $a +region box block 0 ${nx} 0 ${ny} 0 ${nz} +create_box 1 box +create_atoms 1 box + +mass 1 180.88 + +# choose potential + +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# Definition of SNAP potential Ta_Cand06A +# Assumes 1 LAMMPS atom type + +variable zblcutinner equal 4 +variable zblcutouter equal 4.8 +variable zblz equal 73 + +# Specify hybrid with SNAP, ZBL + +pair_style hybrid/overlay & +zbl ${zblcutinner} ${zblcutouter} & +mliap model mliappy LATER & +descriptor sna Ta06A.mliap.descriptor +pair_coeff 1 1 zbl ${zblz} ${zblz} +pair_coeff * * mliap Ta +""" +after_loading =\ +""" + +# Setup output + +compute eatom all pe/atom +compute energy all reduce sum c_eatom + +compute satom all stress/atom NULL +compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] +variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + +thermo_style custom step temp epair c_energy etotal press v_press +thermo 10 +thermo_modify norm yes + +# Set up NVE run + +timestep 0.5e-3 +neighbor 1.0 bin +neigh_modify once no every 1 delay 0 check yes + +# Run MD + +velocity all create 300.0 4928459 loop geom +fix 1 all nve +run ${nsteps} +""" + +import lammps + +lmp = lammps.lammps(cmdargs=['-echo','both']) + +# this commmand must be run before the MLIAP object is declared in lammps. + +lmp.mliappy.activate() + +# setup the simulation and declare an empty model +# by specifying model filename as "LATER" + +lmp.commands_string(before_loading) + +# define the PyTorch model by loading a pkl file. +# this could also be done in other ways. + +import pickle +with open('Ta06A.mliap.pytorch.model.pkl','rb') as pfile: + model = pickle.load(pfile) + +# connect the PyTorch model to the mliap pair style + +lmp.mliappy.load_model(model) + +# run the simulation with the mliap pair style + +lmp.commands_string(after_loading) From 3ed41295cdf81b67828c46485e6ca12bf080101b Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Fri, 4 Dec 2020 15:01:39 -0700 Subject: [PATCH 16/39] Tweaked build instructions --- src/MLIAP/Install.sh | 6 +----- src/MLIAP/README | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/MLIAP/Install.sh b/src/MLIAP/Install.sh index 8fccbc2a9c..bd7f7d23a8 100755 --- a/src/MLIAP/Install.sh +++ b/src/MLIAP/Install.sh @@ -26,10 +26,6 @@ action () { fi } -# force rebuild of files using python header - -touch ../lmppython.h - # all package files with no dependencies for file in *.cpp *.h; do @@ -47,7 +43,7 @@ if (test $1 = 1) then elif (test $1 = 0) then if (test -e ../Makefile.package) then - sed -i -e 's/[^ \t]*MLIAPPY[^ \t]* //g' ../Makefile.package + sed -i -e 's/[^ \t]*-DLMP_MLIAPPY[^ \t]* //g' ../Makefile.package fi fi diff --git a/src/MLIAP/README b/src/MLIAP/README index 4cb197826e..d94a1bac16 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -31,14 +31,14 @@ potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP>. *Additional instructions for compiling PyTorch energy models* -The *MLIAPPY* extension written by Nick Lubers (LANL) +The *MLIAPPY* extension written by Nick Lubbers (LANL) provides a coupling to PyTorch energy models. Before compiling LAMMPS with either make or cmake, you have to run cythonize to create the coupling source files in the src/MLIAP directory e.g. -cd MLIAP +cd src/MLIAP cythonize mliap_model_python_couple.pyx After that, install the MLIAP package with make or cmake From 3f5a896aab4bc4fe2a89c8af1dcd883e16c1f262 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 17:35:10 -0500 Subject: [PATCH 17/39] update build system to make it auto-adapt to include python support or not into MLIAP --- cmake/CMakeLists.txt | 1 - cmake/Modules/FindCythonize.cmake | 30 ++++++++++++++++++++++++++++++ cmake/Modules/LAMMPSUtils.cmake | 1 + cmake/Modules/Packages/MLIAP.cmake | 30 ++++++++++++++++++++++++++++-- doc/src/Packages_details.rst | 12 ++++++------ lib/python/Makefile.lammps | 2 +- lib/python/Makefile.mliap_python | 3 +++ src/Depend.sh | 5 +++++ src/MLIAP/Install.sh | 30 ++++++++++++++++++++++++------ src/MLIAP/compute_mliap.cpp | 6 +++--- src/MLIAP/pair_mliap.cpp | 8 ++++---- src/PYTHON/python_impl.cpp | 10 +++++----- src/Purge.list | 2 ++ 13 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 cmake/Modules/FindCythonize.cmake create mode 100644 lib/python/Makefile.mliap_python diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index a034cf6d17..e9f9136398 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -194,7 +194,6 @@ endif() # "hard" dependencies between packages resulting # in an error instead of skipping over files pkg_depends(MLIAP SNAP) -pkg_depends(MLIAP PYTHON) pkg_depends(MPIIO MPI) pkg_depends(USER-ATC MANYBODY) pkg_depends(USER-LB MPI) diff --git a/cmake/Modules/FindCythonize.cmake b/cmake/Modules/FindCythonize.cmake new file mode 100644 index 0000000000..9a37904ea7 --- /dev/null +++ b/cmake/Modules/FindCythonize.cmake @@ -0,0 +1,30 @@ +# Find the Cythonize tool. +# +# This code sets the following variables: +# +# Cythonize_EXECUTABLE +# +# adapted from https://github.com/cmarshall108/cython-cmake-example/blob/master/cmake/FindCython.cmake +#============================================================================= + +if(CMAKE_VERSION VERSION_LESS 3.12) + find_package(PythonInterp 3.6 QUIET) # Deprecated since version 3.12 + if(PYTHONINTERP_FOUND) + set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE}) + endif() +else() + find_package(Python3 3.6 COMPONENTS Interpreter QUIET) +endif() + +# Use the Cython executable that lives next to the Python executable +# if it is a local installation. +if(Python3_EXECUTABLE) + get_filename_component(_python_path ${Python3_EXECUTABLE} PATH) + find_program(Cythonize_EXECUTABLE + NAMES cythonize3 cythonize cythonize.bat + HINTS ${_python_path}) +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cythonize REQUIRED_VARS Cythonize_EXECUTABLE) +mark_as_advanced(Cythonize_EXECUTABLE) diff --git a/cmake/Modules/LAMMPSUtils.cmake b/cmake/Modules/LAMMPSUtils.cmake index 339ba867bd..fb1203ec73 100644 --- a/cmake/Modules/LAMMPSUtils.cmake +++ b/cmake/Modules/LAMMPSUtils.cmake @@ -50,6 +50,7 @@ function(check_for_autogen_files source_dir) file(GLOB SRC_AUTOGEN_FILES ${source_dir}/style_*.h) file(GLOB SRC_AUTOGEN_PACKAGES ${source_dir}/packages_*.h) list(APPEND SRC_AUTOGEN_FILES ${SRC_AUTOGEN_PACKAGES} ${source_dir}/lmpinstalledpkgs.h ${source_dir}/lmpgitversion.h) + list(APPEND SRC_AUTOGEN_FILES ${SRC_AUTOGEN_PACKAGES} ${source_dir}/MLIAP/mliap_model_python_couple ${source_dir}/MLIAP/mliap_model_python_couple.cpp) foreach(_SRC ${SRC_AUTOGEN_FILES}) get_filename_component(FILENAME "${_SRC}" NAME) if(EXISTS ${source_dir}/${FILENAME}) diff --git a/cmake/Modules/Packages/MLIAP.cmake b/cmake/Modules/Packages/MLIAP.cmake index e877d072b6..153900e2b8 100644 --- a/cmake/Modules/Packages/MLIAP.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -1,3 +1,29 @@ -execute_process(COMMAND cythonize mliap_model_python_couple.pyx WORKING_DIRECTORY ../src/MLIAP) +# if PYTHON package is included we may also include Python support in MLIAP +set(ENABLE_MLIAP_PYTHON_DEFAULT OFF) +if(PKG_PYTHON) + find_package(Cythonize) + if(Cythonize_FOUND) + set(ENABLE_MLIAP_PYTHON_DEFAULT ON) + endif() +endif() -target_compile_definitions(lammps PRIVATE -DLMP_MLIAPPY) +option(ENABLE_MLIAP_PYTHON "Build MLIAP package with Python support" ${ENABLE_MLIAP_PYTHON_DEFAULT}) + +if(ENABLE_MLIAP_PYTHON) + find_package(Cythonize REQUIRED) + if(NOT_PKG_PYTHON) + message(FATAL_ERROR "Must install PYTHON package for MLIAP_PYTHON") + endif() + + set(MLIAP_CYTHON_DIR ${CMAKE_BINARY_DIR}/cython) + file(MAKE_DIRECTORY ${MLIAP_CYTHON_DIR}) + add_custom_command(OUTPUT ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.cpp ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.h + COMMAND ${CMAKE_COMMAND} -E copy ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx + COMMAND ${Cythonize_EXECUTABLE} ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx -3 + WORKING_DIRECTORY ${MLIAP_CYTHON_DIR} + MAIN_DEPENDENCY ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx + COMMENT "Generating C++ sources with cythonize...") + target_compile_definitions(lammps PRIVATE -DMLIAP_PYTHON) + target_sources(lammps PRIVATE ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.cpp) + target_include_directories(lammps PRIVATE ${MLIAP_CYTHON_DIR}) +endif() diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index 3ed5cabe37..3fb906addf 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -666,10 +666,10 @@ A general interface for machine-learning interatomic potentials, including PyTor **Install:** -To use this package, also the :ref:`SNAP package ` -package needs to be installed. If building the *mliappy* model, -use -DLMP_MLIAPPY and the :ref:`PYTHON package ` -package needs to be installed. The version of python must be >3.5. +To use this package, also the :ref:`SNAP package ` package needs +to be installed. To make the *mliappy* model available, also the +:ref:`PYTHON package ` package needs to be installed and the version of +python must be 3.5 or later. **Author:** Aidan Thompson (Sandia), Nicholas Lubbers (LANL). @@ -681,8 +681,8 @@ package needs to be installed. The version of python must be >3.5. * :doc:`compute_style mliap ` * examples/mliap (see README) -When built with the *mliappy* model using -DLMP_MLIAPPY, this package -includes an extension for coupling with python models, including PyTorch. +When built with the *mliappy* model this package includes an extension for +coupling with python models, including PyTorch. In this case, the python interpreter linked to LAMMPS will need cython and numpy installed. The examples build models with PyTorch, which would thus need to be installed. diff --git a/lib/python/Makefile.lammps b/lib/python/Makefile.lammps index 4289674e99..adda24caec 100644 --- a/lib/python/Makefile.lammps +++ b/lib/python/Makefile.lammps @@ -2,6 +2,6 @@ # See the README file for more explanation python_SYSINC = $(shell which python-config > /dev/null 2>&1 && python-config --includes || :) -python_SYSLIB = $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :) +python_SYSLIB = -lpython3 $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :) python_SYSPATH = PYTHON=python diff --git a/lib/python/Makefile.mliap_python b/lib/python/Makefile.mliap_python new file mode 100644 index 0000000000..00483a4a6a --- /dev/null +++ b/lib/python/Makefile.mliap_python @@ -0,0 +1,3 @@ + +../mliap_model_python_couple.cpp: ../mliap_model_python_couple.pyx + cythonize -3 ../mliap_model_python_couple.cpp diff --git a/src/Depend.sh b/src/Depend.sh index e629ca9197..f77d435fc5 100755 --- a/src/Depend.sh +++ b/src/Depend.sh @@ -106,6 +106,10 @@ if (test $1 = "PERI") then depend USER-OMP fi +if (test $1 = "PYTHON") then + depend MLIAP +fi + if (test $1 = "RIGID") then depend KOKKOS depend USER-OMP @@ -114,6 +118,7 @@ fi if (test $1 = "SNAP") then depend KOKKOS + depend MLIAP fi if (test $1 = "USER-CGSDK") then diff --git a/src/MLIAP/Install.sh b/src/MLIAP/Install.sh index bd7f7d23a8..e6ba4042a9 100755 --- a/src/MLIAP/Install.sh +++ b/src/MLIAP/Install.sh @@ -26,24 +26,42 @@ action () { fi } +# enforce package dependency +if (test $1 = 1 || test $1 = 2) then + if (test ! -e ../sna.h) then + echo "Must install SNAP package to use MLIAP package" + exit 1 + fi +fi + # all package files with no dependencies -for file in *.cpp *.h; do +for file in *.cpp *.h *.pyx; do test -f ${file} && action $file done # edit 2 Makefile.package files to include/exclude package info if (test $1 = 1) then - - if (test -e ../Makefile.package) then - sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_MLIAPPY |' ../Makefile.package + if (test "$(type cythonize 2> /dev/null)" != "" && test -e ../python_impl.cpp) then + if (test -e ../Makefile.package) then + sed -i -e 's|^PKG_INC =[ \t]*|&-DMLIAP_PYTHON |' ../Makefile.package + fi + if (test -e ../Makefile.package.settings) then + sed -i -e '/^include.*python.*mliap_python.*$/d' ../Makefile.package.settings + # multiline form needed for BSD sed on Macs + sed -i -e '4 i \ +include ..\/..\/lib\/python\/Makefile.mliap_python +' ../Makefile.package.settings + fi + cythonize -3 ../mliap_model_python_couple.pyx fi elif (test $1 = 0) then if (test -e ../Makefile.package) then - sed -i -e 's/[^ \t]*-DLMP_MLIAPPY[^ \t]* //g' ../Makefile.package + sed -i -e 's/[^ \t]*-DMLIAP_PYTHON[^ \t]* //g' ../Makefile.package fi - + rm -f ../mliap_model_python_couple.cpp ../mliap_model_python_couple.h + sed -i -e '/^include.*python.*mliap_python.*$/d' ../Makefile.package.settings fi diff --git a/src/MLIAP/compute_mliap.cpp b/src/MLIAP/compute_mliap.cpp index 72fb63ecda..0842e421c0 100644 --- a/src/MLIAP/compute_mliap.cpp +++ b/src/MLIAP/compute_mliap.cpp @@ -21,7 +21,7 @@ #include "mliap_model_linear.h" #include "mliap_model_quadratic.h" #include "mliap_descriptor_snap.h" -#ifdef LMP_MLIAPPY +#ifdef MLIAP_PYTHON #include "mliap_model_python.h" #endif @@ -74,12 +74,12 @@ ComputeMLIAP::ComputeMLIAP(LAMMPS *lmp, int narg, char **arg) : model = new MLIAPModelQuadratic(lmp); iarg += 2; } - #ifdef LMP_MLIAPPY +#ifdef MLIAP_PYTHON else if (strcmp(arg[iarg+1],"mliappy") == 0) { model = new MLIAPModelPython(lmp); iarg += 2; } - #endif +#endif else error->all(FLERR,"Illegal compute mliap command"); modelflag = 1; } else if (strcmp(arg[iarg],"descriptor") == 0) { diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index 5c0474d2ca..6f75ef542e 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -21,7 +21,7 @@ #include "mliap_model_linear.h" #include "mliap_model_quadratic.h" #include "mliap_descriptor_snap.h" -#ifdef LMP_MLIAPPY +#ifdef MLIAP_PYTHON #include "mliap_model_python.h" #endif @@ -128,7 +128,7 @@ void PairMLIAP::allocate() void PairMLIAP::settings(int narg, char ** arg) { - + if (narg < 4) error->all(FLERR,"Illegal pair_style command"); @@ -152,12 +152,12 @@ void PairMLIAP::settings(int narg, char ** arg) if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); model = new MLIAPModelQuadratic(lmp,arg[iarg+2]); iarg += 3; - #ifdef LMP_MLIAPPY +#ifdef MLIAP_PYTHON } else if (strcmp(arg[iarg+1],"mliappy") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal pair_style mliap command"); model = new MLIAPModelPython(lmp,arg[iarg+2]); iarg += 3; - #endif +#endif } else error->all(FLERR,"Illegal pair_style mliap command"); modelflag = 1; } else if (strcmp(arg[iarg],"descriptor") == 0) { diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 62f19d0f12..533394f7b1 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -26,7 +26,7 @@ #include #include // IWYU pragma: export -#ifdef LMP_MLIAPPY +#ifdef MLIAP_PYTHON #include "mliap_model_python.h" // The above should somehow really be included in the next file. // We could get around this with cython --capi-reexport-cincludes @@ -58,14 +58,14 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp) // one-time initialization of Python interpreter // pyMain stores pointer to main module external_interpreter = Py_IsInitialized(); - - #ifdef LMP_MLIAPPY + +#ifdef MLIAP_PYTHON // Inform python intialization scheme of the mliappy module. // This -must- happen before python is initialized. int err = PyImport_AppendInittab("mliap_model_python_couple", PyInit_mliap_model_python_couple); if (err) error->all(FLERR,"Could not register MLIAPPY embedded python module."); - #endif - +#endif + Py_Initialize(); PyEval_InitThreads(); diff --git a/src/Purge.list b/src/Purge.list index 0251f923be..2853ce2a7c 100644 --- a/src/Purge.list +++ b/src/Purge.list @@ -49,6 +49,8 @@ packages_ntopo.h # other auto-generated files lmpinstalledpkgs.h lmpgitversion.h +mliap_model_python_couple.cpp +mliap_model_python_couple.h # removed on 9 Sep 2020 mergesort.h # renamed on 8 May 2020 From 280c19cf3258e754937fced81e798965cf29894c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 17:46:54 -0500 Subject: [PATCH 18/39] rename CMake configuation variable to MLIAP_ENABLE_PYTHON to be more consistent with other packages --- cmake/Modules/Packages/MLIAP.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/Modules/Packages/MLIAP.cmake b/cmake/Modules/Packages/MLIAP.cmake index 153900e2b8..0f19c54461 100644 --- a/cmake/Modules/Packages/MLIAP.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -1,15 +1,15 @@ # if PYTHON package is included we may also include Python support in MLIAP -set(ENABLE_MLIAP_PYTHON_DEFAULT OFF) +set(MLIAP_ENABLE_PYTHON_DEFAULT OFF) if(PKG_PYTHON) find_package(Cythonize) if(Cythonize_FOUND) - set(ENABLE_MLIAP_PYTHON_DEFAULT ON) + set(MLIAP_ENABLE_PYTHON_DEFAULT ON) endif() endif() -option(ENABLE_MLIAP_PYTHON "Build MLIAP package with Python support" ${ENABLE_MLIAP_PYTHON_DEFAULT}) +option(MLIAP_ENABLE_PYTHON "Build MLIAP package with Python support" ${MLIAP_ENABLE_PYTHON_DEFAULT}) -if(ENABLE_MLIAP_PYTHON) +if(MLIAP_ENABLE_PYTHON) find_package(Cythonize REQUIRED) if(NOT_PKG_PYTHON) message(FATAL_ERROR "Must install PYTHON package for MLIAP_PYTHON") From 3eb22e240673743c7ce29c0b3abb0662f712ed81 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 17:47:21 -0500 Subject: [PATCH 19/39] cleanup and compilation for python off --- python/lammps.py | 12 ++++++------ src/MLIAP/mliap_data.cpp | 2 +- src/MLIAP/mliap_model_python.cpp | 14 +++++++++----- src/MLIAP/mliap_model_python.h | 2 +- src/MLIAP/mliap_model_python_couple.pyx | 15 ++++----------- src/MLIAP/pair_mliap.cpp | 8 ++++---- 6 files changed, 25 insertions(+), 28 deletions(-) diff --git a/python/lammps.py b/python/lammps.py index 85fbd1217b..6f88ee86a7 100644 --- a/python/lammps.py +++ b/python/lammps.py @@ -505,7 +505,7 @@ class lammps(object): self.FIX_EXTERNAL_CALLBACK_FUNC = CFUNCTYPE(None, py_object, self.c_bigint, c_int, POINTER(self.c_tagint), POINTER(POINTER(c_double)), POINTER(POINTER(c_double))) self.lib.lammps_set_fix_external_callback.argtypes = [c_void_p, c_char_p, self.FIX_EXTERNAL_CALLBACK_FUNC, py_object] self.lib.lammps_set_fix_external_callback.restype = None - + self.mliappy = MLIAPPY(self) # ------------------------------------------------------------------------- @@ -2931,12 +2931,12 @@ class MLIAPPY(): def __init__(self,lammps): self._module = None self.lammps = lammps - + @property def module(self): if self._module: return self._module - + try: # Begin Importlib magic to find the embedded python module # This is needed because the filename for liblammps does not @@ -2959,10 +2959,10 @@ class MLIAPPY(): # End Importlib magic to find the embedded python module except: raise ImportError("Could not load MLIAPPY coupling module") - + def activate(self): self.module - + def load_model(self,model): self.module.load_from_python(model) - + diff --git a/src/MLIAP/mliap_data.cpp b/src/MLIAP/mliap_data.cpp index 2559f5330d..c310f0efc7 100644 --- a/src/MLIAP/mliap_data.cpp +++ b/src/MLIAP/mliap_data.cpp @@ -29,7 +29,7 @@ MLIAPData::MLIAPData(LAMMPS *lmp, int gradgradflag_in, int *map_in, class MLIAPModel* model_in, class MLIAPDescriptor* descriptor_in, class PairMLIAP* pairmliap_in) : - Pointers(lmp), gradforce(nullptr), betas(nullptr), + Pointers(lmp), gradforce(nullptr), betas(nullptr), descriptors(nullptr), eatoms(nullptr), gamma(nullptr), gamma_row_index(nullptr), gamma_col_index(nullptr), egradient(nullptr), numneighs(nullptr), iatoms(nullptr), ielems(nullptr), jatoms(nullptr), jelems(nullptr), diff --git a/src/MLIAP/mliap_model_python.cpp b/src/MLIAP/mliap_model_python.cpp index 2aa588ff32..e47356390f 100644 --- a/src/MLIAP/mliap_model_python.cpp +++ b/src/MLIAP/mliap_model_python.cpp @@ -15,6 +15,8 @@ Contributing author: Nicholas Lubbers (LANL) ------------------------------------------------------------------------- */ +#ifdef MLIAP_PYTHON + #include #include "mliap_model_python.h" #include "mliap_model_python_couple.h" @@ -43,9 +45,9 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS* lmp, char* coefffilename) : PyGILState_Release(gstate); error->all(FLERR,"Could not initialize embedded Python"); } - + PyObject* coupling_module = PyImport_ImportModule("mliap_model_python_couple"); - + if (!coupling_module) { PyErr_Print(); PyErr_Clear(); @@ -97,7 +99,7 @@ void MLIAPModelPython::read_coeffs(char * fname) error->all(FLERR,"Loading python model failure."); } PyGILState_Release(gstate); - + if (loaded) { this->connect_param_counts(); } @@ -113,7 +115,7 @@ void MLIAPModelPython::connect_param_counts() nelements = MLIAPPY_nelements(this); nparams = MLIAPPY_nparams(this); ndescriptors = MLIAPPY_ndescriptors(this); - + if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); @@ -137,7 +139,7 @@ void MLIAPModelPython::compute_gradients(MLIAPData* data) if (not model_loaded) { error->all(FLERR,"Model not loaded."); } - + PyGILState_STATE gstate = PyGILState_Ensure(); MLIAPPY_compute_gradients(this, data); if (PyErr_Occurred()) { @@ -196,3 +198,5 @@ double MLIAPModelPython::memory_usage() // todo: get approximate memory usage in coupling code. return 0; } + +#endif diff --git a/src/MLIAP/mliap_model_python.h b/src/MLIAP/mliap_model_python.h index 0ef87f86fd..57110f36e2 100644 --- a/src/MLIAP/mliap_model_python.h +++ b/src/MLIAP/mliap_model_python.h @@ -38,7 +38,7 @@ protected: virtual void read_coeffs(char *); private: - + }; } diff --git a/src/MLIAP/mliap_model_python_couple.pyx b/src/MLIAP/mliap_model_python_couple.pyx index ad95ea2c48..49bdd47412 100644 --- a/src/MLIAP/mliap_model_python_couple.pyx +++ b/src/MLIAP/mliap_model_python_couple.pyx @@ -1,12 +1,5 @@ # cython: language_level=3 # distutils: language = c++ -# distutils: define_macros="LMP_MLIAPPY" -# distutils: extra_compile_args= -stdlib=libc++ -std=c++11 -# distutils: include_dirs = ../STUBS .. ../MLIAP -# distutils: extra_link_args= -stdlib=libc++ -# Note: only the language_level and language commands are needed, the rest pertain -# to building mliap_model_python_couple as a standalone python extension, which -# is experimental. cimport cython @@ -88,11 +81,11 @@ def load_from_python(model): LOADED_MODELS[c_id]=model lmp_model = c_id lmp_model.connect_param_counts() - + cdef public void MLIAPPY_unload_model(MLIAPModelPython * c_model) with gil: del LOADED_MODELS[c_id(c_model)] - + cdef public int MLIAPPY_nparams(MLIAPModelPython * c_model) with gil: return int(retrieve(c_model).n_params) @@ -107,7 +100,7 @@ cdef public void MLIAPPY_compute_gradients(MLIAPModelPython * c_model, MLIAPData n_d = data.ndescriptors n_a = data.natoms - + # Make numpy arrays from pointers beta_np = np.asarray( &data.betas[0][0]) desc_np = np.asarray( &data.descriptors[0][0]) @@ -116,7 +109,7 @@ cdef public void MLIAPPY_compute_gradients(MLIAPModelPython * c_model, MLIAPData # Invoke python model on numpy arrays. model(elem_np,desc_np,beta_np,en_np) - + # Get the total energy from the atom energy. energy = np.sum(en_np) data.energy = energy diff --git a/src/MLIAP/pair_mliap.cpp b/src/MLIAP/pair_mliap.cpp index 6f75ef542e..0c6f3903f6 100644 --- a/src/MLIAP/pair_mliap.cpp +++ b/src/MLIAP/pair_mliap.cpp @@ -73,17 +73,17 @@ PairMLIAP::~PairMLIAP() void PairMLIAP::compute(int eflag, int vflag) { - + // consistency checks if (data->ndescriptors != model->ndescriptors) { error->all(FLERR,"Incompatible model and descriptor descriptor count"); }; - + if (data->nelements != model->nelements) { error->all(FLERR,"Incompatible model and descriptor element count"); }; - + ev_init(eflag,vflag); data->generate_neighdata(list, eflag, vflag); @@ -249,7 +249,7 @@ void PairMLIAP::coeff(int narg, char **arg) void PairMLIAP::e_tally(MLIAPData* data) { if (eflag_global) eng_vdwl += data->energy; - if (eflag_atom) + if (eflag_atom) for (int ii = 0; ii < data->natoms; ii++) { const int i = data->iatoms[ii]; eatom[i] += data->eatoms[ii]; From 2ccb39b54c3c82bc70cdbee2ccaa976adac33455 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 17:49:07 -0500 Subject: [PATCH 20/39] doc updates --- doc/src/Build_extras.rst | 35 +++++++++++++++++++++++++++++++++++ doc/src/compute_mliap.rst | 6 +++--- doc/src/pair_mliap.rst | 6 +++--- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index 5ef29fbca1..8b11ede347 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -37,6 +37,7 @@ This is the list of packages that may require additional steps. * :ref:`KOKKOS ` * :ref:`LATTE ` * :ref:`MESSAGE ` + * :ref:`MLIAP ` * :ref:`MSCG ` * :ref:`OPT ` * :ref:`POEMS ` @@ -732,6 +733,40 @@ be installed on your system. ---------- +.. _mliap: + +MLIAP package +--------------------------- + +Building the MLIAP package requires also enabling the SNAP package. +There will be an error message if this requirement is not satisfied. +Using the *mliappy* model also requires enabling the PYTHON package +**and** requires you have the `cython `_ software +installed and a working ``cythonize`` command. This requires Python +version 3.6 or later. + +.. tabs:: + + .. tab:: CMake build + + .. code-block:: bash + + -D MLIAP_ENABLE_PYTHON=value # enable mliappy model (default is autodetect) + + Without this setting, CMake will check whether it can find a + suitable Python version and the ``cythonize`` command and choose + the default accordingly. + + .. tab:: Traditional make + + The build uses the ``lib/python/Makefile.mliap_python`` file in the + compile/link process to add a rule to update the files generated by + the ``cythonize`` command in case the corresponding .pyx file was + modified. You may need to need to modify ``lib/python/Makefile.lammps`` + if the LAMMPS build fails. + +---------- + .. _mscg: MSCG package diff --git a/doc/src/compute_mliap.rst b/doc/src/compute_mliap.rst index 66bf868e0d..579086ad4a 100644 --- a/doc/src/compute_mliap.rst +++ b/doc/src/compute_mliap.rst @@ -56,14 +56,14 @@ and it is also straightforward to add new descriptor styles. The compute *mliap* command must be followed by two keywords *model* and *descriptor* in either order. -The *model* keyword is followed by the model style (*linear*, *quadratic* or *mliappy*). +The *model* keyword is followed by the model style (*linear*, *quadratic* or *mliappy*). The *mliappy* model is only available if lammps is built with MLIAPPY package. The *descriptor* keyword is followed by a descriptor style, and additional arguments. -The compute currently supports just one descriptor style, but it is +The compute currently supports just one descriptor style, but it is is straightforward to add new descriptor styles. -The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, +The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, including the linear, quadratic, and chem variants. A single additional argument specifies the descriptor filename containing the parameters and setting used by the SNAP descriptor. diff --git a/doc/src/pair_mliap.rst b/doc/src/pair_mliap.rst index 4c1845d514..9dd8c5c6b1 100644 --- a/doc/src/pair_mliap.rst +++ b/doc/src/pair_mliap.rst @@ -41,9 +41,9 @@ and the geometric quantities that characterize the atomic positions (*descriptor*). By defining *model* and *descriptor* separately, it is possible to use many different models with a given descriptor, or many different descriptors with a given model. The -pair style currently supports just one descriptor style, but it is +pair style currently supports just one descriptor style, but it is is straightforward to add new descriptor styles. -The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, +The SNAP descriptor style *sna* is the same as that used by :doc:`pair_style snap `, including the linear, quadratic, and chem variants. The available models are *linear*, *quadratic*, and *mliappy*. The *mliappy* style can be used to couple python models, @@ -62,7 +62,7 @@ that specify the mapping of MLIAP element names to LAMMPS atom types, where N is the number of LAMMPS atom types. -The *model* keyword is followed by the model style. This is followed +The *model* keyword is followed by the model style. This is followed by a single argument specifying the model filename containing the parameters for a set of elements. The model filename usually ends in the *.mliap.model* extension. From 161fdbd7ec356bb2022f1ef56f1bab396aa9e98e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 18:28:13 -0500 Subject: [PATCH 21/39] whitespace --- doc/src/lattice.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/lattice.rst b/doc/src/lattice.rst index e937541864..b87ddaaf70 100644 --- a/doc/src/lattice.rst +++ b/doc/src/lattice.rst @@ -254,9 +254,9 @@ in commands that use the spacings should be decipherable. Example commands for generating a Wurtzite crystal. The lattice constants approximate those of CdSe. The :math:`\sqrt{3}\times 1` orthorhombic supercell is used -with the x, y, and z directions oriented -along :math:`[\bar{1}\bar{2}30]`, -:math:`[10\bar{1}0]`, and :math:`[0001]`, respectively. +with the x, y, and z directions oriented +along :math:`[\bar{1}\bar{2}30]`, +:math:`[10\bar{1}0]`, and :math:`[0001]`, respectively. .. code-block:: LAMMPS From 77168b510512393aec275c026195c60b125395a2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 18:32:11 -0500 Subject: [PATCH 22/39] delete hack --- lib/python/Makefile.lammps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Makefile.lammps b/lib/python/Makefile.lammps index adda24caec..4289674e99 100644 --- a/lib/python/Makefile.lammps +++ b/lib/python/Makefile.lammps @@ -2,6 +2,6 @@ # See the README file for more explanation python_SYSINC = $(shell which python-config > /dev/null 2>&1 && python-config --includes || :) -python_SYSLIB = -lpython3 $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :) +python_SYSLIB = $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :) python_SYSPATH = PYTHON=python From 5b6b327a5d4a36bcd7bdca557f104cc347d0a46d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 8 Dec 2020 00:04:54 -0500 Subject: [PATCH 23/39] fix CMake errors --- cmake/Modules/LAMMPSUtils.cmake | 2 +- cmake/Modules/Packages/MLIAP.cmake | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/LAMMPSUtils.cmake b/cmake/Modules/LAMMPSUtils.cmake index fb1203ec73..37275843fa 100644 --- a/cmake/Modules/LAMMPSUtils.cmake +++ b/cmake/Modules/LAMMPSUtils.cmake @@ -50,7 +50,7 @@ function(check_for_autogen_files source_dir) file(GLOB SRC_AUTOGEN_FILES ${source_dir}/style_*.h) file(GLOB SRC_AUTOGEN_PACKAGES ${source_dir}/packages_*.h) list(APPEND SRC_AUTOGEN_FILES ${SRC_AUTOGEN_PACKAGES} ${source_dir}/lmpinstalledpkgs.h ${source_dir}/lmpgitversion.h) - list(APPEND SRC_AUTOGEN_FILES ${SRC_AUTOGEN_PACKAGES} ${source_dir}/MLIAP/mliap_model_python_couple ${source_dir}/MLIAP/mliap_model_python_couple.cpp) + list(APPEND SRC_AUTOGEN_FILES ${SRC_AUTOGEN_PACKAGES} ${source_dir}/mliap_model_python_couple.h ${source_dir}/mliap_model_python_couple.cpp) foreach(_SRC ${SRC_AUTOGEN_FILES}) get_filename_component(FILENAME "${_SRC}" NAME) if(EXISTS ${source_dir}/${FILENAME}) diff --git a/cmake/Modules/Packages/MLIAP.cmake b/cmake/Modules/Packages/MLIAP.cmake index 0f19c54461..0fba0fd63d 100644 --- a/cmake/Modules/Packages/MLIAP.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -11,8 +11,8 @@ option(MLIAP_ENABLE_PYTHON "Build MLIAP package with Python support" ${MLIAP_ENA if(MLIAP_ENABLE_PYTHON) find_package(Cythonize REQUIRED) - if(NOT_PKG_PYTHON) - message(FATAL_ERROR "Must install PYTHON package for MLIAP_PYTHON") + if(NOT PKG_PYTHON) + message(FATAL_ERROR "Must install PYTHON package for MLIAP with Python support") endif() set(MLIAP_CYTHON_DIR ${CMAKE_BINARY_DIR}/cython) From c4ee2f2e4243c5c79832eb03916b39b40ae9d3d7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 8 Dec 2020 00:28:16 -0500 Subject: [PATCH 24/39] don't need Python interpreter for compiling the PYTHON package --- cmake/Modules/Packages/PYTHON.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/Packages/PYTHON.cmake b/cmake/Modules/Packages/PYTHON.cmake index e3158dc509..ef8b056a85 100644 --- a/cmake/Modules/Packages/PYTHON.cmake +++ b/cmake/Modules/Packages/PYTHON.cmake @@ -3,7 +3,7 @@ if(CMAKE_VERSION VERSION_LESS 3.12) target_include_directories(lammps PRIVATE ${PYTHON_INCLUDE_DIRS}) target_link_libraries(lammps PRIVATE ${PYTHON_LIBRARIES}) else() - find_package(Python REQUIRED COMPONENTS Development Interpreter) + find_package(Python REQUIRED COMPONENTS Development) target_include_directories(lammps PRIVATE ${Python_INCLUDE_DIRS}) target_link_libraries(lammps PRIVATE Python::Python) endif() From ddcd5a3c2e856d174960f635062628f36c2cac0d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Dec 2020 10:28:12 -0500 Subject: [PATCH 25/39] small CMake tweaks and cleanups --- cmake/Modules/Packages/MLIAP.cmake | 4 ++-- cmake/Modules/Packages/PYTHON.cmake | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/Packages/MLIAP.cmake b/cmake/Modules/Packages/MLIAP.cmake index 0fba0fd63d..ffb10acec9 100644 --- a/cmake/Modules/Packages/MLIAP.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -12,14 +12,14 @@ option(MLIAP_ENABLE_PYTHON "Build MLIAP package with Python support" ${MLIAP_ENA if(MLIAP_ENABLE_PYTHON) find_package(Cythonize REQUIRED) if(NOT PKG_PYTHON) - message(FATAL_ERROR "Must install PYTHON package for MLIAP with Python support") + message(FATAL_ERROR "Must enable PYTHON package for including Python support in MLIAP") endif() set(MLIAP_CYTHON_DIR ${CMAKE_BINARY_DIR}/cython) file(MAKE_DIRECTORY ${MLIAP_CYTHON_DIR}) add_custom_command(OUTPUT ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.cpp ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.h COMMAND ${CMAKE_COMMAND} -E copy ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx - COMMAND ${Cythonize_EXECUTABLE} ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx -3 + COMMAND ${Cythonize_EXECUTABLE} -3 ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx WORKING_DIRECTORY ${MLIAP_CYTHON_DIR} MAIN_DEPENDENCY ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx COMMENT "Generating C++ sources with cythonize...") diff --git a/cmake/Modules/Packages/PYTHON.cmake b/cmake/Modules/Packages/PYTHON.cmake index ef8b056a85..7be25a6b05 100644 --- a/cmake/Modules/Packages/PYTHON.cmake +++ b/cmake/Modules/Packages/PYTHON.cmake @@ -4,7 +4,6 @@ if(CMAKE_VERSION VERSION_LESS 3.12) target_link_libraries(lammps PRIVATE ${PYTHON_LIBRARIES}) else() find_package(Python REQUIRED COMPONENTS Development) - target_include_directories(lammps PRIVATE ${Python_INCLUDE_DIRS}) target_link_libraries(lammps PRIVATE Python::Python) endif() target_compile_definitions(lammps PRIVATE -DLMP_PYTHON) From 50a9ac92a7ecc73dc3c53500f2e75da891f9382f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Dec 2020 10:28:27 -0500 Subject: [PATCH 26/39] update docs for MLIAP some more --- doc/src/Build_extras.rst | 26 +++++++++++++++++++------- doc/src/Packages_details.rst | 12 +++++++----- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index 8b11ede347..34a75b66dc 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -738,12 +738,12 @@ be installed on your system. MLIAP package --------------------------- -Building the MLIAP package requires also enabling the SNAP package. -There will be an error message if this requirement is not satisfied. -Using the *mliappy* model also requires enabling the PYTHON package -**and** requires you have the `cython `_ software -installed and a working ``cythonize`` command. This requires Python -version 3.6 or later. +Building the MLIAP package requires including the :ref:`SNAP ` +package. There will be an error message if this requirement is not satisfied. +Using the *mliappy* model also requires enabling the :ref:`PYTHON ` +package **and** requires you have the `cython `_ software +installed and with it a working ``cythonize`` command. This feature requires +compiling LAMMPS with Python version 3.6 or later. .. tabs:: @@ -755,7 +755,11 @@ version 3.6 or later. Without this setting, CMake will check whether it can find a suitable Python version and the ``cythonize`` command and choose - the default accordingly. + the default accordingly. During the build procedure the provided + .pyx file(s) will be automatically translated to C++ code and compiled. + Please do **not** run ``cythonize`` manually in the ``src/MLIAP`` folder, + as that can lead to compilation errors if PYTHON support is not included. + If you did by accident, please remove the generated .cpp and .h files. .. tab:: Traditional make @@ -764,6 +768,14 @@ version 3.6 or later. the ``cythonize`` command in case the corresponding .pyx file was modified. You may need to need to modify ``lib/python/Makefile.lammps`` if the LAMMPS build fails. + To manually enforce building MLIAP with Python support, you can add + ``-DMLIAP_PYTHON`` to the ``LMP_INC`` variable in your machine makefile. + You may have to manually run the cythonize command on .pyx file(s) + in the ``src`` folder, if this is not automatically done during + installing the MLIAP package. Please do **not** run ``cythonize`` + in the ``src/MLIAP`` folder, as that can lead to compilation errors + if PYTHON support is not included. + If you did by accident, please remove the generated .cpp and .h files. ---------- diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index 3fb906addf..e044adfcb3 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -668,8 +668,9 @@ A general interface for machine-learning interatomic potentials, including PyTor To use this package, also the :ref:`SNAP package ` package needs to be installed. To make the *mliappy* model available, also the -:ref:`PYTHON package ` package needs to be installed and the version of -python must be 3.5 or later. +:ref:`PYTHON package ` package needs to be installed, the version of +Python must be 3.6 or later, and the `cython `_ software +must be installed. **Author:** Aidan Thompson (Sandia), Nicholas Lubbers (LANL). @@ -682,9 +683,10 @@ python must be 3.5 or later. * examples/mliap (see README) When built with the *mliappy* model this package includes an extension for -coupling with python models, including PyTorch. -In this case, the python interpreter linked to LAMMPS will need cython and numpy installed. -The examples build models with PyTorch, which would thus need to be installed. +coupling with Python models, including PyTorch. In this case, the Python +interpreter linked to LAMMPS will need the ``cython`` and ``numpy`` modules +installed. The provided examples build models with PyTorch, which would +therefore also needs to be installed to run those examples. ---------- From f7e0fbf064b610781c643066e0eea54692479456 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Dec 2020 10:28:40 -0500 Subject: [PATCH 27/39] update MLIAP readme files --- examples/mliap/README.pytorch | 4 ++-- src/MLIAP/README | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/examples/mliap/README.pytorch b/examples/mliap/README.pytorch index 7f511168a7..49868208fe 100644 --- a/examples/mliap/README.pytorch +++ b/examples/mliap/README.pytorch @@ -17,8 +17,8 @@ From that point you can run the example lmp -in in.mliap.pytorch.Ta06A -echo bot 2: Running models from python with LAMMPS in library mode: mliap_pytorch_Ta06A.py Before testing this, ensure that the first example (using LAMMPS executable) works. -Also, not all python installations support this mode of operation. -It requires that the Python interpreter be initialized. +Also, not all python installations support this mode of operation. +It requires that the Python interpreter be initialized. To check this for your Python library, run the Py_IsInitialized() method. If the return value is True, you should be able to run the example, diff --git a/src/MLIAP/README b/src/MLIAP/README index d94a1bac16..7841b7c158 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -32,14 +32,17 @@ potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP>. *Additional instructions for compiling PyTorch energy models* The *MLIAPPY* extension written by Nick Lubbers (LANL) -provides a coupling to PyTorch energy models. +provides a coupling to PyTorch energy models. This should be automatically +enabled by default if the prerequisite software is installed. It can be +enforced during CMake configuration by setting the variable +MLIAP_ENABLE_PYTHON=yes or for conventional build by adding -DMLIAP_PYTHON +to the LMP_INC variable in your makefile and running the cythonize script +on the .pyx file(s) copied to the src folder. -Before compiling LAMMPS with either make or cmake, you have -to run cythonize to create the coupling source files -in the src/MLIAP directory e.g. +This requires to also install the PYTHON package and have the cython +(https://cython.org) software installed. During configuration/compilation +the cythonize script will be used to convert the provided .pyx file(s) +to C++ code. Please do not run the cythonize script in the src/MLIAP folder. +If you have done so by accident, you need to delete the generated .cpp and .h +file(s) in the src/MLIAP folder or there may be problems during compilation. -cd src/MLIAP -cythonize mliap_model_python_couple.pyx - -After that, install the MLIAP package with make or cmake -and build LAMMPS. From cc222791a58e5aee2484613e568e17bc425836f5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Dec 2020 10:47:06 -0500 Subject: [PATCH 28/39] use variables to infer filenames from original .pyx source --- cmake/Modules/Packages/MLIAP.cmake | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/cmake/Modules/Packages/MLIAP.cmake b/cmake/Modules/Packages/MLIAP.cmake index ffb10acec9..d3f601a1e1 100644 --- a/cmake/Modules/Packages/MLIAP.cmake +++ b/cmake/Modules/Packages/MLIAP.cmake @@ -15,15 +15,17 @@ if(MLIAP_ENABLE_PYTHON) message(FATAL_ERROR "Must enable PYTHON package for including Python support in MLIAP") endif() - set(MLIAP_CYTHON_DIR ${CMAKE_BINARY_DIR}/cython) - file(MAKE_DIRECTORY ${MLIAP_CYTHON_DIR}) - add_custom_command(OUTPUT ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.cpp ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.h - COMMAND ${CMAKE_COMMAND} -E copy ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx - COMMAND ${Cythonize_EXECUTABLE} -3 ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.pyx - WORKING_DIRECTORY ${MLIAP_CYTHON_DIR} - MAIN_DEPENDENCY ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx - COMMENT "Generating C++ sources with cythonize...") + set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython) + set(MLIAP_CYTHON_SRC ${LAMMPS_SOURCE_DIR}/MLIAP/mliap_model_python_couple.pyx) + get_filename_component(MLIAP_CYTHON_BASE ${MLIAP_CYTHON_SRC} NAME_WE) + file(MAKE_DIRECTORY ${MLIAP_BINARY_DIR}) + add_custom_command(OUTPUT ${MLIAP_BINARY_DIR}/${MLIAP_CYTHON_BASE}.cpp ${MLIAP_BINARY_DIR}/${MLIAP_CYTHON_BASE}.h + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MLIAP_CYTHON_SRC} ${MLIAP_BINARY_DIR}/${MLIAP_CYTHON_BASE}.pyx + COMMAND ${Cythonize_EXECUTABLE} -3 ${MLIAP_BINARY_DIR}/${MLIAP_CYTHON_BASE}.pyx + WORKING_DIRECTORY ${MLIAP_BINARY_DIR} + MAIN_DEPENDENCY ${MLIAP_CYTHON_SRC} + COMMENT "Generating C++ sources with cythonize...") target_compile_definitions(lammps PRIVATE -DMLIAP_PYTHON) - target_sources(lammps PRIVATE ${MLIAP_CYTHON_DIR}/mliap_model_python_couple.cpp) - target_include_directories(lammps PRIVATE ${MLIAP_CYTHON_DIR}) + target_sources(lammps PRIVATE ${MLIAP_BINARY_DIR}/${MLIAP_CYTHON_BASE}.cpp) + target_include_directories(lammps PRIVATE ${MLIAP_BINARY_DIR}) endif() From 56feb03b38bea4d141c330b7071425831cec5513 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 9 Dec 2020 16:51:36 -0700 Subject: [PATCH 29/39] Edits to README --- examples/mliap/README | 74 +++++++++++++++++++++++++++ examples/mliap/README.pytorch | 35 ------------- examples/mliap/convert_mliap_Ta06A.py | 2 +- examples/mliap/in.mliap.snap.Ta06A | 2 +- 4 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 examples/mliap/README delete mode 100644 examples/mliap/README.pytorch diff --git a/examples/mliap/README b/examples/mliap/README new file mode 100644 index 0000000000..68b6f2e200 --- /dev/null +++ b/examples/mliap/README @@ -0,0 +1,74 @@ +This directory contains multipler examples of +machine-learning potentials defined using the +MLIAP package in LAMMPS. The input files +are descirbed below. + +in.mliap.snap.Ta06A +------------------- +Run linear SNAP, equivalent to examples/snap/in.snap.Ta06A + +in.mliap.snap.WBe.PRB2019 +------------------------- +Run linear SNAP, equivalent to examples/snap/in.snap.WBe.PRB2019 + +in.mliap.snap.quadratic +----------------------- +Run quadratic SNAP + +in.mliap.snap.chem +------------------ +Run EME-SNAP, equivalent to examples/snap/in.snap.InP.JCPA2020 + +in.mliap.snap.compute +--------------------- +Generate gradients w.r.t. coefficients for linear SNAP, +equivalent to in.snap.compute + +in.mliap.quadratic.compute +-------------------------- +Generate gradients w.r.t. coefficients for quadratic SNAP, +equivalent to in.snap.compute.quadratic + +in.mliap.pytorch.Ta06A +----------------------- +This reproduces the output of in.mliap.snap.Ta06A above, +but using the Python coupling to PyTorch. +It can be run in two different ways: + +1: Running a LAMMPS executable: in.mliap.pytorch.Ta06A + +First run convert_mliap_Ta06A.py, which will convert the Ta06A potential +into a pytorch model. It will be saved as "Ta06A.mliap.pytorch.model.pkl". + +It will also copy "../../src/MLIAP/mliappy_pytorch.py" +file into the current working directory. mliappy_pytorch.py contains +class definitions suitable for wrapping an arbitrary PyTorch +energy model. It must be available to python when +creating or unpickling a PyTorch energy model. + +From that point you can run the example as follows + +`lmp -in in.mliap.pytorch.Ta06A -echo both` + +The resultant log.lammps output should be identical to that generated +by in.mliap.snap.Ta06A. + +2: Running a Python script: mliap_pytorch_Ta06A.py + +Before testing this, ensure that the first example +(using LAMMPS executable) works. +Also, not all python installations support this mode of operation. +It requires that the Python interpreter be initialized. +To check this for your Python library, +try running the Py_IsInitialized() method. +If the return value is True, you should be able to run the example, +as follows: + +`python mliap_pytorch_Ta06A.py` + +or + +`mpirun -np 4 python mliap_pytorch_Ta06A.py` + +The resultant log.lammps output should be identical to that generated +by in.mliap.snap.Ta06A and in.mliap.pytorch.Ta06A. diff --git a/examples/mliap/README.pytorch b/examples/mliap/README.pytorch deleted file mode 100644 index 49868208fe..0000000000 --- a/examples/mliap/README.pytorch +++ /dev/null @@ -1,35 +0,0 @@ -README for the PyTorch energy model example - -These two examples run the Ta06 example from the MLIAP package, but using the python coupling. -The differ only in how the coupling is constructed. - -1: Running models using LAMMPS executable: in.mliap.pytorch.Ta06A - -To run this, first run convert_mliap_Ta06A.py, which will convert the Ta06 potential into a pytorch model. -It will be saved as "Ta06A.mliap.pytorch.model.pkl". - -It will also copy the "mliappy_pytorch.py" file into the current working directory. mliappy_pytorch.py contains -class definitions suitable for wrapping an arbitrary PyTorch energy model. It must be available to python when -creating or unpicking a PyTorch energy model. - -From that point you can run the example lmp -in in.mliap.pytorch.Ta06A -echo both - -2: Running models from python with LAMMPS in library mode: mliap_pytorch_Ta06A.py - -Before testing this, ensure that the first example (using LAMMPS executable) works. -Also, not all python installations support this mode of operation. -It requires that the Python interpreter be initialized. -To check this for your Python library, -run the Py_IsInitialized() method. -If the return value is True, you should be able to run the example, -as follows: - -`python mliap_pytorch_Ta06A.py` - -or - -`mpirun -np 4 python mliap_pytorch_Ta06A.py` - -The resultant log.lammps output should be identical to that generated -by in.mliap.snap.Ta06A and in.mliap.pytorch.Ta06A - diff --git a/examples/mliap/convert_mliap_Ta06A.py b/examples/mliap/convert_mliap_Ta06A.py index 6f10f8303c..ba95678c9e 100644 --- a/examples/mliap/convert_mliap_Ta06A.py +++ b/examples/mliap/convert_mliap_Ta06A.py @@ -21,7 +21,7 @@ with torch.autograd.no_grad(): lin.weight.set_(torch.from_numpy(weights).unsqueeze(0)) lin.bias.set_(torch.as_tensor(bias,dtype=torch.float64).unsqueeze(0)) -# Wrap the pytorch model for usage with MLIAPPY +# Wrap the pytorch model for usage with mliappy energy model model = mliappy_pytorch.IgnoreElems(lin) n_descriptors = lin.weight.shape[1] n_params = mliappy_pytorch.calc_n_params(model) diff --git a/examples/mliap/in.mliap.snap.Ta06A b/examples/mliap/in.mliap.snap.Ta06A index 3d94d5c9fc..7b9b5b47d1 100644 --- a/examples/mliap/in.mliap.snap.Ta06A +++ b/examples/mliap/in.mliap.snap.Ta06A @@ -1,4 +1,4 @@ -# Demonstrate MLIAP interface to kinear SNAP potential +# Demonstrate MLIAP interface to linear SNAP potential # Initialize simulation From 4964a569749528df10c58cce85eea237de291531 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 9 Dec 2020 17:12:35 -0700 Subject: [PATCH 30/39] Tweaked build instructions --- doc/src/Build_extras.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index 34a75b66dc..adbfa02952 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -741,7 +741,7 @@ MLIAP package Building the MLIAP package requires including the :ref:`SNAP ` package. There will be an error message if this requirement is not satisfied. Using the *mliappy* model also requires enabling the :ref:`PYTHON ` -package **and** requires you have the `cython `_ software +package **and** requires you have the `cython `_ software installed and with it a working ``cythonize`` command. This feature requires compiling LAMMPS with Python version 3.6 or later. @@ -765,16 +765,17 @@ compiling LAMMPS with Python version 3.6 or later. The build uses the ``lib/python/Makefile.mliap_python`` file in the compile/link process to add a rule to update the files generated by - the ``cythonize`` command in case the corresponding .pyx file was - modified. You may need to need to modify ``lib/python/Makefile.lammps`` + the ``cythonize`` command in case the corresponding .pyx file(s) were + modified. You may need to modify ``lib/python/Makefile.lammps`` if the LAMMPS build fails. - To manually enforce building MLIAP with Python support, you can add + To manually enforce building MLIAP with Python support enabled, + you can add ``-DMLIAP_PYTHON`` to the ``LMP_INC`` variable in your machine makefile. You may have to manually run the cythonize command on .pyx file(s) in the ``src`` folder, if this is not automatically done during installing the MLIAP package. Please do **not** run ``cythonize`` in the ``src/MLIAP`` folder, as that can lead to compilation errors - if PYTHON support is not included. + if Python support is not enabled. If you did by accident, please remove the generated .cpp and .h files. ---------- From b8a7edfaa1434a6fd96535fd99d0949f3f0015d1 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 9 Dec 2020 17:27:20 -0700 Subject: [PATCH 31/39] Tried to distinguish MLIAP package with Python support from PYTHON package --- doc/src/Build_extras.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index adbfa02952..5fa68778b6 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -740,7 +740,8 @@ MLIAP package Building the MLIAP package requires including the :ref:`SNAP ` package. There will be an error message if this requirement is not satisfied. -Using the *mliappy* model also requires enabling the :ref:`PYTHON ` +Using the *mliappy* model also requires enabling Python support, which +in turn requires the :ref:`PYTHON ` package **and** requires you have the `cython `_ software installed and with it a working ``cythonize`` command. This feature requires compiling LAMMPS with Python version 3.6 or later. @@ -758,7 +759,7 @@ compiling LAMMPS with Python version 3.6 or later. the default accordingly. During the build procedure the provided .pyx file(s) will be automatically translated to C++ code and compiled. Please do **not** run ``cythonize`` manually in the ``src/MLIAP`` folder, - as that can lead to compilation errors if PYTHON support is not included. + as that can lead to compilation errors if Python support is not enabled. If you did by accident, please remove the generated .cpp and .h files. .. tab:: Traditional make @@ -771,7 +772,7 @@ compiling LAMMPS with Python version 3.6 or later. To manually enforce building MLIAP with Python support enabled, you can add ``-DMLIAP_PYTHON`` to the ``LMP_INC`` variable in your machine makefile. - You may have to manually run the cythonize command on .pyx file(s) + You may have to manually run the ``cythonize`` command on .pyx file(s) in the ``src`` folder, if this is not automatically done during installing the MLIAP package. Please do **not** run ``cythonize`` in the ``src/MLIAP`` folder, as that can lead to compilation errors From 8f10691ae63f5747d4aed3271b74730bd141d8b7 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 9 Dec 2020 17:33:29 -0700 Subject: [PATCH 32/39] Added link to on-line build info --- src/MLIAP/README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MLIAP/README b/src/MLIAP/README index 7841b7c158..21c34ade5c 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -46,3 +46,7 @@ to C++ code. Please do not run the cythonize script in the src/MLIAP folder. If you have done so by accident, you need to delete the generated .cpp and .h file(s) in the src/MLIAP folder or there may be problems during compilation. +More information on building LAMMPS with this package is here: + +https://lammps.sandia.gov/doc/html/Build_extras.html#mliap + From bf0acf9581a64aeb3147c57f971560ab5ebd007a Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 9 Dec 2020 17:38:31 -0700 Subject: [PATCH 33/39] Tried to distinguish MLIAP package with Python support from PYTHON package --- src/MLIAP/README | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/MLIAP/README b/src/MLIAP/README index 21c34ade5c..9179d9d02f 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -29,10 +29,13 @@ To see how this command can be used within a Python workflow to train machine-learning interatomic potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP>. -*Additional instructions for compiling PyTorch energy models* +*Additional instructions for building MLIAP with Python support enabled* -The *MLIAPPY* extension written by Nick Lubbers (LANL) -provides a coupling to PyTorch energy models. This should be automatically +The *mliappy* energy model requires that the MLIAP package +be compiled with Python support enabled. +This extension written by Nick Lubbers (LANL) +provides a coupling to PyTorch and other Python modules. +This should be automatically enabled by default if the prerequisite software is installed. It can be enforced during CMake configuration by setting the variable MLIAP_ENABLE_PYTHON=yes or for conventional build by adding -DMLIAP_PYTHON From 3dea3188aa7b71e71e2070f58d10c133bf43121c Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Tue, 15 Dec 2020 12:14:03 -0700 Subject: [PATCH 34/39] Added a simple neural network potential --- examples/mliap/README | 8 +++ examples/mliap/in.mliap.pytorch.relu1hidden | 53 ++++++++++++++++++ examples/mliap/relu1hidden.mliap.pytorch | 18 ++++++ .../mliap/relu1hidden.mliap.pytorch.model.pkl | Bin 0 -> 4059 bytes 4 files changed, 79 insertions(+) create mode 100644 examples/mliap/in.mliap.pytorch.relu1hidden create mode 100644 examples/mliap/relu1hidden.mliap.pytorch create mode 100644 examples/mliap/relu1hidden.mliap.pytorch.model.pkl diff --git a/examples/mliap/README b/examples/mliap/README index 68b6f2e200..2641bdc975 100644 --- a/examples/mliap/README +++ b/examples/mliap/README @@ -72,3 +72,11 @@ or The resultant log.lammps output should be identical to that generated by in.mliap.snap.Ta06A and in.mliap.pytorch.Ta06A. + +in.mliap.pytorch.relu1hidden +---------------------------- +This example demonstrates a simple neural network potential +using PyTorch and SNAP descriptors. It uses a ReLU activation +function with just 1 hidden layer. + +`lmp -in in.mliap.pytorch.relu1hidden -echo both` diff --git a/examples/mliap/in.mliap.pytorch.relu1hidden b/examples/mliap/in.mliap.pytorch.relu1hidden new file mode 100644 index 0000000000..f19ffb608d --- /dev/null +++ b/examples/mliap/in.mliap.pytorch.relu1hidden @@ -0,0 +1,53 @@ +# Demonstrate MLIAP interface to linear SNAP potential + +# Initialize simulation + +variable nsteps index 100 +variable nrep equal 4 +variable a equal 3.316 +units metal + +# generate the box and atom positions using a BCC lattice + +variable nx equal ${nrep} +variable ny equal ${nrep} +variable nz equal ${nrep} + +boundary p p p + +lattice bcc $a +region box block 0 ${nx} 0 ${ny} 0 ${nz} +create_box 1 box +create_atoms 1 box + +mass 1 180.88 + +# choose potential + +include relu1hidden.mliap.pytorch + +# Setup output + +compute eatom all pe/atom +compute energy all reduce sum c_eatom + +compute satom all stress/atom NULL +compute str all reduce sum c_satom[1] c_satom[2] c_satom[3] +variable press equal (c_str[1]+c_str[2]+c_str[3])/(3*vol) + +thermo_style custom step temp epair c_energy etotal press v_press +thermo 10 +thermo_modify norm yes + +# Set up NVE run + +timestep 0.5e-3 +neighbor 1.0 bin +neigh_modify once no every 1 delay 0 check yes + +# Run MD + +velocity all create 300.0 4928459 loop geom +fix 1 all nve +run ${nsteps} + diff --git a/examples/mliap/relu1hidden.mliap.pytorch b/examples/mliap/relu1hidden.mliap.pytorch new file mode 100644 index 0000000000..a2271cee39 --- /dev/null +++ b/examples/mliap/relu1hidden.mliap.pytorch @@ -0,0 +1,18 @@ +# DATE: 2014-09-05 UNITS: metal CONTRIBUTOR: Aidan Thompson athomps@sandia.gov CITATION: Thompson, Swiler, Trott, Foiles and Tucker, arxiv.org, 1409.3880 (2014) + +# Definition of SNAP potential Ta_Cand06A +# Assumes 1 LAMMPS atom type + +variable zblcutinner equal 4 +variable zblcutouter equal 4.8 +variable zblz equal 73 + +# Specify hybrid with SNAP, ZBL + +pair_style hybrid/overlay & +zbl ${zblcutinner} ${zblcutouter} & +mliap model mliappy relu1hidden.mliap.pytorch.model.pkl & +descriptor sna Ta06A.mliap.descriptor +pair_coeff 1 1 zbl ${zblz} ${zblz} +pair_coeff * * mliap Ta + diff --git a/examples/mliap/relu1hidden.mliap.pytorch.model.pkl b/examples/mliap/relu1hidden.mliap.pytorch.model.pkl new file mode 100644 index 0000000000000000000000000000000000000000..49e70ca1a4f00345b5ce4ab4afb4d1e7549bba38 GIT binary patch literal 4059 zcmds4`+pSG6`v%Vg{(kCl&8gMDHyE8JbB0?Lj)9;=kQvJbf1&Vz-D&O%q$_0z((98 zAo36ev{p9(tQJ069#PQ94unTPBFaM%KDM$*v85mM^J(cv>4ScH&zYfwTK)i=ANHH` zxaWTFx#!+FH=Y%&3M>9-w8k5)F(O(}cFn}!IU3VR+RzdgaD(e1qYg6jJe@g?Gc>=V zDrzNUHF@q}vN!72{8f@6X*xK9!ALkP1q~&l>aM9;NYbRxI3;MfAbYR~P72@+#40M# zyOWH{&Ypf4MUALlHlMEOhNK!de7w43Ku$0aQ^JPALNd_>uK93B0=kIM)su@u1ODK` zYQGlp%8|%I9lBB2Tu(Q&RYbH7raQ^h-E&t*Q&f}ek#~`~ho?K5b;EB+-Vh^iTkj_8 zJ)XX34M+T;jxINY^dz@l)>5k?p;%bbp*Jb}c(U18rjx?Z_d98ySgA%dX?$3!(p}Jx z<^0|{_(7hW)g(J;bbr}O*nM)2%u>K7;D;joNVb+cK(^NQW7%57K-r=@NVfRgFIyDy zJWfVIj|Ehg*ug>C@O)Lxw~6KlBdWpnSJGTFB#5z{Q2b#RJiyreqz)eJz-EZeCf{Q7 zPyz}>D74uW*=&k!HYGNjQk%_Co6WF1PX?n?0K>n_B+OX&HP<8yU<9M^a2<^7Kw*@% zm}*I>lnoedhw#P>C9J!=nuJvox>=qs7;_sJR&jbn^DZiKL0O*dqqEfbD=HThdEMdhk!je}~LyBL8%qEYEDUF(_z>!ClqRSD@fNXcBCyTi# zssT>7!{fjh5q1DOxgD_>n={YTiK%SDz*!4$jf=zrVQGfF49KAKFrs*PQE5SONzsU* zLx&ZC6*w4;L6&>Z6ayU7S-APY{V(4PfBqgejs3@;zrMGO{hzG8wu$hA%b%xEUi^uP zGI#C3MMNRo`abD@{)-P$Hu;(Dh{;vl$EY_$*(XW<%h@A{!nr2$OXnYIM%kB|+lt7K z3nUQJy~n;qe#`#wG2z%XG>+%yyqRM5c&^-znC{>H9-=w&;xR;_^}ePu!Yi#PbG6qF zqnsXcoZ^|~?v1E7&tKb)dULS$F3QP?Ija$U<2^eO)6I*2P5Skh4mNY7bH>*xP`nt1vy4mpB;eDS3Nh`x#skCOaE=~hH@ z){fnX@tiq3%NTM?`?VqRGioTF@AG^2qn+zLoA~(t(MJBqEOa5{X+W8{Y%FA2x_o19#nQ86gk?Q>@C!3oulK+-oXUIPJ?_VGa#;25b z-+K?ACizqo?Wg(m3EFpltZ)JKz9qaBPZ@avW%H>G#9LUlIf*jAt8G<^VfsQ#BVzpU z@=sBpoR>>+&Cx~Hx@+nwU*_V3wNGuQ51~IV?tT&d&Ct5n5!2lqucBVa?%INK{IjcD z37_ftCZgcDpX!&tzK`~c^VV)d|M==%R=ss^I*+p1u;Cc`b8zeujXVF<2Gk3!4OFM` z_7$|=q`vJ8=^YyJqTMB@uPQ08d^UWP!Z`eIccEQ)XxZC{>Ao*pd5wNE8}0Eg6IMQR#~&oQWHr@^ z5FBOQ2kom5<2a6Y?k03pQC{LDP79aUTI2R`R6ks4fbzr*D}Dvz2?I9lLNvFi6py>- zPZpnzJyWQUU*%|B!l1ue^Khdl&^#C4Z$^8X%iM>^^)ynb_xfh4Kg4m-+kskt--3QSe_M zIp^&@a<(t~$YFnE|M8_cbjY~@e!6_jG274KrX^e6`2f+pbn+CU@42mqQ!qIJQ$(1G zNl(BucSZuHTL~8pm?6SUE8(*mVYUc!Vs`uFvD&A(3HYf9^X&HN3A=roZ?{iBv)d=H z-9Gv3_Q_8TxT1P1B)<{USnm*U_xE&Rj3P1PrZVVu#sbu66+*~vZ#uMme%7up@?*>H z5~WGATp+PltD+7nJG5G|O;@q#E=a&a5yCdzDx0oq(~a14qc&Zz>1x!cC~7q94@#h~ zv`H0#A!BzJtAj-yrmW7BNB{rSVsS}fY3Z#E*KKRj_PwP2`` z{?EC0eBaOgu!6$U!h(`pn%j)qockNTEZ6uDx$$@5N?RGMNWfDfBrt~wXuzLFD}PM} ztQ29DmA|JOVYLX)+&Ir`tOK$(0qaCqZy%6n?E|vGJ|NH82jqGCfNZo6$R;`9cFI9_ zMl2AE1=u4^r&lC<7~>OLht2K-^ny^mAxRHvN|ZJCI=sNnJU$^*uf*Pt?8&CXix?vR E-*|c0EdT%j literal 0 HcmV?d00001 From e7fa0a6bac75824361c9b13d9aecc8667a41fc43 Mon Sep 17 00:00:00 2001 From: Nicholas Lubbers Date: Mon, 21 Dec 2020 11:51:10 -0700 Subject: [PATCH 35/39] Changes to MLIAP python - update lammps python package to use setuptools - refactor MLIAP classes into lammps python package lammps.mliap package - change TorchWrapper to use dtype and device as arguments - turn activation of mliappy into functions (was a class) - add a check to see if python interpreter is compatible with python lib calls internal to lammps mliap_model_python_couple.pyx: - load models ending in '.pt' or '.pth' with pytorch rather than pickle --- doc/src/pair_mliap.rst | 10 ++++ examples/mliap/Ta06A.mliap.pytorch | 2 +- examples/mliap/convert_mliap_Ta06A.py | 21 +++----- examples/mliap/mliap_pytorch_Ta06A.py | 28 +++++----- python/install.py | 37 ++++++------- python/lammps/core.py | 39 -------------- python/lammps/mliap/__init__.py | 13 +++++ python/lammps/mliap/loader.py | 52 +++++++++++++++++++ .../lammps/mliap/pytorch.py | 24 +++++---- python/setup.py | 4 +- src/MLIAP/mliap_model_python_couple.pyx | 10 ++-- 11 files changed, 135 insertions(+), 105 deletions(-) create mode 100644 python/lammps/mliap/__init__.py create mode 100644 python/lammps/mliap/loader.py rename src/MLIAP/mliappy_pytorch.py => python/lammps/mliap/pytorch.py (80%) diff --git a/doc/src/pair_mliap.rst b/doc/src/pair_mliap.rst index 9dd8c5c6b1..af0cc9e855 100644 --- a/doc/src/pair_mliap.rst +++ b/doc/src/pair_mliap.rst @@ -84,6 +84,16 @@ for the :doc:`pair_style snap ` coefficient file. Specifically, the line containing the element weight and radius is omitted, since these are handled by the *descriptor*. +Notes on mliappy models: +When the *model* keyword is *mliappy*, the filename should end in '.pt', +'.pth' for pytorch models, or be a pickle file. To load a model from +memory (i.e. an existing python object), specify the filename as +"LATER", and then call `lammps.mliap.load_model(model)` from python +before using the pair style. When using lammps via the library mode, you will need to call +`lammps.mliappy.activate_mliappy(lmp)` on the active lammps object +before the pair style is defined. This call locates and loads the mliap-specific +python module that is built into lammps. + The *descriptor* keyword is followed by a descriptor style, and additional arguments. Currently the only descriptor style is *sna*, indicating the bispectrum component descriptors used by the Spectral Neighbor Analysis Potential (SNAP) potentials of diff --git a/examples/mliap/Ta06A.mliap.pytorch b/examples/mliap/Ta06A.mliap.pytorch index c6c6bc653d..5489688a82 100644 --- a/examples/mliap/Ta06A.mliap.pytorch +++ b/examples/mliap/Ta06A.mliap.pytorch @@ -11,7 +11,7 @@ variable zblz equal 73 pair_style hybrid/overlay & zbl ${zblcutinner} ${zblcutouter} & -mliap model mliappy Ta06A.mliap.pytorch.model.pkl & +mliap model mliappy Ta06A.mliap.pytorch.model.pt & descriptor sna Ta06A.mliap.descriptor pair_coeff 1 1 zbl ${zblz} ${zblz} pair_coeff * * mliap Ta diff --git a/examples/mliap/convert_mliap_Ta06A.py b/examples/mliap/convert_mliap_Ta06A.py index ba95678c9e..8a7466743f 100644 --- a/examples/mliap/convert_mliap_Ta06A.py +++ b/examples/mliap/convert_mliap_Ta06A.py @@ -1,13 +1,9 @@ import sys import numpy as np import torch -import pickle -import os -import shutil -shutil.copyfile('../../src/MLIAP/mliappy_pytorch.py','./mliappy_pytorch.py') - -import mliappy_pytorch +# torch.nn.modules useful for defining a MLIAPPY model. +from lammps.mliap.pytorch import TorchWrapper, IgnoreElems # Read coefficients coeffs = np.genfromtxt("Ta06A.mliap.model",skip_header=6) @@ -21,13 +17,10 @@ with torch.autograd.no_grad(): lin.weight.set_(torch.from_numpy(weights).unsqueeze(0)) lin.bias.set_(torch.as_tensor(bias,dtype=torch.float64).unsqueeze(0)) -# Wrap the pytorch model for usage with mliappy energy model -model = mliappy_pytorch.IgnoreElems(lin) +# Wrap the pytorch model for usage with mliappy coupling. +model = IgnoreElems(lin) # The linear module does not use the types. n_descriptors = lin.weight.shape[1] -n_params = mliappy_pytorch.calc_n_params(model) -n_types = 1 -linked_model = mliappy_pytorch.TorchWrapper64(model,n_descriptors=n_descriptors,n_elements=n_types) +n_elements = 1 +linked_model = TorchWrapper(model,n_descriptors=n_descriptors,n_elements=n_elements) -# Save the result. -with open("Ta06A.mliap.pytorch.model.pkl",'wb') as pfile: - pickle.dump(linked_model,pfile) +torch.save(linked_model,"Ta06A.mliap.pytorch.model.pt") diff --git a/examples/mliap/mliap_pytorch_Ta06A.py b/examples/mliap/mliap_pytorch_Ta06A.py index 71c89f112e..c4387e21a3 100644 --- a/examples/mliap/mliap_pytorch_Ta06A.py +++ b/examples/mliap/mliap_pytorch_Ta06A.py @@ -81,26 +81,24 @@ import lammps lmp = lammps.lammps(cmdargs=['-echo','both']) -# this commmand must be run before the MLIAP object is declared in lammps. +# Before defining the pair style, one must do the following: +import lammps.mliap +lammps.mliap.activate_mliappy(lmp) +# Otherwise, when running lammps in library mode, +# you will get an error: +# "ERROR: Loading MLIAPPY coupling module failure." -lmp.mliappy.activate() - -# setup the simulation and declare an empty model +# Setup the simulation and declare an empty model # by specifying model filename as "LATER" - lmp.commands_string(before_loading) -# define the PyTorch model by loading a pkl file. -# this could also be done in other ways. +# Define the model however you like. In this example +# we load it from disk: +import torch +model = torch.load('Ta06A.mliap.pytorch.model.pt') -import pickle -with open('Ta06A.mliap.pytorch.model.pkl','rb') as pfile: - model = pickle.load(pfile) +# Connect the PyTorch model to the mliap pair style. +lammps.mliap.load_model(model) -# connect the PyTorch model to the mliap pair style - -lmp.mliappy.load_model(model) - # run the simulation with the mliap pair style - lmp.commands_string(after_loading) diff --git a/python/install.py b/python/install.py index a6b69c1ee6..8c632c096e 100644 --- a/python/install.py +++ b/python/install.py @@ -95,22 +95,26 @@ print("Installing LAMMPS Python package version %s into site-packages folder" % # we need to switch to the folder of the python package os.chdir(os.path.dirname(args.package)) -from distutils.core import setup +from setuptools import setup, find_packages from distutils.sysconfig import get_python_lib import site -tryuser=False +#Arguments common to global or user install -- everything but data_files +setup_kwargs= dict(name="lammps", + version=verstr, + author="Steve Plimpton", + author_email="sjplimp@sandia.gov", + url="https://lammps.sandia.gov", + description="LAMMPS Molecular Dynamics Python package", + license="GPL", + packages=find_packages(), + ) + +tryuser=False try: sys.argv = ["setup.py","install"] # as if had run "python setup.py install" - setup(name = "lammps", - version = verstr, - author = "Steve Plimpton", - author_email = "sjplimp@sandia.gov", - url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python package", - license = "GPL", - packages=['lammps'], - data_files = [(os.path.join(get_python_lib(), 'lammps'), [args.lib])]) + setup_kwargs['data_files']=[(os.path.join(get_python_lib(), 'lammps'), [args.lib])] + setup(**setup_kwargs) except: tryuser=True print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE) @@ -118,14 +122,7 @@ except: if tryuser: try: sys.argv = ["setup.py","install","--user"] # as if had run "python setup.py install --user" - setup(name = "lammps", - version = verstr, - author = "Steve Plimpton", - author_email = "sjplimp@sandia.gov", - url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python package", - license = "GPL", - packages=['lammps'], - data_files = [(os.path.join(site.USER_SITE, 'lammps'), [args.lib])]) + setup_kwargs['data_files']=[(os.path.join(site.USER_SITE, 'lammps'), [args.lib])] + setup(**setup_kwargs) except: print("Installation into user site package folder failed.") diff --git a/python/lammps/core.py b/python/lammps/core.py index e30f036e1b..a75a02e358 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -379,8 +379,6 @@ class lammps(object): self.lib.lammps_set_fix_external_callback.argtypes = [c_void_p, c_char_p, self.FIX_EXTERNAL_CALLBACK_FUNC, py_object] self.lib.lammps_set_fix_external_callback.restype = None - self.mliappy = MLIAPPY(self) - # ------------------------------------------------------------------------- # shut-down LAMMPS instance @@ -1673,41 +1671,4 @@ class lammps(object): idx = self.lib.lammps_find_compute_neighlist(self.lmp, computeid, request) return idx -class MLIAPPY(): - def __init__(self,lammps): - self._module = None - self.lammps = lammps - @property - def module(self): - if self._module: - return self._module - - try: - # Begin Importlib magic to find the embedded python module - # This is needed because the filename for liblammps does not - # match the spec for normal python modules, wherein - # file names match with PyInit function names. - # Also, python normally doesn't look for extensions besides '.so' - # We fix both of these problems by providing an explict - # path to the extension module 'mliap_model_python_couple' in - import sys - import importlib.util - import importlib.machinery - - path = self.lammps.lib._name - loader = importlib.machinery.ExtensionFileLoader('mliap_model_python_couple',path) - spec = importlib.util.spec_from_loader('mliap_model_python_couple',loader) - module = importlib.util.module_from_spec(spec) - sys.modules['mliap_model_python_couple']=module - spec.loader.exec_module(module) - self._module = module - # End Importlib magic to find the embedded python module - except: - raise ImportError("Could not load MLIAPPY coupling module") - - def activate(self): - self.module - - def load_model(self,model): - self.module.load_from_python(model) diff --git a/python/lammps/mliap/__init__.py b/python/lammps/mliap/__init__.py new file mode 100644 index 0000000000..06c127055e --- /dev/null +++ b/python/lammps/mliap/__init__.py @@ -0,0 +1,13 @@ + +# Check compatiblity of this build with the python shared library. +# If this fails, lammps will segfault because its library will +# try to improperly start up a new interpreter. +import sysconfig +import ctypes +library = sysconfig.get_config_vars('INSTSONAME')[0] +pylib = ctypes.CDLL(library) +if not pylib.Py_IsInitialized(): + raise RuntimeError("This interpreter is not compatible with python-based mliap for LAMMPS.") +del sysconfig, ctypes, library, pylib + +from .loader import load_model, activate_mliappy \ No newline at end of file diff --git a/python/lammps/mliap/loader.py b/python/lammps/mliap/loader.py new file mode 100644 index 0000000000..b875d8d834 --- /dev/null +++ b/python/lammps/mliap/loader.py @@ -0,0 +1,52 @@ +# ---------------------------------------------------------------------- +# 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 author: Nicholas Lubbers (LANL) +# ------------------------------------------------------------------------- + + +import sys +import importlib.util +import importlib.machinery + +def activate_mliappy(lmp): + try: + # Begin Importlib magic to find the embedded python module + # This is needed because the filename for liblammps does not + # match the spec for normal python modules, wherein + # file names match with PyInit function names. + # Also, python normally doesn't look for extensions besides '.so' + # We fix both of these problems by providing an explict + # path to the extension module 'mliap_model_python_couple' in + + path = lmp.lib._name + loader = importlib.machinery.ExtensionFileLoader('mliap_model_python_couple', path) + spec = importlib.util.spec_from_loader('mliap_model_python_couple', loader) + module = importlib.util.module_from_spec(spec) + sys.modules['mliap_model_python_couple'] = module + spec.loader.exec_module(module) + # End Importlib magic to find the embedded python module + + except Exception as ee: + raise ImportError("Could not load MLIAP python coupling module.") from ee + +def load_model(model): + try: + import mliap_model_python_couple + except ImportError as ie: + raise ImportError("MLIAP python module must be activated before loading\n" + "the pair style. Call lammps.mliap.activate_mliappy(lmp)." + ) from ie + mliap_model_python_couple.load_from_python(model) + diff --git a/src/MLIAP/mliappy_pytorch.py b/python/lammps/mliap/pytorch.py similarity index 80% rename from src/MLIAP/mliappy_pytorch.py rename to python/lammps/mliap/pytorch.py index ff80720ffa..aa2cf1c97c 100644 --- a/src/MLIAP/mliappy_pytorch.py +++ b/python/lammps/mliap/pytorch.py @@ -22,20 +22,28 @@ def calc_n_params(model): return sum(p.nelement() for p in model.parameters()) class TorchWrapper(torch.nn.Module): - def __init__(self, model,n_descriptors,n_elements,n_params=None): + def __init__(self, model,n_descriptors,n_elements,n_params=None,device=None,dtype=torch.float64): super().__init__() + self.model = model - self.model.to(self.dtype) + self.device = device + self.dtype = dtype + + # Put model on device and convert to dtype + self.to(self.dtype) + self.to(self.device) + if n_params is None: n_params = calc_n_params(model) + self.n_params = n_params self.n_descriptors = n_descriptors self.n_elements = n_elements - def __call__(self, elems, bispectrum, beta, energy): + def forward(self, elems, bispectrum, beta, energy): - bispectrum = torch.from_numpy(bispectrum).to(self.dtype).requires_grad_(True) - elems = torch.from_numpy(elems).to(torch.long) - 1 + bispectrum = torch.from_numpy(bispectrum).to(dtype=self.dtype, device=self.device).requires_grad_(True) + elems = torch.from_numpy(elems).to(dtype=torch.long, device=self.device) - 1 with torch.autograd.enable_grad(): @@ -48,12 +56,6 @@ class TorchWrapper(torch.nn.Module): beta[:] = beta_nn.detach().cpu().numpy().astype(np.float64) energy[:] = energy_nn.detach().cpu().numpy().astype(np.float64) -class TorchWrapper32(TorchWrapper): - dtype = torch.float32 - -class TorchWrapper64(TorchWrapper): - dtype = torch.float64 - class IgnoreElems(torch.nn.Module): def __init__(self,subnet): super().__init__() diff --git a/python/setup.py b/python/setup.py index 9be04138d5..50e215cb09 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,6 +1,6 @@ # this only installs the LAMMPS python package # it assumes the LAMMPS shared library is already installed -from distutils.core import setup +from setuptools import setup, find_packages import os LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -22,5 +22,5 @@ setup( url = "https://lammps.sandia.gov", description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - packages=["lammps"] + packages=find_packages(), ) diff --git a/src/MLIAP/mliap_model_python_couple.pyx b/src/MLIAP/mliap_model_python_couple.pyx index 49bdd47412..1f04964ef6 100644 --- a/src/MLIAP/mliap_model_python_couple.pyx +++ b/src/MLIAP/mliap_model_python_couple.pyx @@ -46,7 +46,7 @@ cdef object c_id(MLIAPModelPython * c_model): """ return int( c_model) -cdef object retrieve(MLIAPModelPython * c_model): +cdef object retrieve(MLIAPModelPython * c_model) with gil: try: model = LOADED_MODELS[c_id(c_model)] except KeyError as ke: @@ -61,8 +61,12 @@ cdef public int MLIAPPY_load_model(MLIAPModelPython * c_model, char* fname) with model = None returnval = 0 else: - with open(str_fname,'rb') as pfile: - model = pickle.load(pfile) + if str_fname.endswith(".pt") or str_fname.endswith('.pth'): + import torch + model = torch.load(str_fname) + else: + with open(str_fname,'rb') as pfile: + model = pickle.load(pfile) returnval = 1 LOADED_MODELS[c_id(c_model)] = model return returnval From cf3ae8cdd26270e56dce49c25aba76dde067217c Mon Sep 17 00:00:00 2001 From: Nicholas Lubbers Date: Tue, 22 Dec 2020 09:59:50 -0700 Subject: [PATCH 36/39] switch setuptools back to distutils --- python/install.py | 4 ++-- python/setup.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/install.py b/python/install.py index 8c632c096e..6765c33925 100644 --- a/python/install.py +++ b/python/install.py @@ -95,7 +95,7 @@ print("Installing LAMMPS Python package version %s into site-packages folder" % # we need to switch to the folder of the python package os.chdir(os.path.dirname(args.package)) -from setuptools import setup, find_packages +from distutils.core import setup from distutils.sysconfig import get_python_lib import site @@ -107,7 +107,7 @@ setup_kwargs= dict(name="lammps", url="https://lammps.sandia.gov", description="LAMMPS Molecular Dynamics Python package", license="GPL", - packages=find_packages(), + packages=["lammps","lammps.mliap"], ) tryuser=False diff --git a/python/setup.py b/python/setup.py index 50e215cb09..aff0b14671 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,6 +1,6 @@ # this only installs the LAMMPS python package # it assumes the LAMMPS shared library is already installed -from setuptools import setup, find_packages +from distutils.core import setup import os LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -22,5 +22,5 @@ setup( url = "https://lammps.sandia.gov", description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - packages=find_packages(), + packages=["lammps","lammps.mliap"], ) From 9122b18c6f16a1298b8ccb00976a070ed1799e4a Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 23 Dec 2020 10:17:55 -0700 Subject: [PATCH 37/39] Updated README files --- examples/mliap/README | 54 +++++++++++++++++++++++-------------------- src/MLIAP/README | 22 ++++++++++-------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/examples/mliap/README b/examples/mliap/README index 2641bdc975..9d7d22b0c5 100644 --- a/examples/mliap/README +++ b/examples/mliap/README @@ -1,7 +1,7 @@ -This directory contains multipler examples of +This directory contains multiple examples of machine-learning potentials defined using the MLIAP package in LAMMPS. The input files -are descirbed below. +are described below. in.mliap.snap.Ta06A ------------------- @@ -21,58 +21,62 @@ Run EME-SNAP, equivalent to examples/snap/in.snap.InP.JCPA2020 in.mliap.snap.compute --------------------- -Generate gradients w.r.t. coefficients for linear SNAP, -equivalent to in.snap.compute +Generate the A matrix, the gradients (w.r.t. coefficients) +of total potential energy, forces, and stress tensor for +linear SNAP, equivalent to in.snap.compute in.mliap.quadratic.compute -------------------------- -Generate gradients w.r.t. coefficients for quadratic SNAP, -equivalent to in.snap.compute.quadratic +Generate the A matrix, the gradients (w.r.t. coefficients) +of total potential energy, forces, and stress tensor for +for quadratic SNAP, equivalent to in.snap.compute.quadratic in.mliap.pytorch.Ta06A ----------------------- This reproduces the output of in.mliap.snap.Ta06A above, but using the Python coupling to PyTorch. -It can be run in two different ways: + +This example can be run in two different ways: 1: Running a LAMMPS executable: in.mliap.pytorch.Ta06A -First run convert_mliap_Ta06A.py, which will convert the Ta06A potential -into a pytorch model. It will be saved as "Ta06A.mliap.pytorch.model.pkl". +First run ``python convert_mliap_Ta06A.py``. It creates +a PyTorch energy model that replicates the +SNAP Ta06A potential and saves it in the file +"Ta06A.mliap.pytorch.model.pt". -It will also copy "../../src/MLIAP/mliappy_pytorch.py" -file into the current working directory. mliappy_pytorch.py contains -class definitions suitable for wrapping an arbitrary PyTorch -energy model. It must be available to python when -creating or unpickling a PyTorch energy model. - -From that point you can run the example as follows +You can then run the example as follows `lmp -in in.mliap.pytorch.Ta06A -echo both` The resultant log.lammps output should be identical to that generated by in.mliap.snap.Ta06A. +If this fails, see the instructions for building the MLIAP package +with Python support enabled. Also, confirm that the +LAMMPS Python embedded Python interpreter is +working by running ../examples/in.python. + 2: Running a Python script: mliap_pytorch_Ta06A.py -Before testing this, ensure that the first example -(using LAMMPS executable) works. -Also, not all python installations support this mode of operation. -It requires that the Python interpreter be initialized. -To check this for your Python library, -try running the Py_IsInitialized() method. -If the return value is True, you should be able to run the example, -as follows: +Before testing this, ensure that the previous method +(running a LAMMPS executable) works. + +You can run the example in serial: `python mliap_pytorch_Ta06A.py` -or +or in parallel: `mpirun -np 4 python mliap_pytorch_Ta06A.py` The resultant log.lammps output should be identical to that generated by in.mliap.snap.Ta06A and in.mliap.pytorch.Ta06A. +Not all Python installations support this mode of operation. +It requires that the Python interpreter be initialized. If not, +the script will exit with an error message. + in.mliap.pytorch.relu1hidden ---------------------------- This example demonstrates a simple neural network potential diff --git a/src/MLIAP/README b/src/MLIAP/README index 9179d9d02f..59eb5e34b3 100644 --- a/src/MLIAP/README +++ b/src/MLIAP/README @@ -8,12 +8,15 @@ definitions of the interatomic potential functional form (*model*) and the geometric quantities that characterize the atomic positions (*descriptor*). By defining *model* and *descriptor* separately, it is possible to use many different models with a given descriptor, -or many different descriptors with a given model. Currently, the pair_style -supports just two models, *linear* and *quadratic*, -and one descriptor, *sna*, the SNAP descriptor, including the -linear, quadratic, and chem variants. Work is currently underway to extend -the interface to handle neural network energy models, -and it is also straightforward to add new descriptor styles. +or many different descriptors with a given model. The pair_style +supports the following models: *linear*, *quadratic*, and +*mliappy* (general Python interface to things like PyTorch, see below +for build instructions). +It currently supports only one class of descriptors, +*sna*, the SNAP descriptors, including the +linear, quadratic, and chem variants. +It is straightforward to add new descriptor and model +styles. The mliap compute style provides gradients of the energy, force, and stress tensor w.r.t. model parameters. @@ -27,13 +30,13 @@ reference potential. To see how this command can be used within a Python workflow to train machine-learning interatomic -potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP>. +potentials, see the examples in FitSNAP https://github.com/FitSNAP/FitSNAP. *Additional instructions for building MLIAP with Python support enabled* The *mliappy* energy model requires that the MLIAP package be compiled with Python support enabled. -This extension written by Nick Lubbers (LANL) +This extension, written by Nick Lubbers (LANL), provides a coupling to PyTorch and other Python modules. This should be automatically enabled by default if the prerequisite software is installed. It can be @@ -51,5 +54,4 @@ file(s) in the src/MLIAP folder or there may be problems during compilation. More information on building LAMMPS with this package is here: -https://lammps.sandia.gov/doc/html/Build_extras.html#mliap - +https://lammps.sandia.gov/doc/Build_extras.html#mliap From 780c31c5f7c77fa2846ad771875da041b5598cb4 Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Wed, 23 Dec 2020 12:22:44 -0700 Subject: [PATCH 38/39] Updated PyTorch ReLU example to latest --- examples/mliap/README | 23 +++++++++++++++--- examples/mliap/relu1hidden.mliap.pytorch | 2 +- .../mliap/relu1hidden.mliap.pytorch.model.pkl | Bin 4059 -> 0 bytes .../mliap/relu1hidden.mliap.pytorch.model.pt | Bin 0 -> 11506 bytes 4 files changed, 21 insertions(+), 4 deletions(-) delete mode 100644 examples/mliap/relu1hidden.mliap.pytorch.model.pkl create mode 100644 examples/mliap/relu1hidden.mliap.pytorch.model.pt diff --git a/examples/mliap/README b/examples/mliap/README index 9d7d22b0c5..af848e42ba 100644 --- a/examples/mliap/README +++ b/examples/mliap/README @@ -80,7 +80,24 @@ the script will exit with an error message. in.mliap.pytorch.relu1hidden ---------------------------- This example demonstrates a simple neural network potential -using PyTorch and SNAP descriptors. It uses a ReLU activation -function with just 1 hidden layer. - +using PyTorch and SNAP descriptors. + `lmp -in in.mliap.pytorch.relu1hidden -echo both` + +It was trained on just the energy component (no forces) of +the data used in the original SNAP Ta06A potential for +tantalum (Thompson, Swiler, Trott, Foiles, Tucker, +J Comp Phys, 285, 316 (2015).). Because of the very small amount +of energy training data, it uses just 1 hidden layer with +a ReLU activation function. It is not expected to be +very accurate for forces. + +NOTE: Unlike the previous example, this example uses +a pre-built PyTorch file `Ta06A.mliap.pytorch.model.pt`. +It is read using `torch.load`, +which implicitly uses the Python `pickle` module. +This is known to be insecure. It is possible to construct malicious +pickle data that will execute arbitrary code during unpickling. Never +load data that could have come from an untrusted source, or that +could have been tampered with. Only load data you trust. + diff --git a/examples/mliap/relu1hidden.mliap.pytorch b/examples/mliap/relu1hidden.mliap.pytorch index a2271cee39..32ac4c85a3 100644 --- a/examples/mliap/relu1hidden.mliap.pytorch +++ b/examples/mliap/relu1hidden.mliap.pytorch @@ -11,7 +11,7 @@ variable zblz equal 73 pair_style hybrid/overlay & zbl ${zblcutinner} ${zblcutouter} & -mliap model mliappy relu1hidden.mliap.pytorch.model.pkl & +mliap model mliappy relu1hidden.mliap.pytorch.model.pt & descriptor sna Ta06A.mliap.descriptor pair_coeff 1 1 zbl ${zblz} ${zblz} pair_coeff * * mliap Ta diff --git a/examples/mliap/relu1hidden.mliap.pytorch.model.pkl b/examples/mliap/relu1hidden.mliap.pytorch.model.pkl deleted file mode 100644 index 49e70ca1a4f00345b5ce4ab4afb4d1e7549bba38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4059 zcmds4`+pSG6`v%Vg{(kCl&8gMDHyE8JbB0?Lj)9;=kQvJbf1&Vz-D&O%q$_0z((98 zAo36ev{p9(tQJ069#PQ94unTPBFaM%KDM$*v85mM^J(cv>4ScH&zYfwTK)i=ANHH` zxaWTFx#!+FH=Y%&3M>9-w8k5)F(O(}cFn}!IU3VR+RzdgaD(e1qYg6jJe@g?Gc>=V zDrzNUHF@q}vN!72{8f@6X*xK9!ALkP1q~&l>aM9;NYbRxI3;MfAbYR~P72@+#40M# zyOWH{&Ypf4MUALlHlMEOhNK!de7w43Ku$0aQ^JPALNd_>uK93B0=kIM)su@u1ODK` zYQGlp%8|%I9lBB2Tu(Q&RYbH7raQ^h-E&t*Q&f}ek#~`~ho?K5b;EB+-Vh^iTkj_8 zJ)XX34M+T;jxINY^dz@l)>5k?p;%bbp*Jb}c(U18rjx?Z_d98ySgA%dX?$3!(p}Jx z<^0|{_(7hW)g(J;bbr}O*nM)2%u>K7;D;joNVb+cK(^NQW7%57K-r=@NVfRgFIyDy zJWfVIj|Ehg*ug>C@O)Lxw~6KlBdWpnSJGTFB#5z{Q2b#RJiyreqz)eJz-EZeCf{Q7 zPyz}>D74uW*=&k!HYGNjQk%_Co6WF1PX?n?0K>n_B+OX&HP<8yU<9M^a2<^7Kw*@% zm}*I>lnoedhw#P>C9J!=nuJvox>=qs7;_sJR&jbn^DZiKL0O*dqqEfbD=HThdEMdhk!je}~LyBL8%qEYEDUF(_z>!ClqRSD@fNXcBCyTi# zssT>7!{fjh5q1DOxgD_>n={YTiK%SDz*!4$jf=zrVQGfF49KAKFrs*PQE5SONzsU* zLx&ZC6*w4;L6&>Z6ayU7S-APY{V(4PfBqgejs3@;zrMGO{hzG8wu$hA%b%xEUi^uP zGI#C3MMNRo`abD@{)-P$Hu;(Dh{;vl$EY_$*(XW<%h@A{!nr2$OXnYIM%kB|+lt7K z3nUQJy~n;qe#`#wG2z%XG>+%yyqRM5c&^-znC{>H9-=w&;xR;_^}ePu!Yi#PbG6qF zqnsXcoZ^|~?v1E7&tKb)dULS$F3QP?Ija$U<2^eO)6I*2P5Skh4mNY7bH>*xP`nt1vy4mpB;eDS3Nh`x#skCOaE=~hH@ z){fnX@tiq3%NTM?`?VqRGioTF@AG^2qn+zLoA~(t(MJBqEOa5{X+W8{Y%FA2x_o19#nQ86gk?Q>@C!3oulK+-oXUIPJ?_VGa#;25b z-+K?ACizqo?Wg(m3EFpltZ)JKz9qaBPZ@avW%H>G#9LUlIf*jAt8G<^VfsQ#BVzpU z@=sBpoR>>+&Cx~Hx@+nwU*_V3wNGuQ51~IV?tT&d&Ct5n5!2lqucBVa?%INK{IjcD z37_ftCZgcDpX!&tzK`~c^VV)d|M==%R=ss^I*+p1u;Cc`b8zeujXVF<2Gk3!4OFM` z_7$|=q`vJ8=^YyJqTMB@uPQ08d^UWP!Z`eIccEQ)XxZC{>Ao*pd5wNE8}0Eg6IMQR#~&oQWHr@^ z5FBOQ2kom5<2a6Y?k03pQC{LDP79aUTI2R`R6ks4fbzr*D}Dvz2?I9lLNvFi6py>- zPZpnzJyWQUU*%|B!l1ue^Khdl&^#C4Z$^8X%iM>^^)ynb_xfh4Kg4m-+kskt--3QSe_M zIp^&@a<(t~$YFnE|M8_cbjY~@e!6_jG274KrX^e6`2f+pbn+CU@42mqQ!qIJQ$(1G zNl(BucSZuHTL~8pm?6SUE8(*mVYUc!Vs`uFvD&A(3HYf9^X&HN3A=roZ?{iBv)d=H z-9Gv3_Q_8TxT1P1B)<{USnm*U_xE&Rj3P1PrZVVu#sbu66+*~vZ#uMme%7up@?*>H z5~WGATp+PltD+7nJG5G|O;@q#E=a&a5yCdzDx0oq(~a14qc&Zz>1x!cC~7q94@#h~ zv`H0#A!BzJtAj-yrmW7BNB{rSVsS}fY3Z#E*KKRj_PwP2`` z{?EC0eBaOgu!6$U!h(`pn%j)qockNTEZ6uDx$$@5N?RGMNWfDfBrt~wXuzLFD}PM} ztQ29DmA|JOVYLX)+&Ir`tOK$(0qaCqZy%6n?E|vGJ|NH82jqGCfNZo6$R;`9cFI9_ zMl2AE1=u4^r&lC<7~>OLht2K-^ny^mAxRHvN|ZJCI=sNnJU$^*uf*Pt?8&CXix?vR E-*|c0EdT%j diff --git a/examples/mliap/relu1hidden.mliap.pytorch.model.pt b/examples/mliap/relu1hidden.mliap.pytorch.model.pt new file mode 100644 index 0000000000000000000000000000000000000000..ecc04341a7aa40df2258925e3eeeb34b3dbef19d GIT binary patch literal 11506 zcmb_C33MFAm1A2Lcmg>{aj2f&U{sq$EBW3WbVx z!7ZcV1xxBHbA<=+13RXWqs;8k;0-8#q5r*=GOev@HP&%jO^F>F^=S;1r z7Khw|oi@T7@c$LIRxIjvn9oXF0xM#grKJm2Mr)7h)_@apEUnnSIF>W}VzA68SncZK zm}9znb5Tog(fV~KCUD0HHv%D6puuM+9s{<3wBxWKDMdh7mb!}Ai*$w={4#o$C6lIQ zy2+&C=(%i^0sDF`Y9%weleWzwtaG5J=k&a8x%gPrY%T9}tu9!4G@}ogXCeUv*bIu8YDsx>wClhI%q*+Qg_#aR(Fpkp#LS=V zVreaxPFA56+I0XE@lc(GT~!}z8L80@K?Srm6||~4f~$6fpiuqUg1uF6UKy4}n5G^gaw=mTI>P`J`3K7l#yoHi9xGady$}=rJlaB8P-P zRa@sJ)7G72zpZ7G$_Bfn`zj#T>XD*}02RRtp3J&bSTk$&cd^xU4avP$atlaU)h(?L z90NWp!5yPEg&dNW1)R`!NP~gxf~Zi2KHsCVLK9`nt_qD0cSN`EWv-F&xooy zc)}E`s8&z6X9|Ltz~U1=ay)#F%Ny23w)43oyirLU4L&j12d)lWGe0UVwg;|D4mql8 zSXMaMue(WnN@hz|+6C8MT@&UzNg1 z+70thz=C5W;Zin>(8n4$cwAzBl^Z-JNuyBM;_&%2_sPU@I44h#oI0MSK9%@XaH?qQ za{2_C{&eDaoOWEz)sq?EK+b-KW=~9ruvfvjC5aNx)Pocq6DPWON z^3xP!hA4D#zg4jHm1wA8{#j#o;w2y`qDElqh=Ybx>a%qB(B2+R7JqbT!~#4*v~mV- z!{~r;a z@W(7GCh^BS{21pypSWvYRbxImWmPb^+ozv?dN+uu$_z$6!J$egR{%R~tC`Ee;b&SV zqh~NInl3Xf<{COH;2FWEA*R_nD?(ZUAaWAWIS?XH5&~g&4vv|nx#obL8;U}(73*OI znm8+DF&?9>LJ+i=mU9Y7)6aTMgc-WM)`^h~)x_cpAT(BO>gA;rlMd%Q(^V zMA_Mz-S13uRlfeC~isv8>69U%N#abz!G{L;kGSfQEKyZx)6%ZhWcpzA? zEjpYIaTM?@AwF28LV}-nFyW}utG47a;dCa&8YQsaPc!tKGbQOnQf6i_NJ@ubuG_fekT3!S3U(A}2Q~vbxlo6!8@vikG=r7m zT0EaLBv+y4ylq1j2B#B6juP;<3hQCK00jjSQcds;gT$q`6ch4-%bKx}W9M}tMRp#; zUhS4`&2)5jF(O!L+XY)`B4liM1RYEPDhS}u)~tTLNdg5XA-=^OQI%hwH9I3@>J zkWrdPvI&@(PYED>I>f|$-97nbxDC%kD@338XL}-_VkswbyOvl|Mk4ASmke7 zF4%}04M>%S<*|lm)pRmuzv(KG%~Q`ELi!d5C<5iJX%$PsJQWG}j#${6=sRlFhHDi@ z7+^!v6$^w@S)kD{kGi}WlTdYp$3#`*g2S;O8{sWu)2fqJN>JNsi;#92T$nfw3jzyD z9B_IL9AZc>lYOF4Ny3rh9qAv$g%uN{khh4ON;)>^5gXoO)R>g8BIHs_I9g9yk(A0d zz_x@}#9h|l!z*N{cOebRuq@mHRtaoEdxtB};mbyp=1mT_-Qg`GKtMi4z}`sZHOM4$ zTTn1rTT2hOjttjPU_gVyoY@q4;OGp(sPb1=0I=5@eo$a=R5~$Accu_)3e&@?p^GEq z3kHs8tuUq`lN&s&aO%h=pu8iH4^ft-uoEnhmo8n(@*rQRY^8&P>Wj6v_;DB^gs-XI z?t*{ISW0W#k|=AN0tg0#whduXp*6K=iZ;A5Q3Q;Nsj?#LG~5i`bExZabR*$zZ`mxC zS8D-CW$~s#gVztqB+%H{gerj25t4Q9IAa$m_I1#dCso!ka+c2KSaS3<7s ziz6UlNSbh4{)SNM#0Cx@8SVhO=_x7Uvh{vUOKktXRjH~8Ux)YxA)z7e_@I!%`xzUA zyxKWj5y(YRm+BVH#HgAqStf>DQ8uYUTyXQ$g>FYhC!=%(cn4AV8;28&v2FUxnyhBQ zE3qg;TO(pgd}mXFBwbI6xg?wfdIb54a!OG4cZo9YE5NN4;AmwrxY4TeBQVrL5|!Gm zpl+h9nQ(wzBC3Fl4xQD?Z2baNWG3QB3e)vOly|> z9<)CipaV2K;#JF@IeSJIFjC1<5Q!Wj%M2*ULjza47rXot%&L1v_@#=`GG>Uxd6l@L z6^h`i<^623S^p*u!CRT zv!G|z4t~Y;l

6eq}HJ!WeZn?&O<#`DS{zj6&dFG}aivhOy3=N@YoFOWQ)8G&b}! z0`?SPALUxltWn-4FsEIf>E*h>oZZR$d%00EL`h*99R^egSB>&5y*y`#Y9Mcj)Za2h zj$bfDHeWPEy3P%eq1#lv1T@K=o&||xKvF?na<`|k)JM5|D=*c}VPPz{-6tQlA9CL_eMC~AMxUiTo zt!9E$Ss=}p8N2YDN0MiI`E{zAS>q*rAhix8)ZU4M`vNbu_6F-`%$Uv1koF2DRh5}} zI7ppP)6mBSPRv(RlBS#(N>43X{bI>sk{8mY?@VV(TH0zsz)Gj2D}oqf-5_gxnSdWV zh&m3^=kt*Yyf!vmx9D`nVwyc@4yXmYKc@9LvDQT`?P^O$TT9@rav;4rVh+`k<-n^N z9TK6LvMZ4*rQsG*sU}*{ywWUEE*a-$&YA!Wt*z-$nGr#Bk!1zkzes^_C&EA1y&b2B zB56?MBwRwUn1vl-%))E_YQ&P*#76?Mb42k9I#-YI;Xu&YCcWv1@TS*{@@so}S$fm$(wlxsdeiHqH~q5orlZoE z?w}YW$?=`nOP|@s$BYYskA| z{vCnvyF2+^z5MQKpcxmU*)_^{_wswBXzrDwxlfAbekq#oNzptYMf0HH^fVf7&#Y2k zsnqAtZIO3}_Rts%84r!oS6AZGApY=bdjCz|nD9L^T+8nj!u;U?#KZXpz2VR@;qcZ#+AQFC{LBxZ!b+*hgp?{B_as~&$|)Z)XK!; z*iP;me2m6#eV^nKpKlVK$xq)$>&nkvGO!HceslaDgbQW%K1u!Mchf#5uNbENvwwS? z_)NXq`~t$U_V*58o67$DMe1+rxEI^XWqU{;<#|^;z6|=I;nVhG%hnGOzSM6&`wYT` zPQIM@N&WYJf)AZ_t_o+zOeNf?2qr-^)A8RbJ80$zv{n!hi%;bHOW2oW52TFwwDk-#9w-k*1i3Q+i*O-ZwJ|F`QUZ5-*M-@H)y=U zCVttSYsoIhdq1H4S3dp|(W^Y(NAs!QPm&#l<~=L){>a%RmvJTYk4Pu==Z_vne3jyL z!d{L)@End$HeU87jKkGjPolw^WMCaX~?!x)W(CnwN4V~yt;CSkPzd`Fl zU%Kg=G`{(I%s5qvy+D#@vQ>>~0f Date: Mon, 28 Dec 2020 09:37:13 -0500 Subject: [PATCH 39/39] whitespace --- .gitignore | 1 - python/lammps/core.py | 2 -- python/lammps/mliap/__init__.py | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 92fae19766..0f1b01775d 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,3 @@ Thumbs.db /Makefile /cmake_install.cmake /lmp - diff --git a/python/lammps/core.py b/python/lammps/core.py index a75a02e358..161583b78c 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -1670,5 +1670,3 @@ class lammps(object): computeid = computeid.encode() idx = self.lib.lammps_find_compute_neighlist(self.lmp, computeid, request) return idx - - diff --git a/python/lammps/mliap/__init__.py b/python/lammps/mliap/__init__.py index 06c127055e..0d63cc810b 100644 --- a/python/lammps/mliap/__init__.py +++ b/python/lammps/mliap/__init__.py @@ -10,4 +10,4 @@ if not pylib.Py_IsInitialized(): raise RuntimeError("This interpreter is not compatible with python-based mliap for LAMMPS.") del sysconfig, ctypes, library, pylib -from .loader import load_model, activate_mliappy \ No newline at end of file +from .loader import load_model, activate_mliappy