def zero_point_vibrational_energies(output_str): """ Reads the zero-point energies for each of the hindered rotors from MESS output file string. :param output_str: string of lines of MESS output file :type output_str: str :return zpves: zero-point energy for each of the rotors :rtype: list(float) """ # Patterns for the ZPVE of a rotor num_patterns = (app.EXPONENTIAL_FLOAT, app.FLOAT, app.INTEGER) pattern1 = (app.escape('minimum energy[kcal/mol]') + app.one_or_more(app.SPACE) + '=' + app.one_or_more(app.SPACE) + app.capturing(app.one_of_these(num_patterns))) pattern2 = (app.escape('ground energy [kcal/mol]') + app.one_or_more(app.SPACE) + '=' + app.one_or_more(app.SPACE) + app.capturing(app.one_of_these(num_patterns))) # Obtain each ZPVE from the output string tmp1 = tuple(-float(val) for val in apf.all_captures(pattern1, output_str)) tmp2 = tuple(float(val) for val in apf.all_captures(pattern2, output_str)) tors_zpves = [sum(tmp) for tmp in zip(tmp1, tmp2)] # Convert to Hartrees for i, _ in enumerate(tors_zpves): tors_zpves[i] *= phycon.KCAL2EH return tuple(tors_zpves)
def zpves(output_string): """ Reads the zero-point energies for each of the hindered rotors from MESS output file string. :param output_string: string of lines of MESS output file :type output_string: str :return zpves: zero-point energy for each of the rotors :rtype: list(float) """ # Patterns for the ZPVE of a rotor num_patterns = (app.EXPONENTIAL_FLOAT, app.FLOAT) pattern1 = (app.escape('minimum energy[kcal/mol]') + app.one_or_more(app.SPACE) + '=' + app.one_or_more(app.SPACE) + app.capturing(app.one_of_these(num_patterns))) pattern2 = (app.escape('ground energy [kcal/mol]') + app.one_or_more(app.SPACE) + '=' + app.one_or_more(app.SPACE) + app.capturing(app.one_of_these(num_patterns))) # Obtain each ZPVE from the output string tmp1 = [-float(val) for val in apf.all_captures(pattern1, output_string)] tmp2 = [float(val) for val in apf.all_captures(pattern2, output_string)] tors_zpes = [sum(tmp) for tmp in zip(tmp1, tmp2)] # print('tors_zpes calc test:', tmp1, tmp2, tors_zpes) return tors_zpes
def anharmonic_frequencies_reader(output_string): """ Get the anharmonic vibrational frequencies """ # block block = apf.last_capture( (app.escape('Fundamental Bands (DE w.r.t. Ground State)') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('Overtones (DE w.r.t. Ground State)')), output_string) pattern = (app.INTEGER + app.escape('(1)') + app.SPACE + app.maybe(app.one_or_more(app.LOWERCASE_LETTER)) + app.one_or_more(app.SPACE) + app.FLOAT + app.one_or_more(app.SPACE) + app.capturing(app.FLOAT) + app.one_or_more(app.SPACE) + app.FLOAT + app.one_or_more(app.SPACE) + app.FLOAT + app.one_or_more(app.SPACE) + app.FLOAT) pattern2 = (app.INTEGER + app.escape('(1)') + app.SPACE + app.maybe(app.one_or_more(app.LOWERCASE_LETTER)) + app.one_or_more(app.SPACE) + app.FLOAT + app.one_or_more(app.SPACE) + app.capturing(app.FLOAT) + app.one_or_more(app.SPACE) + app.one_or_more(app.escape('*')) + app.one_or_more(app.SPACE) + app.one_or_more(app.escape('*')) + app.one_or_more(app.SPACE) + app.FLOAT) # Get list of values anharm_freq = [float(val) for val in apf.all_captures(pattern, block)] if not anharm_freq: anharm_freq = [float(val) for val in apf.all_captures(pattern2, block)] return anharm_freq
def ratek_fit_info(rxn_dstr): """ Read the information describing features of the fits to the rate constants """ # Read the temperatures and the Errors from the lines pressure_ptt = ( 'Pressure:' + app.SPACES + app.capturing(app.one_of_these([app.FLOAT, 'High'])) ) trange_ptt = ( 'Temps: ' + app.SPACES + app.capturing(app.INTEGER) + '-' + app.capturing(app.INTEGER) + app.SPACES + 'K' ) mean_ptt = ( 'MeanAbsErr:' + app.SPACES + app.capturing(app.FLOAT) + app.escape('%') + ',' ) max_ptt = ( 'MaxErr:' + app.SPACES + app.capturing(app.FLOAT) + app.escape('%') ) pressure_caps = apf.all_captures(pressure_ptt, rxn_dstr) trange_caps = apf.all_captures(trange_ptt, rxn_dstr) mean_caps = apf.all_captures(mean_ptt, rxn_dstr) max_caps = apf.all_captures(max_ptt, rxn_dstr) pressures = [] for pressure in pressure_caps: if pressure != 'High': pressures.append(float(pressure)) elif pressure == 'High': pressures.append(pressure) trange_vals = [] for cap in trange_caps: temp1, temp2 = cap trange_vals.append([int(temp1), int(temp2)]) if mean_caps is not None: mean_vals = [float(val) for val in mean_caps] else: mean_vals = [] if max_caps is not None: max_vals = [float(val) for val in max_caps] else: max_vals = [] # Build the inf_dct inf_dct = {} for idx, pressure in enumerate(pressures): inf_dct[pressure] = {'temps': trange_vals[idx]} if mean_vals: inf_dct[pressure].update({'mean_err': mean_vals[idx]}) if max_vals: inf_dct[pressure].update({'max_err': max_vals[idx]}) return inf_dct
def irc_path(output_str): """ Reads the coordinates and electronic energies (relative to saddple point) of the Intrinsic Reaction Coordinate. :param output_str: string of the program's output file :type output_str: str :rtype: tuple(automol geom data structure) """ # coordinates block = apf.last_capture( (app.escape('@IRC **** IRC Steps ****') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('---Fragment 1 Intrafragment Coordinates---')), output_str) pattern = ( app.escape('@IRC') + app.SPACES + app.INTEGER + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT + app.SPACES + app.LINE_FILL ) captures = apf.all_captures(pattern, block) if captures is not None: # Remove duplicates that may appear because of Psi4 output printing unique_coords = [] for coord in captures: if coord not in unique_coords: unique_coords.append(coord) coords = [float(coord) for coord in unique_coords] else: coords = None # energies block = apf.last_capture( (app.escape('@IRC **** IRC Report ****') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('@IRC **** IRC Steps ****')), output_str) pattern = ( app.escape('@IRC') + app.SPACES + app.INTEGER + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT ) captures = apf.all_captures(pattern, block) if captures is not None: energies = [float(capture) for capture in captures] else: energies = None return (coords, energies)
def well_average_energy(log_str, well, temp): """ Obtain the average energy of each well from the output of MESS rate calculations. Returns the energies in hartrees. :param log_str: string of the MESS .log file :type log_str: str :param well: name of the well to get energy for :type well: str :param temp: temperature to get the energy for :type temp: float :rtype: dict[str: float] """ # Loop through file to find the energy block with requested temp block_ptt = ( 'MasterEquation::set: starts' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'MasterEquation::set: done' ) blocks = apf.all_captures(block_ptt, log_str) if blocks is not None: for i, block in enumerate(blocks): templine = block.splitlines()[1] blocktemp = float(templine.strip().split()[2]) if numpy.isclose(blocktemp, temp, atol=0.01): block_idx = i break else: block_idx = None # If block with requested temp found, get energies ene_dct = None if block_idx is not None: ptt = ( app.capturing(app.VARIABLE_NAME) + app.SPACE + 'Well:' + app.SPACE + 'average energy =' + app.SPACE + app.capturing(app.NUMBER) + app.SPACE + 'kcal/mol' ) caps = apf.all_captures(ptt, blocks[block_idx]) ene_dct = dict( ((cap[0], float(cap[1])*phycon.KCAL2EH) for cap in caps) ) ene = ene_dct[well] return ene
def irc_path(output_string): """ get the coordinates and energies relative to the saddle point """ # coordinates block = apf.last_capture( (app.escape('@IRC **** IRC Steps ****') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('---Fragment 1 Intrafragment Coordinates---')), output_string) pattern = ( app.escape('@IRC') + app.SPACES + app.INTEGER + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT + app.SPACES + app.LINE_FILL ) captures = apf.all_captures(pattern, block) if captures is not None: # Remove duplicates that may appear because of Psi4 output printing unique_coords = [] for coord in captures: if coord not in unique_coords: unique_coords.append(coord) coords = [float(coord) for coord in unique_coords] else: coords = None # energies block = apf.last_capture( (app.escape('@IRC **** IRC Report ****') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('@IRC **** IRC Steps ****')), output_string) pattern = ( app.escape('@IRC') + app.SPACES + app.INTEGER + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT ) captures = apf.all_captures(pattern, block) if captures is not None: energies = [float(capture) for capture in captures] else: energies = None return (coords, energies)
def read_models_sections(job_path): """ species input """ mod_str = ptt.read_inp_str(job_path, MODEL_INP, remove_comments='#') # Build a dictionary for the PES models pes_model_sections = apf.all_captures(ptt.end_section_wname2('pes_model'), mod_str) assert pes_model_sections is not None pes_model_methods = {} glob_pes_model_methods = {} for section in pes_model_sections: if section[0] == 'global': name = section[0] keyword_dct = build_pes_model_keyword_dct(section[1]) glob_pes_model_methods = keyword_dct break pes_model_methods['global'] = glob_pes_model_methods for section in pes_model_sections: if section[0] != 'global': name = section[0] keyword_dct = build_pes_model_keyword_dct(section[1]) pes_model_methods[name] = combine_glob_and_spc_dct( glob_pes_model_methods, keyword_dct) # Build a dictionary for the spc models spc_model_sections = apf.all_captures(ptt.end_section_wname2('spc_model'), mod_str) assert spc_model_sections is not None spc_model_methods = {} glob_spc_model_methods = {} for section in spc_model_sections: if section[0] == 'global': name = section[0] keyword_dct = build_spc_model_keyword_dct(section[1]) glob_spc_model_methods = keyword_dct break spc_model_methods['global'] = glob_spc_model_methods for section in spc_model_sections: if section[0] != 'global': name = section[0] keyword_dct = build_spc_model_keyword_dct(section[1]) spc_model_methods[name] = combine_glob_and_spc_dct( glob_spc_model_methods, keyword_dct) return pes_model_methods, spc_model_methods
def plog_parameters(rxn_dstr): """ gets parameters associated with plog strings """ pattern = ('PLOG' + app.zero_or_more(app.SPACE) + app.escape('/') + app.zero_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.zero_or_more(app.SPACE) + app.escape('/')) params_lst = apf.all_captures(pattern, rxn_dstr) # Build dictionary of parameters, indexed by parameter if params_lst: params_dct = {} for params in params_lst: pressure = float(params[0]) vals = list(map(float, params[1:])) params_dct[pressure] = vals # if pressure not in params_dct: # params_dct[pressure] = [vals] # else: # params_dct[pressure].append(vals) else: params_dct = None return params_dct
def plog_parameters(rxn_dstr): """ Parses the data string for a reaction in the reactions block for the lines containing the PLog fitting parameters, then reads the parameters from these lines. :param rxn_dstr: data string for species in reaction block :type rxn_dstr: str :return params: PLog fitting parameters :rtype: dict[pressure: params] """ pattern = ('PLOG' + app.zero_or_more(app.SPACE) + app.escape('/') + app.zero_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.zero_or_more(app.SPACE) + app.escape('/')) params_lst = apf.all_captures(pattern, rxn_dstr) # Build dictionary of parameters, indexed by parameter if params_lst: params_dct = {} for params in params_lst: pressure = float(params[0]) vals = list(map(float, params[1:])) if pressure not in params_dct: params_dct[pressure] = [vals] else: params_dct[pressure].append(vals) else: params_dct = None return params_dct
def check_defined_sections(input_string): """ verify all defined sections have been defined """ pattern = (escape('$') + capturing(one_or_more(NONNEWLINE))) matches = all_captures(pattern, input_string) # See if each section has an paired end and is a supported keywords defined_sections = [] for i, match in enumerate(matches): if (i+1) % 2 == 0: if match != 'end': raise ValueError else: defined_sections.append(match) # Check if sections are supported if not all(section in INPUT_SUPPORTED_SECTIONS for section in defined_sections): raise NotImplementedError # Check if elements of keywords if not all(section in defined_sections for section in INPUT_REQUIRED_SECTIONS): raise NotImplementedError
def matrix_keys_and_entries(mat_str, symbol_pattern=SYMBOL_PATTERN, key_pattern=KEY_PATTERN, variable_pattern=VARIABLE_PATTERN): """ the keys and entries of a matrix block, as matrices (float entries are converted to floats) """ column_patterns = matrix_line_column_key_entry_patterns( symbol_pattern, key_pattern, variable_pattern) key_cols = [] entry_cols = [] for col_idx, column_pattern in enumerate(column_patterns): caps = apf.all_captures(column_pattern, mat_str) keys, entries = zip(*caps) if caps else ([], []) keys = list(map(int, keys)) entries = [ float(entry) if apf.is_number(entry) else entry for entry in entries ] key_cols.append([None] * (col_idx + 1) + keys) entry_cols.append([None] * (col_idx + 1) + entries) key_mat = tuple(zip(*key_cols)) entry_mat = tuple(zip(*entry_cols)) return key_mat, entry_mat
def _connected_formula(ich): fml_str = formula_string(ich) fml = { s: int(n) if n else 1 for s, n in apf.all_captures(ptt, fml_str) } return fml
def read_spc_amech(job_path): """ Read an amech style input file for the species """ # Read the AMech species string if os.path.exists(os.path.join(job_path, DAT_INP)): spc_amech_str = ptt.read_inp_str( job_path, DAT_INP, remove_comments='#') print('Found species.dat. Reading file...') else: spc_amech_str = '' print('No species.dat file...') # Build the keyword dcts amech_dct = {} if spc_amech_str: # Read each of the species sections and build the dcts spc_sections = apf.all_captures( ptt.end_section_wname2('spc'), spc_amech_str) if spc_sections: # Get the global species section for section in spc_sections: if section[0] == 'global': # Build the global species section keyword_dct = ptt.build_keyword_dct(section[1]) amech_dct['global'] = keyword_dct else: # Build each species dct to overwrite global dct name = section[0] keyword_dct = ptt.build_keyword_dct(section[1]) amech_dct[name] = keyword_dct return amech_dct
def buffer_enhance_factors(rxn_dstr): """ get the factors of speed-up from bath gas """ species_char = app.one_of_these([ app.LETTER, app.DIGIT, app.escape('('), app.escape(')'), app.UNDERSCORE ]) species_name = app.one_or_more(species_char) # Get the line that could have the bath gas buffer enhancements bath_line_pattern = (_first_line_pattern(rct_ptt=SPECIES_NAMES_PATTERN, prd_ptt=SPECIES_NAMES_PATTERN, coeff_ptt=COEFF_PATTERN) + '\n' + app.capturing(app.LINE)) bath_string = apf.first_capture(bath_line_pattern, rxn_dstr) # Check if this line has bath gas factors or is for something else # If factors in string, get factors bad_strings = ('DUPLICATE', 'LOW', 'TROE', 'CHEB', 'PLOG') if (any(string in bath_string for string in bad_strings) and bath_string.strip() != ''): factors = None else: bath_string = '\n'.join(bath_string.strip().split()) factor_pattern = (app.capturing(species_name) + app.escape('/') + app.capturing(app.NUMBER) + app.escape('/')) baths = apf.all_captures(factor_pattern, bath_string) factors = {} for bath in baths: factors[bath[0]] = float(bath[1]) return factors
def grid_min_freqs(output_string): """ Reads the analytic frequencies for each of the hindered rotors from MESS output file string. Frequency corresponds to the minimum from the minimum on the grid of the user supplied hindered rotor potential in the input. :param output_string: string of lines of MESS output file :type output_string: str :return freqs: frequency for each of the rotors :rtype: list(float) """ # Pattern for the frequency of a rotor pattern = (app.escape('first point frequency estimate =') + app.one_or_more(app.SPACE) + app.capturing(app.NUMBER) + app.one_or_more(app.SPACE) + app.escape('1/cm')) # Obtain each frequency from the output string tors_freqs = [ float(val) for val in apf.all_captures(pattern, output_string) ] print('tors freqs test in grid_min_freq:', tors_freqs) return tors_freqs
def high_p_parameters(rxn_dstr, ea_units, a_units): """ Parses the data string for a reaction in the reactions block for the line containing the chemical equation in order to read the fitting parameters that are on the same line. :param rxn_dstr: data string for species in reaction block :type rxn_dstr: str :return params: Arrhenius fitting parameters for high-P rates :rtype: list(float) """ pattern = _first_line_pattern(rct_ptt=SPECIES_NAMES_PATTERN, prd_ptt=SPECIES_NAMES_PATTERN, param_ptt=app.capturing(COEFF_PATTERN)) string_lst = apf.all_captures(pattern, rxn_dstr) if string_lst: fake_params = [] for string in string_lst: fake_params.append(list(ap_cast(string.split()))) params = fake_params[0] # Convert the units of Ea and A ea_conv_factor = get_ea_conv_factor(rxn_dstr, ea_units) a_conv_factor = get_a_conv_factor(rxn_dstr, a_units) params[2] = params[2] * ea_conv_factor params[0] = params[0] * a_conv_factor else: params = None return params
def stereo_bonds(ich, iso=True, one_indexed=False): """ Parse the stereo bonds from the stereochemistry layer. :param ich: InChI string :type ich: str :param iso: Include isotope stereochemistry? :type iso: bool :param one_indexed: Return indices in one-indexing? :type one_indexed: bool """ if len(split(ich)) > 1: raise NotImplementedError("Multicomponent InChIs not implemented." "Call inchi.split() first") bnd_ptt = '-'.join([app.capturing(app.UNSIGNED_INTEGER)] * 2) ste_dct = stereo_sublayers(ich) iso_dct = isotope_sublayers(ich) blyr = '' if 'b' in ste_dct: blyr += ste_dct['b'] if iso and 'b' in iso_dct: blyr += ',' + iso_dct['b'] bnds = () if blyr: bnds = ap_cast(apf.all_captures(bnd_ptt, blyr)) if not one_indexed: bnds = tuple((i - 1, j - 1) for i, j in bnds) bnds = bnds if bnds is not None else () return bnds
def _read_irc_reaction_path_summary(output_str, read_val): """ Reads the values for the Intrinsic Reaction Path from the table. :param output_str: string of the program's output file :type output_str: str :param read_val: value to read from table :type read_val: str :rtype: tuple(automol geom data structure) """ assert read_val in ('energy', 'coord') block = apf.last_capture( (app.escape('Summary of reaction path following') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('Total number of points:') + app.SPACES + app.INTEGER), output_str) if read_val == 'energy': pattern = (app.INTEGER + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT) elif read_val == 'coord': pattern = (app.INTEGER + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT)) captures = apf.all_captures(pattern, block) if captures is not None: values = [float(capture) for capture in captures] else: values = None return values
def quartic_force_constants(output_str): """ Reads the quartic force constants from the output file string. Returns the constants in _. Hartree*amu(2)*Bohr(-4) :param output_str: string of the program's output file :type output_str: str :rtype: tuple(tuple(float)) """ block = apf.last_capture( ('QUARTIC FORCE CONSTANTS IN NORMAL MODES' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Input to Restart Anharmonic Calculations'), output_str) if block is None: block = apf.last_capture( ('QUARTIC FORCE CONSTANTS IN NORMAL MODES' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Input for POLYMODE'), output_str) pattern = (app.capturing(app.INTEGER) + app.SPACES + app.capturing(app.INTEGER) + app.SPACES + app.capturing(app.INTEGER) + app.SPACES + app.capturing(app.INTEGER) + app.SPACES + app.FLOAT + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT)) caps = apf.all_captures(pattern, block) if caps: qfc_mat = _fc_mat(caps) else: qfc_mat = None return qfc_mat
def reaction_units(string, start_pattern, units_pattern): """ return a block delimited by start and end patterns """ rxn_line_pattern = start_pattern + app.capturing(app.LINE_FILL) units_string = apf.first_capture(rxn_line_pattern, string) units_lst = apf.all_captures(units_pattern, units_string) ckin_ea_units = [ 'CAL/MOLE', 'KCAL/MOLE', 'JOULES/MOLE', 'KJOULES/MOLE', 'KELVINS' ] ckin_a_units = ['MOLES', 'MOLECULES'] if units_lst: if any(unit in ckin_ea_units for unit in units_lst): for unit in ckin_ea_units: if unit in units_lst: ea_unit = unit.lower() else: ea_unit = 'cal/mole' if any(unit in ckin_a_units for unit in units_lst): for unit in ckin_a_units: if unit in units_lst: a_unit = unit.lower() else: a_unit = 'moles' units = (ea_unit, a_unit) else: units = ('cal/mole', 'moles') return units
def centrifugal_distortion_constants(output_str): """ Reads the VPT2-computed quartic centrifugal distortion constants from the output file string. Returns the constants in _. :param output_str: string of the program's output file :type output_str: str :rtype: tuple(tuple(float)) """ # Set patterns for all molecule types and symmetries block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Asymmetric Top Reduction'), output_str) if not block: block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Constants in the Symmetrically Reduced Hamiltonian'), output_str) if not block: block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Rotational l-type doubling constants'), output_str) # Read values pattern = ('TauP' + app.SPACE + app.capturing(app.one_or_more(app.LOWERCASE_LETTER)) + app.SPACES + app.capturing(app.EXPONENTIAL_FLOAT_D) + app.SPACES + app.EXPONENTIAL_FLOAT_D) cent_dist_const = [[lbl, float(val.replace('D', 'E'))] for (lbl, val) in apf.all_captures(pattern, block)] return cent_dist_const
def cubic_force_constants(output_str): """ Reads the cubic force constants from the output file string. Returns the constants in _. Hartree*amu(-3/2)*Bohr(-3) :param output_str: string of the program's output file :type output_str: str :rtype: tuple(tuple(float)) """ block = apf.last_capture( ('CUBIC FORCE CONSTANTS IN NORMAL MODES' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'QUARTIC FORCE CONSTANTS IN NORMAL MODES'), output_str) pattern = (app.capturing(app.INTEGER) + app.SPACES + app.capturing(app.INTEGER) + app.SPACES + app.capturing(app.INTEGER) + app.SPACES + app.FLOAT + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT)) caps = apf.all_captures(pattern, block) if caps: cfc_mat = _fc_mat(caps) else: cfc_mat = None return cfc_mat
def high_coefficients(thm_dstr): """ get the high temperature thermo coefficients """ capture_lst = apf.all_captures(app.EXPONENTIAL_FLOAT, thm_dstr) assert len(capture_lst) in (14, 15) cfts = tuple(map(float, capture_lst[:7])) return cfts
def cent_dist_const_reader(output_string): """ Get the quartic centrifugal distortion constants """ # block block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Asymmetric Top Reduction'), output_string) if not block: block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Constants in the Symmetrically Reduced Hamiltonian'), output_string) if not block: block = apf.last_capture( ('Quartic Centrifugal Distortion Constants Tau Prime' + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + 'Rotational l-type doubling constants'), output_string) # pattern pattern = ('TauP' + app.SPACE + app.capturing(app.one_or_more(app.LOWERCASE_LETTER)) + app.SPACES + app.capturing(app.EXPONENTIAL_FLOAT_D) + app.SPACES + app.EXPONENTIAL_FLOAT_D) # Get list of values cent_dist_const = [[lbl, float(val.replace('D', 'E'))] for (lbl, val) in apf.all_captures(pattern, block)] return cent_dist_const
def irc_points(output_string): """ obtain the geometry, gradient, and hessian at each point along the irc """ # Set pattern to find the end of each IRC optimization pattern = app.escape('@IRC **** Point ' + app.INTEGER + ' on IRC path is optimized ****') block = apf.last_capture( (pattern + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape(' Back-transformation to cartesian coordinates...')), output_string) # Set pattern for grabbing the geometry from the block geo_head_ptt = (app.escape('@IRC Cartesian Geometry (in Angstrom)') + app.LINE_FILL + '\n') # Grab all of the optimized geometries captures = apf.all_captures(pattern, block) if captures is not None: geoms = [] for string in captures: syms, xyzs = ar.geom.read(string, start_ptt=geo_head_ptt, line_start_ptt=app.escape('@IRC')) geoms.append(automol.geom.from_data(syms, xyzs, angstrom=True)) else: geoms = [] # Set the gradients and hessians to empty lists since they MAY not be run grads, hessians = [], [] return geoms, grads, hessians
def _read_irc_reaction_path_summary(output_string, read_val): """ get the desired values from the reaction path summary block """ assert read_val in ('energy', 'coord') block = apf.last_capture( (app.escape('Summary of reaction path following') + app.capturing(app.one_or_more(app.WILDCARD, greedy=False)) + app.escape('Total number of points:') + app.SPACES + app.INTEGER), output_string) if read_val == 'energy': pattern = (app.INTEGER + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT) elif read_val == 'coord': pattern = (app.INTEGER + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT)) captures = apf.all_captures(pattern, block) if captures is not None: values = [float(capture) for capture in captures] else: values = None return values
def high_p(rxn_str, ea_units, a_units): """ Parses the data string for a reaction in the reactions block for the line containing the chemical equation in order to read the fitting parameters that are on the same line. :param rxn_str: raw Chemkin string for a single reaction :type rxn_str: str :param ea_units: units of activation energy :type ea_units: str :param a_units: units of rate constants; either 'moles' or 'molecules' :type a_units: str :return params: Arrhenius fitting parameters for high-P rates :rtype: list(list(float)) """ pattern = _first_line_pattern(rct_ptt=SPECIES_NAMES_PATTERN, prd_ptt=SPECIES_NAMES_PATTERN, param_ptt=app.capturing(COEFF_PATTERN)) string_lst = apf.all_captures(pattern, rxn_str) if string_lst: fake_params = [] for string in string_lst: fake_params.append(list(ap_cast(string.split()))) params = fake_params[0] # Convert the units of Ea and A ea_conv_factor = get_ea_conv_factor(ea_units) a_conv_factor = get_a_conv_factor(rxn_str, a_units) params[2] = params[2] * ea_conv_factor params[0] = params[0] * a_conv_factor params = [params] # convert to list inside a list else: params = None return params
def harmonic_frequencies(output_str): """ Reads the harmonic vibrational frequencies from the output file string. Returns the frequencies in cm-1. :param output_str: string of the program's output file :type output_str: str :rtype: tuple(float) """ pattern = app.escape('Freq [cm^-1]') + app.capturing(app.LINE_FILL) captures = apf.all_captures(pattern, output_str) if captures is not None: freqs = () for capture in captures: vals = capture.split() for val in vals: if 'i' not in val: freqs += (float(val), ) else: freqs += (-1.0 * float(val.replace('i', '')), ) else: freqs = None return freqs
def lennard_jones(output_string): """ reads the lennard jones params from the output """ sigma_ptt = (app.SPACES + app.INTEGER + app.SPACES + app.capturing(app.FLOAT) + app.SPACES + app.FLOAT) epsilon_ptt = (app.SPACES + app.INTEGER + app.SPACES + app.FLOAT + app.SPACES + app.capturing(app.FLOAT)) sigmas = apf.all_captures(sigma_ptt, output_string) epsilons = apf.all_captures(epsilon_ptt, output_string) if sigmas is not None: sigmas = [float(val) for val in sigmas] if epsilons is not None: epsilons = [float(val) for val in epsilons] return sigmas, epsilons