def accept(s, q_old, q_new, w_old=1.0, w_new=1.0): """Returns accept/reject decision based on supplied entropy table.""" import numpy as np from maths_module import metropolis # This routine is essentially the Metropolis-Hastings formula, generalized # to use a specified tabulated function of the energy in the exponent # For NVT MC, s(q) is just E(q)/kT = -q/kT since energy is -q # For Wang-Landau, s(q) is the entropy function, which is updated through the run # In either case, weights (real, but taking positive integer values here) may optionally appear w_tol = np.float_(0.5) # Check that we are within bounds for the entropy table assert q_new >= 0 and q_new < s.size, 'q_new out of bounds' assert q_old >= 0 and q_old < s.size, 'q_old out of bounds' # Check values of weights assert w_old > w_tol, 'Impossible weight error' if w_new < w_tol: # Should really have been detected before return False delta = s[q_new] - s[q_old] # Change in entropy function # Equivalent to exp(-delta) -> (w_new/w_old)*exp(-delta) delta = delta - np.log(w_new / w_old) result = metropolis(delta) return result
for k in range(p): # Loop over ring polymer indices rkj = np.delete(r[k, :, :], i, 0) # Array of all other atoms for this k partial_old = partial_old + potential_1( r[k, i, :], box, r_cut, rkj, p) # Old atom classical potential etc rki = r[k, i, :] + dc rki = rki - np.rint(rki) partial_new = partial_new + potential_1( rki, box, r_cut, rkj, p) # New atom classical potential etc assert not partial_old.ovr, 'Overlap in current configuration' if not partial_new.ovr: # Test for non-overlapping configuration delta = partial_new.pot - partial_old.pot # Change in classical cut (but not shifted) potential delta = delta / temperature if metropolis(delta): # Accept Metropolis test total = total + partial_new - partial_old # Update total values r[:, i, :] = r[:, i, :] + dc # Update positions r[:, i, :] = r[:, i, :] - np.rint( r[:, i, :]) # Periodic boundary conditions c_moves = c_moves + 1 # Increment move counter # Individual atom moves for k in range(p): # Loop over ring polymer indices rkj = np.delete(r[k, :, :], i, 0) # Array of all the other atoms partial_old = potential_1( r[k, i, :], box, r_cut, rkj, p) # Old atom classical potential etc assert not partial_old.ovr, 'Overlap in current configuration'
rj = np.delete(r, i, 0) # Array of all the other atoms partial_old = potential_1(r[i, :], box, r_cut, rj) # Old atom potential, virial etc assert not partial_old.ovr, 'Overlap in current configuration' ri = random_translate_vector( dr_max / box, r[i, :]) # Trial move to new position (in box=1 units) ri = ri - np.rint(ri) # Periodic boundary correction partial_new = potential_1(ri, box, r_cut, rj) # New atom potential, virial etc if not partial_new.ovr: # Test for non-overlapping configuration delta = partial_new.pot - partial_old.pot # Use cut (but not shifted) potential delta = delta / temperature if metropolis(delta): # Accept Metropolis test total = total + partial_new - partial_old # Update total values r[i, :] = ri # Update position moves = moves + 1 # Increment move counter m_ratio = moves / n x_ratio = 0.0 for updown in range(2): # Loop to look one way then the other if m % 2 == updown: # Look up, partner is m+1 if m + 1 < nproc: # Ensure partner exists other_beta = every_beta[ m + 1] # We already know the other beta other_pot = comm.recv( source=m + 1, tag=msg1_id) # Receive pot from other process