def propagate(atoms, asap3, algorithm, algoargs): with seterr(all='raise'): print() md = algorithm(atoms, timestep=20 * fs, logfile='-', loginterval=1000, **algoargs) # Gather data for 50 ps T = [] p = [] for i in range(500): md.run(5) T.append(atoms.get_temperature()) pres = -atoms.get_stress(include_ideal_gas=True)[:3].sum() / 3 p.append(pres) Tmean = np.mean(T) p = np.array(p) pmean = np.mean(p) print('Temperature: {:.2f} K +/- {:.2f} K (N={})'.format( Tmean, np.std(T), len(T))) print('Center-of-mass corrected temperature: {:.2f} K'.format( Tmean * len(atoms) / (len(atoms) - 1))) print('Pressure: {:.2f} bar +/- {:.2f} bar (N={})'.format( pmean / bar, np.std(p) / bar, len(p))) return Tmean, pmean
def test_fixrotation_asap(asap3): rng = np.random.RandomState(123) with seterr(all='raise'): atoms = bulk('Au', cubic=True).repeat((3, 3, 10)) atoms.pbc = False atoms.center(vacuum=5.0 + np.max(atoms.cell) / 2) print(atoms) atoms.calc = asap3.EMT() MaxwellBoltzmannDistribution(atoms, temperature_K=300, force_temp=True, rng=rng) Stationary(atoms) check_inertia(atoms) md = Langevin( atoms, timestep=20 * fs, temperature_K=300, friction=1e-3, logfile='-', loginterval=500, rng=rng) fx = FixRotation(atoms) md.attach(fx) md.run(steps=1000) check_inertia(atoms)
def equilibrated(asap3, berendsenparams): """Make an atomic system with equilibrated temperature and pressure.""" rng = np.random.RandomState(42) with seterr(all='raise'): print() # Must be big enough to avoid ridiculous fluctuations atoms = bulk('Au', cubic=True).repeat((3, 3, 3)) #a[5].symbol = 'Ag' print(atoms) atoms.calc = asap3.EMT() MaxwellBoltzmannDistribution(atoms, temperature_K=100, force_temp=True, rng=rng) Stationary(atoms) assert abs(atoms.get_temperature() - 100) < 0.0001 md = NPTBerendsen(atoms, timestep=20 * fs, logfile='-', loginterval=200, **berendsenparams['npt']) # Equilibrate for 20 ps md.run(steps=1000) T = atoms.get_temperature() pres = -atoms.get_stress( include_ideal_gas=True)[:3].sum() / 3 / GPa * 10000 print("Temperature: {:.2f} K Pressure: {:.2f} bar".format(T, pres)) return atoms
def make_table(self, name): print('VDW: Generating vdW-DF kernel ...') print('VDW:', end=' ') ndelta = len(self.delta_i) nD = len(self.D_j) self.phi_ij = np.zeros((ndelta, nD)) for i in range(self.world.rank, ndelta, self.world.size): print(ndelta - i, end=' ') sys.stdout.flush() delta = self.delta_i[i] for j in range(nD - 1, -1, -1): D = self.D_j[j] d = D * (1.0 + delta) dp = D * (1.0 - delta) if d**2 + dp**2 > self.ds**2: with seterr(divide='ignore'): self.phi_ij[i, j] = phi(d, dp) else: P = np.polyfit([0, self.D_j[j + 1]**2, self.D_j[j + 2]**2], [ self.phi0, self.phi_ij[i, j + 1], self.phi_ij[i, j + 2] ], 2) self.phi_ij[i, :j + 3] = np.polyval(P, self.D_j[:j + 3]**2) break self.world.sum(self.phi_ij) print() print('VDW: Done!') header = ('phi0={0:.3f}, ds={1:.3f}, Dmax={2:.3f}, nD={3}, ndelta={4}'. format(self.phi0, self.ds, self.D_j[-1], len(self.delta_i), len(self.D_j))) if self.world.rank == 0: np.savetxt(name, self.phi_ij, header=header)
def __init__(self, l, alpha_B, rgd, eps=1.0e-7): """Guassian basis set for spherically symmetric atom. l: int Angular momentum quantum number. alpha_B: ndarray Exponents. rgd: GridDescriptor Grid descriptor. eps: float Cutoff for eigenvalues of overlap matrix.""" self.l = l self.alpha_B = alpha_B self.rgd = rgd self.eps = eps A_BB = np.add.outer(alpha_B, alpha_B) M_BB = np.multiply.outer(alpha_B, alpha_B) # Overlap matrix: S_BB = (2 * M_BB**0.5 / A_BB)**(l + 1.5) # Kinetic energy matrix: T_BB = 2**(l + 2.5) * M_BB**(0.5 * l + 0.75) / gamma(l + 1.5) * ( gamma(l + 2.5) * M_BB / A_BB**(l + 2.5) - 0.5 * (l + 1) * gamma(l + 1.5) / A_BB**(l + 0.5) + 0.25 * (l + 1) * (2 * l + 1) * gamma(l + 0.5) / A_BB**(l + 0.5)) # Derivative matrix: D_BB = 2**(l + 2.5) * M_BB**(0.5 * l + 0.75) / gamma(l + 1.5) * ( 0.5 * (l + 1) * gamma(l + 1) / A_BB**(l + 1) - gamma(l + 2) * alpha_B / A_BB**(l + 2)) # 1/r matrix: K_BB = 2**(l + 2.5) * M_BB**(0.5 * l + 0.75) / gamma(l + 1.5) * ( 0.5 * gamma(l + 1) / A_BB**(l + 1)) # Find set of linearly independent functions. # We have len(alpha_B) gaussians (index B) and self.nbasis # linearly independent functions (index b). s_B, U_BB = eigh(S_BB) self.nbasis = int((s_B > eps).sum()) Q_Bb = np.dot(U_BB[:, -self.nbasis:], np.diag(s_B[-self.nbasis:]**-0.5)) self.T_bb = np.dot(np.dot(Q_Bb.T, T_BB), Q_Bb) self.D_bb = np.dot(np.dot(Q_Bb.T, D_BB), Q_Bb) self.K_bb = np.dot(np.dot(Q_Bb.T, K_BB), Q_Bb) r_g = rgd.r_g with seterr(divide='ignore'): # Avoid errors in debug mode from division by zero: gaussians_Bg = np.exp(-np.outer(alpha_B, r_g**2)) * r_g**l prefactors_B = (2 * (2 * alpha_B)**(l + 1.5) / gamma(l + 1.5))**0.5 self.basis_bg = np.dot(Q_Bb.T, prefactors_B[:, None] * gaussians_Bg)
def test_verlet(): with seterr(all='raise'): a = Atoms('4X', masses=[1, 2, 3, 4], positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0.1, 0.2, 0.7)], calculator=TstPotential()) print(a.get_forces()) md = VelocityVerlet(a, timestep=0.5 * fs, logfile='-', loginterval=500) traj = Trajectory('4N.traj', 'w', a) md.attach(traj.write, 100) e0 = a.get_total_energy() md.run(steps=10000) del traj assert abs(read('4N.traj').get_total_energy() - e0) < 0.0001 qn = QuasiNewton(a) qn.run(0.001) assert abs(a.get_potential_energy() - 1.0) < 0.000002
def test_verlet_asap(asap3): with seterr(all='raise'): a = bulk('Au').repeat((2, 2, 2)) a[5].symbol = 'Ag' a.pbc = (True, True, False) print(a) a.calc = asap3.EMT() MaxwellBoltzmannDistribution(a, 300 * kB, force_temp=True) Stationary(a) assert abs(a.get_temperature() - 300) < 0.0001 print(a.get_forces()) md = VelocityVerlet(a, timestep=2 * fs, logfile='-', loginterval=500) traj = Trajectory('Au7Ag.traj', 'w', a) md.attach(traj.write, 100) e0 = a.get_total_energy() md.run(steps=10000) del traj assert abs(a.get_total_energy() - e0) < 0.0001 assert abs(read('Au7Ag.traj').get_total_energy() - e0) < 0.0001
def __init__(self, cell_cv, nk_c, txt=None): txt = txt or sys.stdout self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() print('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr,)), file=txt) self.a = 5 / rc print('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] print('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_ijk = self.gd.empty() pos_ijkv = self.gd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) corner_xv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) # Ignore division by zero (in 0,0,0 corner): with seterr(invalid='ignore'): # Loop over first dimension to avoid too large ndarrays. for pos_jkv, v_jk in zip(pos_ijkv, v_ijk): # Distances to the 8 corners: d_jkxv = pos_jkv[:, :, np.newaxis] - corner_xv r_jk = (d_jkxv**2).sum(axis=3).min(2)**0.5 v_jk[:] = erf(self.a * r_jk) / r_jk # Fix 0/0 corner value: v_ijk[0, 0, 0] = 2 * self.a / pi**0.5 self.K_Q = np.fft.fftn(v_ijk) * self.gd.dv
def test_langevin_asap(asap3): with seterr(all='raise'): rng = np.random.RandomState(0) a = bulk('Au', cubic=True).repeat((4, 4, 4)) a.pbc = (False, False, False) a.center(vacuum=2.0) print(a) a.calc = asap3.EMT() # Set temperature to 10 K MaxwellBoltzmannDistribution(a, temperature_K=10, force_temp=True, rng=rng) Stationary(a) assert abs(a.get_temperature() - 10) < 0.0001 # Langevin dynamics should raise this to 300 K T = 300 md = Langevin(a, timestep=4 * fs, temperature_K=T, friction=0.01, logfile='-', loginterval=500, rng=rng) md.run(steps=3000) # Now gather the temperature over 10000 timesteps, collecting it # every 5 steps temp = [] for i in range(1500): md.run(steps=5) temp.append(a.get_temperature()) temp = np.array(temp) avgtemp = np.mean(temp) fluct = np.std(temp) print("Temperature is {:.2f} K +/- {:.2f} K".format(avgtemp, fluct)) assert abs(avgtemp - T) < 10.0
def test_verlet_thermostats_asap(asap3): rng = np.random.RandomState(0) calculator = asap3.EMT() T_low = 10 T_high = 300 md_kwargs = {'timestep': 0.5 * fs, 'logfile': '-', 'loginterval': 500} with seterr(all='raise'): a = bulk('Au').repeat((4, 4, 4)) a[5].symbol = 'Ag' # test thermalization by MaxwellBoltzmannDistribution thermalize(T_high, a, rng) assert abs(a.get_temperature() - T_high) < 0.0001 # test conservation of total energy e0 using Verlet a_verlet, traj = prepare_md(a, calculator) e0 = a_verlet.get_total_energy() md = VelocityVerlet(a_verlet, **md_kwargs) md.attach(traj.write, 100) md.run(steps=10000) traj_verlet = read('Au7Ag.traj', index=':') assert abs(traj_verlet[-1].get_total_energy() - e0) < 0.0001 # test reproduction of Verlet by Langevin and Andersen for thermostats # switched off pos_verlet = [t.get_positions() for t in traj_verlet[:3]] md_kwargs.update({'temperature_K': T_high}) for MDalgo in [Langevin, Andersen]: a_md, traj = prepare_md(a, calculator) if MDalgo is Langevin: md = MDalgo(a_md, friction=0.0, rng=rng, **md_kwargs) elif MDalgo is Andersen: md = MDalgo(a_md, andersen_prob=0.0, rng=rng, **md_kwargs) md.attach(traj, 100) md.run(steps=200) traj_md = read('Au7Ag.traj', index=':') pos_md = [t.get_positions() for t in traj_md[:3]] assert np.allclose(pos_verlet, pos_md) # Verlet reproduced? # test thermalization to target temperature by thermostats and # conservation of average temperature by thermostats md.set_timestep(4 * fs) if MDalgo is Langevin: md.set_friction(0.01) elif MDalgo is Andersen: md.set_andersen_prob(0.01) thermalize(T_low, a_md, rng) # thermalize with low temperature (T) assert abs(a_md.get_temperature() - T_low) < 0.0001 md.run(steps=500) # equilibration, i.e. thermalization to high T temp = [] def recorder(): temp.append(a_md.get_temperature()) md.attach(recorder, interval=1) md.run(7000) temp = np.array(temp) avgtemp = np.mean(temp) fluct = np.std(temp) print("Temperature is {:.2f} K +/- {:.2f} K".format( avgtemp, fluct)) assert abs(avgtemp - T_high) < 10.0
def allraise(): with seterr(all='raise'): yield
df = DielectricFunction('gsresponse.gpw', eta=25e-3, pbc=pbc, domega0=0.01, integrationmode='tetrahedron integration') df1tetra, df2tetra = df.get_dielectric_function(q_c=[0, 0, 0]) df = DielectricFunction('gsresponse.gpw', domega0=0.01, eta=25e-3) df1, df2 = df.get_dielectric_function(q_c=[0, 0, 0]) omega_w = df.get_frequencies() if world.rank == 0: plt.figure(figsize=(6, 6)) plt.plot(omega_w, df2.imag * 2, label='Point sampling') plt.plot(omega_w, df2tetra.imag * 2, label='Tetrahedron') # Analytical result for graphene sigmainter = 1 / 4. # The surface conductivity of graphene with seterr(divide='ignore', invalid='ignore'): dfanalytic = 1 + (4 * np.pi * 1j / (omega_w / Hartree) * sigmainter / (c / Bohr)) plt.plot(omega_w, dfanalytic.imag, label='Analytic') plt.xlabel('Frequency (eV)') plt.ylabel('$\\mathrm{Im}\\varepsilon$') plt.xlim(0, 6) plt.ylim(0, 50) plt.legend() plt.tight_layout() plt.savefig('graphene_eps.png', dpi=600)
from ase import Atoms from ase.units import fs, kB from ase.calculators.test import TestPotential from ase.md import Langevin from ase.io import Trajectory, read from ase.optimize import QuasiNewton from ase.utils import seterr with seterr(all='raise'): a = Atoms('4X', masses=[1, 2, 3, 4], positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0.1, 0.2, 0.7)], calculator=TestPotential()) print(a.get_forces()) # Langevin should reproduce Verlet if friction is 0. md = Langevin(a, 0.5 * fs, 300 * kB, 0.0, logfile='-', loginterval=500) traj = Trajectory('4N.traj', 'w', a) md.attach(traj, 100) e0 = a.get_total_energy() md.run(steps=10000) del traj assert abs(read('4N.traj').get_total_energy() - e0) < 0.0001 # Try again with nonzero friction. md = Langevin(a, 0.5 * fs, 300 * kB, 0.001, logfile='-', loginterval=500) traj = Trajectory('4NA.traj', 'w', a) md.attach(traj, 100) md.run(steps=10000)
def test_langevin(): with seterr(all='raise'): run()
def calculate(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg, tau_sg, dedtau_sg): ns = len(n_sg) n_sg[n_sg < 1e-6] = 1e-6 if n_sg.ndim == 4: if not self.fixedc: if self.c is None: # We don't have the integral yet - just use 1.0: self.c = 1.0 else: self.I = self.world.sum(self.I) self.c = (self.alpha + self.beta * (self.I / self.gd.volume)**0.5) # Start calculation of c for use in the next SCF step: if ns == 1: gradn_g = sigma_xg[0]**0.5 else: gradn_g = (sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2])**0.5 self.I = self.gd.integrate(gradn_g / n_sg.sum(0)) # The domain is not distributed like the PAW corrections: self.I /= self.world.size lapl_sg = self.gd.empty(ns) for n_g, lapl_g in zip(n_sg, lapl_sg): self.lapl.apply(n_g, lapl_g) else: rgd = self.rgd lapl_sg = [] for n_Lg in self.n_sLg: lapl_g = rgd.laplace(np.dot(self.Y_L, n_Lg)) l = 0 L1 = 0 while L1 < len(self.Y_L): L2 = L1 + 2 * l + 1 n_g = np.dot(self.Y_L[L1:L2], n_Lg[L1:L2]) with seterr(divide='ignore', invalid='ignore'): lapl_g -= l * (l + 1) * n_g / rgd.r_g**2 lapl_g[0] = 0.0 L1 = L2 l += 1 lapl_sg.append(lapl_g) if not self.fixedc: # PAW corrections to integral: w = self.sign * weight_n[self.n] if ns == 1: gradn_g = sigma_xg[0]**0.5 else: gradn_g = (sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2])**0.5 self.I += w * rgd.integrate(gradn_g / n_sg.sum(0)) self.n += 1 if self.n == len(weight_n): self.n = 0 self.sign = -self.sign # dedn_sg[:] = 0.0 sigma_xg[sigma_xg < 1e-10] = 1e-10 tau_sg[tau_sg < 1e-10] = 1e-10 for n_g, sigma_g, lapl_g, tau_g, v_g in zip(n_sg, sigma_xg[::2], lapl_sg, tau_sg, dedn_sg): self.tb09(self.c, n_g.ravel(), sigma_g, lapl_g, tau_g, v_g, dedsigma_xg) self.ldac.calculate(e_g, n_sg, dedn_sg) e_g[:] = 0.0 dedsigma_xg[:] = 0.0 dedtau_sg[:] = 0.0
from ase import Atoms from ase.units import fs from ase.calculators.test import TestPotential from ase.md import VelocityVerlet from ase.io import Trajectory, read from ase.optimize import QuasiNewton from ase.utils import seterr with seterr(all='raise'): a = Atoms('4X', masses=[1, 2, 3, 4], positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0.1, 0.2, 0.7)], calculator=TestPotential()) print(a.get_forces()) md = VelocityVerlet(a, timestep=0.5 * fs, logfile='-', loginterval=500) traj = Trajectory('4N.traj', 'w', a) md.attach(traj.write, 100) e0 = a.get_total_energy() md.run(steps=10000) del traj assert abs(read('4N.traj').get_total_energy() - e0) < 0.0001 qn = QuasiNewton(a) qn.run(0.001) assert abs(a.get_potential_energy() - 1.0) < 0.000002
def test_minkowski(): with seterr(all='raise'): run()