def test_lj_insert(): system_file = pkg_resources.resource_filename(__name__, '../data/lp_avg.chk') ff_file = pkg_resources.resource_filename(__name__, '../data/pars.txt') adsorbate_file = pkg_resources.resource_filename(__name__, '../data/argon.chk') T = 87 * kelvin P = 1 * bar MD_trial_fraction = 0.000 rcut = 15 * angstrom fugacity = P # Try 10 configurations for i in range(10): mcmd = MCMD(system_file, adsorbate_file, ff_file, T, P, fugacity, MD_trial_fraction, rcut, fixed_N = 25) N_frame = len(mcmd.pos) new_pos = random_ads(mcmd.pos_ads, mcmd.rvecs) pos = np.append(mcmd.pos, new_pos, axis=0) new_pos2 = random_ads(mcmd.pos_ads, mcmd.rvecs) pos2 = np.append(pos, new_pos2, axis=0) Z_ads = 2 plen = len(pos) plen2 = len(pos2) e_vdw = LJ(pos2, N_frame, Z_ads, mcmd.rvecs_flat, mcmd.data.sigmas[:plen2], mcmd.data.epsilons[:plen2], rcut) e_vdw_insert = LJ_insert(pos, len(pos)-mcmd.nads, mcmd.N_frame, mcmd.rvecs_flat, mcmd.data.sigmas[:plen], mcmd.data.epsilons[:plen], mcmd.rcut) e_vdw_insert += LJ_insert(pos2, len(pos2)-mcmd.nads, mcmd.N_frame, mcmd.rvecs_flat, mcmd.data.sigmas[:plen2], mcmd.data.epsilons[:plen2], mcmd.rcut) print(e_vdw/kjmol, e_vdw_insert/kjmol) assert np.abs(e_vdw - e_vdw_insert) < 1e-8
def test_ei_rcut(): system_file = pkg_resources.resource_filename(__name__, '../data/lp_avg.chk') ff_file = pkg_resources.resource_filename(__name__, '../data/pars.txt') adsorbate_file = pkg_resources.resource_filename(__name__, '../data/CO2.chk') T = 87 * kelvin P = 1 * bar MD_trial_fraction = 0.000 fugacity = P def get_total_ei(rcut, new_pos, new_pos2): mcmd = MCMD(system_file, adsorbate_file, ff_file, T, P, fugacity, MD_trial_fraction, rcut, fixed_N = 25) sfac = Sfac(mcmd.pos, mcmd.N_frame, mcmd.rvecs_flat, mcmd.charges, mcmd.alpha, mcmd.gcut) pos = np.append(mcmd.pos, new_pos, axis=0) pos2 = np.append(pos, new_pos2, axis=0) Z_ads = 2 plen = len(pos) plen2 = len(pos2) ei_insert_1 = electrostatics_realspace_insert(mcmd.N_frame, len(pos)-mcmd.nads, pos, mcmd.rvecs_flat, mcmd.data.charges[:plen], mcmd.data.radii[:plen], rcut, mcmd.alpha, mcmd.gcut) sfac = np.array(ewald_insertion(sfac, new_pos, mcmd.rvecs_flat, mcmd.data.charges_ads, mcmd.alpha, mcmd.gcut)) ew_insert_1 = ewald_from_sfac(sfac, mcmd.rvecs_flat, mcmd.alpha, mcmd.gcut) ei_insert_2 = ei_insert_1 + electrostatics_realspace_insert(mcmd.N_frame, len(pos2)-mcmd.nads, pos2, mcmd.rvecs_flat, mcmd.data.charges[:plen2], mcmd.data.radii[:plen2], rcut, mcmd.alpha, mcmd.gcut) sfac = np.array(ewald_insertion(sfac, new_pos2, mcmd.rvecs_flat, mcmd.data.charges_ads, mcmd.alpha, mcmd.gcut)) ew_insert_2 = ewald_from_sfac(sfac, mcmd.rvecs_flat, mcmd.alpha, mcmd.gcut) ei_full_2 = electrostatics(pos2, mcmd.N_frame, 2, mcmd.rvecs_flat, mcmd.data.charges[:plen2], mcmd.data.radii[:plen2], rcut, mcmd.alpha, mcmd.gcut) return ew_insert_2 + ei_insert_2, ei_full_2 # Try 10 configurations for i in range(10): mcmd = MCMD(system_file, adsorbate_file, ff_file, T, P, fugacity, MD_trial_fraction, 30*angstrom, fixed_N = 25) sfac = Sfac(mcmd.pos, mcmd.N_frame, mcmd.rvecs_flat, mcmd.charges, mcmd.alpha, mcmd.gcut) new_pos = random_ads(mcmd.pos_ads, mcmd.rvecs) new_pos2 = random_ads(mcmd.pos_ads, mcmd.rvecs) ei_base, ei_base_check = get_total_ei(30*angstrom, new_pos, new_pos2) print('base: ', ei_base/kjmol) assert(np.abs(ei_base - ei_base_check) < 1e-8) for rcut in 25, 20, 15, 12, 10: ei, ei_check = get_total_ei(rcut*angstrom, new_pos, new_pos2) print(rcut, ei/kjmol) assert np.abs(ei_base - ei)/kjmol < 0.2 assert(np.abs(ei - ei_check) < 1e-8)
def test_mm3_tail(): system_file = pkg_resources.resource_filename(__name__, '../data/lp_avg.chk') ff_file = pkg_resources.resource_filename(__name__, '../data/pars.txt') adsorbate_file = pkg_resources.resource_filename(__name__, '../data/argon.chk') T = 87 * kelvin P = 1 * bar MD_trial_fraction = 0.000 fugacity = P mcmd = MCMD(system_file, adsorbate_file, ff_file, T, P, fugacity, MD_trial_fraction, 8*angstrom, fixed_N = 25) # Try 10 configurations for i in range(10): N_frame = len(mcmd.pos) new_pos = random_ads(mcmd.pos_ads, mcmd.rvecs) pos = np.append(mcmd.pos, new_pos, axis=0) Z_ads = 1 plen = len(pos) e_vdw_insert_base = MM3_insert(pos, len(pos)-mcmd.nads, mcmd.N_frame, mcmd.rvecs_flat, mcmd.data.sigmas[:plen], mcmd.data.epsilons[:plen], 30*angstrom) print('base: ', e_vdw_insert_base/kjmol) for rcut in 25, 20, 15, 12, 10: e_vdw_insert = MM3_insert(pos, len(pos)-mcmd.nads, mcmd.N_frame, mcmd.rvecs_flat, mcmd.data.sigmas[:plen], mcmd.data.epsilons[:plen], rcut*angstrom) print(rcut, e_vdw_insert/kjmol) assert np.abs(e_vdw_insert_base - e_vdw_insert)/kjmol < 0.2
def test_ei_insert(): system_file = pkg_resources.resource_filename(__name__, '../data/lp_avg.chk') ff_file = pkg_resources.resource_filename(__name__, '../data/pars.txt') adsorbate_file = pkg_resources.resource_filename(__name__, '../data/CO2.chk') T = 87 * kelvin P = 1 * bar MD_trial_fraction = 0.000 rcut = 15 * angstrom fugacity = P # Try 10 configurations for i in range(10): mcmd = MCMD(system_file, adsorbate_file, ff_file, T, P, fugacity, MD_trial_fraction, rcut, fixed_N = 25) sfac = Sfac(mcmd.pos, mcmd.N_frame, mcmd.rvecs_flat, mcmd.charges, mcmd.alpha, mcmd.gcut) N_frame = len(mcmd.pos) new_pos = random_ads(mcmd.pos_ads, mcmd.rvecs) pos = np.append(mcmd.pos, new_pos, axis=0) new_pos2 = random_ads(mcmd.pos_ads, mcmd.rvecs) pos2 = np.append(pos, new_pos2, axis=0) Z_ads = 2 plen = len(pos) plen2 = len(pos2) ei_insert_1 = electrostatics_realspace_insert(mcmd.N_frame, len(pos)-mcmd.nads, pos, mcmd.rvecs_flat, mcmd.data.charges[:plen], mcmd.data.radii[:plen], mcmd.rcut, mcmd.alpha, mcmd.gcut) sfac = np.array(ewald_insertion(sfac, new_pos, mcmd.rvecs_flat, mcmd.data.charges_ads, mcmd.alpha, mcmd.gcut)) ew_insert_1 = ewald_from_sfac(sfac, mcmd.rvecs_flat, mcmd.alpha, mcmd.gcut) ei_full_1 = electrostatics(pos, mcmd.N_frame, 1, mcmd.rvecs_flat, mcmd.data.charges[:plen], mcmd.data.radii[:plen], mcmd.rcut, mcmd.alpha, mcmd.gcut) print(ei_insert_1/kjmol, ew_insert_1/kjmol, ei_full_1/kjmol) assert (np.abs(ei_full_1 - ei_insert_1 - ew_insert_1) < 1e-8).all() ei_insert_2 = ei_insert_1 + electrostatics_realspace_insert(mcmd.N_frame, len(pos2)-mcmd.nads, pos2, mcmd.rvecs_flat, mcmd.data.charges[:plen2], mcmd.data.radii[:plen2], mcmd.rcut, mcmd.alpha, mcmd.gcut) sfac = np.array(ewald_insertion(sfac, new_pos2, mcmd.rvecs_flat, mcmd.data.charges_ads, mcmd.alpha, mcmd.gcut)) ew_insert_2 = ewald_from_sfac(sfac, mcmd.rvecs_flat, mcmd.alpha, mcmd.gcut) ei_full_2 = electrostatics(pos2, mcmd.N_frame, 2, mcmd.rvecs_flat, mcmd.data.charges[:plen2], mcmd.data.radii[:plen2], mcmd.rcut, mcmd.alpha, mcmd.gcut) print(ei_insert_2/kjmol, ew_insert_2/kjmol, ei_full_2/kjmol) assert (np.abs(ei_full_2 - ei_insert_2 - ew_insert_2) < 1e-8).all()
def run_widom(self, N_iterations, N_sample): if not (os.path.isdir('results')): os.mkdir('results') E_samples = [] print('\n Iteration inst. Hads [kJ/mol] inst. K_H [mol/kg/bar] time [s]') print('-------------------------------------------------------------------') t_it = time() for iteration in range(N_iterations): new_pos = random_ads(self.pos_ads, self.rvecs) self.pos = np.append(self.pos, new_pos, axis=0) e_insertion = self.compute_insertion(new_pos) E_samples.append(e_insertion) # Reset e_el_real, e_vdw, sfac and pos self.sfac = deepcopy(self.sfac_frame) self.e_el_real, self.e_vdw = 0, 0 self.pos = self.pos[:-self.n_ad] if iteration > 0 and iteration % N_sample == 0: E_temp = np.array(E_samples) # if adsorption energies are very positive, a division by 0 error will occur here: try: E_ads = np.average(E_temp*np.exp(-self.beta*E_temp))/np.average(np.exp(-self.beta*E_temp)) except: E_m = min(E_temp) E_ads = np.average(E_temp*np.exp(-self.beta*(E_temp-E_m)))/np.average(np.exp(-self.beta*(E_temp-E_m))) rho = self.mass/np.linalg.det(self.rvecs) K_H = self.beta/rho*np.average(np.exp(-self.beta*E_temp)) print(' {:7.7} {:7.7} {:7.7} {:7.4}'.format( str(iteration),str((E_ads - 1/self.beta)/kjmol),str(K_H/(avogadro/(kilogram*bar))), time()-t_it) ) t_it = time() E_samples = np.array(E_samples) if self.write_all: np.save('results/Widom_E.npy', np.array(E_samples)) else: rho = self.mass/np.linalg.det(self.rvecs) # Do bootstrapping def bootstrap(data, type='Hads'): means = [] for i in range(100): means.append(sample_mean(data, type)) return np.average(means), np.std(np.array(means)) def sample_mean(data, type): resampled = np.random.choice(data, len(data), replace=True) if type == 'Hads': try: return (np.average(resampled*np.exp(-self.beta*resampled))/np.average(np.exp(-self.beta*resampled)) - 1/self.beta)/kjmol except: E_m = min(resampled) return (np.average(resampled*np.exp(-self.beta*(resampled-E_m)))/np.average(np.exp(-self.beta*(resampled-E_m))) - 1/self.beta)/kjmol elif type == 'KH': return np.average(self.beta/rho*np.exp(-self.beta*resampled) / (avogadro/(kilogram*bar))) H_ads_av, H_ads_std = bootstrap(E_samples, type='Hads') K_H_av, K_H_std = bootstrap(E_samples, type='KH') bootstrap_data = np.array([[H_ads_av, H_ads_std], [K_H_av, K_H_std]]) print(bootstrap_data) np.save('results/Widom_result.npy', bootstrap_data)
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()