def make_rotors(self, species, norot=None): rotors = [] if self.par['rotor_scan']: for i, rot in enumerate(species.dihed): if norot is not None: if frequencies.skip_rotor(norot, rot) == 1: continue rotorpot, rotortype = self.make_rotorpot(species, i, rot) if rotortype == 'hindered': rotors.append( self.hinderedrotortpl.format( group=' '.join([ str(pi + 1) for pi in frequencies.partition( species, rot, species.natom)[0][1:] ]), axis='{} {}'.format(str(rot[1] + 1), str(rot[2] + 1)), rotorsymm=self.rotorsymm(species, rot), nrotorpot=self.nrotorpot(species, rot), rotorpot=rotorpot)) elif rotortype == 'free': rotors.append( self.freerotortpl.format( geom=self.make_geom(species), natom=species.natom, group=' '.join([ str(pi + 1) for pi in frequencies.partition( species, rot, species.natom)[0][1:] ]), axis='{} {}'.format(str(rot[1] + 1), str(rot[2] + 1)), )) rotors = '\n'.join(rotors) return rotors
def write_well(self, species): """ Create the block for MESS for a well. well0: reactant on this PES (zero-energy reference) """ # open the templates well_file = pkg_resources.resource_filename('tpl', 'mess_well.tpl') with open(well_file) as f: tpl = f.read() hir_file = pkg_resources.resource_filename('tpl', 'mess_hinderedrotor.tpl') with open(hir_file) as f: rotor_tpl = f.read() rotors = [] if self.par.par['rotor_scan']: for i, rot in enumerate(species.dihed): group = ' '.join([str(pi+1) for pi in frequencies.partition(species, rot, species.natom)[0][1:]]) axis = '{} {}'.format(str(rot[1]+1), str(rot[2]+1)) rotorsymm = species.sigma_int[rot[1]][rot[2]] nrotorpot = species.hir.nrotation // rotorsymm ens = species.hir.hir_energies[i] rotorpot = [(ei - ens[0])*constants.AUtoKCAL for ei in ens] rotorpot = ' '.join(['{:.2f}'.format(ei) for ei in rotorpot[:species.hir.nrotation // rotorsymm]]) rotors.append(rotor_tpl.format(group=group, axis=axis, rotorsymm=rotorsymm, nrotorpot=nrotorpot, rotorpot=rotorpot)) rotors = '\n'.join(rotors) freq = '' #reduced freqs used for mess input to make more accurate with HIR corrections for i, fr in enumerate(species.reduced_freqs): if i == 0: freq += '{:.4f}'.format(fr) elif i > 0 and i % 3 == 0: freq += '\n {:.4f}'.format(fr) else: freq += ' {:.4f}'.format(fr) geom = '' for i, at in enumerate(species.atom): if i > 0: geom += ' ' x, y, z = species.geom[i] geom += '{} {:.6f} {:.6f} {:.6f}\n'.format(at, x, y, z) if self.par.par['pes']: name = '{name}' energy = '{zeroenergy}' else: name = self.well_names[species.chemid] + ' ! ' + str(species.chemid) energy = ((species.energy + species.zpe) - (self.species.energy + self.species.zpe)) * constants.AUtoKCAL mess_well = tpl.format(chemid=name, natom=species.natom, geom=geom, symm=float(species.sigma_ext) / float(species.nopt), nfreq=len(species.reduced_freqs), freq=freq, hinderedrotor=rotors, nelec=1, charge=species.charge, mult=species.mult, zeroenergy=energy) f = open(str(species.chemid) + '.mess', 'w') f.write(mess_well) f.close() return mess_well
def write_barrier(self, reaction): """ Create the block for a MESS barrier. """ # open the templates ts_file = pkg_resources.resource_filename('tpl', 'mess_ts.tpl') with open(ts_file) as f: tpl = f.read() hir_file = pkg_resources.resource_filename('tpl', 'mess_hinderedrotor.tpl') with open(hir_file) as f: rotor_tpl = f.read() tunn_file = pkg_resources.resource_filename('tpl', 'mess_tunneling.tpl') with open(tunn_file) as f: tun_tpl = f.read() rotors = [] if self.par.par['rotor_scan']: for i, rot in enumerate(reaction.ts.dihed): group = ' '.join([str(pi+1) for pi in frequencies.partition(reaction.ts, rot, reaction.ts.natom)[0][1:]]) axis = '{} {}'.format(str(rot[1]+1), str(rot[2]+1)) rotorsymm = reaction.ts.sigma_int[rot[1]][rot[2]] nrotorpot = reaction.ts.hir.nrotation // rotorsymm ens = reaction.ts.hir.hir_energies[i] rotorpot = [(ei - ens[0])*constants.AUtoKCAL for ei in ens] rotorpot = ' '.join(['{:.2f}'.format(ei) for ei in rotorpot[:reaction.ts.hir.nrotation // rotorsymm]]) rotors.append(rotor_tpl.format(group=group, axis=axis, rotorsymm=rotorsymm, nrotorpot=nrotorpot, rotorpot=rotorpot)) rotors = '\n'.join(rotors) freq = '' #reduced freqs used for better accuracy of mess input files for i, fr in enumerate(reaction.ts.reduced_freqs[1:]): if i == 0: freq += '{:.4f}'.format(fr) elif i > 0 and i % 3 == 0: freq += '\n {:.4f}'.format(fr) else: freq += ' {:.4f}'.format(fr) geom = '' for i, at in enumerate(reaction.ts.atom): if i > 0: geom += ' ' x, y, z = reaction.ts.geom[i] geom += '{} {:.6f} {:.6f} {:.6f}\n'.format(at, x, y, z) barriers = [ ((reaction.ts.energy + reaction.ts.zpe) - (self.species.energy + self.species.zpe)) * constants.AUtoKCAL, ((reaction.ts.energy + reaction.ts.zpe) - sum([(opt.species.energy + opt.species.zpe) for opt in reaction.prod_opt])) * constants.AUtoKCAL, ] if any([bi < 0 for bi in barriers]): tun = '' else: tun = tun_tpl.format(cutoff=min(barriers), imfreq=-reaction.ts.reduced_freqs[0], welldepth1=barriers[0], welldepth2=barriers[1]) if len(reaction.products) == 1: prod_name = self.well_names[reaction.products[0].chemid] elif len(reaction.products) == 2: long_name = '_'.join(sorted([str(pi.chemid) for pi in reaction.products])) prod_name = self.bimolec_names[long_name] else: long_name = '_'.join(sorted([str(pi.chemid) for pi in reaction.products])) prod_name = self.termolec_names[long_name] if self.par.par['pes']: name = '{name}' chemid_reac = '' chemid_prod = '' long_rxn_name = '' energy = '{zeroenergy}' else: name = self.ts_names[reaction.instance_name] chemid_reac = self.well_names[self.species.chemid] chemid_prod = prod_name long_rxn_name = reaction.instance_name energy = ((reaction.ts.energy + reaction.ts.zpe) - (self.species.energy + self.species.zpe)) * constants.AUtoKCAL mess_ts = tpl.format(rxn_name=name, chemid_reac=chemid_reac, chemid_prod=chemid_prod, long_rxn_name=long_rxn_name, natom=reaction.ts.natom, geom=geom, symm=float(reaction.ts.sigma_ext) / float(reaction.ts.nopt), nfreq=len(reaction.ts.reduced_freqs) - 1, freq=freq, hinderedrotor=rotors, tunneling=tun, nelec=1, charge=reaction.ts.charge, mult=reaction.ts.mult, zeroenergy=energy) f = open(reaction.instance_name + '.mess', 'w') f.write(mess_ts) f.close() return mess_ts
def write_bimol(self, species_list, bar): """ Create the block for MESS for a bimolecular product. well0: reactant on this PES (zero-energy reference) """ bar=bar #0=barrier, 1=barrierless # open the templates if bar == 0: bimol_file = pkg_resources.resource_filename('tpl', 'mess_bimol.tpl') elif bar == 1: bimol_file = pkg_resources.resource_filename('tpl', 'mess_barrierless.tpl') with open(bimol_file) as f: tpl = f.read() fragment_file = pkg_resources.resource_filename('tpl', 'mess_fragment.tpl') with open(fragment_file) as f: fragment_tpl = f.read() hir_file = pkg_resources.resource_filename('tpl', 'mess_hinderedrotor.tpl') with open(hir_file) as f: rotor_tpl = f.read() atom_file = pkg_resources.resource_filename('tpl', 'mess_atom.tpl') with open(atom_file) as f: atom_tpl = f.read() fragments='' for species in species_list: if species.natom > 1: rotors = [] if self.par.par['rotor_scan']: for i, rot in enumerate(species.dihed): group = ' '.join([str(pi+1) for pi in frequencies.partition(species, rot, species.natom)[0][1:]]) axis = '{} {}'.format(str(rot[1]+1), str(rot[2]+1)) rotorsymm = species.sigma_int[rot[1]][rot[2]] nrotorpot = species.hir.nrotation // rotorsymm ens = species.hir.hir_energies[i] rotorpot = [(ei - ens[0])*constants.AUtoKCAL for ei in ens] rotorpot = ' '.join(['{:.2f}'.format(ei) for ei in rotorpot[:species.hir.nrotation // rotorsymm]]) rotors.append(rotor_tpl.format(group=group, axis=axis, rotorsymm=rotorsymm, nrotorpot=nrotorpot, rotorpot=rotorpot)) rotors = '\n'.join(rotors) freq = '' #reduced freqs used always bc HIR creates more accurate mess input for i, fr in enumerate(species.reduced_freqs): if i == 0: freq += '{:.4f}'.format(fr) elif i > 0 and i % 3 == 0: freq += '\n {:.4f}'.format(fr) else: freq += ' {:.4f}'.format(fr) geom = '' for i, at in enumerate(species.atom): if i > 0: geom += ' ' x, y, z = species.geom[i] geom += '{} {:.6f} {:.6f} {:.6f}\n'.format(at, x, y, z) energy = ((species.energy + species.zpe) - (self.species.energy + self.species.zpe)) * constants.AUtoKCAL if self.par.par['pes']: name = 'fr_name_{}'.format(species.chemid) name = '{' + name + '}' else: name = self.fragment_names[species.chemid] + ' ! ' + str(species.chemid) fragments += fragment_tpl.format(chemid=name, natom=species.natom, geom=geom, symm=float(species.sigma_ext) / float(species.nopt), nfreq=len(species.reduced_freqs), freq=freq, hinderedrotor=rotors, nelec=1, charge=species.charge, mult=species.mult) fragments += '\n' else: if self.par.par['pes']: name = 'fr_name_{}'.format(species.chemid) name = '{' + name + '}' else: name = self.fragment_names[species.chemid] + ' ! ' + str(species.chemid) # atom template fragments += atom_tpl.format(chemid=name, element=species.atom[0], nelec=1, charge=species.charge, mult=species.mult) fragments += '\n' pr_name = '_'.join(sorted([str(species.chemid) for species in species_list])) if self.par.par['pes']: name = '{name}' energy = '{ground_energy}' else: if bar == 0: name = self.bimolec_names[pr_name] + ' ! ' + pr_name elif bar == 1: name = self.barrierless_names[pr_name] energy = (sum([sp.energy for sp in species_list]) + sum([sp.zpe for sp in species_list]) - (self.species.energy + self.species.zpe)) * constants.AUtoKCAL if bar == 0: bimol = tpl.format(chemids=name, fragments=fragments, ground_energy=energy) elif bar == 1: bimol = tpl.format(barrier='nobar', reactant=name, dummy='', chemids='', fragments=fragments, ground_energy=energy) f = open(pr_name + '.mess', 'w') f.write(bimol) f.close() return bimol