8.3. C/C++ interface#
Note
See Environment variables for the runtime environment variables.
8.3.1. C++ interface#
The C++ interface of DeePMD-kit is also available for the model interface, which is considered faster than the Python interface. An example infer_water.cpp is given below:
#include "deepmd/DeepPot.h"
int main(){
deepmd::DeepPot dp ("graph.pb");
std::vector<double > coord = {1., 0., 0., 0., 0., 1.5, 1. ,0. ,3.};
std::vector<double > cell = {10., 0., 0., 0., 10., 0., 0., 0., 10.};
std::vector<int > atype = {1, 0, 1};
double e;
std::vector<double > f, v;
dp.compute (e, f, v, coord, atype, cell);
}
where e, f and v are predicted energy, force and virial of the system, respectively. See deepmd::DeepPot for details.
You can compile infer_water.cpp using gcc:
gcc infer_water.cpp -L $deepmd_root/lib -I $deepmd_root/include -Wl,--no-as-needed -ldeepmd_cc -lstdc++ -Wl,-rpath=$deepmd_root/lib -o infer_water
and then run the program:
./infer_water
8.3.2. Backend plugins#
The C and C++ libraries load backend implementations as runtime plugins. An application links to libdeepmd_cc or libdeepmd_c; it does not need to link directly to TensorFlow, PyTorch, JAX, or Paddle. When a model is opened, DeePMD-kit detects the backend from the model format and loads only the corresponding backend plugin.
The plugin library names are:
TensorFlow:
libdeepmd_backend_tf.soPyTorch:
libdeepmd_backend_pt.soPyTorch exportable:
libdeepmd_backend_ptexpt.soJAX:
libdeepmd_backend_jax.soPaddle:
libdeepmd_backend_pd.so
On macOS the suffix is .dylib; on Windows the libraries use .dll without the lib prefix. Native installs and the pre-compiled C library package place these plugins in the same lib directory as libdeepmd_cc and libdeepmd_c. Python wheels place them in deepmd/lib.
The backend plugin search order is:
directories listed in
DP_BACKEND_PLUGIN_PATH, split by:on Unix and;on Windows;the directory that contains
libdeepmd_cc;the platform dynamic loader search path for the bare plugin library name.
If the requested plugin or its backend runtime cannot be loaded, only that backend fails with a Unable to load ... backend plugin error. Other backends can still run as long as their own plugins and runtime libraries are available. This also allows a no-backend libdeepmd_cc or libdeepmd_c build; install or copy the backend plugin next to the library, or set DP_BACKEND_PLUGIN_PATH, before loading a model that uses that backend. Build instructions for this layout are in Install DeePMD-kit’s C++ interface.
DP_PLUGIN_PATH is different: it is used for customized OP plugin libraries after the backend has been selected.
8.3.3. C interface#
Although C is harder to write, the C library will not be affected by different versions of C++ compilers.
An example infer_water.c is given below:
#include <stdio.h>
#include <stdlib.h>
#include "deepmd/c_api.h"
int main(){
const char* model = "graph.pb";
double coord[] = {1., 0., 0., 0., 0., 1.5, 1. ,0. ,3.};
double cell[] = {10., 0., 0., 0., 10., 0., 0., 0., 10.};
int atype[] = {1, 0, 1};
// init C pointers with given memory
double* e = malloc(sizeof(*e));
double* f = malloc(sizeof(*f) * 9); // natoms * 3
double* v = malloc(sizeof(*v) * 9);
double* ae = malloc(sizeof(*ae) * 9); // natoms
double* av = malloc(sizeof(*av) * 27); // natoms * 9
// DP model
DP_DeepPot* dp = DP_NewDeepPot(model);
DP_DeepPotCompute (dp, 3, coord, atype, cell, e, f, v, ae, av);
// print results
printf("energy: %f\n", *e);
for (int ii = 0; ii < 9; ++ii)
printf("force[%d]: %f\n", ii, f[ii]);
for (int ii = 0; ii < 9; ++ii)
printf("force[%d]: %f\n", ii, v[ii]);
// free memory
free(e);
free(f);
free(v);
free(ae);
free(av);
DP_DeleteDeepPot(dp);
}
where e, f and v are predicted energy, force and virial of the system, respectively. ae and av are atomic energy and atomic virials, respectively. See DP_DeepPotCompute() for details.
You can compile infer_water.c using gcc:
gcc infer_water.c -L $deepmd_root/lib -I $deepmd_root/include -Wl,--no-as-needed -ldeepmd_c -Wl,-rpath=$deepmd_root/lib -o infer_water
and then run the program:
./infer_water
8.3.4. Header-only C++ library interface (recommended)#
The header-only C++ library is built based on the C library. Thus, it has the same ABI compatibility as the C library but provides a powerful C++ interface. To use it, include deepmd/deepmd.hpp.
#include "deepmd/deepmd.hpp"
int main(){
deepmd::hpp::DeepPot dp ("graph.pb");
std::vector<double > coord = {1., 0., 0., 0., 0., 1.5, 1. ,0. ,3.};
std::vector<double > cell = {10., 0., 0., 0., 10., 0., 0., 0., 10.};
std::vector<int > atype = {1, 0, 1};
double e;
std::vector<double > f, v;
dp.compute (e, f, v, coord, atype, cell);
}
Note that the feature of the header-only C++ library is still limited compared to the original C++ library. See deepmd::hpp::DeepPot for details.
You can compile infer_water_hpp.cpp using gcc:
gcc infer_water_hpp.cpp -L $deepmd_root/lib -I $deepmd_root/include -Wl,--no-as-needed -ldeepmd_c -Wl,-rpath=$deepmd_root/lib -o infer_water_hpp
and then run the program:
./infer_water_hpp
In some cases, one may want to pass the custom neighbor list instead of the native neighbor list. The above code can be revised as follows:
// neighbor list
std::vector<std::vector<int >> nlist_vec = {
{1, 2},
{0, 2},
{0, 1}
};
std::vector<int> ilist(3), numneigh(3);
std::vector<int*> firstneigh(3);
InputNlist nlist(3, &ilist[0], &numneigh[0], &firstneigh[0]);
convert_nlist(nlist, nlist_vec);
dp.compute (e, f, v, coord, atype, cell, 0, nlist, 0);
Here, nlist_vec means the neighbors of atom 0 are atom 1 and atom 2, the neighbors of atom 1 are atom 0 and atom 2, and the neighbors of atom 2 are atom 0 and atom 1.