def get_atoms(): # 2x2-Al(001) surface with 3 layers and an # Au atom adsorbed in a hollow site: slab = fcc100('Al', size=(2, 2, 3)) add_adsorbate(slab, 'Au', 1.7, 'hollow') slab.center(axis=2, vacuum=4.0) # Fix second and third layers: mask = [atom.tag > 1 for atom in slab] slab.set_constraint(FixAtoms(mask=mask)) # Use EMT potential: slab.set_calculator(EMT()) # Initial state: qn = QuasiNewton(slab, logfile=None) qn.run(fmax=0.05) initial = slab.copy() # Final state: slab[-1].x += slab.get_cell()[0, 0] / 2 qn = QuasiNewton(slab, logfile=None) qn.run(fmax=0.05) final = slab.copy() # Setup a NEB calculation constraint = FixAtoms(mask=[atom.tag > 1 for atom in initial]) images = [initial] for i in range(3): image = initial.copy() image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, parallel=mpi.parallel) neb.interpolate() def set_calculator(calc): i = 0 for image in neb.images[1:-1]: if not mpi.parallel or mpi.rank // (mpi.size // 3) == i: image.set_calculator(calc) i += 1 neb.set_calculator = set_calculator return neb
# All the cells should be the same. assert (calc.get_atoms().get_cell() == CONTCAR_Al.get_cell()).all() assert (Al.get_cell() == CONTCAR_Al.get_cell()).all() return Al # -- Perform Volume relaxation using ASE with Vasp as force/stress calculator def ase_ext.vol_relax(): Al = bulk('Al', 'fcc', a=4.5, cubic=True) calc = Vasp(xc='LDA') Al.set_calculator(calc) from ase_ext.constraints import StrainFilter sf = StrainFilter(Al) qn = QuasiNewton(sf, logfile='relaxation.log') qn.run(fmax=0.1, steps=5) print('Stress:\n', calc.read_stress()) print('Al post ASE volume relaxation\n', calc.get_atoms().get_cell()) return Al # Test function for comparing two cells def cells_almost_equal(cellA, cellB, tol=0.01): return (np.abs(cellA - cellB) < tol).all() # Correct LDA relaxed cell a_rel = 4.18 LDA_cell = np.diag([a_rel, a_rel, a_rel])
from ase_ext import Atoms from ase_ext.calculators.emt import EMT from ase_ext.optimize import QuasiNewton from ase_ext.vibrations import Vibrations from ase_ext.thermochemistry import IdealGasThermo n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(n2).run(fmax=0.01) vib = Vibrations(n2) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(-1, nimages=20) vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear', atoms=n2, symmetrynumber=2, spin=0) thermo.get_free_energy(temperature=298.15, pressure=2 * 101325.)
from ase_ext.io import PickleTrajectory from ase_ext.neb import NEB from ase_ext.calculators.lj import LennardJones from ase_ext.optimize import QuasiNewton print([a.get_potential_energy() for a in PickleTrajectory('H.traj')]) images = [PickleTrajectory('H.traj')[-1]] for i in range(4): images.append(images[0].copy()) images[-1].positions[6, 1] = 2 - images[0].positions[6, 1] neb = NEB(images) neb.interpolate() for image in images: image.set_calculator(LennardJones()) for a in neb.images: print(a.positions[-1], a.get_potential_energy()) dyn = QuasiNewton(neb, trajectory='mep.traj') print(dyn.run(fmax=0.01, steps=25)) for a in neb.images: print(a.positions[-1], a.get_potential_energy())
# Distance between Cu atoms on a (111) surface: a = 3.6 d = a / sqrt(2) y = d * sqrt(3) / 2 fcc111 = Atoms('Cu', cell=[(d, 0, 0), (d / 2, y, 0), (d / 2, y / 3, -a / sqrt(3))], pbc=True) slab = fcc111 * (2, 2, 4) slab.set_cell([2 * d, 2 * y, 1]) slab.set_pbc((1, 1, 0)) slab.set_calculator(EMT()) Z = slab.get_positions()[:, 2] indices = [i for i, z in enumerate(Z) if z < Z.mean()] constraint = FixAtoms(indices=indices) slab.set_constraint(constraint) dyn = QuasiNewton(slab) dyn.run(fmax=0.05) Z = slab.get_positions()[:, 2] print(Z[0] - Z[1]) print(Z[1] - Z[2]) print(Z[2] - Z[3]) b = 1.2 h = 2.0 slab += Atom('C', (d, 2 * y / 3, h)) slab += Atom('O', (3 * d / 2, y / 3, h)) traj = PickleTrajectory('initial.traj', 'w', slab) dyn = QuasiNewton(slab) dyn.attach(traj.write) dyn.run(fmax=0.05) #view(slab)
from ase_ext import Atoms from ase_ext.calculators.emt import EMT from ase_ext.optimize import QuasiNewton n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(n2).run(0.01) print(n2.get_distance(0, 1), n2.get_potential_energy())
pass else: a = 3.6 b = a / 2 initial = Atoms('Cu4', positions=[(0, 0, 0), (0, b, b), (b, 0, b), (b, b, 0)], cell=(a, a, a), pbc=True) initial *= (4, 4, 4) del initial[0] images = [initial] + [initial.copy() for i in range(6)] images[-1].positions[0] = (0, 0, 0) for image in images: image.set_calculator(EMT()) #image.set_calculator(ASAP()) for image in [images[0], images[-1]]: QuasiNewton(image).run(fmax=0.01) neb = NEB(images) neb.interpolate() for a in images: print(a.positions[0], a.get_potential_energy()) dyn = MDMin(neb, dt=0.1, trajectory='mep1.traj') #dyn = QuasiNewton(neb) print(dyn.run(fmax=0.01, steps=25)) for a in images: print(a.positions[0], a.get_potential_energy())
# Make band: images = [initial.copy() for i in range(6)] neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(list(range(len(initial) - 1))) for image in images: image.set_calculator(EMT()) image.set_constraint(constraint) # Displace last image: images[-1].positions[-1] += (d, 0, 0) #images[-1].positions[-1] += (d, d, 0) # Relax height of Ag atom for initial and final states: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.01) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.01) # Interpolate positions between initial and final states: neb.interpolate() for image in images: print(image.positions[-1], image.get_potential_energy()) #dyn = MDMin(neb, dt=0.4) #dyn = FIRE(neb, dt=0.4) dyn = QuasiNewton(neb, trajectory='mep.traj') dyn.run(fmax=0.05)
# Distance between Cu atoms on a (111) surface: a = 3.6 d = a / sqrt(2) fcc111 = Atoms(symbols='Cu', cell=[(d, 0, 0), (d / 2, d * sqrt(3) / 2, 0), (d / 2, d * sqrt(3) / 6, -a / sqrt(3))], pbc=True) slab = fcc111 * (2, 2, 4) slab.set_cell([2 * d, d * sqrt(3), 1]) slab.set_pbc((1, 1, 0)) slab.set_calculator(EMT()) Z = slab.get_positions()[:, 2] indices = [i for i, z in enumerate(Z) if z < Z.mean()] constraint = FixAtoms(indices=indices) slab.set_constraint(constraint) dyn = QuasiNewton(slab) dyn.run(fmax=0.05) Z = slab.get_positions()[:, 2] print(Z[0] - Z[1]) print(Z[1] - Z[2]) print(Z[2] - Z[3]) b = 1.2 h = 1.5 slab += Atom('C', (d / 2, -b / 2, h)) slab += Atom('O', (d / 2, +b / 2, h)) s = slab.copy() dyn = QuasiNewton(slab) dyn.run(fmax=0.05) #view(slab)
import numpy as np from ase_ext import Atoms from ase_ext.units import fs from ase_ext.calculators.test import TestPotential from ase_ext.calculators.emt import EMT from ase_ext.md import VelocityVerlet from ase_ext.io import PickleTrajectory, read from ase_ext.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