def get_yaff_system(self, snapshot=0): numbers = np.array([ pt[symbol].number for symbol in self.structure.get_chemical_symbols() ]) if snapshot == 0: struct = self.structure else: struct = self.get_structure(iteration_step=snapshot, wrap_atoms=False) pos = struct.positions.reshape(-1, 3) * angstrom cell = struct.cell if cell is None: system = System(numbers, pos, ffatypes=self.ffatypes, ffatype_ids=self.ffatype_ids) else: system = System(numbers, pos, rvecs=cell * angstrom, ffatypes=self.ffatypes, ffatype_ids=self.ffatype_ids) system.detect_bonds() system.set_standard_masses() return system
def detect_ffatypes(self, ffatypes=None, ffatype_rules=None, ffatype_level=None): ''' Define atom types by explicitely giving them through the ffatypes keyword, defining atype rules using the ATSELECT language implemented in Yaff (see the Yaff documentation at http://molmod.github.io/yaff/ug_atselect.html) or by specifying the ffatype_level employing the built-in routine in QuickFF. ''' numbers = np.array([pt[symbol].number for symbol in self.structure.get_chemical_symbols()]) if self.structure.cell is None: system = System(numbers, self.structure.positions.copy()*angstrom) else: system = System(numbers, self.structure.positions.copy()*angstrom, rvecs=self.structure.cell*angstrom) system.detect_bonds() if not sum([ffatypes is None, ffatype_rules is None, ffatype_level is None]) == 2: raise IOError('Exactly one of ffatypes, ffatype_rules and ffatype_level should be defined') if ffatypes is not None: assert ffatype_rules is None, 'ffatypes and ffatype_rules cannot be defined both' system.ffatypes = ffatypes system.ffatype_ids = None system._init_derived_ffatypes() if ffatype_rules is not None: system.detect_ffatypes(ffatype_rules) if ffatype_level is not None: set_ffatypes(system, ffatype_level) self.ffatypes = system.ffatypes.copy() self.ffatype_ids = system.ffatype_ids.copy()
def write_chk(input_dict,working_directory='.'): # collect data and initialize Yaff system if 'cell' in input_dict.keys() and input_dict['cell'] is not None: system = System(input_dict['numbers'], input_dict['pos']*angstrom, ffatypes=input_dict['ffatypes'], ffatype_ids=input_dict['ffatype_ids'], rvecs=input_dict['cell']*angstrom) else: system = System(input_dict['numbers'], input_dict['pos']*angstrom, ffatypes=input_dict['ffatypes'], ffatype_ids=input_dict['ffatype_ids']) # determine masses, bonds and ffaypes from ffatype_rules system.detect_bonds() system.set_standard_masses() # write dictionary to MolMod CHK file system.to_file(posixpath.join(working_directory,'system.chk'))
def __init__(self, system, rules=None, cases=None): self.system = system self.cases = cases # Compile the rules if they are present if cases is None: if rules is None: rules = ['!0'] * self.natom compiled_rules = [] for rule in rules: if isinstance(rule, str): rule = atsel_compile(rule) compiled_rules.append(rule) self.rules = compiled_rules self.cases = list(self._iter_cases()) elif rules is not None: raise ValueError( 'Either rules are cases must be provided, not both.') # Construct a fake system, a dlist and an iclist for just one ic self.fake_system = System(numbers=np.zeros(self.natom, int), pos=np.zeros((self.natom, 3), float), rvecs=self.system.cell.rvecs) self.dlist = DeltaList(self.fake_system) self.iclist = InternalCoordinateList(self.dlist) self.tangent = np.zeros((self.natom, 3), float)
def test_uio66zrbrick_crossterms(): with log.section('NOSETEST', 2): # Load input data for a ficticious system of an isolated # UiO-66 brick with path('quickff.data.systems.uio66-zr-brick', 'system.chk') as fn: data = load_chk(fn) system = System(data['numbers'],data['pos'],charges=data['charges'], ffatypes=data['ffatypes'],bonds=data['bonds'],radii=data['radii']) system.set_standard_masses() ai = SecondOrderTaylor('ai', coords=system.pos.copy(), grad=data['gradient'], hess=data['hessian']) # Run QuickFF with tmpdir('test_uio66') as dn: fn_yaff = os.path.join(dn, 'pars_cov.txt') fn_sys = os.path.join(dn, 'system.chk') fn_log = os.path.join(dn, 'quickff.log') program = DeriveFF(system, ai, Settings(consistent_cross_rvs=True, remove_dysfunctional_cross=True,fn_yaff=fn_yaff,fn_sys=fn_sys,log_file=fn_log)) program.run() # Check force constants of cross terms and corresponding diagonal terms print("%50s %15s %15s"%("Basename","Cross FC","Diag FC")) for term in program.valence.terms: if not term.is_master(): continue if term.basename.startswith('Cross'): fc = program.valence.get_params(term.index, only='fc') for i in [0,1]: fc_diag = program.valence.get_params(term.diag_term_indexes[i], only='fc') print("%50s %15.6f %15.6f %50s" % (term.basename,fc,fc_diag,program.valence.terms[term.diag_term_indexes[i]].basename)) if fc_diag==0.0: assert fc==0.0
def test_detect_bonds_cyclopropene_exceptions(): system = get_system_cyclopropene() # create system without bonds system = System(system.numbers, system.pos) # Add bonds between all hydrogen and carbon atoms (unrealistic but useful for testing) system.detect_bonds({(1, 6): 8.0 * angstrom}) assert system.nbond == 3 + 4 * 3
def test_detect_bonds_water_exceptions(): system = get_system_water32() # create system without bonds system = System(system.numbers, system.pos) # Add bonds between hydrogen atoms (unrealistic but useful for testing) system.detect_bonds({(1, 1): 2.0 * angstrom}) assert system.nbond >= 96
def read_system(name): # Load system data dn = 'quickff.data.systems' if '/' in name: words = name.split('/') dn += '.%s' % ('.'.join(words[:-1])) name = words[-1] with path(dn, name) as fn: numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio( fn) fns_wpart = glob(os.path.join(os.path.dirname(fn), 'gaussian_mbis.h5')) # Try to load charges. charges = None if len(fns_wpart) > 0: with h5.File(fns_wpart[0], 'r') as f: charges = f['charges'][:] # Create system object. system = System(numbers, coords, charges=charges) system.detect_bonds() system.set_standard_masses() # Load ab initio data. ai = SecondOrderTaylor('ai', coords=system.pos.copy(), energy=energy, grad=grad, hess=hess, pbc=pbc) return system, ai
def load_system_cube(fn): '''Load system from fn in cube format''' # TODO: this should be moved into Yaff/MolMod print 'Loading atomic structure from CUBE file.' with open(fn) as f: # Skip two header lines. f.next() f.next() # Read number of atoms. natom = int(f.next().split()[0]) assert natom > 0 # Read real-space vectors rvecs = np.zeros((3, 3), float) for irow in xrange(3): words = f.next().split() nrep = int(words[0]) rvecs[irow, 0] = nrep * float(words[1]) rvecs[irow, 1] = nrep * float(words[2]) rvecs[irow, 2] = nrep * float(words[3]) print 'Treating system as periodic with the following cell vectors' print 'in Angstrom. (Cell vectors are displayed as rows.)' print rvecs / angstrom # Read atomic numbers and coordinates numbers = np.zeros(natom, int) coordinates = np.zeros((natom, 3), float) for iatom in xrange(natom): words = f.next().split() numbers[iatom] = int(words[0]) coordinates[iatom, 0] = float(words[2]) coordinates[iatom, 1] = float(words[3]) coordinates[iatom, 2] = float(words[4]) print return System(numbers=numbers, pos=coordinates, rvecs=rvecs)
def test_detect_bonds_glycine(): system = get_system_glycine() check_detect_bonds(system) system = System(system.numbers, system.pos) system.detect_bonds() assert hasattr(system, 'neighs1') assert hasattr(system, 'neighs2') assert hasattr(system, 'neighs3')
def read_system(name): fn = context.get_fn('systems/%s' %name) numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio(fn) system = System(numbers, coords) system.detect_bonds() system.set_standard_masses() ai = SecondOrderTaylor('ai', coords=system.pos.copy(), energy=energy, grad=grad, hess=hess, pbc=pbc) return system, ai
def test_iter_matches_single_atom(): system = System.from_file(context.get_fn('test/rhodium_complex_nobornane.xyz')) system.detect_bonds() system_ref = System(pos=np.zeros((1, 3), float), numbers = np.array([45])) system_ref.detect_bonds() selected = set(system.iter_matches(system_ref).next()) reference = set([28]) np.testing.assert_equal(selected, reference)
def test_supercell_nobonds(): cellpar = 2.867 * angstrom sys111 = System( numbers=np.array([26, 26]), pos=np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) * cellpar, ffatypes=['Fe', 'Fe'], rvecs=np.identity(3) * cellpar, ) sys333 = sys111.supercell(3, 3, 3)
def test_iter_matches_single_atom(): system = System.from_file( pkg_resources.resource_filename( __name__, '../data/test/rhodium_complex_nobornane.xyz')) system.detect_bonds() system_ref = System(pos=np.zeros((1, 3), float), numbers=np.array([45])) system_ref.detect_bonds() selected = set(next(system.iter_matches(system_ref))) reference = set([28]) np.testing.assert_equal(selected, reference)
def test_scopes2(): system = System(numbers=np.array([8, 1, 1, 6, 1, 1, 1, 8, 1]), pos=np.zeros((9, 3), float), scopes=['WAT', 'METH'], scope_ids=np.array([0, 0, 0, 1, 1, 1, 1, 1, 1]), ffatypes=['O', 'H', 'C', 'H_C', 'O', 'H_O'], ffatype_ids=np.array([0, 1, 1, 2, 3, 3, 3, 4, 5])) assert (system.scopes == ['WAT', 'METH']).all() assert (system.scope_ids == np.array([0, 0, 0, 1, 1, 1, 1, 1, 1])).all() assert (system.ffatypes == ['O', 'H', 'C', 'H_C', 'O', 'H_O']).all() assert (system.ffatype_ids == np.array([0, 1, 1, 2, 3, 3, 3, 4, 5])).all()
def write_chk(input_dict, working_directory='.'): # collect data and initialize Yaff system if 'cell' in input_dict.keys() and input_dict['cell'] is not None: system = System(input_dict['numbers'], input_dict['pos']*angstrom, rvecs=input_dict['cell']*angstrom, ffatypes=input_dict['ffatypes_man'], ffatype_ids=input_dict['ffatype_ids_man']) else: system = System(input_dict['numbers'], input_dict['pos']*angstrom, ffatypes=input_dict['ffatypes_man'], ffatype_ids=input_dict['ffatype_ids_man']) # determine masses, bonds and ffaypes from ffatype_rules system.detect_bonds() system.set_standard_masses() # write dictionnairy to MolMod CHK file system.to_file(posixpath.join(working_directory,'input.chk')) # Reload input.chk as dictionairy and add AI input data d = load_chk(posixpath.join(working_directory,'input.chk')) assert isinstance(input_dict['aiener'], float), "AI energy not defined in input, use job.read_abintio(...)" assert isinstance(input_dict['aigrad'], np.ndarray), "AI gradient not defined in input, use job.read_abintio(...)" assert isinstance(input_dict['aihess'], np.ndarray), "AI hessian not defined in input, use job.read_abintio(...)" d['energy'] = input_dict['aiener'] d['grad'] = input_dict['aigrad'] d['hess'] = input_dict['aihess'] dump_chk(posixpath.join(working_directory,'input.chk'), d)
def test_supercell_charges(): cellpar = 2.867 * angstrom sys111 = System( numbers=np.array([26, 26]), pos=np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) * cellpar, ffatypes=['Fe', 'Fe'], charges=np.array([0.1, 1.0]), radii=np.array([0.0, 2.0]), rvecs=np.identity(3) * cellpar, ) sys333 = sys111.supercell(3, 3, 3) assert (sys333.charges == np.tile(np.array([0.1, 1.0]), 27)).all() assert (sys333.radii == np.tile(np.array([0.0, 2.0]), 27)).all()
def test_scopes3(): system = System(numbers=np.array([8, 1, 1, 6, 1, 1, 1, 8, 1]), pos=np.zeros((9, 3), float), scopes=['WAT', 'METH'], scope_ids=np.array([0, 0, 0, 1, 1, 1, 1, 1, 1]), ffatypes=['O', 'H', 'C', 'H_C', 'H_O'], ffatype_ids=np.array([0, 1, 1, 2, 3, 3, 3, 0, 4])) assert (system.scopes == ['WAT', 'METH']).all() assert (system.scope_ids == np.array([0, 0, 0, 1, 1, 1, 1, 1, 1])).all() assert (system.ffatypes == ['O', 'H', 'C', 'H_C', 'H_O', 'O']).all() assert (system.ffatype_ids == np.array([0, 1, 1, 2, 3, 3, 3, 5, 4])).all() assert system.get_scope(0) == 'WAT' assert system.get_scope(3) == 'METH' assert system.get_ffatype(0) == 'O' assert system.get_ffatype(7) == 'O' assert system.get_ffatype(8) == 'H_O'
def read_system(name): # Load system data. fn = context.get_fn(os.path.join('systems', name)) numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio(fn) # Try to load charges. charges = None fns_wpart = glob(os.path.join(os.path.dirname(fn), 'gaussian_mbis.h5')) if len(fns_wpart) > 0: with h5.File(fns_wpart[0], 'r') as f: charges = f['charges'][:] # Create system object. system = System(numbers, coords, charges=charges) system.detect_bonds() system.set_standard_masses() # Load ab initio data. ai = SecondOrderTaylor('ai', coords=system.pos.copy(), energy=energy, grad=grad, hess=hess, pbc=pbc) return system, ai
def test_remove_duplicate_dipoles(): cellpar = 2.867 * angstrom system1 = System( numbers=np.array([26, 27]), pos=np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) * cellpar, ffatypes=['A', 'B'], dipoles=np.array([[0.1, 1.0, 2.0], [0.5, 0.7, 0.9]]), radii2=np.array([0.0, 2.0]), rvecs=np.identity(3) * cellpar, ) system2 = system1.supercell(1, 2, 1) system2.cell = system1.cell system3 = system2.remove_duplicate() for j, number in enumerate([26, 27]): #By removing duplicates, atoms might be reordered i = np.where(system3.numbers == number)[0] assert system1.radii2[j] == system3.radii2[i] assert np.all(system1.dipoles[j] == system3.dipoles[i])
self.make_output() #settings with log.section('INIT', 2, timer='Initialization'): settings = Settings(fn_yaff='pars_cov.txt', plot_traj='All', xyz_traj=True) #load Gaussian Formatted Checkpoint file fchk = FCHKFile('gaussian.fchk') numbers = fchk.fields.get('Atomic numbers') energy = fchk.fields.get('Total Energy') coords = fchk.fields.get('Current cartesian coordinates').reshape([len(numbers), 3]) grad = fchk.fields.get('Cartesian Gradient').reshape([len(numbers), 3]) hess = fchk.get_hessian().reshape([len(numbers), 3, len(numbers), 3]) #Construct Yaff System file system = System(numbers, coords) system.detect_bonds() system.set_standard_masses() #Construct a QuickFF SecondOrderTaylor object containing the AI reference with log.section('INIT', 2, timer='Initialization'): ai = SecondOrderTaylor('ai', coords=coords, energy=energy, grad=grad, hess=hess) #define atom types rules = [ ('H', '1 & =1%8'), #hydrogen atom with one oxygen neighbor ('O', '8 & =2%1'), #oxygen atom with two hydrogen neighbors ] system.detect_ffatypes(rules) #construct electrostatic force field from HE charges in gaussian_wpart.h5
def write_lammps_table_jelle(ff): from yaff import NeighborList, PairPotEI, Switch3, ForcePartPair, Scalings,\ PairPotMM3 nffa = ff.system.ffatypes.shape[0] numbers = [] for i in xrange(nffa): index0 = np.where(ff.system.ffatype_ids == i)[0][0] if np.sum(ff.system.ffatype_ids == i) > 1: index1 = np.where(ff.system.ffatype_ids == i)[0][1] numbers.append([index0, index1]) for j in xrange(i + 1, nffa): index1 = np.where(ff.system.ffatype_ids == j)[0][0] numbers.append([index0, index1]) part_names = [part.name for part in ff.parts] print part_names ftab = open('lammps_smoothei2.table', 'w') ftab.write("# LAMMPS tabulated potential generated by Yaff\n") ftab.write("# All quantities in atomic units\n") ftab.write( "# The names of the tables refer to the ffatypes that have to be used in the Yaff system\n" ) ftab.write("#%4s %13s %21s %21s\n" % ("i", "d", "V", "F")) for number in numbers: pos = np.zeros((2, 3)) pos[1, 2] = 1.0 smallsys = System(system.numbers[number], pos, charges=system.charges[number], radii=system.radii[number]) smallsys_noradii = System(system.numbers[number], pos, charges=system.charges[number]) idx_ei = -1 idx_mm3 = -1 for idx, part in enumerate(ff.parts): if part.name == 'pair_ei': idx_ei = idx elif part.name == 'pair_mm3': idx_mm3 = idx tr = ff.parts[idx_ei].pair_pot.get_truncation() rcut = ff.parts[idx_ei].pair_pot.rcut alpha = ff.parts[idx_ei].pair_pot.alpha nlist = NeighborList(smallsys) pair_pot = PairPotEI(smallsys.charges, alpha, rcut, tr=Switch3(tr.width), radii=smallsys.radii) # pair_pot = PairPotEI(smallsys.charges, 0.0, rcut, tr=None, radii=smallsys.radii) scalings = Scalings(smallsys, scale1=1.0, scale2=1.0, scale3=1.0) part0 = ForcePartPair(smallsys, nlist, scalings, pair_pot) ff0 = ForceField(smallsys, [part0], nlist) ff0.compute() nlist1 = NeighborList(smallsys_noradii) # pair_pot = PairPotEI(smallsys_noradii.charges, alpha, rcut, tr=Switch3(tr.width)) pair_pot = PairPotEI(smallsys_noradii.charges, alpha, rcut, tr=None) scalings = Scalings(smallsys_noradii, scale1=1.0, scale2=1.0, scale3=1.0) part1 = ForcePartPair(smallsys_noradii, nlist1, scalings, pair_pot) ff1 = ForceField(smallsys_noradii, [part1], nlist1) ff1.compute() tr = ff.parts[idx_mm3].pair_pot.get_truncation() rcut = ff.parts[idx_mm3].pair_pot.rcut nlist2 = NeighborList(smallsys) pair_pot = PairPotMM3(ff.parts[idx_mm3].pair_pot.sigmas[number], ff.parts[idx_mm3].pair_pot.epsilons[number], ff.parts[idx_mm3].pair_pot.onlypaulis[number], rcut, Switch3(tr.width)) scalings = Scalings(smallsys, scale1=1.0, scale2=1.0, scale3=1.0) part2 = ForcePartPair(smallsys, nlist, scalings, pair_pot) ff2 = ForceField(smallsys, [part2], nlist) ff2.nlist.nneigh = 1 ff2.compute() distances = np.linspace(0.5 * angstrom, rcut, 5000) energies = [] toplot = [] for d in distances: gposnn0 = np.zeros(ff0.system.pos.shape, float) ff0.nlist.neighs[0] = (0, 1, d, 0.0, 0.0, d, 0, 0, 0) energy0 = ff0.compute(gpos=gposnn0) gposnn1 = np.zeros(ff1.system.pos.shape, float) ff1.nlist.neighs[0] = (0, 1, d, 0.0, 0.0, d, 0, 0, 0) energy1 = ff1.compute(gpos=gposnn1) gposnn2 = np.zeros(ff2.system.pos.shape, float) ff2.nlist.neighs[0] = (0, 1, d, 0.0, 0.0, d, 0, 0, 0) energy2 = ff2.compute(gpos=gposnn2) toplot.append([d, energy0, energy1, energy2]) row = [ d, energy0 - energy1 + energy2, gposnn0[0, 2] - gposnn1[0, 2] + gposnn2[0, 2] ] # row = [d, energy2, gposnn2[0,2]] energies.append(row) energies = np.asarray(energies) toplot = np.asarray(toplot) ffa0 = ff.system.ffatypes[ff.system.ffatype_ids[number[0]]] ffa1 = ff.system.ffatypes[ff.system.ffatype_ids[number[1]]] if ffa0 > ffa1: name = '%s-%s' % (ffa0, ffa1) else: name = '%s-%s' % (ffa1, ffa0) ftab.write("%s\nN %d R %f %f\n\n" % (name, energies.shape[0], distances[0], distances[-1])) for irow, row in enumerate(energies): ftab.write("%05d %+13.8f %+21.12f %+21.12f\n" % (irow + 1, row[0], row[1], row[2])) print name
def test_exclusion(): def random_rotation(pos): com = np.average(pos, axis=0) pos -= com while True: V1 = np.random.rand() V2 = np.random.rand() S = V1**2 + V2**2 if S < 1: break theta = np.array([ 2 * np.pi * (2 * V1 * np.sqrt(1 - S) - 0.5), 2 * np.pi * (2 * V2 * np.sqrt(1 - S) - 0.5), np.pi * ((1 - 2 * S) / 2) ]) R_x = np.array([[1, 0, 0], [0, np.cos(theta[0]), -np.sin(theta[0])], [0, np.sin(theta[0]), np.cos(theta[0])]]) R_y = np.array([[np.cos(theta[1]), 0, np.sin(theta[1])], [0, 1, 0], [-np.sin(theta[1]), 0, np.cos(theta[1])]]) R_z = np.array([[np.cos(theta[2]), -np.sin(theta[2]), 0], [np.sin(theta[2]), np.cos(theta[2]), 0], [0, 0, 1]]) R = np.dot(R_z, np.dot(R_y, R_x)) pos_new = np.zeros((len(pos), len(pos[0]))) for i, p in enumerate(pos): pos_new[i] = np.dot(R, np.array(p).T) return pos_new + com def get_adsorbate_pos(adsorbate, rvecs): pos = adsorbate.pos pos = random_rotation(pos) pos -= np.average(pos, axis=0) new_com = np.random.rand() * rvecs[0] + np.random.rand( ) * rvecs[1] + np.random.rand() * rvecs[2] return pos + new_com # Empty framework system = System.from_file( pkg_resources.resource_filename(__name__, '../../data/test/CAU_13.chk')) N_system = len(system.pos) ff_file = pkg_resources.resource_filename( __name__, '../../data/test/parameters_CAU-13_xylene.txt') ff = ForceField.generate(system, ff_file) ff.nlist.update() E_parts = {part.name: part.compute() for part in ff.parts} ff_new = ForceField.generate(system, ff_file, exclude_frame=True, n_frame=N_system) ff_new.nlist.update() E_parts_new = {part.name: part.compute() for part in ff_new.parts} # Add 4 adsorbates adsorbate = System.from_file( pkg_resources.resource_filename(__name__, '../../data/test/xylene.chk')) pos = system.pos ffatypes = np.append(system.ffatypes, adsorbate.ffatypes) bonds = system.bonds numbers = system.numbers ffatype_ids = system.ffatype_ids charges = system.charges masses = system.masses for i in range(4): pos = np.append(pos, get_adsorbate_pos(adsorbate, system.cell.rvecs), axis=0) bonds = np.append(bonds, adsorbate.bonds + N_system + len(adsorbate.pos) * i, axis=0) numbers = np.append(numbers, adsorbate.numbers, axis=0) ffatype_ids = np.append(ffatype_ids, adsorbate.ffatype_ids + max(system.ffatype_ids) + 1, axis=0) charges = np.append(charges, adsorbate.charges, axis=0) masses = np.append(masses, adsorbate.masses, axis=0) # Framework with 4 adsorbates system = System(numbers, pos, ffatypes=ffatypes, ffatype_ids=ffatype_ids, bonds=bonds,\ rvecs = system.cell.rvecs, charges=charges, masses=masses) ff = ForceField.generate(system, ff_file) ff_new = ForceField.generate(system, ff_file, exclude_frame=True, n_frame=N_system) # Test 100 random configurations for i in range(100): new_pos = ff.system.pos for i in range(4): new_pos[N_system + i * len(adsorbate.pos):N_system + (i + 1) * len(adsorbate.pos)] = get_adsorbate_pos( adsorbate, system.cell.rvecs) ff.update_pos(new_pos) ff_new.update_pos(new_pos) ff.nlist.update() ff_new.nlist.update() E_parts_rand = {part.name: part.compute() for part in ff.parts} E_parts_new_rand = {part.name: part.compute() for part in ff_new.parts} for key, _ in E_parts.items(): assert (E_parts[key] - E_parts_rand[key]) - ( E_parts_new[key] - E_parts_new_rand[key]) < 10e-12
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 qff(args=None): if args is None: args = qff_parse_args() else: args = qff_parse_args(args) #define logger verbosity = None if args.silent: verbosity = 'silent' else: if args.very_verbose: verbosity = 'highest' elif args.verbose: verbosity = 'high' #get settings kwargs = { 'fn_traj': args.fn_traj, 'only_traj': args.only_traj, 'program_mode': args.program_mode, 'plot_traj': args.plot_traj, 'xyz_traj': args.xyz_traj, 'suffix': args.suffix, 'log_level': verbosity, 'log_file': args.logfile, 'ffatypes': args.ffatypes, 'ei': args.ei, 'ei_rcut': args.ei_rcut, 'vdw': args.vdw, 'vdw_rcut': args.vdw_rcut, 'covres': args.covres, } settings = Settings(fn=args.config_file, **kwargs) with log.section('INIT', 1, timer='Initializing'): log.dump('Initializing system') #read system and ab initio reference system = None energy = 0.0 grad = None hess = None pbc = None rvecs = None for fn in args.fn: 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 list(sample.keys()): energy = sample['energy'] if 'grad' in list(sample.keys()): grad = sample['grad'] elif 'gradient' in list(sample.keys()): grad = sample['gradient'] if 'hess' in list(sample.keys()): hess = sample['hess'] elif 'hessian' in list(sample.keys()): hess = sample['hessian'] if 'rvecs' in list(sample.keys()): pbc = [1, 1, 1] else: pbc = [0, 0, 0] if system is None: system = System.from_file(fn) else: if 'pos' in list(sample.keys()): system.pos = sample['pos'] elif 'coords' in list(sample.keys()): system.pos = sample['coords'] if 'rvecs' in list(sample.keys()): system.cell = Cell(sample['rvecs']) elif 'cell' in list(sample.keys()): system.cell = Cell(sample['cell']) if 'bonds' in list(sample.keys()): system.bonds = sample['bonds'] if 'ffatypes' in list(sample.keys()): system.ffatypes = sample['ffatypes'] if 'ffatype_ids' in list(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 settings.ffatypes is not None: set_ffatypes(system, settings.ffatypes) else: raise AssertionError('No atom types defined') if settings.do_hess_negfreq_proj: log.dump( 'Projecting negative frequencies out of the mass-weighted hessian.' ) with log.section('SYS', 3, 'Initializing'): hess = project_negative_freqs(hess, system.masses) #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 settings.ei is not None: if rvecs is None: if settings.ei_rcut is None: rcut = 50 * angstrom else: rcut = settings.ei_rcut ff = ForceField.generate(system, settings.ei, rcut=rcut) else: if settings.ei_rcut is None: rcut = 20 * angstrom else: rcut = settings.ei_rcut ff = ForceField.generate(system, settings.ei, rcut=rcut, alpha_scale=3.2, gcut_scale=1.5, smooth_ei=True) refs.append(YaffForceField('EI', ff)) if settings.vdw is not None: ff = ForceField.generate(system, settings.vdw, rcut=settings.vdw_rcut) refs.append(YaffForceField('vdW', ff)) if settings.covres is not None: ff = ForceField.generate(system, settings.covres) refs.append(YaffForceField('Cov res', ff)) #define quickff program assert settings.program_mode in allowed_programs, \ 'Given program mode %s not allowed. Choose one of %s' %( settings.program_mode, ', '.join([prog for prog in allowed_programs if not prog=='BaseProgram']) ) mode = program_modes[settings.program_mode] program = mode(system, ai, settings, ffrefs=refs) #run program program.run() return program
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 run_GCMC(self, N_iterations, N_sample): A = Acceptance() if rank == 0: if not (os.path.isdir('results')): try: os.mkdir('results') except:pass if self.write_traj: ftraj = open('results/traj_%.8f.xyz'%(self.P/bar), 'w') e = 0 t_it = time() N_samples = [] E_samples = [] pressures = [] traj = [] q0s = [] if rank == 0: print('\n Iteration inst. N inst. E inst. V time [s]') print('--------------------------------------------------------') for iteration in range(N_iterations+1): if self.ads_ei: sfac_init = deepcopy(self.sfac) pos_init = deepcopy(self.pos) rvecs_init = deepcopy(self.rvecs) rvecs_flat_init = deepcopy(self.rvecs_flat) V_init = self.V e_el_real_init = self.e_el_real e_vdw_init = self.e_vdw switch = np.random.rand() acc = 0 # Insertion / deletion if(switch < self.prob[0] and not self.Z_ads == self.fixed_N): if(switch < self.prob[0]/2): new_pos = random_ads(self.pos_ads, self.rvecs) e_new = self.insertion(new_pos) exp_value = self.beta * (-e_new + e) if(exp_value > 100): acc = 1 elif(exp_value < -100): acc = 0 else: acc = min(1, self.V*self.beta*self.fugacity/self.Z_ads * np.exp(exp_value)) # Reject monte carlo move if np.random.rand() > acc: self.pos = pos_init if self.ads_ei: self.sfac = sfac_init self.e_el_real = e_el_real_init self.e_vdw = e_vdw_init self.Z_ads -= 1 else: e = e_new elif(self.Z_ads > 0): deleted_coord, e_new = self.deletion() exp_value = -self.beta * (e_new - e) if(exp_value > 100): acc = 1 else: acc = min(1, (self.Z_ads+1)/self.V/self.beta/self.fugacity * np.exp(exp_value)) # Reject monte carlo move if np.random.rand() > acc: self.pos = pos_init if self.ads_ei: self.sfac = sfac_init self.e_el_real = e_el_real_init self.e_vdw = e_vdw_init self.Z_ads += 1 else: e = e_new elif(switch < self.prob[1]): if self.Z_ads != 0: trial = np.random.randint(self.Z_ads) if((switch < self.prob[0] + (self.prob[1]-self.prob[0])/2) or self.nads == 1): # Calculate translation energy as deletion + insertion of molecule deleted_coord, e_new = self.deletion() deleted_coord += self.step * (np.random.rand(3) - 0.5) e_new = self.insertion(deleted_coord) else: # Calculate rotation energy as deletion + insertion of molecule deleted_coord, e_new = self.deletion() deleted_coord = random_rot(deleted_coord, circlefrac=0.1) e_new = self.insertion(deleted_coord) exp_value = -self.beta * (e_new - e) if(exp_value > 0): exp_value = 0 acc = min(1, np.exp(exp_value)) # Reject monte carlo move if np.random.rand() > acc: self.pos = pos_init if self.ads_ei: self.sfac = sfac_init self.e_el_real = e_el_real_init self.e_vdw = e_vdw_init else: e = e_new else: # Construct system and forcefield class for the MD engine from yaff import System, ForceField, XYZWriter, VerletScreenLog, MTKBarostat, \ NHCThermostat, TBCombination, VerletIntegrator, HDF5Writer, log log.set_level(0) n = np.append(self.data.numbers_MOF, np.tile(self.data.numbers_ads, self.Z_ads)) ffa_MOF = self.data.system.ffatypes[self.data.system.ffatype_ids] ffa_ads = self.data.system_ads.ffatypes[self.data.system_ads.ffatype_ids] ffa = np.append(ffa_MOF, np.tile(ffa_ads, self.Z_ads)) assert len(self.pos) == len(ffa) s = System(n, self.pos, ffatypes = ffa, rvecs=self.rvecs) s.detect_bonds() ff = ForceField.generate(s, self.ff_file, rcut=self.rcut, alpha_scale=self.alpha_scale, gcut_scale=self.gcut_scale, tailcorrections=True) ff_lammps = swap_noncovalent_lammps(ff, fn_system='system_%.8f.dat'%(self.P/bar), fn_table='table.dat', nrows=5000, kspace='pppm', kspace_accuracy=1e-7, scalings_ei = [1.0, 1.0, 1.0], move_central_cell=False, fn_log="none", overwrite_table=False, comm=comm) # Setup and NPT MD run if rank == 0: vsl = VerletScreenLog(step=50) if self.write_h5s: if self.fixed_N: hdf5_writer = HDF5Writer(h5.File('results/temp_%d.h5'%self.fixed_N, mode='w'), step=101) else: hdf5_writer = HDF5Writer(h5.File('results/temp_%.8f.h5'%(self.P/bar), mode='w'), step=101) ensemble_hook = NHCThermostat(temp=self.T, timecon=100*femtosecond, chainlength=3) if self.barostat: mtk = MTKBarostat(ff_lammps, temp=self.T, press=self.P, \ timecon=1000*femtosecond, vol_constraint = self.vol_constraint, anisotropic = True) ensemble_hook = TBCombination(ensemble_hook, mtk) if self.meta: cv = CVVolume(ff_lammps.system) sigma = 1000*angstrom**3 K = 20*kjmol step = 498 # Run MD t = time() if self.write_h5s: if rank == 0: verlet = VerletIntegrator(ff_lammps, self.timestep, hooks=[ensemble_hook, vsl, hdf5_writer], temp0=self.T) else: verlet = VerletIntegrator(ff_lammps, self.timestep, hooks=[ensemble_hook], temp0=self.T) else: if rank == 0: hooks = [ensemble_hook, vsl] if self.meta: meta = MTDHook(ff_lammps, cv, sigma, K, start=step, step=step) for q0 in q0s: meta.hills.add_hill(q0, K) hooks.append(meta) verlet = VerletIntegrator(ff_lammps, self.timestep, hooks=hooks, temp0=self.T) else: hooks = [ensemble_hook] if self.meta: meta = MTDHook(ff_lammps, cv, sigma, K, start=step, step=step) for q0 in q0s: meta.hills.add_hill(q0, K) hooks.append(meta) verlet = VerletIntegrator(ff_lammps, self.timestep, hooks=hooks, temp0=self.T) e0_tot = verlet._compute_ekin() + ff_lammps.compute() verlet.run(600) ef_tot = verlet._compute_ekin() + ff_lammps.compute() if not self.vol_constraint: Vn = np.linalg.det(ff_lammps.system.cell.rvecs) exp_value = -self.beta * (ef_tot - e0_tot + self.P * (Vn - self.V) - len(self.pos)/self.beta * np.log(Vn/self.V)) else: exp_value = -self.beta * (ef_tot - e0_tot) if(exp_value > 0): exp_value = 0 acc = min(1, np.exp(exp_value)) # Accept monte carlo move if np.random.rand() < acc: if self.write_h5s: # Append MD data to previous data self.append_h5() # Rebuild data for MC pos_total = ff_lammps.system.pos self.pos = pos_total[:self.N_frame] pos_molecules = pos_total[self.N_frame:] self.rvecs = ff_lammps.system.cell.rvecs self.rvecs_flat = self.rvecs.reshape(9) self.V = np.linalg.det(self.rvecs) if self.meta: q0s.append(self.V) if self.ads_ei: self.sfac = Sfac(self.pos, self.N_frame, self.rvecs_flat, \ self.charges, self.alpha, self.gcut) self.e_el_real = 0 self.e_vdw = 0 if self.Z_ads > 0: for p in np.split(pos_molecules, self.Z_ads): e_new = self.insertion(p) self.Z_ads -= 1 e = e_new else: e = 0 else: self.pos = pos_init self.rvecs = rvecs_init self.rvecs_flat = rvecs_flat_init self.V = V_init if rank == 0: log.set_level(log.medium) if(iteration % N_sample == 0 and iteration > 0): eprint = e if np.abs(eprint) < 1e-10: eprint = 0 if rank == 0: print(' {:7.7} {:7.7} {:7.7} {:7.7} {:7.4}'.format( str(iteration),str(self.Z_ads),str(eprint/kjmol),str(self.V/angstrom**3),time()-t_it) ) t_it = time() N_samples.append(self.Z_ads) E_samples.append(e) if self.Z_ads == self.fixed_N: traj.append(self.pos) if rank == 0 and self.write_traj: natom = self.N_frame + self.nads * self.Z_ads rv = self.rvecs_flat/angstrom ffa_MOF = self.data.system.ffatypes[self.data.system.ffatype_ids] ffa_ads = self.data.system_ads.ffatypes[self.data.system_ads.ffatype_ids] ffa = np.append(ffa_MOF, np.tile(ffa_ads, self.Z_ads)) ftraj.write('%d\n%f %f %f %f %f %f %f %f %f\n'%(natom, rv[0], rv[1], rv[2], rv[3], rv[4], rv[5], rv[6], rv[7], rv[8])) for s, p in zip(ffa, self.pos/angstrom): ftraj.write('%s %f %f %f\n'%(s, p[0], p[1], p[2])) if rank == 0: print('Average N: %.3f'%np.average(N_samples)) if self.fixed_N: np.save('results/N_%d.npy'%self.fixed_N, np.array(N_samples)) np.save('results/E_%d.npy'%self.fixed_N, np.array(E_samples)) else: np.save('results/N_%.8f.npy'%(self.P/bar), np.array(N_samples)) np.save('results/E_%.8f.npy'%(self.P/bar), np.array(E_samples)) if self.fixed_N: from yaff import System n = np.append(self.data.numbers_MOF, np.tile(self.data.numbers_ads, self.Z_ads)) s = System(n, self.pos, rvecs=self.rvecs) s.to_file('results/end_%d.xyz'%self.fixed_N) mol = Molecule.from_file('results/end_%d.xyz'%self.fixed_N) symbols = mol.symbols self.write_traj(traj, symbols) os.remove('results/end_%d.xyz'%self.fixed_N) if self.write_traj: ftraj.close()
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()