def buildtree(input_atoms, u, v, j, e): if j == 0: atomsp = leapfrog(input_atoms, v * e) if u <= np.exp(-atomsp.get_total_energy()): # if u <= atomsp.get_total_energy(): cp = [atomsp] else: # print 'Fail MH' cp = [] sp = u < np.exp(delta_max - atomsp.get_total_energy()) # sp = u < delta_max + atomsp.get_total_energy() if sp == 0: # print 'Fail slice test' pass return atomsp, atomsp, cp, sp else: neg_atoms, pos_atoms, cp, sp = buildtree(input_atoms, u, v, j - 1, e) if v == -1: neg_atoms, _, cpp, spp = buildtree(neg_atoms, u, v, j - 1, e) else: _, pos_atoms, cpp, spp = buildtree(pos_atoms, u, v, j - 1, e) datoms = pos_atoms.positions - neg_atoms.positions sp = sp * spp * ( np.dot(datoms.flatten(), neg_atoms.get_momenta().flatten()) >= 0) \ * (np.dot(datoms.flatten(), pos_atoms.get_momenta().flatten()) >= 0) cp += cpp return neg_atoms, pos_atoms, cp, sp
def check_leapfrog_reversibility(value): """ Test leapfrog with non-trivial momentum in reverse Parameters ---------- value: list or tuple The values to use in the tests """ atoms = value[0] calc = Spring(rt=1, k=100) atoms.set_momenta(np.ones((len(atoms), 3))) atoms.set_calculator(calc) atoms2 = leapfrog(atoms, 1, False) atoms3 = leapfrog(atoms2, -1, False) stats_check(atoms.positions, atoms3.positions)
def _find_step_size(self, input_atoms, thermal_nrg=None, momentum=None): """ Find a suitable starting step size for the simulation Parameters ----------- input_atoms: ase.Atoms object The starting atoms for the simulation thermal_nrg: The thermal energy for the simulation Returns ------- float: The step size """ atoms = dc(input_atoms) step_size = .5 if thermal_nrg: MaxwellBoltzmannDistribution(atoms, temp=thermal_nrg, force_temp=True) elif momentum: atoms.set_momenta( self.random_state.normal(0, 1, (len(atoms), 3)) * self.momentum) else: print('Some thermal energy needed') atoms_prime = leapfrog(atoms, step_size) a = 2 * (np.exp(-1 * atoms_prime.get_total_energy() + atoms.get_total_energy()) > 0.5) - 1 while (np.exp(-1 * atoms_prime.get_total_energy() + atoms.get_total_energy()))**a > 2**-a: step_size *= 2**a print('trying step size', step_size) atoms_prime = leapfrog(atoms, step_size) if step_size < 1e-7 or step_size > 1e7: step_size = 1. break print('optimal step size', step_size) return step_size
def _find_step_size(self, input_atoms, thermal_nrg=None, momentum=None): """ Find a suitable starting step size for the simulation Parameters ----------- input_atoms: ase.Atoms object The starting atoms for the simulation thermal_nrg: The thermal energy for the simulation Returns ------- float: The step size """ atoms = dc(input_atoms) step_size = .5 if thermal_nrg: MaxwellBoltzmannDistribution(atoms, temp=thermal_nrg, force_temp=True) elif momentum: atoms.set_momenta(self.random_state.normal(0, 1, ( len(atoms), 3))) else: print('Some thermal energy needed') atoms_prime = leapfrog(atoms, step_size) a = 2 * (np.exp( -1 * atoms_prime.get_total_energy() + atoms.get_total_energy() ) > 0.5) - 1 while (np.exp(-1 * atoms_prime.get_total_energy() + atoms.get_total_energy())) ** a > 2 ** -a: step_size *= 2 ** a print('trying step size', step_size) atoms_prime = leapfrog(atoms, step_size) if step_size < 1e-7 or step_size > 1e7: step_size = 1. break print('optimal step size', step_size) return step_size
def check_leapfrog_no_momentum(value): """ Test leapfrog with null forces Parameters ---------- value: list or tuple The values to use in the tests """ atoms = value[0] calc = Spring(rt=1, k=100) atoms.set_calculator(calc) atoms2 = leapfrog(atoms, 1, False) stats_check(atoms.positions, atoms2.positions)
def check_leapfrog_momentum(value): """ Test leapfrog with non-trivial momentum Parameters ---------- value: list or tuple The values to use in the tests """ atoms = value[0] calc = Spring(rt=1, k=100) atoms.set_momenta(np.ones((len(atoms), 3))) atoms.set_calculator(calc) atoms2 = leapfrog(atoms, 1, False) stats_check(atoms.positions, atoms2.positions - atoms.get_velocities())
def classical_dynamics(atoms, stepsize, n_steps): """ Create a new atomic configuration by simulating the hamiltonian dynamics of the system Parameters ---------- atoms: ase.Atoms ase.Atoms The atomic configuration stepsize: float The step size for the simulation n_steps: int The number of steps Returns ------- list of ase.Atoms This list contains all the moves made during the simulation """ atoms.get_forces() traj = [atoms] for n in range(n_steps): traj.append(leapfrog(traj[-1], stepsize)) return traj
def buildtree(input_atoms, u, v, j, e, e0, rs, beta=1): """ Build the tree of samples for NUTS, recursively Parameters ----------- input_atoms: ase.Atoms object The atoms for the tree u: float slice parameter, the baseline energy to compare against v: -1 or 1 The direction of the tree leaves, negative means that we simulate backwards in time j: int The tree depth e: float The stepsize e0: float Current energy rs: numpy.random.RandomState object The random state object used to generate the random numbers. Use of a unified random number generator with a known seed should help us to generate reproducible simulations beta: float Thermodynamic beta, a proxy for thermal energy Returns ------- Many things """ if j == 0: atoms_prime = leapfrog(input_atoms, v * e) neg_delta_energy = e0 - atoms_prime.get_total_energy() try: exp1 = np.exp(neg_delta_energy) exp2 = np.exp(Emax + neg_delta_energy) except: exp1 = 0 exp2 = 0 # print exp1, exp2 # n_prime = int(u <= np.exp(-atoms_prime.get_total_energy())) # s_prime = int(u <= np.exp(Emax-atoms_prime.get_total_energy())) n_prime = int(u <= exp1) s_prime = int(u < exp2) return (atoms_prime, atoms_prime, atoms_prime, n_prime, s_prime, min(1, np.exp(-atoms_prime.get_total_energy() + input_atoms.get_total_energy())), 1) else: (neg_atoms, pos_atoms, atoms_prime, n_prime, s_prime, a_prime, na_prime) = buildtree(input_atoms, u, v, j - 1, e, e0, rs, beta) if s_prime == 1: if v == -1: (neg_atoms, _, atoms_prime_prime, n_prime_prime, s_prime_prime, app, napp) = buildtree(neg_atoms, u, v, j - 1, e, e0, rs, beta) else: (_, pos_atoms, atoms_prime_prime, n_prime_prime, s_prime_prime, app, napp) = buildtree(pos_atoms, u, v, j - 1, e, e0, rs, beta) if rs.uniform() < float(n_prime_prime / ( max(n_prime + n_prime_prime, 1))): atoms_prime = atoms_prime_prime a_prime = a_prime + app na_prime = na_prime + napp datoms = pos_atoms.positions - neg_atoms.positions span = datoms.flatten() s_prime = s_prime_prime * ( span.dot(neg_atoms.get_velocities().flatten()) >= 0) * ( span.dot(pos_atoms.get_velocities().flatten()) >= 0) n_prime = n_prime + n_prime_prime return (neg_atoms, pos_atoms, atoms_prime, n_prime, s_prime, a_prime, na_prime)
def buildtree(input_atoms, u, v, j, e, e0, rs, beta=1): """ Build the tree of samples for NUTS, recursively Parameters ----------- input_atoms: ase.Atoms object The atoms for the tree u: float slice parameter, the baseline energy to compare against v: -1 or 1 The direction of the tree leaves, negative means that we simulate backwards in time j: int The tree depth e: float The stepsize e0: float Current energy rs: numpy.random.RandomState object The random state object used to generate the random numbers. Use of a unified random number generator with a known seed should help us to generate reproducible simulations beta: float Thermodynamic beta, a proxy for thermal energy Returns ------- Many things """ if j == 0: atoms_prime = leapfrog(input_atoms, v * e) neg_delta_energy = e0 - atoms_prime.get_total_energy() try: exp1 = np.exp(neg_delta_energy) exp2 = np.exp(Emax + neg_delta_energy) except: exp1 = 0 exp2 = 0 # print exp1, exp2 # n_prime = int(u <= np.exp(-atoms_prime.get_total_energy())) # s_prime = int(u <= np.exp(Emax-atoms_prime.get_total_energy())) n_prime = int(u <= exp1) s_prime = int(u < exp2) return (atoms_prime, atoms_prime, atoms_prime, n_prime, s_prime, min( 1, np.exp(-atoms_prime.get_total_energy() + input_atoms.get_total_energy())), 1) else: (neg_atoms, pos_atoms, atoms_prime, n_prime, s_prime, a_prime, na_prime) = buildtree(input_atoms, u, v, j - 1, e, e0, rs, beta) if s_prime == 1: if v == -1: (neg_atoms, _, atoms_prime_prime, n_prime_prime, s_prime_prime, app, napp) = buildtree(neg_atoms, u, v, j - 1, e, e0, rs, beta) else: (_, pos_atoms, atoms_prime_prime, n_prime_prime, s_prime_prime, app, napp) = buildtree(pos_atoms, u, v, j - 1, e, e0, rs, beta) if rs.uniform() < float(n_prime_prime / (max(n_prime + n_prime_prime, 1))): atoms_prime = atoms_prime_prime a_prime = a_prime + app na_prime = na_prime + napp datoms = pos_atoms.positions - neg_atoms.positions span = datoms.flatten() s_prime = s_prime_prime * (span.dot( neg_atoms.get_velocities().flatten()) >= 0) * (span.dot( pos_atoms.get_velocities().flatten()) >= 0) n_prime = n_prime + n_prime_prime return (neg_atoms, pos_atoms, atoms_prime, n_prime, s_prime, a_prime, na_prime)