diff --git a/source/api_c/include/c_api.h b/source/api_c/include/c_api.h index 2d68cb62db..7823fe70e0 100644 --- a/source/api_c/include/c_api.h +++ b/source/api_c/include/c_api.h @@ -47,6 +47,7 @@ extern DP_DeepPot* DP_NewDeepPotWithParam(const char* c_model, /** * @brief Evaluate the energy, force and virial by using a DP. (double version) + * @attention The number of frames is assumed to be 1. * @param[in] dp The DP to use. * @param[in] natoms The number of atoms. * @param[in] coord The coordinates of atoms. The array should be of size natoms @@ -77,6 +78,7 @@ extern void DP_DeepPotCompute(DP_DeepPot* dp, /** * @brief Evaluate the energy, force and virial by using a DP. (float version) + * @attention The number of frames is assumed to be 1. * @param[in] dp The DP to use. * @param[in] natoms The number of atoms. * @param[in] coord The coordinates of atoms. The array should be of size natoms @@ -108,6 +110,7 @@ extern void DP_DeepPotComputef(DP_DeepPot* dp, /** * @brief Evaluate the energy, force and virial by using a DP with the neighbor *list. (double version) + * @attention The number of frames is assumed to be 1. * @param[in] dp The DP to use. * @param[in] natoms The number of atoms. * @param[in] coord The coordinates of atoms. The array should be of size natoms @@ -145,6 +148,7 @@ extern void DP_DeepPotComputeNList(DP_DeepPot* dp, /** * @brief Evaluate the energy, force and virial by using a DP with the neighbor *list. (float version) + * @attention The number of frames is assumed to be 1. * @param[in] dp The DP to use. * @param[in] natoms The number of atoms. * @param[in] coord The coordinates of atoms. The array should be of size natoms @@ -179,6 +183,168 @@ extern void DP_DeepPotComputeNListf(DP_DeepPot* dp, float* atomic_energy, float* atomic_virial); +/** + * @brief Evaluate the energy, force and virial by using a DP. (double version) + * @version 2 + * @param[in] dp The DP to use. + * @param[in] nframes The number of frames. + * @param[in] natoms The number of atoms. + * @param[in] coord The coordinates of atoms. The array should be of size natoms + *x 3. + * @param[in] atype The atom types. The array should contain natoms ints. + * @param[in] box The cell of the region. The array should be of size 9. Pass + *NULL if pbc is not used. + * @param[in] fparam The frame parameters. (not work at this time) + * @param[in] aparam The atom parameters. (not work at this time) + * @param[out] energy Output energy. + * @param[out] force Output force. The array should be of size natoms x 3. + * @param[out] virial Output virial. The array should be of size 9. + * @param[out] atomic_energy Output atomic energy. The array should be of size + *natoms. + * @param[out] atomic_virial Output atomic virial. The array should be of size + *natoms x 9. + * @warning The output arrays should be allocated before calling this function. + *Pass NULL if not required. + **/ +extern void DP_DeepPotCompute2(DP_DeepPot* dp, + const int nframes, + const int natom, + const double* coord, + const int* atype, + const double* cell, + const double* fparam, + const double* aparam, + double* energy, + double* force, + double* virial, + double* atomic_energy, + double* atomic_virial); + +/** + * @brief Evaluate the energy, force and virial by using a DP. (float version) + * @version 2 + * @param[in] dp The DP to use. + * @param[in] nframes The number of frames. + * @param[in] natoms The number of atoms. + * @param[in] coord The coordinates of atoms. The array should be of size natoms + *x 3. + * @param[in] atype The atom types. The array should contain natoms ints. + * @param[in] box The cell of the region. The array should be of size 9. Pass + *NULL if pbc is not used. + * @param[in] fparam The frame parameters. (not work at this time) + * @param[in] aparam The atom parameters. (not work at this time) + * @param[out] energy Output energy. + * @param[out] force Output force. The array should be of size natoms x 3. + * @param[out] virial Output virial. The array should be of size 9. + * @param[out] atomic_energy Output atomic energy. The array should be of size + *natoms. + * @param[out] atomic_virial Output atomic virial. The array should be of size + *natoms x 9. + * @warning The output arrays should be allocated before calling this function. + *Pass NULL if not required. + **/ +extern void DP_DeepPotComputef2(DP_DeepPot* dp, + const int nframes, + const int natom, + const float* coord, + const int* atype, + const float* cell, + const float* fparam, + const float* aparam, + double* energy, + float* force, + float* virial, + float* atomic_energy, + float* atomic_virial); + +/** + * @brief Evaluate the energy, force and virial by using a DP with the neighbor + *list. (double version) + * @version 2 + * @param[in] dp The DP to use. + * @param[in] nframes The number of frames. + * @param[in] natoms The number of atoms. + * @param[in] coord The coordinates of atoms. The array should be of size natoms + *x 3. + * @param[in] atype The atom types. The array should contain natoms ints. + * @param[in] box The cell of the region. The array should be of size 9. Pass + *NULL if pbc is not used. + * @param[in] nghost The number of ghost atoms. + * @param[in] nlist The neighbor list. + * @param[in] ago Update the internal neighbour list if ago is 0. + * @param[in] fparam The frame parameters. (not work at this time) + * @param[in] aparam The atom parameters. (not work at this time) + * @param[out] energy Output energy. + * @param[out] force Output force. The array should be of size natoms x 3. + * @param[out] virial Output virial. The array should be of size 9. + * @param[out] atomic_energy Output atomic energy. The array should be of size + *natoms. + * @param[out] atomic_virial Output atomic virial. The array should be of size + *natoms x 9. + * @warning The output arrays should be allocated before calling this function. + *Pass NULL if not required. + **/ +extern void DP_DeepPotComputeNList2(DP_DeepPot* dp, + const int nframes, + const int natom, + const double* coord, + const int* atype, + const double* cell, + const int nghost, + const DP_Nlist* nlist, + const int ago, + const double* fparam, + const double* aparam, + double* energy, + double* force, + double* virial, + double* atomic_energy, + double* atomic_virial); + +/** + * @brief Evaluate the energy, force and virial by using a DP with the neighbor + *list. (float version) + * @version 2 + * @param[in] dp The DP to use. + * @param[in] nframes The number of frames. + * @param[in] natoms The number of atoms. + * @param[in] coord The coordinates of atoms. The array should be of size natoms + *x 3. + * @param[in] atype The atom types. The array should contain natoms ints. + * @param[in] box The cell of the region. The array should be of size 9. Pass + *NULL if pbc is not used. + * @param[in] nghost The number of ghost atoms. + * @param[in] nlist The neighbor list. + * @param[in] ago Update the internal neighbour list if ago is 0. + * @param[in] fparam The frame parameters. (not work at this time) + * @param[in] aparam The atom parameters. (not work at this time) + * @param[out] energy Output energy. + * @param[out] force Output force. The array should be of size natoms x 3. + * @param[out] virial Output virial. The array should be of size 9. + * @param[out] atomic_energy Output atomic energy. The array should be of size + *natoms. + * @param[out] atomic_virial Output atomic virial. The array should be of size + *natoms x 9. + * @warning The output arrays should be allocated before calling this function. + *Pass NULL if not required. + **/ +extern void DP_DeepPotComputeNListf2(DP_DeepPot* dp, + const int nframes, + const int natom, + const float* coord, + const int* atype, + const float* cell, + const int nghost, + const DP_Nlist* nlist, + const int ago, + const float* fparam, + const float* aparam, + double* energy, + float* force, + float* virial, + float* atomic_energy, + float* atomic_virial); + /** * @brief The deep potential model deviation. **/ diff --git a/source/api_c/include/deepmd.hpp b/source/api_c/include/deepmd.hpp index 8e7a1a9404..2122125f52 100644 --- a/source/api_c/include/deepmd.hpp +++ b/source/api_c/include/deepmd.hpp @@ -16,10 +16,13 @@ This header-only library provides a C++ 11 interface to the DeePMD-kit C API. template inline void _DP_DeepPotCompute(DP_DeepPot *dp, + const int nframes, const int natom, const FPTYPE *coord, const int *atype, const FPTYPE *cell, + const FPTYPE *fparam, + const FPTYPE *aparam, double *energy, FPTYPE *force, FPTYPE *virial, @@ -28,36 +31,43 @@ inline void _DP_DeepPotCompute(DP_DeepPot *dp, template <> inline void _DP_DeepPotCompute(DP_DeepPot *dp, + const int nframes, const int natom, const double *coord, const int *atype, const double *cell, + const double *fparam, + const double *aparam, double *energy, double *force, double *virial, double *atomic_energy, double *atomic_virial) { - DP_DeepPotCompute(dp, natom, coord, atype, cell, energy, force, virial, - atomic_energy, atomic_virial); + DP_DeepPotCompute2(dp, nframes, natom, coord, atype, cell, fparam, aparam, + energy, force, virial, atomic_energy, atomic_virial); } template <> inline void _DP_DeepPotCompute(DP_DeepPot *dp, + const int nframes, const int natom, const float *coord, const int *atype, const float *cell, + const float *fparam, + const float *aparam, double *energy, float *force, float *virial, float *atomic_energy, float *atomic_virial) { - DP_DeepPotComputef(dp, natom, coord, atype, cell, energy, force, virial, - atomic_energy, atomic_virial); + DP_DeepPotComputef2(dp, nframes, natom, coord, atype, cell, fparam, aparam, + energy, force, virial, atomic_energy, atomic_virial); } template inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, + const int nframes, const int natom, const FPTYPE *coord, const int *atype, @@ -65,6 +75,8 @@ inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, const int nghost, const DP_Nlist *nlist, const int ago, + const FPTYPE *fparam, + const FPTYPE *aparam, double *energy, FPTYPE *force, FPTYPE *virial, @@ -73,6 +85,7 @@ inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, template <> inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, + const int nframes, const int natom, const double *coord, const int *atype, @@ -80,17 +93,21 @@ inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, const int nghost, const DP_Nlist *nlist, const int ago, + const double *fparam, + const double *aparam, double *energy, double *force, double *virial, double *atomic_energy, double *atomic_virial) { - DP_DeepPotComputeNList(dp, natom, coord, atype, cell, nghost, nlist, ago, - energy, force, virial, atomic_energy, atomic_virial); + DP_DeepPotComputeNList2(dp, nframes, natom, coord, atype, cell, nghost, nlist, + ago, fparam, aparam, energy, force, virial, + atomic_energy, atomic_virial); } template <> inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, + const int nframes, const int natom, const float *coord, const int *atype, @@ -98,13 +115,16 @@ inline void _DP_DeepPotComputeNList(DP_DeepPot *dp, const int nghost, const DP_Nlist *nlist, const int ago, + const float *fparam, + const float *aparam, double *energy, float *force, float *virial, float *atomic_energy, float *atomic_virial) { - DP_DeepPotComputeNListf(dp, natom, coord, atype, cell, nghost, nlist, ago, - energy, force, virial, atomic_energy, atomic_virial); + DP_DeepPotComputeNListf2(dp, nframes, natom, coord, atype, cell, nghost, + nlist, ago, fparam, aparam, energy, force, virial, + atomic_energy, atomic_virial); } template @@ -380,6 +400,17 @@ inline void _DP_DipoleChargeModifierComputeNList( dvcorr_); } +inline double *_DP_Get_Energy_Pointer(std::vector &vec, + const int nframes) { + vec.resize(nframes); + return &vec[0]; +} + +inline double *_DP_Get_Energy_Pointer(double &vec, const int nframes) { + assert(nframes == 1); + return &vec; +} + namespace deepmd { namespace hpp { /** @@ -486,29 +517,31 @@ class DeepPot { * @param[in] box The cell of the region. The array should be of size nframes *x 9 (PBC) or empty (no PBC). **/ - template - void compute(double &ener, + template + void compute(ENERGYVTYPE &ener, std::vector &force, std::vector &virial, const std::vector &coord, const std::vector &atype, const std::vector &box) { unsigned int natoms = atype.size(); - assert(natoms * 3 == coord.size()); + unsigned int nframes = coord.size() / natoms / 3; + assert(nframes * natoms * 3 == coord.size()); if (!box.empty()) { - assert(box.size() == 9); + assert(box.size() == nframes * 9); } const VALUETYPE *coord_ = &coord[0]; const VALUETYPE *box_ = !box.empty() ? &box[0] : nullptr; const int *atype_ = &atype[0]; - double *ener_ = &ener; - force.resize(natoms * 3); - virial.resize(9); + double *ener_ = _DP_Get_Energy_Pointer(ener, nframes); + force.resize(nframes * natoms * 3); + virial.resize(nframes * 9); VALUETYPE *force_ = &force[0]; VALUETYPE *virial_ = &virial[0]; - _DP_DeepPotCompute(dp, natoms, coord_, atype_, box_, ener_, - force_, virial_, nullptr, nullptr); + _DP_DeepPotCompute(dp, nframes, natoms, coord_, atype_, box_, + nullptr, nullptr, ener_, force_, virial_, + nullptr, nullptr); }; /** * @brief Evaluate the energy, force, virial, atomic energy, and atomic virial @@ -524,8 +557,8 @@ class DeepPot { * @param[in] box The cell of the region. The array should be of size nframes *x 9 (PBC) or empty (no PBC). **/ - template - void compute(double &ener, + template + void compute(ENERGYVTYPE &ener, std::vector &force, std::vector &virial, std::vector &atom_energy, @@ -534,27 +567,28 @@ class DeepPot { const std::vector &atype, const std::vector &box) { unsigned int natoms = atype.size(); - assert(natoms * 3 == coord.size()); + unsigned int nframes = coord.size() / natoms / 3; + assert(nframes * natoms * 3 == coord.size()); if (!box.empty()) { - assert(box.size() == 9); + assert(box.size() == nframes * 9); } const VALUETYPE *coord_ = &coord[0]; const VALUETYPE *box_ = !box.empty() ? &box[0] : nullptr; const int *atype_ = &atype[0]; - double *ener_ = &ener; - force.resize(natoms * 3); - virial.resize(9); - atom_energy.resize(natoms); - atom_virial.resize(natoms * 9); + double *ener_ = _DP_Get_Energy_Pointer(ener, nframes); + force.resize(nframes * natoms * 3); + virial.resize(nframes * 9); + atom_energy.resize(nframes * natoms); + atom_virial.resize(nframes * natoms * 9); VALUETYPE *force_ = &force[0]; VALUETYPE *virial_ = &virial[0]; VALUETYPE *atomic_ener_ = &atom_energy[0]; VALUETYPE *atomic_virial_ = &atom_virial[0]; - _DP_DeepPotCompute(dp, natoms, coord_, atype_, box_, ener_, - force_, virial_, atomic_ener_, - atomic_virial_); + _DP_DeepPotCompute(dp, nframes, natoms, coord_, atype_, box_, + nullptr, nullptr, ener_, force_, virial_, + atomic_ener_, atomic_virial_); }; /** @@ -572,8 +606,8 @@ class DeepPot { * @param[in] nlist The neighbor list. * @param[in] ago Update the internal neighbour list if ago is 0. **/ - template - void compute(double &ener, + template + void compute(ENERGYVTYPE &ener, std::vector &force, std::vector &virial, const std::vector &coord, @@ -583,22 +617,23 @@ class DeepPot { const InputNlist &lmp_list, const int &ago) { unsigned int natoms = atype.size(); - assert(natoms * 3 == coord.size()); + unsigned int nframes = coord.size() / natoms / 3; + assert(nframes * natoms * 3 == coord.size()); if (!box.empty()) { - assert(box.size() == 9); + assert(box.size() == nframes * 9); } const VALUETYPE *coord_ = &coord[0]; const VALUETYPE *box_ = !box.empty() ? &box[0] : nullptr; const int *atype_ = &atype[0]; - double *ener_ = &ener; - force.resize(natoms * 3); - virial.resize(9); + double *ener_ = _DP_Get_Energy_Pointer(ener, nframes); + force.resize(nframes * natoms * 3); + virial.resize(nframes * 9); VALUETYPE *force_ = &force[0]; VALUETYPE *virial_ = &virial[0]; - _DP_DeepPotComputeNList(dp, natoms, coord_, atype_, box_, nghost, - lmp_list.nl, ago, ener_, force_, virial_, - nullptr, nullptr); + _DP_DeepPotComputeNList( + dp, nframes, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, + nullptr, nullptr, ener_, force_, virial_, nullptr, nullptr); }; /** * @brief Evaluate the energy, force, virial, atomic energy, and atomic virial @@ -617,8 +652,8 @@ class DeepPot { * @param[in] nlist The neighbor list. * @param[in] ago Update the internal neighbour list if ago is 0. **/ - template - void compute(double &ener, + template + void compute(ENERGYVTYPE &ener, std::vector &force, std::vector &virial, std::vector &atom_energy, @@ -630,27 +665,28 @@ class DeepPot { const InputNlist &lmp_list, const int &ago) { unsigned int natoms = atype.size(); - assert(natoms * 3 == coord.size()); + unsigned int nframes = coord.size() / natoms / 3; + assert(nframes * natoms * 3 == coord.size()); if (!box.empty()) { - assert(box.size() == 9); + assert(box.size() == nframes * 9); } const VALUETYPE *coord_ = &coord[0]; const VALUETYPE *box_ = !box.empty() ? &box[0] : nullptr; const int *atype_ = &atype[0]; - double *ener_ = &ener; - force.resize(natoms * 3); - virial.resize(9); - atom_energy.resize(natoms); - atom_virial.resize(natoms * 9); + double *ener_ = _DP_Get_Energy_Pointer(ener, nframes); + force.resize(nframes * natoms * 3); + virial.resize(nframes * 9); + atom_energy.resize(nframes * natoms); + atom_virial.resize(nframes * natoms * 9); VALUETYPE *force_ = &force[0]; VALUETYPE *virial_ = &virial[0]; VALUETYPE *atomic_ener_ = &atom_energy[0]; VALUETYPE *atomic_virial_ = &atom_virial[0]; - _DP_DeepPotComputeNList(dp, natoms, coord_, atype_, box_, nghost, - lmp_list.nl, ago, ener_, force_, virial_, - atomic_ener_, atomic_virial_); + _DP_DeepPotComputeNList( + dp, nframes, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, + nullptr, nullptr, ener_, force_, virial_, atomic_ener_, atomic_virial_); }; /** * @brief Get the cutoff radius. diff --git a/source/api_c/src/c_api.cc b/source/api_c/src/c_api.cc index 4647aea98b..ae4171746f 100644 --- a/source/api_c/src/c_api.cc +++ b/source/api_c/src/c_api.cc @@ -96,29 +96,32 @@ DP_DipoleChargeModifier* DP_NewDipoleChargeModifierWithParam( template inline void DP_DeepPotCompute_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const VALUETYPE* coord, const int* atype, const VALUETYPE* cell, + const VALUETYPE* fparam, + const VALUETYPE* aparam, double* energy, VALUETYPE* force, VALUETYPE* virial, VALUETYPE* atomic_energy, VALUETYPE* atomic_virial) { // init C++ vectors from C arrays - std::vector coord_(coord, coord + natoms * 3); + std::vector coord_(coord, coord + nframes * natoms * 3); std::vector atype_(atype, atype + natoms); std::vector cell_; if (cell) { // pbc - cell_.assign(cell, cell + 9); + cell_.assign(cell, cell + nframes * 9); } - double e; + std::vector e; std::vector f, v, ae, av; dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_); // copy from C++ vectors to C arrays, if not NULL pointer - if (energy) *energy = e; + if (energy) std::copy(e.begin(), e.end(), energy); if (force) std::copy(f.begin(), f.end(), force); if (virial) std::copy(v.begin(), v.end(), virial); if (atomic_energy) std::copy(ae.begin(), ae.end(), atomic_energy); @@ -126,10 +129,13 @@ inline void DP_DeepPotCompute_variant(DP_DeepPot* dp, } template void DP_DeepPotCompute_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const double* coord, const int* atype, const double* cell, + const double* fparam, + const double* aparam, double* energy, double* force, double* virial, @@ -137,10 +143,13 @@ template void DP_DeepPotCompute_variant(DP_DeepPot* dp, double* atomic_virial); template void DP_DeepPotCompute_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const float* coord, const int* atype, const float* cell, + const float* fparam, + const float* aparam, double* energy, float* force, float* virial, @@ -149,6 +158,7 @@ template void DP_DeepPotCompute_variant(DP_DeepPot* dp, template inline void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const VALUETYPE* coord, const int* atype, @@ -156,26 +166,28 @@ inline void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, const int nghost, const DP_Nlist* nlist, const int ago, + const VALUETYPE* fparam, + const VALUETYPE* aparam, double* energy, VALUETYPE* force, VALUETYPE* virial, VALUETYPE* atomic_energy, VALUETYPE* atomic_virial) { // init C++ vectors from C arrays - std::vector coord_(coord, coord + natoms * 3); + std::vector coord_(coord, coord + nframes * natoms * 3); std::vector atype_(atype, atype + natoms); std::vector cell_; if (cell) { // pbc - cell_.assign(cell, cell + 9); + cell_.assign(cell, cell + nframes * 9); } - double e; + std::vector e; std::vector f, v, ae, av; dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_, nghost, nlist->nl, ago); // copy from C++ vectors to C arrays, if not NULL pointer - if (energy) *energy = e; + if (energy) std::copy(e.begin(), e.end(), energy); if (force) std::copy(f.begin(), f.end(), force); if (virial) std::copy(v.begin(), v.end(), virial); if (atomic_energy) std::copy(ae.begin(), ae.end(), atomic_energy); @@ -183,6 +195,7 @@ inline void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, } template void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const double* coord, const int* atype, @@ -190,6 +203,8 @@ template void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, const int nghost, const DP_Nlist* nlist, const int ago, + const double* fparam, + const double* aparam, double* energy, double* force, double* virial, @@ -197,6 +212,7 @@ template void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, double* atomic_virial); template void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, + const int nframes, const int natoms, const float* coord, const int* atype, @@ -204,6 +220,8 @@ template void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, const int nghost, const DP_Nlist* nlist, const int ago, + const float* fparam, + const float* aparam, double* energy, float* force, float* virial, @@ -596,8 +614,8 @@ void DP_DeepPotCompute(DP_DeepPot* dp, double* virial, double* atomic_energy, double* atomic_virial) { - DP_DeepPotCompute_variant(dp, natoms, coord, atype, cell, energy, - force, virial, atomic_energy, + DP_DeepPotCompute_variant(dp, 1, natoms, coord, atype, cell, NULL, + NULL, energy, force, virial, atomic_energy, atomic_virial); } @@ -611,8 +629,9 @@ void DP_DeepPotComputef(DP_DeepPot* dp, float* virial, float* atomic_energy, float* atomic_virial) { - DP_DeepPotCompute_variant(dp, natoms, coord, atype, cell, energy, - force, virial, atomic_energy, atomic_virial); + DP_DeepPotCompute_variant(dp, 1, natoms, coord, atype, cell, NULL, + NULL, energy, force, virial, atomic_energy, + atomic_virial); } void DP_DeepPotComputeNList(DP_DeepPot* dp, @@ -628,9 +647,9 @@ void DP_DeepPotComputeNList(DP_DeepPot* dp, double* virial, double* atomic_energy, double* atomic_virial) { - DP_DeepPotComputeNList_variant(dp, natoms, coord, atype, cell, nghost, - nlist, ago, energy, force, virial, - atomic_energy, atomic_virial); + DP_DeepPotComputeNList_variant( + dp, 1, natoms, coord, atype, cell, nghost, nlist, ago, NULL, NULL, energy, + force, virial, atomic_energy, atomic_virial); } void DP_DeepPotComputeNListf(DP_DeepPot* dp, @@ -646,11 +665,91 @@ void DP_DeepPotComputeNListf(DP_DeepPot* dp, float* virial, float* atomic_energy, float* atomic_virial) { - DP_DeepPotComputeNList_variant(dp, natoms, coord, atype, cell, nghost, - nlist, ago, energy, force, virial, - atomic_energy, atomic_virial); + DP_DeepPotComputeNList_variant( + dp, 1, natoms, coord, atype, cell, nghost, nlist, ago, NULL, NULL, energy, + force, virial, atomic_energy, atomic_virial); } +// multiple frames +void DP_DeepPotCompute2(DP_DeepPot* dp, + const int nframes, + const int natoms, + const double* coord, + const int* atype, + const double* cell, + const double* fparam, + const double* aparam, + double* energy, + double* force, + double* virial, + double* atomic_energy, + double* atomic_virial) { + DP_DeepPotCompute_variant(dp, nframes, natoms, coord, atype, cell, + fparam, aparam, energy, force, virial, + atomic_energy, atomic_virial); +} + +void DP_DeepPotComputef2(DP_DeepPot* dp, + const int nframes, + const int natoms, + const float* coord, + const int* atype, + const float* cell, + const float* fparam, + const float* aparam, + double* energy, + float* force, + float* virial, + float* atomic_energy, + float* atomic_virial) { + DP_DeepPotCompute_variant(dp, nframes, natoms, coord, atype, cell, + fparam, aparam, energy, force, virial, + atomic_energy, atomic_virial); +} + +void DP_DeepPotComputeNList2(DP_DeepPot* dp, + const int nframes, + const int natoms, + const double* coord, + const int* atype, + const double* cell, + const int nghost, + const DP_Nlist* nlist, + const int ago, + const double* fparam, + const double* aparam, + double* energy, + double* force, + double* virial, + double* atomic_energy, + double* atomic_virial) { + DP_DeepPotComputeNList_variant( + dp, nframes, natoms, coord, atype, cell, nghost, nlist, ago, fparam, + aparam, energy, force, virial, atomic_energy, atomic_virial); +} + +void DP_DeepPotComputeNListf2(DP_DeepPot* dp, + const int nframes, + const int natoms, + const float* coord, + const int* atype, + const float* cell, + const int nghost, + const DP_Nlist* nlist, + const int ago, + const float* fparam, + const float* aparam, + double* energy, + float* force, + float* virial, + float* atomic_energy, + float* atomic_virial) { + DP_DeepPotComputeNList_variant( + dp, nframes, natoms, coord, atype, cell, nghost, nlist, ago, fparam, + aparam, energy, force, virial, atomic_energy, atomic_virial); +} +// end multiple frames + const char* DP_DeepPotGetTypeMap(DP_DeepPot* dp) { std::string type_map; dp->dp.get_type_map(type_map); diff --git a/source/api_c/tests/test_deeppot_a_nframes_hpp.cc b/source/api_c/tests/test_deeppot_a_nframes_hpp.cc new file mode 100644 index 0000000000..7e39c06560 --- /dev/null +++ b/source/api_c/tests/test_deeppot_a_nframes_hpp.cc @@ -0,0 +1,781 @@ +#include + +#include +#include +#include +#include + +#include "deepmd.hpp" +#include "test_utils.h" + +template +class TestInferDeepPotANFrames : public ::testing::Test { + protected: + std::vector coord = { + 12.83, 2.56, 2.18, 12.09, 2.87, 2.74, 00.25, 3.32, 1.68, + 3.36, 3.00, 1.81, 3.51, 2.51, 2.60, 4.27, 3.22, 1.56, + 12.83, 2.56, 2.18, 12.09, 2.87, 2.74, 00.25, 3.32, 1.68, + 3.36, 3.00, 1.81, 3.51, 2.51, 2.60, 4.27, 3.22, 1.56}; + std::vector atype = {0, 1, 1, 0, 1, 1}; + std::vector box = {13., 0., 0., 0., 13., 0., 0., 0., 13., + 13., 0., 0., 0., 13., 0., 0., 0., 13.}; + std::vector expected_e = { + -9.275780747115504710e+01, -1.863501786584258468e+02, + -1.863392472863538103e+02, -9.279281325486221021e+01, + -1.863671545232153903e+02, -1.863619822847602165e+02, + -9.275780747115504710e+01, -1.863501786584258468e+02, + -1.863392472863538103e+02, -9.279281325486221021e+01, + -1.863671545232153903e+02, -1.863619822847602165e+02}; + std::vector expected_f = { + -3.034045420701179663e-01, 8.405844663871177014e-01, + 7.696947487118485642e-02, 7.662001266663505117e-01, + -1.880601391333554251e-01, -6.183333871091722944e-01, + -5.036172391059643427e-01, -6.529525836149027151e-01, + 5.432962643022043459e-01, 6.382357912332115024e-01, + -1.748518296794561167e-01, 3.457363524891907125e-01, + 1.286482986991941552e-03, 3.757251165286925043e-01, + -5.972588700887541124e-01, -5.987006197104716154e-01, + -2.004450304880958100e-01, 2.495901655353461868e-01, + -3.034045420701179663e-01, 8.405844663871177014e-01, + 7.696947487118485642e-02, 7.662001266663505117e-01, + -1.880601391333554251e-01, -6.183333871091722944e-01, + -5.036172391059643427e-01, -6.529525836149027151e-01, + 5.432962643022043459e-01, 6.382357912332115024e-01, + -1.748518296794561167e-01, 3.457363524891907125e-01, + 1.286482986991941552e-03, 3.757251165286925043e-01, + -5.972588700887541124e-01, -5.987006197104716154e-01, + -2.004450304880958100e-01, 2.495901655353461868e-01}; + std::vector expected_v = { + -2.912234126853306959e-01, -3.800610846612756388e-02, + 2.776624987489437202e-01, -5.053761003913598976e-02, + -3.152373041953385746e-01, 1.060894290092162379e-01, + 2.826389131596073745e-01, 1.039129970665329250e-01, + -2.584378792325942586e-01, -3.121722367954994914e-01, + 8.483275876786681990e-02, 2.524662342344257682e-01, + 4.142176771106586414e-02, -3.820285230785245428e-02, + -2.727311173065460545e-02, 2.668859789777112135e-01, + -6.448243569420382404e-02, -2.121731470426218846e-01, + -8.624335220278558922e-02, -1.809695356746038597e-01, + 1.529875294531883312e-01, -1.283658185172031341e-01, + -1.992682279795223999e-01, 1.409924999632362341e-01, + 1.398322735274434292e-01, 1.804318474574856390e-01, + -1.470309318999652726e-01, -2.593983661598450730e-01, + -4.236536279233147489e-02, 3.386387920184946720e-02, + -4.174017537818433543e-02, -1.003500282164128260e-01, + 1.525690815194478966e-01, 3.398976109910181037e-02, + 1.522253908435125536e-01, -2.349125581341701963e-01, + 9.515545977581392825e-04, -1.643218849228543846e-02, + 1.993234765412972564e-02, 6.027265332209678569e-04, + -9.563256398907417355e-02, 1.510815124001868293e-01, + -7.738094816888557714e-03, 1.502832772532304295e-01, + -2.380965783745832010e-01, -2.309456719810296654e-01, + -6.666961081213038098e-02, 7.955566551234216632e-02, + -8.099093777937517447e-02, -3.386641099800401927e-02, + 4.447884755740908608e-02, 1.008593228579038742e-01, + 4.556718179228393811e-02, -6.078081273849572641e-02, + -2.912234126853306959e-01, -3.800610846612756388e-02, + 2.776624987489437202e-01, -5.053761003913598976e-02, + -3.152373041953385746e-01, 1.060894290092162379e-01, + 2.826389131596073745e-01, 1.039129970665329250e-01, + -2.584378792325942586e-01, -3.121722367954994914e-01, + 8.483275876786681990e-02, 2.524662342344257682e-01, + 4.142176771106586414e-02, -3.820285230785245428e-02, + -2.727311173065460545e-02, 2.668859789777112135e-01, + -6.448243569420382404e-02, -2.121731470426218846e-01, + -8.624335220278558922e-02, -1.809695356746038597e-01, + 1.529875294531883312e-01, -1.283658185172031341e-01, + -1.992682279795223999e-01, 1.409924999632362341e-01, + 1.398322735274434292e-01, 1.804318474574856390e-01, + -1.470309318999652726e-01, -2.593983661598450730e-01, + -4.236536279233147489e-02, 3.386387920184946720e-02, + -4.174017537818433543e-02, -1.003500282164128260e-01, + 1.525690815194478966e-01, 3.398976109910181037e-02, + 1.522253908435125536e-01, -2.349125581341701963e-01, + 9.515545977581392825e-04, -1.643218849228543846e-02, + 1.993234765412972564e-02, 6.027265332209678569e-04, + -9.563256398907417355e-02, 1.510815124001868293e-01, + -7.738094816888557714e-03, 1.502832772532304295e-01, + -2.380965783745832010e-01, -2.309456719810296654e-01, + -6.666961081213038098e-02, 7.955566551234216632e-02, + -8.099093777937517447e-02, -3.386641099800401927e-02, + 4.447884755740908608e-02, 1.008593228579038742e-01, + 4.556718179228393811e-02, -6.078081273849572641e-02}; + int natoms; + int nframes = 2; + std::vector expected_tot_e; + std::vector expected_tot_v; + + deepmd::hpp::DeepPot dp; + + void SetUp() override { + std::string file_name = "../../tests/infer/deeppot.pbtxt"; + deepmd::hpp::convert_pbtxt_to_pb("../../tests/infer/deeppot.pbtxt", + "deeppot.pb"); + + dp.init("deeppot.pb"); + + natoms = expected_e.size() / nframes; + EXPECT_EQ(nframes * natoms * 3, expected_f.size()); + EXPECT_EQ(nframes * natoms * 9, expected_v.size()); + expected_tot_e.resize(nframes); + expected_tot_v.resize(nframes * 9); + std::fill(expected_tot_e.begin(), expected_tot_e.end(), 0.); + std::fill(expected_tot_v.begin(), expected_tot_v.end(), 0.); + for (int kk = 0; kk < nframes; ++kk) { + for (int ii = 0; ii < natoms; ++ii) { + expected_tot_e[kk] += expected_e[kk * natoms + ii]; + } + for (int ii = 0; ii < natoms; ++ii) { + for (int dd = 0; dd < 9; ++dd) { + expected_tot_v[kk * 9 + dd] += + expected_v[kk * natoms * 9 + ii * 9 + dd]; + } + } + } + }; + + void TearDown() override { remove("deeppot.pb"); }; +}; + +TYPED_TEST_SUITE(TestInferDeepPotANFrames, ValueTypes); + +TYPED_TEST(TestInferDeepPotANFrames, cpu_build_nlist) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + std::vector ener; + std::vector force, virial; + dp.compute(ener, force, virial, coord, atype, box); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_build_nlist_atomic) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + std::vector ener; + std::vector force, virial, atom_ener, atom_vir; + dp.compute(ener, force, virial, atom_ener, atom_vir, coord, atype, box); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + EXPECT_EQ(atom_ener.size(), nframes * natoms); + EXPECT_EQ(atom_vir.size(), nframes * natoms * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms; ++ii) { + EXPECT_LT(fabs(atom_ener[ii] - expected_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 9; ++ii) { + EXPECT_LT(fabs(atom_vir[ii] - expected_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_lmp_nlist) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + float rc = dp.cutoff(); + std::vector coord_first(coord.begin(), coord.begin() + 3 * natoms); + std::vector box_first(box.begin(), box.begin() + 9); + int nloc = coord_first.size() / 3; + std::vector coord_cpy; + std::vector atype_cpy, mapping; + std::vector > nlist_data; + _build_nlist(nlist_data, coord_cpy, atype_cpy, mapping, + coord_first, atype, box_first, rc); + int nall = coord_cpy.size() / 3; + std::vector ilist(nloc), numneigh(nloc); + std::vector firstneigh(nloc); + deepmd::hpp::InputNlist inlist(nloc, &ilist[0], &numneigh[0], &firstneigh[0]); + convert_nlist(inlist, nlist_data); + std::vector coord_cpy2(nframes * nall * 3); + for (int ii = 0; ii < nframes; ++ii) { + for (int jj = 0; jj < nall * 3; ++jj) { + coord_cpy2[ii * nall * 3 + jj] = coord_cpy[jj]; + } + } + + std::vector ener; + std::vector force_, virial; + dp.compute(ener, force_, virial, coord_cpy2, atype_cpy, box, nall - nloc, + inlist, 0); + std::vector force; + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } + + std::fill(ener.begin(), ener.end(), 0.0); + std::fill(force_.begin(), force_.end(), 0.0); + std::fill(virial.begin(), virial.end(), 0.0); + dp.compute(ener, force_, virial, coord_cpy2, atype_cpy, box, nall - nloc, + inlist, 1); + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_lmp_nlist_atomic) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + float rc = dp.cutoff(); + std::vector coord_first(coord.begin(), coord.begin() + 3 * natoms); + std::vector box_first(box.begin(), box.begin() + 9); + int nloc = coord_first.size() / 3; + std::vector coord_cpy; + std::vector atype_cpy, mapping; + std::vector > nlist_data; + _build_nlist(nlist_data, coord_cpy, atype_cpy, mapping, + coord_first, atype, box_first, rc); + int nall = coord_cpy.size() / 3; + std::vector ilist(nloc), numneigh(nloc); + std::vector firstneigh(nloc); + deepmd::hpp::InputNlist inlist(nloc, &ilist[0], &numneigh[0], &firstneigh[0]); + convert_nlist(inlist, nlist_data); + std::vector coord_cpy2(nframes * nall * 3); + for (int ii = 0; ii < nframes; ++ii) { + for (int jj = 0; jj < nall * 3; ++jj) { + coord_cpy2[ii * nall * 3 + jj] = coord_cpy[jj]; + } + } + + std::vector ener; + std::vector force_, atom_ener_, atom_vir_, virial; + std::vector force, atom_ener, atom_vir; + dp.compute(ener, force_, virial, atom_ener_, atom_vir_, coord_cpy2, atype_cpy, + box, nall - nloc, inlist, 0); + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + _fold_back(atom_ener, atom_ener_, mapping, nloc, nall, 1, nframes); + _fold_back(atom_vir, atom_vir_, mapping, nloc, nall, 9, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + EXPECT_EQ(atom_ener.size(), nframes * natoms); + EXPECT_EQ(atom_vir.size(), nframes * natoms * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms; ++ii) { + EXPECT_LT(fabs(atom_ener[ii] - expected_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 9; ++ii) { + EXPECT_LT(fabs(atom_vir[ii] - expected_v[ii]), EPSILON); + } + + std::fill(ener.begin(), ener.end(), 0.0); + std::fill(force_.begin(), force_.end(), 0.0); + std::fill(virial.begin(), virial.end(), 0.0); + std::fill(atom_ener_.begin(), atom_ener_.end(), 0.0); + std::fill(atom_vir_.begin(), atom_vir_.end(), 0.0); + dp.compute(ener, force_, virial, atom_ener_, atom_vir_, coord_cpy2, atype_cpy, + box, nall - nloc, inlist, 1); + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + _fold_back(atom_ener, atom_ener_, mapping, nloc, nall, 1, nframes); + _fold_back(atom_vir, atom_vir_, mapping, nloc, nall, 9, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + EXPECT_EQ(atom_ener.size(), nframes * natoms); + EXPECT_EQ(atom_vir.size(), nframes * natoms * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms; ++ii) { + EXPECT_LT(fabs(atom_ener[ii] - expected_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 9; ++ii) { + EXPECT_LT(fabs(atom_vir[ii] - expected_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_lmp_nlist_2rc) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + float rc = dp.cutoff(); + std::vector coord_first(coord.begin(), coord.begin() + 3 * natoms); + std::vector box_first(box.begin(), box.begin() + 9); + int nloc = coord_first.size() / 3; + std::vector coord_cpy; + std::vector atype_cpy, mapping; + std::vector > nlist_data; + _build_nlist(nlist_data, coord_cpy, atype_cpy, mapping, + coord_first, atype, box_first, rc * 2); + int nall = coord_cpy.size() / 3; + std::vector ilist(nloc), numneigh(nloc); + std::vector firstneigh(nloc); + deepmd::hpp::InputNlist inlist(nloc, &ilist[0], &numneigh[0], &firstneigh[0]); + convert_nlist(inlist, nlist_data); + std::vector coord_cpy2(nframes * nall * 3); + for (int ii = 0; ii < nframes; ++ii) { + for (int jj = 0; jj < nall * 3; ++jj) { + coord_cpy2[ii * nall * 3 + jj] = coord_cpy[jj]; + } + } + + std::vector ener; + std::vector force_(nall * 3, 0.0), virial(nframes * 9, 0.0); + dp.compute(ener, force_, virial, coord_cpy2, atype_cpy, box, nall - nloc, + inlist, 0); + std::vector force; + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } + + std::fill(ener.begin(), ener.end(), 0.0); + std::fill(force_.begin(), force_.end(), 0.0); + std::fill(virial.begin(), virial.end(), 0.0); + dp.compute(ener, force_, virial, coord_cpy2, atype_cpy, box, nall - nloc, + inlist, 1); + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_lmp_nlist_type_sel) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + float rc = dp.cutoff(); + + // add vir atoms + int nvir = 2; + std::vector coord_vir(nvir * 3); + std::vector atype_vir(nvir, 2); + for (int ii = 0; ii < nvir; ++ii) { + coord_vir[ii] = coord[ii]; + } + coord.insert(coord.begin(), coord_vir.begin(), coord_vir.end()); + atype.insert(atype.begin(), atype_vir.begin(), atype_vir.end()); + natoms += nvir; + std::vector expected_f_vir(nvir * 3, 0.0); + // two frames + expected_f.insert(expected_f.begin(), expected_f_vir.begin(), + expected_f_vir.end()); + expected_f.insert(expected_f.begin() + natoms * 3, expected_f_vir.begin(), + expected_f_vir.end()); + std::vector coord_first(coord.begin(), coord.begin() + 3 * natoms); + std::vector box_first(box.begin(), box.begin() + 9); + + // build nlist + int nloc = coord_first.size() / 3; + std::vector coord_cpy; + std::vector atype_cpy, mapping; + std::vector > nlist_data; + _build_nlist(nlist_data, coord_cpy, atype_cpy, mapping, + coord_first, atype, box_first, rc); + int nall = coord_cpy.size() / 3; + std::vector ilist(nloc), numneigh(nloc); + std::vector firstneigh(nloc); + deepmd::hpp::InputNlist inlist(nloc, &ilist[0], &numneigh[0], &firstneigh[0]); + convert_nlist(inlist, nlist_data); + std::vector coord_cpy2(nframes * nall * 3); + for (int ii = 0; ii < nframes; ++ii) { + for (int jj = 0; jj < nall * 3; ++jj) { + coord_cpy2[ii * nall * 3 + jj] = coord_cpy[jj]; + } + } + + // dp compute + std::vector ener; + std::vector force_(nall * 3, 0.0), virial(nframes * 9, 0.0); + dp.compute(ener, force_, virial, coord_cpy2, atype_cpy, box, nall - nloc, + inlist, 0); + // fold back + std::vector force; + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} + +TYPED_TEST(TestInferDeepPotANFrames, cpu_lmp_nlist_type_sel_atomic) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + float rc = dp.cutoff(); + + // add vir atoms + int nvir = 2; + std::vector coord_vir(nvir * 3); + std::vector atype_vir(nvir, 2); + for (int ii = 0; ii < nvir; ++ii) { + coord_vir[ii] = coord[ii]; + } + coord.insert(coord.begin(), coord_vir.begin(), coord_vir.end()); + atype.insert(atype.begin(), atype_vir.begin(), atype_vir.end()); + natoms += nvir; + std::vector expected_f_vir(nvir * 3, 0.0); + // two frames + expected_f.insert(expected_f.begin(), expected_f_vir.begin(), + expected_f_vir.end()); + expected_f.insert(expected_f.begin() + natoms * 3, expected_f_vir.begin(), + expected_f_vir.end()); + std::vector coord_first(coord.begin(), coord.begin() + 3 * natoms); + std::vector box_first(box.begin(), box.begin() + 9); + + // build nlist + int nloc = coord_first.size() / 3; + std::vector coord_cpy; + std::vector atype_cpy, mapping; + std::vector > nlist_data; + _build_nlist(nlist_data, coord_cpy, atype_cpy, mapping, + coord_first, atype, box_first, rc); + int nall = coord_cpy.size() / 3; + std::vector ilist(nloc), numneigh(nloc); + std::vector firstneigh(nloc); + deepmd::hpp::InputNlist inlist(nloc, &ilist[0], &numneigh[0], &firstneigh[0]); + convert_nlist(inlist, nlist_data); + std::vector coord_cpy2(nframes * nall * 3); + for (int ii = 0; ii < nframes; ++ii) { + for (int jj = 0; jj < nall * 3; ++jj) { + coord_cpy2[ii * nall * 3 + jj] = coord_cpy[jj]; + } + } + + // dp compute + std::vector ener; + std::vector force_(nall * 3, 0.0), virial(nframes * 9, 0.0), + atomic_energy, atomic_virial; + dp.compute(ener, force_, virial, atomic_energy, atomic_virial, coord_cpy2, + atype_cpy, box, nall - nloc, inlist, 0); + // fold back + std::vector force; + _fold_back(force, force_, mapping, nloc, nall, 3, nframes); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} + +template +class TestInferDeepPotANFramesNoPbc : public ::testing::Test { + protected: + std::vector coord = { + 12.83, 2.56, 2.18, 12.09, 2.87, 2.74, 00.25, 3.32, 1.68, + 3.36, 3.00, 1.81, 3.51, 2.51, 2.60, 4.27, 3.22, 1.56, + 12.83, 2.56, 2.18, 12.09, 2.87, 2.74, 00.25, 3.32, 1.68, + 3.36, 3.00, 1.81, 3.51, 2.51, 2.60, 4.27, 3.22, 1.56}; + std::vector atype = {0, 1, 1, 0, 1, 1}; + std::vector box = {}; + std::vector expected_e = { + -9.255934839310273787e+01, -1.863253376736990106e+02, + -1.857237299341402945e+02, -9.279308539717486326e+01, + -1.863708105823244239e+02, -1.863635196514972563e+02, + -9.255934839310273787e+01, -1.863253376736990106e+02, + -1.857237299341402945e+02, -9.279308539717486326e+01, + -1.863708105823244239e+02, -1.863635196514972563e+02}; + std::vector expected_f = { + -2.161037360255332107e+00, 9.052994347015581589e-01, + 1.635379623977007979e+00, 2.161037360255332107e+00, + -9.052994347015581589e-01, -1.635379623977007979e+00, + -1.167128117249453811e-02, 1.371975700096064992e-03, + -1.575265180249604477e-03, 6.226508593971802341e-01, + -1.816734122009256991e-01, 3.561766019664774907e-01, + -1.406075393906316626e-02, 3.789140061530929526e-01, + -6.018777878642909140e-01, -5.969188242856223736e-01, + -1.986125696522633155e-01, 2.472764510780630642e-01, + -2.161037360255332107e+00, 9.052994347015581589e-01, + 1.635379623977007979e+00, 2.161037360255332107e+00, + -9.052994347015581589e-01, -1.635379623977007979e+00, + -1.167128117249453811e-02, 1.371975700096064992e-03, + -1.575265180249604477e-03, 6.226508593971802341e-01, + -1.816734122009256991e-01, 3.561766019664774907e-01, + -1.406075393906316626e-02, 3.789140061530929526e-01, + -6.018777878642909140e-01, -5.969188242856223736e-01, + -1.986125696522633155e-01, 2.472764510780630642e-01}; + std::vector expected_v = { + -7.042445481792056761e-01, 2.950213647777754078e-01, + 5.329418202437231633e-01, 2.950213647777752968e-01, + -1.235900311906896754e-01, -2.232594111831812944e-01, + 5.329418202437232743e-01, -2.232594111831813499e-01, + -4.033073234276823849e-01, -8.949230984097404917e-01, + 3.749002169013777030e-01, 6.772391014992630298e-01, + 3.749002169013777586e-01, -1.570527935667933583e-01, + -2.837082722496912512e-01, 6.772391014992631408e-01, + -2.837082722496912512e-01, -5.125052659994422388e-01, + 4.858210330291591605e-02, -6.902596153269104431e-03, + 6.682612642430500391e-03, -5.612247004554610057e-03, + 9.767795567660207592e-04, -9.773758942738038254e-04, + 5.638322117219018645e-03, -9.483806049779926932e-04, + 8.493873281881353637e-04, -2.941738570564985666e-01, + -4.482529909499673171e-02, 4.091569840186781021e-02, + -4.509020615859140463e-02, -1.013919988807244071e-01, + 1.551440772665269030e-01, 4.181857726606644232e-02, + 1.547200233064863484e-01, -2.398213304685777592e-01, + -3.218625798524068354e-02, -1.012438450438508421e-02, + 1.271639330380921855e-02, 3.072814938490859779e-03, + -9.556241797915024372e-02, 1.512251983492413077e-01, + -8.277872384009607454e-03, 1.505412040827929787e-01, + -2.386150620881526407e-01, -2.312295470054945568e-01, + -6.631490213524345034e-02, 7.932427266386249398e-02, + -8.053754366323923053e-02, -3.294595881137418747e-02, + 4.342495071150231922e-02, 1.004599500126941436e-01, + 4.450400364869536163e-02, -5.951077548033092968e-02, + -7.042445481792056761e-01, 2.950213647777754078e-01, + 5.329418202437231633e-01, 2.950213647777752968e-01, + -1.235900311906896754e-01, -2.232594111831812944e-01, + 5.329418202437232743e-01, -2.232594111831813499e-01, + -4.033073234276823849e-01, -8.949230984097404917e-01, + 3.749002169013777030e-01, 6.772391014992630298e-01, + 3.749002169013777586e-01, -1.570527935667933583e-01, + -2.837082722496912512e-01, 6.772391014992631408e-01, + -2.837082722496912512e-01, -5.125052659994422388e-01, + 4.858210330291591605e-02, -6.902596153269104431e-03, + 6.682612642430500391e-03, -5.612247004554610057e-03, + 9.767795567660207592e-04, -9.773758942738038254e-04, + 5.638322117219018645e-03, -9.483806049779926932e-04, + 8.493873281881353637e-04, -2.941738570564985666e-01, + -4.482529909499673171e-02, 4.091569840186781021e-02, + -4.509020615859140463e-02, -1.013919988807244071e-01, + 1.551440772665269030e-01, 4.181857726606644232e-02, + 1.547200233064863484e-01, -2.398213304685777592e-01, + -3.218625798524068354e-02, -1.012438450438508421e-02, + 1.271639330380921855e-02, 3.072814938490859779e-03, + -9.556241797915024372e-02, 1.512251983492413077e-01, + -8.277872384009607454e-03, 1.505412040827929787e-01, + -2.386150620881526407e-01, -2.312295470054945568e-01, + -6.631490213524345034e-02, 7.932427266386249398e-02, + -8.053754366323923053e-02, -3.294595881137418747e-02, + 4.342495071150231922e-02, 1.004599500126941436e-01, + 4.450400364869536163e-02, -5.951077548033092968e-02}; + int natoms; + int nframes = 2; + std::vector expected_tot_e; + std::vector expected_tot_v; + + deepmd::hpp::DeepPot dp; + + void SetUp() override { + std::string file_name = "../../tests/infer/deeppot.pbtxt"; + deepmd::hpp::convert_pbtxt_to_pb(file_name, "deeppot.pb"); + + dp.init("deeppot.pb"); + + natoms = expected_e.size() / nframes; + EXPECT_EQ(nframes * natoms * 3, expected_f.size()); + EXPECT_EQ(nframes * natoms * 9, expected_v.size()); + expected_tot_e.resize(nframes); + expected_tot_v.resize(nframes * 9); + std::fill(expected_tot_e.begin(), expected_tot_e.end(), 0.); + std::fill(expected_tot_v.begin(), expected_tot_v.end(), 0.); + for (int kk = 0; kk < nframes; ++kk) { + for (int ii = 0; ii < natoms; ++ii) { + expected_tot_e[kk] += expected_e[kk * natoms + ii]; + } + for (int ii = 0; ii < natoms; ++ii) { + for (int dd = 0; dd < 9; ++dd) { + expected_tot_v[kk * 9 + dd] += + expected_v[kk * natoms * 9 + ii * 9 + dd]; + } + } + } + }; + + void TearDown() override { remove("deeppot.pb"); }; +}; + +TYPED_TEST_SUITE(TestInferDeepPotANFramesNoPbc, ValueTypes); + +TYPED_TEST(TestInferDeepPotANFramesNoPbc, cpu_build_nlist) { + using VALUETYPE = TypeParam; + std::vector& coord = this->coord; + std::vector& atype = this->atype; + std::vector& box = this->box; + std::vector& expected_e = this->expected_e; + std::vector& expected_f = this->expected_f; + std::vector& expected_v = this->expected_v; + int& natoms = this->natoms; + int& nframes = this->nframes; + std::vector& expected_tot_e = this->expected_tot_e; + std::vector& expected_tot_v = this->expected_tot_v; + deepmd::hpp::DeepPot& dp = this->dp; + std::vector ener; + std::vector force, virial; + dp.compute(ener, force, virial, coord, atype, box); + + EXPECT_EQ(ener.size(), nframes); + EXPECT_EQ(force.size(), nframes * natoms * 3); + EXPECT_EQ(virial.size(), nframes * 9); + + for (int ii = 0; ii < nframes; ++ii) { + EXPECT_LT(fabs(ener[ii] - expected_tot_e[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * natoms * 3; ++ii) { + EXPECT_LT(fabs(force[ii] - expected_f[ii]), EPSILON); + } + for (int ii = 0; ii < nframes * 3 * 3; ++ii) { + EXPECT_LT(fabs(virial[ii] - expected_tot_v[ii]), EPSILON); + } +} diff --git a/source/api_c/tests/test_utils.h b/source/api_c/tests/test_utils.h index 45d4f3e515..647341c2f9 100644 --- a/source/api_c/tests/test_utils.h +++ b/source/api_c/tests/test_utils.h @@ -16,14 +16,19 @@ inline void _fold_back(typename std::vector::iterator out, const std::vector &mapping, const int nloc, const int nall, - const int ndim) { + const int ndim, + const int nframes = 1) { // out.resize(nloc*ndim); - std::copy(in, in + nloc * ndim, out); - for (int ii = nloc; ii < nall; ++ii) { - int in_idx = ii; - int out_idx = mapping[in_idx]; - for (int dd = 0; dd < ndim; ++dd) { - *(out + out_idx * ndim + dd) += *(in + in_idx * ndim + dd); + for (int kk = 0; kk < nframes; ++kk) { + std::copy(in + kk * nall * ndim, in + kk * nall * ndim + nloc * ndim, + out + kk * nloc * ndim); + for (int ii = nloc; ii < nall; ++ii) { + int in_idx = ii; + int out_idx = mapping[in_idx]; + for (int dd = 0; dd < ndim; ++dd) { + *(out + kk * nloc * ndim + out_idx * ndim + dd) += + *(in + kk * nall * ndim + in_idx * ndim + dd); + } } } } @@ -34,9 +39,11 @@ inline void _fold_back(std::vector &out, const std::vector &mapping, const int nloc, const int nall, - const int ndim) { - out.resize(nloc * ndim); - _fold_back(out.begin(), in.begin(), mapping, nloc, nall, ndim); + const int ndim, + const int nframes = 1) { + out.resize(nframes * nloc * ndim); + _fold_back(out.begin(), in.begin(), mapping, nloc, nall, ndim, + nframes); } template