def main(): try: input_file = sys.argv[1] except IndexError: print('To use KinBot, supply one argument being the input file!') sys.exit(-1) # print the license message to the console print(license_message.message) # initialize the parameters for this run masterpar = Parameters(input_file) par = masterpar.par input_file = masterpar.input_file # set up the logging environment if par['verbose']: logging.basicConfig(filename='kinbot.log', level=logging.DEBUG) else: logging.basicConfig(filename='kinbot.log', level=logging.INFO) # write the license message to the log file logging.info(license_message.message) logging.info('Input parameters') for param in par: logging.info('{} {}'.format(param, par[param])) # time stamp of the KinBot start logging.info('Starting KinBot at {}'.format(datetime.datetime.now())) # Make the necessary directories if not os.path.exists('perm'): os.makedirs('perm') if not os.path.exists('scratch'): os.makedirs('scratch') if not os.path.exists(par['single_point_qc']): os.mkdir(par['single_point_qc']) if par['rotor_scan'] == 1: if not os.path.exists('hir'): os.mkdir('hir') if not os.path.exists('hir_profiles'): os.mkdir('hir_profiles') if not os.path.exists('perm/hir/'): os.makedirs('perm/hir/') if par['conformer_search'] == 1: if not os.path.exists('conf'): os.mkdir('conf') if not os.path.exists('perm/conf'): os.makedirs('perm/conf') if not os.path.exists('me'): os.mkdir('me') # initialize the reactant well0 = StationaryPoint('well0', par['charge'], par['mult'], smiles=par['smiles'], structure=par['structure']) well0.short_name = 'w1' # write the initial reactant geometry to a file for visualization geom_out = open('geometry.xyz', 'w') geom_out.write('{}\n\n'.format(well0.natom)) for i, at in enumerate(well0.atom): x, y, z = well0.geom[i] geom_out.write('{} {:.6f} {:.6f} {:.6f}\n'.format(at, x, y, z)) geom_out.write('\n\n') geom_out.close() # characterize the initial reactant well0.characterize(dimer=par['dimer']) well0.name = str(well0.chemid) start_name = well0.name # initialize the qc instance qc = QuantumChemistry(par) # only run filecopying if PES is turned on # if par['pes']: # check if this well was calcualted before in another directory # this flag indicates that this kinbot run # should wait for the information from another # kinbot run to become available and copy the necessary information # wait_for_well = 1 # while wait_for_well: # wait_for_well = filecopying.copy_from_database_folder(well0.chemid, well0.chemid, qc) # if wait_for_well: # time.sleep(1) # start the initial optimization of the reactant logging.info('Starting optimization of intial well') qc.qc_opt(well0, well0.geom) err, well0.geom = qc.get_qc_geom(str(well0.chemid) + '_well', well0.natom, wait=1) err, well0.freq = qc.get_qc_freq(str(well0.chemid) + '_well', well0.natom, wait=1) if err < 0: logging.error('Error with initial structure optimization.') return if any(well0.freq[i] <= 0 for i in range(len(well0.freq))): logging.error('Found imaginary frequency for initial structure.') return # characterize again and look for differences well0.characterize(dimer=par['dimer']) well0.name = str(well0.chemid) if well0.name != start_name: logging.error( 'The first well optimized to a structure different from the input.' ) return # do an MP2 optimization of the reactant, # to compare some scan barrier heigths to if par['families'] == ['all'] or \ 'birad_recombination_R' in par['families'] or \ 'r12_cycloaddition' in par['families'] or \ 'r14_birad_scission' in par['families'] or \ 'R_Addition_MultipleBond' in par['families'] or \ (par['skip_families'] != ['none'] and \ ('birad_recombination_R' not in par['skip_families'] or \ 'r12_cycloaddition' not in par['skip_families'] or \ 'r14_birad_scission' not in par['skip_families'] or \ 'R_Addition_MultipleBond' not in par['skip_families'])) or \ par['reaction_search'] == 0: logging.info('Starting MP2 optimization of intial well') qc.qc_opt(well0, well0.geom, mp2=1) err, geom = qc.get_qc_geom( str(well0.chemid) + '_well_mp2', well0.natom, 1) # comparison for barrierless scan if par['barrierless_saddle']: logging.info( 'Optimization of intial well for barrierless at {}/{}'.format( par['barrierless_saddle_method'], par['barrierless_saddle_basis'])) qc.qc_opt(well0, well0.geom, bls=1) err, geom = qc.get_qc_geom( str(well0.chemid) + '_well_bls', well0.natom, 1) # characterize again and look for differences well0.characterize(dimer=par['dimer']) well0.name = str(well0.chemid) err, well0.energy = qc.get_qc_energy(str(well0.chemid) + '_well', 1) err, well0.zpe = qc.get_qc_zpe(str(well0.chemid) + '_well', 1) well_opt = Optimize(well0, par, qc, wait=1) well_opt.do_optimization() if well_opt.shigh == -999: logging.error( 'Error with high level optimization of initial structure.') return if par['pes']: filecopying.copy_to_database_folder(well0.chemid, well0.chemid, qc) if par['reaction_search'] == 1: logging.info('Starting reaction searches of intial well') rf = ReactionFinder(well0, par, qc) rf.find_reactions() rg = ReactionGenerator(well0, par, qc, input_file) rg.generate() if par['homolytic_scissions'] == 1: logging.info('Starting the search for homolytic scission products') well0.homolytic_scissions = HomolyticScissions(well0, par, qc) well0.homolytic_scissions.find_homolytic_scissions() if par['me'] > 0: # it will be 2 for kinbots when the mess file is needed but not run mess = MESS(par, well0) mess.write_input(qc) if par['me'] == 1: logging.info('Starting Master Equation calculations') if par['me_code'] == 'mess': mess.run() postprocess.createSummaryFile(well0, qc, par) postprocess.createPESViewerInput(well0, qc, par) postprocess.creatMLInput(well0, qc, par) logging.info('Finished KinBot at {}'.format(datetime.datetime.now())) print("Done!")
def create_mess_input(par, wells, products, reactions, well_energies, prod_energies, parent): """ When calculating a full pes, the files from the separate wells are read and concatenated into one file Two things per file need to be updated 1. the names of all the wells, bimolecular products and ts's 2. all the zpe corrected energies """ # generate short names for all startionary points well_short, pr_short, fr_short, ts_short = create_short_names( wells, products, reactions) # list of the strings to write to mess input file s = [] # write the header s.append(write_header(par, well_short[wells[0]])) # write the wells s.append('######################') s.append('# WELLS') s.append('######################') for well in wells: name = well_short[well] + ' ! ' + well energy = well_energies[well] with open(parent[well] + '/' + well + '.mess') as f: s.append(f.read().format(name=name, zeroenergy=energy)) s.append('!****************************************') # write the products s.append('######################') s.append('# BIMOLECULAR PRODUCTS') s.append('######################') for prod in products: name = pr_short[prod] + ' ! ' + prod energy = prod_energies[prod] fr_names = {} for fr in prod.split('_'): key = 'fr_name_{}'.format(fr) value = fr_short[fr] + ' ! ' + fr fr_names[key] = value with open(parent[prod] + '/' + prod + '.mess') as f: s.append(f.read().format(name=name, ground_energy=energy, **fr_names)) s.append('!****************************************') # write the barrier s.append('######################') s.append('# BARRIERS') s.append('######################') for rxn in reactions: name = [ts_short[rxn[1]]] name.append(well_short[rxn[0]]) if len(rxn[2]) == 1: name.append(well_short[rxn[2][0]]) else: name.append(pr_short['_'.join(sorted(rxn[2]))]) name.append('!') name.append(rxn[1]) energy = rxn[3] with open(rxn[0] + '/' + rxn[1] + '.mess') as f: s.append(f.read().format(name=' '.join(name), zeroenergy=energy)) s.append('!****************************************') # add last end statement s.append('!****************************************') s.append('End ! end kinetics\n') if not os.path.exists('me'): os.mkdir('me') # write everything to a file with open('me/mess.inp', 'w') as f: f.write('\n'.join(s)) dummy = StationaryPoint('dummy', par.par['charge'], par.par['mult'], smiles=par.par['smiles'], structure=par.par['structure']) mess = MESS(par, dummy) if par.par['me']: mess.run()
def main(): try: input_file = sys.argv[1] except IndexError: print('To use KinBot, supply one argument being the input file!') sys.exit(-1) # print the license message to the console print(license_message.message) # initialize the parameters for this run par = Parameters(input_file) # set up the logging environment if par.par['verbose']: logging.basicConfig(filename='kinbot.log', level=logging.DEBUG) else: logging.basicConfig(filename='kinbot.log', level=logging.INFO) # write the license message to the log file logging.info(license_message.message) # time stamp of the KinBot start logging.info('Starting KinBot at {}'.format(datetime.datetime.now())) # Make the necessary directories if not os.path.exists('perm'): os.makedirs('perm') if not os.path.exists('scratch'): os.makedirs('scratch') if not os.path.exists(par.par['single_point_qc']): os.mkdir(par.par['single_point_qc']) if par.par['rotor_scan'] == 1: if not os.path.exists('hir'): os.mkdir('hir') if not os.path.exists('hir_profiles'): os.mkdir('hir_profiles') if not os.path.exists('perm/hir/'): os.makedirs('perm/hir/') if par.par['conformer_search'] == 1: if not os.path.exists('conf'): os.mkdir('conf') if not os.path.exists('perm/conf'): os.makedirs('perm/conf') if not os.path.exists('me'): os.mkdir('me') if par.par['pes'] and par.par['specific_reaction']: logging.error('Specific reaction cannot be searched in PES mode.') return # initialize the reactant well0 = StationaryPoint('well0', par.par['charge'], par.par['mult'], smiles=par.par['smiles'], structure=par.par['structure']) well0.short_name = 'w1' # wrtie the initial reactant geometry to a file for visualization geom_out = open('geometry.xyz', 'w') geom_out.write('{}\n\n'.format(well0.natom)) for i, at in enumerate(well0.atom): x, y, z = well0.geom[i] geom_out.write('{} {:.6f} {:.6f} {:.6f}\n'.format(at, x, y, z)) geom_out.write('\n\n') geom_out.close() # characterize the initial reactant well0.characterize(par.par['dimer']) well0.name = str(well0.chemid) start_name = well0.name # initialize the qc instance qc = QuantumChemistry(par) # start the initial optimization of the reactant logging.info('Starting optimization of intial well') qc.qc_opt(well0, well0.geom) err, well0.geom = qc.get_qc_geom(str(well0.chemid) + '_well', well0.natom, wait=1) err, well0.freq = qc.get_qc_freq(str(well0.chemid) + '_well', well0.natom, wait=1) if err < 0: logging.error('Error with initial structure optimization.') return if any(well0.freq[i] <= 0 for i in range(len(well0.freq))): logging.error('Found imaginary frequency for initial structure.') return # characterize again and look for differences well0.characterize(par.par['dimer']) well0.name = str(well0.chemid) if well0.name != start_name: logging.error('The first well optimized to a structure different from the input.') return # do an MP2 optimization of the reactant, # to compare Beta scission barrier heigths to logging.info('Starting MP2 optimization of intial well') qc.qc_opt(well0, well0.geom, mp2=1) err, geom = qc.get_qc_geom(str(well0.chemid) + '_well_mp2', well0.natom, 1) # characterize again and look for differences well0.characterize(par.par['dimer']) well0.name = str(well0.chemid) # read the energy and the zpe corrected energy err, well0.energy = qc.get_qc_energy(str(well0.chemid) + '_well', 1) err, well0.zpe = qc.get_qc_zpe(str(well0.chemid) + '_well', 1) well_opt = Optimize(well0, par, qc, wait=1) well_opt.do_optimization() if well_opt.shigh == -999: logging.error('Error with high level optimization of initial structure.') return # do the reaction search using heuristics if par.par['reaction_search'] == 1: logging.info('Starting reaction searches of intial well') rf = ReactionFinder(well0, par, qc) rf.find_reactions() rg = ReactionGenerator(well0, par, qc) rg.generate() # do the homolytic scission products search if par.par['homolytic_scissions'] == 1: logging.info('Starting the search for homolytic scission products') well0.homolytic_scissions = HomolyticScissions(well0, par, qc) well0.homolytic_scissions.find_homolytic_scissions() # initialize the master equation instance mess = MESS(par, well0) mess.write_input() mesmer = MESMER(par, well0) mesmer.write_input() if par.par['me'] == 1: logging.info('Starting Master Equation calculations') if par.par['me_code'] == 'mess': mess.run() elif par.par['me_code'] == 'mesmer': mesmer.run() else: logging.error('Cannot recognize me code {}'.format(par.par['me_code'])) # postprocess the calculations postprocess.createSummaryFile(well0, qc, par) postprocess.createPESViewerInput(well0, qc, par) postprocess.creatMLInput(well0, qc, par) logging.info('Finished KinBot at {}'.format(datetime.datetime.now())) print("Done!")
def create_mess_input(par, wells, products, reactions, well_energies, prod_energies, parent): """ When calculating a full pes, the files from the separate wells are read and concatenated into one file Two things per file need to be updated 1. the names of all the wells, bimolecular products and ts's 2. all the zpe corrected energies """ # generate short names for all startionary points well_short, pr_short, fr_short, ts_short = create_short_names(wells, products, reactions) # list of the strings to write to mess input file s = [] # write the header s.append(write_header(par, well_short[wells[0]])) # write the wells s.append('######################') s.append('# WELLS') s.append('######################') for well in wells: name = well_short[well] + ' ! ' + well energy = well_energies[well] with open(parent[well] + '/' + well + '.mess') as f: s.append(f.read().format(name=name, zeroenergy=energy)) s.append('!****************************************') # write the products s.append('######################') s.append('# BIMOLECULAR PRODUCTS') s.append('######################') for prod in products: name = pr_short[prod] + ' ! ' + prod energy = prod_energies[prod] fr_names = {} for fr in prod.split('_'): key = 'fr_name_{}'.format(fr) value = fr_short[fr] + ' ! ' + fr fr_names[key] = value with open(parent[prod] + '/' + prod + '.mess') as f: s.append(f.read().format(name=name, ground_energy=energy, **fr_names)) s.append('!****************************************') # write the barrier s.append('######################') s.append('# BARRIERS') s.append('######################') for rxn in reactions: name = [ts_short[rxn[1]]] name.append(well_short[rxn[0]]) if len(rxn[2]) == 1: name.append(well_short[rxn[2][0]]) else: name.append(pr_short['_'.join(sorted(rxn[2]))]) name.append('!') name.append(rxn[1]) energy = rxn[3] with open(rxn[0] + '/' + rxn[1] + '.mess') as f: s.append(f.read().format(name=' '.join(name), zeroenergy=energy)) s.append('!****************************************') # add last end statement s.append('!****************************************') s.append('End ! end kinetics\n') if not os.path.exists('me'): os.mkdir('me') # write everything to a file with open('me/mess.inp', 'w') as f: f.write('\n'.join(s)) dummy = StationaryPoint('dummy', par.par['charge'], par.par['mult'], smiles=par.par['smiles'], structure=par.par['structure']) mess = MESS(par, dummy) if par.par['me']: mess.run()