diff --git a/CMakeLists.txt b/CMakeLists.txt index 056a394..5858706 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ if("${BUILD_TESTING}") py_${PROJECT_NAME} "${${PROJECT_NAME}_PYTHON_TEST_DIR}/unit_tests/test_${PROJECT_NAME}.py" DEPENDS nwchemex - SUBMODULES simde chemist pluginplay parallelzone friendzone chemcache nwchemex + SUBMODULES simde chemist pluginplay parallelzone friendzone chemcache nwchemex tensorwrapper integrals scf nux ) endif() diff --git a/src/python/structurefinder/__init__.py b/src/python/structurefinder/__init__.py index b30b4bf..4de7eee 100644 --- a/src/python/structurefinder/__init__.py +++ b/src/python/structurefinder/__init__.py @@ -13,6 +13,7 @@ # limitations under the License. from .pyberny import load_pyberny_modules +from .lj_potential.lennard_jones_potential_module import load_lennard_jones_potential def load_modules(mm): @@ -20,3 +21,4 @@ def load_modules(mm): Loads the collection of all modules provided by StructureFinder. """ load_pyberny_modules(mm) + load_lennard_jones_potential(mm) diff --git a/src/python/structurefinder/lj_potential/lennard_jones_potential_module.py b/src/python/structurefinder/lj_potential/lennard_jones_potential_module.py new file mode 100644 index 0000000..6d67d1b --- /dev/null +++ b/src/python/structurefinder/lj_potential/lennard_jones_potential_module.py @@ -0,0 +1,72 @@ +# Copyright 2025 NWChemEx Community +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +@author: Felix Rojas +""" + +import numpy as np +import pluginplay as pp +from simde import TotalEnergy +import tensorwrapper as tw + + +class LennardJonesPotential(pp.ModuleBase): + # Module Construct -------------------------------------------------------- + def __init__(self): + """ + This module Evaluates the Lennard-Jones 1D potential function (E) + """ + pp.ModuleBase.__init__(self) + self.description("Lennard-Jones 1D potential function") + self.satisfies_property_type(TotalEnergy()) + + #-------------------------------------------------------------------------- + + # Module run_ member function --------------------------------------------- + def run_(self, inputs, submods): + """ + Parameters + ---------- + inputs : Diatomic distance, + TYPE ---> Float + + Returns + ------- + E: Lennard-Jonnes 1D potential Energy, + TYPE ---> Float + """ + pt = TotalEnergy() + chem_sys, = pt.unwrap_inputs(inputs) + mol = chem_sys.molecule + coor_0 = np.array([mol.at(0).x, mol.at(0).y, mol.at(0).z]) + coor_1 = np.array([mol.at(1).x, mol.at(1).y, mol.at(1).z]) + #---------------------------------------------------------------------- + assert (mol.size() == 2) #<--- To check molcule size contains 2-atoms + #---------------------------------------------------------------------- + r = np.linalg.norm(coor_0 - coor_1) + #-------------- LENNARD-JONES FUNCTION -------------------------------- + E = 4 * ((1 / r**12) - (1 / r**6)) + #------------- ANALYTIC FORCE ----------------------------------------- + DE_x = -24 * ((2 / r**13) - (1 / r**7)) + FC = -DE_x + #---------------------------------------------------------------------- + E = tw.Tensor(np.array(E)) + rv = self.results() + return pt.wrap_results(rv, E) + + #-------------------------------------------------------------------------- + + +def load_lennard_jones_potential(mm): + mm.add_module("Lennard-Jones", LennardJonesPotential()) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index 886f192..f3c005c 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -16,6 +16,7 @@ from simde import EnergyNuclearGradientStdVectorD, TotalEnergy, MoleculeFromString from berny import Berny, geomlib import chemist +import numpy as np class GeomoptViaPyberny(pp.ModuleBase): @@ -70,7 +71,7 @@ def run_(self, inputs, submods): EnergyNuclearGradientStdVectorD(), geom, geom_points.as_point_set()) print('Interim gradient: \n' + str(gradients) + '\n') - optimizer.send((energy, gradients)) + optimizer.send((np.array(energy).item(), gradients)) opt_geom = geom.molecule.nuclei print( diff --git a/tests/python/unit_tests/test_lennard_jones_potential/__init__.py b/tests/python/unit_tests/test_lennard_jones_potential/__init__.py new file mode 100644 index 0000000..a8d4745 --- /dev/null +++ b/tests/python/unit_tests/test_lennard_jones_potential/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2025 NWChemEx Community +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/python/unit_tests/test_lennard_jones_potential/test_lennard_jones_potential.py b/tests/python/unit_tests/test_lennard_jones_potential/test_lennard_jones_potential.py new file mode 100644 index 0000000..0dc59c1 --- /dev/null +++ b/tests/python/unit_tests/test_lennard_jones_potential/test_lennard_jones_potential.py @@ -0,0 +1,35 @@ +# Copyright 2024 NWChemEx Community +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import numpy as np +import structurefinder +import nwchemex +import pluginplay as pp +import chemist +import unittest +from simde import TotalEnergy + + +class TestLennardJonesPotential(unittest.TestCase): + + def test_lennard_jones_potential(self): + result = self.mm.run_as(TotalEnergy(), "Lennard-Jones", + chemist.ChemicalSystem(self.mol)) + self.assertEqual(np.array(result).item(), -1.0) + + def setUp(self): + self.mm = pp.ModuleManager() + structurefinder.load_modules(self.mm) + self.mol = chemist.Molecule() + self.mol.push_back(chemist.Atom("H", 1, 1.0079, 0.0, 0.0, 0.0)) + self.mol.push_back(chemist.Atom("H", 1, 1.0079, 0.0, 0.0, 2**(1 / 6))) diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index 26611e6..f7a948b 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -14,6 +14,7 @@ import structurefinder import nwchemex +import numpy as np import pluginplay as pp import chemist import unittest @@ -35,7 +36,8 @@ def test_optimize_pyberny(self): egy = mm.run_as(TotalEnergy(), "PyBerny", chemist.ChemicalSystem(self.mol)) print("Energy = " + str(egy)) - self.assertAlmostEqual(egy, -1.117505879316, 10) + print(np.array(egy).item()) + self.assertAlmostEqual(np.array(egy).item(), -1.117505879316, 10) def setUp(self): self.mol = chemist.Molecule()