def fit_volume(self, name, atoms, data=None): N, x = self.fit cell0 = atoms.get_cell() v = atoms.get_volume() if x > 0: strains = np.linspace(1 - x, 1 + x, N) else: strains = np.linspace(1 + x / v, 1 - x / v, N)**(1./3) energies = [] traj = Trajectory(self.get_filename(name, 'fit.traj'), 'w') for s in strains: atoms.set_cell(cell0 * s, scale_atoms=True) energies.append(atoms.get_potential_energy()) traj.write(atoms) traj.close() if data is not None: data['strains'] = strains data['energies'] = energies else: assert N % 2 == 1 data = {'energy': energies[N // 2], 'strains': strains, 'energies': energies} return data
class Ensemble(Optimizer): def __init__(self, atoms, restart=None, logfile=None, trajectory=None, seed=None, verbose=False): Optimizer.__init__(self, atoms, restart, logfile, trajectory=None) atoms.get_forces() atoms.get_potential_energy() if seed is None: seed = np.random.randint(0, 2 ** 31) self.verbose = verbose self.random_state = RandomState(seed) self.starting_atoms = dc(atoms) self.pe = [] self.metadata = {'seed': seed} self.traj = [dc(atoms)] print(self.traj[0].get_momenta()) if trajectory is not None: self.trajectory = Trajectory(trajectory, mode='w') self.trajectory.write(self.traj[-1]) if self.verbose: print('Trajectory written', len(self.traj)) else: self.trajectory = None if verbose: print('trajectory file', self.trajectory) def check_eq(self, eq_steps, tol): ret = np.cumsum(self.pe, dtype=float) ret[eq_steps:] = ret[eq_steps:] - ret[:-eq_steps] ret = ret[eq_steps - 1:] / eq_steps return np.sum(np.gradient(ret[eq_steps:])) < tol def run(self, steps=100000000, eq_steps=None, eq_tol=None, **kwargs): self.metadata['planned iterations'] = steps i = 0 while i < steps: # Check if we are at equilibrium, if we want that if eq_steps is not None: if self.check_eq(eq_steps, eq_tol): break # Verboseness if self.verbose: print('iteration number', i) try: self.step() i += 1 # If we blow up, write the last structure down and exit gracefully except KeyboardInterrupt: print('Interupted, returning data') return self.traj, self.metadata if self.trajectory is not None: self.trajectory.close() return self.traj, self.metadata def step(self): pass def estimate_simulation_duration(self, atoms, iterations): pass
def eos(self, atoms, name): args = self.args traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) N, eps = args.equation_of_state.split(',') N = int(N) eps = float(eps) / 100 strains = np.linspace(1 - eps, 1 + eps, N) v1 = atoms.get_volume() volumes = strains**3 * v1 energies = [] cell1 = atoms.cell for s in strains: atoms.set_cell(cell1 * s, scale_atoms=True) energies.append(atoms.get_potential_energy()) traj.write(atoms) traj.close() eos = EquationOfState(volumes, energies, args.eos_type) v0, e0, B = eos.fit() atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True) data = {'volumes': volumes, 'energies': energies, 'fitted_energy': e0, 'fitted_volume': v0, 'bulk_modulus': B, 'eos_type': args.eos_type} return data
def eos(self, atoms, name): opts = self.opts traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) eps = 0.01 strains = np.linspace(1 - eps, 1 + eps, 5) v1 = atoms.get_volume() volumes = strains**3 * v1 energies = [] cell1 = atoms.cell for s in strains: atoms.set_cell(cell1 * s, scale_atoms=True) energies.append(atoms.get_potential_energy()) traj.write(atoms) traj.close() eos = EquationOfState(volumes, energies, opts.eos_type) v0, e0, B = eos.fit() atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True) data = {'volumes': volumes, 'energies': energies, 'fitted_energy': e0, 'fitted_volume': v0, 'bulk_modulus': B, 'eos_type': opts.eos_type} return data
def do_vasp(pos1, pos2, snimgs): nimgs = int(snimgs) ini = read(pos1) fin = read(pos2) ini.wrap() fin.wrap() traj = [ini] traj += [ini.copy() for i in range(nimgs)] traj += [fin] neb = NEB(traj) neb.interpolate('idpp') images = neb.images if not os.path.exists('00'): os.mkdir('00') if not os.path.exists(i2str(nimgs + 1)): os.mkdir(i2str(nimgs + 1)) images[0].write('00/POSCAR', vasp5=True, direct=True) images[-1].write(i2str(nimgs + 1) + '/POSCAR', vasp5=True, direct=True) for i in range(nimgs): if not os.path.exists(i2str(i + 1)): os.mkdir(i2str(i + 1)) images[i + 1].write(i2str(i + 1) + '/POSCAR', vasp5=True, direct=True) traj = Trajectory('images.tarj', 'w') for i in images: traj.write(i)
def write_trajectory(filename, ccdata, popname="mulliken", index=None): """Write an ASE Trajectory object from a ccData object. We try to write the following properties: atomcoords, atomnos, atomcharges, atomspins, atommasses, scfenergies, grads, moments (dipole only) and freeenergy. No charge or mult is written since ASE calculates them from atomcharges and atomspins. When a program do a final single point calculation at the end of an optimization (e.g., ORCA), we'll have unequal number of grads and atomcoords. This means the last geometry in the written .traj will lack forces. Some unit conversions are done here, but things are converted back in read_trajectory/makecclib. Inputs: filename - path to traj file to be written. ccdata - an instance of ccData. popname - population analysis to use for atomic partial charges and atomic spin densities. Molecular charge and multiplicity are evaluated from them. index - sequence of integers indicating which atomcoords indices should be exported. By default, all are exported. """ _check_ase(_found_ase) traj = Trajectory(filename, "w") for i, atomcoords in enumerate(ccdata.atomcoords): if index is not None and i not in index: continue atomspins = None if hasattr(ccdata, "atomspins"): atomspins = ccdata.atomspins[popname] atoms = makease( atomcoords, ccdata.atomnos, ccdata.atomcharges[popname], atomspins, ccdata.atommasses, ) properties = {} if hasattr(ccdata, "scfenergies"): properties.update({"energy": ccdata.scfenergies[i]}) if hasattr(ccdata, "grads"): try: properties.update( {"forces": -ccdata.grads[i] * units.Hartree / units.Bohr}) except IndexError: pass if i == len(ccdata.atomcoords) - 1: # last geometry if hasattr(ccdata, "moments"): properties.update({"dipole": ccdata.moments[1] * units.Bohr}) if hasattr(ccdata, "free_energy"): properties.update( {"free_energy": ccdata.freeenergy * units.Hartree}) traj.write(atoms, **properties)
def __init__(self, slab: Atoms, adsorbate: Atoms, bonds: List[Tuple[int, int]], dists: List[float], initial_height: float = 1.0, weight: float = 1.0, scale: float = 1.0, trajectory: str = None) -> None: self.slab = slab self.adsorbate = adsorbate zmax_slab = np.max(self.slab.positions[:, 2]) zmin_ads = np.min(self.adsorbate.positions[:, 2]) self.adsorbate.positions[:, 2] += initial_height + zmax_slab - zmin_ads self.ads_ref = self.slab + self.adsorbate self.bonds = bonds self.dists = dists self.weight = weight self.scale = scale self.trajectory = trajectory if self.trajectory is not None: self.trajectory = Trajectory(self.trajectory, 'w', self.ads_ref)
def eosfit_spec(atoms, calc, rg, method="birchmurnaghan"): from ase.eos import EquationOfState from numpy import linspace rootdir = os.getcwd() if not os.path.exists('eosfit'): os.mkdir('eosfit') os.chdir('eosfit') cell = atoms.get_cell() atoms.set_calculator(calc) traj = Trajectory('eosfit.traj', 'w') for x in rg: print(str(x)) atoms.set_cell(cell * x, scale_atoms=True) atoms.get_potential_energy() traj.write(atoms) configs = Trajectory('eosfit.traj', 'r') volumes = [at.get_volume() for at in configs] energies = [at.get_potential_energy() for at in configs] eos = EquationOfState(volumes, energies, eos=method) v0, e0, B = eos.fit() eos.plot('eosfit.svg') fp = open('eosdata.dat', 'w') fp.write('Volume\t\tEnergy') for i in range(len(configs)): fp.write(str(volumes[i]) + '\t' + str(energies[i]) + '\n') os.chdir(rootdir)
def __init__(self, atoms, restart=None, logfile=None, trajectory=None, seed=None, verbose=False): Optimizer.__init__(self, atoms, restart, logfile, trajectory=None) atoms.get_forces() atoms.get_potential_energy() if seed is None: seed = np.random.randint(0, 2**31) self.verbose = verbose self.random_state = RandomState(seed) self.starting_atoms = dc(atoms) self.pe = [] self.metadata = {'seed': seed} self.traj = [dc(atoms)] print(self.traj[0].get_momenta()) if trajectory is not None: self.trajectory = Trajectory(trajectory, mode='w') self.trajectory.write(self.traj[-1]) if self.verbose: print('Trajectory written', len(self.traj)) else: self.trajectory = None if verbose: print('trajectory file', self.trajectory)
def plot_energy(traj='md.traj'): images = Trajectory(traj) e,ei,ei_,diff = [],[],[],[] # ir_mpnn = IRFF(atoms=images[0], # libfile='ffield.json', # nn=True) # ir_mpnn.get_potential_energy(images[0]) #ir_reax = IRFF(atoms=images[0], # libfile='ffield', # nn=False) #ir_reax.get_potential_energy(images[0]) #atoms = read(traj,index=-1) #print(atoms.get_potential_energy()) #exit() images = Trajectory('md.traj') v = [] for i,atoms in enumerate(images): ei.append(atoms.get_potential_energy()) # ei.append(ir_mpnn.get_potential_energy(atoms)) #ei_.append(ir_reax.get_potential_energy(atoms)) #diff.append(abs(e[-1]-ei[-1])) #print(' * energy: ',e[-1],ei[-1],ei_[-1],diff[-1]) v.append(atoms.get_volume()) # stress = atoms.get_stress() # print(stress) del atoms #print(' * mean difference: ',np.mean(diff)) #e_min = min(e) #e_max = max(e) #e = np.array(e) - e_min e_min = min(ei) ei = np.array(ei) - e_min #e_min = min(ei_) #ei_ = np.array(ei_) - e_min plt.figure() plt.ylabel(r'$Total$ $Energy$ ($eV$)') plt.xlabel(r'$MD$ $Step$') # plt.xlim(0,i) # plt.ylim(0,np.max(hist)+0.01) plt.plot(ei,alpha=0.9, linestyle='-',# marker='o',markerfacecolor='k',markersize=5, color='k',label='ReaxFF-MPNN') # plt.plot(v,ei,alpha=0.9, # linestyle='-',marker='^',markerfacecolor='none', # markeredgewidth=1,markeredgecolor='blue',markersize=5, # color='blue',label='IRFF') # plt.text( 0.0, e_max, '%.3f' %e_min, fontdict={'size':10.5, 'color': 'k'}) plt.legend(loc='best',edgecolor='yellowgreen') # lower left upper right plt.savefig('Energy.pdf',transparent=True) plt.close()
def run_onlineal(cluster, parent_calc, elements, al_learner_params, config, dataset_parent, optimizer): # if len(dataset_parent) == 0: # dataset_parent = [] #images = [cluster] print('run_onlineal dataset_parent length:', len(dataset_parent)) flare_params = config ml_potential = FlarePPCalc(flare_params, [cluster]) #print("parent_calc", parent_calc) #if(type(parent_calc == EMT)): #print("True") if ((type(parent_calc) == Vasp) or (type(parent_calc == EMT))): onlinecalc = OnlineLearner( al_learner_params, dataset_parent, ml_potential, parent_calc, ) if os.path.exists("relaxing.traj"): os.remove("relaxing.traj") cluster.calc = onlinecalc dyn = optimizer(cluster, trajectory='relaxing.traj') dyn.attach(mixed_replay, 1, cluster.calc, dyn) dyn.attach(check_final_point, 1, cluster.calc, dyn) dyn.run(fmax=0.05, steps=1000) elif type(parent_calc) == VaspInteractive: with parent_calc as calc: onlinecalc = OnlineLearner( al_learner_params, dataset_parent, ml_potential, calc, ) if os.path.exists("relaxing.traj"): os.remove("relaxing.traj") cluster.calc = onlinecalc dyn = optimizer(cluster, trajectory='relaxing.traj') dyn.attach(mixed_replay, 1, cluster.calc, dyn) dyn.attach(check_final_point, 1, cluster.calc, dyn) dyn.run(fmax=0.05, steps=1000) #optim_struc = Relaxation(cluster, optimizer, fmax=0.01, steps=100) #optim_struc.run(onlinecalc, filename="relaxing") #relaxed_clus = optim_struc.get_trajectory("relaxing")[-1] relaxed_clus = Trajectory('relaxing.traj')[-1] print('al relaxed clus') print(relaxed_clus) print(relaxed_clus.get_positions()) print('\n') print('\n') return relaxed_clus, onlinecalc.parent_calls, onlinecalc.parent_dataset
def main(fname): fname_out = fname.split(".")[0] fname_out += "only_cluster.traj" traj = Trajectory(fname, mode="r") traj_clust = Trajectory(fname_out, mode="w") for i, atoms in enumerate(traj): print("{} of {}".format(i, len(traj))) cluster = extract_cluster(atoms) traj_clust.write(cluster)
def sel(traj='md.traj',m=3): newt= traj.replace('.traj','_.traj') images = Trajectory(traj) his = TrajectoryWriter(newt,mode='w') images = Trajectory(traj) for i,atoms in enumerate(images): if i%m==0: his.write(atoms=atoms) his.close()
def plot_gga(ax, ax1): def murnaghan(V, E0, B0, BP, V0): 'From PRB 28,5480 (1983' E = E0 + B0 * V / BP * \ (((V0 / V)**BP) / (BP - 1) + 1) - V0 * B0 / (BP - 1) return E traj = Trajectory('nagao2-r3m-gga.traj') v = [i.get_volume() for i in traj] e1 = np.array([i.get_total_energy() * Rydberg for i in traj]) eos_data = eos(v, e1, eos='murnaghan') eos_data.fit() V = np.linspace(35, 54, 100) E = murnaghan(V, eos_data.eos_parameters[0], eos_data.eos_parameters[1], eos_data.eos_parameters[2], eos_data.eos_parameters[3]) r3m_e = E r3m_v = V traj = Trajectory('nagao2-p2n1_gga.traj') v = [i.get_volume()*0.25 for i in traj] e1 = np.array([i.get_total_energy() * Rydberg*0.25 for i in traj]) eos_data = eos(v, e1, eos='murnaghan') eos_data.fit() V = np.linspace(45, 65, 100) E = murnaghan(V, eos_data.eos_parameters[0], eos_data.eos_parameters[1], eos_data.eos_parameters[2], eos_data.eos_parameters[3]) p2n1_e = E p2n1_v = V minimum = np.min([r3m_e, p2n1_e]) c = "k" label = "R$\\bar{3}$m" ax.plot(r3m_v, r3m_e-minimum, c=c, label=label) c = "r" label = "Pna$2_1$" ax.plot(p2n1_v, p2n1_e-minimum, c=c, label=label) ax.legend() c = "k" label = "R$\\bar{3}$m" p = -1*np.gradient(r3m_e, np.diff(r3m_v)[0]) h = r3m_e-p*r3m_v h1 = h p1 = p ax1.plot(p, h, c=c, label=label) c = "r" label = "Pna$2_1$" p = -1*np.gradient(p2n1_e, np.diff(p2n1_v)[0]) h = p2n1_e-p*p2n1_v h2 = h p2 = p ax1.plot(p, h, c=c, label=label) ax1.legend() return h1, h2, p1, p2
def sortraj(traj='siesta.traj'): newt = traj[:-5] + '_.traj' images = Trajectory(traj) his = TrajectoryWriter(newt, mode='w') images = Trajectory(traj) for i in range(50): atoms = images[i] his.write(atoms=atoms) his.close()
def col(traj='siesta.traj', start=0, end=20): newt = traj.replace('.traj', '_.traj') images = Trajectory(traj) his = TrajectoryWriter(newt, mode='w') images = Trajectory(traj) for i in range(start, end): atoms = images[i] his.write(atoms=atoms) his.close()
def ase_md_playground(): geom = AnaPot.get_geom((0.52, 1.80, 0), atoms=("H", )) atoms = geom.as_ase_atoms() # ase_calc = FakeASE(geom.calculator) # from ase.optimize import BFGS # dyn = BFGS(atoms) # dyn.run(fmax=0.05) import ase from ase import units from ase.io.trajectory import Trajectory from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md.verlet import VelocityVerlet MaxwellBoltzmannDistribution(atoms, 300 * units.kB) momenta = atoms.get_momenta() momenta[0, 2] = 0. # Zero 3rd dimension atoms.set_momenta(momenta) dyn = VelocityVerlet(atoms, .005 * units.fs) # 5 fs time step. def printenergy(a): """Function to print the potential, kinetic and total energy""" epot = a.get_potential_energy() / len(a) ekin = a.get_kinetic_energy() / len(a) print('Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) ' 'Etot = %.3feV' % (epot, ekin, ekin / (1.5 * units.kB), epot + ekin)) # Now run the dynamics printenergy(atoms) traj_fn = 'asemd.traj' traj = Trajectory(traj_fn, 'w', atoms) dyn.attach(traj.write, interval=5) # dyn.attach(bumms().bimms, interval=1) dyn.run(10000) printenergy(atoms) traj.close() traj = ase.io.read(traj_fn+"@:")#, "r") pos = [a.get_positions() for a in traj] from pysisyphus.constants import BOHR2ANG pos = np.array(pos) / BOHR2ANG calc = geom.calculator calc.plot() ax = calc.ax ax.plot(*pos[:,0,:2].T) plt.show()
def e(i=1,j=0,k=2): colors = ['r','b','k','y'] markers= ['s','o','^','+'] images1 = Trajectory('h2o-s1.traj') images2 = Trajectory('h2o-s2.traj') images3 = Trajectory('h2o-s3.traj') images4 = Trajectory('h2o-s4.traj') E,R,angles = [],[],[] for images in [images1,images2,images3,images4]: e,r = [],[] for atoms in images: e.append(atoms.get_potential_energy()) ri = atoms.positions[i] rj = atoms.positions[j] rk = atoms.positions[k] rij= rj - ri rjk= rk - rj rik= rk - ri rij2 = np.sum(np.square(rij)) rij_ = np.sqrt(rij2) r.append(rij_) rik2 = np.sum(np.square(rik)) rik_ = np.sqrt(rik2) rjk2 = np.sum(np.square(rjk)) rjk_ = np.sqrt(rjk2) cos_ = (rij2+rjk2-rik2)/(2.0*rij_*rjk_) a = np.arccos(cos_)*180.0/3.14159 R.append(r) E.append(e) angles.append(a) plt.figure() plt.ylabel('Energy (eV)') plt.xlabel('Radius (Angstrom)') # plt.xlim(0,i) # plt.ylim(0,np.max(hist)+0.01) for i_,e in enumerate(E): e_min = min(e) e = np.array(e) - e_min plt.plot(R[i_],e,alpha=0.8, linestyle='-',marker='^',markersize=5, color=colors[i_],label='H-O-H: %4.1f' %angles[i_]) plt.legend(loc='best',edgecolor='yellowgreen') plt.savefig('Energy.pdf',transparent=True) plt.close()
def findConformers(self, strref=None, icsref=None): """ all stretches have to be the same; """ if strref is None or icsref is None: stre = self.notdis[0].ic.getStretchBendTorsOop()[0][0] ics = self.notdis[0].ic.getStretchBendTorsOop()[1] else: stre = strref ics = icsref xx = Trajectory('confs.traj', 'a') yy = Trajectory('notconfs.traj', 'a') cnt = 0 for i in self.notdis: istre = i.ic.getStretchBendTorsOop()[0][0] iics = i.ic.getStretchBendTorsOop()[1] same = True if len(stre) > len(istre): same = False else: for j in stre: #print j #print i.oldn if not (iics[j][0] == ics[j][0] and iics[j][1] == iics[j][1]): same = False break if same: xx.write(i.atoms) cnt += 1 print str(cnt) + ' - ' + str(i.oldn) self.conf.append(i) else: yy.write(i.atoms)
def test_md(): import numpy as np import unittest from ase.units import Ry, Ha from ase.calculators.openmx import OpenMX from ase.io.trajectory import Trajectory from ase.optimize import QuasiNewton from ase.constraints import UnitCellFilter from ase.calculators.calculator import PropertyNotImplementedError from ase import Atoms """ Only OpenMX 3.8 or higher version pass this test""" bud = Atoms('CH4', np.array([ [0.000000, 0.000000, 0.100000], [0.682793, 0.682793, 0.682793], [-0.682793, -0.682793, 0.68279], [-0.682793, 0.682793, -0.682793], [0.682793, -0.682793, -0.682793]]), cell=[10, 10, 10]) calc = OpenMX( label='ch4', xc='GGA', energy_cutoff=300 * Ry, convergence=1e-4 * Ha, # Use 'C_PBE19' and 'H_PBE19' for version 3.9 definition_of_atomic_species=[['C', 'C5.0-s1p1', 'C_PBE13'], ['H', 'H5.0-s1', 'H_PBE13']], kpts=(4, 4, 4), eigensolver='Band' ) bud.set_calculator(calc) try: bud.get_stress() except PropertyNotImplementedError as err: raise unittest.SkipTest(err) traj = Trajectory('example.traj', 'w', bud) ucf = UnitCellFilter(bud, mask=[True, True, False, False, False, False]) dyn = QuasiNewton(ucf) dyn.attach(traj.write) dyn.run(fmax=0.1) bud.get_potential_energy() # XXX maybe assert something? traj.close()
def getTrajactory(self): atoms = self.xv_to_atoms(self.label + '.XV') atoms.pbc = [True, True, True] filename = 'Trajectory' atomsList = [] with open(self.label + '.MD_CAR') as f: blockLine = self.numAtom + 7 context = f.readlines() for step in range(self.curStep - 1): output = context[step * blockLine:(step + 1) * blockLine] coodinates = np.array([[ float(value.replace('\n', '')) for value in line.split() ] for line in output[7:]]) atomsCurrent = atoms.copy() atomsCurrent.set_scaled_positions(coodinates) atomsList.append(atomsCurrent) from ase.io import write write(filename, atomsList, 'traj') from ase.io.trajectory import Trajectory traj = Trajectory(filename) return traj
def SinglePointEnergies(traj, label='aimd', frame=50, cpu=4): his = TrajectoryWriter(label + '.traj', mode='w') images = Trajectory(traj) tframe = len(images) E = [] if tframe > frame: ind_ = np.linspace(0, tframe, num=frame, dtype=np.int32) for i in range(tframe): if tframe > frame: if i in ind_: atoms = images[i] else: continue else: atoms = images[i] e_ = atoms.get_potential_energy() atoms_ = single_point(atoms, cpu=cpu) e = atoms_.get_potential_energy() his.write(atoms=atoms_) print('- Energies from MLP: %9.5f DFT: %9.5f' % (e_, e)) E.append(e) his.close() images = None return E
def ple(traj='md.traj'): images = Trajectory(traj) ir = IRFF_NP(atoms=images[0], libfile='ffield.json', rcut=None, nn=True) e, e_, r_ = [], [], [] for atoms in images: # for i in range(62): # atoms = images[i] e.append(atoms.get_potential_energy()) ir.calculate(atoms) # r_.append(ir.r[atomi][atomj]) e_.append(ir.E) fig, ax = plt.subplots() plt.plot(e, label=r'$DFT$ ($SIESTA$)', color='red', markeredgewidth=1, ms=5, alpha=0.8, linewidth=2, linestyle='-') # plt.plot(e,label=r'$Potential$ $Energy$', color='red', # marker='^',markerfacecolor='none', # markeredgewidth=1, # ms=5,alpha=0.8, # linewidth=1, linestyle='-') plt.legend(loc='best', edgecolor='yellowgreen') plt.savefig('popeng.svg', transparent=True) plt.close()
def replay_trajectory(self, traj): """Initialize hessian from old trajectory.""" self.replay = True closelater = None if isinstance(traj, str): from ase.io.trajectory import Trajectory traj = closelater = Trajectory(traj, 'r') try: r0 = None g0 = None for i in range(0, len(traj) - 1): r = traj[i].get_positions().ravel() g = -traj[i].get_forces().ravel() / self.alpha self.update(r, g, r0, g0, self.p) self.p = -np.dot(self.H, g) r0 = r.copy() g0 = g.copy() self.r0 = r0 self.g0 = g0 finally: if closelater is not None: closelater.close()
def test_md(factory): # XXX ugly hack ver = factory.factory.version() if LooseVersion(ver) < '3.8': pytest.skip('No stress tensor until openmx 3.8+') bud = Atoms('CH4', np.array([[0.000000, 0.000000, 0.100000], [0.682793, 0.682793, 0.682793], [-0.682793, -0.682793, 0.68279], [-0.682793, 0.682793, -0.682793], [0.682793, -0.682793, -0.682793]]), cell=[10, 10, 10]) calc = factory.calc( label='ch4', xc='GGA', energy_cutoff=300 * Ry, convergence=1e-4 * Ha, # Use 'C_PBE19' and 'H_PBE19' for version 3.9 definition_of_atomic_species=[['C', 'C5.0-s1p1', 'C_PBE13'], ['H', 'H5.0-s1', 'H_PBE13']], kpts=(1, 1, 1), eigensolver='Band') bud.calc = calc with Trajectory('example.traj', 'w', bud) as traj: ucf = UnitCellFilter(bud, mask=[True, True, False, False, False, False]) dyn = QuasiNewton(ucf) dyn.attach(traj.write) dyn.run(fmax=0.1) bud.get_potential_energy()
def __cleanup__(self): """ Tries to load in structures previously submitted to the queing system. """ confs = self.dc.get_all_candidates_in_queue() for c in confs: fdone = '{0}/cand{1}_done.traj'.format(self.tmp_folder, c) if os.path.isfile(fdone) and os.path.getsize(fdone) > 0: try: a = [] niter = 0 while len(a) == 0 and niter < 5: t = Trajectory(fdone, 'r') a = [ats for ats in t] if len(a) == 0: time.sleep(1.) niter += 1 if len(a) == 0: txt = 'Could not read candidate ' + \ '{0} from the filesystem'.format(c) raise IOError(txt) a = a[-1] a.info['confid'] = c self.dc.add_relaxed_step( a, find_neighbors=self.find_neighbors, perform_parametrization=self.perform_parametrization) except IOError as e: print(e)
def relax(runID): db = connect(db_name) atoms = db.get_atoms(id=runID) con = sq.connect(db_name) cur = con.cursor() cur.execute("SELECT value FROM text_key_values WHERE id=? AND key='name'", (runID, )) name = cur.fetchone()[0] con.close() calc = gp.GPAW(mode=gp.PW(600), xc="PBE", kpts=(4, 4, 4), nbands="120%", symmetry="off") atoms.set_calculator(calc) precon = Exp(mu=1.0, mu_c=1.0) save_to_db = SaveToDB(db_name, runID, name) logfile = "logfile%d.log" % (runID) traj = "trajectory%d.traj" % (runID) uf = UnitCellFilter(atoms, hydrostatic_strain=True) relaxer = PreconLBFGS(uf, logfile=logfile, use_armijo=True, precon=precon) relaxer.attach(save_to_db, interval=1, atoms=atoms) trajObj = Trajectory(traj, "w", atoms) relaxer.attach(trajObj) relaxer.run(fmax=0.05, smax=0.003)
def bhopt(atoms=None, gen='poscar.gen', fmax=0.3, step=100, dr=0.5, temperature=100, optimizer=BFGS, vdwnn=False, nn=True, v=False): if atoms is None: atoms = read(gen) atoms.calc = IRFF(atoms=atoms, libfile='ffield.json', rcut=None, nn=nn, vdwnn=vdwnn) optimizer = BasinHopping( atoms=atoms, # the system to optimize temperature=temperature * kB, # 'temperature' to overcome barriers dr=dr, # maximal stepwidth optimizer=optimizer, fmax=fmax, # maximal force for the optimizer trajectory="opt.traj") optimizer.run(step) if v: images = Trajectory('opt.traj') view(images[-1]) return atoms
def md(atoms=None, gen='poscar.gen', step=100, nn=True, ffield='ffield.json', initT=300, timeStep=0.1, vdwnn=False, print_interval=1): irmd = IRMD(time_step=timeStep, totstep=step, atoms=atoms, gen=gen, Tmax=10000, ro=0.8, rmin=0.5, initT=initT, vdwnn=vdwnn, print_interval=print_interval, nn=nn, ffield=ffield) irmd.run() irmd.close() del irmd images = Trajectory('md.traj') # if v: # view(images[-1]) # ,viewer='x3d' return images
def main(): args = get_args() if not os.path.exists(args.filename): exit(f'Trajectory file {args.filename} doesn\'t exist') if not args.filename.endswith('.traj'): exit('Trajectory must be an ASE .traj file') out_filename = args.filename.replace('.traj', '.xyz') # Make sure the file is empty open(out_filename, 'w').close() # Convert the trajectory to a .xyz file read_traj = Trajectory(args.filename, 'r') for timestep in range(len(read_traj)): if timestep % args.stride == 0: atoms = read_traj[timestep] if args.nowrap is False: atoms.wrap() write(out_filename, atoms, format='xyz', append=True) return None
def opt(atoms=None, gen='poscar.gen', fmax=0.3, step=100, optimizer=BFGS, vdwnn=False, nn=True): if atoms is None: atoms = read(gen) atoms.calc = IRFF(atoms=atoms, libfile='ffield.json', rcut=None, nn=nn, vdwnn=vdwnn) def check(atoms=atoms): epot_ = atoms.get_potential_energy() r = atoms.calc.r.detach().numpy() i_ = np.where(np.logical_and(r < 0.5, r > 0.0001)) n = len(i_[0]) try: assert not np.isnan(epot_), '- Energy is NaN!' except: atoms.write('poscarN.gen') raise ValueError('- Energy is NaN!') optimizer_ = optimizer(atoms, trajectory="opt.traj") optimizer_.attach(check, interval=1) optimizer_.run(fmax, step) images = Trajectory('opt.traj') # view(images[-1]) return images
def main(): atoms = bulk("Al", cubic=True) atoms = atoms * (3, 3, 3) for i in range(int(len(atoms) / 5)): atoms[i].symbol = "Mg" atoms.rattle(stdev=0.005) calc = gp.GPAW(mode=gp.PW(500), xc="PBE", kpts=(4, 4, 4), nbands="120%") atoms.set_calculator(calc) logfile = "relax250.log" traj = "relax250.traj" trajObj = Trajectory(traj, 'w', atoms) precon = Exp(mu=1) relaxer = PreconLBFGS(atoms, logfile=logfile, use_armijo=True, precon=precon, memory=50) #relaxer = PreconFIRE( atoms, logfile=logfile, use_armijo=True, precon=precon ) relaxer.attach(trajObj) try: relaxer.run(fmax=0.05) except Exception as exc: print(exc)
def get_bulk(name, proto): # Get bulk properties dir_root = os.path.join("../../data/2D-bulk/{}-{}".format(name, proto)) gpw_file = os.path.join(dir_root, "gs.gpw") traj_file = os.path.join(dir_root, "{}-{}_relax.traj".format(name, proto)) eps_file = os.path.join(dir_root, "eps_df.npz") if (not os.path.exists(gpw_file)) or (not os.path.exists(eps_file)): return None else: try: d = Trajectory(traj_file)[-1].cell[-1][-1] except Exception: print(Exception) c_atoms = read(gpw_file) # calc = GPAW(gpw_file) d = c_atoms.cell[-1][-1] # d = calc.get_atoms().cell[-1][-1] f = numpy.load(eps_file) eps_xx = f["eps_x"][0].real eps_zz = f["eps_z"][0].real calc = GPAW(gpw_file) try: E_GGA, *_ = bandgap(calc) except Exception: E_GGA = None return d, eps_xx, eps_zz, E_GGA
def bde(ffield='ffield.json', nn='T', gen='poscar.gen', traj='C2H4.traj'): images = Trajectory(traj) atoms = images[0] nn_ = True if nn == 'T' else False ir = IRFF_NP(atoms=atoms, libfile=ffield, rcut=None, nn=nn_) natom = ir.natom Empnn, Esiesta = [], [] eb, eb_ = [], [] for atoms in images: ir.calculate(atoms) Empnn.append(ir.E) Esiesta.append(atoms.get_potential_energy()) # eb.append(ir.ebond[i][j]) fig, ax = plt.subplots() plt.plot(Empnn[0:14], label=r'$E_{MPNN}$', color='blue', linewidth=2, linestyle='-.') plt.plot(Esiesta[0:14], label=r'$E_{SIESTA}$', color='r', linewidth=2, linestyle='-') plt.legend(loc='best', edgecolor='yellowgreen') plt.savefig('Ecompare.pdf') plt.show() plt.close()
def write_mode(self, n=None, kT=units.kB * 300, nimages=30): """Write mode number n to trajectory file. If n is not specified, writes all non-zero modes.""" if n == None: for index, energy in enumerate(self.get_energies()): if abs(energy) > 1e-5: self.write_mode(n=index, kT=kT, nimages=nimages) return mode = self.get_mode(n) * sqrt(kT / abs(self.hnu[n])) p = self.atoms.positions.copy() n %= 3 * len(self.indices) traj = Trajectory("%s.%d.traj" % (self.name, n), "w") calc = self.atoms.get_calculator() self.atoms.set_calculator() for x in np.linspace(0, 2 * pi, nimages, endpoint=False): self.atoms.set_positions(p + sin(x) * mode) traj.write(self.atoms) self.atoms.set_positions(p) self.atoms.set_calculator(calc) traj.close()
def make_inspection_traj(self, points=10, filename=None): """Make trajectory file for the vibrational mode for inspection""" if filename is None: filename = self.an_filename+'_inspect.traj' traj = Trajectory(filename, mode='w', atoms=self.atoms) old_pos = self.atoms.positions.copy() calc = self.atoms.get_calculator() self.atoms.set_calculator() displacements = self.get_initial_displacements(displacements=points) for displacement in displacements: new_pos = self.get_displacement_positions(displacement) self.atoms.set_positions(new_pos) traj.write(self.atoms) self.atoms.set_positions(old_pos) self.atoms.set_calculator(calc) traj.close()
def make_inspection_traj( self, num_displacements=10, filename=None): """Make trajectory file for translational mode to inspect""" if filename is None: filename = self.an_filename+'_inspect.traj' traj = Trajectory(filename, mode='w', atoms=self.atoms) old_pos = self.atoms.positions.copy() calc = self.atoms.get_calculator() self.atoms.set_calculator() angles = self.get_initial_angles(nsamples=num_displacements) for angle in angles: new_pos = self.get_rotate_positions(angle) self.atoms.set_positions(new_pos) traj.write(self.atoms) self.atoms.set_positions(old_pos) self.atoms.set_calculator(calc) traj.close()
def fit_bond_length(self, name, atoms, data=None): N, x = self.fit d0 = atoms.get_distance(0, 1) distances = np.linspace(d0 * (1 - x), d0 * (1 + x), N) energies = [] traj = Trajectory(self.get_filename(name, 'fit.traj'), 'w') for d in distances: atoms.set_distance(0, 1, d) energies.append(atoms.get_potential_energy()) self.check_occupation_numbers(atoms) traj.write(atoms) traj.close() if data is not None: data['distances'] = distances data['energies'] = energies else: assert N % 2 == 1 data = {'energy': energies[N // 2], 'distances': distances, 'energies': energies} return data
def check_ase(self, value): """ Test NUTS simulation Parameters ---------- value: list or tuple The values to use in the tests """ print(self.traj_file) ideal_atoms, _ = value[0] write_traj = Trajectory(self.traj_file.name, mode='w') traj = [] for i in range(3): write_traj.write(ideal_atoms) traj.append(ideal_atoms) self.traj_file.close() assert os.path.exists(self.traj_file.name) print(self.traj_file) read_traj = TrajectoryReader(self.traj_file.name) print(len(traj), len(read_traj)) assert len(traj) == len(read_traj) del traj
def write_h_spacemodes(self, n=None, kT=units.kB * 300, nimages=30): """Write mode number n to trajectory file. If n is not specified, writes all non-zero modes.""" if n is None: for index, energy in enumerate(self.hnu_h_post): if abs(energy) > 1e-5: self.write_h_spacemodes(n=index, kT=kT, nimages=nimages) return mode = self.reduced_h_modes[n] * np.sqrt(kT / abs(self.hnu_h_post[n])) p = self.atoms.positions.copy() traj = Trajectory('%sHarmonic_%02d.traj' % (self.pre_names, n), 'w') calc = self.atoms.get_calculator() self.atoms.set_calculator() for x in np.linspace(0, 2 * np.pi, nimages, endpoint=False): pos_delta = np.zeros_like(p) pos_delta[self.vib.indices] += ( np.sin(x) * mode.reshape((len(self.vib.indices), 3))) self.atoms.set_positions(p + pos_delta) traj.write(self.atoms) self.atoms.set_positions(p) self.atoms.set_calculator(calc) traj.close()
def __init__(self, atoms, temperature=100 * kB, optimizer=FIRE, fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='-', local_minima_trajectory='local_minima.traj', adjust_cm=True): """Parameters: atoms: Atoms object The Atoms object to operate on. trajectory: string Pickle file used to store trajectory of atomic movement. logfile: file object or str If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. """ self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = Trajectory(local_minima_trajectory, 'w', atoms) Dynamics.__init__(self, atoms, logfile, trajectory) self.initialize()
def __init__(self, atoms, restart=None, logfile=None, trajectory=None, seed=None, verbose=False): Optimizer.__init__(self, atoms, restart, logfile, trajectory=None) atoms.get_forces() atoms.get_potential_energy() if seed is None: seed = np.random.randint(0, 2 ** 31) self.verbose = verbose self.random_state = RandomState(seed) self.starting_atoms = dc(atoms) self.pe = [] self.metadata = {'seed': seed} self.traj = [dc(atoms)] print(self.traj[0].get_momenta()) if trajectory is not None: self.trajectory = Trajectory(trajectory, mode='w') self.trajectory.write(self.traj[-1]) if self.verbose: print('Trajectory written', len(self.traj)) else: self.trajectory = None if verbose: print('trajectory file', self.trajectory)
from numpy import linspace from ase.calculators.fleur import FLEUR from ase.build import bulk from ase.io.trajectory import Trajectory atoms = bulk('Ni', a=3.52) calc = FLEUR(xc='PBE', kmax=3.6, kpts=(10, 10, 10), workdir='lat_const') atoms.set_calculator(calc) traj = Trajectory('Ni.traj','w', atoms) cell0 = atoms.get_cell() for s in linspace(0.95, 1.05, 7): cell = cell0 * s atoms.set_cell((cell)) ene = atoms.get_potential_energy() traj.write()
def write_modes(self, q_c, branches=0, kT=units.kB*300, born=False, repeat=(1, 1, 1), nimages=30, center=False): """Write modes to trajectory file. Parameters ---------- q_c: ndarray q-vector of the modes. branches: int or list Branch index of modes. kT: float Temperature in units of eV. Determines the amplitude of the atomic displacements in the modes. born: bool Include non-analytic contribution to the force constants at q -> 0. repeat: tuple Repeat atoms (l, m, n) times in the directions of the lattice vectors. Displacements of atoms in repeated cells carry a Bloch phase factor given by the q-vector and the cell lattice vector R_m. nimages: int Number of images in an oscillation. center: bool Center atoms in unit cell if True (default: False). """ if isinstance(branches, int): branch_l = [branches] else: branch_l = list(branches) # Calculate modes omega_l, u_l = self.band_structure([q_c], modes=True, born=born) # Repeat atoms atoms = self.atoms * repeat # Center if center: atoms.center() # Here ``Na`` refers to a composite unit cell/atom dimension pos_Nav = atoms.get_positions() # Total number of unit cells N = np.prod(repeat) # Corresponding lattice vectors R_m R_cN = np.indices(repeat).reshape(3, -1) # Bloch phase phase_N = np.exp(2.j * pi * np.dot(q_c, R_cN)) phase_Na = phase_N.repeat(len(self.atoms)) for l in branch_l: omega = omega_l[0, l] u_av = u_l[0, l] # Mean displacement of a classical oscillator at temperature T u_av *= sqrt(kT) / abs(omega) mode_av = np.zeros((len(self.atoms), 3), dtype=complex) # Insert slice with atomic displacements for the included atoms mode_av[self.indices] = u_av # Repeat and multiply by Bloch phase factor mode_Nav = np.vstack(N * [mode_av]) * phase_Na[:, np.newaxis] traj = Trajectory('%s.mode.%d.traj' % (self.name, l), 'w') for x in np.linspace(0, 2*pi, nimages, endpoint=False): atoms.set_positions((pos_Nav + np.exp(1.j * x) * mode_Nav).real) traj.write(atoms) traj.close()
a2 = a0.copy() a2.set_masses() a2.center(vacuum=2.0) a2.rattle(stdev=0.2) a3 = molecule('CH3CH2OH') a4 = bulk('Au').repeat((2, 2, 2)) a5 = bulk('Cu').repeat((2, 2, 3)) # Add constraints to some of the images: images = [a0, a1, a2, a3, a4, a5] for i, img in enumerate(images[3:]): img.set_constraint(FixAtoms(indices=range(i + 3))) if i == 2: img.constraints.append(FixBondLength(5, 6)) traj = Trajectory('out.traj', 'w') for i, img in enumerate(images): traj.write(img) print(i, traj.multiple_headers) assert traj.multiple_headers == (i >= 2) traj.close() #view(images) rtraj = Trajectory('out.traj') newimages = list(rtraj) assert len(images) == len(newimages) for i in range(len(images)): assert images[i] == newimages[i], i h1 = get_header_data(images[i])
a = random_solid(els, density, sx=sx, sy=sy) n = a.get_atomic_numbers().copy() # Relax with the quick potential a.set_atomic_numbers([6]*len(a)) a.set_calculator(quick_calc) FIRE(a, downhill_check=True).run(fmax=1.0, steps=nsteps_relax) a.set_atomic_numbers(n) write(initial_fn, a) else: print('... reading %s ...' % liquid_fn) a = read(liquid_fn) # Thermalize with the slow (but correct) potential a.set_calculator(calc) traj = Trajectory(liquid_fn, 'a', a) dyn = Langevin(a, dt1, T1, 1.0/tau1, logfile='-', loginterval=int(dtdump/dt1)) dyn.attach(traj.write, interval=int(dtdump/dt1)) # every 100 fs nsteps = int(teq/dt1)-len(traj)*int(dtdump/dt1) print('Need to run for further {} steps to reach total of {} steps.'.format(nsteps, int(teq/dt1))) if nsteps <= 0: nsteps = 1 dyn.run(nsteps) traj.close() # Write snapshot write(liquid_final_fn, a) else: print('... reading %s ...' % liquid_final_fn) a = read(liquid_final_fn)
# RuntimeError: Optimal parameters not found: # Number of calls to function has reached maxfev = 1000. eos_strl3 = [m for m in eos_strl] eos_strl3.remove('AntonSchmidt') results = {} # prepare energies and volumes b = bulk('Al', 'fcc', a=4.0, orthorhombic=True) b.set_calculator(EMT()) cell = b.get_cell() volumes = [] energies = [] traj = Trajectory('eos.traj', 'w') for x in np.linspace(0.97, 1.03, 5): b.set_cell(cell * x, scale_atoms=True) volumes.append(b.get_volume()) energies.append(b.get_potential_energy()) traj.write(b) for n, (v, e) in enumerate(zip(volumes, energies)): vref = ref['volumes'][n] eref = ref['energies'][n] vabserr = abs((v - vref) / vref) vstrerr = str(n) + ' volume: ' + str(v) + ': ' + str(vref) + ': ' + str(vabserr) assert vabserr < 1.e-6, vstrerr eabserr = abs((e - eref) / eref) estrerr = str(n) + ' energy: ' + str(e) + ': ' + str(eref) + ': ' + str(eabserr) assert eabserr < 1.e-4, estrerr
def write(self, filename): from ase.io.trajectory import Trajectory traj = Trajectory(filename, 'w', self) traj.write() traj.close()
through the other. Such atoms have coordinates outside the box. This facilitates analysis of e.g. diffusion, but can be problematic when plotting. This script reads through a trajectory file, and write a new one where all atoms are mapped into the computational box. If there are axes with free boundary conditions, the corresponding coordinate is left unchanged. SIDE EFFECT: All energies, forces and stresses are removed (yes, this can be considered as a bug!) """ from __future__ import print_function import sys from ase.io.trajectory import Trajectory if len(sys.argv) != 3: print(__doc__) sys.exit(1) infile = Trajectory(sys.argv[1]) outfile = None for atoms in infile: atoms.set_scaled_positions(atoms.get_scaled_positions()) atoms.set_calculator(None) # or the singlepointcalculator fails! if outfile is None: outfile = Trajectory(sys.argv[2], "w") outfile.write(atoms) outfile.close()
class BasinHopping(Dynamics): """Basin hopping algorithm. After Wales and Doye, J. Phys. Chem. A, vol 101 (1997) 5111-5116 and David J. Wales and Harold A. Scheraga, Science, Vol. 285, 1368 (1999) """ def __init__(self, atoms, temperature=100 * kB, optimizer=FIRE, fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='-', local_minima_trajectory='local_minima.traj', adjust_cm=True): """Parameters: atoms: Atoms object The Atoms object to operate on. trajectory: string Pickle file used to store trajectory of atomic movement. logfile: file object or str If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. """ self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = Trajectory(local_minima_trajectory, 'w', atoms) Dynamics.__init__(self, atoms, logfile, trajectory) self.initialize() def todict(self): d = {'type': 'optimization', 'optimizer': self.__class__.__name__, 'local-minima-optimizer': self.optimizer.__name__, 'temperature': self.kT, 'max-force': self.fmax, 'maximal-step-width': self.dr} return d def initialize(self): self.positions = 0.0 * self.atoms.get_positions() self.Emin = self.get_energy(self.atoms.get_positions()) or 1.e32 self.rmin = self.atoms.get_positions() self.positions = self.atoms.get_positions() self.call_observers() self.log(-1, self.Emin, self.Emin) def run(self, steps): """Hop the basins for defined number of steps.""" ro = self.positions Eo = self.get_energy(ro) for step in range(steps): En = None while En is None: rn = self.move(ro) En = self.get_energy(rn) if En < self.Emin: # new minimum found self.Emin = En self.rmin = self.atoms.get_positions() self.call_observers() self.log(step, En, self.Emin) accept = np.exp((Eo - En) / self.kT) > np.random.uniform() if accept: ro = rn.copy() Eo = En def log(self, step, En, Emin): if self.logfile is None: return name = self.__class__.__name__ self.logfile.write('%s: step %d, energy %15.6f, emin %15.6f\n' % (name, step, En, Emin)) self.logfile.flush() def move(self, ro): """Move atoms by a random step.""" atoms = self.atoms # displace coordinates disp = np.random.uniform(-1., 1., (len(atoms), 3)) rn = ro + self.dr * disp atoms.set_positions(rn) if self.cm is not None: cm = atoms.get_center_of_mass() atoms.translate(self.cm - cm) rn = atoms.get_positions() world.broadcast(rn, 0) atoms.set_positions(rn) return atoms.get_positions() def get_minimum(self): """Return minimal energy and configuration.""" atoms = self.atoms.copy() atoms.set_positions(self.rmin) return self.Emin, atoms def get_energy(self, positions): """Return the energy of the nearest local minimum.""" if np.sometrue(self.positions != positions): self.positions = positions self.atoms.set_positions(positions) opt = self.optimizer(self.atoms, logfile=self.optimizer_logfile) opt.run(fmax=self.fmax) if self.lm_trajectory is not None: self.lm_trajectory.write(self.atoms) self.energy = self.atoms.get_potential_energy() return self.energy
import numpy as np from ase import Atoms from ase.io.trajectory import Trajectory from ase.calculators.emt import EMT a = 4.0 # approximate lattice constant b = a / 2 ag = Atoms('Ag', cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1, calculator=EMT()) # use EMT potential cell = ag.get_cell() traj = Trajectory('Ag.traj', 'w') for x in np.linspace(0.95, 1.05, 5): ag.set_cell(cell * x, scale_atoms=True) ag.get_potential_energy() traj.write(ag)