def check_isomorphic(conformer): """ Compares whatever is in the log file 'f' to the SMILES of the passed in 'conformer' """ starting_molecule = RMGMolecule(SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() atoms = self.read_log(os.path.join(scratch_dir, f)) test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) return False else: logging.info("{} was successful and was validated!".format( calc.label)) return True
def calculate_conformer(self, conformer, calculator): if isinstance(calculator, Gaussian): calc = calculator.get_conformer_calc(conformer=conformer, convergence='Tight') else: calc = calculator.get_conformer_calc(conformer=conformer) scratch = calculator.scratch scratch_dir = os.path.join(calculator.scratch, "species", conformer.smiles, "conformers") f = calc.label + ".log" if not os.path.exists(os.path.join(scratch_dir, f)): logging.info("Submitting conformer calculation for {}".format( calc.label)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) else: logging.info( "It appears that we already have a complete log file for {}". format(calc.label)) complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if not complete: logging.info( "It seems that the file never completed for {} completed, running it again" .format(calc.label)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if (complete and converged): logging.info("{} was successful and was validated!".format( calc.label)) atoms = self.read_log(os.path.join(scratch_dir, f)) starting_molecule = RMGMolecule(SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) result = False else: logging.info("{} was successful and was validated!".format( calc.label)) result = True if not complete: logging.info("It appears that {} was killed prematurely".format( calc.label)) result = False elif not converged: logging.info("{} did not converge".format(calc.label)) result = False if isinstance(calculator, Gaussian): if not calc.convergence.lower() in [ "tight", "verytight", "loose" ]: logging.info("{} failed QM optimization".format( calc.label)) else: logging.info( "Resubmitting {} with default convergence criteria". format(calc.label)) atoms = self.read_log(os.path.join(scratch_dir, f)) conformer.ase_molecule = atoms conformer.update_coords_from("ase") calc = calculator.get_conformer_calc(conformer, convergence="") logging.info( "Removing the old log file that didn't converge, restarting from last geometry" ) os.remove(os.path.join(scratch_dir, f)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) scratch_dir = os.path.join(calculator.scratch, "species", conformer.smiles, "conformers") f = calc.label + ".log" if not os.path.exists(os.path.join(scratch_dir, f)): logging.info( "It seems that {} was never run...".format( calc.label)) result = False complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if not complete: logging.info( "It appears that {} was killed prematurely".format( calc.label)) result = False elif not converged: logging.info("{} failed second QM optimization".format( calc.label)) result = False else: atoms = self.read_log(os.path.join(scratch_dir, f)) starting_molecule = RMGMolecule( SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) result = False else: logging.info( "{} was successful and was validated!".format( calc.label)) result = True if not result: fail_dir = os.path.join(scratch_dir, "failures") try: os.makedirs(os.path.join(scratch_dir, "failures")) except OSError: logging.info("{} already exists...".format(fail_dir)) move(os.path.join(scratch_dir, f), os.path.join(scratch_dir, "failures", f)) return False return True
def validate_irc(self, calc=None): """ A method to verify an IRC calc """ assert "irc" in calc.label, "The calculator provided is not an IRC calculator" reaction_label = calc.label.split("_irc")[0] logging.info("Validating IRC file...") irc_path = os.path.join(calc.scratch, calc.label + ".log") if not os.path.exists(irc_path): logging.info("It seems that the IRC claculation has not been run.") return False f = open(irc_path, "r") file_lines = f.readlines()[-5:] completed = False for file_line in file_lines: if "Normal termination" in file_line: logging.info("IRC successfully ran") completed = True if not completed: logging.info("IRC failed... could not be validated...") return False pth1 = list() steps = list() with open(irc_path) as outputFile: for line in outputFile: line = line.strip() if line.startswith('Point Number:'): if int(line.split()[2]) > 0: if int(line.split()[-1]) == 1: ptNum = int(line.split()[2]) pth1.append(ptNum) else: pass elif line.startswith('# OF STEPS ='): numStp = int(line.split()[-1]) steps.append(numStp) # This indexes the coordinate to be used from the parsing if steps == []: logging.error('No steps taken in the IRC calculation!') return False else: pth1End = sum(steps[:pth1[-1]]) # Compare the reactants and products ircParse = ccread(irc_path) # cf. # http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information atomcoords = ircParse.atomcoords atomnos = ircParse.atomnos # Convert the IRC geometries into RMG molecules # We don't know which is reactant or product, so take the two at the end of the # paths and compare to the reactants and products mol1 = RMGMolecule() mol1.fromXYZ(atomnos, atomcoords[pth1End]) mol2 = RMGMolecule() mol2.fromXYZ(atomnos, atomcoords[-1]) testReaction = RMGReaction( reactants=mol1.split(), products=mol2.split(), ) r, p = reaction_label.split("_") reactants = [] products = [] for react in r.split("+"): react = RMGMolecule(SMILES=react) reactants.append(react) for prod in p.split("+"): prod = RMGMolecule(SMILES=prod) products.append(prod) possible_reactants = [] possible_products = [] for reactant in reactants: possible_reactants.append( reactant.generate_resonance_structures()) for product in products: possible_products.append( product.generate_resonance_structures()) possible_reactants = list(itertools.product(*possible_reactants)) possible_products = list(itertools.product(*possible_products)) for possible_reactant in possible_reactants: reactant_list = [] for react in possible_reactant: reactant_list.append(react.toSingleBonds()) for possible_product in possible_products: product_list = [] for prod in possible_product: product_list.append(prod.toSingleBonds()) targetReaction = RMGReaction(reactants=list(reactant_list), products=list(product_list)) if targetReaction.isIsomorphic(testReaction): logging.info("IRC calculation was successful!") return True logging.info("IRC calculation failed for {} :(".format(calc.label)) return False
def validate_irc(self): """ A method to verify an IRC calc """ logging.info("Validating IRC file...") irc_path = os.path.join( self.directory, "ts", self.conformer.reaction_label, "irc", self.conformer.reaction_label + "_irc_" + self.conformer.direction + "_" + str(self.conformer.index) + ".log") complete, converged = self.verify_output_file(irc_path) if not complete: logging.info("It seems that the IRC claculation did not complete") return False if not converged: logging.info("The IRC calculation did not converge...") return False pth1 = list() steps = list() with open(irc_path) as outputFile: for line in outputFile: line = line.strip() if line.startswith('Point Number:'): if int(line.split()[2]) > 0: if int(line.split()[-1]) == 1: ptNum = int(line.split()[2]) pth1.append(ptNum) else: pass elif line.startswith('# OF STEPS ='): numStp = int(line.split()[-1]) steps.append(numStp) # This indexes the coordinate to be used from the parsing if steps == []: logging.error('No steps taken in the IRC calculation!') return False else: pth1End = sum(steps[:pth1[-1]]) # Compare the reactants and products ircParse = ccread(irc_path) atomcoords = ircParse.atomcoords atomnos = ircParse.atomnos mol1 = RMGMolecule() mol1.fromXYZ(atomnos, atomcoords[pth1End]) mol2 = RMGMolecule() mol2.fromXYZ(atomnos, atomcoords[-1]) testReaction = RMGReaction( reactants=mol1.split(), products=mol2.split(), ) r, p = self.conformer.reaction_label.split("_") reactants = [] products = [] for react in r.split("+"): react = RMGMolecule(SMILES=react) reactants.append(react) for prod in p.split("+"): prod = RMGMolecule(SMILES=prod) products.append(prod) possible_reactants = [] possible_products = [] for reactant in reactants: possible_reactants.append( reactant.generate_resonance_structures()) for product in products: possible_products.append( product.generate_resonance_structures()) possible_reactants = list(itertools.product(*possible_reactants)) possible_products = list(itertools.product(*possible_products)) for possible_reactant in possible_reactants: reactant_list = [] for react in possible_reactant: reactant_list.append(react.toSingleBonds()) for possible_product in possible_products: product_list = [] for prod in possible_product: product_list.append(prod.toSingleBonds()) targetReaction = RMGReaction(reactants=list(reactant_list), products=list(product_list)) if targetReaction.isIsomorphic(testReaction): logging.info("IRC calculation was successful!") return True logging.info("IRC calculation failed for {} :(".format(calc.label)) return False