From cea06dabf8ea6fc2a10804f59ee48b8548abd18b Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 16:41:47 +0100 Subject: [PATCH 01/13] Serenity interface python code and examples --- .../C2H4.xyz | 8 + .../C2H4_CCSD.py | 34 ++++ .../SerenityAMS_DataTransfer_examples/HF.xyz | 4 + .../HF_CCSD_T.py | 34 ++++ .../SerenityAMS_DataTransfer_examples/N2.xyz | 4 + .../N2_CCSD.py | 34 ++++ examples/SerenityCalculator/example.py | 35 ++++ examples/SerenityCalculator/my_calculator.py | 15 ++ .../SerenityInterface_examples/dft_res.py | 31 +++ examples/SerenityInterface_examples/fde.py | 29 +++ .../gly-gly-gly.xyz | 26 +++ examples/SerenityInterface_examples/hf_res.py | 25 +++ .../SerenityInterface_examples/hf_unres.py | 20 ++ .../localization.py | 22 +++ .../methylRadical.xyz | 6 + examples/SerenityInterface_examples/mp2.py | 19 ++ .../SerenityInterface_examples/riboflavin.xyz | 49 +++++ interfaces/thirdparty/serenity.py | 185 ++++++++++++++++++ interfaces/thirdparty/serenity_calculator.py | 30 +++ 19 files changed, 610 insertions(+) create mode 100644 examples/SerenityAMS_DataTransfer_examples/C2H4.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py create mode 100644 examples/SerenityAMS_DataTransfer_examples/HF.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py create mode 100644 examples/SerenityAMS_DataTransfer_examples/N2.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py create mode 100644 examples/SerenityCalculator/example.py create mode 100644 examples/SerenityCalculator/my_calculator.py create mode 100644 examples/SerenityInterface_examples/dft_res.py create mode 100644 examples/SerenityInterface_examples/fde.py create mode 100644 examples/SerenityInterface_examples/gly-gly-gly.xyz create mode 100644 examples/SerenityInterface_examples/hf_res.py create mode 100644 examples/SerenityInterface_examples/hf_unres.py create mode 100644 examples/SerenityInterface_examples/localization.py create mode 100644 examples/SerenityInterface_examples/methylRadical.xyz create mode 100644 examples/SerenityInterface_examples/mp2.py create mode 100644 examples/SerenityInterface_examples/riboflavin.xyz create mode 100644 interfaces/thirdparty/serenity.py create mode 100644 interfaces/thirdparty/serenity_calculator.py diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz b/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz new file mode 100644 index 000000000..9bf655c1e --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz @@ -0,0 +1,8 @@ +6 +Ethene + H 1.1610 0.0661 1.0238 + C 0.6579 -0.0045 0.0639 + H 1.3352 -0.0830 -0.7815 + C -0.6579 0.0045 -0.0639 + H -1.3355 0.0830 0.7812 + H -1.1608 -0.0661 -1.0239 diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py new file mode 100644 index 000000000..2b597164f --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_C2H4_DZ') + +mol = Molecule('C2H4.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'DZ' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_C2H4_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.C2H4.geometry = 'C2H4.xyz' + +sersett.input.task.CC.system = 'C2H4' +sersett.input.task.CC.level = 'CCSD' + +serjob = SerenityJob(settings=sersett, name='Serenity_C2H4_CCSD') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/HF.xyz b/examples/SerenityAMS_DataTransfer_examples/HF.xyz new file mode 100644 index 000000000..b4bf470e2 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/HF.xyz @@ -0,0 +1,4 @@ +2 + + F 0.91860 0.00000 500.00000 + H 0.00000 0.00000 500.00000 diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py new file mode 100644 index 000000000..885ea46cd --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_T_HF_TZP') + +mol = Molecule('HF.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'TZP' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_HF_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.HF.geometry = 'HF.xyz' + +sersett.input.task.CC.system = 'HF' +sersett.input.task.CC.level = 'CCSD(T)' + +serjob = SerenityJob(settings=sersett, name='Serenity_HF_CCSD_T') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/N2.xyz b/examples/SerenityAMS_DataTransfer_examples/N2.xyz new file mode 100644 index 000000000..525276476 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/N2.xyz @@ -0,0 +1,4 @@ +2 +nitrogen + N 0.000000 0.000000 0.000000 + N 1.097600 0.000000 0.000000 diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py new file mode 100644 index 000000000..ac96ef2d8 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_N2_DZ') + +mol = Molecule('N2.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'DZ' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_N2_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.N2.geometry = 'N2.xyz' + +sersett.input.task.CC.system = 'N2' +sersett.input.task.CC.level = 'CCSD' + +serjob = SerenityJob(settings=sersett, name='Serenity_N2_CCSD') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py new file mode 100644 index 000000000..1f53d16af --- /dev/null +++ b/examples/SerenityCalculator/example.py @@ -0,0 +1,35 @@ +from scm.plams import * +import os +init() + +molecule = from_smiles("[HH]") + +# first do a pesscan with pure AMS +s = Settings() +s.input.ams.Task = "PESScan" +s.input.ams.PESScan.ScanCoordinate.nPoints = 5 +s.input.ams.PESScan.ScanCoordinate.Distance = '1 2 0.65 0.8' +s.input.ForceField.Type = "UFF" +psjob = AMSJob(settings=s, molecule=molecule, name="ams_pesscan") +psjob.run() + +# then run a replay with the serenity calculator + +s = Settings() +s.input.ams.Task = "Replay" +s.input.ams.Replay.File = psjob.results.rkfpath() +s.input.ASE.File = os.path.abspath("my_calculator.py") + +job = AMSJob(settings=s, molecule=molecule, name="serenity_replay") +job.run() + +errormsg = job.get_errormsg() +if errormsg: + log(errormsg) + +replayresults = job.results.get_pesscan_results() +log(replayresults) + + + +finish() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py new file mode 100644 index 000000000..a14696271 --- /dev/null +++ b/examples/SerenityCalculator/my_calculator.py @@ -0,0 +1,15 @@ +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings +from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator +import os + +def get_calculator() -> SerenityCalculator: + s = SerenitySettings() + s.input.system.A.charge = '0' + s.input.system.A.spin = '0' + s.input.system.A.method = 'HF' + s.input.system.A.basis.label = '6-31GS' + s.input.task.SCF.act = 'A' + + calc = SerenityCalculator(settings=s) + return calc + diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py new file mode 100644 index 000000000..5ff2189ba --- /dev/null +++ b/examples/SerenityInterface_examples/dft_res.py @@ -0,0 +1,31 @@ +from scm.plams import * +init(folder='test_riboflavin') + +#instead of giving the geometry key and the file as value you can also do: +#Riboflavin = Molecule() +#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) +#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) +#Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) +#... +#name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job +#serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') + + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' +#The electronic structure method +sersett.input.system.Riboflavin.method = 'DFT' +sersett.input.system.Riboflavin.basis.label = '6-31GS' +#Settings used for the DFT calculation. +sersett.input.system.Riboflavin.dft.functional = 'PBE' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'Riboflavin' +#Every task in Serenity has a print-level which can be tuned to +#adjust the amount of output generated. +sersett.input.task.SCF.printLevel = 'normal' + +serjob = SerenityJob(settings=sersett, name='Serenity_Riboflavin') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py new file mode 100644 index 000000000..b96d9196a --- /dev/null +++ b/examples/SerenityInterface_examples/fde.py @@ -0,0 +1,29 @@ +from scm.plams import * +init(folder='test') + +mol1 = Molecule() +mol1.add_atom(Atom(symbol='O', coords=(0,0,0))) +mol1.add_atom(Atom(symbol='H', coords=(0.758602,0,0.504284))) +mol1.add_atom(Atom(symbol='H', coords=(0.260455,0,-0.872893))) + +mol2 = Molecule() +mol2.add_atom(Atom(symbol='O', coords=(3,0.5,0))) +mol2.add_atom(Atom(symbol='H', coords=(3.758602,0.5,0.504284))) +mol2.add_atom(Atom(symbol='H', coords=(3.260455,0.5,-0.872893))) + +sersett = SerenitySettings() +sersett.input.system.water1.method = 'dft' +sersett.input.system.water1.dft.functional = 'pw91' + +sersett.input.system.water2.method = 'dft' +sersett.input.system.water2.dft.functional = 'pw91' + +sersett.input.task.fde.act = 'water1' +sersett.input.task.fde.env = 'water2' +sersett.input.task.fde.emb.naddxcfunc = 'pw91' +sersett.input.task.fde.emb.naddkinfunc = 'pw91k' +#when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry +serjob = SerenityJob(molecule={"water1":mol1, "water2":mol2}, settings=sersett, name='water_dimer') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/gly-gly-gly.xyz b/examples/SerenityInterface_examples/gly-gly-gly.xyz new file mode 100644 index 000000000..c339103f2 --- /dev/null +++ b/examples/SerenityInterface_examples/gly-gly-gly.xyz @@ -0,0 +1,26 @@ +24 +gly-gly-gly.out Energy: -174.7655800 +N -2.04230 -2.89390 2.81300 +H -1.13560 -3.27750 2.63740 +C -2.02210 -1.44800 2.54880 +H -2.71180 -3.33290 2.21390 +C -1.63580 -1.20010 1.07880 +H -2.99220 -1.03750 2.73680 +H -1.30570 -0.97820 3.18990 +O -0.88210 -2.01130 0.48090 +N -2.14750 -0.01590 0.37400 +H -2.23950 -0.22170 -0.60020 +C -1.21100 1.10310 0.55210 +C -1.74710 2.34360 -0.18620 +H -1.11250 1.32330 1.59460 +H -0.25520 0.83540 0.15230 +O -2.98730 2.50950 -0.31940 +N -0.80990 3.33410 -0.73540 +H 0.01930 3.35400 -0.17680 +C -1.43940 4.66250 -0.72550 +C -0.45770 5.70010 -1.30080 +H -2.32670 4.64120 -1.32320 +H -1.69250 4.92970 0.27920 +O 0.82490 5.52860 -1.16310 +O -0.91070 6.74840 -1.92470 +H -0.29860 7.39520 -2.28340 diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py new file mode 100644 index 000000000..3fec330f4 --- /dev/null +++ b/examples/SerenityInterface_examples/hf_res.py @@ -0,0 +1,25 @@ +from scm.plams import * +init(folder='test_gly-gly-gly') + +#instead of giving the geometry key you can also do: +#mol = Molecule('gly-gly-gly.xyz') +#serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +#the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name + + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' +#You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = '0' +sersett.input.system.gly_gly_gly.spin = '0' +#The electronic structure method +sersett.input.system.gly_gly_gly.method = 'HF' +sersett.input.system.gly_gly_gly.basis.label = '6-31GS' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'gly_gly_gly' + +serjob = SerenityJob(settings=sersett, name='Serenity_gly-gly-gly') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py new file mode 100644 index 000000000..d59761f3f --- /dev/null +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -0,0 +1,20 @@ +from scm.plams import * +init(folder='test_methylradical') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.MethylRadical.geometry = 'methylRadical.xyz' +#You can define the excess number of alpha electrons here +sersett.input.system.MethylRadical.spin = '1' +#This means that we allow singly occupied orbitals which leads to different +#spatial-orbitals for alpha and beta electrons. +#Serenity will choose this automatically as soon as spin != 0. +sersett.input.system.MethylRadical.scfMode = 'UNRESTRICTED' +sersett.input.system.MethylRadical.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'MethylRadical' + +serjob = SerenityJob(settings=sersett, name='Serenity_methylradical') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py new file mode 100644 index 000000000..ab9448876 --- /dev/null +++ b/examples/SerenityInterface_examples/localization.py @@ -0,0 +1,22 @@ +from scm.plams import * +init(folder='test_localization') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' +sersett.input.system.Riboflavin.method = 'DFT' +sersett.input.system.Riboflavin.dft.functional = 'PBE' +sersett.input.system.Riboflavin.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'Riboflavin' +#Localize the orbtials +sersett.input.task.loc.act = 'Riboflavin' +sersett.input.task.loc.locType = 'IBO' +#Print the orbitals to file +sersett.input.task.cube.act = 'Riboflavin' +sersett.input.task.cube.occOrbitals = 'true' + +serjob = SerenityJob(settings=sersett, name='Serenity_localization') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/methylRadical.xyz b/examples/SerenityInterface_examples/methylRadical.xyz new file mode 100644 index 000000000..a8b3556d6 --- /dev/null +++ b/examples/SerenityInterface_examples/methylRadical.xyz @@ -0,0 +1,6 @@ +4 +ID: 1554368615348329383 +C -4.551405 2.815581 -0.046505 +H -3.534208 3.169619 0.019728 +H -5.061105 2.467877 0.839038 +H -5.061061 2.812282 -0.998071 diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py new file mode 100644 index 000000000..7bbbb76bc --- /dev/null +++ b/examples/SerenityInterface_examples/mp2.py @@ -0,0 +1,19 @@ +from scm.plams import * +init(folder='test_mp2') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' +sersett.input.system.gly_gly_gly.method = 'HF' +sersett.input.system.gly_gly_gly.charge = '0' +sersett.input.system.gly_gly_gly.spin = '0' +sersett.input.system.gly_gly_gly.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'gly_gly_gly' +#Localize the orbtials +sersett.input.task.MP2.act = 'gly_gly_gly' + +serjob = SerenityJob(settings=sersett, name='Serenity_mp2') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/riboflavin.xyz b/examples/SerenityInterface_examples/riboflavin.xyz new file mode 100644 index 000000000..1b9c20368 --- /dev/null +++ b/examples/SerenityInterface_examples/riboflavin.xyz @@ -0,0 +1,49 @@ +47 + + C -2.335 1.498 5.390 + C -2.573 0.058 4.841 + C -3.154 0.011 3.393 + H -3.030 -1.024 3.026 + C -4.675 0.327 3.240 + H -4.908 1.357 3.541 + C -5.105 0.213 1.754 + H -4.534 0.924 1.133 + H -4.917 -0.811 1.390 + O -6.509 0.511 1.658 + H -6.838 0.455 0.766 + O -5.517 -0.583 3.973 + H -5.456 -0.489 4.917 + O -2.408 0.897 2.540 + H -1.479 0.691 2.518 + H -3.222 -0.530 5.505 + O -1.304 -0.625 4.790 + H -0.882 -0.701 5.640 + H -1.926 1.471 6.411 + H -1.510 1.913 4.791 + N -3.532 2.354 5.356 + C -4.597 2.143 6.189 + C -4.605 1.191 7.220 + C -5.761 0.911 7.962 + C -6.942 1.619 7.705 + C -6.918 2.647 6.758 + H -7.801 3.252 6.581 + C -5.759 2.911 6.026 + N -5.767 3.928 5.145 + C -4.777 4.187 4.398 + C -4.784 5.293 3.434 + O -5.764 6.017 3.365 + N -3.692 5.455 2.656 + H -3.687 6.203 1.988 + C -2.607 4.647 2.741 + O -1.641 4.821 2.015 + N -2.581 3.637 3.637 + C -3.583 3.342 4.492 + C -8.252 1.291 8.437 + H -8.412 0.203 8.474 + H -9.121 1.739 7.932 + H -8.204 1.687 9.462 + C -5.721 -0.170 9.055 + H -4.692 -0.438 9.336 + H -6.225 -1.074 8.683 + H -6.231 0.182 9.964 + H -3.711 0.642 7.480 diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py new file mode 100644 index 000000000..32513a0b9 --- /dev/null +++ b/interfaces/thirdparty/serenity.py @@ -0,0 +1,185 @@ +from scm.plams.core.basejob import SingleJob +from scm.plams.core.results import Results +from scm.plams.core.settings import Settings +from scm.plams.mol.molecule import Molecule +from scm.plams.tools.units import Units + +from pathlib import Path +import numpy as np +import h5py +import shutil +import os + +__all__ = ['SerenityJob', 'SerenityResults', 'SerenitySettings'] + + +class SerenitySettings(Settings): + """A Subclass of the Settings class to set the iteration order through keys.""" + + def __iter__(self): + """Iteration through keys follows insertion order instead of lexicographical order.""" + return iter(self.keys()) + + +class SerenityResults(Results): + """A Subclass of the Results class to access the results given in the Serenity output. Can be extended as required.""" + + def _get_energy_type(self, search='Total Energy', index=-1, unit='a.u.'): + + s = self.grep_output(search) + s = [ item for item in s if not '...' in item ] + s = s[index] + def convert_with_fallback(item): + try: + return float(item.split()[-1]) + except ValueError: + try: + return float(item.split()[-2]) + except ValueError: + raise ValueError("Can not convert type to float.") + + if not isinstance(index, slice): + return Units.convert(convert_with_fallback(s), 'a.u.', unit) + else: + return [Units.convert(convert_with_fallback(x), 'a.u.', unit) for x in s] + + def get_energy(self, index=-1, unit='a.u.'): + """Returns 'Total Energy (DFT)/(HF):' from the output file. Set ``index`` to choose the n-th occurence of the total energy in the output. Defaults to the last occurence.""" + return self._get_energy_type('Total Energy', index=index, unit=unit) + + def get_ccsd_energy_correction(self, index=-1, unit='a.u.'): + """Returns the 'CCSD Energy Correction' from the output file. Set ``index`` to choose the n-th occurrence of the CCSD energy correction in the output. Defaults to the last occurrence.""" + return self._get_energy_type('CCSD Energy Correction', index=index, unit=unit) + + def get_triples_energy_correction(self, index=-1, unit='a.u.'): + return self._get_energy_type('Triples Energy Correction', index=index, unit=unit) + + def get_local_ccsd_energy(self, index=-1, unit='a.u.'): + return self._get_energy_type('Total Local-CCSD Energy', index=index, unit=unit) + + +class SerenityJob(SingleJob): + """A Subclass of the SingleJob class representing a computational job with Serenity.""" + + _result_type = SerenityResults + + def _get_ready(self): + """If molecule is defined, xyz files are generated accordingly. If there is data to transfer between ADF and Serenity, file formats are converted.""" + SingleJob._get_ready(self) + if isinstance(self.molecule, dict): + for name, mol in self.molecule.items(): + mol.write(os.path.join(self.path, f"{name}.xyz")) + elif isinstance(self.molecule, Molecule): + self.molecule.write(os.path.join(self.path, "mol.xyz")) + + base_path = Path(self.path).parent + ams_job_dirs = [d for d in base_path.iterdir() if d.is_dir() and any(f.startswith('SerenityAMS') for f in os.listdir(d))] + + if ams_job_dirs: + self._translate_AMSJob_to_Serenity(ams_job_dirs[0]) # Processes the first matching directory + return + + def _translate_AMSJob_to_Serenity(self, AMSJob_folder): + def convert_to_HDF5(binary_file, hdf5_file, dataset_name, shape=None): + hdf5_file_path = Path(self.path) / hdf5_file + data = np.fromfile(str(binary_file), dtype=np.float64) + if shape: + data = data.reshape(shape) + with h5py.File(str(hdf5_file_path), 'w') as h5file: + h5file.create_dataset(dataset_name, data=data, dtype='float64') + n_basis_func_file_source = AMSJob_folder / 'SerenityAMS.nBasisFunc.txt' + n_basis_func_file_dest = Path(self.path) / 'SerenityAMS.nBasisFunc.txt' + shutil.copy(n_basis_func_file_source, n_basis_func_file_dest) + with open(n_basis_func_file_dest, 'r') as file: + dim_size = int(file.readline().strip()) + convert_to_HDF5( + AMSJob_folder / 'SerenityAMS.ERIs.bin', + 'SerenityAMS.ERIs.h5', + 'ERIs', + (dim_size, dim_size, dim_size, dim_size) + ) + convert_to_HDF5( + AMSJob_folder / 'SerenityAMS.orbEnergies.bin', + 'SerenityAMS.orbEnergies.h5', + 'orbitalEnergies' + ) + + def get_input(self): + """Transforms all contents of the ``input`` branch of |Settings| into a string with blocks, subblocks, nested blocks, keys and values. Reserved keywords are handled in a specific manner.""" + currentworkdir = Path.cwd() + _reserved_keywords = ["task", "system"] + + def parse(key, value, indent=''): + ret = '' + if isinstance(value, Settings): + if not any(k == key for k in _reserved_keywords): + ret += '{}+{}\n'.format(indent, key) + for el in value: + ret += parse(el, value[el], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif "task" in key: + for el in value: + ret += '{}+{} {}\n'.format(indent, key, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif "system" in key: + molecule_exists = hasattr(self, 'molecule') and self.molecule is not None + if molecule_exists: + if isinstance(self.molecule, dict): + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + ret += '{}{} geometry {}.xyz\n'.format(indent, indent, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + elif isinstance(self.molecule, Molecule): + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + ret += '{}{} geometry mol.xyz\n'.format(indent, indent) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + else: + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif isinstance(value, list): + for el in value: + ret += parse(key, el, indent) + + elif value == '' or value is True: + ret += '{}{}\n'.format(indent, key) + else: + if key == 'geometry': + geometry_path = currentworkdir / value + abs_geometry_path = geometry_path.resolve() + ret += '{}{} {}\n'.format(indent, key, abs_geometry_path) + else: + ret += '{}{} {}\n'.format(indent, key, str(value)) + return ret + + inp = '' + + for item in self.settings.input: + inp += parse(item, self.settings.input[item]) + '\n' + + return inp + + def get_runscript(self): + """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" + input_file = self._filename('inp') + output_file = self._filename('out') + + #return 'serenity {} |tee ser_{}'.format(input_file, output_file) + return 'serenity {}'.format(input_file) + + diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py new file mode 100644 index 000000000..37c2d1fbc --- /dev/null +++ b/interfaces/thirdparty/serenity_calculator.py @@ -0,0 +1,30 @@ +from ase.calculators.calculator import Calculator, all_changes +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob +from scm.plams.interfaces.molecule.ase import fromASE +from scm.plams import init, finish, Units, config +import os + + +class SerenityCalculator(Calculator): + implemented_properties = ["energy"] + + def __init__(self, settings: SerenitySettings): + super().__init__() + self.settings = settings + self.results = dict() + + def calculate(self, atoms=None, properties=["energy"], system_changes=all_changes): + init() + config.default_jobmanager.hashing = None + config.jobmanager.hashing = None + atoms.write("my_system.xyz") + for sys in self.settings.input.system: + self.settings.input.system[sys].geometry = os.path.abspath("my_system.xyz") + job = SerenityJob(settings=self.settings, name="serenity_job") + job.run() + self.results = dict() + self.results["energy"] = job.results.get_energy() * Units.convert(1.0, "hartree", "eV") + # delete_job(job) + + def clean_exit(self): + finish() From 5a0a42a3b9790120ef215696d480bcb8263d1533 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 18:46:52 +0100 Subject: [PATCH 02/13] I run black on my files --- .../C2H4_CCSD.py | 37 +++++++-------- .../HF_CCSD_T.py | 37 +++++++-------- .../N2_CCSD.py | 37 +++++++-------- examples/SerenityCalculator/example.py | 4 +- examples/SerenityCalculator/my_calculator.py | 12 ++--- .../SerenityInterface_examples/dft_res.py | 45 ++++++++++--------- examples/SerenityInterface_examples/fde.py | 35 ++++++++------- examples/SerenityInterface_examples/hf_res.py | 33 +++++++------- .../SerenityInterface_examples/hf_unres.py | 27 +++++------ .../localization.py | 31 ++++++------- examples/SerenityInterface_examples/mp2.py | 25 ++++++----- 11 files changed, 166 insertions(+), 157 deletions(-) diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 2b597164f..56f846241 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_C2H4_DZ') -mol = Molecule('C2H4.xyz') +init(folder="PLAMS_CCSD_C2H4_DZ") + +mol = Molecule("C2H4.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'DZ' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_C2H4_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "DZ" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_C2H4_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.C2H4.geometry = 'C2H4.xyz' +sersett.input.system.C2H4.geometry = "C2H4.xyz" -sersett.input.task.CC.system = 'C2H4' -sersett.input.task.CC.level = 'CCSD' +sersett.input.task.CC.system = "C2H4" +sersett.input.task.CC.level = "CCSD" -serjob = SerenityJob(settings=sersett, name='Serenity_C2H4_CCSD') +serjob = SerenityJob(settings=sersett, name="Serenity_C2H4_CCSD") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index 885ea46cd..f34563b84 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_T_HF_TZP') -mol = Molecule('HF.xyz') +init(folder="PLAMS_CCSD_T_HF_TZP") + +mol = Molecule("HF.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'TZP' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_HF_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "TZP" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_HF_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.HF.geometry = 'HF.xyz' +sersett.input.system.HF.geometry = "HF.xyz" -sersett.input.task.CC.system = 'HF' -sersett.input.task.CC.level = 'CCSD(T)' +sersett.input.task.CC.system = "HF" +sersett.input.task.CC.level = "CCSD(T)" -serjob = SerenityJob(settings=sersett, name='Serenity_HF_CCSD_T') +serjob = SerenityJob(settings=sersett, name="Serenity_HF_CCSD_T") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index ac96ef2d8..b86914317 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_N2_DZ') -mol = Molecule('N2.xyz') +init(folder="PLAMS_CCSD_N2_DZ") + +mol = Molecule("N2.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'DZ' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_N2_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "DZ" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_N2_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.N2.geometry = 'N2.xyz' +sersett.input.system.N2.geometry = "N2.xyz" -sersett.input.task.CC.system = 'N2' -sersett.input.task.CC.level = 'CCSD' +sersett.input.task.CC.system = "N2" +sersett.input.task.CC.level = "CCSD" -serjob = SerenityJob(settings=sersett, name='Serenity_N2_CCSD') +serjob = SerenityJob(settings=sersett, name="Serenity_N2_CCSD") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 1f53d16af..1f335b7ff 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,5 +1,6 @@ from scm.plams import * import os + init() molecule = from_smiles("[HH]") @@ -8,7 +9,7 @@ s = Settings() s.input.ams.Task = "PESScan" s.input.ams.PESScan.ScanCoordinate.nPoints = 5 -s.input.ams.PESScan.ScanCoordinate.Distance = '1 2 0.65 0.8' +s.input.ams.PESScan.ScanCoordinate.Distance = "1 2 0.65 0.8" s.input.ForceField.Type = "UFF" psjob = AMSJob(settings=s, molecule=molecule, name="ams_pesscan") psjob.run() @@ -31,5 +32,4 @@ log(replayresults) - finish() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py index a14696271..f28dc439e 100644 --- a/examples/SerenityCalculator/my_calculator.py +++ b/examples/SerenityCalculator/my_calculator.py @@ -2,14 +2,14 @@ from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator import os + def get_calculator() -> SerenityCalculator: s = SerenitySettings() - s.input.system.A.charge = '0' - s.input.system.A.spin = '0' - s.input.system.A.method = 'HF' - s.input.system.A.basis.label = '6-31GS' - s.input.task.SCF.act = 'A' + s.input.system.A.charge = "0" + s.input.system.A.spin = "0" + s.input.system.A.method = "HF" + s.input.system.A.basis.label = "6-31GS" + s.input.task.SCF.act = "A" calc = SerenityCalculator(settings=s) return calc - diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index 5ff2189ba..ee83b9c30 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,31 +1,32 @@ from scm.plams import * -init(folder='test_riboflavin') -#instead of giving the geometry key and the file as value you can also do: -#Riboflavin = Molecule() -#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) -#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) -#Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) -#... -#name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job -#serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') +init(folder="test_riboflavin") + +# instead of giving the geometry key and the file as value you can also do: +# Riboflavin = Molecule() +# Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) +# Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) +# Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) +# ... +# name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job +# serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' -#The electronic structure method -sersett.input.system.Riboflavin.method = 'DFT' -sersett.input.system.Riboflavin.basis.label = '6-31GS' -#Settings used for the DFT calculation. -sersett.input.system.Riboflavin.dft.functional = 'PBE' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'Riboflavin' -#Every task in Serenity has a print-level which can be tuned to -#adjust the amount of output generated. -sersett.input.task.SCF.printLevel = 'normal' +# The path to the geometry file +sersett.input.system.Riboflavin.geometry = "riboflavin.xyz" +# The electronic structure method +sersett.input.system.Riboflavin.method = "DFT" +sersett.input.system.Riboflavin.basis.label = "6-31GS" +# Settings used for the DFT calculation. +sersett.input.system.Riboflavin.dft.functional = "PBE" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "Riboflavin" +# Every task in Serenity has a print-level which can be tuned to +# adjust the amount of output generated. +sersett.input.task.SCF.printLevel = "normal" -serjob = SerenityJob(settings=sersett, name='Serenity_Riboflavin') +serjob = SerenityJob(settings=sersett, name="Serenity_Riboflavin") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index b96d9196a..587f7308f 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,29 +1,30 @@ from scm.plams import * -init(folder='test') + +init(folder="test") mol1 = Molecule() -mol1.add_atom(Atom(symbol='O', coords=(0,0,0))) -mol1.add_atom(Atom(symbol='H', coords=(0.758602,0,0.504284))) -mol1.add_atom(Atom(symbol='H', coords=(0.260455,0,-0.872893))) +mol1.add_atom(Atom(symbol="O", coords=(0, 0, 0))) +mol1.add_atom(Atom(symbol="H", coords=(0.758602, 0, 0.504284))) +mol1.add_atom(Atom(symbol="H", coords=(0.260455, 0, -0.872893))) mol2 = Molecule() -mol2.add_atom(Atom(symbol='O', coords=(3,0.5,0))) -mol2.add_atom(Atom(symbol='H', coords=(3.758602,0.5,0.504284))) -mol2.add_atom(Atom(symbol='H', coords=(3.260455,0.5,-0.872893))) +mol2.add_atom(Atom(symbol="O", coords=(3, 0.5, 0))) +mol2.add_atom(Atom(symbol="H", coords=(3.758602, 0.5, 0.504284))) +mol2.add_atom(Atom(symbol="H", coords=(3.260455, 0.5, -0.872893))) sersett = SerenitySettings() -sersett.input.system.water1.method = 'dft' -sersett.input.system.water1.dft.functional = 'pw91' +sersett.input.system.water1.method = "dft" +sersett.input.system.water1.dft.functional = "pw91" -sersett.input.system.water2.method = 'dft' -sersett.input.system.water2.dft.functional = 'pw91' +sersett.input.system.water2.method = "dft" +sersett.input.system.water2.dft.functional = "pw91" -sersett.input.task.fde.act = 'water1' -sersett.input.task.fde.env = 'water2' -sersett.input.task.fde.emb.naddxcfunc = 'pw91' -sersett.input.task.fde.emb.naddkinfunc = 'pw91k' -#when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry -serjob = SerenityJob(molecule={"water1":mol1, "water2":mol2}, settings=sersett, name='water_dimer') +sersett.input.task.fde.act = "water1" +sersett.input.task.fde.env = "water2" +sersett.input.task.fde.emb.naddxcfunc = "pw91" +sersett.input.task.fde.emb.naddkinfunc = "pw91k" +# when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry +serjob = SerenityJob(molecule={"water1": mol1, "water2": mol2}, settings=sersett, name="water_dimer") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index 3fec330f4..c12b04517 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,25 +1,26 @@ from scm.plams import * -init(folder='test_gly-gly-gly') -#instead of giving the geometry key you can also do: -#mol = Molecule('gly-gly-gly.xyz') -#serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') -#the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name +init(folder="test_gly-gly-gly") + +# instead of giving the geometry key you can also do: +# mol = Molecule('gly-gly-gly.xyz') +# serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +# the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' -#You can define the charge and the excess number of alpha electrons here -sersett.input.system.gly_gly_gly.charge = '0' -sersett.input.system.gly_gly_gly.spin = '0' -#The electronic structure method -sersett.input.system.gly_gly_gly.method = 'HF' -sersett.input.system.gly_gly_gly.basis.label = '6-31GS' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'gly_gly_gly' +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +# You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +# The electronic structure method +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.basis.label = "6-31GS" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" -serjob = SerenityJob(settings=sersett, name='Serenity_gly-gly-gly') +serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index d59761f3f..2cea71468 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,20 +1,21 @@ from scm.plams import * -init(folder='test_methylradical') + +init(folder="test_methylradical") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.MethylRadical.geometry = 'methylRadical.xyz' -#You can define the excess number of alpha electrons here -sersett.input.system.MethylRadical.spin = '1' -#This means that we allow singly occupied orbitals which leads to different -#spatial-orbitals for alpha and beta electrons. -#Serenity will choose this automatically as soon as spin != 0. -sersett.input.system.MethylRadical.scfMode = 'UNRESTRICTED' -sersett.input.system.MethylRadical.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'MethylRadical' +# The path to the geometry file +sersett.input.system.MethylRadical.geometry = "methylRadical.xyz" +# You can define the excess number of alpha electrons here +sersett.input.system.MethylRadical.spin = "1" +# This means that we allow singly occupied orbitals which leads to different +# spatial-orbitals for alpha and beta electrons. +# Serenity will choose this automatically as soon as spin != 0. +sersett.input.system.MethylRadical.scfMode = "UNRESTRICTED" +sersett.input.system.MethylRadical.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "MethylRadical" -serjob = SerenityJob(settings=sersett, name='Serenity_methylradical') +serjob = SerenityJob(settings=sersett, name="Serenity_methylradical") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index ab9448876..3d6c44d41 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,22 +1,23 @@ from scm.plams import * -init(folder='test_localization') + +init(folder="test_localization") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' -sersett.input.system.Riboflavin.method = 'DFT' -sersett.input.system.Riboflavin.dft.functional = 'PBE' -sersett.input.system.Riboflavin.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'Riboflavin' -#Localize the orbtials -sersett.input.task.loc.act = 'Riboflavin' -sersett.input.task.loc.locType = 'IBO' -#Print the orbitals to file -sersett.input.task.cube.act = 'Riboflavin' -sersett.input.task.cube.occOrbitals = 'true' +# The path to the geometry file +sersett.input.system.Riboflavin.geometry = "riboflavin.xyz" +sersett.input.system.Riboflavin.method = "DFT" +sersett.input.system.Riboflavin.dft.functional = "PBE" +sersett.input.system.Riboflavin.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "Riboflavin" +# Localize the orbtials +sersett.input.task.loc.act = "Riboflavin" +sersett.input.task.loc.locType = "IBO" +# Print the orbitals to file +sersett.input.task.cube.act = "Riboflavin" +sersett.input.task.cube.occOrbitals = "true" -serjob = SerenityJob(settings=sersett, name='Serenity_localization') +serjob = SerenityJob(settings=sersett, name="Serenity_localization") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index 7bbbb76bc..c03a9b3a5 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,19 +1,20 @@ from scm.plams import * -init(folder='test_mp2') + +init(folder="test_mp2") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' -sersett.input.system.gly_gly_gly.method = 'HF' -sersett.input.system.gly_gly_gly.charge = '0' -sersett.input.system.gly_gly_gly.spin = '0' -sersett.input.system.gly_gly_gly.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'gly_gly_gly' -#Localize the orbtials -sersett.input.task.MP2.act = 'gly_gly_gly' +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +sersett.input.system.gly_gly_gly.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" +# Localize the orbtials +sersett.input.task.MP2.act = "gly_gly_gly" -serjob = SerenityJob(settings=sersett, name='Serenity_mp2') +serjob = SerenityJob(settings=sersett, name="Serenity_mp2") serjob.run() finish() From ea4b0924e4f3943919405c80be7625e72824be7e Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 18:48:21 +0100 Subject: [PATCH 03/13] I had forgotten one file --- interfaces/thirdparty/serenity.py | 145 +++++++++++++++--------------- 1 file changed, 71 insertions(+), 74 deletions(-) diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 32513a0b9..32dcd05be 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -10,7 +10,7 @@ import shutil import os -__all__ = ['SerenityJob', 'SerenityResults', 'SerenitySettings'] +__all__ = ["SerenityJob", "SerenityResults", "SerenitySettings"] class SerenitySettings(Settings): @@ -23,12 +23,12 @@ def __iter__(self): class SerenityResults(Results): """A Subclass of the Results class to access the results given in the Serenity output. Can be extended as required.""" - - def _get_energy_type(self, search='Total Energy', index=-1, unit='a.u.'): + def _get_energy_type(self, search="Total Energy", index=-1, unit="a.u."): s = self.grep_output(search) - s = [ item for item in s if not '...' in item ] + s = [item for item in s if not "..." in item] s = s[index] + def convert_with_fallback(item): try: return float(item.split()[-1]) @@ -39,28 +39,28 @@ def convert_with_fallback(item): raise ValueError("Can not convert type to float.") if not isinstance(index, slice): - return Units.convert(convert_with_fallback(s), 'a.u.', unit) + return Units.convert(convert_with_fallback(s), "a.u.", unit) else: - return [Units.convert(convert_with_fallback(x), 'a.u.', unit) for x in s] + return [Units.convert(convert_with_fallback(x), "a.u.", unit) for x in s] - def get_energy(self, index=-1, unit='a.u.'): + def get_energy(self, index=-1, unit="a.u."): """Returns 'Total Energy (DFT)/(HF):' from the output file. Set ``index`` to choose the n-th occurence of the total energy in the output. Defaults to the last occurence.""" - return self._get_energy_type('Total Energy', index=index, unit=unit) - - def get_ccsd_energy_correction(self, index=-1, unit='a.u.'): + return self._get_energy_type("Total Energy", index=index, unit=unit) + + def get_ccsd_energy_correction(self, index=-1, unit="a.u."): """Returns the 'CCSD Energy Correction' from the output file. Set ``index`` to choose the n-th occurrence of the CCSD energy correction in the output. Defaults to the last occurrence.""" - return self._get_energy_type('CCSD Energy Correction', index=index, unit=unit) - - def get_triples_energy_correction(self, index=-1, unit='a.u.'): - return self._get_energy_type('Triples Energy Correction', index=index, unit=unit) + return self._get_energy_type("CCSD Energy Correction", index=index, unit=unit) + + def get_triples_energy_correction(self, index=-1, unit="a.u."): + return self._get_energy_type("Triples Energy Correction", index=index, unit=unit) - def get_local_ccsd_energy(self, index=-1, unit='a.u.'): - return self._get_energy_type('Total Local-CCSD Energy', index=index, unit=unit) + def get_local_ccsd_energy(self, index=-1, unit="a.u."): + return self._get_energy_type("Total Local-CCSD Energy", index=index, unit=unit) class SerenityJob(SingleJob): """A Subclass of the SingleJob class representing a computational job with Serenity.""" - + _result_type = SerenityResults def _get_ready(self): @@ -73,113 +73,110 @@ def _get_ready(self): self.molecule.write(os.path.join(self.path, "mol.xyz")) base_path = Path(self.path).parent - ams_job_dirs = [d for d in base_path.iterdir() if d.is_dir() and any(f.startswith('SerenityAMS') for f in os.listdir(d))] + ams_job_dirs = [ + d for d in base_path.iterdir() if d.is_dir() and any(f.startswith("SerenityAMS") for f in os.listdir(d)) + ] if ams_job_dirs: self._translate_AMSJob_to_Serenity(ams_job_dirs[0]) # Processes the first matching directory return - + def _translate_AMSJob_to_Serenity(self, AMSJob_folder): def convert_to_HDF5(binary_file, hdf5_file, dataset_name, shape=None): hdf5_file_path = Path(self.path) / hdf5_file data = np.fromfile(str(binary_file), dtype=np.float64) if shape: data = data.reshape(shape) - with h5py.File(str(hdf5_file_path), 'w') as h5file: - h5file.create_dataset(dataset_name, data=data, dtype='float64') - n_basis_func_file_source = AMSJob_folder / 'SerenityAMS.nBasisFunc.txt' - n_basis_func_file_dest = Path(self.path) / 'SerenityAMS.nBasisFunc.txt' + with h5py.File(str(hdf5_file_path), "w") as h5file: + h5file.create_dataset(dataset_name, data=data, dtype="float64") + + n_basis_func_file_source = AMSJob_folder / "SerenityAMS.nBasisFunc.txt" + n_basis_func_file_dest = Path(self.path) / "SerenityAMS.nBasisFunc.txt" shutil.copy(n_basis_func_file_source, n_basis_func_file_dest) - with open(n_basis_func_file_dest, 'r') as file: + with open(n_basis_func_file_dest, "r") as file: dim_size = int(file.readline().strip()) convert_to_HDF5( - AMSJob_folder / 'SerenityAMS.ERIs.bin', - 'SerenityAMS.ERIs.h5', - 'ERIs', - (dim_size, dim_size, dim_size, dim_size) - ) - convert_to_HDF5( - AMSJob_folder / 'SerenityAMS.orbEnergies.bin', - 'SerenityAMS.orbEnergies.h5', - 'orbitalEnergies' + AMSJob_folder / "SerenityAMS.ERIs.bin", + "SerenityAMS.ERIs.h5", + "ERIs", + (dim_size, dim_size, dim_size, dim_size), ) + convert_to_HDF5(AMSJob_folder / "SerenityAMS.orbEnergies.bin", "SerenityAMS.orbEnergies.h5", "orbitalEnergies") def get_input(self): """Transforms all contents of the ``input`` branch of |Settings| into a string with blocks, subblocks, nested blocks, keys and values. Reserved keywords are handled in a specific manner.""" currentworkdir = Path.cwd() _reserved_keywords = ["task", "system"] - def parse(key, value, indent=''): - ret = '' + def parse(key, value, indent=""): + ret = "" if isinstance(value, Settings): - if not any(k == key for k in _reserved_keywords): - ret += '{}+{}\n'.format(indent, key) + if not any(k == key for k in _reserved_keywords): + ret += "{}+{}\n".format(indent, key) for el in value: - ret += parse(el, value[el], indent + ' ') - ret += '{}-{}\n'.format(indent, key) - + ret += parse(el, value[el], indent + " ") + ret += "{}-{}\n".format(indent, key) + elif "task" in key: for el in value: - ret += '{}+{} {}\n'.format(indent, key, el) + ret += "{}+{} {}\n".format(indent, key, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif "system" in key: - molecule_exists = hasattr(self, 'molecule') and self.molecule is not None + molecule_exists = hasattr(self, "molecule") and self.molecule is not None if molecule_exists: if isinstance(self.molecule, dict): for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) - ret += '{}{} geometry {}.xyz\n'.format(indent, indent, el) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) + ret += "{}{} geometry {}.xyz\n".format(indent, indent, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif isinstance(self.molecule, Molecule): for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) - ret += '{}{} geometry mol.xyz\n'.format(indent, indent) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) + ret += "{}{} geometry mol.xyz\n".format(indent, indent) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) - else: + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) + else: for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif isinstance(value, list): for el in value: ret += parse(key, el, indent) - elif value == '' or value is True: - ret += '{}{}\n'.format(indent, key) + elif value == "" or value is True: + ret += "{}{}\n".format(indent, key) else: - if key == 'geometry': + if key == "geometry": geometry_path = currentworkdir / value abs_geometry_path = geometry_path.resolve() - ret += '{}{} {}\n'.format(indent, key, abs_geometry_path) + ret += "{}{} {}\n".format(indent, key, abs_geometry_path) else: - ret += '{}{} {}\n'.format(indent, key, str(value)) + ret += "{}{} {}\n".format(indent, key, str(value)) return ret - inp = '' + inp = "" for item in self.settings.input: - inp += parse(item, self.settings.input[item]) + '\n' + inp += parse(item, self.settings.input[item]) + "\n" + + return inp - return inp - def get_runscript(self): """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" - input_file = self._filename('inp') - output_file = self._filename('out') - - #return 'serenity {} |tee ser_{}'.format(input_file, output_file) - return 'serenity {}'.format(input_file) - + input_file = self._filename("inp") + output_file = self._filename("out") + # return 'serenity {} |tee ser_{}'.format(input_file, output_file) + return "serenity {}".format(input_file) From 54b5ff588e32465fbdc57b38f266d3f9b0e490c9 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 10:51:56 +0100 Subject: [PATCH 04/13] Fixed the files according to Black and Flake8 --- .../C2H4_CCSD.py | 3 ++- .../HF_CCSD_T.py | 3 ++- .../N2_CCSD.py | 3 ++- examples/SerenityCalculator/example.py | 2 +- examples/SerenityCalculator/my_calculator.py | 1 - .../SerenityInterface_examples/dft_res.py | 3 ++- examples/SerenityInterface_examples/fde.py | 3 ++- examples/SerenityInterface_examples/hf_res.py | 3 ++- .../SerenityInterface_examples/hf_unres.py | 3 ++- .../localization.py | 3 ++- examples/SerenityInterface_examples/mp2.py | 3 ++- .../SerenityInterface_examples/oldhf_res.py | 27 +++++++++++++++++++ interfaces/thirdparty/serenity.py | 2 +- interfaces/thirdparty/serenity_calculator.py | 3 ++- 14 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 examples/SerenityInterface_examples/oldhf_res.py diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 56f846241..2c2a5498a 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_C2H4_DZ") diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index f34563b84..716d3d6f4 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_T_HF_TZP") diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index b86914317..f080cf445 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_N2_DZ") diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 1f335b7ff..78e137020 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,5 +1,5 @@ -from scm.plams import * import os +from scm.plams import init, finish, from_smiles, Settings, AMSJob, log init() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py index f28dc439e..16eac12e6 100644 --- a/examples/SerenityCalculator/my_calculator.py +++ b/examples/SerenityCalculator/my_calculator.py @@ -1,6 +1,5 @@ from scm.plams.interfaces.thirdparty.serenity import SerenitySettings from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator -import os def get_calculator() -> SerenityCalculator: diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index ee83b9c30..37ff4192a 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_riboflavin") diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index 587f7308f..7d71ce4d1 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Atom +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test") diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index c12b04517..3b38d7aa5 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index 2cea71468..38fa692a0 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_methylradical") diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index 3d6c44d41..616ae8924 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_localization") diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index c03a9b3a5..771f3b62e 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_mp2") diff --git a/examples/SerenityInterface_examples/oldhf_res.py b/examples/SerenityInterface_examples/oldhf_res.py new file mode 100644 index 000000000..3b38d7aa5 --- /dev/null +++ b/examples/SerenityInterface_examples/oldhf_res.py @@ -0,0 +1,27 @@ +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob + +init(folder="test_gly-gly-gly") + +# instead of giving the geometry key you can also do: +# mol = Molecule('gly-gly-gly.xyz') +# serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +# the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name + + +sersett = SerenitySettings() +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +# You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +# The electronic structure method +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.basis.label = "6-31GS" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" + +serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") +serjob.run() + +finish() diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 32dcd05be..6c06ec0e6 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -176,7 +176,7 @@ def parse(key, value, indent=""): def get_runscript(self): """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" input_file = self._filename("inp") - output_file = self._filename("out") + # output_file = self._filename("out") # return 'serenity {} |tee ser_{}'.format(input_file, output_file) return "serenity {}".format(input_file) diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py index 37c2d1fbc..5479c0ac6 100644 --- a/interfaces/thirdparty/serenity_calculator.py +++ b/interfaces/thirdparty/serenity_calculator.py @@ -1,6 +1,7 @@ from ase.calculators.calculator import Calculator, all_changes from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob -from scm.plams.interfaces.molecule.ase import fromASE + +# from scm.plams.interfaces.molecule.ase import fromASE from scm.plams import init, finish, Units, config import os From bc9d5d5201a524610e725e65b91f3819324d6f67 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 16:02:02 +0100 Subject: [PATCH 05/13] Removed init() and finish() when useless, though still kept them in a couple of select places purely for readability, to make it clear what we are doing --- doc/build_plams_doc_warn_errors.txt | 0 examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py | 4 +--- examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py | 4 +--- examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py | 4 +--- examples/SerenityCalculator/example.py | 7 +------ examples/SerenityInterface_examples/dft_res.py | 4 +--- examples/SerenityInterface_examples/fde.py | 4 +--- examples/SerenityInterface_examples/hf_res.py | 4 +--- examples/SerenityInterface_examples/hf_unres.py | 4 +--- examples/SerenityInterface_examples/localization.py | 4 +--- examples/SerenityInterface_examples/mp2.py | 4 +--- examples/SerenityInterface_examples/oldhf_res.py | 4 +--- interfaces/thirdparty/serenity_calculator.py | 3 +-- 13 files changed, 12 insertions(+), 38 deletions(-) create mode 100644 doc/build_plams_doc_warn_errors.txt diff --git a/doc/build_plams_doc_warn_errors.txt b/doc/build_plams_doc_warn_errors.txt new file mode 100644 index 000000000..e69de29bb diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 2c2a5498a..f2a730817 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_C2H4_DZ") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index 716d3d6f4..bcdc28f80 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_T_HF_TZP") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index f080cf445..dcdbd0be9 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_N2_DZ") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 78e137020..a6840b531 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,7 +1,5 @@ import os -from scm.plams import init, finish, from_smiles, Settings, AMSJob, log - -init() +from scm.plams import from_smiles, Settings, AMSJob, log molecule = from_smiles("[HH]") @@ -30,6 +28,3 @@ replayresults = job.results.get_pesscan_results() log(replayresults) - - -finish() diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index 37ff4192a..6ee40ad84 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_riboflavin") @@ -29,5 +29,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_Riboflavin") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index 7d71ce4d1..472c24e94 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Atom +from scm.plams import init, Molecule, Atom from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test") @@ -27,5 +27,3 @@ # when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry serjob = SerenityJob(molecule={"water1": mol1, "water2": mol2}, settings=sersett, name="water_dimer") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index 3b38d7aa5..ba57ea206 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") @@ -23,5 +23,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index 38fa692a0..72ace4441 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_methylradical") @@ -18,5 +18,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_methylradical") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index 616ae8924..ff77bbecc 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_localization") @@ -20,5 +20,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_localization") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index 771f3b62e..d52166f8f 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_mp2") @@ -17,5 +17,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_mp2") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/oldhf_res.py b/examples/SerenityInterface_examples/oldhf_res.py index 3b38d7aa5..ba57ea206 100644 --- a/examples/SerenityInterface_examples/oldhf_res.py +++ b/examples/SerenityInterface_examples/oldhf_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") @@ -23,5 +23,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() - -finish() diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py index 5479c0ac6..070bae7af 100644 --- a/interfaces/thirdparty/serenity_calculator.py +++ b/interfaces/thirdparty/serenity_calculator.py @@ -2,7 +2,7 @@ from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob # from scm.plams.interfaces.molecule.ase import fromASE -from scm.plams import init, finish, Units, config +from scm.plams import finish, Units, config import os @@ -15,7 +15,6 @@ def __init__(self, settings: SerenitySettings): self.results = dict() def calculate(self, atoms=None, properties=["energy"], system_changes=all_changes): - init() config.default_jobmanager.hashing = None config.jobmanager.hashing = None atoms.write("my_system.xyz") From 612f1d516abe42696211c8458cf937805f2b8318 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 16:39:07 +0100 Subject: [PATCH 06/13] Resolved an issue from the pull request --- interfaces/thirdparty/serenity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 6c06ec0e6..52d89a5d7 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -65,7 +65,7 @@ class SerenityJob(SingleJob): def _get_ready(self): """If molecule is defined, xyz files are generated accordingly. If there is data to transfer between ADF and Serenity, file formats are converted.""" - SingleJob._get_ready(self) + self._get_ready(self) if isinstance(self.molecule, dict): for name, mol in self.molecule.items(): mol.write(os.path.join(self.path, f"{name}.xyz")) From b8f5d07f3d498f34d3557dd692026a305496f798 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 16:41:47 +0100 Subject: [PATCH 07/13] Serenity interface python code and examples --- .../C2H4.xyz | 8 + .../C2H4_CCSD.py | 34 ++++ .../SerenityAMS_DataTransfer_examples/HF.xyz | 4 + .../HF_CCSD_T.py | 34 ++++ .../SerenityAMS_DataTransfer_examples/N2.xyz | 4 + .../N2_CCSD.py | 34 ++++ examples/SerenityCalculator/example.py | 35 ++++ examples/SerenityCalculator/my_calculator.py | 15 ++ .../SerenityInterface_examples/dft_res.py | 31 +++ examples/SerenityInterface_examples/fde.py | 29 +++ .../gly-gly-gly.xyz | 26 +++ examples/SerenityInterface_examples/hf_res.py | 25 +++ .../SerenityInterface_examples/hf_unres.py | 20 ++ .../localization.py | 22 +++ .../methylRadical.xyz | 6 + examples/SerenityInterface_examples/mp2.py | 19 ++ .../SerenityInterface_examples/riboflavin.xyz | 49 +++++ interfaces/thirdparty/serenity.py | 185 ++++++++++++++++++ interfaces/thirdparty/serenity_calculator.py | 30 +++ 19 files changed, 610 insertions(+) create mode 100644 examples/SerenityAMS_DataTransfer_examples/C2H4.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py create mode 100644 examples/SerenityAMS_DataTransfer_examples/HF.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py create mode 100644 examples/SerenityAMS_DataTransfer_examples/N2.xyz create mode 100644 examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py create mode 100644 examples/SerenityCalculator/example.py create mode 100644 examples/SerenityCalculator/my_calculator.py create mode 100644 examples/SerenityInterface_examples/dft_res.py create mode 100644 examples/SerenityInterface_examples/fde.py create mode 100644 examples/SerenityInterface_examples/gly-gly-gly.xyz create mode 100644 examples/SerenityInterface_examples/hf_res.py create mode 100644 examples/SerenityInterface_examples/hf_unres.py create mode 100644 examples/SerenityInterface_examples/localization.py create mode 100644 examples/SerenityInterface_examples/methylRadical.xyz create mode 100644 examples/SerenityInterface_examples/mp2.py create mode 100644 examples/SerenityInterface_examples/riboflavin.xyz create mode 100644 interfaces/thirdparty/serenity.py create mode 100644 interfaces/thirdparty/serenity_calculator.py diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz b/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz new file mode 100644 index 000000000..9bf655c1e --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4.xyz @@ -0,0 +1,8 @@ +6 +Ethene + H 1.1610 0.0661 1.0238 + C 0.6579 -0.0045 0.0639 + H 1.3352 -0.0830 -0.7815 + C -0.6579 0.0045 -0.0639 + H -1.3355 0.0830 0.7812 + H -1.1608 -0.0661 -1.0239 diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py new file mode 100644 index 000000000..2b597164f --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_C2H4_DZ') + +mol = Molecule('C2H4.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'DZ' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_C2H4_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.C2H4.geometry = 'C2H4.xyz' + +sersett.input.task.CC.system = 'C2H4' +sersett.input.task.CC.level = 'CCSD' + +serjob = SerenityJob(settings=sersett, name='Serenity_C2H4_CCSD') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/HF.xyz b/examples/SerenityAMS_DataTransfer_examples/HF.xyz new file mode 100644 index 000000000..b4bf470e2 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/HF.xyz @@ -0,0 +1,4 @@ +2 + + F 0.91860 0.00000 500.00000 + H 0.00000 0.00000 500.00000 diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py new file mode 100644 index 000000000..885ea46cd --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_T_HF_TZP') + +mol = Molecule('HF.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'TZP' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_HF_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.HF.geometry = 'HF.xyz' + +sersett.input.task.CC.system = 'HF' +sersett.input.task.CC.level = 'CCSD(T)' + +serjob = SerenityJob(settings=sersett, name='Serenity_HF_CCSD_T') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/N2.xyz b/examples/SerenityAMS_DataTransfer_examples/N2.xyz new file mode 100644 index 000000000..525276476 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/N2.xyz @@ -0,0 +1,4 @@ +2 +nitrogen + N 0.000000 0.000000 0.000000 + N 1.097600 0.000000 0.000000 diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py new file mode 100644 index 000000000..ac96ef2d8 --- /dev/null +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -0,0 +1,34 @@ +from scm.plams import * +init(folder='PLAMS_CCSD_N2_DZ') + +mol = Molecule('N2.xyz') +adfsett = Settings() +adfsett.input.ams.task = 'SinglePoint' +adfsett.input.adf.IntegralsToFile = 'SERENITY' +adfsett.input.adf.TotalEnergy = '' +adfsett.input.adf.NumericalQuality = 'VeryGood' +adfsett.input.adf.basis.core = 'None' +adfsett.input.adf.basis.type = 'DZ' +adfsett.input.adf.basis.CreateOutput = 'yes' +adfsett.input.adf.relativity = 'Level=None' +adfsett.input.adf.symmetry = 'NoSym' +adfsett.input.adf.xc.hartreefock = '' + +adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_N2_HF') +adfjob.run() +bonding_energy = adfjob.results.get_energy() +print(f"ADF bonding energy: {bonding_energy} hartree") + + +sersett = SerenitySettings() +sersett.input.system.N2.geometry = 'N2.xyz' + +sersett.input.task.CC.system = 'N2' +sersett.input.task.CC.level = 'CCSD' + +serjob = SerenityJob(settings=sersett, name='Serenity_N2_CCSD') +serjob.run() +ccsd_correction = serjob.results.get_ccsd_energy_correction() +print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + +finish() diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py new file mode 100644 index 000000000..1f53d16af --- /dev/null +++ b/examples/SerenityCalculator/example.py @@ -0,0 +1,35 @@ +from scm.plams import * +import os +init() + +molecule = from_smiles("[HH]") + +# first do a pesscan with pure AMS +s = Settings() +s.input.ams.Task = "PESScan" +s.input.ams.PESScan.ScanCoordinate.nPoints = 5 +s.input.ams.PESScan.ScanCoordinate.Distance = '1 2 0.65 0.8' +s.input.ForceField.Type = "UFF" +psjob = AMSJob(settings=s, molecule=molecule, name="ams_pesscan") +psjob.run() + +# then run a replay with the serenity calculator + +s = Settings() +s.input.ams.Task = "Replay" +s.input.ams.Replay.File = psjob.results.rkfpath() +s.input.ASE.File = os.path.abspath("my_calculator.py") + +job = AMSJob(settings=s, molecule=molecule, name="serenity_replay") +job.run() + +errormsg = job.get_errormsg() +if errormsg: + log(errormsg) + +replayresults = job.results.get_pesscan_results() +log(replayresults) + + + +finish() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py new file mode 100644 index 000000000..a14696271 --- /dev/null +++ b/examples/SerenityCalculator/my_calculator.py @@ -0,0 +1,15 @@ +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings +from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator +import os + +def get_calculator() -> SerenityCalculator: + s = SerenitySettings() + s.input.system.A.charge = '0' + s.input.system.A.spin = '0' + s.input.system.A.method = 'HF' + s.input.system.A.basis.label = '6-31GS' + s.input.task.SCF.act = 'A' + + calc = SerenityCalculator(settings=s) + return calc + diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py new file mode 100644 index 000000000..5ff2189ba --- /dev/null +++ b/examples/SerenityInterface_examples/dft_res.py @@ -0,0 +1,31 @@ +from scm.plams import * +init(folder='test_riboflavin') + +#instead of giving the geometry key and the file as value you can also do: +#Riboflavin = Molecule() +#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) +#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) +#Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) +#... +#name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job +#serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') + + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' +#The electronic structure method +sersett.input.system.Riboflavin.method = 'DFT' +sersett.input.system.Riboflavin.basis.label = '6-31GS' +#Settings used for the DFT calculation. +sersett.input.system.Riboflavin.dft.functional = 'PBE' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'Riboflavin' +#Every task in Serenity has a print-level which can be tuned to +#adjust the amount of output generated. +sersett.input.task.SCF.printLevel = 'normal' + +serjob = SerenityJob(settings=sersett, name='Serenity_Riboflavin') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py new file mode 100644 index 000000000..b96d9196a --- /dev/null +++ b/examples/SerenityInterface_examples/fde.py @@ -0,0 +1,29 @@ +from scm.plams import * +init(folder='test') + +mol1 = Molecule() +mol1.add_atom(Atom(symbol='O', coords=(0,0,0))) +mol1.add_atom(Atom(symbol='H', coords=(0.758602,0,0.504284))) +mol1.add_atom(Atom(symbol='H', coords=(0.260455,0,-0.872893))) + +mol2 = Molecule() +mol2.add_atom(Atom(symbol='O', coords=(3,0.5,0))) +mol2.add_atom(Atom(symbol='H', coords=(3.758602,0.5,0.504284))) +mol2.add_atom(Atom(symbol='H', coords=(3.260455,0.5,-0.872893))) + +sersett = SerenitySettings() +sersett.input.system.water1.method = 'dft' +sersett.input.system.water1.dft.functional = 'pw91' + +sersett.input.system.water2.method = 'dft' +sersett.input.system.water2.dft.functional = 'pw91' + +sersett.input.task.fde.act = 'water1' +sersett.input.task.fde.env = 'water2' +sersett.input.task.fde.emb.naddxcfunc = 'pw91' +sersett.input.task.fde.emb.naddkinfunc = 'pw91k' +#when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry +serjob = SerenityJob(molecule={"water1":mol1, "water2":mol2}, settings=sersett, name='water_dimer') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/gly-gly-gly.xyz b/examples/SerenityInterface_examples/gly-gly-gly.xyz new file mode 100644 index 000000000..c339103f2 --- /dev/null +++ b/examples/SerenityInterface_examples/gly-gly-gly.xyz @@ -0,0 +1,26 @@ +24 +gly-gly-gly.out Energy: -174.7655800 +N -2.04230 -2.89390 2.81300 +H -1.13560 -3.27750 2.63740 +C -2.02210 -1.44800 2.54880 +H -2.71180 -3.33290 2.21390 +C -1.63580 -1.20010 1.07880 +H -2.99220 -1.03750 2.73680 +H -1.30570 -0.97820 3.18990 +O -0.88210 -2.01130 0.48090 +N -2.14750 -0.01590 0.37400 +H -2.23950 -0.22170 -0.60020 +C -1.21100 1.10310 0.55210 +C -1.74710 2.34360 -0.18620 +H -1.11250 1.32330 1.59460 +H -0.25520 0.83540 0.15230 +O -2.98730 2.50950 -0.31940 +N -0.80990 3.33410 -0.73540 +H 0.01930 3.35400 -0.17680 +C -1.43940 4.66250 -0.72550 +C -0.45770 5.70010 -1.30080 +H -2.32670 4.64120 -1.32320 +H -1.69250 4.92970 0.27920 +O 0.82490 5.52860 -1.16310 +O -0.91070 6.74840 -1.92470 +H -0.29860 7.39520 -2.28340 diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py new file mode 100644 index 000000000..3fec330f4 --- /dev/null +++ b/examples/SerenityInterface_examples/hf_res.py @@ -0,0 +1,25 @@ +from scm.plams import * +init(folder='test_gly-gly-gly') + +#instead of giving the geometry key you can also do: +#mol = Molecule('gly-gly-gly.xyz') +#serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +#the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name + + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' +#You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = '0' +sersett.input.system.gly_gly_gly.spin = '0' +#The electronic structure method +sersett.input.system.gly_gly_gly.method = 'HF' +sersett.input.system.gly_gly_gly.basis.label = '6-31GS' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'gly_gly_gly' + +serjob = SerenityJob(settings=sersett, name='Serenity_gly-gly-gly') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py new file mode 100644 index 000000000..d59761f3f --- /dev/null +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -0,0 +1,20 @@ +from scm.plams import * +init(folder='test_methylradical') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.MethylRadical.geometry = 'methylRadical.xyz' +#You can define the excess number of alpha electrons here +sersett.input.system.MethylRadical.spin = '1' +#This means that we allow singly occupied orbitals which leads to different +#spatial-orbitals for alpha and beta electrons. +#Serenity will choose this automatically as soon as spin != 0. +sersett.input.system.MethylRadical.scfMode = 'UNRESTRICTED' +sersett.input.system.MethylRadical.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'MethylRadical' + +serjob = SerenityJob(settings=sersett, name='Serenity_methylradical') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py new file mode 100644 index 000000000..ab9448876 --- /dev/null +++ b/examples/SerenityInterface_examples/localization.py @@ -0,0 +1,22 @@ +from scm.plams import * +init(folder='test_localization') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' +sersett.input.system.Riboflavin.method = 'DFT' +sersett.input.system.Riboflavin.dft.functional = 'PBE' +sersett.input.system.Riboflavin.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'Riboflavin' +#Localize the orbtials +sersett.input.task.loc.act = 'Riboflavin' +sersett.input.task.loc.locType = 'IBO' +#Print the orbitals to file +sersett.input.task.cube.act = 'Riboflavin' +sersett.input.task.cube.occOrbitals = 'true' + +serjob = SerenityJob(settings=sersett, name='Serenity_localization') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/methylRadical.xyz b/examples/SerenityInterface_examples/methylRadical.xyz new file mode 100644 index 000000000..a8b3556d6 --- /dev/null +++ b/examples/SerenityInterface_examples/methylRadical.xyz @@ -0,0 +1,6 @@ +4 +ID: 1554368615348329383 +C -4.551405 2.815581 -0.046505 +H -3.534208 3.169619 0.019728 +H -5.061105 2.467877 0.839038 +H -5.061061 2.812282 -0.998071 diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py new file mode 100644 index 000000000..7bbbb76bc --- /dev/null +++ b/examples/SerenityInterface_examples/mp2.py @@ -0,0 +1,19 @@ +from scm.plams import * +init(folder='test_mp2') + +sersett = SerenitySettings() +#The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' +sersett.input.system.gly_gly_gly.method = 'HF' +sersett.input.system.gly_gly_gly.charge = '0' +sersett.input.system.gly_gly_gly.spin = '0' +sersett.input.system.gly_gly_gly.basis.label = 'Def2-SVP' +#Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = 'gly_gly_gly' +#Localize the orbtials +sersett.input.task.MP2.act = 'gly_gly_gly' + +serjob = SerenityJob(settings=sersett, name='Serenity_mp2') +serjob.run() + +finish() diff --git a/examples/SerenityInterface_examples/riboflavin.xyz b/examples/SerenityInterface_examples/riboflavin.xyz new file mode 100644 index 000000000..1b9c20368 --- /dev/null +++ b/examples/SerenityInterface_examples/riboflavin.xyz @@ -0,0 +1,49 @@ +47 + + C -2.335 1.498 5.390 + C -2.573 0.058 4.841 + C -3.154 0.011 3.393 + H -3.030 -1.024 3.026 + C -4.675 0.327 3.240 + H -4.908 1.357 3.541 + C -5.105 0.213 1.754 + H -4.534 0.924 1.133 + H -4.917 -0.811 1.390 + O -6.509 0.511 1.658 + H -6.838 0.455 0.766 + O -5.517 -0.583 3.973 + H -5.456 -0.489 4.917 + O -2.408 0.897 2.540 + H -1.479 0.691 2.518 + H -3.222 -0.530 5.505 + O -1.304 -0.625 4.790 + H -0.882 -0.701 5.640 + H -1.926 1.471 6.411 + H -1.510 1.913 4.791 + N -3.532 2.354 5.356 + C -4.597 2.143 6.189 + C -4.605 1.191 7.220 + C -5.761 0.911 7.962 + C -6.942 1.619 7.705 + C -6.918 2.647 6.758 + H -7.801 3.252 6.581 + C -5.759 2.911 6.026 + N -5.767 3.928 5.145 + C -4.777 4.187 4.398 + C -4.784 5.293 3.434 + O -5.764 6.017 3.365 + N -3.692 5.455 2.656 + H -3.687 6.203 1.988 + C -2.607 4.647 2.741 + O -1.641 4.821 2.015 + N -2.581 3.637 3.637 + C -3.583 3.342 4.492 + C -8.252 1.291 8.437 + H -8.412 0.203 8.474 + H -9.121 1.739 7.932 + H -8.204 1.687 9.462 + C -5.721 -0.170 9.055 + H -4.692 -0.438 9.336 + H -6.225 -1.074 8.683 + H -6.231 0.182 9.964 + H -3.711 0.642 7.480 diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py new file mode 100644 index 000000000..32513a0b9 --- /dev/null +++ b/interfaces/thirdparty/serenity.py @@ -0,0 +1,185 @@ +from scm.plams.core.basejob import SingleJob +from scm.plams.core.results import Results +from scm.plams.core.settings import Settings +from scm.plams.mol.molecule import Molecule +from scm.plams.tools.units import Units + +from pathlib import Path +import numpy as np +import h5py +import shutil +import os + +__all__ = ['SerenityJob', 'SerenityResults', 'SerenitySettings'] + + +class SerenitySettings(Settings): + """A Subclass of the Settings class to set the iteration order through keys.""" + + def __iter__(self): + """Iteration through keys follows insertion order instead of lexicographical order.""" + return iter(self.keys()) + + +class SerenityResults(Results): + """A Subclass of the Results class to access the results given in the Serenity output. Can be extended as required.""" + + def _get_energy_type(self, search='Total Energy', index=-1, unit='a.u.'): + + s = self.grep_output(search) + s = [ item for item in s if not '...' in item ] + s = s[index] + def convert_with_fallback(item): + try: + return float(item.split()[-1]) + except ValueError: + try: + return float(item.split()[-2]) + except ValueError: + raise ValueError("Can not convert type to float.") + + if not isinstance(index, slice): + return Units.convert(convert_with_fallback(s), 'a.u.', unit) + else: + return [Units.convert(convert_with_fallback(x), 'a.u.', unit) for x in s] + + def get_energy(self, index=-1, unit='a.u.'): + """Returns 'Total Energy (DFT)/(HF):' from the output file. Set ``index`` to choose the n-th occurence of the total energy in the output. Defaults to the last occurence.""" + return self._get_energy_type('Total Energy', index=index, unit=unit) + + def get_ccsd_energy_correction(self, index=-1, unit='a.u.'): + """Returns the 'CCSD Energy Correction' from the output file. Set ``index`` to choose the n-th occurrence of the CCSD energy correction in the output. Defaults to the last occurrence.""" + return self._get_energy_type('CCSD Energy Correction', index=index, unit=unit) + + def get_triples_energy_correction(self, index=-1, unit='a.u.'): + return self._get_energy_type('Triples Energy Correction', index=index, unit=unit) + + def get_local_ccsd_energy(self, index=-1, unit='a.u.'): + return self._get_energy_type('Total Local-CCSD Energy', index=index, unit=unit) + + +class SerenityJob(SingleJob): + """A Subclass of the SingleJob class representing a computational job with Serenity.""" + + _result_type = SerenityResults + + def _get_ready(self): + """If molecule is defined, xyz files are generated accordingly. If there is data to transfer between ADF and Serenity, file formats are converted.""" + SingleJob._get_ready(self) + if isinstance(self.molecule, dict): + for name, mol in self.molecule.items(): + mol.write(os.path.join(self.path, f"{name}.xyz")) + elif isinstance(self.molecule, Molecule): + self.molecule.write(os.path.join(self.path, "mol.xyz")) + + base_path = Path(self.path).parent + ams_job_dirs = [d for d in base_path.iterdir() if d.is_dir() and any(f.startswith('SerenityAMS') for f in os.listdir(d))] + + if ams_job_dirs: + self._translate_AMSJob_to_Serenity(ams_job_dirs[0]) # Processes the first matching directory + return + + def _translate_AMSJob_to_Serenity(self, AMSJob_folder): + def convert_to_HDF5(binary_file, hdf5_file, dataset_name, shape=None): + hdf5_file_path = Path(self.path) / hdf5_file + data = np.fromfile(str(binary_file), dtype=np.float64) + if shape: + data = data.reshape(shape) + with h5py.File(str(hdf5_file_path), 'w') as h5file: + h5file.create_dataset(dataset_name, data=data, dtype='float64') + n_basis_func_file_source = AMSJob_folder / 'SerenityAMS.nBasisFunc.txt' + n_basis_func_file_dest = Path(self.path) / 'SerenityAMS.nBasisFunc.txt' + shutil.copy(n_basis_func_file_source, n_basis_func_file_dest) + with open(n_basis_func_file_dest, 'r') as file: + dim_size = int(file.readline().strip()) + convert_to_HDF5( + AMSJob_folder / 'SerenityAMS.ERIs.bin', + 'SerenityAMS.ERIs.h5', + 'ERIs', + (dim_size, dim_size, dim_size, dim_size) + ) + convert_to_HDF5( + AMSJob_folder / 'SerenityAMS.orbEnergies.bin', + 'SerenityAMS.orbEnergies.h5', + 'orbitalEnergies' + ) + + def get_input(self): + """Transforms all contents of the ``input`` branch of |Settings| into a string with blocks, subblocks, nested blocks, keys and values. Reserved keywords are handled in a specific manner.""" + currentworkdir = Path.cwd() + _reserved_keywords = ["task", "system"] + + def parse(key, value, indent=''): + ret = '' + if isinstance(value, Settings): + if not any(k == key for k in _reserved_keywords): + ret += '{}+{}\n'.format(indent, key) + for el in value: + ret += parse(el, value[el], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif "task" in key: + for el in value: + ret += '{}+{} {}\n'.format(indent, key, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif "system" in key: + molecule_exists = hasattr(self, 'molecule') and self.molecule is not None + if molecule_exists: + if isinstance(self.molecule, dict): + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + ret += '{}{} geometry {}.xyz\n'.format(indent, indent, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + elif isinstance(self.molecule, Molecule): + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + ret += '{}{} geometry mol.xyz\n'.format(indent, indent) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + else: + for el in value: + ret += '{}+{}\n'.format(indent, key) + ret += '{}{} name {}\n'.format(indent, indent, el) + for v in value[el]: + ret += parse(v, value[el][v], indent + ' ') + ret += '{}-{}\n'.format(indent, key) + + elif isinstance(value, list): + for el in value: + ret += parse(key, el, indent) + + elif value == '' or value is True: + ret += '{}{}\n'.format(indent, key) + else: + if key == 'geometry': + geometry_path = currentworkdir / value + abs_geometry_path = geometry_path.resolve() + ret += '{}{} {}\n'.format(indent, key, abs_geometry_path) + else: + ret += '{}{} {}\n'.format(indent, key, str(value)) + return ret + + inp = '' + + for item in self.settings.input: + inp += parse(item, self.settings.input[item]) + '\n' + + return inp + + def get_runscript(self): + """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" + input_file = self._filename('inp') + output_file = self._filename('out') + + #return 'serenity {} |tee ser_{}'.format(input_file, output_file) + return 'serenity {}'.format(input_file) + + diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py new file mode 100644 index 000000000..37c2d1fbc --- /dev/null +++ b/interfaces/thirdparty/serenity_calculator.py @@ -0,0 +1,30 @@ +from ase.calculators.calculator import Calculator, all_changes +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob +from scm.plams.interfaces.molecule.ase import fromASE +from scm.plams import init, finish, Units, config +import os + + +class SerenityCalculator(Calculator): + implemented_properties = ["energy"] + + def __init__(self, settings: SerenitySettings): + super().__init__() + self.settings = settings + self.results = dict() + + def calculate(self, atoms=None, properties=["energy"], system_changes=all_changes): + init() + config.default_jobmanager.hashing = None + config.jobmanager.hashing = None + atoms.write("my_system.xyz") + for sys in self.settings.input.system: + self.settings.input.system[sys].geometry = os.path.abspath("my_system.xyz") + job = SerenityJob(settings=self.settings, name="serenity_job") + job.run() + self.results = dict() + self.results["energy"] = job.results.get_energy() * Units.convert(1.0, "hartree", "eV") + # delete_job(job) + + def clean_exit(self): + finish() From 97ce05a4db4988f73fb6fd7109ef1d91e074aadb Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 18:46:52 +0100 Subject: [PATCH 08/13] I run black on my files --- .../C2H4_CCSD.py | 37 +++++++-------- .../HF_CCSD_T.py | 37 +++++++-------- .../N2_CCSD.py | 37 +++++++-------- examples/SerenityCalculator/example.py | 4 +- examples/SerenityCalculator/my_calculator.py | 12 ++--- .../SerenityInterface_examples/dft_res.py | 45 ++++++++++--------- examples/SerenityInterface_examples/fde.py | 35 ++++++++------- examples/SerenityInterface_examples/hf_res.py | 33 +++++++------- .../SerenityInterface_examples/hf_unres.py | 27 +++++------ .../localization.py | 31 ++++++------- examples/SerenityInterface_examples/mp2.py | 25 ++++++----- 11 files changed, 166 insertions(+), 157 deletions(-) diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 2b597164f..56f846241 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_C2H4_DZ') -mol = Molecule('C2H4.xyz') +init(folder="PLAMS_CCSD_C2H4_DZ") + +mol = Molecule("C2H4.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'DZ' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_C2H4_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "DZ" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_C2H4_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.C2H4.geometry = 'C2H4.xyz' +sersett.input.system.C2H4.geometry = "C2H4.xyz" -sersett.input.task.CC.system = 'C2H4' -sersett.input.task.CC.level = 'CCSD' +sersett.input.task.CC.system = "C2H4" +sersett.input.task.CC.level = "CCSD" -serjob = SerenityJob(settings=sersett, name='Serenity_C2H4_CCSD') +serjob = SerenityJob(settings=sersett, name="Serenity_C2H4_CCSD") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index 885ea46cd..f34563b84 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_T_HF_TZP') -mol = Molecule('HF.xyz') +init(folder="PLAMS_CCSD_T_HF_TZP") + +mol = Molecule("HF.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'TZP' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_HF_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "TZP" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_HF_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.HF.geometry = 'HF.xyz' +sersett.input.system.HF.geometry = "HF.xyz" -sersett.input.task.CC.system = 'HF' -sersett.input.task.CC.level = 'CCSD(T)' +sersett.input.task.CC.system = "HF" +sersett.input.task.CC.level = "CCSD(T)" -serjob = SerenityJob(settings=sersett, name='Serenity_HF_CCSD_T') +serjob = SerenityJob(settings=sersett, name="Serenity_HF_CCSD_T") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index ac96ef2d8..b86914317 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,32 +1,33 @@ from scm.plams import * -init(folder='PLAMS_CCSD_N2_DZ') -mol = Molecule('N2.xyz') +init(folder="PLAMS_CCSD_N2_DZ") + +mol = Molecule("N2.xyz") adfsett = Settings() -adfsett.input.ams.task = 'SinglePoint' -adfsett.input.adf.IntegralsToFile = 'SERENITY' -adfsett.input.adf.TotalEnergy = '' -adfsett.input.adf.NumericalQuality = 'VeryGood' -adfsett.input.adf.basis.core = 'None' -adfsett.input.adf.basis.type = 'DZ' -adfsett.input.adf.basis.CreateOutput = 'yes' -adfsett.input.adf.relativity = 'Level=None' -adfsett.input.adf.symmetry = 'NoSym' -adfsett.input.adf.xc.hartreefock = '' - -adfjob = AMSJob(molecule=mol, settings=adfsett, name='ADF_N2_HF') +adfsett.input.ams.task = "SinglePoint" +adfsett.input.adf.IntegralsToFile = "SERENITY" +adfsett.input.adf.TotalEnergy = "" +adfsett.input.adf.NumericalQuality = "VeryGood" +adfsett.input.adf.basis.core = "None" +adfsett.input.adf.basis.type = "DZ" +adfsett.input.adf.basis.CreateOutput = "yes" +adfsett.input.adf.relativity = "Level=None" +adfsett.input.adf.symmetry = "NoSym" +adfsett.input.adf.xc.hartreefock = "" + +adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_N2_HF") adfjob.run() bonding_energy = adfjob.results.get_energy() print(f"ADF bonding energy: {bonding_energy} hartree") sersett = SerenitySettings() -sersett.input.system.N2.geometry = 'N2.xyz' +sersett.input.system.N2.geometry = "N2.xyz" -sersett.input.task.CC.system = 'N2' -sersett.input.task.CC.level = 'CCSD' +sersett.input.task.CC.system = "N2" +sersett.input.task.CC.level = "CCSD" -serjob = SerenityJob(settings=sersett, name='Serenity_N2_CCSD') +serjob = SerenityJob(settings=sersett, name="Serenity_N2_CCSD") serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 1f53d16af..1f335b7ff 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,5 +1,6 @@ from scm.plams import * import os + init() molecule = from_smiles("[HH]") @@ -8,7 +9,7 @@ s = Settings() s.input.ams.Task = "PESScan" s.input.ams.PESScan.ScanCoordinate.nPoints = 5 -s.input.ams.PESScan.ScanCoordinate.Distance = '1 2 0.65 0.8' +s.input.ams.PESScan.ScanCoordinate.Distance = "1 2 0.65 0.8" s.input.ForceField.Type = "UFF" psjob = AMSJob(settings=s, molecule=molecule, name="ams_pesscan") psjob.run() @@ -31,5 +32,4 @@ log(replayresults) - finish() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py index a14696271..f28dc439e 100644 --- a/examples/SerenityCalculator/my_calculator.py +++ b/examples/SerenityCalculator/my_calculator.py @@ -2,14 +2,14 @@ from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator import os + def get_calculator() -> SerenityCalculator: s = SerenitySettings() - s.input.system.A.charge = '0' - s.input.system.A.spin = '0' - s.input.system.A.method = 'HF' - s.input.system.A.basis.label = '6-31GS' - s.input.task.SCF.act = 'A' + s.input.system.A.charge = "0" + s.input.system.A.spin = "0" + s.input.system.A.method = "HF" + s.input.system.A.basis.label = "6-31GS" + s.input.task.SCF.act = "A" calc = SerenityCalculator(settings=s) return calc - diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index 5ff2189ba..ee83b9c30 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,31 +1,32 @@ from scm.plams import * -init(folder='test_riboflavin') -#instead of giving the geometry key and the file as value you can also do: -#Riboflavin = Molecule() -#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) -#Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) -#Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) -#... -#name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job -#serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') +init(folder="test_riboflavin") + +# instead of giving the geometry key and the file as value you can also do: +# Riboflavin = Molecule() +# Riboflavin.add_atom(Atom(symbol='C', coords=(-2.335,1.498,5.390))) +# Riboflavin.add_atom(Atom(symbol='C', coords=(-2.573,0.058,4.841))) +# Riboflavin.add_atom(Atom(symbol='C', coords=(-3.154,0.011,3.393))) +# ... +# name of the molecule does not necessarily have to match the name of the system. You have to give the molecule to the job +# serjob = SerenityJob(molecule=Riboflavin, settings=sersett, name='Serenity_Riboflavin') sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' -#The electronic structure method -sersett.input.system.Riboflavin.method = 'DFT' -sersett.input.system.Riboflavin.basis.label = '6-31GS' -#Settings used for the DFT calculation. -sersett.input.system.Riboflavin.dft.functional = 'PBE' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'Riboflavin' -#Every task in Serenity has a print-level which can be tuned to -#adjust the amount of output generated. -sersett.input.task.SCF.printLevel = 'normal' +# The path to the geometry file +sersett.input.system.Riboflavin.geometry = "riboflavin.xyz" +# The electronic structure method +sersett.input.system.Riboflavin.method = "DFT" +sersett.input.system.Riboflavin.basis.label = "6-31GS" +# Settings used for the DFT calculation. +sersett.input.system.Riboflavin.dft.functional = "PBE" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "Riboflavin" +# Every task in Serenity has a print-level which can be tuned to +# adjust the amount of output generated. +sersett.input.task.SCF.printLevel = "normal" -serjob = SerenityJob(settings=sersett, name='Serenity_Riboflavin') +serjob = SerenityJob(settings=sersett, name="Serenity_Riboflavin") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index b96d9196a..587f7308f 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,29 +1,30 @@ from scm.plams import * -init(folder='test') + +init(folder="test") mol1 = Molecule() -mol1.add_atom(Atom(symbol='O', coords=(0,0,0))) -mol1.add_atom(Atom(symbol='H', coords=(0.758602,0,0.504284))) -mol1.add_atom(Atom(symbol='H', coords=(0.260455,0,-0.872893))) +mol1.add_atom(Atom(symbol="O", coords=(0, 0, 0))) +mol1.add_atom(Atom(symbol="H", coords=(0.758602, 0, 0.504284))) +mol1.add_atom(Atom(symbol="H", coords=(0.260455, 0, -0.872893))) mol2 = Molecule() -mol2.add_atom(Atom(symbol='O', coords=(3,0.5,0))) -mol2.add_atom(Atom(symbol='H', coords=(3.758602,0.5,0.504284))) -mol2.add_atom(Atom(symbol='H', coords=(3.260455,0.5,-0.872893))) +mol2.add_atom(Atom(symbol="O", coords=(3, 0.5, 0))) +mol2.add_atom(Atom(symbol="H", coords=(3.758602, 0.5, 0.504284))) +mol2.add_atom(Atom(symbol="H", coords=(3.260455, 0.5, -0.872893))) sersett = SerenitySettings() -sersett.input.system.water1.method = 'dft' -sersett.input.system.water1.dft.functional = 'pw91' +sersett.input.system.water1.method = "dft" +sersett.input.system.water1.dft.functional = "pw91" -sersett.input.system.water2.method = 'dft' -sersett.input.system.water2.dft.functional = 'pw91' +sersett.input.system.water2.method = "dft" +sersett.input.system.water2.dft.functional = "pw91" -sersett.input.task.fde.act = 'water1' -sersett.input.task.fde.env = 'water2' -sersett.input.task.fde.emb.naddxcfunc = 'pw91' -sersett.input.task.fde.emb.naddkinfunc = 'pw91k' -#when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry -serjob = SerenityJob(molecule={"water1":mol1, "water2":mol2}, settings=sersett, name='water_dimer') +sersett.input.task.fde.act = "water1" +sersett.input.task.fde.env = "water2" +sersett.input.task.fde.emb.naddxcfunc = "pw91" +sersett.input.task.fde.emb.naddkinfunc = "pw91k" +# when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry +serjob = SerenityJob(molecule={"water1": mol1, "water2": mol2}, settings=sersett, name="water_dimer") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index 3fec330f4..c12b04517 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,25 +1,26 @@ from scm.plams import * -init(folder='test_gly-gly-gly') -#instead of giving the geometry key you can also do: -#mol = Molecule('gly-gly-gly.xyz') -#serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') -#the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name +init(folder="test_gly-gly-gly") + +# instead of giving the geometry key you can also do: +# mol = Molecule('gly-gly-gly.xyz') +# serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +# the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' -#You can define the charge and the excess number of alpha electrons here -sersett.input.system.gly_gly_gly.charge = '0' -sersett.input.system.gly_gly_gly.spin = '0' -#The electronic structure method -sersett.input.system.gly_gly_gly.method = 'HF' -sersett.input.system.gly_gly_gly.basis.label = '6-31GS' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'gly_gly_gly' +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +# You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +# The electronic structure method +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.basis.label = "6-31GS" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" -serjob = SerenityJob(settings=sersett, name='Serenity_gly-gly-gly') +serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index d59761f3f..2cea71468 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,20 +1,21 @@ from scm.plams import * -init(folder='test_methylradical') + +init(folder="test_methylradical") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.MethylRadical.geometry = 'methylRadical.xyz' -#You can define the excess number of alpha electrons here -sersett.input.system.MethylRadical.spin = '1' -#This means that we allow singly occupied orbitals which leads to different -#spatial-orbitals for alpha and beta electrons. -#Serenity will choose this automatically as soon as spin != 0. -sersett.input.system.MethylRadical.scfMode = 'UNRESTRICTED' -sersett.input.system.MethylRadical.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'MethylRadical' +# The path to the geometry file +sersett.input.system.MethylRadical.geometry = "methylRadical.xyz" +# You can define the excess number of alpha electrons here +sersett.input.system.MethylRadical.spin = "1" +# This means that we allow singly occupied orbitals which leads to different +# spatial-orbitals for alpha and beta electrons. +# Serenity will choose this automatically as soon as spin != 0. +sersett.input.system.MethylRadical.scfMode = "UNRESTRICTED" +sersett.input.system.MethylRadical.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "MethylRadical" -serjob = SerenityJob(settings=sersett, name='Serenity_methylradical') +serjob = SerenityJob(settings=sersett, name="Serenity_methylradical") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index ab9448876..3d6c44d41 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,22 +1,23 @@ from scm.plams import * -init(folder='test_localization') + +init(folder="test_localization") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.Riboflavin.geometry = 'riboflavin.xyz' -sersett.input.system.Riboflavin.method = 'DFT' -sersett.input.system.Riboflavin.dft.functional = 'PBE' -sersett.input.system.Riboflavin.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'Riboflavin' -#Localize the orbtials -sersett.input.task.loc.act = 'Riboflavin' -sersett.input.task.loc.locType = 'IBO' -#Print the orbitals to file -sersett.input.task.cube.act = 'Riboflavin' -sersett.input.task.cube.occOrbitals = 'true' +# The path to the geometry file +sersett.input.system.Riboflavin.geometry = "riboflavin.xyz" +sersett.input.system.Riboflavin.method = "DFT" +sersett.input.system.Riboflavin.dft.functional = "PBE" +sersett.input.system.Riboflavin.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "Riboflavin" +# Localize the orbtials +sersett.input.task.loc.act = "Riboflavin" +sersett.input.task.loc.locType = "IBO" +# Print the orbitals to file +sersett.input.task.cube.act = "Riboflavin" +sersett.input.task.cube.occOrbitals = "true" -serjob = SerenityJob(settings=sersett, name='Serenity_localization') +serjob = SerenityJob(settings=sersett, name="Serenity_localization") serjob.run() finish() diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index 7bbbb76bc..c03a9b3a5 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,19 +1,20 @@ from scm.plams import * -init(folder='test_mp2') + +init(folder="test_mp2") sersett = SerenitySettings() -#The path to the geometry file -sersett.input.system.gly_gly_gly.geometry = 'gly-gly-gly.xyz' -sersett.input.system.gly_gly_gly.method = 'HF' -sersett.input.system.gly_gly_gly.charge = '0' -sersett.input.system.gly_gly_gly.spin = '0' -sersett.input.system.gly_gly_gly.basis.label = 'Def2-SVP' -#Performs a SCF calculation for the given active (act) system -sersett.input.task.SCF.act = 'gly_gly_gly' -#Localize the orbtials -sersett.input.task.MP2.act = 'gly_gly_gly' +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +sersett.input.system.gly_gly_gly.basis.label = "Def2-SVP" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" +# Localize the orbtials +sersett.input.task.MP2.act = "gly_gly_gly" -serjob = SerenityJob(settings=sersett, name='Serenity_mp2') +serjob = SerenityJob(settings=sersett, name="Serenity_mp2") serjob.run() finish() From ddf3091cb340cdd226af107a443078f73e015216 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Wed, 8 Jan 2025 18:48:21 +0100 Subject: [PATCH 09/13] I had forgotten one file --- interfaces/thirdparty/serenity.py | 145 +++++++++++++++--------------- 1 file changed, 71 insertions(+), 74 deletions(-) diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 32513a0b9..32dcd05be 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -10,7 +10,7 @@ import shutil import os -__all__ = ['SerenityJob', 'SerenityResults', 'SerenitySettings'] +__all__ = ["SerenityJob", "SerenityResults", "SerenitySettings"] class SerenitySettings(Settings): @@ -23,12 +23,12 @@ def __iter__(self): class SerenityResults(Results): """A Subclass of the Results class to access the results given in the Serenity output. Can be extended as required.""" - - def _get_energy_type(self, search='Total Energy', index=-1, unit='a.u.'): + def _get_energy_type(self, search="Total Energy", index=-1, unit="a.u."): s = self.grep_output(search) - s = [ item for item in s if not '...' in item ] + s = [item for item in s if not "..." in item] s = s[index] + def convert_with_fallback(item): try: return float(item.split()[-1]) @@ -39,28 +39,28 @@ def convert_with_fallback(item): raise ValueError("Can not convert type to float.") if not isinstance(index, slice): - return Units.convert(convert_with_fallback(s), 'a.u.', unit) + return Units.convert(convert_with_fallback(s), "a.u.", unit) else: - return [Units.convert(convert_with_fallback(x), 'a.u.', unit) for x in s] + return [Units.convert(convert_with_fallback(x), "a.u.", unit) for x in s] - def get_energy(self, index=-1, unit='a.u.'): + def get_energy(self, index=-1, unit="a.u."): """Returns 'Total Energy (DFT)/(HF):' from the output file. Set ``index`` to choose the n-th occurence of the total energy in the output. Defaults to the last occurence.""" - return self._get_energy_type('Total Energy', index=index, unit=unit) - - def get_ccsd_energy_correction(self, index=-1, unit='a.u.'): + return self._get_energy_type("Total Energy", index=index, unit=unit) + + def get_ccsd_energy_correction(self, index=-1, unit="a.u."): """Returns the 'CCSD Energy Correction' from the output file. Set ``index`` to choose the n-th occurrence of the CCSD energy correction in the output. Defaults to the last occurrence.""" - return self._get_energy_type('CCSD Energy Correction', index=index, unit=unit) - - def get_triples_energy_correction(self, index=-1, unit='a.u.'): - return self._get_energy_type('Triples Energy Correction', index=index, unit=unit) + return self._get_energy_type("CCSD Energy Correction", index=index, unit=unit) + + def get_triples_energy_correction(self, index=-1, unit="a.u."): + return self._get_energy_type("Triples Energy Correction", index=index, unit=unit) - def get_local_ccsd_energy(self, index=-1, unit='a.u.'): - return self._get_energy_type('Total Local-CCSD Energy', index=index, unit=unit) + def get_local_ccsd_energy(self, index=-1, unit="a.u."): + return self._get_energy_type("Total Local-CCSD Energy", index=index, unit=unit) class SerenityJob(SingleJob): """A Subclass of the SingleJob class representing a computational job with Serenity.""" - + _result_type = SerenityResults def _get_ready(self): @@ -73,113 +73,110 @@ def _get_ready(self): self.molecule.write(os.path.join(self.path, "mol.xyz")) base_path = Path(self.path).parent - ams_job_dirs = [d for d in base_path.iterdir() if d.is_dir() and any(f.startswith('SerenityAMS') for f in os.listdir(d))] + ams_job_dirs = [ + d for d in base_path.iterdir() if d.is_dir() and any(f.startswith("SerenityAMS") for f in os.listdir(d)) + ] if ams_job_dirs: self._translate_AMSJob_to_Serenity(ams_job_dirs[0]) # Processes the first matching directory return - + def _translate_AMSJob_to_Serenity(self, AMSJob_folder): def convert_to_HDF5(binary_file, hdf5_file, dataset_name, shape=None): hdf5_file_path = Path(self.path) / hdf5_file data = np.fromfile(str(binary_file), dtype=np.float64) if shape: data = data.reshape(shape) - with h5py.File(str(hdf5_file_path), 'w') as h5file: - h5file.create_dataset(dataset_name, data=data, dtype='float64') - n_basis_func_file_source = AMSJob_folder / 'SerenityAMS.nBasisFunc.txt' - n_basis_func_file_dest = Path(self.path) / 'SerenityAMS.nBasisFunc.txt' + with h5py.File(str(hdf5_file_path), "w") as h5file: + h5file.create_dataset(dataset_name, data=data, dtype="float64") + + n_basis_func_file_source = AMSJob_folder / "SerenityAMS.nBasisFunc.txt" + n_basis_func_file_dest = Path(self.path) / "SerenityAMS.nBasisFunc.txt" shutil.copy(n_basis_func_file_source, n_basis_func_file_dest) - with open(n_basis_func_file_dest, 'r') as file: + with open(n_basis_func_file_dest, "r") as file: dim_size = int(file.readline().strip()) convert_to_HDF5( - AMSJob_folder / 'SerenityAMS.ERIs.bin', - 'SerenityAMS.ERIs.h5', - 'ERIs', - (dim_size, dim_size, dim_size, dim_size) - ) - convert_to_HDF5( - AMSJob_folder / 'SerenityAMS.orbEnergies.bin', - 'SerenityAMS.orbEnergies.h5', - 'orbitalEnergies' + AMSJob_folder / "SerenityAMS.ERIs.bin", + "SerenityAMS.ERIs.h5", + "ERIs", + (dim_size, dim_size, dim_size, dim_size), ) + convert_to_HDF5(AMSJob_folder / "SerenityAMS.orbEnergies.bin", "SerenityAMS.orbEnergies.h5", "orbitalEnergies") def get_input(self): """Transforms all contents of the ``input`` branch of |Settings| into a string with blocks, subblocks, nested blocks, keys and values. Reserved keywords are handled in a specific manner.""" currentworkdir = Path.cwd() _reserved_keywords = ["task", "system"] - def parse(key, value, indent=''): - ret = '' + def parse(key, value, indent=""): + ret = "" if isinstance(value, Settings): - if not any(k == key for k in _reserved_keywords): - ret += '{}+{}\n'.format(indent, key) + if not any(k == key for k in _reserved_keywords): + ret += "{}+{}\n".format(indent, key) for el in value: - ret += parse(el, value[el], indent + ' ') - ret += '{}-{}\n'.format(indent, key) - + ret += parse(el, value[el], indent + " ") + ret += "{}-{}\n".format(indent, key) + elif "task" in key: for el in value: - ret += '{}+{} {}\n'.format(indent, key, el) + ret += "{}+{} {}\n".format(indent, key, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif "system" in key: - molecule_exists = hasattr(self, 'molecule') and self.molecule is not None + molecule_exists = hasattr(self, "molecule") and self.molecule is not None if molecule_exists: if isinstance(self.molecule, dict): for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) - ret += '{}{} geometry {}.xyz\n'.format(indent, indent, el) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) + ret += "{}{} geometry {}.xyz\n".format(indent, indent, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif isinstance(self.molecule, Molecule): for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) - ret += '{}{} geometry mol.xyz\n'.format(indent, indent) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) + ret += "{}{} geometry mol.xyz\n".format(indent, indent) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) - else: + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) + else: for el in value: - ret += '{}+{}\n'.format(indent, key) - ret += '{}{} name {}\n'.format(indent, indent, el) + ret += "{}+{}\n".format(indent, key) + ret += "{}{} name {}\n".format(indent, indent, el) for v in value[el]: - ret += parse(v, value[el][v], indent + ' ') - ret += '{}-{}\n'.format(indent, key) + ret += parse(v, value[el][v], indent + " ") + ret += "{}-{}\n".format(indent, key) elif isinstance(value, list): for el in value: ret += parse(key, el, indent) - elif value == '' or value is True: - ret += '{}{}\n'.format(indent, key) + elif value == "" or value is True: + ret += "{}{}\n".format(indent, key) else: - if key == 'geometry': + if key == "geometry": geometry_path = currentworkdir / value abs_geometry_path = geometry_path.resolve() - ret += '{}{} {}\n'.format(indent, key, abs_geometry_path) + ret += "{}{} {}\n".format(indent, key, abs_geometry_path) else: - ret += '{}{} {}\n'.format(indent, key, str(value)) + ret += "{}{} {}\n".format(indent, key, str(value)) return ret - inp = '' + inp = "" for item in self.settings.input: - inp += parse(item, self.settings.input[item]) + '\n' + inp += parse(item, self.settings.input[item]) + "\n" + + return inp - return inp - def get_runscript(self): """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" - input_file = self._filename('inp') - output_file = self._filename('out') - - #return 'serenity {} |tee ser_{}'.format(input_file, output_file) - return 'serenity {}'.format(input_file) - + input_file = self._filename("inp") + output_file = self._filename("out") + # return 'serenity {} |tee ser_{}'.format(input_file, output_file) + return "serenity {}".format(input_file) From f0cf95aa8c70bd53039a7a2bc077f088308331d3 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 10:51:56 +0100 Subject: [PATCH 10/13] Fixed the files according to Black and Flake8 --- .../C2H4_CCSD.py | 3 ++- .../HF_CCSD_T.py | 3 ++- .../N2_CCSD.py | 3 ++- examples/SerenityCalculator/example.py | 2 +- examples/SerenityCalculator/my_calculator.py | 1 - .../SerenityInterface_examples/dft_res.py | 3 ++- examples/SerenityInterface_examples/fde.py | 3 ++- examples/SerenityInterface_examples/hf_res.py | 3 ++- .../SerenityInterface_examples/hf_unres.py | 3 ++- .../localization.py | 3 ++- examples/SerenityInterface_examples/mp2.py | 3 ++- .../SerenityInterface_examples/oldhf_res.py | 27 +++++++++++++++++++ interfaces/thirdparty/serenity.py | 2 +- interfaces/thirdparty/serenity_calculator.py | 3 ++- 14 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 examples/SerenityInterface_examples/oldhf_res.py diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 56f846241..2c2a5498a 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_C2H4_DZ") diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index f34563b84..716d3d6f4 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_T_HF_TZP") diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index b86914317..f080cf445 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_N2_DZ") diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 1f335b7ff..78e137020 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,5 +1,5 @@ -from scm.plams import * import os +from scm.plams import init, finish, from_smiles, Settings, AMSJob, log init() diff --git a/examples/SerenityCalculator/my_calculator.py b/examples/SerenityCalculator/my_calculator.py index f28dc439e..16eac12e6 100644 --- a/examples/SerenityCalculator/my_calculator.py +++ b/examples/SerenityCalculator/my_calculator.py @@ -1,6 +1,5 @@ from scm.plams.interfaces.thirdparty.serenity import SerenitySettings from scm.plams.interfaces.thirdparty.serenity_calculator import SerenityCalculator -import os def get_calculator() -> SerenityCalculator: diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index ee83b9c30..37ff4192a 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_riboflavin") diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index 587f7308f..7d71ce4d1 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish, Molecule, Atom +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test") diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index c12b04517..3b38d7aa5 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index 2cea71468..38fa692a0 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_methylradical") diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index 3d6c44d41..616ae8924 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_localization") diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index c03a9b3a5..771f3b62e 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,4 +1,5 @@ -from scm.plams import * +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_mp2") diff --git a/examples/SerenityInterface_examples/oldhf_res.py b/examples/SerenityInterface_examples/oldhf_res.py new file mode 100644 index 000000000..3b38d7aa5 --- /dev/null +++ b/examples/SerenityInterface_examples/oldhf_res.py @@ -0,0 +1,27 @@ +from scm.plams import init, finish +from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob + +init(folder="test_gly-gly-gly") + +# instead of giving the geometry key you can also do: +# mol = Molecule('gly-gly-gly.xyz') +# serjob = SerenityJob(molecule=mol, settings=sersett, name='Serenity_gly-gly-gly') +# the name of the molecule does not have to match the name of the system it will be given as mol.xyz not depending on the given name + + +sersett = SerenitySettings() +# The path to the geometry file +sersett.input.system.gly_gly_gly.geometry = "gly-gly-gly.xyz" +# You can define the charge and the excess number of alpha electrons here +sersett.input.system.gly_gly_gly.charge = "0" +sersett.input.system.gly_gly_gly.spin = "0" +# The electronic structure method +sersett.input.system.gly_gly_gly.method = "HF" +sersett.input.system.gly_gly_gly.basis.label = "6-31GS" +# Performs a SCF calculation for the given active (act) system +sersett.input.task.SCF.act = "gly_gly_gly" + +serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") +serjob.run() + +finish() diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 32dcd05be..6c06ec0e6 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -176,7 +176,7 @@ def parse(key, value, indent=""): def get_runscript(self): """Returned runscript: ``serenity myinput.in |tee ser_myinput.out`` or ``serenity myinput.in``""" input_file = self._filename("inp") - output_file = self._filename("out") + # output_file = self._filename("out") # return 'serenity {} |tee ser_{}'.format(input_file, output_file) return "serenity {}".format(input_file) diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py index 37c2d1fbc..5479c0ac6 100644 --- a/interfaces/thirdparty/serenity_calculator.py +++ b/interfaces/thirdparty/serenity_calculator.py @@ -1,6 +1,7 @@ from ase.calculators.calculator import Calculator, all_changes from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob -from scm.plams.interfaces.molecule.ase import fromASE + +# from scm.plams.interfaces.molecule.ase import fromASE from scm.plams import init, finish, Units, config import os From aa3e7a0836f7eca776aeb4953093528d977434b0 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 16:02:02 +0100 Subject: [PATCH 11/13] Removed init() and finish() when useless, though still kept them in a couple of select places purely for readability, to make it clear what we are doing --- doc/build_plams_doc_warn_errors.txt | 0 examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py | 4 +--- examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py | 4 +--- examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py | 4 +--- examples/SerenityCalculator/example.py | 7 +------ examples/SerenityInterface_examples/dft_res.py | 4 +--- examples/SerenityInterface_examples/fde.py | 4 +--- examples/SerenityInterface_examples/hf_res.py | 4 +--- examples/SerenityInterface_examples/hf_unres.py | 4 +--- examples/SerenityInterface_examples/localization.py | 4 +--- examples/SerenityInterface_examples/mp2.py | 4 +--- examples/SerenityInterface_examples/oldhf_res.py | 4 +--- interfaces/thirdparty/serenity_calculator.py | 3 +-- 13 files changed, 12 insertions(+), 38 deletions(-) create mode 100644 doc/build_plams_doc_warn_errors.txt diff --git a/doc/build_plams_doc_warn_errors.txt b/doc/build_plams_doc_warn_errors.txt new file mode 100644 index 000000000..e69de29bb diff --git a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py index 2c2a5498a..f2a730817 100644 --- a/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/C2H4_CCSD.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_C2H4_DZ") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py index 716d3d6f4..bcdc28f80 100644 --- a/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py +++ b/examples/SerenityAMS_DataTransfer_examples/HF_CCSD_T.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_T_HF_TZP") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py index f080cf445..dcdbd0be9 100644 --- a/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py +++ b/examples/SerenityAMS_DataTransfer_examples/N2_CCSD.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Settings, AMSJob +from scm.plams import init, Molecule, Settings, AMSJob from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="PLAMS_CCSD_N2_DZ") @@ -32,5 +32,3 @@ serjob.run() ccsd_correction = serjob.results.get_ccsd_energy_correction() print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") - -finish() diff --git a/examples/SerenityCalculator/example.py b/examples/SerenityCalculator/example.py index 78e137020..a6840b531 100644 --- a/examples/SerenityCalculator/example.py +++ b/examples/SerenityCalculator/example.py @@ -1,7 +1,5 @@ import os -from scm.plams import init, finish, from_smiles, Settings, AMSJob, log - -init() +from scm.plams import from_smiles, Settings, AMSJob, log molecule = from_smiles("[HH]") @@ -30,6 +28,3 @@ replayresults = job.results.get_pesscan_results() log(replayresults) - - -finish() diff --git a/examples/SerenityInterface_examples/dft_res.py b/examples/SerenityInterface_examples/dft_res.py index 37ff4192a..6ee40ad84 100644 --- a/examples/SerenityInterface_examples/dft_res.py +++ b/examples/SerenityInterface_examples/dft_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_riboflavin") @@ -29,5 +29,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_Riboflavin") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/fde.py b/examples/SerenityInterface_examples/fde.py index 7d71ce4d1..472c24e94 100644 --- a/examples/SerenityInterface_examples/fde.py +++ b/examples/SerenityInterface_examples/fde.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish, Molecule, Atom +from scm.plams import init, Molecule, Atom from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test") @@ -27,5 +27,3 @@ # when using a dictionary and the molecule class to provide geometries you have no make sure that the given names match the systems that should use the respective geometry serjob = SerenityJob(molecule={"water1": mol1, "water2": mol2}, settings=sersett, name="water_dimer") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/hf_res.py b/examples/SerenityInterface_examples/hf_res.py index 3b38d7aa5..ba57ea206 100644 --- a/examples/SerenityInterface_examples/hf_res.py +++ b/examples/SerenityInterface_examples/hf_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") @@ -23,5 +23,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/hf_unres.py b/examples/SerenityInterface_examples/hf_unres.py index 38fa692a0..72ace4441 100644 --- a/examples/SerenityInterface_examples/hf_unres.py +++ b/examples/SerenityInterface_examples/hf_unres.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_methylradical") @@ -18,5 +18,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_methylradical") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/localization.py b/examples/SerenityInterface_examples/localization.py index 616ae8924..ff77bbecc 100644 --- a/examples/SerenityInterface_examples/localization.py +++ b/examples/SerenityInterface_examples/localization.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_localization") @@ -20,5 +20,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_localization") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/mp2.py b/examples/SerenityInterface_examples/mp2.py index 771f3b62e..d52166f8f 100644 --- a/examples/SerenityInterface_examples/mp2.py +++ b/examples/SerenityInterface_examples/mp2.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_mp2") @@ -17,5 +17,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_mp2") serjob.run() - -finish() diff --git a/examples/SerenityInterface_examples/oldhf_res.py b/examples/SerenityInterface_examples/oldhf_res.py index 3b38d7aa5..ba57ea206 100644 --- a/examples/SerenityInterface_examples/oldhf_res.py +++ b/examples/SerenityInterface_examples/oldhf_res.py @@ -1,4 +1,4 @@ -from scm.plams import init, finish +from scm.plams import init from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob init(folder="test_gly-gly-gly") @@ -23,5 +23,3 @@ serjob = SerenityJob(settings=sersett, name="Serenity_gly-gly-gly") serjob.run() - -finish() diff --git a/interfaces/thirdparty/serenity_calculator.py b/interfaces/thirdparty/serenity_calculator.py index 5479c0ac6..070bae7af 100644 --- a/interfaces/thirdparty/serenity_calculator.py +++ b/interfaces/thirdparty/serenity_calculator.py @@ -2,7 +2,7 @@ from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob # from scm.plams.interfaces.molecule.ase import fromASE -from scm.plams import init, finish, Units, config +from scm.plams import finish, Units, config import os @@ -15,7 +15,6 @@ def __init__(self, settings: SerenitySettings): self.results = dict() def calculate(self, atoms=None, properties=["energy"], system_changes=all_changes): - init() config.default_jobmanager.hashing = None config.jobmanager.hashing = None atoms.write("my_system.xyz") From 61c0c2a11cae4cba0827a435a96e7535c3b6c601 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Thu, 9 Jan 2025 16:39:07 +0100 Subject: [PATCH 12/13] Resolved an issue from the pull request --- interfaces/thirdparty/serenity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/thirdparty/serenity.py b/interfaces/thirdparty/serenity.py index 6c06ec0e6..52d89a5d7 100644 --- a/interfaces/thirdparty/serenity.py +++ b/interfaces/thirdparty/serenity.py @@ -65,7 +65,7 @@ class SerenityJob(SingleJob): def _get_ready(self): """If molecule is defined, xyz files are generated accordingly. If there is data to transfer between ADF and Serenity, file formats are converted.""" - SingleJob._get_ready(self) + self._get_ready(self) if isinstance(self.molecule, dict): for name, mol in self.molecule.items(): mol.write(os.path.join(self.path, f"{name}.xyz")) From 9b879b5dac2ce099f5ce5915c6d29961197f8db0 Mon Sep 17 00:00:00 2001 From: Franco Egidi Date: Tue, 14 Jan 2025 15:36:49 +0100 Subject: [PATCH 13/13] Added Serenity documentation and updated the CHANGELOG --- CHANGELOG.md | 1 + doc/source/conf.py | 4 ++ doc/source/general.rst | 1 + doc/source/interfaces/serenity.rst | 89 ++++++++++++++++++++++++++++ doc/source/interfaces/thirdparty.rst | 1 + 5 files changed, 96 insertions(+) create mode 100644 doc/source/interfaces/serenity.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbe4c4c2..7b4196bf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ This changelog is effective from the 2025 releases. * Logging of job summaries to CSV logfile * Logging of AMS job error messages to stdout and logfile on job failure * Method `get_errormsg` enforced on the `Job` base class, with a default implementation +* Added an interface to the Serenity program through methods such as `SerenityJob`, `SerenityResults` and `SerenitySettings` ### Changed * Functions for optional packages (e.g. RDKit, ASE) are available even when these packages are not installed, but will raise an `MissingOptionalPackageError` when called diff --git a/doc/source/conf.py b/doc/source/conf.py index e2a96f12c..c89025a3c 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -312,6 +312,10 @@ def setup(app): .. |VASPJob| replace:: :class:`VASPJob` .. |VASPResults| replace:: :class:`VASPResults` +.. |SerenityJob| replace:: :class:`~scm.plams.interfaces.serenity.SerenityJob` +.. |SerenitySettings| replace:: :class:`~scm.plams.interfaces.serenity.SerenitySettings` +.. |SerenityResults| replace:: :class:`~scm.plams.interfaces.serenity.SerenityResults` + .. |CRSJob| replace:: :class:`CRSJob` .. |CRSResults| replace:: :class:`CRSResults` diff --git a/doc/source/general.rst b/doc/source/general.rst index ad5257215..0c0c13044 100644 --- a/doc/source/general.rst +++ b/doc/source/general.rst @@ -113,6 +113,7 @@ Added * Support for AMS ``ChemicalSystem`` within |AMSJob| and |AMSResults|. |AMSJob| can accept a ``ChemicalSystem`` as an input system, and the methods :meth:`~scm.plams.interfaces.adfsuite.ams.AMSResults.get_system`, :meth:`~scm.plams.interfaces.adfsuite.ams.AMSResults.get_input_system` and :meth:`~scm.plams.interfaces.adfsuite.ams.AMSResults.get_main_system` on |AMSResults| return a ``ChemicalSystem``. These provide the option to use a ``ChemicalSystem`` in place of a PLAMS ``Molecule``. * Support for work functions through :meth:`~scm.plams.interfaces.adfsuite.ams.AMSResults.get_work_function_results` and :func:`~scm.plams.tools.plot.plot_work_function` * Added :meth:`~scm.plams.interfaces.molecule.packmol.packmol_around` method to pack around an existing molecule or pack molecules into a non-orthorhombic box. +* Added an interface to the `Serenity program `_ through classes such as |SerenityJob|, |SerenitySettings|, and |SerenityResults|. Changed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/interfaces/serenity.rst b/doc/source/interfaces/serenity.rst new file mode 100644 index 000000000..f249d183c --- /dev/null +++ b/doc/source/interfaces/serenity.rst @@ -0,0 +1,89 @@ +Serenity +------------------------- + +.. currentmodule:: scm.plams.interfaces.thirdparty.serenity + +Serenity is a quantum chemistry code originally developed in the group of Johannes Neugebauer at the University of Münster with a strong focus on quantum chemical subsystem/embedding methods. See the `serenity page `_ for more details. + +PLAMS offers a simple Serenity interface and is capable of running Serenity calculations. +The relevant classes are |SerenityJob|, |SerenitySettings|, and |SerenityResults|. + +It is also possible to run post-Hartree-Fock (HF) Serenity calculations starting from a ground-state Self-Consistent-Field calculation perfromed with ADF. + + +Serenity calculation +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Preparing an instance of a |SerenityJob| follows general principles for |SingleJob|. +Here is an example of a simple HF calculation:: + + from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob + + sersett = SerenitySettings() + # The path to the geometry file + sersett.input.system.gly_gly_gly.geometry = "mygeometry.xyz" + # Charge and spin + sersett.input.system.gly_gly_gly.charge = "0" + sersett.input.system.gly_gly_gly.spin = "0" + # The electronic structure method + sersett.input.system.gly_gly_gly.method = "HF" + sersett.input.system.gly_gly_gly.basis.label = "6-31G" + # Performs a SCF calculation + sersett.input.task.SCF.act = "mymolecule" + + serjob = SerenityJob(settings=sersett, name="Serenitycalc") + serjob.run() + +This input performs an HF/6-31G calculation on the chosen molecule. + + +ADF interface +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interfacing ADF with Serenity is done through a special file, saved by ADF, which contains information about the Hamiltonian matrix which can be used by Serenity for post-HF calculations. +Here is a simple example:: + + + from scm.plams import init, Molecule, Settings, AMSJob + from scm.plams.interfaces.thirdparty.serenity import SerenitySettings, SerenityJob + + init(folder="PLAMS_CCSD_N2_DZ") + + mol = Molecule("N2.xyz") + adfsett = Settings() + adfsett.input.ams.task = "SinglePoint" + adfsett.input.adf.IntegralsToFile = "SERENITY" + adfsett.input.adf.TotalEnergy = "" + adfsett.input.adf.basis.core = "None" + adfsett.input.adf.basis.type = "DZ" + adfsett.input.adf.basis.CreateOutput = "yes" + adfsett.input.adf.relativity = "Level=None" + adfsett.input.adf.symmetry = "NoSym" + adfsett.input.adf.xc.hartreefock = "" + + adfjob = AMSJob(molecule=mol, settings=adfsett, name="ADF_N2_HF") + adfjob.run() + bonding_energy = adfjob.results.get_energy() + print(f"ADF bonding energy: {bonding_energy} hartree") + + + sersett = SerenitySettings() + sersett.input.system.N2.geometry = "N2.xyz" + + sersett.input.task.CC.system = "N2" + sersett.input.task.CC.level = "CCSD" + + serjob = SerenityJob(settings=sersett, name="Serenity_N2_CCSD") + serjob.run() + ccsd_correction = serjob.results.get_ccsd_energy_correction() + print(f"Serenity CCSD energy correction: {ccsd_correction} hartree") + + +This script produces the CCSD/DZ energy of the nitrogen molecules using integrals computed by ADF with a Slater-type orbital basis. + +API +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: SerenityJob + :exclude-members: _result_type, _get_ready +.. autoclass:: SerenityResults diff --git a/doc/source/interfaces/thirdparty.rst b/doc/source/interfaces/thirdparty.rst index 0259f4327..38744df12 100644 --- a/doc/source/interfaces/thirdparty.rst +++ b/doc/source/interfaces/thirdparty.rst @@ -20,3 +20,4 @@ They offer a way of using PLAMS |Molecule| class with other libraries capable of orca raspa vasp + serenity