diff --git a/source/api_c/include/c_api.h b/source/api_c/include/c_api.h index 7823fe70e0..0d8a4b2c39 100644 --- a/source/api_c/include/c_api.h +++ b/source/api_c/include/c_api.h @@ -21,6 +21,14 @@ extern DP_Nlist* DP_NewNlist(int inum_, int* numneigh_, int** firstneigh_); +/** + * @brief Check if there is any exceptions throw. + * + * @param dp The neighbor list to use. + * @return const char* error message. + */ +const char* DP_NlistCheckOK(DP_Nlist* dp); + /** * @brief The deep potential. **/ @@ -446,6 +454,14 @@ double DP_DeepPotModelDeviGetCutoff(DP_DeepPotModelDevi* dp); */ int DP_DeepPotModelDeviGetNumbTypes(DP_DeepPotModelDevi* dp); +/** + * @brief Check if there is any exceptions throw. + * + * @param dp The DP model deviation to use. + * @return const char* error message. + */ +const char* DP_DeepPotModelDeviCheckOK(DP_DeepPotModelDevi* dp); + /** * @brief Get the type map of a DP. * @param[in] dp The DP to use. @@ -472,6 +488,14 @@ const char* DP_DeepPotGetTypeMap(DP_DeepPot* dp); **/ typedef struct DP_DeepTensor DP_DeepTensor; +/** + * @brief Check if there is any exceptions throw. + * + * @param dp The DP to use. + * @return const char* error message. + */ +const char* DP_DeepPotCheckOK(DP_DeepPot* dp); + /** * @brief Deep Tensor constructor with initialization. * @param[in] c_model The name of the frozen model file. @@ -755,6 +779,14 @@ int* DP_DeepTensorGetSelTypes(DP_DeepTensor* dt); */ int DP_DeepTensorGetNumbSelTypes(DP_DeepTensor* dt); +/** + * @brief Check if there is any exceptions throw. + * + * @param dt The Deep Tensor to use. + * @return const char* error message. + */ +const char* DP_DeepTensorCheckOK(DP_DeepTensor* dt); + /** * @brief The dipole charge modifier. **/ @@ -878,6 +910,14 @@ int* DP_DipoleChargeModifierGetSelTypes(DP_DipoleChargeModifier* dt); */ int DP_DipoleChargeModifierGetNumbSelTypes(DP_DipoleChargeModifier* dt); +/** + * @brief Check if there is any exceptions throw. + * + * @param dcm The DipoleChargeModifier to use. + * @return const char* error message. + */ +const char* DP_DipoleChargeModifierCheckOK(DP_DipoleChargeModifier* dcm); + /** * @brief Convert PBtxt to PB. * @param[in] c_pbtxt The name of the PBtxt file. diff --git a/source/api_c/include/c_api_internal.h b/source/api_c/include/c_api_internal.h index d0c9f59fcc..741f1e88e3 100644 --- a/source/api_c/include/c_api_internal.h +++ b/source/api_c/include/c_api_internal.h @@ -1,34 +1,65 @@ +#include + #include "DataModifier.h" #include "DeepPot.h" #include "DeepTensor.h" #include "neighbor_list.h" +// catch deepmd::deepmd_exception and store it in dp->exception +// return nothing +#define DP_REQUIRES_OK(dp, xx) \ + try { \ + xx; \ + } catch (deepmd::deepmd_exception & ex) { \ + dp->exception = std::string(ex.what()); \ + return; \ + } + +#define DP_NEW_OK(dpcls, xx) \ + try { \ + xx; \ + } catch (deepmd::deepmd_exception & ex) { \ + dpcls* _new_dp = new dpcls; \ + _new_dp->exception = std::string(ex.what()); \ + return _new_dp; \ + } + struct DP_Nlist { + DP_Nlist(); DP_Nlist(deepmd::InputNlist& nl); deepmd::InputNlist nl; + std::string exception; }; struct DP_DeepPot { + DP_DeepPot(); DP_DeepPot(deepmd::DeepPot& dp); deepmd::DeepPot dp; + std::string exception; }; struct DP_DeepPotModelDevi { + DP_DeepPotModelDevi(); DP_DeepPotModelDevi(deepmd::DeepPotModelDevi& dp); deepmd::DeepPotModelDevi dp; + std::string exception; }; struct DP_DeepTensor { + DP_DeepTensor(); DP_DeepTensor(deepmd::DeepTensor& dt); deepmd::DeepTensor dt; + std::string exception; }; struct DP_DipoleChargeModifier { + DP_DipoleChargeModifier(); DP_DipoleChargeModifier(deepmd::DipoleChargeModifier& dcm); deepmd::DipoleChargeModifier dcm; + std::string exception; }; diff --git a/source/api_c/include/deepmd.hpp b/source/api_c/include/deepmd.hpp index 2122125f52..3bb81078c1 100644 --- a/source/api_c/include/deepmd.hpp +++ b/source/api_c/include/deepmd.hpp @@ -8,12 +8,35 @@ This header-only library provides a C++ 11 interface to the DeePMD-kit C API. #include #include +#include #include #include #include #include "c_api.h" +namespace deepmd { +namespace hpp { +/** + * @brief General DeePMD-kit exception. Throw if anything doesn't work. + **/ +struct deepmd_exception : public std::runtime_error { + public: + deepmd_exception() : runtime_error("DeePMD-kit C API Error!"){}; + deepmd_exception(const std::string &msg) + : runtime_error(std::string("DeePMD-kit C API Error: ") + msg){}; +}; +} // namespace hpp +} // namespace deepmd + +/** + * @brief Check if any exceptions throw in the C++ API. Throw if possible. + */ +#define DP_CHECK_OK(check_func, dp) \ + const char *err_msg = check_func(dp); \ + if (strlen(err_msg)) \ + throw deepmd::hpp::deepmd_exception(std::string(err_msg)); + template inline void _DP_DeepPotCompute(DP_DeepPot *dp, const int nframes, @@ -422,13 +445,17 @@ struct InputNlist { ilist(nullptr), numneigh(nullptr), firstneigh(nullptr), - nl(DP_NewNlist(0, nullptr, nullptr, nullptr)){}; + nl(DP_NewNlist(0, nullptr, nullptr, nullptr)) { + DP_CHECK_OK(DP_NlistCheckOK, nl); + }; InputNlist(int inum_, int *ilist_, int *numneigh_, int **firstneigh_) : inum(inum_), ilist(ilist_), numneigh(numneigh_), firstneigh(firstneigh_), - nl(DP_NewNlist(inum_, ilist_, numneigh_, firstneigh_)){}; + nl(DP_NewNlist(inum_, ilist_, numneigh_, firstneigh_)) { + DP_CHECK_OK(DP_NlistCheckOK, nl); + }; /// @brief C API neighbor list. DP_Nlist *nl; /// @brief Number of core region atoms @@ -504,6 +531,7 @@ class DeepPot { return; } dp = DP_NewDeepPotWithParam(model.c_str(), gpu_rank, file_content.c_str()); + DP_CHECK_OK(DP_DeepPotCheckOK, dp); }; /** @@ -542,6 +570,7 @@ class DeepPot { _DP_DeepPotCompute(dp, nframes, natoms, coord_, atype_, box_, nullptr, nullptr, ener_, force_, virial_, nullptr, nullptr); + DP_CHECK_OK(DP_DeepPotCheckOK, dp); }; /** * @brief Evaluate the energy, force, virial, atomic energy, and atomic virial @@ -589,6 +618,7 @@ class DeepPot { _DP_DeepPotCompute(dp, nframes, natoms, coord_, atype_, box_, nullptr, nullptr, ener_, force_, virial_, atomic_ener_, atomic_virial_); + DP_CHECK_OK(DP_DeepPotCheckOK, dp); }; /** @@ -634,6 +664,7 @@ class DeepPot { _DP_DeepPotComputeNList( dp, nframes, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, nullptr, nullptr, ener_, force_, virial_, nullptr, nullptr); + DP_CHECK_OK(DP_DeepPotCheckOK, dp); }; /** * @brief Evaluate the energy, force, virial, atomic energy, and atomic virial @@ -687,6 +718,7 @@ class DeepPot { _DP_DeepPotComputeNList( dp, nframes, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, nullptr, nullptr, ener_, force_, virial_, atomic_ener_, atomic_virial_); + DP_CHECK_OK(DP_DeepPotCheckOK, dp); }; /** * @brief Get the cutoff radius. @@ -759,6 +791,7 @@ class DeepPotModelDevi { for (std::string const &str : models) cstrings.push_back(str.data()); dp = DP_NewDeepPotModelDevi(cstrings.data(), cstrings.size()); + DP_CHECK_OK(DP_DeepPotModelDeviCheckOK, dp); numb_models = models.size(); }; @@ -804,6 +837,7 @@ class DeepPotModelDevi { _DP_DeepPotModelDeviComputeNList( dp, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, ener_, force_, virial_, nullptr, nullptr); + DP_CHECK_OK(DP_DeepPotModelDeviCheckOK, dp); // reshape ener.resize(numb_models); @@ -867,6 +901,7 @@ class DeepPotModelDevi { _DP_DeepPotModelDeviComputeNList( dp, natoms, coord_, atype_, box_, nghost, lmp_list.nl, ago, ener_, force_, virial_, atomic_ener_, atomic_virial_); + DP_CHECK_OK(DP_DeepPotModelDeviCheckOK, dp); // reshape ener.resize(numb_models); @@ -945,6 +980,7 @@ class DeepTensor { return; } dt = DP_NewDeepTensorWithParam(model.c_str(), gpu_rank, name_scope.c_str()); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); odim = output_dim(); nsel_types = DP_DeepTensorGetNumbSelTypes(dt); }; @@ -979,6 +1015,7 @@ class DeepTensor { _DP_DeepTensorComputeTensor(dt, natoms, coord_, atype_, box_, p_tensor, p_size); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); tensor.resize(size); std::copy(tensor_, tensor_ + size, tensor.begin()); @@ -1021,6 +1058,7 @@ class DeepTensor { _DP_DeepTensorComputeTensorNList(dt, natoms, coord_, atype_, box_, nghost, lmp_list.nl, p_tensor, p_size); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); tensor.resize(size); std::copy(tensor_, tensor_ + size, tensor.begin()); @@ -1064,6 +1102,7 @@ class DeepTensor { _DP_DeepTensorCompute(dt, natoms, coord_, atype_, box_, global_tensor_, force_, virial_, nullptr, nullptr, nullptr); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); }; /** * @brief Evaluate the global tensor, force, virial, atomic tensor, and atomic @@ -1114,6 +1153,7 @@ class DeepTensor { _DP_DeepTensorCompute( dt, natoms, coord_, atype_, box_, global_tensor_, force_, virial_, p_atomic_tensor, atomic_virial_, p_size_at); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); atom_tensor.resize(size_at); std::copy(atomic_tensor_, atomic_tensor_ + size_at, atom_tensor.begin()); @@ -1161,6 +1201,7 @@ class DeepTensor { _DP_DeepTensorComputeNList( dt, natoms, coord_, atype_, box_, nghost, lmp_list.nl, global_tensor_, force_, virial_, nullptr, nullptr, nullptr); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); }; /** * @brief Evaluate the global tensor, force, virial, atomic tensor, and atomic @@ -1215,6 +1256,7 @@ class DeepTensor { _DP_DeepTensorComputeNList( dt, natoms, coord_, atype_, box_, nghost, lmp_list.nl, global_tensor_, force_, virial_, p_atomic_tensor, atomic_virial_, p_size_at); + DP_CHECK_OK(DP_DeepTensorCheckOK, dt); atom_tensor.resize(size_at); std::copy(atomic_tensor_, atomic_tensor_ + size_at, atom_tensor.begin()); @@ -1302,6 +1344,7 @@ class DipoleChargeModifier { } dcm = DP_NewDipoleChargeModifierWithParam(model.c_str(), gpu_rank, name_scope.c_str()); + DP_CHECK_OK(DP_DipoleChargeModifierCheckOK, dcm); nsel_types = DP_DipoleChargeModifierGetNumbSelTypes(dcm); }; /** @@ -1350,6 +1393,7 @@ class DipoleChargeModifier { _DP_DipoleChargeModifierComputeNList( dcm, natoms, dcoord, datype, dbox_, dpairs, npairs, delef, nghost, lmp_list.nl, dfcorr, dvcorr); + DP_CHECK_OK(DP_DipoleChargeModifierCheckOK, dcm); }; /** * @brief Get the cutoff radius. diff --git a/source/api_c/src/c_api.cc b/source/api_c/src/c_api.cc index ae4171746f..fbac3baa5c 100644 --- a/source/api_c/src/c_api.cc +++ b/source/api_c/src/c_api.cc @@ -12,17 +12,19 @@ extern "C" { +DP_Nlist::DP_Nlist() {} DP_Nlist::DP_Nlist(deepmd::InputNlist& nl) : nl(nl) {} DP_Nlist* DP_NewNlist(int inum_, int* ilist_, int* numneigh_, int** firstneigh_) { - deepmd::InputNlist nl(inum_, ilist_, numneigh_, firstneigh_); - DP_Nlist* new_nl = new DP_Nlist(nl); - return new_nl; + DP_NEW_OK(DP_Nlist, + deepmd::InputNlist nl(inum_, ilist_, numneigh_, firstneigh_); + DP_Nlist* new_nl = new DP_Nlist(nl); return new_nl;) } +DP_DeepPot::DP_DeepPot() {} DP_DeepPot::DP_DeepPot(deepmd::DeepPot& dp) : dp(dp) {} DP_DeepPot* DP_NewDeepPot(const char* c_model) { @@ -37,29 +39,29 @@ DP_DeepPot* DP_NewDeepPotWithParam(const char* c_model, const char* c_file_content) { std::string model(c_model); std::string file_content(c_file_content); - deepmd::DeepPot dp(model, gpu_rank, file_content); - DP_DeepPot* new_dp = new DP_DeepPot(dp); - return new_dp; + DP_NEW_OK(DP_DeepPot, deepmd::DeepPot dp(model, gpu_rank, file_content); + DP_DeepPot* new_dp = new DP_DeepPot(dp); return new_dp;) } +DP_DeepPotModelDevi::DP_DeepPotModelDevi() {} DP_DeepPotModelDevi::DP_DeepPotModelDevi(deepmd::DeepPotModelDevi& dp) : dp(dp) {} DP_DeepPotModelDevi* DP_NewDeepPotModelDevi(const char** c_models, int n_models) { std::vector model(c_models, c_models + n_models); - deepmd::DeepPotModelDevi dp(model); - DP_DeepPotModelDevi* new_dp = new DP_DeepPotModelDevi(dp); - return new_dp; + DP_NEW_OK(DP_DeepPotModelDevi, deepmd::DeepPotModelDevi dp(model); + DP_DeepPotModelDevi* new_dp = new DP_DeepPotModelDevi(dp); + return new_dp;) } +DP_DeepTensor::DP_DeepTensor() {} DP_DeepTensor::DP_DeepTensor(deepmd::DeepTensor& dt) : dt(dt) {} DP_DeepTensor* DP_NewDeepTensor(const char* c_model) { std::string model(c_model); - deepmd::DeepTensor dt(model); - DP_DeepTensor* new_dt = new DP_DeepTensor(dt); - return new_dt; + DP_NEW_OK(DP_DeepTensor, deepmd::DeepTensor dt(model); + DP_DeepTensor* new_dt = new DP_DeepTensor(dt); return new_dt;) } DP_DeepTensor* DP_NewDeepTensorWithParam(const char* c_model, @@ -67,29 +69,30 @@ DP_DeepTensor* DP_NewDeepTensorWithParam(const char* c_model, const char* c_name_scope) { std::string model(c_model); std::string name_scope(c_name_scope); - deepmd::DeepTensor dt(model, gpu_rank, name_scope); - DP_DeepTensor* new_dt = new DP_DeepTensor(dt); - return new_dt; + DP_NEW_OK(DP_DeepTensor, deepmd::DeepTensor dt(model, gpu_rank, name_scope); + DP_DeepTensor* new_dt = new DP_DeepTensor(dt); return new_dt;) } +DP_DipoleChargeModifier::DP_DipoleChargeModifier() {} DP_DipoleChargeModifier::DP_DipoleChargeModifier( deepmd::DipoleChargeModifier& dcm) : dcm(dcm) {} DP_DipoleChargeModifier* DP_NewDipoleChargeModifier(const char* c_model) { std::string model(c_model); - deepmd::DipoleChargeModifier dcm(model); - DP_DipoleChargeModifier* new_dcm = new DP_DipoleChargeModifier(dcm); - return new_dcm; + DP_NEW_OK(DP_DipoleChargeModifier, deepmd::DipoleChargeModifier dcm(model); + DP_DipoleChargeModifier* new_dcm = new DP_DipoleChargeModifier(dcm); + return new_dcm;) } DP_DipoleChargeModifier* DP_NewDipoleChargeModifierWithParam( const char* c_model, const int gpu_rank, const char* c_name_scope) { std::string model(c_model); std::string name_scope(c_name_scope); - deepmd::DipoleChargeModifier dcm(model, gpu_rank, name_scope); - DP_DipoleChargeModifier* new_dcm = new DP_DipoleChargeModifier(dcm); - return new_dcm; + DP_NEW_OK(DP_DipoleChargeModifier, + deepmd::DipoleChargeModifier dcm(model, gpu_rank, name_scope); + DP_DipoleChargeModifier* new_dcm = new DP_DipoleChargeModifier(dcm); + return new_dcm;) } } // extern "C" @@ -119,7 +122,7 @@ inline void DP_DeepPotCompute_variant(DP_DeepPot* dp, std::vector e; std::vector f, v, ae, av; - dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_); + DP_REQUIRES_OK(dp, dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_)); // copy from C++ vectors to C arrays, if not NULL pointer if (energy) std::copy(e.begin(), e.end(), energy); if (force) std::copy(f.begin(), f.end(), force); @@ -184,8 +187,8 @@ inline void DP_DeepPotComputeNList_variant(DP_DeepPot* dp, std::vector e; std::vector f, v, ae, av; - dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_, nghost, nlist->nl, - ago); + DP_REQUIRES_OK(dp, 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) std::copy(e.begin(), e.end(), energy); if (force) std::copy(f.begin(), f.end(), force); @@ -263,8 +266,8 @@ void DP_DeepPotModelDeviComputeNList_variant(DP_DeepPotModelDevi* dp, std::vector e; std::vector> f, v, ae, av; - dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_, nghost, nlist->nl, - ago); + DP_REQUIRES_OK(dp, dp->dp.compute(e, f, v, ae, av, coord_, atype_, cell_, + nghost, nlist->nl, ago)); // 2D vector to 2D array, flatten first if (energy) { std::copy(e.begin(), e.end(), energy); @@ -339,7 +342,7 @@ inline void DP_DeepTensorComputeTensor_variant(DP_DeepTensor* dt, } std::vector t; - dt->dt.compute(t, coord_, atype_, cell_); + DP_REQUIRES_OK(dt, dt->dt.compute(t, coord_, atype_, cell_)); // do not know the size of tensor in advance... *tensor = new VALUETYPE[t.size()]; std::copy(t.begin(), t.end(), *tensor); @@ -382,7 +385,8 @@ inline void DP_DeepTensorComputeTensorNList_variant(DP_DeepTensor* dt, } std::vector t; - dt->dt.compute(t, coord_, atype_, cell_, nghost, nlist->nl); + DP_REQUIRES_OK(dt, + dt->dt.compute(t, coord_, atype_, cell_, nghost, nlist->nl)); // do not know the size of tensor in advance... *tensor = new VALUETYPE[t.size()]; std::copy(t.begin(), t.end(), *tensor); @@ -433,7 +437,7 @@ inline void DP_DeepTensorCompute_variant(DP_DeepTensor* dt, } std::vector t, f, v, at, av; - dt->dt.compute(t, f, v, at, av, coord_, atype_, cell_); + DP_REQUIRES_OK(dt, dt->dt.compute(t, f, v, at, av, coord_, atype_, cell_)); // copy from C++ vectors to C arrays, if not NULL pointer if (global_tensor) std::copy(t.begin(), t.end(), global_tensor); if (force) std::copy(f.begin(), f.end(), force); @@ -495,7 +499,8 @@ inline void DP_DeepTensorComputeNList_variant(DP_DeepTensor* dt, } std::vector t, f, v, at, av; - dt->dt.compute(t, f, v, at, av, coord_, atype_, cell_, nghost, nlist->nl); + DP_REQUIRES_OK(dt, dt->dt.compute(t, f, v, at, av, coord_, atype_, cell_, + nghost, nlist->nl)); // copy from C++ vectors to C arrays, if not NULL pointer if (global_tensor) std::copy(t.begin(), t.end(), global_tensor); if (force) std::copy(f.begin(), f.end(), force); @@ -567,8 +572,8 @@ inline void DP_DipoleChargeModifierComputeNList_variant( std::vector delef_(delef, delef + natoms * 3); std::vector df, dv; - dcm->dcm.compute(df, dv, coord_, atype_, cell_, pairs_, delef_, nghost, - nlist->nl); + DP_REQUIRES_OK(dcm, dcm->dcm.compute(df, dv, coord_, atype_, cell_, pairs_, + delef_, nghost, nlist->nl)); // copy from C++ vectors to C arrays, if not NULL pointer if (dfcorr_) std::copy(df.begin(), df.end(), dfcorr_); if (dvcorr_) std::copy(dv.begin(), dv.end(), dvcorr_); @@ -602,8 +607,27 @@ template void DP_DipoleChargeModifierComputeNList_variant( float* dfcorr_, float* dvcorr_); +/** + * @brief Convert std::string to const char + * @param[in] str std::string to be converted + * @return const char* + */ +const char* string_to_char(std::string& str) { + // copy from string to char* + const std::string::size_type size = str.size(); + // +1 for '\0' + char* buffer = new char[size + 1]; + std::copy(str.begin(), str.end(), buffer); + buffer[size] = '\0'; + return buffer; +} + extern "C" { +const char* DP_NlistCheckOK(DP_Nlist* nlist) { + return string_to_char(nlist->exception); +} + void DP_DeepPotCompute(DP_DeepPot* dp, const int natoms, const double* coord, @@ -753,19 +777,17 @@ void DP_DeepPotComputeNListf2(DP_DeepPot* dp, const char* DP_DeepPotGetTypeMap(DP_DeepPot* dp) { std::string type_map; dp->dp.get_type_map(type_map); - // copy from string to char* - const std::string::size_type size = type_map.size(); - // +1 for '\0' - char* buffer = new char[size + 1]; - std::copy(type_map.begin(), type_map.end(), buffer); - buffer[size] = '\0'; - return buffer; + return string_to_char(type_map); } double DP_DeepPotGetCutoff(DP_DeepPot* dp) { return dp->dp.cutoff(); } int DP_DeepPotGetNumbTypes(DP_DeepPot* dp) { return dp->dp.numb_types(); } +const char* DP_DeepPotCheckOK(DP_DeepPot* dp) { + return string_to_char(dp->exception); +} + void DP_DeepPotModelDeviComputeNList(DP_DeepPotModelDevi* dp, const int natoms, const double* coord, @@ -810,6 +832,10 @@ int DP_DeepPotModelDeviGetNumbTypes(DP_DeepPotModelDevi* dp) { return dp->dp.numb_types(); } +const char* DP_DeepPotModelDeviCheckOK(DP_DeepPotModelDevi* dp) { + return string_to_char(dp->exception); +} + void DP_DeepTensorComputeTensor(DP_DeepTensor* dt, const int natoms, const double* coord, @@ -940,6 +966,10 @@ int DP_DeepTensorGetNumbSelTypes(DP_DeepTensor* dt) { return dt->dt.sel_types().size(); } +const char* DP_DeepTensorCheckOK(DP_DeepTensor* dt) { + return string_to_char(dt->exception); +} + void DP_DipoleChargeModifierComputeNList(DP_DipoleChargeModifier* dcm, const int natom, const double* coord, @@ -990,6 +1020,10 @@ int DP_DipoleChargeModifierGetNumbSelTypes(DP_DipoleChargeModifier* dcm) { return dcm->dcm.sel_types().size(); } +const char* DP_DipoleChargeModifierCheckOK(DP_DipoleChargeModifier* dcm) { + return string_to_char(dcm->exception); +} + void DP_ConvertPbtxtToPb(const char* c_pbtxt, const char* c_pb) { std::string pbtxt(c_pbtxt); std::string pb(c_pb); diff --git a/source/api_c/tests/test_deepmd_exception.cc b/source/api_c/tests/test_deepmd_exception.cc new file mode 100644 index 0000000000..9968c640a3 --- /dev/null +++ b/source/api_c/tests/test_deepmd_exception.cc @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "deepmd.hpp" + +TEST(TestDeepmdException, deepmdexception) { + std::string expected_error_message = "DeePMD-kit C API Error: unittest"; + try { + throw deepmd::hpp::deepmd_exception("unittest"); + } catch (deepmd::hpp::deepmd_exception &ex) { + EXPECT_STREQ(expected_error_message.c_str(), ex.what()); + } +} + +TEST(TestDeepmdException, deepmdexception_nofile) { + ASSERT_THROW(deepmd::hpp::DeepPot("_no_such_file.pb"), + deepmd::hpp::deepmd_exception); +} diff --git a/source/api_cc/tests/test_deepmd_exception.cc b/source/api_cc/tests/test_deepmd_exception.cc index dd2c812685..e13e2c4672 100644 --- a/source/api_cc/tests/test_deepmd_exception.cc +++ b/source/api_cc/tests/test_deepmd_exception.cc @@ -9,6 +9,7 @@ #include #include +#include "DeepPot.h" #include "errors.h" TEST(TestDeepmdException, deepmdexception) { std::string expected_error_message = "DeePMD-kit Error: unittest"; @@ -18,3 +19,7 @@ TEST(TestDeepmdException, deepmdexception) { EXPECT_STREQ(expected_error_message.c_str(), ex.what()); } } + +TEST(TestDeepmdException, deepmdexception_nofile) { + ASSERT_THROW(deepmd::DeepPot("_no_such_file.pb"), deepmd::deepmd_exception); +}