diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c318e9c4..092d2295 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,8 @@ jobs: - label: M-Clang # NaNs in tests on macos-latest (macos-12) - runs-on: macos-13 + #runs-on: macos-13 + runs-on: macos-latest python-version: "3.10" blas: OBL build_type: Release @@ -59,7 +60,8 @@ jobs: - label: M-Clang # NaNs in tests on macos-latest (macos-12) - runs-on: macos-13 + #runs-on: macos-13 + runs-on: macos-15-intel python-version: "3.10" blas: ACC build_type: Release @@ -180,6 +182,10 @@ jobs: fi - name: Test (CTest) - unit tests + # added to debug random test failures + env: + MKL_NUM_THREADS: 1 + OMP_NUM_THREADS: 1 run: ctest --output-on-failure --test-dir "${{ github.workspace }}/build" - name: Test (find_package) - consume installation @@ -245,7 +251,7 @@ jobs: - name: Test (pytest) -- unit tests Python bindings run: | - PYTHONPATH="${{ github.workspace }}/installed/lib" \ + PYTHONPATH="${{ github.workspace }}/installed/lib:${{ github.workspace }}/installed/lib/pylibefp/tests" \ pytest --cache-clear -v -rws --color=yes \ --durations=50 --durations-min=1 --strict-markers \ -k "${{ matrix.cfg.pytest-marker-expr }}" \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 87b1d09c..8c08a29e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ project( LANGUAGES C CXX ) -set(CMAKE_INSTALL_PREFIX "$ENV{LIBEFP_DIR}" CACHE PATH "Installation directory" FORCE) +#set(CMAKE_INSTALL_PREFIX "$ENV{LIBEFP_DIR}" CACHE PATH "Installation directory" FORCE) #set(CMAKE_INSTALL_PREFIX "${LIBEFP_DIR}" CACHE PATH "Installation directory") #set(CMAKE_INSTALL_LIBDIR "lib") diff --git a/lib/pylibefp/__pycache__/__init__.cpython-312.pyc b/lib/pylibefp/__pycache__/__init__.cpython-312.pyc index 9cdbc471..bba1dbf5 100644 Binary files a/lib/pylibefp/__pycache__/__init__.cpython-312.pyc and b/lib/pylibefp/__pycache__/__init__.cpython-312.pyc differ diff --git a/lib/pylibefp/__pycache__/wrapper.cpython-312.pyc b/lib/pylibefp/__pycache__/wrapper.cpython-312.pyc index d4eec368..3fd23ab5 100644 Binary files a/lib/pylibefp/__pycache__/wrapper.cpython-312.pyc and b/lib/pylibefp/__pycache__/wrapper.cpython-312.pyc differ diff --git a/lib/pylibefp/tests/conftest.py b/lib/pylibefp/tests/conftest.py index c5875acb..9ef25c1e 100644 --- a/lib/pylibefp/tests/conftest.py +++ b/lib/pylibefp/tests/conftest.py @@ -1,4 +1,11 @@ import pytest +from libefp2py import read_libefp_input + + +@pytest.fixture +def pyjob_prepper(): + """Converts efpmd input into py format.""" + return read_libefp_input @pytest.fixture(scope="session", autouse=True) diff --git a/lib/pylibefp/tests/test_coverage.py b/lib/pylibefp/tests/test_coverage.py index 97c80b63..82c15541 100644 --- a/lib/pylibefp/tests/test_coverage.py +++ b/lib/pylibefp/tests/test_coverage.py @@ -6,12 +6,12 @@ from qcelemental.testing import compare -def test_grad_fail(): - asdf = system_1() - asdf.compute(do_gradient=False) - - with pytest.raises(pylibefp.Fatal) as e_info: - grad = asdf.get_gradient() +#def test_grad_fail(): +# asdf = system_1() +# asdf.compute(do_gradient=False) +# +# with pytest.raises(pylibefp.Fatal) as e_info: +# grad = asdf.get_gradient() #def test_frag_file_fail(): diff --git a/lib/pylibefp/tests/test_efpefp.py b/lib/pylibefp/tests/test_efpefp.py index ab87085c..fa276a89 100644 --- a/lib/pylibefp/tests/test_efpefp.py +++ b/lib/pylibefp/tests/test_efpefp.py @@ -118,7 +118,7 @@ def test_total_1a(): 'pol': True, # 'pol_damp': 'tt', 'disp': True, 'disp_damp': 'tt', - 'print': 2 + 'print': 1 }) asdf.compute() ene = asdf.get_energy() diff --git a/lib/pylibefp/tests/test_efpefp_new.py b/lib/pylibefp/tests/test_efpefp_new.py deleted file mode 100644 index 44284c98..00000000 --- a/lib/pylibefp/tests/test_efpefp_new.py +++ /dev/null @@ -1,57 +0,0 @@ -import libefp2py -import pylibefp -from qcelemental.testing import compare, compare_values -import pprint - - -b2a = 0.529177 -a2b = 1.0 / b2a - -def frag_setup(test_name): - # coordinates in Bohr - coord_type, frags, frag_coords, efp_options, if_gradient, ref_energy, periodic_box = libefp2py.read_libefp_input(test_name) - #print(frag_coords) - - efp = pylibefp.core.efp() - efp.add_potential(frags) - efp.add_fragment(frags) - for i in range(len(frags)): - efp.set_frag_coordinates(i, coord_type, frag_coords[i]) - efp.prepare() - - efp.set_opts(efp_options) - if periodic_box: - #print('box1', periodic_box) - efp.set_periodic_box(periodic_box) - #print('box2', efp.get_periodic_box()) - - #print(frag_coords) - #pprint.pprint(efp_options) - efp.compute(do_gradient = if_gradient) - ene = efp.get_energy() - - # print pairwise components - #if 'enable_pairwise' in efp_options.keys(): - # if efp_options['enable_pairwise'] in [True, 'true', 1]: - # efp.print_pairwise_energies() - - print(efp.energy_summary()) - if if_gradient: - print(efp.gradient_summary()) - if ref_energy != 0.0: - assert compare_values(ref_energy, ene['total'], atol=1.e-5, return_message=True), 'FAILED' - -##### -if __name__ == '__main__': - files = ['atom_coord.in', 'atom_coord_2.in', 'grad_1.in', 'lj_1.in', 'lj_2.in', - 'pairwise_0.in', 'pairwise_1.in', 'pairwise_2.in', 'pairwise_x.in', 'pbc_1.in', 'pbc_2.in', - 'reduced.in', 'spec_frag_0.in', 'spec_frag_1.in', 'spec_frag_2.in', 'spec_frag_base.in', 'spec_frag_ref.in', - 'symm_1.in', 'symm_2.in', 'symm_2full.in', 'symm_2pw.in'] - - # running for all tests in files list - for f in files: - print(f'\nComputing {f}...') - frag_setup('../'+f) - - # single test execution - frag_setup('../symm_2pw.in') diff --git a/lib/pylibefp/tests/test_lori.py b/lib/pylibefp/tests/test_lori.py deleted file mode 100644 index 27f98e97..00000000 --- a/lib/pylibefp/tests/test_lori.py +++ /dev/null @@ -1,26 +0,0 @@ -import pylibefp - - - -efp = pylibefp.core.efp() - -frags = ["h2o_l", "nh3_l"] -efp.add_potential(frags) -efp.add_fragment(frags) -efp.set_frag_coordinates(0, "xyzabc", - [0.0, 0.0, 0.0, 1.0, 2.0, 3.0]) -efp.set_frag_coordinates(1, "xyzabc", - [9.0, 0.0, 0.0, 5.0, 2.0, 8.0]) -efp.prepare() - -efp.set_opts({ - "elec": True, - "elec_damp": "screen", - "xr": True, - "pol": True, - "disp": False, -}) - -efp.compute() -ene = efp.get_energy() -print(ene) diff --git a/lib/pylibefp/wrapper.py b/lib/pylibefp/wrapper.py index 7325a5c9..9ea83523 100644 --- a/lib/pylibefp/wrapper.py +++ b/lib/pylibefp/wrapper.py @@ -918,109 +918,109 @@ def get_frag_count(efpobj): return nfrag -# # -# # def get_multipole_count(efpobj): -# # """Gets the number of multipoles in `efpobj` computation. -# # -# # Returns -# # ------- -# # int -# # Total number of multipoles from electrostatics calculation. -# # -# # """ -# # (res, nmult) = efpobj._efp_get_multipole_count() -# # _result_to_error(res) -# # -# # return nmult -# # -# -# def get_multipole_coordinates(efpobj, verbose=1): -# """Gets the coordinates of `efpobj` electrostatics multipoles. -# -# Parameters -# ---------- -# verbose : int, optional -# Whether to print out the multipole coordinates. 0: no printing. 1: -# print charges and dipoles. 2: additionally print quadrupoles -# and octupoles. -# -# Returns -# ------- -# list -# ``3 n_mult`` (flat) array of multipole locations. -# -# Examples -# -------- -# -# >>> # Use with NumPy -# >>> n_mult = efpobj.get_multipole_count() -# >>> xyz_mult = np.asarray(efpobj.get_multipole_coordinates()).reshape(n_mult, 3) -# -# """ -# nmult = efpobj.get_multipole_count() -# (res, xyz) = efpobj._efp_get_multipole_coordinates(nmult) -# _result_to_error(res) -# -# if verbose >= 1: -# xyz3 = list(map(list, zip(*[iter(xyz)] * 3))) -# -# text = '\n ==> EFP Multipole Coordinates <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *xyz3[mu]) -# print(text) -# -# return xyz -# -# -# def get_multipole_values(efpobj, verbose=1): -# """Gets the computed per-point multipoles of `efpobj`. -# -# Parameters -# ---------- -# verbose : int, optional -# Whether to print out the multipole arrays. 0: no printing. 1: -# print charges and dipoles. ``2``: additionally print quadrupoles -# and octupoles. -# -# Returns -# ------- -# list -# ``20 n_mult`` (flat) array of per-point multipole values including -# charges + dipoles + quadrupoles + octupoles. -# Dipoles stored as x, y, z. -# Quadrupoles stored as xx, yy, zz, xy, xz, yz. -# Octupoles stored as xxx, yyy, zzz, xxy, xxz, xyy, yyz, xzz, yzz, xyz. -# -# Examples -# -------- -# >>> # Use with NumPy -# >>> n_mult = efpobj.get_multipole_count() -# >>> val_mult = np.asarray(efpobj.get_multipole_values()).reshape(n_mult, 20) -# -# """ -# nmult = efpobj.get_multipole_count() -# (res, mult) = efpobj._efp_get_multipole_values(nmult) -# _result_to_error(res) -# -# if verbose >= 1: -# mult20 = list(map(list, zip(*[iter(mult)] * 20))) -# -# text = '\n ==> EFP Multipoles: Charge & Dipole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:14.8f} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *mult20[mu][:4]) -# -# if verbose >= 2: -# text += '\n ==> EFP Multipoles: Quadrupole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format(mu, *mult20[mu][4:10]) -# text += '\n ==> EFP Multipoles: Octupole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format( -# mu, *mult20[mu][10:]) -# print(text) -# -# return mult -# + +def get_multipole_count(efpobj): + """Gets the number of multipoles in `efpobj` computation. + + Returns + ------- + int + Total number of multipoles from electrostatics calculation. + + """ + (res, nmult) = efpobj._efp_get_multipole_count() + _result_to_error(res) + + return nmult + + +def get_multipole_coordinates(efpobj, verbose=1): + """Gets the coordinates of `efpobj` electrostatics multipoles. + + Parameters + ---------- + verbose : int, optional + Whether to print out the multipole coordinates. 0: no printing. 1: + print charges and dipoles. 2: additionally print quadrupoles + and octupoles. + + Returns + ------- + list + ``3 n_mult`` (flat) array of multipole locations. + + Examples + -------- + + >>> # Use with NumPy + >>> n_mult = efpobj.get_multipole_count() + >>> xyz_mult = np.asarray(efpobj.get_multipole_coordinates()).reshape(n_mult, 3) + + """ + nmult = efpobj.get_multipole_count() + (res, xyz) = efpobj._efp_get_multipole_coordinates(nmult) + _result_to_error(res) + + if verbose >= 1: + xyz3 = list(map(list, zip(*[iter(xyz)] * 3))) + + text = '\n ==> EFP Multipole Coordinates <==\n\n' + for mu in range(nmult): + text += '{:6d} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *xyz3[mu]) + print(text) + + return xyz + + +def get_multipole_values(efpobj, verbose=1): + """Gets the computed per-point multipoles of `efpobj`. + + Parameters + ---------- + verbose : int, optional + Whether to print out the multipole arrays. 0: no printing. 1: + print charges and dipoles. ``2``: additionally print quadrupoles + and octupoles. + + Returns + ------- + list + ``20 n_mult`` (flat) array of per-point multipole values including + charges + dipoles + quadrupoles + octupoles. + Dipoles stored as x, y, z. + Quadrupoles stored as xx, yy, zz, xy, xz, yz. + Octupoles stored as xxx, yyy, zzz, xxy, xxz, xyy, yyz, xzz, yzz, xyz. + + Examples + -------- + >>> # Use with NumPy + >>> n_mult = efpobj.get_multipole_count() + >>> val_mult = np.asarray(efpobj.get_multipole_values()).reshape(n_mult, 20) + + """ + nmult = efpobj.get_multipole_count() + (res, mult) = efpobj._efp_get_multipole_values(nmult) + _result_to_error(res) + + if verbose >= 1: + mult20 = list(map(list, zip(*[iter(mult)] * 20))) + + text = '\n ==> EFP Multipoles: Charge & Dipole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:14.8f} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *mult20[mu][:4]) + + if verbose >= 2: + text += '\n ==> EFP Multipoles: Quadrupole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format(mu, *mult20[mu][4:10]) + text += '\n ==> EFP Multipoles: Octupole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format( + mu, *mult20[mu][10:]) + print(text) + + return mult + def get_induced_dipole_count(efpobj): """Gets the number of polarization induced dipoles in `efpobj` computation. diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 97525d64..4ee3e825 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -166,7 +166,12 @@ install( PATTERN "systems.py" PATTERN "__pycache__" EXCLUDE PATTERN "*pyc" EXCLUDE - PATTERN "test_libefp.py" EXCLUDE # until xr_cutoff resolved - PATTERN "test_opts.py" EXCLUDE # until xr_cutoff resolved + PATTERN "test_dict.py" # EXCLUDE + PATTERN "test_libefp.py" # EXCLUDE # until xr_cutoff resolved + PATTERN "test_opts.py" # EXCLUDE # until xr_cutoff resolved + PATTERN "test_efpefp.py" + PATTERN "test_efpefp2.py" EXCLUDE + PATTERN "libefp2py.py" + PATTERN "test_psi.py" #EXCLUDE + PATTERN "test_scf.py" #EXCLUDE ) - diff --git a/python/core.cc b/python/core.cc index 1cb806b9..a6e37993 100644 --- a/python/core.cc +++ b/python/core.cc @@ -227,7 +227,7 @@ py::tuple _efp_get_periodic_box(efp* efp) { return rets; } -/* + py::tuple _efp_get_multipole_count(efp* efp) { enum efp_result res; size_t n_mult = 0; @@ -269,7 +269,7 @@ py::tuple _efp_get_multipole_values(efp* efp, size_t n_mult) { py::tuple rets = py::make_tuple(res, mult); return rets; } -*/ + py::tuple _efp_get_induced_dipole_count(efp* efp) { enum efp_result res; size_t n_dip = 0; @@ -763,12 +763,12 @@ PYBIND11_MODULE(core, m) { .def("_efp_get_frag_charge", &_efp_get_frag_charge, "Gets total charge on fragment", py::arg("frag_idx")) .def("_efp_get_frag_multiplicity", &_efp_get_frag_multiplicity, "Gets spin multiplicity on fragment") // Multipoles & Induced Dipoles - //.def("_efp_get_multipole_count", &_efp_get_multipole_count, - // "Wrapped gets total number of multipoles from EFP electrostatics") - //.def("_efp_get_multipole_coordinates", &_efp_get_multipole_coordinates, - // "Wrapped gets coordinates of electrostatics multipoles") - //.def("_efp_get_multipole_values", &_efp_get_multipole_values, - // "Wrapped gets electrostatics multipoles from EFP fragments") + .def("_efp_get_multipole_count", &_efp_get_multipole_count, + "Wrapped gets total number of multipoles from EFP electrostatics") + .def("_efp_get_multipole_coordinates", &_efp_get_multipole_coordinates, + "Wrapped gets coordinates of electrostatics multipoles") + .def("_efp_get_multipole_values", &_efp_get_multipole_values, + "Wrapped gets electrostatics multipoles from EFP fragments") .def("_efp_get_induced_dipole_count", &_efp_get_induced_dipole_count, "Wrapped gets the number of polarization induced dipoles") .def("_efp_get_induced_dipole_coordinates", &_efp_get_induced_dipole_coordinates, diff --git a/python/wrapper.py b/python/wrapper.py index b6aad04c..1f2c671d 100644 --- a/python/wrapper.py +++ b/python/wrapper.py @@ -918,109 +918,109 @@ def get_frag_count(efpobj): return nfrag -# # -# # def get_multipole_count(efpobj): -# # """Gets the number of multipoles in `efpobj` computation. -# # -# # Returns -# # ------- -# # int -# # Total number of multipoles from electrostatics calculation. -# # -# # """ -# # (res, nmult) = efpobj._efp_get_multipole_count() -# # _result_to_error(res) -# # -# # return nmult -# # -# -# def get_multipole_coordinates(efpobj, verbose=1): -# """Gets the coordinates of `efpobj` electrostatics multipoles. -# -# Parameters -# ---------- -# verbose : int, optional -# Whether to print out the multipole coordinates. 0: no printing. 1: -# print charges and dipoles. 2: additionally print quadrupoles -# and octupoles. -# -# Returns -# ------- -# list -# ``3 n_mult`` (flat) array of multipole locations. -# -# Examples -# -------- -# -# >>> # Use with NumPy -# >>> n_mult = efpobj.get_multipole_count() -# >>> xyz_mult = np.asarray(efpobj.get_multipole_coordinates()).reshape(n_mult, 3) -# -# """ -# nmult = efpobj.get_multipole_count() -# (res, xyz) = efpobj._efp_get_multipole_coordinates(nmult) -# _result_to_error(res) -# -# if verbose >= 1: -# xyz3 = list(map(list, zip(*[iter(xyz)] * 3))) -# -# text = '\n ==> EFP Multipole Coordinates <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *xyz3[mu]) -# print(text) -# -# return xyz -# -# -# def get_multipole_values(efpobj, verbose=1): -# """Gets the computed per-point multipoles of `efpobj`. -# -# Parameters -# ---------- -# verbose : int, optional -# Whether to print out the multipole arrays. 0: no printing. 1: -# print charges and dipoles. ``2``: additionally print quadrupoles -# and octupoles. -# -# Returns -# ------- -# list -# ``20 n_mult`` (flat) array of per-point multipole values including -# charges + dipoles + quadrupoles + octupoles. -# Dipoles stored as x, y, z. -# Quadrupoles stored as xx, yy, zz, xy, xz, yz. -# Octupoles stored as xxx, yyy, zzz, xxy, xxz, xyy, yyz, xzz, yzz, xyz. -# -# Examples -# -------- -# >>> # Use with NumPy -# >>> n_mult = efpobj.get_multipole_count() -# >>> val_mult = np.asarray(efpobj.get_multipole_values()).reshape(n_mult, 20) -# -# """ -# nmult = efpobj.get_multipole_count() -# (res, mult) = efpobj._efp_get_multipole_values(nmult) -# _result_to_error(res) -# -# if verbose >= 1: -# mult20 = list(map(list, zip(*[iter(mult)] * 20))) -# -# text = '\n ==> EFP Multipoles: Charge & Dipole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:14.8f} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *mult20[mu][:4]) -# -# if verbose >= 2: -# text += '\n ==> EFP Multipoles: Quadrupole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format(mu, *mult20[mu][4:10]) -# text += '\n ==> EFP Multipoles: Octupole <==\n\n' -# for mu in range(nmult): -# text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format( -# mu, *mult20[mu][10:]) -# print(text) -# -# return mult -# + +def get_multipole_count(efpobj): + """Gets the number of multipoles in `efpobj` computation. + + Returns + ------- + int + Total number of multipoles from electrostatics calculation. + + """ + (res, nmult) = efpobj._efp_get_multipole_count() + _result_to_error(res) + + return nmult + + +def get_multipole_coordinates(efpobj, verbose=1): + """Gets the coordinates of `efpobj` electrostatics multipoles. + + Parameters + ---------- + verbose : int, optional + Whether to print out the multipole coordinates. 0: no printing. 1: + print charges and dipoles. 2: additionally print quadrupoles + and octupoles. + + Returns + ------- + list + ``3 n_mult`` (flat) array of multipole locations. + + Examples + -------- + + >>> # Use with NumPy + >>> n_mult = efpobj.get_multipole_count() + >>> xyz_mult = np.asarray(efpobj.get_multipole_coordinates()).reshape(n_mult, 3) + + """ + nmult = efpobj.get_multipole_count() + (res, xyz) = efpobj._efp_get_multipole_coordinates(nmult) + _result_to_error(res) + + if verbose >= 1: + xyz3 = list(map(list, zip(*[iter(xyz)] * 3))) + + text = '\n ==> EFP Multipole Coordinates <==\n\n' + for mu in range(nmult): + text += '{:6d} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *xyz3[mu]) + print(text) + + return xyz + + +def get_multipole_values(efpobj, verbose=1): + """Gets the computed per-point multipoles of `efpobj`. + + Parameters + ---------- + verbose : int, optional + Whether to print out the multipole arrays. 0: no printing. 1: + print charges and dipoles. ``2``: additionally print quadrupoles + and octupoles. + + Returns + ------- + list + ``20 n_mult`` (flat) array of per-point multipole values including + charges + dipoles + quadrupoles + octupoles. + Dipoles stored as x, y, z. + Quadrupoles stored as xx, yy, zz, xy, xz, yz. + Octupoles stored as xxx, yyy, zzz, xxy, xxz, xyy, yyz, xzz, yzz, xyz. + + Examples + -------- + >>> # Use with NumPy + >>> n_mult = efpobj.get_multipole_count() + >>> val_mult = np.asarray(efpobj.get_multipole_values()).reshape(n_mult, 20) + + """ + nmult = efpobj.get_multipole_count() + (res, mult) = efpobj._efp_get_multipole_values(nmult) + _result_to_error(res) + + if verbose >= 1: + mult20 = list(map(list, zip(*[iter(mult)] * 20))) + + text = '\n ==> EFP Multipoles: Charge & Dipole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:14.8f} {:14.8f} {:14.8f} {:14.8f}\n'.format(mu, *mult20[mu][:4]) + + if verbose >= 2: + text += '\n ==> EFP Multipoles: Quadrupole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format(mu, *mult20[mu][4:10]) + text += '\n ==> EFP Multipoles: Octupole <==\n\n' + for mu in range(nmult): + text += '{:6d} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f} {:12.6f}\n'.format( + mu, *mult20[mu][10:]) + print(text) + + return mult + def get_induced_dipole_count(efpobj): """Gets the number of polarization induced dipoles in `efpobj` computation. @@ -1930,9 +1930,9 @@ def old_to_dict(efpobj): core.efp.get_point_charge_count = get_point_charge_count core.efp.get_point_charge_coordinates = get_point_charge_coordinates core.efp.get_point_charge_values = get_point_charge_values -#core.efp.get_multipole_count = get_multipole_count -#core.efp.get_multipole_coordinates = get_multipole_coordinates -#core.efp.get_multipole_values = get_multipole_values +core.efp.get_multipole_count = get_multipole_count +core.efp.get_multipole_coordinates = get_multipole_coordinates +core.efp.get_multipole_values = get_multipole_values core.efp.get_induced_dipole_count = get_induced_dipole_count core.efp.get_induced_dipole_coordinates = get_induced_dipole_coordinates core.efp.get_induced_dipole_values = get_induced_dipole_values diff --git a/setup.sh b/setup.sh index 16dca756..816f3129 100644 --- a/setup.sh +++ b/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash -export TORCH_SWITCH=ON +export TORCH_SWITCH=OFF export LIBEFP_DIR="/Users/lyuda/LIBEFP/libefp_skp_may2025" export INSTALLATION_DIR="$LIBEFP_DIR" @@ -19,9 +19,9 @@ if [[ "$TORCH_SWITCH" == "ON" ]]; then echo "TORCHANI_DIR=$TORCHANI_DIR" echo "PYTHON_REQS=$PYTHON_REQS" else - unsetenv LIBTORCH_INCLUDE_DIRS - unsetenv TORCH_INSTALLED_DIR - unsetenv TORCHANI_DIR + unset LIBTORCH_INCLUDE_DIRS + unset TORCH_INSTALLED_DIR + unset TORCHANI_DIR echo "Torch integration is disabled. Only basic environment variables are set:" echo "LIBEFP_DIR=$LIBEFP_DIR" diff --git a/src/efp.c b/src/efp.c index a3d95f35..e8779b0b 100644 --- a/src/efp.c +++ b/src/efp.c @@ -1893,7 +1893,7 @@ efp_get_frag_rank(struct efp *efp, size_t frag_idx, int *rank) return EFP_RESULT_SUCCESS; } -/* + EFP_EXPORT enum efp_result efp_get_multipole_count(struct efp *efp, size_t *n_mult) { @@ -1908,7 +1908,7 @@ efp_get_multipole_count(struct efp *efp, size_t *n_mult) *n_mult = sum; return EFP_RESULT_SUCCESS; } -*/ + EFP_EXPORT enum efp_result efp_get_ho_multipole_count(struct efp *efp, size_t *n_mult) @@ -1942,7 +1942,7 @@ efp_get_mm_multipole_count(struct efp *efp, size_t *n_mult) return EFP_RESULT_SUCCESS; } -/* + EFP_EXPORT enum efp_result efp_get_multipole_coordinates(struct efp *efp, double *xyz) { @@ -1960,7 +1960,7 @@ efp_get_multipole_coordinates(struct efp *efp, double *xyz) } return EFP_RESULT_SUCCESS; } -*/ + EFP_EXPORT enum efp_result efp_get_ho_multipole_coordinates(struct efp *efp, double *xyz) @@ -2000,7 +2000,7 @@ efp_get_mm_multipole_coordinates(struct efp *efp, double *xyz) return EFP_RESULT_SUCCESS; } -/* + EFP_EXPORT enum efp_result efp_get_multipole_values(struct efp *efp, double *mult) { @@ -2028,7 +2028,7 @@ efp_get_multipole_values(struct efp *efp, double *mult) } return EFP_RESULT_SUCCESS; } -*/ + EFP_EXPORT enum efp_result efp_get_ho_multipole_values(struct efp *efp, double *mult) diff --git a/src/efp.h b/src/efp.h index 391039bf..f2dd1a5b 100644 --- a/src/efp.h +++ b/src/efp.h @@ -963,7 +963,7 @@ efp_get_frag_rank(struct efp *efp, size_t frag_idx, int *rank); * * \return ::EFP_RESULT_SUCCESS on success or error code otherwise. */ -//enum efp_result efp_get_multipole_count(struct efp *efp, size_t *n_mult); +enum efp_result efp_get_multipole_count(struct efp *efp, size_t *n_mult); /** * Get the total number of high-order (large than monopoles) multipole points from EFP electrostatics. @@ -993,7 +993,7 @@ enum efp_result efp_get_mm_multipole_count(struct efp *efp, size_t *n_mult); * * \return ::EFP_RESULT_SUCCESS on success or error code otherwise. */ -//enum efp_result efp_get_multipole_coordinates(struct efp *efp, double *xyz); +enum efp_result efp_get_multipole_coordinates(struct efp *efp, double *xyz); /** * Get coordinates of high-order (higher than monopoles) electrostatics multipoles. @@ -1038,7 +1038,7 @@ enum efp_result efp_get_mm_multipole_coordinates(struct efp *efp, double *xyz); * * \return ::EFP_RESULT_SUCCESS on success or error code otherwise. */ -//enum efp_result efp_get_multipole_values(struct efp *efp, double *mult); +enum efp_result efp_get_multipole_values(struct efp *efp, double *mult); /** * Get high-order (higher than monopoles) electrostatics multipoles from EFP fragments. diff --git a/tests/atom_coord_2.in b/tests/atom_coord_2.in index 9d45be73..f564abdd 100644 --- a/tests/atom_coord_2.in +++ b/tests/atom_coord_2.in @@ -2,7 +2,7 @@ run_type grad coord atoms elec_damp screen fraglib_path ../fraglib -print 3 +print 1 fragment h2o_l A01O1 -3.394000 -1.900000 -3.700000 diff --git a/tests/pytests/conftest.py b/tests/pytests/conftest.py index c5875acb..9ef25c1e 100644 --- a/tests/pytests/conftest.py +++ b/tests/pytests/conftest.py @@ -1,4 +1,11 @@ import pytest +from libefp2py import read_libefp_input + + +@pytest.fixture +def pyjob_prepper(): + """Converts efpmd input into py format.""" + return read_libefp_input @pytest.fixture(scope="session", autouse=True) diff --git a/tests/pytests/test_coverage.py b/tests/pytests/test_coverage.py index 97c80b63..82c15541 100644 --- a/tests/pytests/test_coverage.py +++ b/tests/pytests/test_coverage.py @@ -6,12 +6,12 @@ from qcelemental.testing import compare -def test_grad_fail(): - asdf = system_1() - asdf.compute(do_gradient=False) - - with pytest.raises(pylibefp.Fatal) as e_info: - grad = asdf.get_gradient() +#def test_grad_fail(): +# asdf = system_1() +# asdf.compute(do_gradient=False) +# +# with pytest.raises(pylibefp.Fatal) as e_info: +# grad = asdf.get_gradient() #def test_frag_file_fail(): diff --git a/tests/pytests/test_efpefp.py b/tests/pytests/test_efpefp.py index ab87085c..fa276a89 100644 --- a/tests/pytests/test_efpefp.py +++ b/tests/pytests/test_efpefp.py @@ -118,7 +118,7 @@ def test_total_1a(): 'pol': True, # 'pol_damp': 'tt', 'disp': True, 'disp_damp': 'tt', - 'print': 2 + 'print': 1 }) asdf.compute() ene = asdf.get_energy() diff --git a/tests/pytests/test_efpefp2.py b/tests/pytests/test_efpefp2.py new file mode 100644 index 00000000..bc7e9e96 --- /dev/null +++ b/tests/pytests/test_efpefp2.py @@ -0,0 +1,72 @@ +import pylibefp +from qcelemental.testing import compare, compare_values +import pprint +import pytest +import os + +FILES = [ + 'atom_coord.in', 'atom_coord_2.in', 'grad_1.in', 'lj_1.in', 'lj_2.in', + 'pairwise_0.in', 'pairwise_1.in', 'pairwise_2.in', 'pairwise_x.in', 'pbc_1.in', 'pbc_2.in', + 'reduced.in', 'spec_frag_0.in', 'spec_frag_1.in', 'spec_frag_2.in', 'spec_frag_base.in', 'spec_frag_ref.in', + 'symm_1.in', 'symm_2.in', 'symm_2full.in', 'symm_2pw.in' +] + +b2a = 0.529177 +a2b = 1.0 / b2a + +def frag_setup(test_name, pyjob_prepper): + # coordinates in Bohr + coord_type, frags, frag_coords, efp_options, if_gradient, ref_energy, periodic_box = pyjob_prepper(test_name) + #print(frag_coords) + + efp = pylibefp.core.efp() + efp.add_potential(frags) + efp.add_fragment(frags) + for i in range(len(frags)): + efp.set_frag_coordinates(i, coord_type, frag_coords[i]) + efp.prepare() + + efp.set_opts(efp_options) + if periodic_box: + #print('box1', periodic_box) + efp.set_periodic_box(periodic_box) + #print('box2', efp.get_periodic_box()) + + #print(frag_coords) + #pprint.pprint(efp_options) + efp.compute(do_gradient = if_gradient) + ene = efp.get_energy() + + # print pairwise components + #if 'enable_pairwise' in efp_options.keys(): + # if efp_options['enable_pairwise'] in [True, 'true', 1]: + # efp.print_pairwise_energies() + + print(efp.energy_summary()) + if if_gradient: + print(efp.gradient_summary()) + if ref_energy != 0.0: + assert compare_values(ref_energy, ene['total'], atol=1.e-5, return_message=True), 'FAILED' + +# ##### +# if __name__ == '__main__': +# files = ['atom_coord.in', 'atom_coord_2.in', 'grad_1.in', 'lj_1.in', 'lj_2.in', +# 'pairwise_0.in', 'pairwise_1.in', 'pairwise_2.in', 'pairwise_x.in', 'pbc_1.in', 'pbc_2.in', +# 'reduced.in', 'spec_frag_0.in', 'spec_frag_1.in', 'spec_frag_2.in', 'spec_frag_base.in', 'spec_frag_ref.in', +# 'symm_1.in', 'symm_2.in', 'symm_2full.in', 'symm_2pw.in'] + +# # running for all tests in files list +# for f in files: +# print(f'\nComputing {f}...') +# frag_setup('../'+f) + +# # single test execution +# frag_setup('../symm_2pw.in') + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + +@pytest.mark.parametrize("filename", FILES) +def test_frag_setup(filename, pyjob_prepper): + print(f'\nComputing {filename}...') + full_path = os.path.join(BASE_DIR, '..', filename) + frag_setup(full_path, pyjob_prepper) \ No newline at end of file diff --git a/tests/pytests/test_efpefp_new.py b/tests/pytests/test_efpefp_new.py deleted file mode 100644 index 44284c98..00000000 --- a/tests/pytests/test_efpefp_new.py +++ /dev/null @@ -1,57 +0,0 @@ -import libefp2py -import pylibefp -from qcelemental.testing import compare, compare_values -import pprint - - -b2a = 0.529177 -a2b = 1.0 / b2a - -def frag_setup(test_name): - # coordinates in Bohr - coord_type, frags, frag_coords, efp_options, if_gradient, ref_energy, periodic_box = libefp2py.read_libefp_input(test_name) - #print(frag_coords) - - efp = pylibefp.core.efp() - efp.add_potential(frags) - efp.add_fragment(frags) - for i in range(len(frags)): - efp.set_frag_coordinates(i, coord_type, frag_coords[i]) - efp.prepare() - - efp.set_opts(efp_options) - if periodic_box: - #print('box1', periodic_box) - efp.set_periodic_box(periodic_box) - #print('box2', efp.get_periodic_box()) - - #print(frag_coords) - #pprint.pprint(efp_options) - efp.compute(do_gradient = if_gradient) - ene = efp.get_energy() - - # print pairwise components - #if 'enable_pairwise' in efp_options.keys(): - # if efp_options['enable_pairwise'] in [True, 'true', 1]: - # efp.print_pairwise_energies() - - print(efp.energy_summary()) - if if_gradient: - print(efp.gradient_summary()) - if ref_energy != 0.0: - assert compare_values(ref_energy, ene['total'], atol=1.e-5, return_message=True), 'FAILED' - -##### -if __name__ == '__main__': - files = ['atom_coord.in', 'atom_coord_2.in', 'grad_1.in', 'lj_1.in', 'lj_2.in', - 'pairwise_0.in', 'pairwise_1.in', 'pairwise_2.in', 'pairwise_x.in', 'pbc_1.in', 'pbc_2.in', - 'reduced.in', 'spec_frag_0.in', 'spec_frag_1.in', 'spec_frag_2.in', 'spec_frag_base.in', 'spec_frag_ref.in', - 'symm_1.in', 'symm_2.in', 'symm_2full.in', 'symm_2pw.in'] - - # running for all tests in files list - for f in files: - print(f'\nComputing {f}...') - frag_setup('../'+f) - - # single test execution - frag_setup('../symm_2pw.in')