def check_terms(name): 'Check whether all ICs are present in ValenceFF instance' #TODO: CROSS terms with log.section('NOSETST', 2): system, ref = read_system(name) guess_ffatypes(system, 'high') valence = ValenceFF(system) #check if every bond is present and harmonic for bond in system.iter_bonds(): found = False for term in valence.iter_terms('BONDHARM'): at0, at1 = term.get_atoms() if bond[0]==at0 and bond[1]==at1 \ or bond[0]==at1 and bond[1]==at0: assert not found, 'BondHarm term %s was already found!' % str( bond) found = True assert found, 'No BondHarm term found for bond %s' % str(bond) #check if every bend is present for angle in system.iter_angles(): found = False for term in valence.iter_terms('BENDAHARM'): at0, at1, at2 = term.get_atoms() if angle[0]==at0 and angle[1]==at1 and angle[2]==at2 \ or angle[0]==at2 and angle[1]==at1 and angle[2]==at0: assert not found, 'BendAHarm term %s was already found!' % str( angle) found = True assert found, 'No BendAHarm term found for bond %s' % str(angle) #check if every dihedral is present for dihed in system.iter_dihedrals(): found = False for term in valence.iter_terms('TORSION'): at0, at1, at2, at3 = term.get_atoms() if dihed[0]==at0 and dihed[1]==at1 and dihed[2]==at2 and dihed[3]==at3\ or dihed[0]==at3 and dihed[1]==at2 and dihed[2]==at1 and dihed[3]==at0: assert not found, 'Torsion term %s was already found!' % str( dihed) found = True assert found, 'No Torsion term found for bond %s' % str(dihedral) #check if every oop distance is present and Harm for rv of 0 and SQHARM else for oop in system.iter_oops(): found = False for term in valence.iter_terms('/OOPDIST'): at0, at1, at2, at3 = term.get_atoms() for p0, p1, p2 in permutations([at0, at1, at2]): if oop[0] == p0 and oop[1] == p1 and oop[2] == p2 and oop[ 3] == at3: assert not found, 'OopDist term %s was already found!' % str( oop) found = True for term in valence.iter_terms('SQOOPDIST'): at0, at1, at2, at3 = term.get_atoms() for p0, p1, p2 in permutations([at0, at1, at2]): if oop[0] == p0 and oop[1] == p1 and oop[2] == p2 and oop[ 3] == at3: assert not found, 'SqOopDist term %s was already found!' % str( oop) found = True assert found, 'No (Sq)OopDist term found for bond %s' % str(oop)
def test_h2(): #frequency of H2 stretch mode in gaussian.fchk calculation is 4416.656/cm #and an equilibrium bond length of 0.7442380 A. This test checks if the #force field predicts the same values r0 = 0.7442380 * angstrom freq = (2 * np.pi) * 4416.65640485 * lightspeed / centimeter mass = pt['H'].mass / 2 #reduced mass for the H2 stretch mode #Load system, model and pert. theory and estimate ff with log.section('NOSETST', 2): system, ai = read_system('H2/gaussian.fchk') guess_ffatypes(system, 'low') program = DeriveNonDiagFF(system, ai) program.do_pt_generate() program.do_pt_estimate() K_pt, rv_pt = program.valence.get_params(0, only='all') program.do_hc_estimatefc(['HC_FC_DIAG']) K_hc, rv_hc = program.valence.get_params(0, only='all') #print results print '' print 'AI : K = %.3f kjmol/A^2 q0 = %.6f A' % ( mass * freq**2 / (kjmol / angstrom**2), r0 / angstrom) print 'FF (PT): K = %.3f kjmol/A^2 q0 = %.6f A' % ( K_pt / (kjmol / angstrom**2), rv_pt / angstrom) print 'FF (HC): K = %.3f kjmol/A^2 q0 = %.6f A' % ( K_hc / (kjmol / angstrom**2), rv_hc / angstrom) print '' #perform assertion checks assert abs(K_pt / (mass * freq**2) - 1.0) < 1e-3 assert abs(rv_pt / r0 - 1.0) < 1e-3 assert abs(K_hc / (mass * freq**2) - 1.0) < 1e-3 assert abs(rv_hc / r0 - 1.0) < 1e-3 assert abs(K_hc / K_pt - 1.0) < 1e-6 assert abs(rv_hc / rv_pt - 1.0) < 1e-6
def check_hessian_dihedrals(name, tol=1e-3 * kjmol / angstrom**2): with log.section('NOSETST', 2): system, ref = read_system(name) guess_ffatypes(system, 'highest') valence = ValenceFF(system) for term in valence.iter_terms('TORSION'): psi0 = get_dihedral_angle(term, system) inonzero, izero = get_indices_zero_nonzero(term, len(system.numbers)) rv = np.random.uniform(low=0, high=180) * deg #q0 fc = np.random.uniform(low=10, high=50) * kjmol ref, num = get_analytic_numeric_hessian(valence, term, fc=fc, rv0=rv) #assert that hessian elements of atoms not part of the current dihedral #are zero if len(izero[0]) > 0: assert (abs(ref[izero])).max() < 1e-12 * kjmol / angstrom**2 assert (abs(num[izero])).max() < 1e-12 * kjmol / angstrom**2 M = (abs(ref - num)).max() iM, jM = np.where(abs(ref - num) == M)[0][0], np.where( abs(ref - num) == M)[1][0] print '%25s (eq=%.1f deg random FC=%8.3f kjmol RV=%7.3f deg): MaxDev(%2i,%2i)=%.3e kjmol/A^2' % ( term.basename, psi0 / deg, fc / kjmol, rv / deg, iM, jM, M / (kjmol / angstrom**2)) if abs(abs(psi0) - 180 * deg) < 1 * deg or abs(psi0) < 1 * deg: print ' ==> SKIPPED due to instable numerical implementation of derivatives in Yaff for values dihedrals to 0 or 180 deg' else: assert M < tol del system, valence, ref, num
def check_hessian_oops(name, tol=1e-3 * kjmol / angstrom**2): with log.section('PROGRAM', 2): system, ref = read_system(name) guess_ffatypes(system, 'highest') valence = ValenceFF(system) for term in valence.iter_terms('/OOPDIST'): inonzero, izero = get_indices_zero_nonzero(term, len(system.numbers)) rv = 0.0 fc = np.random.uniform(low=500, high=5000) * kjmol / angstrom**2 ref, num = get_analytic_numeric_hessian(valence, term, fc=fc, rv0=rv) #assert that hessian elements of atoms not part of the current oop #are zero if len(izero[0]) > 0: assert (abs(ref[izero])).max() < 1e-12 * kjmol / angstrom**2 assert (abs(num[izero])).max() < 1e-12 * kjmol / angstrom**2 M = (abs(ref - num)).max() iM, jM = np.where(abs(ref - num) == M)[0][0], np.where( abs(ref - num) == M)[1][0] print '%25s (random FC=%8.3f kjmol/A^2 RV=%7.3f A ): MaxDev(%2i,%2i)=%.3e kjmol/A^2' % ( term.basename, fc / (kjmol / angstrom**2), rv / angstrom, iM, jM, M / (kjmol / angstrom**2)) assert M < tol for term in valence.iter_terms('SQOOPDIST'): inonzero, izero = get_indices_zero_nonzero(term, len(system.numbers)) rv = np.random.uniform(low=0.01, high=0.1) * angstrom**2 fc = np.random.uniform(low=500, high=5000) * kjmol / angstrom**4 ref, num = get_analytic_numeric_hessian(valence, term, fc=fc, rv0=rv) #assert that hessian elements of atoms not part of the current oop #are zero if len(izero[0]) > 0: assert (abs(ref[izero])).max() < 1e-12 * kjmol / angstrom**2 assert (abs(num[izero])).max() < 1e-12 * kjmol / angstrom**2 M = (abs(ref - num)).max() iM, jM = np.where(abs(ref - num) == M)[0][0], np.where( abs(ref - num) == M)[1][0] print '%25s (random FC=%8.3f kjmol/A^4 RV=%7.3f A^2): MaxDev(%2i,%2i)=%.3e kjmol/A^2' % ( term.basename, fc / (kjmol / angstrom**4), rv / angstrom**2, iM, jM, M / (kjmol / angstrom**2)) assert M < tol del system, valence, ref, num
def check_hessian_bends(name, tol=1e-3 * kjmol / angstrom**2): with log.section('NOSETST', 2): system, ref = read_system(name) guess_ffatypes(system, 'highest') valence = ValenceFF(system) for term in valence.iter_terms('BENDAHARM'): inonzero, izero = get_indices_zero_nonzero(term, len(system.numbers)) rv = np.random.uniform(low=10, high=170) * deg fc = np.random.uniform(low=100, high=1000) * kjmol / rad**2 ref, num = get_analytic_numeric_hessian(valence, term, fc=fc, rv0=rv) #assert that hessian elements of atoms not part of the current bend #are zero if len(izero[0]) > 0: assert (abs(ref[izero])).max() < 1e-12 * kjmol / angstrom**2 assert (abs(num[izero])).max() < 1e-12 * kjmol / angstrom**2 M = (abs(ref - num)).max() iM, jM = np.where(abs(ref - num) == M)[0][0], np.where( abs(ref - num) == M)[1][0] print '%25s (random FC=%8.3f kjmol/rad^2 RV=%7.3f deg): MaxDev(%2i,%2i)=%.3e kjmol/A^2' % ( term.basename, fc / (kjmol / rad**2), rv / deg, iM, jM, M / (kjmol / angstrom**2)) assert M < tol del system, valence, ref, num
def main(): args = parse_args() # Load system file if args.fn_sys.endswith('.fchk'): numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio( args.fn_sys, do_hess=False) system = System(numbers, coords, rvecs=None, charges=None, radii=None, masses=masses) system.detect_bonds() else: system = System.from_file(args.fn_sys) # Guess atom types if needed if args.ffatypes is not None: guess_ffatypes(system, args.ffatypes) ffatypes = [system.ffatypes[i] for i in system.ffatype_ids] # Load atomic charges fn_charges, _, path = args.charges.partition(':') if fn_charges.endswith('.h5'): with h5.File(fn_charges, 'r') as f: if not path in f: raise IOError( 'Given HDF5 file %s does not contain a dataset %s' % (fn_charges, path)) charges = f[path][:] radii = None if args.gaussian: path_radii = os.path.join(os.path.dirname(path), 'radii') if 'radii' in f[path]: radii = average(f['%s/radii' % path][:], ffatypes, fmt='dict') else: radii = average(get_ei_radii(system.numbers), ffatypes, fmt='dict') elif fn_charges.endswith('.chk'): sample = load_chk(fn_charges) if path in sample.keys(): charges = sample[path] else: raise IOError( 'Given CHK file %s does not contain a dataset with label %s' % (fn_charges, path)) radii = None if args.gaussian: if 'radii' in sample.keys(): radii = average(sample['radii'], ffatypes, fmt='dict') else: raise IOError( 'Invalid extension, fn_charges should be a HDF5 or a CHK file.') # Derive charge parameters if args.bci: constraints = {} if args.bci_constraints is not None: constraints = read_bci_constraints(args.bci_constraints) bcis = charges_to_bcis(charges, ffatypes, system.bonds, constraints=constraints, verbose=args.verbose) make_yaff_ei(args.fn_out, None, bcis=bcis, radii=radii) else: charges = average(charges, ffatypes, fmt='dict', verbose=args.verbose) make_yaff_ei(args.fn_out, charges, radii=radii)
def main(): options, args = parse() fn_sys, fn_in, path = args if fn_sys.endswith('.fchk'): numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio( fn_sys, do_hess=False) system = System(numbers, coords, rvecs=None, charges=None, radii=None, masses=masses) system.detect_bonds() else: system = System.from_file(fn_sys) if options.ffatypes is not None: guess_ffatypes(system, options.ffatypes) ffatypes = [system.ffatypes[i] for i in system.ffatype_ids] if fn_in.endswith('.h5'): h5 = h5py.File(fn_in) if not path in h5 or 'charges' not in h5[path]: raise IOError( 'Given HDF5 file %s does not contain dataset %s/charges' % (fn_in, path)) charges = h5['%s/charges' % path][:] radii = None if options.gaussian: if 'radii' in h5[path]: radii = average(h5['%s/radii' % path][:], ffatypes, fmt='dict') else: radii = average(get_ei_radii(system.numbers), ffatypes, fmt='dict') elif fn_in.endswith('.chk'): sample = load_chk(fn_in) if path in sample.keys(): charges = sample[path] else: raise IOError( 'Given CHK file %s does not contain dataset with label %s' % (fn_in, path)) radii = None if options.gaussian: if 'radii' in sample.keys(): radii = average(sample['radii'], ffatypes, fmt='dict') else: raise IOError( 'Invalid extension, fn_in should be a HDF5 or a CHK file.') if options.output is None: if path == '.': fn_out = 'pars_ei.txt' else: fn_out = 'pars_ei_%s.txt' % path.replace('/', '_') else: fn_out = options.output if options.bci: constraints = {} if options.bci_constraints is not None: constraints = read_bci_constraints(options.bci_constraints) bcis = charges_to_bcis(charges, ffatypes, system.bonds, constraints=constraints, verbose=options.verbose) make_yaff_ei(fn_out, None, bcis=bcis, radii=radii) else: charges = average(charges, ffatypes, fmt='dict', verbose=options.verbose) make_yaff_ei(fn_out, charges, radii=radii)
def main(): options, fns = parse() #define logger if options.silent: log.set_level('silent') else: if options.very_verbose: log.set_level('highest') elif options.verbose: log.set_level('high') if options.logfile is not None and isinstance(options.logfile, str): log.write_to_file(options.logfile) with log.section('QFF', 1, timer='Initializing'): log.dump('Initializing system') #read system and ab initio reference system = None energy = 0.0 grad = None hess = None rvecs = None for fn in fns: if fn.endswith('.fchk') or fn.endswith('.xml'): numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio( fn) if system is None: system = System(numbers, coords, rvecs=rvecs, charges=None, radii=None, masses=masses) else: system.pos = coords.copy() system.cell = Cell(rvecs) system.numbers = numbers.copy() if masses is not None: system.masses = masses.copy() system._init_derived() elif fn.endswith('.chk'): sample = load_chk(fn) if 'energy' in sample.keys(): energy = sample['energy'] if 'grad' in sample.keys(): grad = sample['grad'] elif 'gradient' in sample.keys(): grad = sample['gradient'] if 'hess' in sample.keys(): hess = sample['hess'] elif 'hessian' in sample.keys(): hess = sample['hessian'] if system is None: system = System.from_file(fn) else: if 'pos' in sample.keys(): system.pos = sample['pos'] elif 'coords' in sample.keys(): system.pos = sample['coords'] if 'rvecs' in sample.keys(): system.cell = Cell(sample['rvecs']) elif 'cell' in sample.keys(): system.cell = Cell(sample['cell']) if 'bonds' in sample.keys(): system.bonds = sample['bonds'] if 'ffatypes' in sample.keys(): system.ffatypes = sample['ffatypes'] if 'ffatype_ids' in sample.keys(): system.ffatype_ids = sample['ffatype_ids'] system._init_derived() else: raise NotImplementedError('File format for %s not supported' % fn) assert system is not None, 'No system could be defined from input' assert grad is not None, 'No ab initio gradient found in input' assert hess is not None, 'No ab initio hessian found in input' #complete the system information if system.bonds is None: system.detect_bonds() if system.masses is None: system.set_standard_masses() if system.ffatypes is None: if options.ffatypes in ['low', 'medium', 'high', 'highest']: guess_ffatypes(system, options.ffatypes) elif options.ffatypes is not None: raise NotImplementedError( 'Guessing atom types from %s not implemented' % options.ffatypes) else: raise AssertionError('No atom types defined') #construct ab initio reference ai = SecondOrderTaylor('ai', coords=system.pos.copy(), energy=energy, grad=grad, hess=hess, pbc=pbc) #detect a priori defined contributions to the force field refs = [] if options.ei is not None: if rvecs is None: ff = ForceField.generate(system, options.ei, rcut=50 * angstrom) else: ff = ForceField.generate(system, options.ei, rcut=20 * angstrom, alpha_scale=3.2, gcut_scale=1.5, smooth_ei=True) refs.append(YaffForceField('EI', ff)) if options.vdw is not None: ff = ForceField.generate(system, options.vdw, rcut=20 * angstrom) refs.append(YaffForceField('vdW', ff)) if options.covres is not None: ff = ForceField.generate(system, options.covres) refs.append(YaffForceField('Cov res', ff)) #define quickff program assert options.program_mode in allowed_programs, \ 'Given program mode %s not allowed. Choose one of %s' %( options.program_mode, ', '.join([prog for prog in allowed_programs if not prog=='BaseProgram']) ) mode = program_modes[options.program_mode] only_traj = 'PT_ALL' if options.only_traj is not None: only_traj = options.only_traj.split(',') program = mode(system, ai, ffrefs=refs, fn_traj=options.fn_traj, only_traj=only_traj, plot_traj=options.ener_traj, xyz_traj=options.xyz_traj, suffix=options.suffix) #run program program.run()
def test_output_charmm22(): with log.section('NOSETST', 2): system, ai = read_system('ethanol/gaussian.fchk') guess_ffatypes(system, 'low') with tmpdir('test_output_charmm22') as dn: fn_yaff = os.path.join(dn, 'pars_cov.txt') fn_charmm22_prm = os.path.join(dn, 'test.prm') fn_charmm22_psf = os.path.join(dn, 'test.psf') fn_sys = os.path.join(dn, 'system.chk') program = DeriveDiagFF(system, ai, fn_yaff=fn_yaff, fn_charmm22_prm=fn_charmm22_prm, fn_charmm22_psf=fn_charmm22_psf, fn_sys=fn_sys) program.run() assert os.path.isfile(fn_yaff) assert os.path.isfile(fn_charmm22_prm) assert os.path.isfile(fn_charmm22_psf) assert os.path.isfile(fn_sys) # Count the number of BOND, ANGLES and DIHEDRAL lines in the PRM file. counts = {} with open(fn_charmm22_prm, 'r') as f: for line in f: line = line[:line.find('!')].strip() if len(line) == 0: continue if line in ['BONDS', 'ANGLES', 'DIHEDRALS', 'IMPROPER']: key = line counts[key] = 0 else: counts[key] += 1 assert counts['BONDS'] == 4 assert counts['ANGLES'] == 5 assert counts['DIHEDRALS'] == 2 assert counts['IMPROPER'] == 0 # Count the number atoms, bonds, angles and dihedrals in the PSF file and # check for consistency. with open(fn_charmm22_psf, 'r') as f: natom = 0 assert f.next() == 'PSF\n' for line in f: if '!NATOM' in line: natom = int(line.split()[0]) break assert natom == system.natom for iatom in xrange(natom + 1): f.next() line = f.next() assert '!NBOND: bonds' in line nbond = int(line.split()[0]) nline = int(np.ceil(nbond / 4.0)) numbers = (''.join([f.next() for iline in xrange(nline)])).split() assert len(numbers) == nbond * 2 f.next() line = f.next() assert '!NTHETA: angles' in line ntheta = int(line.split()[0]) nline = int(np.ceil(ntheta / 3.0)) numbers = (''.join([f.next() for iline in xrange(nline)])).split() assert len(numbers) == ntheta * 3 f.next() line = f.next() assert '!NPHI: dihedrals' in line nphi = int(line.split()[0]) nline = int(np.ceil(nphi / 2.0)) numbers = (''.join([f.next() for iline in xrange(nline)])).split() assert len(numbers) == nphi * 4 f.next() line = f.next() assert '!NIMPHI: impropers' in line nimphi = int(line.split()[0]) assert nimphi == 0