def get_irc_calc(self, ts=None, mem="5GB", nprocshared=20, scratch=".", method="m062x", basis="6-311+g(2df,2p)"): "A method to create the IRC calculator object" if ts is None: if self.ts is None: return None elif not isinstance(self.conformer, TS): return None else: ts = self.conformer ts.rmg_molecule.updateMultiplicity() label = ts.reaction_label.replace( "(", "left").replace(")", "right") + "_irc_" + str(ts.index) calc = ASEGaussian(mem=mem, nprocshared=nprocshared, label=label, scratch=scratch, method=method, basis=basis, extra="irc=(calcall)", multiplicity=ts.rmg_molecule.multiplicity) calc.atoms = ts.ase_molecule del calc.parameters['force'] return calc
def get_overall_calc(self, ts=None, direction="forward", settings=None, scratch=None): """ A method to create a calculator that optimizes the overall geometry of a `TS` object Parameters: - ts (TS): A `TS` object that you want to perform calculations on - direction (str): the forward or reverse direction of the `TS` object - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ if settings is None: settings = self.settings if scratch is None: scratch = self.scratch method = settings["method"] basis = settings["basis"] mem = settings["mem"] nprocshared = settings["nprocshared"] assert direction.lower() in ["forward", "reverse"] assert isinstance(ts, TS), "A TS object was not provided..." ts.rmg_molecule.updateMultiplicity() label = ts.reaction_label + "_" + direction.lower() + "_" + str( ts.index) new_scratch = os.path.join(scratch, "ts", ts.reaction_label, "conformers") try: os.makedirs(new_scratch) except OSError: pass calc = ASEGaussian( mem=mem, nprocshared=nprocshared, label=label, scratch=new_scratch, method=method, basis=basis, extra= "opt=(ts,calcfc,noeigentest,maxcycles=900) freq scf=(maxcycle=900) IOP(7/33=1,2/16=3)", multiplicity=ts.rmg_molecule.multiplicity) calc.atoms = ts.ase_molecule del calc.parameters['force'] return calc
def get_rotor_calc(self, conformer=None, torsion=None, mem="5GB", nprocshared=20, scratch=".", method="m062x", basis="6-311+g(2df,2p)", steps=36, step_size=10.0): """ A method to create all of the calculators needed to perform hindered rotor calculations given a conformer and a torsion """ assert (torsion and (isinstance(torsion, Torsion)) ), "To create a rotor calculator, you must provide a Torsion object." if not conformer: if not self.conformer: return None conformer = self.conformer assert isinstance( conformer, Conformer), "A Conformer object was not provided..." string = "" for bond in conformer.bonds: i, j = bond.atom_indices string += "B {} {}\n".format(i + 1, j + 1) i, j, k, l = torsion.atom_indices string += "D {} {} {} {} S {} {}".format(i + 1, j + 1, k + 1, l + 1, steps, float(step_size)) if isinstance(conformer, TS): label = self.label + "_tor_{}_{}".format(j, k) elif isinstance(conformer, Conformer): label = Chem.rdinchi.InchiToInchiKey(Chem.MolToInchi( Chem.MolFromSmiles(conformer.smiles))).strip("-N") label += "_tor{}{}".format(j, k) label = conformer.smiles + "_tor_{}_{}".format(j, k) conformer.rmg_molecule.updateMultiplicity() mult = conformer.rmg_molecule.multiplicity calc = ASEGaussian(mem=mem, nprocshared=nprocshared, label=label, scratch=scratch, method=method, basis=basis, extra="Opt=(CalcFC,ModRedun)", multiplicity=mult, addsec=[string]) calc.atoms = conformer.ase_molecule del calc.parameters['force'] return calc
def get_center_calc(self): """ A method to create a calculator that optimizes the reaction center of a `TS` object Parameters: - ts (TS): A `TS` object that you want to perform calculations on - direction (str): the forward or reverse direction of the `TS` object - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ assert self.conformer.direction.lower() in ["forward", "reverse"] assert isinstance(self.conformer, TS), "A TS object was not provided..." indicies = [] for i, atom in enumerate(self.conformer.rmg_molecule.atoms): if not (atom.label != ""): indicies.append(i) addsec = "" for combo in list(itertools.combinations(indicies, 2)): a, b = combo addsec += "{0} {1} F\n".format(a + 1, b + 1) self.conformer.rmg_molecule.updateMultiplicity() label = self.conformer.reaction_label + "_" + self.conformer.direction.lower( ) + "_center_" + str(self.conformer.index) new_scratch = os.path.join(self.directory, "ts", self.conformer.reaction_label, "conformers") try: os.makedirs(new_scratch) except OSError: pass ase_gaussian = ASEGaussian( mem=self.settings["mem"], nprocshared=self.settings["nprocshared"], label=label, scratch=new_scratch, method=self.settings["method"], basis=self.settings["basis"], extra= "Opt=(ts,calcfc,noeigentest,ModRedun,maxcycles=900) scf=(maxcycle=900)", multiplicity=self.conformer.rmg_molecule.multiplicity, addsec=[addsec[:-1]]) ase_gaussian.atoms = self.conformer.ase_molecule del ase_gaussian.parameters['force'] return ase_gaussian
def get_shell_calc(self): """ A method to create a calculator that optimizes the reaction shell of a `TS` object Parameters: - ts (TS): A `TS` object that you want to perform calculations on - direction (str): the forward or reverse direction of the `TS` object - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - directory (str): a directory where you want log files to be written to Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ assert isinstance(self.conformer, TS), "A TS object was not provided..." assert self.conformer.direction.lower() in ["forward", "reverse"] self.conformer.rmg_molecule.updateMultiplicity() label = self.conformer.reaction_label + "_" + self.conformer.direction.lower( ) + "_shell_" + str(self.conformer.index) new_scratch = os.path.join(self.directory, "ts", self.conformer.reaction_label, "conformers") try: os.makedirs(new_scratch) except OSError: pass ind1 = self.conformer.rmg_molecule.getLabeledAtom("*1").sortingLabel ind2 = self.conformer.rmg_molecule.getLabeledAtom("*2").sortingLabel ind3 = self.conformer.rmg_molecule.getLabeledAtom("*3").sortingLabel combos = "" combos += "{0} {1} F\n".format(ind1 + 1, ind2 + 1) combos += "{0} {1} F\n".format(ind2 + 1, ind3 + 1) combos += "{0} {1} {2} F".format(ind1 + 1, ind2 + 1, ind3 + 1) ase_gaussian = ASEGaussian( mem=self.settings["mem"], nprocshared=self.settings["nprocshared"], label=label, scratch=new_scratch, method=self.settings["method"], basis=self.settings["basis"], extra= "Opt=(ModRedun,Loose,maxcycles=900) Int(Grid=SG1) scf=(maxcycle=900)", multiplicity=self.conformer.rmg_molecule.multiplicity, addsec=[combos]) ase_gaussian.atoms = self.conformer.ase_molecule del ase_gaussian.parameters['force'] return ase_gaussian
def get_conformer_calc(self): """ A method that creates a calculator for a `Conformer` that will perform a geometry optimization Parameters: - conformer (Conformer): A `Conformer` object that you want to perform hindered rotor calculations on - torsion (Torsion): A `Torsion` object that you want to perform hindered rotor calculations about - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to - convergence (str): ['verytight','tight','' (default)], specifies the convergence criteria of the geometry optimization Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ if isinstance(self.conformer, TS): logging.info( "TS object provided, cannot obtain a species calculator for a TS" ) return None assert isinstance(self.conformer, Conformer), "A Conformer object was not provided..." self.conformer.rmg_molecule.updateMultiplicity() label = "{}_{}".format(self.conformer.smiles, self.conformer.index) new_scratch = os.path.join(self.directory, "species", self.conformer.smiles, "conformers") try: os.makedirs(new_scratch) except OSError: pass ase_gaussian = ASEGaussian( mem=self.settings["mem"], nprocshared=self.settings["nprocshared"], label=label, scratch=new_scratch, method=self.settings["method"], basis=self.settings["basis"], extra= "opt=(calcfc,maxcycles=900,{}) freq IOP(7/33=1,2/16=3) scf=(maxcycle=900)" .format(self.convergence), multiplicity=self.conformer.rmg_molecule.multiplicity) ase_gaussian.atoms = self.conformer.ase_molecule del ase_gaussian.parameters['force'] return ase_gaussian
def get_center_calc(self, ts=None, mem="5GB", nprocshared=20, scratch=".", method="m062x", basis="6-311+g(2df,2p)"): "A method to create a calculator that optimizes the reaction shell" if ts is None: if self.ts is None: return None elif not isinstance(self.conformer, TS): return None else: ts = self.conformer assert isinstance(ts, TS), "A TS object was not provided..." indicies = [] for i, atom in enumerate(ts.rmg_molecule.atoms): if not (atom.label != ""): indicies.append(i) combos = "" for combo in list(itertools.combinations(indicies, 2)): a, b = combo combos += "{0} {1} F\n".format(a + 1, b + 1) ts.rmg_molecule.updateMultiplicity() label = ts.reaction_label.replace("(", "left").replace( ")", "right") + "_center" calc = ASEGaussian( mem=mem, nprocshared=nprocshared, label=label, scratch=scratch, method=method, basis=basis, extra="Opt=(ModRedun,Loose,maxcycle=1000) Int(Grid=SG1)", multiplicity=ts.rmg_molecule.multiplicity, addsec=[combos[:-1]]) del calc.parameters['force'] return calc
def get_species_calc(self, conformer=None, mem="5GB", nprocshared=20, scratch=".", method="m062x", basis="6-311+g(2df,2p)"): "A method that creates a calculator for a reactant or product that will perform a geometry optimization" if not conformer: if not self.conformer: return None conformer = self.conformer if isinstance(conformer, TS): logging.info( "TS object provided, cannot obtain a species calculator for a TS" ) return None assert isinstance(conformer, Conformer), "A Conformer object was not provided..." conformer.rmg_molecule.updateMultiplicity() # using this round about way of doing stuff because rmg's `toAugumentedInChIKey` method doesn't work on our cluster smiles = conformer.rmg_molecule.toSMILES() label = Chem.rdinchi.InchiToInchiKey( Chem.MolToInchi( Chem.MolFromSmiles(smiles))).strip("-N") + "_{}".format( conformer.index) calc = ASEGaussian( mem=mem, nprocshared=nprocshared, label=label, scratch=scratch, method=method, basis=basis, extra="opt=(verytight,gdiis,maxcycle=1000) freq IOP(2/16=3)", multiplicity=conformer.rmg_molecule.multiplicity) del calc.parameters['force'] return calc
def get_irc_calc(self): """ A method to create a calculator that runs an IRC calculation the overall geometry of a `TS` object Parameters: - ts (TS): A `TS` object that you want to perform calculations on - direction (str): the forward or reverse direction of the `TS` object - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ assert isinstance(self.conformer, TS), "A TS object was not provided..." self.conformer.rmg_molecule.updateMultiplicity() label = self.conformer.reaction_label + "_irc_" + self.conformer.direction + "_" + str( self.conformer.index) new_scratch = os.path.join(self.directory, "ts", self.conformer.reaction_label, "irc") try: os.makedirs(new_scratch) except OSError: pass ase_gaussian = ASEGaussian( mem=self.settings["mem"], nprocshared=self.settings["nprocshared"], label=label, scratch=new_scratch, method=self.settings["method"], basis=self.settings["basis"], extra="irc=(calcall)", multiplicity=self.conformer.rmg_molecule.multiplicity) ase_gaussian.atoms = self.conformer.ase_molecule del ase_gaussian.parameters['force'] return ase_gaussian
def get_overall_calc(self, ts=None, mem="5GB", nprocshared=20, scratch=".", method="m062x", basis="6-311+g(2df,2p)"): "A method to create a calculator that optimizes the reaction shell" if ts is None: if self.ts is None: return None elif not isinstance(self.conformer, TS): return None else: ts = self.conformer assert isinstance(ts, TS), "A TS object was not provided..." ts.rmg_molecule.updateMultiplicity() label = ts.reaction_label.replace( "(", "left").replace(")", "right") + "_" + str(ts.index) calc = ASEGaussian( mem=mem, nprocshared=nprocshared, label=label, scratch=scratch, method=method, basis=basis, extra="opt=(ts,calcfc,noeigentest,maxcycles=900) freq", multiplicity=ts.rmg_molecule.multiplicity) calc.atoms = ts.ase_molecule del calc.parameters['force'] return calc
def get_rotor_calc(self, conformer=None, torsion=None, settings=None, scratch=None, steps=36, step_size=10.0): """ A method to create all of the calculators needed to perform hindered rotor calculations given a `Conformer` and a `Torsion`. Parameters: - conformer (Conformer): A `Conformer` object that you want to perform hindered rotor calculations on - torsion (Torsion): A `Torsion` object that you want to perform hindered rotor calculations about - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to - steps (int): the number of steps you want performed in this scan - step_size (float): the size, in degrees, of the step you to scan along Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ if settings is None: settings = self.settings if scratch is None: scratch = self.scratch method = settings["method"] basis = settings["basis"] mem = settings["mem"] nprocshared = settings["nprocshared"] assert ( torsion and (isinstance(torsion, Torsion)) ), "To create a rotor calculator, you must provide a Torsion object." assert isinstance(conformer, Conformer), "A Conformer object was not provided..." if isinstance(conformer, TS): extra = "Opt=(ts,CalcFC,ModRedun)" else: extra = "Opt=(CalcFC,ModRedun)" string = "" for bond in conformer.bonds: i, j = bond.atom_indices string += "B {} {}\n".format(i + 1, j + 1) i, j, k, l = torsion.atom_indices string += "D {} {} {} {} S {} {}\n".format(i + 1, j + 1, k + 1, l + 1, steps, float(step_size)) if isinstance(conformer, TS): label = da = conformer.reaction_label label += "_{}by{}_{}_{}".format(steps, int(step_size), j, k) t = "ts" elif isinstance(conformer, Conformer): label = da = conformer.smiles label += "_{}by{}_{}_{}".format(steps, int(step_size), j, k) t = "species" for locked_torsion in conformer.torsions: # TODO: maybe doesn't work; if sorted(locked_torsion.atom_indices) != sorted( torsion.atom_indices): a, b, c, d = locked_torsion.atom_indices string += 'D {0} {1} {2} {3} F\n'.format( a + 1, b + 1, c + 1, d + 1) conformer.rmg_molecule.updateMultiplicity() mult = conformer.rmg_molecule.multiplicity new_scratch = os.path.join(scratch, t, da, "rotors") calc = ASEGaussian(mem=mem, nprocshared=nprocshared, label=label, scratch=new_scratch, method=method, basis=basis, extra=extra, multiplicity=mult, addsec=[string[:-1]]) calc.atoms = conformer.ase_molecule del calc.parameters['force'] return calc
def get_conformer_calc(self, conformer=None, settings=None, scratch=None, convergence=None): """ A method that creates a calculator for a `Conformer` that will perform a geometry optimization Parameters: - conformer (Conformer): A `Conformer` object that you want to perform hindered rotor calculations on - torsion (Torsion): A `Torsion` object that you want to perform hindered rotor calculations about - settings (dict): a dictionary of settings containing method, basis, mem, nprocshared - scratch (str): a directory where you want log files to be written to - steps (int): the number of steps you want performed in this scan - step_size (float): the size, in degrees, of the step you to scan along - convergence (str): ['verytight','tight','' (default)], specifies the convergence criteria of the geometry optimization Returns: - calc (ASEGaussian): an ASEGaussian calculator with all of the proper setting specified """ if settings is None: settings = self.settings if scratch is None: scratch = self.scratch if convergence is None: convergence = self.convergence assert convergence.lower() in ["", "verytight", "tight", "loose"] method = settings["method"] basis = settings["basis"] mem = settings["mem"] nprocshared = settings["nprocshared"] if isinstance(conformer, TS): logging.info( "TS object provided, cannot obtain a species calculator for a TS" ) return None assert isinstance(conformer, Conformer), "A Conformer object was not provided..." conformer.rmg_molecule.updateMultiplicity() short_label = conformer.smiles label = short_label + "_{}".format(conformer.index) new_scratch = os.path.join(scratch, "species", short_label, "conformers") try: os.makedirs(new_scratch) except OSError: pass calc = ASEGaussian( mem=mem, nprocshared=nprocshared, label=label, scratch=new_scratch, method=method, basis=basis, extra= "opt=(CalcFC,MaxCycles=900,{}) freq IOp(7/33=1,2/16=3) scf=(MaxCycle=900)" .format(convergence), multiplicity=conformer.rmg_molecule.multiplicity) calc.atoms = conformer.ase_molecule calc.convergence = convergence del calc.parameters['force'] return calc