def test_multiple_paramaters(self): """ This test makes sure that input files with multi-parameter keywords and route cards with multiple lines can be parsed accurately. """ filepath = os.path.join(test_dir, "l-cysteine.inp") route = { "test": None, "integral": { "grid": "UltraFine" }, "opt": { "Z-Matrix": None, "maxcycles": "80", "tight": None }, } gin = GaussianInput.from_file(filepath) self.assertEqual(gin.dieze_tag, "#n") self.assertEqual(gin.functional, "B3LYP") self.assertEqual(gin.basis_set, "6-31+G**") self.assertEqual(gin.route_parameters, route) self.assertEqual(gin.title, "L-cysteine neutral") self.assertEqual(gin.charge, 0) self.assertEqual(gin.spin_multiplicity, 1)
def test_from_file(self): filepath = os.path.join(test_dir, "MethylPyrrolidine_drawn.gjf") gau = GaussianInput.from_file(filepath) self.assertEqual(gau.molecule.composition.formula, "H11 C5 N1") self.assertIn("opt", gau.route_parameters) self.assertEqual(gau.route_parameters["geom"], "connectivity") self.assertEqual(gau.functional, "b3lyp") self.assertEqual(gau.basis_set, "6-311+g(d,p)") filepath = os.path.join(test_dir, "g305_hb.txt") with open(filepath) as f: txt = f.read() toks = txt.split("--link1--") for i, t in enumerate(toks): lines = t.strip().split("\n") lines = [l.strip() for l in lines] gau = GaussianInput.from_string("\n".join(lines)) self.assertIsNotNone(gau.molecule) if i == 0: mol = gau.molecule ans = """Full Formula (H4 O2) Reduced Formula: H2O Charge = 0, Spin Mult = 1 Sites (6) 0 O 0.000000 0.000000 0.000000 1 O 0.000000 0.000000 2.912902 2 H 0.892596 0.000000 -0.373266 3 H 0.143970 0.000219 0.964351 4 H -0.582554 0.765401 3.042783 5 H -0.580711 -0.766761 3.043012""" self.assertEqual(str(mol), ans)
def test_from_file(self): filepath = os.path.join(test_dir, 'MethylPyrrolidine_drawn.gjf') gau = GaussianInput.from_file(filepath) self.assertEqual(gau.molecule.composition.formula, "H11 C5 N1") self.assertIn("opt", gau.route_parameters) self.assertEqual(gau.route_parameters["geom"], "connectivity") self.assertEqual(gau.functional, "b3lyp") self.assertEqual(gau.basis_set, "6-311+g(d,p)") filepath = os.path.join(test_dir, "g305_hb.txt") with open(filepath) as f: txt = f.read() toks = txt.split("--link1--") for i, t in enumerate(toks): lines = t.strip().split("\n") lines = [l.strip() for l in lines] gau = GaussianInput.from_string("\n".join(lines)) self.assertIsNotNone(gau.molecule) if i == 0: mol = gau.molecule ans = """Full Formula (H4 O2) Reduced Formula: H2O Charge = 0, Spin Mult = 1 Sites (6) 0 O 0.000000 0.000000 0.000000 1 O 0.000000 0.000000 2.912902 2 H 0.892596 0.000000 -0.373266 3 H 0.143970 0.000219 0.964351 4 H -0.582554 0.765401 3.042783 5 H -0.580711 -0.766761 3.043012""" self.assertEqual(str(mol), ans)
def read_mol(filename): """ Reads a molecule based on file extension. For example, anything ending in a "xyz" is assumed to be a XYZ file. Supported formats include xyz, gaussian input (gjf|g03|g09|com|inp), Gaussian output (.out|and pymatgen's JSON serialized molecules. Using openbabel, many more extensions are supported but requires openbabel to be installed. Args: filename (str): A filename to read from. Returns: A Molecule object. """ fname = os.path.basename(filename) if fnmatch(fname.lower(), "*.xyz*"): return XYZ.from_file(filename).molecule elif any([fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["gjf", "g03", "g09", "com", "inp"]]): return GaussianInput.from_file(filename).molecule elif any([fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["out", "lis", "log"]]): return GaussianOutput(filename).final_structure elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"): with zopen(filename) as f: s = json.load(f, cls=MontyDecoder) if type(s) != Molecule: raise IOError("File does not contain a valid serialized " "molecule") return s else: m = re.search("\.(pdb|mol|mdl|sdf|sd|ml2|sy2|mol2|cml|mrv)", filename.lower()) if m: return BabelMolAdaptor.from_file(filename, m.group(1)).pymatgen_mol raise ValueError("Unrecognized file extension!")
def better_guess(cls, gaussian_cmd, input_file, output_file, stderr_file='stderr.txt', backup=True, cart_coords=True): orig_input = GaussianInput.from_file(input_file) yield (GaussianJob(gaussian_cmd=gaussian_cmd, input_file=input_file, output_file=output_file, stderr_file=stderr_file, suffix='.guess1', backup=backup)) if GaussianErrorHandler.activate_better_guess: # TODO: check why it comes here only if the lower job is not # failing and not in the else condition # continue only if other corrections are invalid or failed lower_output = GaussianOutput(output_file) if len(lower_output.errors) == 0: # if the calculation at the lower level of theory succeeded if not filter(os.listdir('.'), '*.[Cc][Hh][Kk]'): raise FileNotFoundError( 'Missing checkpoint file. Required ' 'to read initial guesses') gin = GaussianInput( mol=None, charge=orig_input.charge, spin_multiplicity=orig_input.spin_multiplicity, title=orig_input.title, functional=orig_input.functional, basis_set=orig_input.basis_set, route_parameters=lower_output.route_parameters, input_parameters=orig_input.input_parameters, link0_parameters=orig_input.link0_parameters, dieze_tag=orig_input.dieze_tag, gen_basis=orig_input.gen_basis) gin.route_parameters['Guess'] = 'Read' gin.route_parameters['Geom'] = 'Checkpoint' gin.write_file(input_file, cart_coords=cart_coords) yield (GaussianJob(gaussian_cmd=gaussian_cmd, input_file=input_file, output_file=output_file, stderr_file=stderr_file, suffix='.guess2', backup=backup)) else: logger.info('Failed to generate a better initial guess') else: logger.info('Calculation completed normally without having to ' 'generate a better initial guess')
def test_multiple_paramaters(self): """ This test makes sure that input files with multi-parameter keywords and route cards with multiple lines can be parsed accurately. """ filepath = os.path.join(test_dir, "l-cysteine.inp") route = {"test": None, "integral": {"grid": "UltraFine"}, "opt": {"Z-Matrix": None, "maxcycles": "80", "tight": None}} gin = GaussianInput.from_file(filepath) self.assertEqual(gin.dieze_tag, "#n") self.assertEqual(gin.functional, "B3LYP") self.assertEqual(gin.basis_set, "6-31+G**") self.assertEqual(gin.route_parameters, route) self.assertEqual(gin.title, "L-cysteine neutral") self.assertEqual(gin.charge, 0) self.assertEqual(gin.spin_multiplicity, 1)
def read_mol(filename): """ Reads a molecule based on file extension. For example, anything ending in a "xyz" is assumed to be a XYZ file. Supported formats include xyz, gaussian input (gjf|g03|g09|com|inp), Gaussian output (.out|and pymatgen's JSON serialized molecules. Using openbabel, many more extensions are supported but requires openbabel to be installed. Args: filename (str): A filename to read from. Returns: A Molecule object. """ fname = os.path.basename(filename) if fnmatch(fname.lower(), "*.xyz*"): return XYZ.from_file(filename).molecule elif any([ fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["gjf", "g03", "g09", "com", "inp"] ]): return GaussianInput.from_file(filename).molecule elif any([ fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["out", "lis", "log"] ]): return GaussianOutput(filename).final_structure elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"): with zopen(filename) as f: s = json.load(f, cls=MontyDecoder) if type(s) != Molecule: raise IOError("File does not contain a valid serialized " "molecule") return s else: m = re.search("\.(pdb|mol|mdl|sdf|sd|ml2|sy2|mol2|cml|mrv)", filename.lower()) if m: return BabelMolAdaptor.from_file(filename, m.group(1)).pymatgen_mol raise ValueError("Unrecognized file extension!")
def calculate_properties(rin, directory): with cd(directory): # found that the relax often crashed or didn't finish, so will restart # the calculation in these cases try: rout = GaussianOutput('relax.log') if not rout.properly_terminated: logging.info('restarting {}'.format(directory)) route = rout.route route['integral'] = '(acc2e=12)' rout.to_input('relax.com', cart_coords=True, route_parameters=route) os.system('g09 < relax.com > relax.log') except IOError: # relaxation hasn't been run yet logging.info('started processing {}'.format(directory)) rin.write_file('relax.com', cart_coords=True) os.system('g09 < relax.com > relax.log') except IndexError, AttributeError: # the relax calculation used the wrong header, fix this and restart rin = GaussianInput.from_file('relax.com') rin.route_parameters['integral'] = '(acc2e=12)' rin.write_file('relax.com', cart_coords=True) os.system('g09 < relax.com > relax.log') rout = GaussianOutput('relax.log') if not rout.properly_terminated: logging.error( '{} relaxation did not terminate correctly'.format(directory)) return 0 # do the TD-DFT calculation tdin = GaussianInput(rout.final_structure, charge=0, title=rin.title, functional=functional, spin_multiplicity=1, basis_set=basis_set, dieze_tag=dieze_tag, link0_parameters=link0, route_parameters=td_params) td_done = False if os.path.isfile('td.log'): tdout = GaussianOutput('td.log') if tdout.properly_terminated: td_done = True if not td_done: tdin.write_file('td.com', cart_coords=True) os.system('g09 < td.com > td.log') tdout = GaussianOutput('td.log') if not tdout.properly_terminated: logging.error( '{} TD-DFT did not terminate correctly'.format(directory)) return 0 # do the TD-DFT calculation w. Tamm-Dancoff approx tdain = GaussianInput(rout.final_structure, charge=0, title=rin.title, spin_multiplicity=1, functional=functional, basis_set=basis_set, dieze_tag=dieze_tag, link0_parameters=link0, route_parameters=tda_params) tda_done = False if os.path.isfile('tda.log'): tdaout = GaussianOutput('tda.log') if tdaout.properly_terminated: tda_done = True if not tda_done: tdain.write_file('tda.com', cart_coords=True) os.system('g09 < tda.com > tda.log') tdaout = GaussianOutput('tda.log') if not tdaout.properly_terminated: logging.error( '{} TDA-DFT did not terminate correctly'.format(directory)) return 0 # add the dummy atoms for the NICS(1)_zz calculations mol_nics = rout.final_structure mol_nics = add_dummy_atoms(mol_nics, six_mem_a) mol_nics = add_dummy_atoms(mol_nics, six_mem_b) mol_nics = add_dummy_atoms(mol_nics, five_mem_a) mol_nics = add_dummy_atoms(mol_nics, five_mem_b) # run NICS on the ground state and triplet state nicssin = GaussianInput(mol_nics, charge=0, title=rin.title, spin_multiplicity=1, functional=functional, basis_set=basis_set, dieze_tag=dieze_tag, link0_parameters=link0, route_parameters=nmr_params) nicssin.write_file('nics_singlet.com', cart_coords=True) # work around as pymatgen does not allow Bq as an element os.system("sed -i 's/X-Bq0+/Bq/g' nics_singlet.com") os.system('g09 < nics_singlet.com > nics_singlet.log') # can't have NICS job completion check due to above mentioned pmg bug nicstin = GaussianInput(mol_nics, charge=0, title=rin.title, spin_multiplicity=3, functional=functional, basis_set=basis_set, dieze_tag=dieze_tag, link0_parameters=link0, route_parameters=nmr_params) nicstin.write_file('nics_triplet.com', cart_coords=True) os.system("sed -i 's/X-Bq0+/Bq/g' nics_triplet.com") os.system('g09 < nics_triplet.com > nics_triplet.log')
'title': ginp.title, 'index': index}) ############################################ # generate substituted pyridine structures # ############################################ # need to consider that nx positions 2 and 3 are incompatible # with substitutional sites z and y, respectively and ny # position 3 is incompatible with substitional site x # # the other important note is that we need to substitute the atoms from the # highest site_id downwards, otherwise the order and index of the atoms will # change gin = GaussianInput.from_file(os.path.join('..', 'templates', 'input-template.com')) gin.route_parameters['integral'] = '(acc2e=12)' # hack to get round pmg bug print "generating pyridine substituted structures..." for nx, ny, x_sub, y_sub, z_sub in itertools.product(nx_sites, ny_sites, subs, subs, subs): mol = copy.deepcopy(gin) # if there are any clashes then skip the structure if ((x_sub[0] and ny[0] == 3) or (y_sub[0] and nx[0] == 3) or (z_sub[0] and nx[0] == 2)): continue # make a list of the substitutions and sort from highest to lowest site_id # this list includes the H atoms next to the N we introduce in to the rings sub_list = []