From 7a70816a06bc99388e4054112feebc61c9a1362e Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Wed, 23 Apr 2025 08:07:12 -0500 Subject: [PATCH 1/8] updated pyberny property to TotalEnergyNuclearOptimization --- .../structurefinder/pyberny/__init__.py | 64 +++++++++---------- .../test_optimizers/test_pybernyop.py | 13 ++-- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index f3c005c..2f881ac 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -13,75 +13,75 @@ # limitations under the License. import pluginplay as pp -from simde import EnergyNuclearGradientStdVectorD, TotalEnergy, MoleculeFromString +from simde import ( + EnergyNuclearGradientStdVectorD, + TotalEnergyNuclearOptimization, + MoleculeFromString, + TotalEnergy, +) from berny import Berny, geomlib import chemist import numpy as np class GeomoptViaPyberny(pp.ModuleBase): - def __init__(self): pp.ModuleBase.__init__(self) - self.satisfies_property_type(TotalEnergy()) + self.satisfies_property_type(TotalEnergyNuclearOptimization()) self.description("Performs PyBerny optimization") self.add_submodule(TotalEnergy(), "Energy") self.add_submodule(EnergyNuclearGradientStdVectorD(), "Gradient") self.add_submodule(MoleculeFromString(), "StringConv") def run_(self, inputs, submods): - pt = TotalEnergy() - mol, = pt.unwrap_inputs(inputs) - molecule = mol.molecule + pt = TotalEnergyNuclearOptimization() + sys, points = pt.unwrap_inputs(inputs) + molecule = sys.molecule # Convert Chemist Chemical System to XYZ xyz = "" - xyz += (str(molecule.size()) + "\n\n") + xyz += str(molecule.size()) + "\n\n" for i in range(molecule.size()): - xyz += (molecule.at(i).name + " " + str(molecule.at(i).x) + " " + - str(molecule.at(i).y) + " " + str(molecule.at(i).z) + "\n") + xyz += ( + molecule.at(i).name + + " " + + str(molecule.at(i).x) + + " " + + str(molecule.at(i).y) + + " " + + str(molecule.at(i).z) + + "\n" + ) # Loads the geometry string into the Berny optimizer # object. - optimizer = Berny(geomlib.loads(xyz, fmt='xyz')) + optimizer = Berny(geomlib.loads(xyz, fmt="xyz")) for geom in optimizer: - # Converts the "Berny" geometry object to Chemical System - geom2xyz = geom.dumps('xyz') - print('Berny Geom to XYZ value: \n' + geom2xyz + '\n') - lines = geom2xyz.split('\n') - print('Lines of geom2xyz: \n' + str(lines) + '\n') - mol_string = '\n'.join(lines[2:]) - print('Lines to string: \n' + mol_string + '\n') + geom2xyz = geom.dumps("xyz") + lines = geom2xyz.split("\n") + mol_string = "\n".join(lines[2:]) xyz2chem_mol = submods["StringConv"].run_as( - MoleculeFromString(), mol_string) - print('String conversion from xyz to chem sys: \n' + - str(xyz2chem_mol.nuclei) + '\n') + MoleculeFromString(), mol_string + ) geom = chemist.ChemicalSystem(xyz2chem_mol) - print('Chemical system of xyz2chem_mol: \n' + - str(geom.molecule.nuclei) + '\n') geom_nuclei = geom.molecule.nuclei.as_nuclei() - geom_points = geom_nuclei.charges.point_set + geom_points = geom_nuclei.charges.point_set.as_point_set() # Main optimizer operation energy = submods["Energy"].run_as(TotalEnergy(), geom) - print('Interim energy: \n' + str(energy) + '\n') gradients = submods["Gradient"].run_as( - EnergyNuclearGradientStdVectorD(), geom, - geom_points.as_point_set()) - print('Interim gradient: \n' + str(gradients) + '\n') + EnergyNuclearGradientStdVectorD(), geom, geom_points + ) optimizer.send((np.array(energy).item(), gradients)) - opt_geom = geom.molecule.nuclei - print( - 'Resulting relaxed geometry (assigned to variable opt_geom): \n' + - str(opt_geom)) + opt_geom = geom.molecule.nuclei.as_nuclei().charges.point_set.as_point_set() # Optimized energy is of type "float" e = energy print(e) rv = self.results() - return pt.wrap_results(rv, e) + return pt.wrap_results(rv, e, opt_geom) def load_pyberny_modules(mm): diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index f7a948b..a9d782d 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -18,11 +18,10 @@ import pluginplay as pp import chemist import unittest -from simde import TotalEnergy +from simde import TotalEnergyNuclearOptimization class Test_optimize_pyberny(unittest.TestCase): - def test_optimize_pyberny(self): mm = pp.ModuleManager() nwchemex.load_modules(mm) @@ -31,10 +30,12 @@ def test_optimize_pyberny(self): mm.change_input("NWChem : SCF Gradient", "basis set", "sto-3g") mm.change_submod("PyBerny", "Gradient", "NWChem : SCF Gradient") mm.change_submod("PyBerny", "Energy", "NWChem : SCF") - mm.change_submod("Pyberny", "StringConv", - "ChemicalSystem via QCElemental") - egy = mm.run_as(TotalEnergy(), "PyBerny", - chemist.ChemicalSystem(self.mol)) + mm.change_submod("Pyberny", "StringConv", "ChemicalSystem via QCElemental") + egy = mm.run_as( + TotalEnergyNuclearOptimization(), + "PyBerny", + chemist.ChemicalSystem(self.mol), + ) print("Energy = " + str(egy)) print(np.array(egy).item()) self.assertAlmostEqual(np.array(egy).item(), -1.117505879316, 10) From 51e72a05b82d6a2ac8857c748226139ea6eeff36 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Wed, 23 Apr 2025 11:47:12 -0500 Subject: [PATCH 2/8] updated pyberny to use TotalEnergyNuclearOptimization property type in simde --- .../structurefinder/pyberny/__init__.py | 5 ++-- .../test_optimizers/test_pybernyop.py | 30 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index 2f881ac..c9e4f06 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -76,12 +76,13 @@ def run_(self, inputs, submods): ) optimizer.send((np.array(energy).item(), gradients)) - opt_geom = geom.molecule.nuclei.as_nuclei().charges.point_set.as_point_set() + opt_geom_nuclei = geom.molecule.nuclei.as_nuclei() + opt_geom_points = opt_geom_nuclei.charges.point_set.as_point_set() # Optimized energy is of type "float" e = energy print(e) rv = self.results() - return pt.wrap_results(rv, e, opt_geom) + return pt.wrap_results(rv, e, opt_geom_points) def load_pyberny_modules(mm): diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index a9d782d..03f71ea 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -26,21 +26,25 @@ def test_optimize_pyberny(self): mm = pp.ModuleManager() nwchemex.load_modules(mm) structurefinder.load_modules(mm) - mm.change_input("NWChem : SCF", "basis set", "sto-3g") - mm.change_input("NWChem : SCF Gradient", "basis set", "sto-3g") - mm.change_submod("PyBerny", "Gradient", "NWChem : SCF Gradient") - mm.change_submod("PyBerny", "Energy", "NWChem : SCF") - mm.change_submod("Pyberny", "StringConv", "ChemicalSystem via QCElemental") - egy = mm.run_as( - TotalEnergyNuclearOptimization(), - "PyBerny", - chemist.ChemicalSystem(self.mol), - ) - print("Energy = " + str(egy)) - print(np.array(egy).item()) - self.assertAlmostEqual(np.array(egy).item(), -1.117505879316, 10) + pyberny_mod = mm.at("PyBerny") + nwchem_scf_mod = mm.at("NWChem : SCF") + nwchem_grad_mod = mm.at("NWChem : SCF Gradient") + string_conv_mod = mm.at("ChemicalSystem via QCElemental") + + nwchem_scf_mod.change_input("basis set", "sto-3g") + nwchem_grad_mod.change_input("basis set", "sto-3g") + pyberny_mod.change_submod("Energy", nwchem_scf_mod) + pyberny_mod.change_submod("Gradient", nwchem_grad_mod) + pyberny_mod.change_submod("StringConv", string_conv_mod) + egy = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), + self.sys, + self.point_set) + self.assertAlmostEqual(np.array(egy[0]).item(), -1.117505879316, 10) def setUp(self): 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, 1.0)) + self.sys = chemist.ChemicalSystem(self.mol) + self.nuclei = self.mol.nuclei.as_nuclei() + self.point_set = self.nuclei.charges.point_set.as_point_set() From bfa96aa55fd644ba8e421163b3c4569093dc059a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 23 Apr 2025 16:50:47 +0000 Subject: [PATCH 3/8] Committing clang-format changes --- .../structurefinder/pyberny/__init__.py | 19 +++++-------------- .../test_optimizers/test_pybernyop.py | 4 ++-- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index c9e4f06..0470270 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -25,6 +25,7 @@ class GeomoptViaPyberny(pp.ModuleBase): + def __init__(self): pp.ModuleBase.__init__(self) self.satisfies_property_type(TotalEnergyNuclearOptimization()) @@ -42,16 +43,8 @@ def run_(self, inputs, submods): xyz = "" xyz += str(molecule.size()) + "\n\n" for i in range(molecule.size()): - xyz += ( - molecule.at(i).name - + " " - + str(molecule.at(i).x) - + " " - + str(molecule.at(i).y) - + " " - + str(molecule.at(i).z) - + "\n" - ) + xyz += (molecule.at(i).name + " " + str(molecule.at(i).x) + " " + + str(molecule.at(i).y) + " " + str(molecule.at(i).z) + "\n") # Loads the geometry string into the Berny optimizer # object. @@ -63,8 +56,7 @@ def run_(self, inputs, submods): lines = geom2xyz.split("\n") mol_string = "\n".join(lines[2:]) xyz2chem_mol = submods["StringConv"].run_as( - MoleculeFromString(), mol_string - ) + MoleculeFromString(), mol_string) geom = chemist.ChemicalSystem(xyz2chem_mol) geom_nuclei = geom.molecule.nuclei.as_nuclei() geom_points = geom_nuclei.charges.point_set.as_point_set() @@ -72,8 +64,7 @@ def run_(self, inputs, submods): # Main optimizer operation energy = submods["Energy"].run_as(TotalEnergy(), geom) gradients = submods["Gradient"].run_as( - EnergyNuclearGradientStdVectorD(), geom, geom_points - ) + EnergyNuclearGradientStdVectorD(), geom, geom_points) optimizer.send((np.array(energy).item(), gradients)) opt_geom_nuclei = geom.molecule.nuclei.as_nuclei() diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index 03f71ea..b48f90b 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -22,6 +22,7 @@ class Test_optimize_pyberny(unittest.TestCase): + def test_optimize_pyberny(self): mm = pp.ModuleManager() nwchemex.load_modules(mm) @@ -36,8 +37,7 @@ def test_optimize_pyberny(self): pyberny_mod.change_submod("Energy", nwchem_scf_mod) pyberny_mod.change_submod("Gradient", nwchem_grad_mod) pyberny_mod.change_submod("StringConv", string_conv_mod) - egy = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), - self.sys, + egy = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), self.sys, self.point_set) self.assertAlmostEqual(np.array(egy[0]).item(), -1.117505879316, 10) From 0e8ef6d3781f8e6695ab162ac850865736b3e090 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Wed, 23 Apr 2025 16:38:30 -0500 Subject: [PATCH 4/8] removed extrandeous print statements --- src/python/structurefinder/pyberny/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index 0470270..3dcd2b7 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -69,11 +69,9 @@ def run_(self, inputs, submods): opt_geom_nuclei = geom.molecule.nuclei.as_nuclei() opt_geom_points = opt_geom_nuclei.charges.point_set.as_point_set() - # Optimized energy is of type "float" - e = energy - print(e) + rv = self.results() - return pt.wrap_results(rv, e, opt_geom_points) + return pt.wrap_results(rv, energy, opt_geom_points) def load_pyberny_modules(mm): From 8d4306b8165c028a1c82800e49a33eabe56ee6c5 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Sun, 4 May 2025 23:02:13 -0500 Subject: [PATCH 5/8] Added point set testing to test --- .../test_optimizers/test_pybernyop.py | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index b48f90b..5d1b7a6 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -20,6 +20,12 @@ import unittest from simde import TotalEnergyNuclearOptimization +def threed_distance(coords): + val = 0 + for i in range(int(len(coords) / 2)): + val += (coords[i] - coords[i + 3]) ** 2 + distance = np.sqrt(val) + return distance class Test_optimize_pyberny(unittest.TestCase): @@ -27,6 +33,7 @@ def test_optimize_pyberny(self): mm = pp.ModuleManager() nwchemex.load_modules(mm) structurefinder.load_modules(mm) + pyberny_mod = mm.at("PyBerny") nwchem_scf_mod = mm.at("NWChem : SCF") nwchem_grad_mod = mm.at("NWChem : SCF Gradient") @@ -37,9 +44,21 @@ def test_optimize_pyberny(self): pyberny_mod.change_submod("Energy", nwchem_scf_mod) pyberny_mod.change_submod("Gradient", nwchem_grad_mod) pyberny_mod.change_submod("StringConv", string_conv_mod) + egy = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), self.sys, - self.point_set) - self.assertAlmostEqual(np.array(egy[0]).item(), -1.117505879316, 10) + self.point_set_i) + + energy = np.array(egy[0]).item() + point_set = egy[1] + coords = [] + for atom in range(point_set.size()): + for coord in range(3): + coords.append(point_set.at(atom).coord(coord)) + + distance = threed_distance(coords) + + self.assertAlmostEqual(energy, self.energy, 10) + self.assertAlmostEqual(distance, self.distance, 8) def setUp(self): self.mol = chemist.Molecule() @@ -47,4 +66,6 @@ def setUp(self): self.mol.push_back(chemist.Atom("H", 1, 1.0079, 0.0, 0.0, 1.0)) self.sys = chemist.ChemicalSystem(self.mol) self.nuclei = self.mol.nuclei.as_nuclei() - self.point_set = self.nuclei.charges.point_set.as_point_set() + self.point_set_i = self.nuclei.charges.point_set.as_point_set() + self.distance = 1.34606231 + self.energy = -1.117505879316 From 3897b97e768b845a8b0c8f63d04ae84f6cab2b83 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 5 May 2025 04:03:41 +0000 Subject: [PATCH 6/8] Committing clang-format changes --- tests/python/unit_tests/test_optimizers/test_pybernyop.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index 5d1b7a6..2350dc7 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -20,13 +20,15 @@ import unittest from simde import TotalEnergyNuclearOptimization + def threed_distance(coords): val = 0 for i in range(int(len(coords) / 2)): - val += (coords[i] - coords[i + 3]) ** 2 + val += (coords[i] - coords[i + 3])**2 distance = np.sqrt(val) return distance + class Test_optimize_pyberny(unittest.TestCase): def test_optimize_pyberny(self): From a30f9a37be1db9623d4923689420b2af185d1984 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Mon, 5 May 2025 11:18:36 -0500 Subject: [PATCH 7/8] made suggested changes to pyberny module and tests --- src/python/structurefinder/pyberny/__init__.py | 8 +++++--- .../unit_tests/test_optimizers/test_pybernyop.py | 13 ++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/python/structurefinder/pyberny/__init__.py b/src/python/structurefinder/pyberny/__init__.py index 3dcd2b7..8cf0ac2 100644 --- a/src/python/structurefinder/pyberny/__init__.py +++ b/src/python/structurefinder/pyberny/__init__.py @@ -42,9 +42,11 @@ def run_(self, inputs, submods): # Convert Chemist Chemical System to XYZ xyz = "" xyz += str(molecule.size()) + "\n\n" - for i in range(molecule.size()): - xyz += (molecule.at(i).name + " " + str(molecule.at(i).x) + " " + - str(molecule.at(i).y) + " " + str(molecule.at(i).z) + "\n") + + #TODO ensure points == molecule.nuclei.charges.point_set + for i in range(points.size()): + xyz += (molecule.at(i).name + " " + str(points.at(i).x) + " " + + str(points.at(i).y) + " " + str(points.at(i).z) + "\n") # Loads the geometry string into the Berny optimizer # object. diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index 5d1b7a6..36317b5 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -20,7 +20,7 @@ import unittest from simde import TotalEnergyNuclearOptimization -def threed_distance(coords): +def diatomic_bond_distance(coords): val = 0 for i in range(int(len(coords) / 2)): val += (coords[i] - coords[i + 3]) ** 2 @@ -45,18 +45,17 @@ def test_optimize_pyberny(self): pyberny_mod.change_submod("Gradient", nwchem_grad_mod) pyberny_mod.change_submod("StringConv", string_conv_mod) - egy = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), self.sys, + energy, points = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), self.sys, self.point_set_i) - energy = np.array(egy[0]).item() - point_set = egy[1] coords = [] - for atom in range(point_set.size()): + for atom in range(points.size()): for coord in range(3): - coords.append(point_set.at(atom).coord(coord)) + coords.append(points.at(atom).coord(coord)) - distance = threed_distance(coords) + distance = diatomic_bond_distance(coords) + energy = np.array(energy).item() self.assertAlmostEqual(energy, self.energy, 10) self.assertAlmostEqual(distance, self.distance, 8) From 259229b56ec4597a24c132bdff47b099d9d50794 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 5 May 2025 16:23:06 +0000 Subject: [PATCH 8/8] Committing clang-format changes --- tests/python/unit_tests/test_optimizers/test_pybernyop.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/python/unit_tests/test_optimizers/test_pybernyop.py b/tests/python/unit_tests/test_optimizers/test_pybernyop.py index bb1ba2e..22da6c0 100644 --- a/tests/python/unit_tests/test_optimizers/test_pybernyop.py +++ b/tests/python/unit_tests/test_optimizers/test_pybernyop.py @@ -20,6 +20,7 @@ import unittest from simde import TotalEnergyNuclearOptimization + def diatomic_bond_distance(coords): val = 0 for i in range(int(len(coords) / 2)): @@ -46,8 +47,8 @@ def test_optimize_pyberny(self): pyberny_mod.change_submod("Gradient", nwchem_grad_mod) pyberny_mod.change_submod("StringConv", string_conv_mod) - energy, points = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), self.sys, - self.point_set_i) + energy, points = pyberny_mod.run_as(TotalEnergyNuclearOptimization(), + self.sys, self.point_set_i) coords = [] for atom in range(points.size()):