def test_vlist_peroxide_dihed_angle_cosine(): number_of_tests = 50 for i in xrange(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) vlist = ValenceList(iclist) bonds = [] while len(bonds) < 3: i0, i1 = [ int(x) for x in np.random.uniform(low=0, high=4, size=2) ] #pick 2 random atoms if i0 == i1 or (i0, i1) in bonds or (i1, i0) in bonds: continue if (i0, i1) in system.bonds or (i1, i0) in system.bonds: iclist.add_ic(Bond(i0, i1)) bonds.append((i0, i1)) mult = np.random.randint(1, 4) amp = np.random.normal(0, 1) phi0 = np.random.uniform(0, 2 * np.pi) vlist.add_term(Cosine(mult, amp, phi0, DihedAngle(0, 1, 2, 3))) dlist.forward() iclist.forward() energy = vlist.forward() # calculate energy manually angle = dihed_angle(system.pos)[0] check_energy = 0.5 * amp * (1 - np.cos(mult * (angle - phi0))) assert abs(energy - check_energy) < 1e-8
def test_vlist_peroxide_dihed_angle_cosine(): number_of_tests=50 for i in range(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) vlist = ValenceList(iclist) bonds=[] while len(bonds)<3: i0, i1 = [int(x) for x in np.random.uniform(low=0,high=4,size=2)] #pick 2 random atoms if i0==i1 or (i0,i1) in bonds or (i1,i0) in bonds: continue if (i0,i1) in system.bonds or (i1,i0) in system.bonds: iclist.add_ic(Bond(i0,i1)) bonds.append((i0,i1)) mult = np.random.randint(1, 4) amp = np.random.normal(0, 1) phi0 = np.random.uniform(0, 2*np.pi) vlist.add_term(Cosine(mult, amp, phi0, DihedAngle(0,1,2,3))) dlist.forward() iclist.forward() energy = vlist.forward() # calculate energy manually angle = dihed_angle(system.pos)[0] check_energy = 0.5*amp*(1-np.cos(mult*(angle-phi0))) assert abs(energy - check_energy) < 1e-8
def test_vlist_peroxide_dihed_cos_chebychev6(): number_of_tests = 50 for i in xrange(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) vlist = ValenceList(iclist) bonds = [] while len(bonds) < 3: i0, i1 = [ int(x) for x in np.random.uniform(low=0, high=4, size=2) ] #pick 2 random atoms if i0 == i1 or (i0, i1) in bonds or (i1, i0) in bonds: continue if (i0, i1) in system.bonds or (i1, i0) in system.bonds: iclist.add_ic(Bond(i0, i1)) bonds.append((i0, i1)) amp = np.random.normal(0, 1) sign = np.random.randint(2) if sign == 0: sign = -1 vlist.add_term(Chebychev6(amp, DihedCos(0, 1, 2, 3), sign=sign)) dlist.forward() iclist.forward() energy = vlist.forward() # calculate energy manually psi = dihed_angle(system.pos)[0] check_energy = 0.5 * amp * (1.0 + sign * np.cos(6 * psi)) assert abs(energy - check_energy) < 1e-8
def test_vlist_peroxide_dihed_cos_chebychev6(): number_of_tests=50 for i in range(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) vlist = ValenceList(iclist) bonds=[] while len(bonds)<3: i0, i1 = [int(x) for x in np.random.uniform(low=0,high=4,size=2)] #pick 2 random atoms if i0==i1 or (i0,i1) in bonds or (i1,i0) in bonds: continue if (i0,i1) in system.bonds or (i1,i0) in system.bonds: iclist.add_ic(Bond(i0,i1)) bonds.append((i0,i1)) amp = np.random.normal(0, 1) sign = np.random.randint(2) if sign==0: sign = -1 vlist.add_term(Chebychev6(amp, DihedCos(0,1,2,3), sign=sign)) dlist.forward() iclist.forward() energy = vlist.forward() # calculate energy manually psi = dihed_angle(system.pos)[0] check_energy = 0.5*amp*(1.0+sign*np.cos(6*psi)) assert abs(energy - check_energy) < 1e-8
def test_zero_dihed_steven(): pos = np.array([ [ 3.99364178360816302e+00, 6.30763314754801546e-02, -3.46387534695341159e+00 ], [ 8.25853872852823123e+00, -2.56426319334358244e+00, 2.79913814647939019e-01 ], [ 6.27951244286421861e+00, -1.73747102970232015e+00, -2.05686744048685455e+00 ], [ 8.12025850622788603e+00, -6.72445448176343996e-01, 2.91920676811204993e+00 ], ]) numbers = np.array([1, 2, 3, 4]) system = System(numbers, pos) fp = ForcePartValence(system) fp.add_term(Cosine(3, 0.001, 0.0, DihedAngle(0, 1, 2, 3))) gpos = np.zeros(pos.shape) fp.compute(gpos) # Dihedral is very nearly zero, but not exactly assert np.abs(fp.iclist.ictab[0]['value'] - dihed_angle(system.pos)[0]) < 1e-8 assert np.abs(fp.iclist.ictab[0]['grad']) < 1e-8 assert not np.isnan(gpos).any()
def test_gpos_vtens_dihed_angle_cosine_peroxide(): system = get_system_peroxide() part = ForcePartValence(system) part.add_term(Cosine(3, 1.5, 2 * np.pi / 3, DihedAngle(0, 1, 2, 3))) print(dihed_angle(system.pos)[0] / np.pi) check_gpos_part(system, part) check_vtens_part(system, part)
def test_iclist_peroxide_dihedral_angle(): number_of_tests=50 for i in xrange(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) # The bonds are added randomly to get different situations in the delta list bonds=[] while len(bonds)<3: i0, i1 = [int(x) for x in np.random.uniform(low=0,high=4,size=2)] #pick 2 random atoms if i0==i1 or (i0,i1) in bonds or (i1,i0) in bonds: continue if (i0,i1) in system.bonds or (i1,i0) in system.bonds: iclist.add_ic(Bond(i0,i1)) bonds.append((i0,i1)) iclist.add_ic(DihedAngle(0,1,2,3)) dlist.forward() iclist.forward() assert iclist.ictab[3]['kind']==4 #assert the third ic is DihedralAngle assert abs(iclist.ictab[3]['value'] - dihed_angle(system.pos)[0]) < 1e-5
def test_iclist_peroxide_dihedral_cos6(): number_of_tests=50 for i in range(number_of_tests): system = get_system_peroxide() system.pos += np.random.normal(0.0, 0.1, system.pos.shape)*angstrom dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) # The bonds are added randomly to get different situations in the delta list bonds=[] while len(bonds)<3: i0, i1 = [int(x) for x in np.random.uniform(low=0,high=4,size=2)] #pick 2 random atoms if i0==i1 or (i0,i1) in bonds or (i1,i0) in bonds: continue if (i0,i1) in system.bonds or (i1,i0) in system.bonds: iclist.add_ic(Bond(i0,i1)) bonds.append((i0,i1)) iclist.add_ic(DihedCos6(0,1,2,3)) dlist.forward() iclist.forward() angle = dihed_angle(system.pos)[0] print('psi=%.3f deg: target=%.6f value=%.6f' %(angle/deg, np.cos(6*angle), iclist.ictab[3]['value'])) assert abs(iclist.ictab[3]['value'] - np.cos(6*angle)) < 1e-5
def test_vlist_peroxide_dihed_angle(): number_of_tests=50 for i in range(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) vlist = ValenceList(iclist) bonds=[] while len(bonds)<3: i0, i1 = [int(x) for x in np.random.uniform(low=0,high=4,size=2)] #pick 2 random atoms if i0==i1 or (i0,i1) in bonds or (i1,i0) in bonds: continue if (i0,i1) in system.bonds or (i1,i0) in system.bonds: iclist.add_ic(Bond(i0,i1)) bonds.append((i0,i1)) vlist.add_term(Harmonic(1.5, 0.1 , DihedAngle(0,1,2,3))) dlist.forward() iclist.forward() energy = vlist.forward() # calculate energy manually angle = dihed_angle(system.pos)[0] check_energy = 0.5*1.5*(angle-0.1)**2 assert abs(energy - check_energy) < 1e-8
def test_iclist_peroxide_dihedral_angle(): number_of_tests = 50 for i in range(number_of_tests): system = get_system_peroxide() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) # The bonds are added randomly to get different situations in the delta list bonds = [] while len(bonds) < 3: i0, i1 = [ int(x) for x in np.random.uniform(low=0, high=4, size=2) ] #pick 2 random atoms if i0 == i1 or (i0, i1) in bonds or (i1, i0) in bonds: continue if (i0, i1) in system.bonds or (i1, i0) in system.bonds: iclist.add_ic(Bond(i0, i1)) bonds.append((i0, i1)) iclist.add_ic(DihedAngle(0, 1, 2, 3)) dlist.forward() iclist.forward() assert iclist.ictab[3][ 'kind'] == 4 #assert the third ic is DihedralAngle assert abs(iclist.ictab[3]['value'] - dihed_angle(system.pos)[0]) < 1e-5
def test_iclist_peroxide_dihedral_cos6(): number_of_tests = 50 for i in range(number_of_tests): system = get_system_peroxide() system.pos += np.random.normal(0.0, 0.1, system.pos.shape) * angstrom dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) # The bonds are added randomly to get different situations in the delta list bonds = [] while len(bonds) < 3: i0, i1 = [ int(x) for x in np.random.uniform(low=0, high=4, size=2) ] #pick 2 random atoms if i0 == i1 or (i0, i1) in bonds or (i1, i0) in bonds: continue if (i0, i1) in system.bonds or (i1, i0) in system.bonds: iclist.add_ic(Bond(i0, i1)) bonds.append((i0, i1)) iclist.add_ic(DihedCos6(0, 1, 2, 3)) dlist.forward() iclist.forward() angle = dihed_angle(system.pos)[0] print('psi=%.3f deg: target=%.6f value=%.6f' % (angle / deg, np.cos(6 * angle), iclist.ictab[3]['value'])) assert abs(iclist.ictab[3]['value'] - np.cos(6 * angle)) < 1e-5
def load_rotscan_g03log(fn_log, top_indexes=None): """Load the torsional potential from a Gaussian 03 log/output file. Argument: | ``fn_log`` -- The filename of the gaussian output. Optional argument: | ``top_indexes`` -- The atom indexes that define the rotor. These do not have to include the atoms that define the rotational axis. When not given, an attempt is made to derive this information from the dihedral angle used for the scan. """ # find the line that specifies the dihedral angle with open(fn_log) as f: found_modredundant = False for line in f: if line.startswith(" The following ModRedundant input section has been read:"): found_modredundant = True break if not found_modredundant: raise IOError("Could not find the ModRedundant section in the log file.") dihedral = None num_geoms = 0 for line in f: line = line.strip() if len(line) == 0: break else: words = line.split() if words[0] == "D" and (words[5] == "S" or words[5] == "F"): if dihedral is None: dihedral = list(int(word)-1 for word in words[1:5]) else: raise IOError("Found multiple dihedral angle scan, which is not supported.") if dihedral is None: raise IOError("Could not find the dihedral angle of the rotational scan.") # load all the energies and compute the corresponding angles energies = [] angles = [] geometries = [] for line in f: if line.startswith(" Input orientation:") or \ line.startswith(" Standard orientation:"): # read the molecule numbers = [] last_coordinates = [] ## skip four lines for i in xrange(4): f.next() # read atoms for line in f: if line.startswith(" -----"): break words = line.split() numbers.append(int(words[1])) last_coordinates.append((float(words[3]), float(words[4]), float(words[5]))) if line.startswith(" SCF Done:"): # read the energy last_energy = float(line[line.find("=")+1:].split()[0]) if line.startswith(" -- Stationary point found."): # store last emergy and geometry in list energies.append(last_energy) last_coordinates = np.array(last_coordinates)*angstrom geometries.append(last_coordinates) angles.append(dihed_angle(last_coordinates[dihedral])[0]) if len(energies) == 0: raise IOError("Could not find any stationary point") if top_indexes is None: # Define the molecular geometry that is used in the constructor of # RotScan to detect the top. from molmod.molecules import Molecule as BaseMolecule molecule = BaseMolecule(numbers, geometries[0]) else: molecule = None result = RotScan( dihedral, molecule, top_indexes, np.array([angles, energies]) ) result.geometries = np.array(geometries) return result
#!/usr/bin/env python import argparse import molmod as mm import numpy as np import mdtraj as md def eval_pplane(atoms_xyz): return mm.opbend_dist(atoms_xyz)[0] / mm.angstrom CV_KIND_DICT = { 'BOND': lambda atoms_xyz: mm.bond_length(atoms_xyz)[0] / mm.angstrom, 'ANGLE': lambda atoms_xyz: mm.bend_angle(atoms_xyz)[0] / mm.deg, 'DIHEDRAL': lambda atoms_xyz: mm.dihed_angle(atoms_xyz)[0] / mm.deg, 'PPLANE': lambda atoms_xyz: eval_pplane(np.roll(atoms_xyz, -3)) } MULTICV_KIND_DICT = {'MBOND': (2, 'BOND'), 'MANGLE': (3, 'ANGLE'), 'MDIHEDRAL': (4, 'DIHEDRAL'), 'MPPLANE': (4, 'PPLANE')} def get_center(xyz, indices): return np.mean(np.take(xyz, indices, axis=0), axis=0) def get_centers(xyz, centers):
def test_iclist_mil53_dihedral_angles(): system = get_system_mil53() dlist = DeltaList(system) iclist = InternalCoordinateList(dlist) ic_values = [] gpos = np.zeros(system.pos.shape) forbidden_dihedrals = [ ["O_HY", "AL", "O_HY", "AL"], ["O_HY", "AL", "O_HY", "H_HY"], ["O_CA", "AL", "O_CA", "C_CA"], ] for i1, i2 in system.bonds: # Add bonds here to avoid that all ic signs are +1 iclist.add_ic(Bond(i2, i1)) for i0 in system.neighs1[i1]: if i0 == i2: continue for i3 in system.neighs1[i2]: if i3 == i1: continue # Compute using molmod delta0 = system.pos[i0] - system.pos[i1] delta1 = system.pos[i2] - system.pos[i1] delta2 = system.pos[i3] - system.pos[i2] system.cell.mic(delta0) system.cell.mic(delta1) system.cell.mic(delta2) pos = np.zeros((4, 3)) pos[0] = system.pos[i1] + delta0 pos[1] = system.pos[i1] pos[2] = system.pos[i1] + delta1 pos[3] = pos[2] + delta2 phi0, dphi0 = dihed_angle(pos, deriv=1) # Compute value using yaff iic = iclist.add_ic(DihedAngle(i0, i1, i2, i3)) ic = iclist.ictab[iic] dlist.forward() iclist.forward() phi1 = ic['value'] if np.abs(phi1 - phi0) > 1e-8: raise AssertionError( "DihedralAngle(%d,%d,%d,%d): molmod " "value = %12.8f yaff value = %12.8f diff = %12.2e" % (i0, i1, i2, i3, phi0, phi1, phi0 - phi1)) # Compute derivative using yaff gpos[:] = 0.0 ic['grad'] = 1.0 iclist.back() dlist.back(gpos, None) # Derivative of DihedCos fails in these cases, and DihedAngle # derivatives are base on this types = [ system.get_ffatype(i0), system.get_ffatype(i1), system.get_ffatype(i2), system.get_ffatype(i3) ] if types in forbidden_dihedrals or types[:: -1] in forbidden_dihedrals: continue ddiff = gpos[[i0, i1, i2, i3]] - dphi0 if np.any(np.abs(ddiff) > 1e-6): raise AssertionError( "DihedralAngle(%d,%d,%d,%d): largest " "absolute derivative deviation = %12.2e" % (i0, i1, i2, i3, np.amax(np.abs(ddiff))))