def run_md(fdata, atoms): from ase import units from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md import VelocityVerlet fdata = fdata[:-7] traj = ase.io.Trajectory(fdata + ".traj", 'w') calc = Amp.load("amp.amp") atoms.set_calculator(calc) atoms.get_potential_energy() MaxwellBoltzmannDistribution(atoms, 100. * units.kB) #Boltzmann constant eV/K traj.write(atoms) dyn = VelocityVerlet(atoms, dt=1. * units.fs) for step in range(200): pot = atoms.get_potential_energy() # kin = atoms.get_kinetic_energy() with open(fdata + '.txt', 'a') as f: f.write("{}: Total Energy={}, POT={}, KIN={}\n".format( step, pot + kin, pot, kin)) dyn.run(5) ase.io.write(fdata + '.xyz', ase.io.read(fdata + '.traj'), append=True) traj.write(atoms)
def run_md(atoms): from ase import units from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md import VelocityVerlet traj = ase.io.Trajectory("traj.traj", 'w') calc = Amp.load("amp.amp") atoms.set_calculator(calc) atoms.get_potential_energy() MaxwellBoltzmannDistribution(atoms, 10. * units.kB) traj.write(atoms) dyn = VelocityVerlet(atoms, dt=1. * units.fs) f = open("md.ene", "w") f.write("{:^5s}{:^10s}{:^10s}{:^10s}\n".format("time", "Etot", "Epot", "Ekin")) for step in range(100): pot = atoms.get_potential_energy() # kin = atoms.get_kinetic_energy() tot = pot + kin f.write("{:5d}{:10.5f}{:10.5f}{:10.5f}\n".format(step, tot, pot, kin)) print("{}: Total Energy={}, POT={}, KIN={}".format( step, tot, pot, kin)) dyn.run(10) traj.write(atoms) f.close()
def test_idealgas(): from ase.md import VelocityVerlet from ase.build import bulk from ase.units import kB from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.calculators.idealgas import IdealGas import numpy as np atoms = bulk('Kr').repeat((10, 10, 10)) assert len(atoms) == 1000 atoms.center(vacuum=100) atoms.set_calculator(IdealGas()) T = 1000 MaxwellBoltzmannDistribution(atoms, T * kB) print("Temperature: {} K".format(atoms.get_temperature())) md = VelocityVerlet(atoms, timestep=0.1) for i in range(5): md.run(5) s = atoms.get_stress(include_ideal_gas=True) p = -s[:3].sum() / 3 v = atoms.get_volume() N = len(atoms) T = atoms.get_temperature() print("pV = {} NkT = {}".format(p * v, N * kB * T)) assert np.fabs(p * v - N * kB * T) < 1e-6
def test_idealgas(): rng = np.random.RandomState(17) atoms = bulk('Kr').repeat((10, 10, 10)) assert len(atoms) == 1000 atoms.center(vacuum=100) atoms.calc = IdealGas() natoms = len(atoms) md_temp = 1000 MaxwellBoltzmannDistribution(atoms, md_temp * kB, rng=rng) print("Temperature: {} K".format(atoms.get_temperature())) md = VelocityVerlet(atoms, timestep=0.1) for i in range(5): md.run(5) stress = atoms.get_stress(include_ideal_gas=True) stresses = atoms.get_stresses(include_ideal_gas=True) assert stresses.mean(0) == pytest.approx(stress) pressure = -stress[:3].sum() / 3 pV = pressure * atoms.cell.volume NkT = natoms * kB * atoms.get_temperature() print(f"pV = {pV} NkT = {NkT}") assert pV == pytest.approx(NkT, abs=1e-6)
def TestEnergyConservation(): print "Running TestEnergyConservation..." calc = Morse(elements, epsilon, alpha, rmin) atoms = SimpleCubic('Ar', size=(10,10,10), latticeconstant=5.0) n = 0 while n < 100: i = np.random.randint(len(atoms)-1) if atoms[i].number != atomic_numbers['Ru']: atoms[i].number = atomic_numbers['Ru'] n += 1 atoms.set_calculator(calc) # Set initial momentum MaxwellBoltzmannDistribution(atoms, 300*units.kB) # Run dynamics dyn = VelocityVerlet(atoms, 1.0 * units.fs, logfile='test-energy.dat', loginterval=10) dyn.run(10) etot = (atoms.get_potential_energy() + atoms.get_kinetic_energy())/len(atoms) print "%-9s %-9s %-9s" % ("Epot", "Ekin", "Sum") for i in range(25): if i: dyn.run(100) epot = atoms.get_potential_energy()/len(atoms) ekin = atoms.get_kinetic_energy()/len(atoms) print "%9.5f %9.5f %9.5f" % (epot, ekin, epot+ekin) ReportTest("Step %i." % (i,), epot+ekin, etot, 1e-3, silent=True)
def amp_md(atoms, nstep, dt): from ase import units from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md import VelocityVerlet traj = ase.io.Trajectory("traj.traj", 'w') try: calc = Amp.load("amp.amp") except FileNotFoundError: try: calc = Amp.load("amp-untrained-parameters.amp") except FileNotFoundError: print("Error: amp-pes.amp file does not exist, input amp-pot file by -p") sys.exit(1) atoms.set_calculator(calc) atoms.get_potential_energy() MaxwellBoltzmannDistribution(atoms, 300 * units.kB) traj.write(atoms) dyn = VelocityVerlet(atoms, dt=dt * units.fs) f = open("md.ene", "w") f.write("{:^5s} {:^10s} {:^10s} {:^10s}\n".format("time","Etot","Epot","Ekin")) for step in range(nstep): pot = atoms.get_potential_energy() # kin = atoms.get_kinetic_energy() tot = pot + kin f.write("{:5d}{:10.5f}{:10.5f}{:10.5f}\n".format(step, tot, pot, kin)) print("{}: Total Energy={}, POT={}, KIN={}".format(step, tot, pot, kin)) dyn.run(2) traj.write(atoms) # write kinetic energy, but pot is not seen in ase f.close()
def run(self, calc, filename): slab = self.starting_geometry.copy() slab.set_calculator(calc) np.random.seed(1) MaxwellBoltzmannDistribution(slab, self.temp * units.kB) if self.ensemble == "NVE": dyn = VelocityVerlet(slab, self.dt * units.fs) elif self.ensemble == "nvtberendsen": dyn = nvtberendsen.NVTBerendsen(slab, self.dt * units.fs, self.temp, taut=300 * units.fs) elif self.ensemble == "langevin": dyn = Langevin(slab, self.dt * units.fs, self.temp * units.kB, 0.002) traj = ase.io.Trajectory(filename + ".traj", "w", slab) dyn.attach(traj.write, interval=1) try: fixed_atoms = len(slab.constraints[0].get_indices()) except: fixed_atoms = 0 pass def printenergy(a=slab): """Function to print( the potential, kinetic, and total energy)""" epot = a.get_potential_energy() / len(a) ekin = a.get_kinetic_energy() / (len(a) - fixed_atoms) print("Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) " "Etot = %.3feV" % (epot, ekin, ekin / (1.5 * units.kB), epot + ekin)) if printenergy: dyn.attach(printenergy, interval=10) dyn.run(self.count)
def test_nve_against_ase(self): from ase.build import bulk ase_atoms = bulk("Ar", cubic=True) * [8, 8, 8] ase_atoms.calc = aLJ( epsilon=self.epsilon, sigma=self.sigma, rc=self.rc, ro=self.ro, smooth=True ) ase_dyn = VelocityVerlet(ase_atoms, timestep=self.dt) asax_atoms = bulk("Ar", cubic=True) * [8, 8, 8] asax_atoms.calc = jLJ( epsilon=self.epsilon, sigma=self.sigma, rc=self.rc, ro=self.ro, x64=True ) asax_dyn = VelocityVerlet(asax_atoms, timestep=self.dt) for i in range(10): ase_dyn.run(steps=1) asax_dyn.run(steps=1) self.assertAllClose( ase_atoms.get_positions(wrap=True), asax_atoms.get_positions(wrap=True), atol=1e-8, equal_nan=False, )
def microcanonical(atoms, dt=1.0, steps=100, output=1, name=None, verbose=False): """ Perform little microcanonical simulation. parameters: ----------- atoms: dt: time step in fs steps: how many md steps output: output frequency name: TrajectoryRecording name verbose: increase verbosity Return TrajectoryRecording object for further analysis. """ if name == None: try: name = atoms.get_chemical_formula(mode="hill") except: name = 'microcanonical' name += '.trj' traj = Trajectory(name, 'w', atoms) rec = TrajectoryRecording(atoms, verbose) md = VelocityVerlet(atoms, dt * fs) md.attach(rec, interval=output) md.attach(traj.write, interval=output) md.run(steps) return rec
def _molecular_dynamics(self, step, N): """Performs a molecular dynamics simulation, until mdmin is exceeded. If resuming, the file number (md%05i) is expected.""" mincount = 0 energies, oldpositions = [], [] thermalized = False if not thermalized: self.MaxwellBoltzmannDistribution(N, temp=self.temperature * kB, force_temp=True) traj = io.Trajectory('md.traj', 'a', self.atoms) dyn = VelocityVerlet(self.atoms, dt=self.timestep * units.fs) log = MDLogger(dyn, self.atoms, 'md.log', header=True, stress=False, peratom=False) dyn.attach(log, interval=1) dyn.attach(traj, interval=1) os.remove('md.log') os.remove('md.traj') while mincount < self.mdmin: dyn.run(1) energies.append(self.atoms.get_potential_energy()) passedmin = self.passedminimum(energies) if passedmin: mincount += 1 oldpositions.append(self.atoms.positions.copy()) # Reset atoms to minimum point. self.atoms.positions = oldpositions[passedmin[0]]
def test(): # Generate atomic system to create test data. atoms = fcc110('Cu', (2, 2, 2), vacuum=7.) adsorbate = Atoms([Atom('H', atoms[7].position + (0., 0., 2.)), Atom('H', atoms[7].position + (0., 0., 5.))]) atoms.extend(adsorbate) atoms.set_constraint(FixAtoms(indices=[0, 2])) calc = EMT() # cheap calculator atoms.set_calculator(calc) # Run some molecular dynamics to generate data. trajectory = io.Trajectory('data.traj', 'w', atoms=atoms) MaxwellBoltzmannDistribution(atoms, temp=300. * units.kB) dynamics = VelocityVerlet(atoms, dt=1. * units.fs) dynamics.attach(trajectory) for step in range(50): dynamics.run(5) trajectory.close() # Train the calculator. train_images, test_images = randomize_images('data.traj') calc = Amp(descriptor=Behler(), regression=NeuralNetwork()) calc.train(train_images, energy_goal=0.001, force_goal=None) # Plot and test the predictions. import matplotlib matplotlib.use('Agg') from matplotlib import pyplot fig, ax = pyplot.subplots() for image in train_images: actual_energy = image.get_potential_energy() predicted_energy = calc.get_potential_energy(image) ax.plot(actual_energy, predicted_energy, 'b.') for image in test_images: actual_energy = image.get_potential_energy() predicted_energy = calc.get_potential_energy(image) ax.plot(actual_energy, predicted_energy, 'r.') ax.set_xlabel('Actual energy, eV') ax.set_ylabel('Amp energy, eV') fig.savefig('parityplot.png')
def test_forcecurve(plt): from ase.build import bulk from ase.calculators.emt import EMT from ase.utils.forcecurve import force_curve from ase.md import VelocityVerlet from ase.units import fs from ase.io import read atoms = bulk('Au', cubic=True) * (2, 1, 1) atoms.calc = EMT() atoms.rattle(stdev=0.05) md = VelocityVerlet(atoms, timestep=12.0 * fs, trajectory='tmp.traj') md.run(steps=10) images = read('tmp.traj', ':') force_curve(images)
def init_md(self, name, time_step=0.5, temp_init=300, temp_bath=None, reset=False, interval=1): """ Initialize an ase molecular dynamics trajectory. The logfile needs to be specifies, so that old trajectories are not overwritten. This functionality can be used to subsequently carry out equilibration and production. Args: name (str): Basic name of logfile and trajectory time_step (float): Time step in fs (default=0.5) temp_init (float): Initial temperature of the system in K (default is 300) temp_bath (float): Carry out Langevin NVT dynamics at the specified temperature. If set to None, NVE dynamics are performed instead (default=None) reset (bool): Whether dynamics should be restarted with new initial conditions (default=False) interval (int): Data is stored every interval steps (default=1) """ # If a previous dynamics run has been performed, don't reinitialize velocities unless explicitely requested # via restart=True if not self.dynamics or reset: self._init_velocities(temp_init=temp_init) # Set up dynamics if temp_bath is None: self.dynamics = VelocityVerlet(self.molecule, time_step * units.fs) else: self.dynamics = Langevin(self.molecule, time_step * units.fs, temp_bath * units.kB, 0.01) # Create monitors for logfile and a trajectory file logfile = os.path.join(self.working_dir, "%s.log" % name) trajfile = os.path.join(self.working_dir, "%s.traj" % name) logger = MDLogger(self.dynamics, self.molecule, logfile, stress=False, peratom=False, header=True, mode='a') trajectory = Trajectory(trajfile, 'w', self.molecule) # Attach monitors to trajectory self.dynamics.attach(logger, interval=interval) self.dynamics.attach(trajectory.write, interval=interval)
def generate_data(count, filename, temp, hook, cons_t=False): """Generates test or training data with a simple MD simulation.""" traj = ase.io.Trajectory(filename, "w") slab = fcc100("Cu", size=(3, 3, 3)) ads = molecule("CO") add_adsorbate(slab, ads, 5, offset=(1, 1)) cons = FixAtoms(indices=[ atom.index for atom in slab if (atom.tag == 2 or atom.tag == 3) ]) if hook: cons2 = Hookean(a1=28, a2=27, rt=1.58, k=10.0) slab.set_constraint([cons, cons2]) else: slab.set_constraint(cons) slab.center(vacuum=13., axis=2) slab.set_pbc(True) slab.wrap(pbc=[True] * 3) slab.set_calculator(EMT()) slab.get_forces() dyn = QuasiNewton(slab) dyn.run(fmax=0.05) traj.write(slab) if cons_t is True: dyn = Langevin(slab, 1.0 * units.fs, temp * units.kB, 0.002) else: dyn = VelocityVerlet(slab, dt=1.0 * units.fs) for step in range(count): dyn.run(20) traj.write(slab)
def generate_data(count, filename='training.traj'): """Generates test or training data with a simple MD simulation.""" if os.path.exists(filename): return traj = ase.io.Trajectory(filename, 'w') atoms = fcc110('Pt', (2, 2, 2), vacuum=7.) atoms.extend(Atoms([Atom('Cu', atoms[7].position + (0., 0., 2.5)), Atom('Cu', atoms[7].position + (0., 0., 5.))])) atoms.set_constraint(FixAtoms(indices=[0, 2])) atoms.set_calculator(EMT()) atoms.get_potential_energy() traj.write(atoms) MaxwellBoltzmannDistribution(atoms, 300. * units.kB) dyn = VelocityVerlet(atoms, dt=1. * units.fs) for step in range(count - 1): dyn.run(50) traj.write(atoms)
def canonical(atoms,dt=1.0,steps=1000,output=10,name=None,verbose=False): """ Perform little canonical simulation. parameters: ----------- atoms: atoms with calculator attached dt: time step in fs steps: how many md steps output: output frequency name: TrajectoryRecording name verbose: increase verbosity """ if name==None: try: name=atoms.get_chemical_formula(mode="hill") except: name='microcanonical' name+='.trj' traj=PickleTrajectory(name,'w',atoms) rec=TrajectoryRecording(atoms,verbose) md=VelocityVerlet(atoms,dt*fs) md.attach(rec,interval=output) md.attach(traj.write,interval=output) md.run(steps) return rec
def test_forcecurve(testdir, plt): atoms = bulk('Au', cubic=True) * (2, 1, 1) atoms.calc = EMT() atoms.rattle(stdev=0.05) with VelocityVerlet(atoms, timestep=12.0 * fs, trajectory='tmp.traj') as md: md.run(steps=10) images = read('tmp.traj', ':') force_curve(images)
def _molecular_dynamics(self, resume=None): """Performs a molecular dynamics simulation, until mdmin is exceeded. If resuming, the file number (md%05i) is expected.""" self._log('msg', 'Molecular dynamics: md%05i' % self._counter) mincount = 0 energies, oldpositions = [], [] thermalized = False if resume: self._log('msg', 'Resuming MD from md%05i.traj' % resume) if os.path.getsize('md%05i.traj' % resume) == 0: self._log( 'msg', 'md%05i.traj is empty. Resuming from ' 'qn%05i.traj.' % (resume, resume - 1)) atoms = io.read('qn%05i.traj' % (resume - 1), index=-1) else: with io.Trajectory('md%05i.traj' % resume, 'r') as images: for atoms in images: energies.append(atoms.get_potential_energy()) oldpositions.append(atoms.positions.copy()) passedmin = self._passedminimum(energies) if passedmin: mincount += 1 self._atoms.set_momenta(atoms.get_momenta()) thermalized = True self._atoms.positions = atoms.get_positions() self._log('msg', 'Starting MD with %i existing energies.' % len(energies)) if not thermalized: MaxwellBoltzmannDistribution(self._atoms, temperature_K=self._temperature, force_temp=True) traj = io.Trajectory('md%05i.traj' % self._counter, 'a', self._atoms) dyn = VelocityVerlet(self._atoms, timestep=self._timestep * units.fs) log = MDLogger(dyn, self._atoms, 'md%05i.log' % self._counter, header=True, stress=False, peratom=False) with traj, dyn, log: dyn.attach(log, interval=1) dyn.attach(traj, interval=1) while mincount < self._mdmin: dyn.run(1) energies.append(self._atoms.get_potential_energy()) passedmin = self._passedminimum(energies) if passedmin: mincount += 1 oldpositions.append(self._atoms.positions.copy()) # Reset atoms to minimum point. self._atoms.positions = oldpositions[passedmin[0]]
def run_md(atoms): from ase import units from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md import VelocityVerlet traj = ase.io.Trajectory("traj.traj", 'w') calc = Amp.load("amp.amp") atoms.set_calculator(calc) atoms.get_potential_energy() MaxwellBoltzmannDistribution(atoms, 300. * units.kB) traj.write(atoms) dyn = VelocityVerlet(atoms, dt=1. * units.fs) for step in range(100): pot = atoms.get_potential_energy() # kin = atoms.get_kinetic_energy() print("{}: Total Energy={}, POT={}, KIN={}".format( step, pot + kin, pot, kin)) dyn.run(10) traj.write(atoms)
def generate_data(count): """Generates test or training data with a simple MD simulation.""" atoms = fcc110('Pt', (2, 2, 2), vacuum=7.) adsorbate = Atoms([Atom('Cu', atoms[7].position + (0., 0., 2.5)), Atom('Cu', atoms[7].position + (0., 0., 5.))]) atoms.extend(adsorbate) atoms.set_constraint(FixAtoms(indices=[0, 2])) atoms.set_calculator(EMT()) MaxwellBoltzmannDistribution(atoms, 300. * units.kB) dyn = VelocityVerlet(atoms, dt=1. * units.fs) newatoms = atoms.copy() newatoms.set_calculator(EMT()) newatoms.get_potential_energy() images = [newatoms] for step in range(count - 1): dyn.run(50) newatoms = atoms.copy() newatoms.set_calculator(EMT()) newatoms.get_potential_energy() images.append(newatoms) return images
def generate_data(count): """Generates test or training data with a simple MD simulation.""" atoms = fcc110('Pt', (2, 2, 1), vacuum=7.) adsorbate = Atoms([Atom('Cu', atoms[3].position + (0., 0., 2.5)), Atom('Cu', atoms[3].position + (0., 0., 5.))]) atoms.extend(adsorbate) atoms.set_constraint(FixAtoms(indices=[0, 2])) atoms.set_calculator(EMT()) MaxwellBoltzmannDistribution(atoms, 300. * units.kB) dyn = VelocityVerlet(atoms, dt=1. * units.fs) newatoms = atoms.copy() newatoms.set_calculator(EMT()) newatoms.get_potential_energy() images = [newatoms] for step in range(count - 1): dyn.run(50) newatoms = atoms.copy() newatoms.set_calculator(EMT()) newatoms.get_potential_energy() images.append(newatoms) return images
def create_system(self, name, time_step=1.0, temp=300, temp_init=None, restart=False, store=1, nvt=False, friction=0.001): """ Parameters ----------- name : str Name for output files. time_step : float, optional Time step in fs for simulation. temp : float, optional Temperature in K for NVT simulation. temp_init : float, optional Optional different temperature for initialization than thermostate set at. restart : bool, optional Determines whether simulation is restarted or not, determines whether new velocities are initialized. store : int, optional Frequency at which output is written to log files. nvt : bool, optional Determines whether to run NVT simulation, default is False. friction : float, optional friction coefficient in fs^-1 for Langevin integrator """ if temp_init is None: temp_init = temp if not self.md or restart: MaxwellBoltzmannDistribution(self.mol, temp_init * units.kB) if not nvt: self.md = VelocityVerlet(self.mol, time_step * units.fs) else: self.md = Langevin(self.mol, time_step * units.fs, temp * units.kB, friction / units.fs) logfile = os.path.join(self.tmp, "{}.log".format(name)) trajfile = os.path.join(self.tmp, "{}.traj".format(name)) logger = MDLogger(self.md, self.mol, logfile, stress=False, peratom=False, header=True, mode="a") trajectory = Trajectory(trajfile, "w", self.mol) self.md.attach(logger, interval=store) self.md.attach(trajectory.write, interval=store)
def check_energy_conservation(atoms, dt=1.0 * fs, steps=200, tol=0.01, plot=False): """ For given initial atoms, check the energy conservation with NVE simulation. @param atoms: ase atoms instance @param dt: time step @param steps: number of time steps used in the check @param plot: use maplotlib to plot the etot,epot -graph Energy is conserved if fluctuation of total energy is tolerance times the fluctuation of potential energy. """ dyn = VelocityVerlet(atoms, dt=dt) epot = [] ekin = [] for i in range(steps): dyn.run(1) epot.append(atoms.get_potential_energy()) ekin.append(atoms.get_kinetic_energy()) epot = np.array(epot) ekin = np.array(ekin) etot = epot + ekin depot = np.sqrt(np.var(epot)) detot = np.sqrt(np.var(etot)) if plot: import pylab as pl pl.plot(epot, label='epot') pl.plot(etot, label='etot') pl.legend() pl.xlabel('time step') pl.ylabel('energy (eV)') pl.show() if detot < tol * depot: return True else: return False
def TestEnergyConservation(): print "Running TestEnergyConservation..." calc = Morse(elements, epsilon, alpha, rmin) atoms = SimpleCubic('Ar', size=(10, 10, 10), latticeconstant=5.0) n = 0 while n < 100: i = np.random.randint(len(atoms) - 1) if atoms[i].number != atomic_numbers['Ru']: atoms[i].number = atomic_numbers['Ru'] n += 1 atoms.set_calculator(calc) # Set initial momentum MaxwellBoltzmannDistribution(atoms, 300 * units.kB) # Run dynamics dyn = VelocityVerlet(atoms, 1.0 * units.fs, logfile='test-energy.dat', loginterval=10) dyn.run(10) etot = (atoms.get_potential_energy() + atoms.get_kinetic_energy()) / len(atoms) print "%-9s %-9s %-9s" % ("Epot", "Ekin", "Sum") for i in range(25): if i: dyn.run(100) epot = atoms.get_potential_energy() / len(atoms) ekin = atoms.get_kinetic_energy() / len(atoms) print "%9.5f %9.5f %9.5f" % (epot, ekin, epot + ekin) ReportTest("Step %i." % (i, ), epot + ekin, etot, 1e-3, silent=True)
def generate_training_set(individual, db_name): """ Do MD using EMT calculator with each slab for 10 steps and add it to train.db """ db = connect(db_name) for miller_indices in individual: # Do MD slab = generate_slab(miller_indices, 5) slab = make_supercell(slab, P=[[3, 1, 1], [1, 3, 1], [1, 1, 1]]) slab.set_calculator(EMT()) slab.get_potential_energy() db.write(slab) MaxwellBoltzmannDistribution(slab, 300. * units.kB) dyn = VelocityVerlet(slab, dt=1. * units.fs) for i in range(1, 10): dyn.run(10) db.write(slab)
def check_energy_conservation(atoms,dt=1.0*fs,steps=200,tol=0.01,plot=False): """ For given initial atoms, check the energy conservation with NVE simulation. @param atoms: ase atoms instance @param dt: time step @param steps: number of time steps used in the check @param plot: use maplotlib to plot the etot,epot -graph Energy is conserved if fluctuation of total energy is tolerance times the fluctuation of potential energy. """ dyn = VelocityVerlet(atoms,dt=dt) epot = [] ekin = [] for i in range(steps): dyn.run(1) epot.append( atoms.get_potential_energy() ) ekin.append( atoms.get_kinetic_energy() ) epot = np.array(epot) ekin = np.array(ekin) etot = epot + ekin depot = np.sqrt( np.var(epot) ) detot = np.sqrt( np.var(etot) ) if plot: import pylab as pl pl.plot(epot,label='epot') pl.plot(etot,label='etot') pl.legend() pl.xlabel('time step') pl.ylabel('energy (eV)') pl.show() if detot < tol*depot: return True else: return False
def _molecular_dynamics(self, resume=None): """Performs a molecular dynamics simulation, until mdmin is exceeded. If resuming, the file number (md%05i) is expected.""" self._log('msg', 'Molecular dynamics: md%05i' % self._counter) mincount = 0 energies, oldpositions = [], [] thermalized = False if resume: self._log('msg', 'Resuming MD from md%05i.traj' % resume) if os.path.getsize('md%05i.traj' % resume) == 0: self._log('msg', 'md%05i.traj is empty. Resuming from ' 'qn%05i.traj.' % (resume, resume - 1)) atoms = io.read('qn%05i.traj' % (resume - 1), index=-1) else: images = io.PickleTrajectory('md%05i.traj' % resume, 'r') for atoms in images: energies.append(atoms.get_potential_energy()) oldpositions.append(atoms.positions.copy()) passedmin = self._passedminimum(energies) if passedmin: mincount += 1 self._atoms.set_momenta(atoms.get_momenta()) thermalized = True self._atoms.positions = atoms.get_positions() self._log('msg', 'Starting MD with %i existing energies.' % len(energies)) if not thermalized: MaxwellBoltzmannDistribution(self._atoms, temp=self._temperature * units.kB, force_temp=True) traj = io.PickleTrajectory('md%05i.traj' % self._counter, 'a', self._atoms) dyn = VelocityVerlet(self._atoms, dt=self._timestep * units.fs) log = MDLogger(dyn, self._atoms, 'md%05i.log' % self._counter, header=True, stress=False, peratom=False) dyn.attach(log, interval=1) dyn.attach(traj, interval=1) while mincount < self._mdmin: dyn.run(1) energies.append(self._atoms.get_potential_energy()) passedmin = self._passedminimum(energies) if passedmin: mincount += 1 oldpositions.append(self._atoms.positions.copy()) # Reset atoms to minimum point. self._atoms.positions = oldpositions[passedmin[0]]
def md_run(images, count, calc, filename, dir, temp, cons_t=False): """Generates test or training data with a simple MD simulation.""" log = Logger("results/logs/" + filename + ".txt") traj = ase.io.Trajectory("".join([dir, filename, ".traj"]), "w") slab = images[0].copy() slab.set_calculator(calc) slab.get_forces() traj.write(slab) if cons_t is True: dyn = Langevin(slab, 1.0 * units.fs, temp * units.kB, 0.002) else: dyn = VelocityVerlet(slab, dt=1.0 * units.fs) time_start = time.time() for step in range(count): dyn.run(20) traj.write(slab) time_elapsed = time.time() - time_start log("MD Simulation Dynamics: %s" % dyn) log("MD Simulation Time: %s \n" % time_elapsed)
def generate_data(count, filename, temp, hook, cons_t=False): """Generates test or training data with a simple MD simulation.""" traj = ase.io.Trajectory(filename, "w") pair = molecule("CO") cons = Hookean(a1=0, a2=1, rt=1.58, k=10.0) # pair.set_constraint(cons) pair.set_calculator(EMT()) pair.get_potential_energy() dyn = QuasiNewton(pair, trajectory=(filename[:-5] + "_relax.traj")) dyn.run(fmax=0.05) traj.write(pair) MaxwellBoltzmannDistribution(pair, temp * units.kB) if cons_t is True: dyn = Langevin(pair, 5 * units.fs, temp * units.kB, 0.002) else: dyn = VelocityVerlet(pair, dt=1.0 * units.fs) for step in range(count - 1): dyn.run(50) traj.write(pair)
def test_md(): from ase import Atoms from ase.calculators.emt import EMT from ase.md import VelocityVerlet from ase.io import Trajectory a = 3.6 b = a / 2 fcc = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1) fcc *= (2, 1, 1) fcc.set_calculator(EMT()) fcc.set_momenta([(0.9, 0.0, 0.0), (-0.9, 0, 0)]) md = VelocityVerlet(fcc, timestep=0.1) def f(): print(fcc.get_potential_energy(), fcc.get_total_energy()) md.attach(f) md.attach(Trajectory('Cu2.traj', 'w', fcc).write, interval=3) md.run(steps=20) Trajectory('Cu2.traj', 'r')[-1]
def test(): # Generate atomic system to create test data. atoms = fcc110('Cu', (2, 2, 2), vacuum=7.) adsorbate = Atoms([ Atom('H', atoms[7].position + (0., 0., 2.)), Atom('H', atoms[7].position + (0., 0., 5.)) ]) atoms.extend(adsorbate) atoms.set_constraint(FixAtoms(indices=[0, 2])) calc = EMT() # cheap calculator atoms.set_calculator(calc) # Run some molecular dynamics to generate data. trajectory = io.Trajectory('data.traj', 'w', atoms=atoms) MaxwellBoltzmannDistribution(atoms, temp=300. * units.kB) dynamics = VelocityVerlet(atoms, dt=1. * units.fs) dynamics.attach(trajectory) for step in range(50): dynamics.run(5) trajectory.close() # Train the calculator. train_images, test_images = randomize_images('data.traj') calc = Amp(descriptor=Behler(), regression=NeuralNetwork()) calc.train(train_images, energy_goal=0.001, force_goal=None) # Plot and test the predictions. import matplotlib matplotlib.use('Agg') from matplotlib import pyplot fig, ax = pyplot.subplots() for image in train_images: actual_energy = image.get_potential_energy() predicted_energy = calc.get_potential_energy(image) ax.plot(actual_energy, predicted_energy, 'b.') for image in test_images: actual_energy = image.get_potential_energy() predicted_energy = calc.get_potential_energy(image) ax.plot(actual_energy, predicted_energy, 'r.') ax.set_xlabel('Actual energy, eV') ax.set_ylabel('Amp energy, eV') fig.savefig('parityplot.png')
def test_md(): a = 3.6 b = a / 2 fcc = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1) fcc *= (2, 1, 1) fcc.calc = EMT() fcc.set_momenta([(0.9, 0.0, 0.0), (-0.9, 0, 0)]) def f(): print(fcc.get_potential_energy(), fcc.get_total_energy()) with VelocityVerlet(fcc, timestep=0.1) as md: md.attach(f) with Trajectory('Cu2.traj', 'w', fcc) as traj: md.attach(traj.write, interval=3) md.run(steps=20) with Trajectory('Cu2.traj', 'r') as traj: traj[-1]
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
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
from ase import Atoms from ase.calculators.emt import EMT from ase.md import VelocityVerlet from ase.io import Trajectory a = 3.6 b = a / 2 fcc = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1) fcc *= (2, 1, 1) fcc.set_calculator(EMT()) fcc.set_momenta([(0.9, 0.0, 0.0), (-0.9, 0, 0)]) md = VelocityVerlet(fcc, dt=0.1) def f(): print(fcc.get_potential_energy(), fcc.get_total_energy()) md.attach(f) md.attach(Trajectory('Cu2.traj', 'w', fcc).write, interval=3) md.run(steps=20) fcc2 = Trajectory('Cu2.traj', 'r')[-1]
def test_hookean(): """ Test of Hookean constraint. Checks for activity in keeping a bond, preventing vaporization, and that energy is conserved in NVE dynamics. """ import numpy as np from ase import Atoms, Atom from ase.build import fcc110 from ase.calculators.emt import EMT from ase.constraints import FixAtoms, Hookean from ase.md import VelocityVerlet from ase import units class SaveEnergy: """Class to save energy.""" def __init__(self, atoms): self.atoms = atoms self.energies = [] def __call__(self): self.energies.append(atoms.get_total_energy()) # Make Pt 110 slab with Cu2 adsorbate. atoms = fcc110('Pt', (2, 2, 2), vacuum=7.) adsorbate = Atoms([ Atom('Cu', atoms[7].position + (0., 0., 2.5)), Atom('Cu', atoms[7].position + (0., 0., 5.0)) ]) atoms.extend(adsorbate) calc = EMT() atoms.calc = calc # Constrain the surface to be fixed and a Hookean constraint between # the adsorbate atoms. constraints = [ FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Pt']), Hookean(a1=8, a2=9, rt=2.6, k=15.), Hookean(a1=8, a2=(0., 0., 1., -15.), k=15.) ] atoms.set_constraint(constraints) # Give it some kinetic energy. momenta = atoms.get_momenta() momenta[9, 2] += 20. momenta[9, 1] += 2. atoms.set_momenta(momenta) # Propagate in Velocity Verlet (NVE). dyn = VelocityVerlet(atoms, timestep=1.0 * units.fs) energies = SaveEnergy(atoms) dyn.attach(energies) dyn.run(steps=100) # Test the max bond length and position. bondlength = np.linalg.norm(atoms[8].position - atoms[9].position) assert bondlength < 3.0 assert atoms[9].z < 15.0 # Test that energy was conserved. assert max(energies.energies) - min(energies.energies) < 0.01 # Make sure that index shuffle works. neworder = list(range(len(atoms))) neworder[8] = 9 # Swap two atoms. neworder[9] = 8 atoms = atoms[neworder] assert atoms.constraints[1].indices[0] == 9 assert atoms.constraints[1].indices[1] == 8 assert atoms.constraints[2].index == 9
strain_ramp_length) print('Applied initial load: delta=%.2f strain=%.4f' % (params.delta, params.delta*eps_G)) ase.io.write('crack_2.xyz', c, format='extxyz') c.set_calculator(calc) # relax initial structure #opt = FIRE(c) #opt.run(fmax=1e-3) ase.io.write('crack_3.xyz', c, format='extxyz') dyn = VelocityVerlet(c, params.dt, logfile=None) set_initial_velocities(dyn.atoms) crack_pos = [] traj = NetCDFTrajectory('traj.nc', 'w', c) dyn.attach(traj.write, 10, dyn.atoms, arrays=['stokes', 'momenta']) dyn.attach(find_crack_tip, 10, dyn.atoms, dt=params.dt*10, store=True, results=crack_pos) # run for 2000 time steps to reach steady state at initial load for i in range(20): dyn.run(100) if extend_strip(dyn.atoms, params.a, params.N, params.M, params.vacuum): set_constraints(dyn.atoms, params.a, delta_strain=None) # start decreasing strain
import numpy as np from ase import Atoms from ase.units import fs from ase.calculators.test import TestPotential from ase.calculators.emt import EMT from ase.md import VelocityVerlet from ase.io import PickleTrajectory, read from ase.optimize import QuasiNewton np.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, dt=0.5 * fs, logfile='-', loginterval=500) traj = PickleTrajectory('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
from ase.constraints import FixAtoms from ase.calculators.siesta import Siesta from ase.md import VelocityVerlet from ase import units # Read in the geometry from a xyz file, set the cell, boundary conditions and center atoms = read('geom.xyz') atoms.set_cell([7.66348,7.66348,7.66348*2]) atoms.set_pbc((1,1,1)) atoms.center() # Set initial velocities for hydrogen atoms along the z-direction p = atoms.get_momenta() p[0,2]= -1.5 p[1,2]= -1.5 atoms.set_momenta(p) # Keep some atoms fixed during the simulation atoms.set_constraint(FixAtoms(indices=range(18,38))) # Set the calculator and attach it to the system calc = Siesta('si001+h2',basis='SZ',xc='PBE',meshcutoff=50*units.Ry) calc.set_fdf('PAO.EnergyShift', 0.25 * units.eV) calc.set_fdf('PAO.SplitNorm', 0.15) atoms.set_calculator(calc) # Set the VelocityVerlet algorithm and run it dyn = VelocityVerlet(atoms,dt=1.0 * units.fs,trajectory='si001+h2.traj') dyn.run(steps=100)
calc = EMT() atoms.set_calculator(calc) # Constrain the surface to be fixed and a Hookean constraint between # the adsorbate atoms. constraints = [FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Pt']), Hookean(a1=8, a2=9, rt=2.6, k=15.), Hookean(a1=8, a2=(0., 0., 1., -15.), k=15.)] atoms.set_constraint(constraints) # Give it some kinetic energy. momenta = atoms.get_momenta() momenta[9, 2] += 20. momenta[9, 1] += 2. atoms.set_momenta(momenta) # Propagate in Velocity Verlet (NVE). dyn = VelocityVerlet(atoms, dt=1.0*units.fs) energies = SaveEnergy(atoms) dyn.attach(energies) dyn.run(steps=100) # Test the max bond length and position. bondlength = np.linalg.norm(atoms[8].position - atoms[9].position) assert bondlength < 3.0 assert atoms[9].z < 15.0 # Test that energy was conserved. assert max(energies.energies) - min(energies.energies) < 0.01