From 4b872c00e8e05bb50f3b418ed5d35322d2b7d7e6 Mon Sep 17 00:00:00 2001 From: Paul Saxe Date: Sun, 4 Jun 2023 21:54:19 -0400 Subject: [PATCH 1/3] Added thermochemistry step and cube files for plotting. --- psi4_step/__init__.py | 65 +-- psi4_step/energy.py | 119 +++++- psi4_step/energy_parameters.py | 37 +- psi4_step/initialization.py | 2 +- psi4_step/initialization_parameters.py | 21 +- psi4_step/optimization.py | 8 +- psi4_step/psi4.py | 80 ++-- psi4_step/psi4_metadata.py | 542 +++++++++++++++++++----- psi4_step/thermochemistry.py | 368 ++++++++++++++++ psi4_step/thermochemistry_parameters.py | 139 ++++++ psi4_step/thermochemistry_step.py | 95 +++++ psi4_step/tk_energy.py | 75 +++- psi4_step/tk_optimization.py | 6 +- psi4_step/tk_thermochemistry.py | 202 +++++++++ setup.py | 4 +- 15 files changed, 1582 insertions(+), 181 deletions(-) create mode 100644 psi4_step/thermochemistry.py create mode 100644 psi4_step/thermochemistry_parameters.py create mode 100644 psi4_step/thermochemistry_step.py create mode 100644 psi4_step/tk_thermochemistry.py diff --git a/psi4_step/__init__.py b/psi4_step/__init__.py index dcdd233..00b6fe9 100644 --- a/psi4_step/__init__.py +++ b/psi4_step/__init__.py @@ -8,43 +8,48 @@ # Bring up the classes so that they appear to be directly in # the psi4_step package. -from psi4_step.psi4_metadata import methods # noqa: F401 -from psi4_step.psi4_metadata import dft_functionals # noqa: F401 -from psi4_step.psi4_metadata import optimization_methods # noqa: F401 -from psi4_step.psi4_metadata import optimization_convergence # noqa: F401 -from psi4_step.psi4_metadata import metadata # noqa: F401 - -from psi4_step.psi4 import Psi4 # noqa: F401 -from psi4_step.psi4_parameters import Psi4Parameters # noqa: F401 -from psi4_step.psi4_step import Psi4Step # noqa: F401 -from psi4_step.tk_psi4 import TkPsi4 # noqa: F401 - -from psi4_step.initialization import Initialization # noqa: F401 -from psi4_step.initialization_parameters import InitializationParameters # noqa: F401 -from psi4_step.initialization_step import InitializationStep # noqa: F401 -from psi4_step.tk_initialization import TkInitialization # noqa: F401 - -from psi4_step.energy import Energy # noqa: F401 -from psi4_step.energy_parameters import EnergyParameters # noqa: F401 -from psi4_step.energy_step import EnergyStep # noqa: F401 -from psi4_step.tk_energy import TkEnergy # noqa: F401 - -from psi4_step.optimization import Optimization # noqa: F401 -from psi4_step.optimization_parameters import OptimizationParameters # noqa: F401 -from psi4_step.optimization_step import OptimizationStep # noqa: F401 -from psi4_step.tk_optimization import TkOptimization # noqa: F401 - -# from psi4_step.accelerated_optimization import AcceleratedOptimization # noqa: F401 -# from psi4_step.accelerated_optimization_parameters import ( # noqa: F401 +from .psi4_metadata import methods # noqa: F401 +from .psi4_metadata import dft_functionals # noqa: F401 +from .psi4_metadata import optimization_methods # noqa: F401 +from .psi4_metadata import optimization_convergence # noqa: F401 +from .psi4_metadata import metadata # noqa: F401 + +from .psi4 import Psi4 # noqa: F401 +from .psi4_parameters import Psi4Parameters # noqa: F401 +from .psi4_step import Psi4Step # noqa: F401 +from .tk_psi4 import TkPsi4 # noqa: F401 + +from .initialization import Initialization # noqa: F401 +from .initialization_parameters import InitializationParameters # noqa: F401 +from .initialization_step import InitializationStep # noqa: F401 +from .tk_initialization import TkInitialization # noqa: F401 + +from .energy import Energy # noqa: F401 +from .energy_parameters import EnergyParameters # noqa: F401 +from .energy_step import EnergyStep # noqa: F401 +from .tk_energy import TkEnergy # noqa: F401 + +from .optimization import Optimization # noqa: F401 +from .optimization_parameters import OptimizationParameters # noqa: F401 +from .optimization_step import OptimizationStep # noqa: F401 +from .tk_optimization import TkOptimization # noqa: F401 + +# from .accelerated_optimization import AcceleratedOptimization # noqa: F401 +# from .accelerated_optimization_parameters import ( # noqa: F401 # AcceleratedOptimizationParameters, # ) -# from psi4_step.accelerated_optimization_step import ( # noqa: F401 +# from .accelerated_optimization_step import ( # noqa: F401 # AcceleratedOptimizationStep, # ) -# from psi4_step.tk_accelerated_optimization import ( # noqa: F401 +# from .tk_accelerated_optimization import ( # noqa: F401 # TkAcceleratedOptimization, # ) +from .thermochemistry_step import ThermochemistryStep # noqa: F401 +from .thermochemistry import Thermochemistry # noqa: F401 +from .thermochemistry_parameters import ThermochemistryParameters # noqa: F401 +from .tk_thermochemistry import TkThermochemistry # noqa: F401 + # Handle versioneer from ._version import get_versions diff --git a/psi4_step/energy.py b/psi4_step/energy.py index ba3678e..0aafd90 100644 --- a/psi4_step/energy.py +++ b/psi4_step/energy.py @@ -19,7 +19,7 @@ class Energy(seamm.Node): - def __init__(self, flowchart=None, title="Energy", extension=None): + def __init__(self, flowchart=None, title="Energy", extension=None, logger=logger): """Initialize the node""" logger.debug("Creating Energy {}".format(self)) @@ -92,6 +92,14 @@ def description_text(self, P=None, calculation_type="Single-point energy"): text += " The spin will not be restricted and may not be a " text += "proper eigenstate." + # Plotting + if P["density"]: + if P["orbitals"]: + text += "\nThe alpha and beta electron, total, and spin densities, " + text += f"and orbitals {P['selected orbitals']} will be plotted." + elif P["orbitals"]: + text += f"\nThe orbitals {P['selected orbitals']} will be plotted." + return self.header + "\n" + __(text, **P, indent=4 * " ").__str__() def get_input(self, calculation_type="energy", restart=None): @@ -277,7 +285,9 @@ def get_input(self, calculation_type="energy", restart=None): lines.append( " json.dump(fix_multipoles(variables), fd, sort_keys=True, indent=3)" ) - lines.append("") + + # Orbital plots + lines.append(self.plot_input()) return "\n".join(lines) @@ -303,7 +313,7 @@ def analyze(self, indent="", data={}, out=[]): create_tables=self.parameters["create tables"].get(), ) - text = "The calculated energy is {Eelec:.6f} Ha." + text = "The calculated energy is {Eelec:.6f} E_h." else: data = {} tmp = str(json_file) @@ -315,3 +325,106 @@ def analyze(self, indent="", data={}, out=[]): raise RuntimeError(text) printer.normal(__(text, **data, indent=self.indent + 4 * " ")) + + def plot_input(self): + """Generate the input for plotting to cube files.""" + _, configuration = self.get_system_configuration(None) + + P = self.parameters.current_values_to_dict( + context=seamm.flowchart_variables._data + ) + + tasks = [] + if P["density"]: + tasks.append("density") + + orbitals = [] + if P["orbitals"]: + tasks.append("orbitals") + # and work out the orbitals + txt = P["selected orbitals"] + if txt == "all": + pass + else: + # Which is the HOMO orbital? + # This will not work with ECPs. + n_electrons = ( + sum(configuration.atoms.atomic_numbers) - configuration.charge + ) + multiplicity = configuration.spin_multiplicity + homo = (n_electrons - (multiplicity - 1)) // 2 + (multiplicity - 1) + + for chunk in txt.split(","): + chunk = chunk.strip() + if ":" in chunk or ".." in chunk: + if ":" in chunk: + first, last = chunk.split(":") + elif ".." in chunk: + first, last = chunk.split("..") + first = first.strip().upper() + last = last.strip().upper() + + if first == "HOMO": + first = homo + elif first == "LUMO": + first = homo + 1 + else: + first = int(first.removeprefix("HOMO").removeprefix("LUMO")) + if first < 0: + first = homo + first + else: + first = homo + 1 + first + + if last == "HOMO": + last = homo + elif last == "LUMO": + last = homo + 1 + else: + last = int(last.removeprefix("HOMO").removeprefix("LUMO")) + if last < 0: + last = homo + last + else: + last = homo + 1 + last + + orbitals.extend(range(first, last + 1)) + else: + first = chunk.strip().upper() + + if first == "HOMO": + first = homo + elif first == "LUMO": + first = homo + 1 + else: + first = int(first.removeprefix("HOMO").removeprefix("LUMO")) + if first < 0: + first = homo + first + else: + first = homo + 1 + first + orbitals.append(first) + + if len(tasks) == 0: + return "" + + lines = [] + txt = "', '".join(tasks) + lines.append("") + lines.append("# Cube files for density and orbitals") + lines.append(f"set cubeprop_tasks ['{txt}']") + if len(orbitals) > 0: + txt = ", ".join([f"{i}, {-i}" for i in orbitals]) + lines.append(f"set cubeprop_orbitals [{txt}]") + + lines.append("") + lines.append("cubeprop(wfn)") + lines.append( + f""" +# Prefix the files with the substep number +paths = Path.cwd().glob('*.cube') +for path in paths: + name = path.name + newpath = path.with_name('@{self._id[-1]}+' + name) + path.rename(newpath) +""" + ) + + return "\n".join(lines) diff --git a/psi4_step/energy_parameters.py b/psi4_step/energy_parameters.py index 143b449..1fbf17b 100644 --- a/psi4_step/energy_parameters.py +++ b/psi4_step/energy_parameters.py @@ -272,10 +272,45 @@ class EnergyParameters(seamm.Parameters): }, } + output = { + "density": { + "default": "no", + "kind": "boolean", + "default_units": "", + "enumeration": ("yes", "no"), + "format_string": "", + "description": "Plot total density:", + "help_text": "Whether to plot the total charge density.", + }, + "orbitals": { + "default": "no", + "kind": "boolean", + "default_units": "", + "enumeration": ("yes", "no"), + "format_string": "", + "description": "Plot orbitals:", + "help_text": "Whether to plot orbitals.", + }, + "selected orbitals": { + "default": "-1, HOMO, LUMO, +1", + "kind": "string", + "default_units": "", + "enumeration": ("all", "-1, HOMO, LUMO, +1"), + "format_string": "", + "description": "Selected orbitals:", + "help_text": "Which orbitals to plot.", + }, + } + def __init__(self, defaults={}, data=None): """Initialize the instance, by default from the default parameters given in the class""" super().__init__( - defaults={**EnergyParameters.parameters, **defaults}, data=data + defaults={ + **EnergyParameters.parameters, + **EnergyParameters.output, + **defaults, + }, + data=data, ) diff --git a/psi4_step/initialization.py b/psi4_step/initialization.py index d41b8ac..c93ec02 100644 --- a/psi4_step/initialization.py +++ b/psi4_step/initialization.py @@ -87,7 +87,7 @@ def get_input(self): result.append(f"set basis {P['basis']}") result.append("") - # result.append(f"initial.symmetrize({P['symmetry_tolerance']})") + result.append(f"initial.symmetrize({P['symmetry_tolerance']})") result.append("point_group = initial.point_group().symbol()") # Dump the properties to a json file diff --git a/psi4_step/initialization_parameters.py b/psi4_step/initialization_parameters.py index 03c5901..19f903c 100644 --- a/psi4_step/initialization_parameters.py +++ b/psi4_step/initialization_parameters.py @@ -18,18 +18,33 @@ class InitializationParameters(seamm.Parameters): "default_units": "", "enumeration": ( "6-31G", - "6-31G*", - "6-31G**", + "6-31G(d)", + "6-31G(d,p)", + "6-31+G", + "6-31+G(d)", + "6-31+G(d,p)", + "6-311G", + "6-311G(d)", + "6-311G(d,p)", + "6-311+G", + "6-311+G(d)", + "6-311+G(d,p)", "cc-pVDZ", "cc-pVTZ", "cc-pVQZ", + "def2-SV(P)", + "def2-SVP", + "def2-TZVP", + "def2-TZVPP", + "def2-QZVP", + "def2-QZVPP", ), "format_string": "s", "description": "Basis:", "help_text": ("The basis set to use."), }, "symmetry_tolerance": { - "default": "0.05", + "default": "0.00001", "kind": "float", "default_units": None, "enumeration": tuple(), diff --git a/psi4_step/optimization.py b/psi4_step/optimization.py index 28f4ee0..d65124c 100644 --- a/psi4_step/optimization.py +++ b/psi4_step/optimization.py @@ -19,7 +19,13 @@ class Optimization(psi4_step.Energy): - def __init__(self, flowchart=None, title="Optimization", extension=None): + def __init__( + self, + flowchart=None, + title="Optimization", + extension=None, + logger=logger, + ): """Initialize the node""" logger.debug("Creating Optimization {}".format(self)) diff --git a/psi4_step/psi4.py b/psi4_step/psi4.py index 1c13ac9..b0ca38d 100644 --- a/psi4_step/psi4.py +++ b/psi4_step/psi4.py @@ -422,6 +422,7 @@ def run(self): input_data = [] input_data.append("import json") input_data.append("import numpy as np") + input_data.append("from pathlib import Path") input_data.append("import pprint") input_data.append("") input_data.append(f"memory {memory}") @@ -461,36 +462,55 @@ def run(self): directory = Path(self.directory) directory.mkdir(parents=True, exist_ok=True) - return_files = ["output.dat", "*properties.json", "*structure.json"] - exe_path = Path(options["psi4_path"]) - env = { - "PSIPATH": str(exe_path), - "PATH": str(exe_path), - } - - local = seamm.ExecLocal() - exe = exe_path / "psi4" - result = local.run( - cmd=[str(exe), f"-n {n_threads}"], - files=files, - return_files=return_files, - env=env, - directory=directory, - in_situ=True, - ) # yapf: disable - - if result is None: - self.logger.error("There was an error running Psi4") - raise RuntimeError("There was an error running Psi4") - - self.logger.debug("\n" + pprint.pformat(result)) - - failed = False - if "output.dat" in result["files"]: - if result["output.dat"]["data"] is not None: - if "*** Psi4 exiting successfully." not in result["output.dat"]["data"]: - self.logger.warning("Psi4 did not complete successfully.") - failed = True + return_files = ["output.dat", "*.json", "*.cube"] + + # Check for already having run + path = Path(self.directory) / "success.dat" + if path.exists(): + result = {} + path = Path(self.directory) / "stdout.txt" + if path.exists(): + result["stdout"] = path.read_text() + result["stderr"] = "" + failed = False + else: + exe_path = Path(options["psi4_path"]) + env = { + "PSIPATH": str(exe_path), + "PATH": str(exe_path), + } + + local = seamm.ExecLocal() + exe = exe_path / "psi4" + result = local.run( + cmd=[str(exe), f"-n {n_threads}"], + files=files, + return_files=return_files, + env=env, + directory=directory, + in_situ=True, + ) # yapf: disable + + if result is None: + self.logger.error("There was an error running Psi4") + raise RuntimeError("There was an error running Psi4") + + self.logger.debug("\n" + pprint.pformat(result)) + + failed = False + if "output.dat" in result["files"]: + if result["output.dat"]["data"] is not None: + if ( + "*** Psi4 exiting successfully." + not in result["output.dat"]["data"] + ): + self.logger.warning("Psi4 did not complete successfully.") + failed = True + if not failed: + # Write a small file to say that LAMMPS ran successfully, so cancel + # skip if rerunning. + path = Path(self.directory) / "success.dat" + path.write_text("success") # Analyze the results self.analyze() diff --git a/psi4_step/psi4_metadata.py b/psi4_step/psi4_metadata.py index 7882e51..0e807ce 100644 --- a/psi4_step/psi4_metadata.py +++ b/psi4_step/psi4_metadata.py @@ -1625,7 +1625,7 @@ """ metadata["results"] = { "(T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1633,7 +1633,7 @@ "units": "", }, "-D ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "dispersion correction energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1641,7 +1641,7 @@ "units": "E_h", }, "-D GRADIENT": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "gradient of the dispersion correction energy", "dimensionality": [3, "n_atoms"], "methods": ["dft"], @@ -1649,14 +1649,14 @@ "units": "E_h/a_0", }, "32-POLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "5th order electrical multipole", "dimensionality": ["triangular", 3, 3, 3, 3, 3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "AAA (T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1664,7 +1664,7 @@ "units": "E_h", }, "AAB (T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1672,7 +1672,7 @@ "units": "E_h", }, "ABB (T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1680,7 +1680,7 @@ "units": "E_h", }, "B3LYP-D3(BJ) DISPERSION CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the dispersion correction energy", "dimensionality": "scalar", "methods": ["dft"], @@ -1688,7 +1688,7 @@ "units": "E_h", }, "BBB (T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1696,35 +1696,35 @@ "units": "E_h", }, "CC D1 DIAGNOSTIC": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], "type": "float", }, "CC D2 DIAGNOSTIC": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], "type": "float", }, "CC NEW D1 DIAGNOSTIC": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], "type": "float", }, "CC T1 DIAGNOSTIC": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], "type": "float", }, "CCSD CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the correlation energy for a CCSD calculation", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], @@ -1732,7 +1732,7 @@ "units": "E_h", }, "CCSD OPPOSITE-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], @@ -1740,7 +1740,7 @@ "units": "E_h", }, "CCSD SAME-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], @@ -1748,7 +1748,7 @@ "units": "E_h", }, "CCSD TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the total electronic energy from a CCSD calculation", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], @@ -1756,7 +1756,7 @@ "units": "E_h", }, "CCSD(T) CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1764,7 +1764,7 @@ "units": "E_h", }, "CCSD(T) TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd(t)"], @@ -1772,7 +1772,7 @@ "units": "E_h", }, "CURRENT CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the correlation energy for the current method", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "lccd", "mp2", "mp3", "mp4"], @@ -1780,7 +1780,7 @@ "units": "E_h", }, "CURRENT DIPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electrical dipole moment for the current method", "dimensionality": [3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1788,7 +1788,7 @@ "units": "D", }, "CURRENT DIPOLE X": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electrical dipole moment for the current method", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1796,7 +1796,7 @@ "units": "D", }, "CURRENT DIPOLE Y": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electrical dipole moment for the current method", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1804,7 +1804,7 @@ "units": "D", }, "CURRENT DIPOLE Z": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electrical dipole moment for the current method", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1812,7 +1812,7 @@ "units": "D", }, "CURRENT ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electronic energy from the current method", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1821,7 +1821,7 @@ "units": "E_h", }, "CURRENT GRADIENT": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the gradient of the energy for the current method", "dimensionality": [3, "n_atoms"], "methods": ["dft", "hf"], @@ -1829,7 +1829,7 @@ "units": "E_h/a_0", }, "CURRENT REFERENCE ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1837,7 +1837,7 @@ "units": "E_h", }, "DFT FUNCTIONAL TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "total energy of DFT functional", "dimensionality": "scalar", "methods": ["dft"], @@ -1845,7 +1845,7 @@ "units": "E_h", }, "DFT TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "Total DFT energy including dispersion", "dimensionality": "scalar", "methods": ["dft"], @@ -1853,7 +1853,7 @@ "units": "E_h", }, "DFT VV10 ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "VV10 energy in DFT", "dimensionality": "scalar", "methods": ["dft"], @@ -1861,7 +1861,7 @@ "units": "E_h", }, "DFT XC ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "DFT exchange-correlation energy", "dimensionality": "scalar", "methods": ["dft"], @@ -1869,7 +1869,7 @@ "units": "E_h", }, "DIPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment", "dimensionality": [3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1877,7 +1877,7 @@ "units": "D", }, "DIPOLE X": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1885,7 +1885,7 @@ "units": "D", }, "DIPOLE Y": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1893,7 +1893,7 @@ "units": "D", }, "DIPOLE Z": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1901,7 +1901,7 @@ "units": "D", }, "DISPERSION CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "energy of the dispersion correction", "dimensionality": "scalar", "methods": ["dft"], @@ -1909,7 +1909,7 @@ "units": "E_h", }, "ELECTROSTATIC POTENTIAL": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electrostatic potential at the nuclei", "dimensionality": ["n_atoms"], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1917,7 +1917,7 @@ "units": "E_h", }, "Eelec": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the electronic energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1926,14 +1926,14 @@ "units": "E_h", }, "HEXADECAPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical hexadecapole moment", "dimensionality": ["triangular", 3, 3, 3, 3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "HF TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the Hartree-Fock electronic energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1941,7 +1941,7 @@ "units": "E_h", }, "LCCD CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd"], @@ -1949,7 +1949,7 @@ "units": "E_h", }, "LCCD OPPOSITE-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd"], @@ -1957,7 +1957,7 @@ "units": "E_h", }, "LCCD SAME-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd"], @@ -1965,7 +1965,7 @@ "units": "E_h", }, "LCCD TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd"], @@ -1973,7 +1973,7 @@ "units": "E_h", }, "LCCSD (+LMP2) TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)"], @@ -1981,7 +1981,7 @@ "units": "E_h", }, "LOWDIN_CHARGES": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "atomic charges using Lowdin's method", "dimensionality": ["n_atoms"], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -1989,14 +1989,14 @@ "units": "e", }, "MAYER_INDICES": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "Mayer's bond indices", "dimensionality": ["triangular", "n_atoms", "n_atoms"], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "MP2 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "lccd", "mp2", "mp3", "mp4"], @@ -2004,7 +2004,7 @@ "units": "E_h", }, "MP2 OPPOSITE-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "lccd", "mp2", "mp3", "mp4"], @@ -2012,7 +2012,7 @@ "units": "E_h", }, "MP2 SAME-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "lccd", "mp2", "mp3", "mp4"], @@ -2020,7 +2020,7 @@ "units": "E_h", }, "MP2 SINGLES ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp2"], @@ -2028,7 +2028,7 @@ "units": "E_h", }, "MP2 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "lccd", "mp2", "mp3", "mp4"], @@ -2036,7 +2036,7 @@ "units": "E_h", }, "MP2.5 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3", "mp4"], @@ -2044,7 +2044,7 @@ "units": "E_h", }, "MP2.5 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3", "mp4"], @@ -2052,7 +2052,7 @@ "units": "E_h", }, "MP3 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3", "mp4"], @@ -2060,7 +2060,7 @@ "units": "E_h", }, "MP3 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3", "mp4"], @@ -2068,7 +2068,7 @@ "units": "E_h", }, "MP4 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2076,7 +2076,7 @@ "units": "E_h", }, "MP4 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2084,7 +2084,7 @@ "units": "E_h", }, "MP4(SDQ) CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2092,7 +2092,7 @@ "units": "E_h", }, "MP4(SDQ) TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2100,7 +2100,7 @@ "units": "E_h", }, "MP4(SDTQ) CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2108,7 +2108,7 @@ "units": "E_h", }, "MP4(SDTQ) TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2116,7 +2116,7 @@ "units": "E_h", }, "MP4(T) CORRECTION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp4"], @@ -2124,7 +2124,7 @@ "units": "E_h", }, "MULLIKEN_CHARGES": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "atomic charges using Mulliken's method", "dimensionality": ["n_atoms"], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2132,7 +2132,7 @@ "units": "e", }, "NUCLEAR REPULSION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2141,14 +2141,14 @@ "units": "E_h", }, "OCTUPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical octupole moment", "dimensionality": ["triangular", 3, 3, 3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "ONE-ELECTRON ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the one-electron energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2156,14 +2156,14 @@ "units": "E_h", }, "OPTIMIZATION ITERATIONS": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3"], "type": "float", }, "PCM POLARIZATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the PCM polarization energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2172,42 +2172,42 @@ "units": "E_h", }, "QUADRUPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical quadrupole moment", "dimensionality": ["triangular", 3, 3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "SCF DIPOLE": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment from SCF", "dimensionality": [3], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "SCF DIPOLE X": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment from SCF", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "SCF DIPOLE Y": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment from SCF", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "SCF DIPOLE Z": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "electrical dipole moment from SCF", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, "SCF ITERATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2215,14 +2215,14 @@ "units": "E_h", }, "SCF ITERATIONS": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "number of itereations in the SCF", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "integer", }, "SCF TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2230,7 +2230,7 @@ "units": "E_h", }, "SCF TOTAL GRADIENT": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": [3, "n_atoms"], "methods": ["dft", "hf"], @@ -2238,7 +2238,7 @@ "units": "E_h/a_0", }, "SCS-MP2 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp2", "mp3"], @@ -2246,7 +2246,7 @@ "units": "E_h", }, "SCS-MP2 OPPOSITE-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp2"], @@ -2254,7 +2254,7 @@ "units": "E_h", }, "SCS-MP2 SAME-SPIN CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp2"], @@ -2262,7 +2262,7 @@ "units": "E_h", }, "SCS-MP2 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp2", "mp3"], @@ -2270,7 +2270,7 @@ "units": "E_h", }, "SCS-MP2-VDW CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2278,7 +2278,7 @@ "units": "E_h", }, "SCS-MP2-VDW TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2286,7 +2286,7 @@ "units": "E_h", }, "SCS-MP3 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2294,7 +2294,7 @@ "units": "E_h", }, "SCS-MP3 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2302,7 +2302,7 @@ "units": "E_h", }, "SCS-MP3-VDW CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2310,7 +2310,7 @@ "units": "E_h", }, "SCS-MP3-VDW TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2318,7 +2318,7 @@ "units": "E_h", }, "SCSN-MP2 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2326,7 +2326,7 @@ "units": "E_h", }, "SCSN-MP2 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2334,7 +2334,7 @@ "units": "E_h", }, "SCSN-MP3 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2342,7 +2342,7 @@ "units": "E_h", }, "SCSN-MP3 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2350,7 +2350,7 @@ "units": "E_h", }, "SOS-MP2 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2358,7 +2358,7 @@ "units": "E_h", }, "SOS-MP2 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2366,7 +2366,7 @@ "units": "E_h", }, "SOS-MP3 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2374,7 +2374,7 @@ "units": "E_h", }, "SOS-MP3 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2382,7 +2382,7 @@ "units": "E_h", }, "SOS-PI-MP2 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2390,7 +2390,7 @@ "units": "E_h", }, "SOS-PI-MP2 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["lccd", "mp3"], @@ -2398,7 +2398,7 @@ "units": "E_h", }, "SOS-PI-MP3 CORRELATION ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2406,7 +2406,7 @@ "units": "E_h", }, "SOS-PI-MP3 TOTAL ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "", "dimensionality": "scalar", "methods": ["mp3"], @@ -2414,7 +2414,7 @@ "units": "E_h", }, "TWO-ELECTRON ENERGY": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the two-electron energy", "dimensionality": "scalar", "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], @@ -2422,10 +2422,346 @@ "units": "E_h", }, "WIBERG_LOWDIN_INDICES": { - "calculation": ["energy", "optimization", "thermodynamics", "vibrations"], + "calculation": ["energy", "optimization", "thermochemistry", "vibrations"], "description": "the Wiber-Lowdin bond indices", "dimensionality": ["triangular", "n_atoms", "n_atoms"], "methods": ["ccsd", "ccsd(t)", "dft", "hf", "lccd", "mp2", "mp3", "mp4"], "type": "float", }, -} # yapf: disable + "B": { + "calculation": ["thermochemistry"], + "description": "rotational constants", + "dimensionality": [3], + "type": "float", + "units": "cm^-1", + }, + "Cp_elec": { + "calculation": ["thermochemistry"], + "description": "electronic Cp", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cp_rot": { + "calculation": ["thermochemistry"], + "description": "rotational Cp", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cp_tot": { + "calculation": ["thermochemistry"], + "description": "total Cp", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cp_trans": { + "calculation": ["thermochemistry"], + "description": "translational Cp", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cp_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational Cp", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cv_elec": { + "calculation": ["thermochemistry"], + "description": "electronic Cv", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cv_rot": { + "calculation": ["thermochemistry"], + "description": "rotational Cv", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cv_tot": { + "calculation": ["thermochemistry"], + "description": "total Cv", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cv_trans": { + "calculation": ["thermochemistry"], + "description": "translational Cv", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "Cv_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational Cv", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "E0": { + "calculation": ["thermochemistry"], + "description": "electronic energy", + "dimensionality": "scalar", + "type": "float", + "units": "E_h", + }, + "E_corr": { + "calculation": ["thermochemistry"], + "description": "total correction to the energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "E_elec": { + "calculation": ["thermochemistry"], + "description": "electronic correction to the energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "E_rot": { + "calculation": ["thermochemistry"], + "description": "rotational correction to the energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "E_tot": { + "calculation": ["thermochemistry"], + "description": "corrected energy", + "dimensionality": "scalar", + "type": "float", + "units": "E_h", + }, + "E_trans": { + "calculation": ["thermochemistry"], + "description": "translational correction to the energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "E_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational correction to the energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "G_corr": { + "calculation": ["thermochemistry"], + "description": "total correction to the free energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "G_elec": { + "calculation": ["thermochemistry"], + "description": "electronic correction to the free energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "G_rot": { + "calculation": ["thermochemistry"], + "description": "rotational correction to the free energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "G_tot": { + "calculation": ["thermochemistry"], + "description": "corrected free energy", + "dimensionality": "scalar", + "type": "float", + "units": "E_h", + }, + "G_trans": { + "calculation": ["thermochemistry"], + "description": "translational correction to the free energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "G_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational correction to the free energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "H_corr": { + "calculation": ["thermochemistry"], + "description": "total correction to the enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "H_elec": { + "calculation": ["thermochemistry"], + "description": "electronic correction to the enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "H_rot": { + "calculation": ["thermochemistry"], + "description": "rotational correction to the enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "H_tot": { + "calculation": ["thermochemistry"], + "description": "corrected enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "E_h", + }, + "H_trans": { + "calculation": ["thermochemistry"], + "description": "translational correction to the enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "H_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational correction to the enthalpy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "P": { + "calculation": ["thermochemistry"], + "description": "pressure", + "dimensionality": "scalar", + "type": "float", + "units": "atm", + }, + "S_corr": { + "calculation": ["thermochemistry"], + "description": "total correction to the entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "S_elec": { + "calculation": ["thermochemistry"], + "description": "electronic correction to the entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "S_rot": { + "calculation": ["thermochemistry"], + "description": "rotational correction to the entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "S_tot": { + "calculation": ["thermochemistry"], + "description": "corrected entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "S_trans": { + "calculation": ["thermochemistry"], + "description": "translational correction to the entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "S_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational correction to the entropy", + "dimensionality": "scalar", + "type": "float", + "units": "J/mol/K", + }, + "T": { + "calculation": ["thermochemistry"], + "description": "temperature", + "dimensionality": "scalar", + "type": "float", + "units": "K", + }, + "ZPE_corr": { + "calculation": ["thermochemistry"], + "description": "total zero-point energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "ZPE_elec": { + "calculation": ["thermochemistry"], + "description": "electronic zero-point energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "ZPE_rot": { + "calculation": ["thermochemistry"], + "description": "rotational zero-point energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "ZPE_tot": { + "calculation": ["thermochemistry"], + "description": "energy with zero-point", + "dimensionality": "scalar", + "type": "float", + "units": "E_h", + }, + "ZPE_trans": { + "calculation": ["thermochemistry"], + "description": "translational zero-point energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "ZPE_vib": { + "calculation": ["thermochemistry"], + "description": "vibrational zero-point energy", + "dimensionality": "scalar", + "type": "float", + "units": "kJ/mol", + }, + "degeneracy": { + "calculation": ["thermochemistry"], + "description": "degeneracy for the modes", + "dimensionality": ["n_atoms"], + "type": "integer", + "units": "", + }, + "gamma": { + "calculation": ["thermochemistry"], + "description": "symmetry of the modes", + "dimensionality": ["n_atoms"], + "type": "string", + "units": "", + }, + "omega": { + "calculation": ["thermochemistry"], + "description": "vibrational frequencies", + "dimensionality": ["n_atoms", 2], + "type": "string", + "units": "cm^-1", + }, + "sigma": { + "calculation": ["thermochemistry"], + "description": "symmetry number", + "dimensionality": "scalar", + "type": "integer", + "units": "", + }, +} diff --git a/psi4_step/thermochemistry.py b/psi4_step/thermochemistry.py new file mode 100644 index 0000000..8782bb1 --- /dev/null +++ b/psi4_step/thermochemistry.py @@ -0,0 +1,368 @@ +# -*- coding: utf-8 -*- + +"""Non-graphical part of the Thermochemistry step in a Psi4 flowchart +""" + +import json +import logging +from pathlib import Path +import pkg_resources + +from tabulate import tabulate + +import psi4_step +import molsystem +import seamm +from seamm_util import Q_, units_class +import seamm_util.printing as printing +from seamm_util.printing import FormattedText as __ + +# In addition to the normal logger, two logger-like printing facilities are +# defined: "job" and "printer". "job" send output to the main job.out file for +# the job, and should be used very sparingly, typically to echo what this step +# will do in the initial summary of the job. +# +# "printer" sends output to the file "step.out" in this steps working +# directory, and is used for all normal output from this step. + +logger = logging.getLogger(__name__) +job = printing.getPrinter() +printer = printing.getPrinter("Psi4") + +# Add this module's properties to the standard properties +path = Path(pkg_resources.resource_filename(__name__, "data/")) +csv_file = path / "properties.csv" +if path.exists(): + molsystem.add_properties_from_file(csv_file) + + +class Thermochemistry(psi4_step.Energy): + """ + The non-graphical part of a Thermochemistry step in a flowchart. + + Attributes + ---------- + parser : configargparse.ArgParser + The parser object. + + options : tuple + It contains a two item tuple containing the populated namespace and the + list of remaining argument strings. + + subflowchart : seamm.Flowchart + A SEAMM Flowchart object that represents a subflowchart, if needed. + + parameters : ThermochemistryParameters + The control parameters for Thermochemistry. + + See Also + -------- + TkThermochemistry, + Thermochemistry, ThermochemistryParameters + """ + + def __init__( + self, + flowchart=None, + title="Thermochemistry", + extension=None, + logger=logger, + ): + """A substep for Thermochemistry in a subflowchart for Psi4. + + You may wish to change the title above, which is the string displayed + in the box representing the step in the flowchart. + + Parameters + ---------- + flowchart: seamm.Flowchart + The non-graphical flowchart that contains this step. + + title: str + The name displayed in the flowchart. + extension: None + Not yet implemented + logger : Logger = logger + The logger to use and pass to parent classes + + Returns + ------- + None + """ + logger.debug(f"Creating Thermochemistry {self}") + + super().__init__( + flowchart=flowchart, + title=title, + extension=extension, + logger=logger, + ) + + self._calculation = "thermochemistry" + self._model = None + self._metadata = psi4_step.metadata + self.parameters = psi4_step.ThermochemistryParameters() + + @property + def header(self): + """A printable header for this section of output""" + return "Step {}: {}".format(".".join(str(e) for e in self._id), self.title) + + @property + def version(self): + """The semantic version of this module.""" + return psi4_step.__version__ + + @property + def git_revision(self): + """The git version of this module.""" + return psi4_step.__git_revision__ + + def description_text(self, P=None): + """Create the text description of what this step will do. + The dictionary of control values is passed in as P so that + the code can test values, etc. + + Parameters + ---------- + P: dict + An optional dictionary of the current values of the control + parameters. + Returns + ------- + str + A description of the current step. + """ + if not P: + P = self.parameters.values_to_dict() + + text = super().description_text(P=P, calculation_type="Thermochemistry") + + added = ( + "\nThe thermodynamic functions will be calculated at temperature {T} and " + "pressure {P}." + ) + + return text + "\n" + __(added, **P, indent=4 * " ").__str__() + + def get_input(self, calculation_type="frequency"): + """Get the input for an optimization calculation for Psi4""" + _, configuration = self.get_system_configuration() + + # Create the directory + directory = Path(self.directory) + directory.mkdir(parents=True, exist_ok=True) + + # references = self.parent.references + + P = self.parameters.current_values_to_dict( + context=seamm.flowchart_variables._data + ) + # Have to fix formatting for printing... + PP = dict(P) + for key in PP: + if isinstance(PP[key], units_class): + PP[key] = "{:~P}".format(PP[key]) + + self.description = [] + self.description.append(__(self.description_text(PP), **PP, indent=self.indent)) + # Figure out what we are doing! The method is HF, B3LYP, CCSD, etc. + if P["level"] == "recommended": + method_string = P["method"] + else: + method_string = P["advanced_method"] + + if method_string in psi4_step.methods: + method = psi4_step.methods[method_string]["method"] + else: + method = method_string + + if method == "dft": + if P["level"] == "recommended": + functional_string = P["functional"] + else: + functional_string = P["advanced_functional"] + method = psi4_step.dft_functionals[functional_string]["name"] + if ( + P["dispersion"] != "none" + and len(psi4_step.dft_functionals[functional_string]["dispersion"]) > 1 + ): + method = method + "-" + P["dispersion"] + + lines = [] + lines.append("") + lines.append("#" * 80) + lines.append(f"# {self.header}") + lines.append("#" * 80) + lines.append("") + # lines.append("initial.find_point_group(tolerance=1.0e-5)") + lines.append("initial.symmetrize(1.0e-5)") + lines.append("point_group = initial.point_group().symbol()") + lines.append("") + + if not P["use existing parameters"]: + # Add in the input from the energy part of things + lines.append(super().get_input(calculation_type=calculation_type)) + else: + lines.append(f"Eelec, wfn = frequency('{method}', return_wfn=True)") + + # Orbital plots + lines.append(self.plot_input()) + + lines.append( + f""" +set writer_file_label thermo +set hessian_write on + +thermo_vibinfo = vibanal_wfn(wfn) +path = Path(core.get_writer_file_prefix('thermo') + '.vibrec') +with path.open() as fd: + tmp = json.load(fd) +tmp2 = dict() +for key, value in tmp.items(): + if type(value) == str: + tmp2[key] = json.loads(value) + else: + tmp2[key] = value + +with path.with_name('@{self._id[-1]}+thermochemistry.json').open('w') as fd: + json.dump(tmp2, fd, sort_keys=True, indent=3) +""" + ) + + return "\n".join(lines) + + def analyze(self, indent="", **kwargs): + """Do any analysis of the output from this step. + + Also print important results to the local step.out file using + "printer". + + Parameters + ---------- + indent: str + An extra indentation for the output + """ + # Read in the results from json + directory = Path(self.directory) + json_file = directory / "thermochemistry.json" + if json_file.exists(): + with json_file.open() as fd: + tmp = json.load(fd) + + # Process the data, changing units + d = {} + metadata = self.metadata["results"] + for key, value in tmp.items(): + if key in metadata: + from_units = value["units"].replace("Eh", "E_h") + to_units = metadata[key]["units"] + if from_units == to_units: + d[key] = value["data"] + else: + d[key] = Q_(value["data"], from_units).m_as(to_units) + + # Put any requested results into variables or tables + self.store_results(data=d, create_tables=True) + + # And the output + table = { + "": [ + "Units", + "Electronic", + "Translational", + "Rotational", + "Vibrational", + "Total Correction", + "Total (E_h)", + ], + "S": [ + "J/mol/K", + round(d["S_elec"], 2), + round(d["S_trans"], 2), + round(d["S_rot"], 2), + round(d["S_vib"], 2), + round(d["S_tot"], 2), + ], + "Cv": [ + "J/mol/K", + round(d["Cv_elec"], 2), + round(d["Cv_trans"], 2), + round(d["Cv_rot"], 2), + round(d["Cv_vib"], 2), + round(d["Cv_tot"], 2), + ], + "Cp": [ + "J/mol/K", + round(d["Cp_elec"], 2), + round(d["Cp_trans"], 2), + round(d["Cp_rot"], 2), + round(d["Cp_vib"], 2), + round(d["Cp_tot"], 2), + ], + "E": [ + "kJ/mol", + round(d["E_elec"], 2), + round(d["E_trans"], 2), + round(d["E_rot"], 2), + round(d["E_vib"], 2), + round(d["E_corr"], 2), + round(d["E_tot"], 6), + ], + "H": [ + "kJ/mol", + round(d["H_elec"], 2), + round(d["H_trans"], 2), + round(d["H_rot"], 2), + round(d["H_vib"], 2), + round(d["H_corr"], 2), + round(d["H_tot"], 6), + ], + "G": [ + "kJ/mol", + round(d["G_elec"], 2), + round(d["G_trans"], 2), + round(d["G_rot"], 2), + round(d["G_vib"], 2), + round(d["G_corr"], 2), + round(d["G_tot"], 6), + ], + } + + text = "" + tmp = tabulate( + table, + headers="keys", + tablefmt="simple_outline", + disable_numparse=True, + numalign="decimal", + stralign="center", + colalign=( + "center", + "decimal", + "decimal", + "decimal", + "decimal", + "decimal", + "decimal", + ), + ) + length = len(tmp.splitlines()[0]) + text += "\n" + parameters = self.parameters.current_values_to_dict( + context=seamm.flowchart_variables._data + ) + T = parameters["T"] + P = parameters["P"] + text += f"Thermodynamic Functions at {T:.2f~P} and {P:.2f~P}".center(length) + text += "\n" + text += tmp + text += "\n" + printer.normal(__(text, indent=8 * " ", wrap=False, dedent=False)) + else: + text = ( + "\nThere are no thermochemistry results from Psi4. Perhaps it " + f"failed? Looking for {str(json_file)}." + ) + printer.normal(__(text, indent=self.indent + 4 * " ")) + raise RuntimeError(text) diff --git a/psi4_step/thermochemistry_parameters.py b/psi4_step/thermochemistry_parameters.py new file mode 100644 index 0000000..3ebe431 --- /dev/null +++ b/psi4_step/thermochemistry_parameters.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +""" +Control parameters for the Thermochemistry step in a Psi4 flowchart +""" + +import logging + +from .energy_parameters import EnergyParameters + +logger = logging.getLogger(__name__) + + +class ThermochemistryParameters(EnergyParameters): + """ + The control parameters for Thermochemistry. + + You need to replace the "time" entry in dictionary below these comments with the + definitions of parameters to control this step. The keys are parameters for the + current plugin,the values are dictionaries as outlined below. + + Examples + -------- + :: + + parameters = { + "time": { + "default": 100.0, + "kind": "float", + "default_units": "ps", + "enumeration": tuple(), + "format_string": ".1f", + "description": "Simulation time:", + "help_text": ("The time to simulate in the dynamics run.") + }, + } + + parameters : {str: {str: str}} + A dictionary containing the parameters for the current step. + Each key of the dictionary is a dictionary that contains the + the following keys: + + parameters["default"] : + The default value of the parameter, used to reset it. + + parameters["kind"] : enum() + Specifies the kind of a variable. One of "integer", "float", "string", + "boolean", or "enum" + + While the "kind" of a variable might be a numeric value, it may still have + enumerated custom values meaningful to the user. For instance, if the parameter + is a convergence criterion for an optimizer, custom values like "normal", + "precise", etc, might be adequate. In addition, any parameter can be set to a + variable of expression, indicated by having "$" as the first character in the + field. For example, $OPTIMIZER_CONV. + + parameters["default_units"] : str + The default units, used for resetting the value. + + parameters["enumeration"]: tuple + A tuple of enumerated values. + + parameters["format_string"]: str + A format string for "pretty" output. + + parameters["description"]: str + A short string used as a prompt in the GUI. + + parameters["help_text"]: str + A longer string to display as help for the user. + + See Also + -------- + Thermochemistry, TkThermochemistry, Thermochemistry + ThermochemistryParameters, ThermochemistryStep + """ + + parameters = { + "use existing parameters": { + "default": "yes", + "kind": "boolean", + "default_units": None, + "enumeration": ("yes", "no"), + "format_string": "", + "description": "Use existing parameters", + "help_text": "Whether to use existing parameters from the previous step", + }, + "T": { + "default": 298.15, + "kind": "float", + "default_units": "K", + "enumeration": tuple(), + "format_string": ".2f", + "description": "Temperature:", + "help_text": "The temperature for the thermochemistry.", + }, + "P": { + "default": 1.0, + "kind": "float", + "default_units": "bar", + "enumeration": tuple(), + "format_string": ".2f", + "description": "Pressure:", + "help_text": "The pressure for the thermochemistry.", + }, + # # Results handling ... uncomment if needed + # "results": { + # "default": {}, + # "kind": "dictionary", + # "default_units": "", + # "enumeration": tuple(), + # "format_string": "", + # "description": "results", + # "help_text": "The results to save to variables or in tables.", + # }, + } + + def __init__(self, defaults={}, data=None): + """ + Initialize the parameters, by default with the parameters defined above + + Parameters + ---------- + defaults: dict + A dictionary of parameters to initialize. The parameters + above are used first and any given will override/add to them. + data: dict + A dictionary of keys and a subdictionary with value and units + for updating the current, default values. + + Returns + ------- + None + """ + + logger.debug("ThermochemistryParameters.__init__") + + super().__init__( + defaults={**ThermochemistryParameters.parameters, **defaults}, data=data + ) diff --git a/psi4_step/thermochemistry_step.py b/psi4_step/thermochemistry_step.py new file mode 100644 index 0000000..b2e9195 --- /dev/null +++ b/psi4_step/thermochemistry_step.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- + +import psi4_step # noqa: E999 + + +class ThermochemistryStep(object): + """Helper class needed for the stevedore integration. + + This must provide a `description()` method that returns a dict containing a + description of this node, and `create_node()` and `create_tk_node()` methods + for creating the graphical and non-graphical nodes. + + The dictionary for the description is the class variable just below these + comments. The felds are as follows: + + my_description : {str, str} + A human-readable description of this step. It can be + several lines long, and needs to be clear to non-expert users. + It contains the following keys: description, group, name. + + my_description["description"] : tuple + A description of the Thermochemistry step. It must be + clear to non-experts. + + my_description["group"] : str + Which group in the menus to put this step. If the group does + not exist it will be created. Common groups are "Building", + "Control", "Custom", "Data", and "Simulations". + + my_description["name"] : str + The name of this step, to be displayed in the menus. + """ + + my_description = { + "description": "An interface for Thermochemistry", + "group": "Calculation", + "name": "Thermochemistry", + } + + def __init__(self, flowchart=None, gui=None): + """Initialize this helper class, which is used by + the application via stevedore to get information about + and create node objects for the flowchart + """ + pass + + def create_node(self, flowchart=None, **kwargs): + """Create and return the new node object. + + Parameters + ---------- + flowchart: seamm.Node + A non-graphical SEAMM node + + **kwargs : keyword arguments + Various keyword arguments such as title, namespace or + extension representing the title displayed in the flowchart, + the namespace for the plugins of a subflowchart and + the extension, respectively. + + Returns + ------- + Thermochemistry + """ + + return psi4_step.Thermochemistry(flowchart=flowchart, **kwargs) + + def create_tk_node(self, canvas=None, **kwargs): + """Create and return the graphical Tk node object. + + Parameters + ---------- + canvas : tk.Canvas + The Tk Canvas widget + + **kwargs : keyword arguments + Various keyword arguments such as tk_flowchart, node, x, y, w, h + representing a graphical flowchart object, a non-graphical node for + a step, and dimensions of the graphical node. + + Returns + ------- + TkThermochemistry + """ + + return psi4_step.TkThermochemistry(canvas=canvas, **kwargs) + + def description(self): + """Return a description of what this step does. + + Returns + ------- + description : dict(str, str) + """ + return ThermochemistryStep.my_description diff --git a/psi4_step/tk_energy.py b/psi4_step/tk_energy.py index 196ed88..f396fef 100644 --- a/psi4_step/tk_energy.py +++ b/psi4_step/tk_energy.py @@ -135,24 +135,58 @@ def create_dialog(self, title="Edit Psi4 Energy Step"): self[key].bind("", self.reset_convergence) self[key].bind("", self.reset_convergence) + # A tab for output -- orbitals, etc. + notebook = self["notebook"] + self["output frame"] = oframe = ttk.Frame(notebook) + notebook.insert(self["results frame"], oframe, text="Output", sticky="new") + + # Frame to isolate widgets + p_frame = self["plot frame"] = ttk.LabelFrame( + self["output frame"], + borderwidth=4, + relief="sunken", + text="Plots", + labelanchor="n", + padding=10, + ) + + for key in psi4_step.EnergyParameters.output: + self[key] = P[key].widget(p_frame) + + # Set the callbacks for changes + for widget in ("orbitals",): + w = self[widget] + w.combobox.bind("<>", self.reset_plotting) + w.combobox.bind("", self.reset_plotting) + w.combobox.bind("", self.reset_plotting) + p_frame.grid(row=0, column=0, sticky="new") + oframe.columnconfigure(0, weight=1) + + self.reset_plotting() + # Top level needs to call reset_dialog if self.node.calculation == "energy": self.reset_dialog() self.logger.debug("Finished creating the dialog") - def reset_dialog(self, widget=None): + return frame + + def reset_dialog(self, row=0, widget=None): """Layout the widgets as needed for the current state""" frame = self["frame"] - for slave in frame.grid_slaves(): - slave.grid_forget() + if row == 0: + for slave in frame.grid_slaves(): + slave.grid_forget() - self["calculation"].grid(row=0, column=0) + self["calculation"].grid(row=row, column=0) self.reset_calculation() - self["convergence"].grid(row=1, column=0) + row += 1 + self["convergence"].grid(row=row, column=0) self.reset_convergence() - return 2 + row += 1 + return row def reset_calculation(self, widget=None): level = self["level"].get() @@ -291,3 +325,32 @@ def reset_convergence(self, widget=None): frame.columnconfigure(0, minsize=150) sw.align_labels(widgets, sticky=tk.E) sw.align_labels(widgets2, sticky=tk.E) + + def reset_plotting(self, widget=None): + frame = self["plot frame"] + for slave in frame.grid_slaves(): + slave.grid_forget() + + plot_orbitals = self["orbitals"].get() == "yes" + + widgets = [] + + row = 0 + for key in ( + "density", + "orbitals", + ): + self[key].grid(row=row, column=0, columnspan=4, sticky=tk.EW) + widgets.append(self[key]) + row += 1 + + if plot_orbitals: + key = "selected orbitals" + self[key].grid(row=row, column=1, columnspan=4, sticky=tk.EW) + row += 1 + + sw.align_labels(widgets, sticky=tk.E) + frame.columnconfigure(0, minsize=50) + frame.columnconfigure(4, weight=1) + + return row diff --git a/psi4_step/tk_optimization.py b/psi4_step/tk_optimization.py index 5b49e20..8ac4b99 100644 --- a/psi4_step/tk_optimization.py +++ b/psi4_step/tk_optimization.py @@ -83,7 +83,7 @@ def create_dialog(self, title="Edit Psi4 Optimization Step"): logger.debug("TkOptimization.create_dialog") # Let parent classes do their thing. - super().create_dialog(title=title) + frame = super().create_dialog(title=title) # Shortcut for parameters P = self.node.parameters @@ -92,7 +92,7 @@ def create_dialog(self, title="Edit Psi4 Optimization Step"): # Frame to isolate widgets opt_frame = self["optimization"] = ttk.LabelFrame( - self["frame"], + frame, borderwidth=4, relief="sunken", text="Geometry Optimization", @@ -116,6 +116,8 @@ def create_dialog(self, title="Edit Psi4 Optimization Step"): if self.node.calculation == "optimization": self.reset_dialog() + return frame + def reset_dialog(self, widget=None): """Layout the widgets, letting our parents go first.""" rows = super().reset_dialog() diff --git a/psi4_step/tk_thermochemistry.py b/psi4_step/tk_thermochemistry.py new file mode 100644 index 0000000..d4532dc --- /dev/null +++ b/psi4_step/tk_thermochemistry.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- + +"""The graphical part of a Thermochemistry step""" + +import logging +import tkinter as tk +import tkinter.ttk as ttk + +import psi4_step +import seamm_widgets as sw + +logger = logging.getLogger(__name__) + + +class TkThermochemistry(psi4_step.TkEnergy): + """ + The graphical part of a Thermochemistry step in a flowchart. + + Attributes + ---------- + tk_flowchart : TkFlowchart = None + The flowchart that we belong to. + node : Node = None + The corresponding node of the non-graphical flowchart + canvas: tkCanvas = None + The Tk Canvas to draw on + dialog : Dialog + The Pmw dialog object + x : int = None + The x-coordinate of the center of the picture of the node + y : int = None + The y-coordinate of the center of the picture of the node + w : int = 200 + The width in pixels of the picture of the node + h : int = 50 + The height in pixels of the picture of the node + self[widget] : dict + A dictionary of tk widgets built using the information + contained in Thermochemistry_parameters.py + + See Also + -------- + Thermochemistry, TkThermochemistry, + ThermochemistryParameters, + """ + + def __init__( + self, + tk_flowchart=None, + node=None, + canvas=None, + x=None, + y=None, + w=200, + h=50, + my_logger=logger, + ): + """ + Initialize a graphical node. + + Parameters + ---------- + tk_flowchart: Tk_Flowchart + The graphical flowchart that we are in. + node: Node + The non-graphical node for this step. + namespace: str + The stevedore namespace for finding sub-nodes. + canvas: Canvas + The Tk canvas to draw on. + x: float + The x position of the nodes center on the canvas. + y: float + The y position of the nodes cetner on the canvas. + w: float + The nodes graphical width, in pixels. + h: float + The nodes graphical height, in pixels. + + Returns + ------- + None + """ + self.dialog = None + + super().__init__( + tk_flowchart=tk_flowchart, + node=node, + canvas=canvas, + x=x, + y=y, + w=w, + h=h, + my_logger=my_logger, + ) + + def create_dialog(self): + """ + Create the dialog. A set of widgets will be chosen by default + based on what is specified in the Thermochemistry_parameters + module. + + Parameters + ---------- + None + + Returns + ------- + None + + See Also + -------- + TkThermochemistry.reset_dialog + """ + + frame = super().create_dialog(title="Thermochemistry") + + # Shortcut for parameters + P = self.node.parameters + + # Frame to isolate widgets + thermo_frame = self["thermochemistry"] = ttk.LabelFrame( + frame, + borderwidth=4, + relief="sunken", + text="Thermochemistry", + labelanchor="n", + padding=10, + ) + # Then create the widgets + for key in psi4_step.ThermochemistryParameters.parameters: + self[key] = P[key].widget(thermo_frame) + + # and binding to change as needed + for key in ("use existing parameters",): + self[key].combobox.bind("<>", self.reset_thermochemistry) + self[key].combobox.bind("", self.reset_thermochemistry) + self[key].combobox.bind("", self.reset_thermochemistry) + + # Top level needs to call reset_dialog + if self.node.calculation == "thermochemistry": + self.reset_dialog() + + return frame + + def reset_dialog(self, widget=None, row=0): + """Layout the widgets in the dialog. + + The widgets are chosen by default from the information in + Thermochemistry_parameter. + + This function simply lays them out row by row with + aligned labels. You may wish a more complicated layout that + is controlled by values of some of the control parameters. + If so, edit or override this method + + Parameters + ---------- + widget : Tk Widget = None + + Returns + ------- + None + + See Also + -------- + TkThermochemistry.create_dialog + """ + # Remove any widgets previously packed + frame = self["frame"] + if row == 0: + for slave in frame.grid_slaves(): + slave.grid_forget() + + # Shortcut for parameters + P = self.node.parameters + + self["thermochemistry"].grid(row=row, column=0) + row += 1 + + self.reset_thermochemistry() + + if not P["use existing parameters"]: + row = super().reset_dialog(row=row) + else: + self.reset_calculation() + return row + + def reset_thermochemistry(self, widget=None): + frame = self["thermochemistry"] + for slave in frame.grid_slaves(): + slave.grid_forget() + + widgets = [] + row = 0 + + for key in ("use existing parameters", "T", "P"): + self[key].grid(row=row, column=0, sticky=tk.EW) + widgets.append(self[key]) + row += 1 + + sw.align_labels(widgets) diff --git a/setup.py b/setup.py index 668e074..0e4ca88 100644 --- a/setup.py +++ b/setup.py @@ -69,14 +69,16 @@ 'Psi4 = psi4_step:Psi4Step', ], 'org.molssi.seamm.psi4': [ + 'Thermochemistry = psi4_step:ThermochemistryStep', 'Energy = psi4_step:EnergyStep', 'Initialization = psi4_step:InitializationStep', 'Optimization = psi4_step:OptimizationStep', ], 'org.molssi.seamm.psi4.tk': [ + 'Thermochemistry = psi4_step:ThermochemistryStep', 'Energy = psi4_step:EnergyStep', 'Initialization = psi4_step:InitializationStep', 'Optimization = psi4_step:OptimizationStep', ], } -) +) \ No newline at end of file From 0ad5496d70ebe4b3da7562c74517d625f9c7df4c Mon Sep 17 00:00:00 2001 From: Paul Saxe Date: Sun, 4 Jun 2023 21:56:30 -0400 Subject: [PATCH 2/3] Preparing for release. --- HISTORY.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 33f034f..716e79f 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,11 @@ History ======= +2023.6.4 -- Enhancements + * Added thermochemistry substep to compute the vibrational and other corrections for + thermochemistry. + * Added ability to create .cube files for plotting the density and orbitals. + 2023.2.21 -- Added control over SCF convergence * Able to set convergence criteria. * Options for damping. level shifting and second-order SCF From ab5634a73c179a399e1191956f75a1d61aafd433 Mon Sep 17 00:00:00 2001 From: Paul Saxe Date: Mon, 5 Jun 2023 07:46:21 -0400 Subject: [PATCH 3/3] Added missed requirement on tabulate. --- devtools/conda-envs/test_env.yaml | 1 + requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index adbc905..0ac073c 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -14,6 +14,7 @@ dependencies: - psutil - scipy - seamm + - tabulate # Testing - black diff --git a/requirements.txt b/requirements.txt index 2e408a1..581ba2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ numpy psutil scipy seamm +tabulate