def mcmc_step(box, width, r_cut, r_skin, update_nblist): # kb = 1.38064852*10**(-13) # N*Å/K (Boltzmann constant) positions_trial = [np.zeros(box.dimension) for i in range(len(box.positions))] trial_step = width * np.random.randn(*np.asarray(positions_trial).shape)/4 #randn -> std norm. dist, divide by 4 to keep results mostly within (-0.5, 0.5) for i in range(len(positions_trial)): positions_trial[i] = pbc.enforce_pbc(box.positions[i] + trial_step[i], box.size) particles_trial = [system.Particle(positions_trial[i], box.particles[i].charge, box.particles[i].sigmaLJ, box.particles[i].epsilonLJ) for i in range(len(box.particles))] # set trial particle list with trial positions if update_nblist: particles_trial = neighbourlist.verlet_neighbourlist(particles_trial, r_cut, r_skin) # update neighbourlist for trial positions else: for i in range(len(particles_trial)): particles_trial[i].neighbourlist = box.particles[i].neighbourlist LJpotential_trial = lennardjones.LJ_potential(particles_trial, r_cut, r_skin) with warnings.catch_warnings(): warnings.simplefilter("ignore") acceptance_prob = min(1.0, np.exp(-(LJpotential_trial - box.LJpotential)/box.temp)) # note: potential is actually potential/kb # if (box_trial.LJpotential>box.LJpotential): # print("increase = " + repr(box_trial.LJpotential-box.LJpotential)) # print("acceptance prob. = " + repr(acceptance_prob)) # if update_nblist: # print(acceptance_prob) if np.random.rand() < acceptance_prob: return positions_trial, True, trial_step, acceptance_prob # Return True for accepted trial step return trial_step and acceptance_prob to use in unit testing return box.positions, False, trial_step, acceptance_prob # return False for rejected trial step (no need to update box object)
def mcmc_step(box, width, r_cut, r_skin, update_nblist, kb=0.008314462175): '''Executes single step of the MCMC simulation (see mcmc below). NB: Currently only using LJ potential. Arguments: box (Box): the system/box object width (float): approximate maximum size (change in individual coordinate) of each mcmc step r_cut (float): cut-off radius for LJ neighbourlist computation r_skin (float): size of skin-reigon for LJ neighbourlist computation kb (float): boltzmann constant. Default is given in kJ/(mol*K). Can be provided in different units if desired (will result in different units for the potential and distances...) Returns: box.positions (numpy array): the updated (if trial step was accepted) array of positions of the particles in the system _ (Bool): an unnamed boolean which relays whether or not the trial step was accepted ''' positions_trial = np.zeros((len(box.particles), box.dimension)) trial_step = width * np.random.randn( *positions_trial.shape ) / 4 #randn -> std norm. dist, divide by 4 to keep output mostly within (-0.5, 0.5) for i in range(len(positions_trial)): positions_trial[i] = pbc.enforce_pbc_coordinates( box.positions[i] + trial_step[i], box.size) if update_nblist: nblist_trial = neighbourlist.verlet_neighbourlist( positions_trial, r_cut, r_skin, box.size) # update neighbourlist for trial positions else: nblist_trial = np.array(box.LJneighbourlists) LJpotential_trial = lennardjones.LJ_potential(positions_trial, nblist_trial, box.sigmas, box.epsilons, r_cut, r_skin, box.size) with warnings.catch_warnings( ): # suppress warnings for possibly large arguments of the exponential function warnings.simplefilter("ignore") acceptance_prob = min( 1.0, np.exp(-(LJpotential_trial - box.LJpotential) / (kb * box.temp))) if np.random.rand() < acceptance_prob: return positions_trial, True # Return True for accepted trial step return box.positions, False
def Ewald_energy(positions,q,r_c,r_s,boxsize): ''' arguments: positions (numpy array): particles' positions q(numpy array): the chage value r_c (float): cutoff radius for Ewald r_s (float): cutoff radius for Ewald box(numpy array):the box length in each dimension ''' r_cut = r_c + r_s EWald_neighbourlists = neighbourlist.verlet_neighbourlist(positions, r_c, r_s, box) unit_convert = (1.602119892525e-19)**2/(4*np.pi*(10**(-10)))/(8.854187817e-12) /1000/128 * 6.022140857 * 10e23 #(kJ/mol) Ewald_short = Ewald_short_energy(positions,EWald_neighbourlists, q,r_cut,box) * unit_convert Ewald_long = Ewald_long_energy(positions,q,r_cut,box) * unit_convert Ewald_self = Ewald_self_energy(positions,q,r_cut) * unit_convert return Ewald_short + Ewald_long - Ewald_self
def compute_LJneighbourlist( self, r_cut, r_skin ): # computes the (LJ) neighbourlists for the particles in the system self.LJneighbourlists = neighbourlist.verlet_neighbourlist( self.positions, r_cut, r_skin, self.size)
for i in range(len(positions)): Ewald_self += Ewald_self_energy_ij(q[i],r_cut) return Ewald_self q = np.ones(128) for i in range(128): if types[i] == 'Cl-' : q[i] = -1 #* 1.602119892525e-19 else: q[i] = 1 #* 1.602119892525e-19 #pool = ThreadPoolExecutor(max_workers=2) r_cut = min(box)/2 EWald_neighbourlists = neighbourlist.verlet_neighbourlist(positions, r_cut, 0, box) #print(EWald_neighbourlists) unit_convert = (1.602119892525e-19)**2/(4*np.pi*(10**(-10)))/(8.854187817e-12) /1000/128 * 6.022140857 * 10e23 short = Ewald_short_energy(positions,EWald_neighbourlists, q, r_cut,box) * unit_convert l = Ewald_long_energy(positions,q,r_cut,box) * unit_convert s = Ewald_self_energy(positions,q,r_cut) * unit_convert print("\rWith cutoff radius = half of the box length") print("The Ewald short range energy:",short,"\t(kJ/mol)") print("The Ewald long range energy:",l,"\t(kJ/mol)") print("The Ewald self energy:",s ,"\t(kJ/mol)") print("The total Ewald energy:",short+l-s,"(kJ/mol)")
def compute_LJneighbourlist(self, r_cut, r_skin): self.particles = neighbourlist.verlet_neighbourlist( self.particles, r_cut, r_skin)