diff --git a/ccinput/constants.py b/ccinput/constants.py index 546fd88..15e4840 100644 --- a/ccinput/constants.py +++ b/ccinput/constants.py @@ -19,6 +19,7 @@ class CalcType(Enum): CONSTR_CONF_SEARCH = 15 OPTFREQ = 20 + TSFREQ = 21 ATOMIC_NUMBER = {} @@ -118,6 +119,7 @@ class CalcType(Enum): "mos", ], CalcType.OPTFREQ: ["Opt+Freq Calculation", "optfreq", "opt+freq"], + CalcType.TSFREQ: ["TS+Freq Calculation", "tsfreq", "ts+freq"], CalcType.CONF_SEARCH: [ "Conformational Search", "conformersearch", diff --git a/ccinput/packages/gaussian.py b/ccinput/packages/gaussian.py index efd4103..c931faa 100644 --- a/ccinput/packages/gaussian.py +++ b/ccinput/packages/gaussian.py @@ -41,6 +41,7 @@ class GaussianCalculation: CalcType.UVVIS: ["td"], CalcType.UVVIS_TDA: ["tda"], CalcType.OPTFREQ: ["opt", "freq"], + CalcType.TSFREQ: ["opt", "freq"], } # Get a set of all unique calculation keywords diff --git a/ccinput/packages/nwchem.py b/ccinput/packages/nwchem.py index 382a239..c947a71 100644 --- a/ccinput/packages/nwchem.py +++ b/ccinput/packages/nwchem.py @@ -56,6 +56,7 @@ class NWChemCalculation: CalcType.NMR: ["property"], CalcType.SP: ["energy"], CalcType.OPTFREQ: ["optimize", "freq"], + CalcType.TSFREQ: ["optimize", "freq"], CalcType.MEP: ["neb ignore"], } @@ -280,6 +281,7 @@ def add_option(self, key, option): CalcType.OPT, CalcType.TS, CalcType.OPTFREQ, + CalcType.TSFREQ, ] ): if self.calculation_block == "": @@ -291,7 +293,7 @@ def add_option(self, key, option): if self.calculation_block == "": self.calculation_block += f"\n freq \n" self.calculation_block += f"{command} \n" - elif block_name == "freq" and self.calc.type == CalcType.OPTFREQ: + elif block_name == "freq" and self.calc.type in [CalcType.OPTFREQ, CalcType.TSFREQ]: temp += f"{command} \n" elif ( block_name in ["neb", "string", "fsm", "mep"] diff --git a/ccinput/packages/orca.py b/ccinput/packages/orca.py index 1fa34a1..67af4ec 100644 --- a/ccinput/packages/orca.py +++ b/ccinput/packages/orca.py @@ -56,6 +56,7 @@ class OrcaCalculation: CalcType.UVVIS, CalcType.MO, CalcType.OPTFREQ, + CalcType.TSFREQ, ] def __init__(self, calc): @@ -142,6 +143,10 @@ def handle_command(self): self.command_line = "OPT " elif self.calc.type == CalcType.OPTFREQ: self.command_line = "OPT FREQ " + elif self.calc.type == CalcType.TSFREQ: + self.command_line = "OPTTS FREQ " + if self.calc.parameters.theory_level != "xtb": + self.add_to_block("geom", ["Calc_Hess true"]) elif self.calc.type == CalcType.TS: self.command_line = "OPTTS " if self.calc.parameters.theory_level != "xtb": diff --git a/ccinput/packages/psi4.py b/ccinput/packages/psi4.py index 401ef72..6cb61b7 100644 --- a/ccinput/packages/psi4.py +++ b/ccinput/packages/psi4.py @@ -35,6 +35,7 @@ class Psi4Calculation: CalcType.FREQ: ["freq", "frequency", "frequencies"], # CalcType.TS, CalcType.OPTFREQ: ["Opt+Freq Calculation", "optfreq", "opt+freq"], + CalcType.TSFREQ: ["TS+Freq Calculation", "tsfreq", "ts+freq"], } def __init__(self, calc: Calculation): @@ -250,6 +251,34 @@ def handle_command(self): calc_type["freq"], method, basis_set, specifications=freq_specs ) self.command_line += f"{cmls_opt}\n{cmls_freqs}" + elif self.calc.type == CalcType.TSFREQ: + multi_specs = self.convert_multispecs_to_dictionary() + calc_type = {"freq": "frequencies", "ts": "ts"} + ts_specs = None + freq_specs = None + + if "ts" in multi_specs: + ts_specs = str("") + ts_specs += self.handle_specifications(multi_specs["ts"]) + if "freq" in multi_specs: + freq_specs = str("") + freq_specs += self.handle_specifications(multi_specs["freq"]) + elif "ts" not in multi_specs: + ts_specs = None + elif "freq" not in multi_specs: + freq_specs = None + else: + raise InvalidParameter( + f"Keys in {multi_specs.keys()} not valid for {self.calc.type} type of calculation" + ) + + cmls_ts = self.create_command_line_string( + calc_type["ts"], method, basis_set, specifications=ts_specs + ) + cmls_freqs = self.create_command_line_string( + calc_type["freq"], method, basis_set, specifications=freq_specs + ) + self.command_line += f"{cmls_ts}\n{cmls_freqs}" else: raise UnimplementedError( f"Calculation Type {self.calc.type} not implemented yet for psi4" diff --git a/ccinput/packages/xtb.py b/ccinput/packages/xtb.py index 7c80bb8..c14527a 100644 --- a/ccinput/packages/xtb.py +++ b/ccinput/packages/xtb.py @@ -13,6 +13,7 @@ class XtbCalculation: CalcType.SP: "xtb", CalcType.UVVIS_TDA: "stda", CalcType.OPTFREQ: "xtb", + CalcType.TSFREQ: "xtb", CalcType.CONF_SEARCH: "crest", CalcType.CONSTR_CONF_SEARCH: "crest", } @@ -323,6 +324,8 @@ def handle_command(self): self.main_command += "--opt " elif self.calc.type == CalcType.OPTFREQ: self.main_command = "--ohess " # Not sure if the tightness will be parsed + elif self.calc.type == CalcType.TSFREQ: + self.main_command = "--ohess " # Same as OPTFREQ for xtb elif self.calc.type == CalcType.CONSTR_CONF_SEARCH: self.main_command += f"-cinp {aux_input} " elif self.calc.type == CalcType.CONSTR_OPT: