diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 23076e9bf5..2f6d2c4ab2 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -41,12 +41,12 @@ jobs: cuda_version: 11.8 dp_pkg_name: deepmd-kit-cu11 # macos-x86-64 - - os: macos-latest + - os: macos-13 python: 311 platform_id: macosx_x86_64 dp_variant: cpu # macos-arm64 - - os: macos-latest + - os: macos-14 python: 311 platform_id: macosx_arm64 dp_variant: cpu diff --git a/.github/workflows/test_cc.yml b/.github/workflows/test_cc.yml index ef6fade8e5..6e12d7880b 100644 --- a/.github/workflows/test_cc.yml +++ b/.github/workflows/test_cc.yml @@ -6,6 +6,9 @@ jobs: testcc: name: Test C++ runs-on: ubuntu-latest + strategy: + matrix: + check_memleak: [true, false] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -25,6 +28,7 @@ jobs: TF_INTER_OP_PARALLELISM_THREADS: 1 LMP_CXX11_ABI_0: 1 CMAKE_GENERATOR: Ninja + CXXFLAGS: ${{ matrix.check_memleak && '-fsanitize=leak' || '' }} # test lammps # ASE issue: https://gitlab.com/ase/ase/-/merge_requests/2843 # TODO: remove ase version when ase has new release @@ -33,6 +37,7 @@ jobs: python -m pip install -e .[cpu,test,lmp] "ase @ https://gitlab.com/ase/ase/-/archive/8c5aa5fd6448c5cfb517a014dccf2b214a9dfa8f/ase-8c5aa5fd6448c5cfb517a014dccf2b214a9dfa8f.tar.gz" env: DP_BUILD_TESTING: 1 + if: ${{ !matrix.check_memleak }} - run: pytest --cov=deepmd source/lmp/tests env: OMP_NUM_THREADS: 1 @@ -40,6 +45,7 @@ jobs: TF_INTER_OP_PARALLELISM_THREADS: 1 LAMMPS_PLUGIN_PATH: ${{ github.workspace }}/dp_test/lib/deepmd_lmp LD_LIBRARY_PATH: ${{ github.workspace }}/dp_test/lib + if: ${{ !matrix.check_memleak }} # test ipi - run: pytest --cov=deepmd source/ipi/tests env: @@ -48,6 +54,7 @@ jobs: TF_INTER_OP_PARALLELISM_THREADS: 1 PATH: ${{ github.workspace }}/dp_test/bin:$PATH LD_LIBRARY_PATH: ${{ github.workspace }}/dp_test/lib + if: ${{ !matrix.check_memleak }} - uses: codecov/codecov-action@v3 with: gcov: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d4e89f1129..0fd2d1b40f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: exclude: ^source/3rdparty - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.1.13 + rev: v0.1.14 hooks: - id: ruff args: ["--fix"] diff --git a/backend/find_tensorflow.py b/backend/find_tensorflow.py index 08a73f7252..b7f17ed299 100644 --- a/backend/find_tensorflow.py +++ b/backend/find_tensorflow.py @@ -50,12 +50,6 @@ def find_tensorflow() -> Tuple[Optional[str], List[str]]: requires = [] tf_spec = None - if os.environ.get("CIBUILDWHEEL", "0") == "1" and os.environ.get( - "CIBW_BUILD", "" - ).endswith("macosx_arm64"): - # cibuildwheel cross build - site_packages = Path(os.environ.get("RUNNER_TEMP")) / "tensorflow" - tf_spec = FileFinder(str(site_packages)).find_spec("tensorflow") if (tf_spec is None or not tf_spec) and os.environ.get( "TENSORFLOW_ROOT" diff --git a/doc/inference/cxx.md b/doc/inference/cxx.md index 6188daba4c..cc7e7be540 100644 --- a/doc/inference/cxx.md +++ b/doc/inference/cxx.md @@ -62,7 +62,7 @@ int main(){ free(v); free(ae); free(av); - free(dp); + DP_DeleteDeepPot(dp); } ``` diff --git a/examples/infer_water/infer_water.c b/examples/infer_water/infer_water.c index f4eeae147f..cf13f45e3a 100644 --- a/examples/infer_water/infer_water.c +++ b/examples/infer_water/infer_water.c @@ -32,5 +32,5 @@ int main() { free(v); free(ae); free(av); - free(dp); + DP_DeleteDeepPot(dp); } diff --git a/pyproject.toml b/pyproject.toml index e91fd320f3..b837d3be44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -141,12 +141,10 @@ manylinux-aarch64-image = "manylinux_2_28" [tool.cibuildwheel.macos] environment = { PIP_PREFER_BINARY="1", DP_LAMMPS_VERSION="stable_2Aug2023_update2", DP_ENABLE_IPI="1" } before-all = [ + # enable MPI for macos-arm64 in the next lammps release for compatibility """if [[ "$CIBW_BUILD" != *macosx_arm64* ]]; then brew install mpich; fi""", ] -before-build = [ - """if [[ "$CIBW_BUILD" == *macosx_arm64* ]]; then python -m pip install "tensorflow-macos>=2.13.0rc0" --platform macosx_12_0_arm64 --no-deps --target=$RUNNER_TEMP/tensorflow; fi""", -] -repair-wheel-command = """if [[ "$CIBW_BUILD" == *macosx_arm64* ]]; then rm -rf $RUNNER_TEMP/tensorflow; fi && delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} --ignore-missing-dependencies""" +repair-wheel-command = """delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} --ignore-missing-dependencies""" [tool.cibuildwheel.linux] repair-wheel-command = "auditwheel repair --exclude libtensorflow_framework.so.2 --exclude libtensorflow_framework.so.1 --exclude libtensorflow_framework.so --exclude _pywrap_tensorflow_internal.so --exclude libtensorflow_cc.so.2 -w {dest_dir} {wheel}" diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index c1c9b8e7fe..f7bef0b2d9 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -231,6 +231,7 @@ if(DEEPMD_C_ROOT) IMPORTED_LOCATION "${deepmd_c}" INTERFACE_INCLUDE_DIRECTORIES "${DEEPMD_INCLUDE_C_DIR}/deepmd") # use variable for TF path to set deepmd_c path + set(TENSORFLOW_ROOT "${DEEPMD_C_ROOT}") set(TensorFlow_LIBRARY_PATH "${DEEPMD_C_ROOT}/lib") set(TENSORFLOW_INCLUDE_DIRS "${DEEPMD_C_ROOT}/include") endif() diff --git a/source/api_c/include/c_api.h b/source/api_c/include/c_api.h index d05f790bf9..4baa7dd4a0 100644 --- a/source/api_c/include/c_api.h +++ b/source/api_c/include/c_api.h @@ -25,6 +25,13 @@ extern DP_Nlist* DP_NewNlist(int inum_, int* numneigh_, int** firstneigh_); +/** + * @brief Delete a neighbor list. + * + * @param nl Neighbor list to delete. + */ +extern void DP_DeleteNlist(DP_Nlist* nl); + /** * @brief Check if there is any exceptions throw. * @@ -72,6 +79,13 @@ extern DP_DeepPot* DP_NewDeepPotWithParam2(const char* c_model, const char* c_file_content, const int size_file_content); +/** + * @brief Delete a Deep Potential. + * + * @param dp Deep Potential to delete. + */ +extern void DP_DeleteDeepPot(DP_DeepPot* dp); + /** * @brief Evaluate the energy, force and virial by using a DP. (double version) * @attention The number of frames is assumed to be 1. @@ -491,6 +505,13 @@ extern DP_DeepPotModelDevi* DP_NewDeepPotModelDeviWithParam( const int n_file_contents, const int* size_file_contents); +/** + * @brief Delete a Deep Potential Model Deviation. + * + * @param dp Deep Potential to delete. + */ +extern void DP_DeleteDeepPotModelDevi(DP_DeepPotModelDevi* dp); + /** * @brief Evaluate the energy, force and virial by using a DP model deviation *with neighbor list. (double version) @@ -792,6 +813,13 @@ extern DP_DeepTensor* DP_NewDeepTensorWithParam(const char* c_model, const int gpu_rank, const char* c_name_scope); +/** + * @brief Delete a Deep Tensor. + * + * @param dp Deep Tensor to delete. + */ +extern void DP_DeleteDeepTensor(DP_DeepTensor* dt); + /** * @brief Evaluate the tensor by using a DP. (double version) * @param[in] dt The Deep Tensor to use. @@ -1094,6 +1122,13 @@ extern DP_DipoleChargeModifier* DP_NewDipoleChargeModifier(const char* c_model); extern DP_DipoleChargeModifier* DP_NewDipoleChargeModifierWithParam( const char* c_model, const int gpu_rank, const char* c_name_scope); +/** + * @brief Delete a Dipole Charge Modifier. + * + * @param dp Dipole Charge Modifier to delete. + */ +extern void DP_DeleteDipoleChargeModifier(DP_DipoleChargeModifier* dcm); + /** * @brief Evaluate the force and virial correction by using a dipole charge *modifier with the neighbor list. (double version) diff --git a/source/api_c/include/deepmd.hpp b/source/api_c/include/deepmd.hpp index 06a50ee3f0..966cc1f24e 100644 --- a/source/api_c/include/deepmd.hpp +++ b/source/api_c/include/deepmd.hpp @@ -522,6 +522,7 @@ struct InputNlist { nl(DP_NewNlist(inum_, ilist_, numneigh_, firstneigh_)) { DP_CHECK_OK(DP_NlistCheckOK, nl); }; + ~InputNlist() { DP_DeleteNlist(nl); }; /// @brief C API neighbor list. DP_Nlist *nl; /// @brief Number of core region atoms @@ -556,6 +557,8 @@ void inline convert_nlist(InputNlist &to_nlist, to_nlist.numneigh[ii] = from_nlist[ii].size(); to_nlist.firstneigh[ii] = &from_nlist[ii][0]; } + // delete the original nl + DP_DeleteNlist(to_nlist.nl); to_nlist.nl = DP_NewNlist(to_nlist.inum, to_nlist.ilist, to_nlist.numneigh, to_nlist.firstneigh); } @@ -568,7 +571,7 @@ class DeepPot { * @brief DP constructor without initialization. **/ DeepPot() : dp(nullptr){}; - ~DeepPot(){}; + ~DeepPot() { DP_DeleteDeepPot(dp); }; /** * @brief DP constructor with initialization. * @param[in] model The name of the frozen model file. @@ -579,7 +582,15 @@ class DeepPot { const int &gpu_rank = 0, const std::string &file_content = "") : dp(nullptr) { - init(model, gpu_rank, file_content); + try { + init(model, gpu_rank, file_content); + } catch (...) { + // Clean up and rethrow, as the destructor will not be called + if (dp) { + DP_DeleteDeepPot(dp); + } + throw; + } }; /** * @brief Initialize the DP. @@ -1100,13 +1111,21 @@ class DeepPotModelDevi { * @brief DP model deviation constructor without initialization. **/ DeepPotModelDevi() : dp(nullptr){}; - ~DeepPotModelDevi(){}; + ~DeepPotModelDevi() { DP_DeleteDeepPotModelDevi(dp); }; /** * @brief DP model deviation constructor with initialization. * @param[in] models The names of the frozen model file. **/ DeepPotModelDevi(const std::vector &models) : dp(nullptr) { - init(models); + try { + init(models); + } catch (...) { + // Clean up and rethrow, as the destructor will not be called + if (dp) { + DP_DeleteDeepPotModelDevi(dp); + } + throw; + } }; /** * @brief Initialize the DP model deviation. @@ -1523,7 +1542,7 @@ class DeepTensor { * @brief Deep Tensor constructor without initialization. **/ DeepTensor() : dt(nullptr){}; - ~DeepTensor(){}; + ~DeepTensor() { DP_DeleteDeepTensor(dt); }; /** * @brief DeepTensor constructor with initialization. * @param[in] model The name of the frozen model file. @@ -1532,7 +1551,15 @@ class DeepTensor { const int &gpu_rank = 0, const std::string &name_scope = "") : dt(nullptr) { - init(model, gpu_rank, name_scope); + try { + init(model, gpu_rank, name_scope); + } catch (...) { + // Clean up and rethrow, as the destructor will not be called + if (dt) { + DP_DeleteDeepTensor(dt); + } + throw; + } }; /** * @brief Initialize the DeepTensor. @@ -1891,7 +1918,7 @@ class DipoleChargeModifier { * @brief DipoleChargeModifier constructor without initialization. **/ DipoleChargeModifier() : dcm(nullptr){}; - ~DipoleChargeModifier(){}; + ~DipoleChargeModifier() { DP_DeleteDipoleChargeModifier(dcm); }; /** * @brief DipoleChargeModifier constructor with initialization. * @param[in] model The name of the frozen model file. @@ -1902,7 +1929,15 @@ class DipoleChargeModifier { const int &gpu_rank = 0, const std::string &name_scope = "") : dcm(nullptr) { - init(model, gpu_rank, name_scope); + try { + init(model, gpu_rank, name_scope); + } catch (...) { + // Clean up and rethrow, as the destructor will not be called + if (dcm) { + DP_DeleteDipoleChargeModifier(dcm); + } + throw; + } }; /** * @brief Initialize the DipoleChargeModifier. diff --git a/source/api_c/src/c_api.cc b/source/api_c/src/c_api.cc index bc6178702f..029d020f45 100644 --- a/source/api_c/src/c_api.cc +++ b/source/api_c/src/c_api.cc @@ -25,6 +25,8 @@ DP_Nlist* DP_NewNlist(int inum_, DP_Nlist* new_nl = new DP_Nlist(nl); return new_nl;) } +void DP_DeleteNlist(DP_Nlist* nl) { delete nl; } + DP_DeepPot::DP_DeepPot() {} DP_DeepPot::DP_DeepPot(deepmd::DeepPot& dp) : dp(dp) { dfparam = dp.dim_fparam(); @@ -61,6 +63,8 @@ DP_DeepPot* DP_NewDeepPotWithParam2(const char* c_model, DP_DeepPot* new_dp = new DP_DeepPot(dp); return new_dp;) } +void DP_DeleteDeepPot(DP_DeepPot* dp) { delete dp; } + DP_DeepPotModelDevi::DP_DeepPotModelDevi() {} DP_DeepPotModelDevi::DP_DeepPotModelDevi(deepmd::DeepPotModelDevi& dp) : dp(dp) { @@ -97,6 +101,8 @@ DP_DeepPotModelDevi* DP_NewDeepPotModelDeviWithParam( return new_dp;) } +void DP_DeleteDeepPotModelDevi(DP_DeepPotModelDevi* dp) { delete dp; } + DP_DeepTensor::DP_DeepTensor() {} DP_DeepTensor::DP_DeepTensor(deepmd::DeepTensor& dt) : dt(dt) {} @@ -115,6 +121,8 @@ DP_DeepTensor* DP_NewDeepTensorWithParam(const char* c_model, DP_DeepTensor* new_dt = new DP_DeepTensor(dt); return new_dt;) } +void DP_DeleteDeepTensor(DP_DeepTensor* dt) { delete dt; } + DP_DipoleChargeModifier::DP_DipoleChargeModifier() {} DP_DipoleChargeModifier::DP_DipoleChargeModifier( deepmd::DipoleChargeModifier& dcm) @@ -137,6 +145,8 @@ DP_DipoleChargeModifier* DP_NewDipoleChargeModifierWithParam( return new_dcm;) } +void DP_DeleteDipoleChargeModifier(DP_DipoleChargeModifier* dcm) { delete dcm; } + } // extern "C" template diff --git a/source/api_c/tests/test_deeppot_a.cc b/source/api_c/tests/test_deeppot_a.cc index 63f53e16e9..b4a9a81f92 100644 --- a/source/api_c/tests/test_deeppot_a.cc +++ b/source/api_c/tests/test_deeppot_a.cc @@ -86,7 +86,10 @@ class TestInferDeepPotA : public ::testing::Test { } }; - void TearDown() override { remove("deeppot.pb"); }; + void TearDown() override { + remove("deeppot.pb"); + DP_DeleteDeepPot(dp); + }; }; TEST_F(TestInferDeepPotA, double_infer) { @@ -119,6 +122,12 @@ TEST_F(TestInferDeepPotA, double_infer) { for (int ii = 0; ii < natoms * 9; ++ii) { EXPECT_LT(fabs(atomic_virial[ii] - expected_v[ii]), 1e-10); } + + delete ener_; + delete[] force_; + delete[] virial_; + delete[] atomic_ener_; + delete[] atomic_virial_; } TEST_F(TestInferDeepPotA, float_infer) { @@ -151,6 +160,11 @@ TEST_F(TestInferDeepPotA, float_infer) { for (int ii = 0; ii < natoms * 9; ++ii) { EXPECT_LT(fabs(atomic_virial[ii] - expected_v[ii]), 1e-6); } + delete ener_; + delete[] force_; + delete[] virial_; + delete[] atomic_ener_; + delete[] atomic_virial_; } TEST_F(TestInferDeepPotA, cutoff) { @@ -253,7 +267,11 @@ class TestInferDeepPotANoPBC : public ::testing::Test { } }; - void TearDown() override { remove("deeppot.pb"); }; + void TearDown() override { + remove("deeppot.pb"); + + DP_DeleteDeepPot(dp); + }; }; TEST_F(TestInferDeepPotANoPBC, double_infer) { @@ -286,6 +304,11 @@ TEST_F(TestInferDeepPotANoPBC, double_infer) { for (int ii = 0; ii < natoms * 9; ++ii) { EXPECT_LT(fabs(atomic_virial[ii] - expected_v[ii]), 1e-10); } + delete ener_; + delete[] force_; + delete[] virial_; + delete[] atomic_ener_; + delete[] atomic_virial_; } TEST_F(TestInferDeepPotANoPBC, float_infer) { @@ -318,4 +341,9 @@ TEST_F(TestInferDeepPotANoPBC, float_infer) { for (int ii = 0; ii < natoms * 9; ++ii) { EXPECT_LT(fabs(atomic_virial[ii] - expected_v[ii]), 1e-6); } + delete ener_; + delete[] force_; + delete[] virial_; + delete[] atomic_ener_; + delete[] atomic_virial_; } diff --git a/source/api_cc/include/DataModifier.h b/source/api_cc/include/DataModifier.h index 1e611a3930..6d443d9b9c 100644 --- a/source/api_cc/include/DataModifier.h +++ b/source/api_cc/include/DataModifier.h @@ -84,7 +84,7 @@ class DipoleChargeModifierBase { * @brief Get the list of sel types. * @return The list of sel types. */ - virtual std::vector sel_types() const = 0; + virtual const std::vector& sel_types() const = 0; }; /** @@ -161,7 +161,7 @@ class DipoleChargeModifier { * @brief Get the list of sel types. * @return The list of sel types. */ - std::vector sel_types() const; + const std::vector& sel_types() const; private: bool inited; diff --git a/source/api_cc/include/DataModifierTF.h b/source/api_cc/include/DataModifierTF.h index 2ca3729525..896ebcad57 100644 --- a/source/api_cc/include/DataModifierTF.h +++ b/source/api_cc/include/DataModifierTF.h @@ -83,7 +83,7 @@ class DipoleChargeModifierTF : public DipoleChargeModifierBase { * @brief Get the list of sel types. * @return The list of sel types. */ - std::vector sel_types() const { + const std::vector& sel_types() const { assert(inited); return sel_type; }; diff --git a/source/api_cc/src/DataModifier.cc b/source/api_cc/src/DataModifier.cc index 954c969c13..d44d552bb2 100644 --- a/source/api_cc/src/DataModifier.cc +++ b/source/api_cc/src/DataModifier.cc @@ -87,6 +87,6 @@ double DipoleChargeModifier::cutoff() const { return dcm->cutoff(); } int DipoleChargeModifier::numb_types() const { return dcm->numb_types(); } -std::vector DipoleChargeModifier::sel_types() const { +const std::vector& DipoleChargeModifier::sel_types() const { return dcm->sel_types(); } diff --git a/source/gmx/CMakeLists.txt b/source/gmx/CMakeLists.txt index c119e4b212..d445479d39 100644 --- a/source/gmx/CMakeLists.txt +++ b/source/gmx/CMakeLists.txt @@ -19,6 +19,7 @@ else() target_link_libraries(${libgmxname} PUBLIC ${LIB_DEEPMD_CC}) target_compile_definitions(${libgmxname} PUBLIC "DP_USE_CXX_API") endif() +target_compile_definitions(${libgmxname} PRIVATE "DP_GMX_PLUGIN_INTERNAL") target_include_directories(${libgmxname} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${libgmxname} diff --git a/source/gmx/include/gmx_plugin.h b/source/gmx/include/gmx_plugin.h index 51eae8ca7e..430ca2fe0d 100644 --- a/source/gmx/include/gmx_plugin.h +++ b/source/gmx/include/gmx_plugin.h @@ -5,7 +5,11 @@ #include "DeepPot.h" namespace deepmd_compat = deepmd; #else +#ifdef DP_GMX_PLUGIN_INTERNAL #include "deepmd.hpp" +#else +#include "deepmd/deepmd.hpp" +#endif namespace deepmd_compat = deepmd::hpp; #endif