def test__from_data(): """ test getters """ assert C2H2CLF_GEO == geom.from_data( syms=geom.symbols(C2H2CLF_GEO), xyzs=geom.coordinates(C2H2CLF_GEO), )
def effective_rotor_count(geo): """ Calculate an effective N parameter using the given parametrization. :param geo: geometry (Bohr) :type geo: automol geometry data structure :rtype: float """ # Conver the geo to a graph gra = graph(geo) symbs = symbols(geo) # Count the rotors (n_pp, n_ps, n_pt, n_pq, n_ss, n_st, n_sq, n_tt, n_tq, n_qq, n_co, n_oo, n_ss_ring, n_rings) = _rotor_counts(gra, symbs) print(' - Rotor Counts for N_eff:') print(' N_pp:{}, N_ps:{}, N_pt:{}, N_pq:{}'.format( n_pp, n_ps, n_pt, n_pq)) print(' N_ss:{}, N_st:{}, N_sq:{}'.format(n_ss, n_st, n_sq)) print(' N_tt:{}, N_tq:{}'.format(n_tt, n_tq)) print(' N_qq:{}'.format(n_qq)) print(' N_co:{}, N_oo:{}'.format(n_co, n_oo)) print(' N_ss_ring:{}, N_rings:{}'.format(n_ss_ring, n_rings)) # Use the rotor counts and the coefficients to calculate Neff c_pp_ps_ss, c_pt_st, c_pq_sq = 1.0, 2.0 / 3.0, 1.0 / 3.0 c_tt_tq_qq, c_co_oo, c_ss_ring = 0.0, 1.0 / 3.0, 1.0 / 2.0 n_eff = 1.0 + (c_pp_ps_ss * (n_pp + n_ps + n_ss) + c_pt_st * (n_pt + n_st) + c_pq_sq * (n_pq + n_sq) + c_tt_tq_qq * (n_tt + n_tq + n_qq) + c_co_oo * (n_co + n_oo) + c_ss_ring * n_ss_ring - n_rings) return n_eff
def format_coords(geo): """ format the coords section """ # Get the number of atoms natoms = len(geo) # Get the geometry information symbols = geom.symbols(geo) coordinates = geom.coordinates(geo) masses = geom.masses(geo) print(masses) # Build a string with the formatted coordinates string if geom.is_atom(geo): geo_str = '{0:<4s}{1:<6d}'.format(symbols[0], masses[0]) else: geo_str = '{0} \n'.format(str(natoms)) for symbol, mass, coords in zip(symbols, masses, coordinates): coords = [coord * phycon.BOHR2ANG for coord in coords] coords_str = '{0:>14.8f}{1:>14.8f}{2:>14.8f}'.format( coords[0], coords[1], coords[2]) geo_str += '{0:<4s}{1:<6.0f}{2}\n'.format(symbol, mass, coords_str) # Remove final newline character from the string geo_str = geo_str.rstrip() return natoms, geo_str
def test__from_data(): """ test geom.from_data """ assert C2H2CLF_GEO == geom.from_data( symbols=geom.symbols(C2H2CLF_GEO), coordinates=geom.coordinates(C2H2CLF_GEO), )
def format_coords(geo): """ format the coords section """ # Get the number of atoms natoms = len(geo) # Get the geometry information symbs = geom.symbols(geo) coords = geom.coordinates(geo) masses = tuple(round(mass) for mass in geom.masses(geo)) # Build a string with the formatted coordinates string if geom.is_atom(geo): geo_str = f'{symbs[0]:<4s}{masses[0]:<6d}' else: geo_str = f'{str(natoms)} \n' for symb, mass, xyzs in zip(symbs, masses, coords): _xyzs = [x * phycon.BOHR2ANG for x in xyzs] xyzs_str = f'{_xyzs[0]:>14.8f}{_xyzs[1]:>14.8f}{_xyzs[2]:>14.8f}' geo_str += f'{symb:<4s}{mass:<6.0f}{xyzs_str}\n' # Remove final newline character from the string geo_str = geo_str.rstrip() return natoms, geo_str
def _pairwise_potentials(geo, idx_pair, potential='exp6'): """ Calculate the sum of the pairwise potential for a given set of atom pairs """ # Get the indexes and symbols idx1, idx2 = idx_pair if idx1 != idx2: # Get the symbols of the atoms symbs = symbols(geo) symb1, symb2 = symbs[idx1], symbs[idx2] # Calculate interatomic distance rdist = (distance(geo, idx1, idx2) * qcc.conversion_factor('bohr', 'angstrom')) # Calculate the potential if potential == 'exp6': params = _read_params(EXP6_DCT, symb1, symb2) pot_val = exp6_potential(rdist, *params) elif potential == 'lj_12_6': params = _read_params(LJ_DCT, symb1, symb2) pot_val = lj_potential(rdist, *params) else: pot_val = None else: pot_val = 1e10 return pot_val
def test__ring_puckering(): smi = 'CC1CCCCC1' ich = smiles.inchi(smi) geo = inchi.geometry(ich) zma = geom.zmatrix(geo) gra = zmat.graph(zma) rings_atoms = graph.rings_atom_keys(gra) val_dct = zmat.value_dictionary(zma) coos = zmat.coordinates(zma) geo = zmat.geometry(zma) da_names = zmat.dihedral_angle_names(zma) for ring_atoms in rings_atoms: rotate_hyds = [] ngbs = graph.atom_sorted_neighbor_atom_keys(gra, ring_atoms[0]) symbs = geom.symbols(geo) for ngb in ngbs: if symbs[ngb] == 'H': rotate_hyds.append(ngb) ring_value_dct = {} for da_name in da_names: da_idxs = list(coos[da_name])[0] if len(list(set(da_idxs) & set(ring_atoms))) == 4: print(da_name, da_idxs) ring_value_dct[da_name] = val_dct[da_name] dist_value_dct = {} for i, _ in enumerate(ring_atoms): dist_value_dct[i] = zmat.distance(zma, ring_atoms[i - 1], ring_atoms[i]) samp_range_dct = {} for key, value in ring_value_dct.items(): samp_range_dct[key] = (value - numpy.pi / 4, value + numpy.pi / 4) print(zmat.samples(zma, 5, samp_range_dct))
def test__is_valid(): """ test geom.is_valid """ # Check validity assert geom.is_valid(C2H2CLF_GEO) # with pytest.raises(ValueError): # geom.is_valid(BAD_GEO) # Check empty geom returns empty information assert not geom.symbols(()) assert not geom.coordinates(())
def _pairwise_potentials(geo, idx_pair, potential='exp6'): """ Calculate the sum of the pairwise potential for a given pair of atoms in a geometry. :param geo: automol geometry object :type geo: tuple(tuple(float)) :param idx_pair: indices of atoms for which to calculate interaction :type idx_pair: tuple(int, int) :param potential: potential model of the atomic interactions :type potential: str :rtype: nd.array """ assert potential in ('exp6', 'lj_12_6'), ( f'potential {potential} != exp6 or lj_12_6') # Get the indexes and symbols idx1, idx2 = idx_pair if idx1 != idx2: # Get the symbols of the atoms symbs = symbols(geo) symb1, symb2 = symbs[idx1], symbs[idx2] # Calculate interatomic distance rdist = (distance(geo, idx1, idx2) * phycon.BOHR2ANG) # Calculate the potential if potential == 'exp6': params = dict_.values_by_unordered_tuple(EXP6_DCT, (symb1, symb2)) pot_val = exp6_potential(rdist, *params) elif potential == 'lj_12_6': params = dict_.values_by_unordered_tuple(LJ_DCT, (symb1, symb2)) pot_val = lj_potential(rdist, *params) else: pot_val = 1.0e10 return pot_val
def test__argunique_coulomb_spectrum(): """ test geom.argunique_coulomb_spectrum """ ref_idxs = (0, 3, 5, 8) geo = C2H2CLF_GEO natms = len(geom.symbols(geo)) geos = [] for idx in range(10): axis = numpy.random.rand(3) angle = numpy.random.rand() geo = geom.rotate(geo, axis, angle) if idx in ref_idxs and idx != 0: idx_to_change = numpy.random.randint(0, natms) new_xyz = numpy.random.rand(3) geo = geom.set_coordinates(geo, {idx_to_change: new_xyz}) geos.append(geo) idxs = geom.argunique_coulomb_spectrum(geos) assert idxs == ref_idxs
def similar_saddle_point_structure(zma, ref_zma, zrxn): """ Perform a series of checks to assess the viability of a transition state geometry prior to saving """ # Initialize viable viable = True # Get the bond dists and calculate the distance of bond being formed ref_geo = automol.zmat.geometry(ref_zma) cnf_geo = automol.zmat.geometry(zma) grxn = relabel_for_geometry(zrxn) frm_bnd_keys = forming_bond_keys(grxn) brk_bnd_keys = breaking_bond_keys(grxn) cnf_dist_lst = [] ref_dist_lst = [] bnd_key_lst = [] cnf_ang_lst = [] ref_ang_lst = [] for frm_bnd_key in frm_bnd_keys: frm_idx1, frm_idx2 = list(frm_bnd_key) cnf_dist = distance(cnf_geo, frm_idx1, frm_idx2) ref_dist = distance(ref_geo, frm_idx1, frm_idx2) cnf_dist_lst.append(cnf_dist) ref_dist_lst.append(ref_dist) bnd_key_lst.append(frm_bnd_key) for brk_bnd_key in brk_bnd_keys: brk_idx1, brk_idx2 = list(brk_bnd_key) cnf_dist = distance(cnf_geo, brk_idx1, brk_idx2) ref_dist = distance(ref_geo, brk_idx1, brk_idx2) cnf_dist_lst.append(cnf_dist) ref_dist_lst.append(ref_dist) bnd_key_lst.append(brk_bnd_key) for frm_bnd_key in frm_bnd_keys: for brk_bnd_key in brk_bnd_keys: for frm_idx in frm_bnd_key: for brk_idx in brk_bnd_key: if frm_idx == brk_idx: idx2 = frm_idx idx1 = list(frm_bnd_key - frozenset({idx2}))[0] idx3 = list(brk_bnd_key - frozenset({idx2}))[0] cnf_ang = central_angle(cnf_geo, idx1, idx2, idx3) ref_ang = central_angle(ref_geo, idx1, idx2, idx3) cnf_ang_lst.append(cnf_ang) ref_ang_lst.append(ref_ang) # Set the maximum allowed displacement for a TS conformer max_disp = 0.6 # better to check for bond-form length in bond scission with ring forming if 'addition' in grxn.class_: max_disp = 0.8 if 'abstraction' in grxn.class_: # this was 1.4 - SJK reduced it to work for some OH abstractions max_disp = 1.0 # Check forming bond angle similar to ini config if 'elimination' not in grxn.class_: for ref_angle, cnf_angle in zip(ref_ang_lst, cnf_ang_lst): if abs(cnf_angle - ref_angle) > .44: # ioprinter.diverged_ts('angle', ref_angle, cnf_angle) viable = False symbs = symbols(cnf_geo) lst_info = zip(ref_dist_lst, cnf_dist_lst, bnd_key_lst) for ref_dist, cnf_dist, bnd_key in lst_info: if 'add' in grxn.class_ or 'abst' in grxn.class_: bnd_key1, bnd_key2 = min(list(bnd_key)), max(list(bnd_key)) symb1 = symbs[bnd_key1] symb2 = symbs[bnd_key2] if bnd_key in frm_bnd_keys: # Check if radical atom is closer to some atom # other than the bonding atom cls = automol.zmat.is_atom_closest_to_bond_atom( zma, bnd_key2, cnf_dist) if not cls: # ioprinter.diverged_ts('distance', ref_dist, cnf_dist) print(' - Radical atom now has a new nearest neighbor') viable = False # check forming bond distance if abs(cnf_dist - ref_dist) > max_disp: # ioprinter.diverged_ts('distance', ref_dist, cnf_dist) viable = False # Check distance relative to equi. bond equi_bnd = dict_.values_by_unordered_tuple(bnd.LEN_DCT, (symb1, symb2), fill_val=0.0) displace_from_equi = cnf_dist - equi_bnd dchk1 = abs(cnf_dist - ref_dist) > 0.1 dchk2 = displace_from_equi < 0.2 if dchk1 and dchk2: # ioprinter.bad_equil_ts(cnf_dist, equi_bnd) viable = False else: # check forming/breaking bond distance # if abs(cnf_dist - ref_dist) > 0.4: # max disp of 0.4 causes problems for bond scission w/ ring forming # not sure if setting it to 0.3 will cause problems for other cases if abs(cnf_dist - ref_dist) > 0.3: # ioprinter.diverged_ts('distance', ref_dist, cnf_dist) viable = False return viable