def test_0_constructor(self): # Test what the setup constructed self.assertEqual(len(self.empty.atom_numbers), 0) self.assertEqual(len(self.empty.coords), 0) self.assertEqual(self.empty.n_alpha, 0) self.assertEqual(self.empty.n_beta, 0) self.assertListEqual(self.water.atom_numbers.tolist(), [1, 8, 1]) self.assertListEqual(self.water.coords[0].tolist(), [0, 0, 1]) self.assertListEqual(self.water.coords[1].tolist(), [0, 0, 0]) self.assertListEqual(self.water.coords[2].tolist(), [1, 0, 0]) self.assertEqual(self.water.n_alpha, 5) self.assertEqual(self.water.n_beta, 5) self.assertListEqual(self.water_triplet.atom_numbers.tolist(), [1, 8, 1]) self.assertListEqual(self.water_triplet.coords[0].tolist(), [0, 0, 1]) self.assertListEqual(self.water_triplet.coords[1].tolist(), [0, 0, 0]) self.assertListEqual(self.water_triplet.coords[2].tolist(), [1, 0, 0]) self.assertEqual(self.water_triplet.n_alpha, 6) self.assertEqual(self.water_triplet.n_beta, 4) self.assertListEqual(self.no.atom_numbers.tolist(), [7, 8]) self.assertListEqual(self.no.coords[0].tolist(), [0, 0, 0]) self.assertListEqual(self.no.coords[1].tolist(), [1, 0, 0]) self.assertEqual(self.no.n_alpha, 8) self.assertEqual(self.no.n_beta, 7) self.assertListEqual(self.oxide.atom_numbers.tolist(), [8]) self.assertListEqual(self.oxide.coords[0].tolist(), [0, 0, 0]) self.assertEqual(self.oxide.n_alpha, 5) self.assertEqual(self.oxide.n_beta, 5) # Construction from atom names and atom numbers wat = molsturm.System(["hydrogen", "O", 1], [[0, 0, 1], [0, 0, 0], [1, 0, 0]]) self.assertListEqual(wat.atom_numbers.tolist(), [1, 8, 1]) self.assertListEqual(wat.coords[0].tolist(), [0, 0, 1]) self.assertListEqual(wat.coords[1].tolist(), [0, 0, 0]) self.assertListEqual(wat.coords[2].tolist(), [1, 0, 0]) self.assertEqual(wat.n_alpha, 5) self.assertEqual(wat.n_beta, 5) # Try to get a triplet oxygen wrongly with self.assertRaises(ValueError): molsturm.System(["O"], [0, 0, 0], (3, 5)) # Missing the coord is ok if only a single atom ox = molsturm.System(["O"]) self.assertListEqual(ox.coords[0].tolist(), [0, 0, 0]) self.assertListEqual(self.oxide.atom_numbers.tolist(), [8]) # But not if two or more with self.assertRaises(ValueError): molsturm.System(["O", "O"]) # May miss the liss for one atom: ox = molsturm.System("O") self.assertListEqual(ox.coords[0].tolist(), [0, 0, 0]) self.assertListEqual(self.oxide.atom_numbers.tolist(), [8])
def setUpClass(cls): water_atoms = ["H", "O", "H"] water_coords = [[0, 0, 1], [0, 0, 0], [1, 0, 0]] no_atoms = ["N", "O"] no_coords = [[0, 0, 0], [1, 0, 0]] cls.empty = molsturm.System() cls.water = molsturm.System(water_atoms, water_coords) cls.water_triplet = molsturm.System(water_atoms, water_coords, (6, 4)) cls.no = molsturm.System(no_atoms, no_coords) cls.oxide = molsturm.System(["O"], [[0, 0, 0]], (5, 5))
def run_hf(xyz, basis, charge=0, multiplicity=1, conv_tol=1e-12, conv_tol_grad=1e-8, max_iter=150): import molsturm # Quick-and-dirty xyz parser: geom = xyz.split() n_atom = len(geom) // 4 assert n_atom * 4 == len(geom) atoms = [geom[i * 4] for i in range(n_atom)] coords = [[ float(geom[i * 4 + 1]), float(geom[i * 4 + 2]), float(geom[i * 4 + 3]) ] for i in range(n_atom)] mol = molsturm.System(atoms, coords) mol.charge = charge mol.multiplicity = multiplicity return molsturm.hartree_fock(mol, basis_type="gaussian", basis_set_name=basis_remap.get(basis, basis), conv_tol=conv_tol_grad, max_iter=max_iter)
def dump_integrals_gaussian(atoms, coords, electrons, basis_set_name, ifile=None): system = molsturm.System(atoms, coords, electrons) params = molsturm.ScfParameters() params.system = system params.basis = molsturm.construct_basis("gaussian", params.system, basis_set_name=basis_set_name) if ifile is None: latoms = [a.lower() for a in atoms] ifile = "integrals_{}_{}.hdf5".format("".join(latoms), basis_set_name) with h5py.File(ifile, "w") as h5f: write_integrals_to_hdf5(params, h5f) g_discr = h5f.create_group("discretisation") g_discr.create_dataset("basis_type", data="gaussian", dtype=h5py.special_dtype(vlen=str)) g_discr.create_dataset("basis_set_name", dtype=h5py.special_dtype(vlen=str), data=basis_set_name) g_discr.create_dataset("has_real_harmonics", data=1, dtype=np.uint8)
def test_2_n_electrons_setter(self): oxy = molsturm.System("O") self.assertEqual(oxy.charge, 0) self.assertEqual(oxy.multiplicity, 1) oxy.n_electrons += 2 self.assertEqual(oxy.charge, -2) self.assertEqual(oxy.multiplicity, 1) oxy = molsturm.System("O", electrons=(5, 3)) self.assertEqual(oxy.charge, 0) self.assertEqual(oxy.multiplicity, 3) oxy.n_electrons += 2 self.assertEqual(oxy.charge, -2) self.assertEqual(oxy.multiplicity, 3) oxy.n_electrons = 9 self.assertEqual(oxy.charge, -1) self.assertEqual(oxy.multiplicity, 2)
def test_2_multiplicity_setter(self): oxy = molsturm.System("O") self.assertEqual(oxy.charge, 0) self.assertEqual(oxy.multiplicity, 1) oxy.multiplicity = 3 self.assertEqual(oxy.charge, 0) self.assertEqual(oxy.multiplicity, 3) with self.assertRaises(ValueError): oxy.multiplicity = 2
def main(): carbon = molsturm.System("c") carbon.multiplicity = 3 params = molsturm.ScfParameters() params.system = carbon params.basis = molsturm.construct_basis("sturmian/atomic/cs_reference_pc", params.system, k_exp=3.3, n_max=4, l_max=3) params["scf/eigensolver/method"] = "lapack" params["scf/print_iterations"] = True params["guess/eigensolver/method"] = "lapack" res = molsturm.self_consistent_field(params) molsturm.print_convergence_summary(res) molsturm.print_energies(res) molsturm.print_mo_occupation(res) molsturm.print_quote(res) return res
def dump_integrals_sturmian(atoms, coords, electrons, k_exp, n_max, l_max, m_max, ifile=None): system = molsturm.System(atoms, coords, electrons) params = molsturm.ScfParameters() params.system = system basis = molsturm.construct_basis("sturmian/atomic", params.system, k_exp=k_exp, n_max=n_max, l_max=l_max, m_max=m_max) basis.backend = "cs_reference" params.basis = basis if ifile is None: latoms = [a.lower() for a in atoms] ifile = ("integrals_{}_{:02d}{:02d}{:02d}_{:.4f}.hdf5" "".format("".join(latoms), n_max, l_max, m_max, k_exp)) with h5py.File(ifile, "w") as h5f: write_integrals_to_hdf5(params, h5f) g_discr = h5f.create_group("discretisation") g_discr.create_dataset("basis_type", data="sturmian/atomic", dtype=h5py.special_dtype(vlen=str)) g_discr.create_dataset("nlm_basis", data=basis.functions) g_discr.create_dataset("k_exp", data=k_exp) g_discr.create_dataset("n_max", data=n_max) g_discr.create_dataset("l_max", data=l_max) g_discr.create_dataset("m_max", data=m_max) g_discr.create_dataset("has_real_harmonics", data=basis.has_real_harmonics, dtype=np.uint8)
## ## molsturm is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with molsturm. If not, see <http://www.gnu.org/licenses/>. ## ## --------------------------------------------------------------------- ## vi: tabstop=2 shiftwidth=2 softtabstop=2 expandtab import molsturm import molsturm.posthf sys = molsturm.System(["beryllium"], [[0, 0, 0]]) bas = molsturm.construct_basis("sturmian/atomic", sys, k_exp=2.1, n_max=11, l_max=0, backend="cs_reference_pc") res = molsturm.hartree_fock(sys, bas, conv_tol=1e-10, print_iterations=True) molsturm.print_convergence_summary(res) molsturm.print_energies(res) molsturm.print_mo_occupation(res) print() res_adc = molsturm.posthf.mp2(res) print("MP2 energy", res_adc["energy_mp2"])
residual = ccd_residual(t2, state.fock, eri_asym) residual_norm = np.max(np.max(residual)) print(fmt.format(n_iter, corr, residual_norm)) # Quasi-Newton update step n_iter += 1 t2 -= residual / ccd_approx_jacobian(t2, state.fock, eri_asym) if n_iter > 100: raise RuntimeError("CCD not converged after 100 iterations.") return corr, t2 if __name__ == "__main__": sys = molsturm.System( atoms=["O", "O"], coords=[(0, 0, 0), (0, 0, 2.8535)], ) sys.multiplicity = 3 state = molsturm.hartree_fock(sys, basis_type="gaussian", basis_set_name="6-31g", conv_tol=5e-7) corr, t2 = ccd(state) maxamp = np.max(np.abs(t2)) print("CCD correlation energy: ", corr) print("Largest t2 amplitude: ", maxamp) print() hf = state.energy_ground_state print("HF energy: ", hf) print("CCD total energy: ", corr + hf)
#!/usr/bin/env python3 ## vi: tabstop=4 shiftwidth=4 softtabstop=4 expandtab import adcc import molsturm # Run SCF in molsturm atoms = ["O", "H", "H"] coords = [[0, 0, 0], [0, 0, 1.795239827225189], [1.693194615993441, 0, -0.599043184453037]] system = molsturm.System(atoms, coords) hfres = molsturm.hartree_fock(system, basis_type="gaussian", basis_set_name="sto-3g", conv_tol=1e-12, print_iterations=True) # Run an adc2 calculation: singlets = adcc.adc2(hfres, n_singlets=5, conv_tol=1e-9) triplets = adcc.adc2(singlets.matrix, n_triplets=3, conv_tol=1e-9) print(singlets.describe()) print(triplets.describe())
def test_2_adjust_electrons(self): oxy = molsturm.System("O") self.assertEqual(oxy.n_alpha, 4) self.assertEqual(oxy.n_beta, 4) self.assertEqual(oxy.multiplicity, 1) self.assertEqual(oxy.charge, 0) # Adjust multiplicity to make triplet oxy.adjust_electrons(multiplicity=3) self.assertEqual(oxy.n_alpha, 5) self.assertEqual(oxy.n_beta, 3) self.assertEqual(oxy.multiplicity, 3) self.assertEqual(oxy.charge, 0) # Adjust electrons to make doublet O^- oxy.adjust_electrons(charge=-1) self.assertEqual(oxy.n_alpha, 5) self.assertEqual(oxy.n_beta, 4) self.assertEqual(oxy.multiplicity, 2) self.assertEqual(oxy.charge, -1) # Adjust electrons to make quartet O^- oxy.adjust_electrons(multiplicity=4) self.assertEqual(oxy.n_alpha, 6) self.assertEqual(oxy.n_beta, 3) self.assertEqual(oxy.multiplicity, 4) self.assertEqual(oxy.charge, -1) # And go back to triplet oxygen oxy.adjust_electrons(charge=0, multiplicity=3) self.assertEqual(oxy.n_alpha, 5) self.assertEqual(oxy.n_beta, 3) self.assertEqual(oxy.multiplicity, 3) self.assertEqual(oxy.charge, 0) # Strip off all electrons: oxy.adjust_electrons(charge=8) self.assertEqual(oxy.n_alpha, 0) self.assertEqual(oxy.n_beta, 0) # Too large charge with self.assertRaises(ValueError): oxy.adjust_electrons(charge=9) # Invalid multiplicity number with self.assertRaises(ValueError): oxy.adjust_electrons(charge=0, multiplicity=2) with self.assertRaises(ValueError): oxy.adjust_electrons(charge=1, multiplicity=3) # All electrons in alpha: oxy.adjust_electrons(charge=0, multiplicity=9) self.assertEqual(oxy.n_alpha, 8) self.assertEqual(oxy.n_beta, 0) # Request larger multiplicity with self.assertRaises(ValueError): oxy.adjust_electrons(charge=0, multiplicity=11) # Change from triplet oxygen to triplet O^{2+} oxy.adjust_electrons(charge=0, multiplicity=3) oxy.adjust_electrons(charge=2) self.assertEqual(oxy.n_alpha, 4) self.assertEqual(oxy.n_beta, 2) self.assertEqual(oxy.multiplicity, 3) self.assertEqual(oxy.charge, 2)
## it under the terms of the GNU General Public License as published ## by the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## molsturm is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with molsturm. If not, see <http://www.gnu.org/licenses/>. ## ## --------------------------------------------------------------------- ## vi: tabstop=2 shiftwidth=2 softtabstop=2 expandtab import molsturm import molsturm.posthf sys = molsturm.System([4], [[0, 0, 0]]) res = molsturm.hartree_fock(sys, basis_type="gaussian", basis_set_name="cc-pvdz", print_iterations=True, conv_tol=1e-10) molsturm.print_convergence_summary(res) molsturm.print_energies(res) molsturm.print_mo_occupation(res) res_adc = molsturm.posthf.mp2(res) print("MP2 energy", res_adc["energy_mp2"]) print("tot energy", res_adc["energy_ground_state"]) molsturm.print_quote(res)
import h5py import sys import numpy as np if len(sys.argv) != 2: raise SystemExit("Need hdf5 integrals file as first arg.") ifile = sys.argv[1] with h5py.File(ifile, "r") as h5f: nelec = list(h5f["system/nelec"]) atom_numbers = np.array(h5f["system/atom_numbers"]) coords = np.array(h5f["system/coords"]) system = molsturm.System( atoms=atom_numbers, coords=coords, electrons=nelec, ) params = molsturm.ScfParameters() params.system = system basis_type = str(h5f["discretisation/basis_type"].value) if basis_type == "gaussian": bas = str(h5f["discretisation/basis_set_name"].value) params.basis = molsturm.construct_basis("gaussian", params.system, basis_set_name=bas) elif basis_type == "sturmian/atomic": k_exp = float(h5f["discretisation/k_exp"].value) n_max = int(h5f["discretisation/n_max"].value) l_max = int(h5f["discretisation/l_max"].value)
#!/usr/bin/env python3 import molsturm from molsturm import integrals from scipy import linalg import numpy as np params = molsturm.ScfParameters() # Supply molecular structure atoms = ["Be"] # as a list of names, symbols, atom numbers ... positions = [[0, 0, 0]] # as a list of triples x,y,z system = molsturm.System(atoms, positions) system.charge = 0 # Optional, 0 by default system.multiplicity = 1 # Optional, 1 by default for even-electron systems, # 2 for odd-electron systems params.system = system # Supply basis set information basis = molsturm.construct_basis("gaussian", system, basis_set_name="pc-3") # basis = molsturm.construct_basis("sturmian/atomic", system, k_exp=1.988, # n_max=5, l_max=1, m_max=1) params.basis = basis # Compute integral data print("Computing integrals ... ", end="", flush=True) s_bb = integrals.overlap_bb(params) t_bb = integrals.kinetic_bb(params) v_bb = integrals.nuclear_attraction_bb(params) eri_bbbb = integrals.electron_repulsion_bbbb(params) print("done")
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with molsturm. If not, see <http://www.gnu.org/licenses/>. ## ## --------------------------------------------------------------------- import molsturm import molsturm.sturmian l_max = 1 n_max = 5 for atom, mult in [("He", 1), ("Be", 1), ("C", 3), ("Ne", 1)]: system = molsturm.System(atom) system.multiplicity = mult scfparams = molsturm.ScfParameters() scfparams.system = system k_guess = molsturm.sturmian.cs.empirical_kopt(scfparams.system) scfparams.basis = molsturm.construct_basis("sturmian/atomic/cs_reference_pc", scfparams.system, k_exp=k_guess, n_max=n_max, l_max=l_max) scfparams["scf/eigensolver/method"] = "lapack" scfparams["guess/eigensolver/method"] = "lapack" print("Running for " + atom + " please wait") best = molsturm.sturmian.cs.find_kopt(scfparams, print_iterations=True)