def get_atoms(): zpos = cos(134.3/2.0*pi/180.0)*1.197 xpos = sin(134.3/2.0*pi/180.0)*1.19 no2 =Atoms('CO', positions=[(-xpos+1.2,0,-zpos), (-xpos+1.2,-1.1,-zpos)]) # Surface slab slab =fcc111('Au', size=(2, 2, 4),vacuum=2*5, orthogonal = True ) slab.center() add_adsorbate(slab,no2,1.5,'bridge') slab.set_pbc((True,True,False)) #constraints constraint = FixAtoms(mask=[(a.tag == 4) or (a.tag == 3) or (a.tag==2) for a in slab]) slab.set_constraint(constraint) return slab
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
def test_vibration_on_surface(self, testdir): from ase.build import fcc111, add_adsorbate ag_slab = fcc111('Ag', (4, 4, 2), a=2) n2 = Atoms('N2', positions=[[0., 0., 0.], [0., np.sqrt(2), np.sqrt(2)]]) add_adsorbate(ag_slab, n2, height=1, position='fcc') # Add an interaction between the N atoms hessian_bottom_corner = np.zeros((2, 3, 2, 3)) hessian_bottom_corner[-1, :, -2] = [1, 1, 1] hessian_bottom_corner[-2, :, -1] = [1, 1, 1] hessian = np.zeros((34, 3, 34, 3)) hessian[32:, :, 32:, :] = hessian_bottom_corner ag_slab.calc = ForceConstantCalculator(hessian.reshape( (34 * 3, 34 * 3)), ref=ag_slab.copy(), f0=np.zeros((34, 3))) # Check that Vibrations with restricted indices returns correct Hessian vibs = Vibrations(ag_slab, indices=[-2, -1]) vibs.run() vibs.read() assert_array_almost_equal(vibs.get_vibrations().get_hessian(), hessian_bottom_corner) # These should blow up if the vectors don't match number of atoms vibs.summary() vibs.write_jmol() for i in range(6): # Frozen atoms should have zero displacement assert_array_almost_equal(vibs.get_mode(i)[0], [0., 0., 0.]) # The N atoms should have finite displacement assert np.all(vibs.get_mode(i)[-2:, :])
def test_custom_fingerprinting(self): """Test the custom fingerprint example""" atoms = fcc111('Pd', size=(2, 2, 3), vacuum=10.0) add_adsorbate(atoms, 'C', 1, 'fcc') # -1 is the tag convention to identify bonded atoms tags = atoms.get_tags() tags[-1] = -1 atoms.set_tags(tags) parameters = [ 'atomic_number', 'dband_center_slab', 'dband_width_slab', 'dband_skewness_slab', 'dband_kurtosis_slab' ] def example_operation( atoms, atoms_parameters, connectivity): # This is a CatKit convention bond_index = np.where(atoms.get_tags() == -1)[0] return np.sum(connectivity[bond_index], axis=1) operations = [ 'bonding_convolution', example_operation ] fp = Fingerprinter(atoms) fingerprints = fp.get_fp(parameters, operations) truth = np.array([276.0, -1.570340288877117, 6.51684717398884, -81.36785228863994, 3651.4867376228817, 3.0]) np.testing.assert_allclose(fingerprints[0], truth)
def construct_geometries(parent_calc, ml2relax): counter_calc = parent_calc # Initial structure guess initial_slab = fcc100("Cu", size=(2, 2, 3)) add_adsorbate(initial_slab, "C", 1.7, "hollow") initial_slab.center(axis=2, vacuum=4.0) mask = [atom.tag > 1 for atom in initial_slab] initial_slab.set_constraint(FixAtoms(mask=mask)) initial_slab.set_pbc(True) initial_slab.wrap(pbc=[True] * 3) initial_slab.set_calculator(counter_calc) # Final structure guess final_slab = initial_slab.copy() final_slab[-1].x += final_slab.get_cell()[0, 0] / 3 final_slab.set_calculator(counter_calc) if not ml2relax: print("BUILDING INITIAL") qn = BFGS(initial_slab, trajectory="initial.traj", logfile="initial_relax_log.txt") qn.run(fmax=0.01, steps=100) print("BUILDING FINAL") qn = BFGS(final_slab, trajectory="final.traj", logfile="final_relax_log.txt") qn.run(fmax=0.01, steps=100) initial_slab = read("initial.traj", "-1") final_slab = read("final.traj", "-1") # If there is already a pre-existing initial and final relaxed parent state we can read # that to use as a starting point # initial_slab = read("/content/parent_initial.traj") # final_slab = read("/content/parent_final.traj") else: initial_slab = initial_slab final_slab = final_slab # initial_force_calls = counter_calc.force_calls return initial_slab, final_slab # , initial_force_calls
def test_dimer_method(testdir): # Set up a small "slab" with an adatoms atoms = fcc100('Pt', size=(2, 2, 1), vacuum=10.0) add_adsorbate(atoms, 'Pt', 1.611, 'hollow') # Freeze the "slab" mask = [atom.tag > 0 for atom in atoms] atoms.set_constraint(FixAtoms(mask=mask)) # Calculate using EMT atoms.calc = EMT() atoms.get_potential_energy() # Set up the dimer with DimerControl(initial_eigenmode_method='displacement', displacement_method='vector', logfile=None, mask=[0, 0, 0, 0, 1]) as d_control: d_atoms = MinModeAtoms(atoms, d_control) # Displace the atoms displacement_vector = [[0.0] * 3] * 5 displacement_vector[-1][1] = -0.1 d_atoms.displace(displacement_vector=displacement_vector) # Converge to a saddle point with MinModeTranslate(d_atoms, trajectory='dimer_method.traj', logfile=None) as dim_rlx: dim_rlx.run(fmax=0.001) # Test the results tolerance = 1e-3 assert (d_atoms.get_barrier_energy() - 1.03733136918 < tolerance) assert (abs(d_atoms.get_curvature() + 0.900467048707) < tolerance) assert (d_atoms.get_eigenmode()[-1][1] < -0.99) assert (abs(d_atoms.get_positions()[-1][1]) < tolerance)
def gridVasp(adsorbate, slab, directory='tempout/', spacing=0.2): """ Takes in slab, adsorbate, and desired output directory. Writes numbered POSCAR files to output directory with adsorbate placed in grid pattern Args: adsorbate: either path (str) for POS/CONTCAR or Atoms obj slab: either path (str) for POS/CONTCAR or Atoms obj directory: path (str) for desired output location spacing: spacing between grid points (eg, 0.2 is a 5x5 grid) Returns: None """ if type(adsorbate) == str: adsorbate = vasp.read_vasp(adsorbate) if type(slab) == str: slab = vasp.read_vasp(slab) # TODO: make this work with path objects? i = 0 # 0 index written POSCAR{i} files for _x in np.arange(0, 1 - spacing, spacing): for _y in np.arange(0, 1 - spacing, spacing): s = slab.copy() x, y, z = slab.cell.cartesian_positions([_x, _y, 0]) add_adsorbate(s, adsorbate, height=2, position=(x, y)) s = Atoms(sorted(s, key=lambda x: x.symbol)) s.cell = slab.cell vasp.write_vasp(directory + "POSCAR" + str(i), s, label='{} on {}'.format( adsorbate.get_chemical_formula(), slab.get_chemical_formula()), vasp5=True) i += 1
def slabgen(termination, size, adsorbate, position): if termination == '100': prim = fcc100('Cu', a=3.6302862146117354, size=(1, 1, 5), vacuum=15, orthogonal=True, periodic=True) elif termination == '111': prim = fcc111_root('Cu', root=3, a=3.6302862146117354, size=(1, 1, 5), vacuum=15) super = make_supercell(prim, size) add_adsorbate(slab=super, adsorbate=adsorbate, height=ads_height, position=position) constr = FixAtoms( indices=[atom.index for atom in super if atom.position[2] < 19]) super.set_constraint(constr) return super
def aual100(site, height, calc=None): slab = fcc100('Al', size=(2, 2, 2)) slab.center(axis=2, vacuum=3.0) add_adsorbate(slab, 'Au', height, site) mask = [atom.symbol == 'Al' for atom in slab] fixlayer = FixAtoms(mask=mask) slab.set_constraint(fixlayer) if calc is None: calc = GPAW(mode=PW(200), kpts=(2, 2, 1), xc='PBE', txt=site + '.txt', eigensolver='rmm-diis', nbands=40) slab.set_calculator(calc) qn = QuasiNewton(slab, trajectory=site + calc.name + '.traj') qn.run(fmax=0.05) if isinstance(calc, GPAW): calc.write(site + '.gpw') return slab.get_potential_energy()
def test_surface(): import numpy as np from ase import Atoms, Atom from ase.build import fcc111, fcc211, add_adsorbate, bulk, surface import math atoms = fcc211('Au', (3, 5, 8), vacuum=10.) assert len(atoms) == 120 atoms = atoms.repeat((2, 1, 1)) assert np.allclose(atoms.get_distance(0, 130), 2.88499566724) atoms = fcc111('Ni', (2, 2, 4), orthogonal=True) add_adsorbate(atoms, 'H', 1, 'bridge') add_adsorbate(atoms, Atom('O'), 1, 'fcc') add_adsorbate(atoms, Atoms('F'), 1, 'hcp') # The next test ensures that a simple string of multiple atoms cannot be used, # which should fail with a KeyError that reports the name of the molecule due # to the string failing to work with Atom(). failed = False try: add_adsorbate(atoms, 'CN', 1, 'ontop') except KeyError as e: failed = True assert e.args[0] == 'CN' assert failed # This test ensures that the default periodic behavior remains unchanged cubic_fcc = bulk("Al", a=4.05, cubic=True) surface_fcc = surface(cubic_fcc, (1,1,1), 3) assert list(surface_fcc.pbc) == [True, True, False] assert surface_fcc.cell[2][2] == 0 # This test checks the new periodic option cubic_fcc = bulk("Al", a=4.05, cubic=True) surface_fcc = surface(cubic_fcc, (1,1,1), 3, periodic=True) assert (list(surface_fcc.pbc) == [True, True, True]) expected_length = 4.05*3**0.5 #for FCC with a=4.05 assert math.isclose(surface_fcc.cell[2][2], expected_length)
from ase.calculators.emt import EMT from ase.constraints import FixBondLengths from ase.optimize import BFGS from ase.build import fcc111, add_adsorbate for wrap in [False, True]: zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.set_calculator(calc) if wrap: # Remap into the cell so bond is actually wrapped: slab.set_scaled_positions(slab.get_scaled_positions() % 1.0) constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax_%d.traj' % wrap) dyn.run(fmax=0.05) assert abs(slab.get_distance(-3, -2, mic=1) - d0) < 1e-9 assert abs(slab.get_distance(-3, -1, mic=1) - d1) < 1e-9
import numpy as np from ase import Atoms, Atom from ase.build import fcc111, fcc211, add_adsorbate atoms = fcc211('Au', (3, 5, 8), vacuum=10.) assert len(atoms) == 120 atoms = atoms.repeat((2, 1, 1)) assert np.allclose(atoms.get_distance(0, 130), 2.88499566724) atoms = fcc111('Ni', (2, 2, 4), orthogonal=True) add_adsorbate(atoms, 'H', 1, 'bridge') add_adsorbate(atoms, Atom('O'), 1, 'fcc') add_adsorbate(atoms, Atoms('F'), 1, 'hcp') # The next test ensures that a simple string of multiple atoms cannot be used, # which should fail with a KeyError that reports the name of the molecule due # to the string failing to work with Atom(). failed = False try: add_adsorbate(atoms, 'CN', 1, 'ontop') except KeyError as e: failed = True assert e.args[0] == 'CN' assert failed
write(name + '.png', slab, show_unit_cell=2, radii=radii[name[:3]], scale=10) for name in surfaces: f = getattr(surface, name) for kwargs in [{}, {'orthogonal': False}, {'orthogonal': True}]: print(name, kwargs) try: slab = f(symbols[name[:3]], size=(3, 4, 5), vacuum=4, **kwargs) except (TypeError, NotImplementedError): continue try: for site in slab.adsorbate_info['sites']: if site.endswith('bridge'): h = 1.5 else: h = 1.2 surface.add_adsorbate(slab, adsorbates.get(site, 'F'), h, site) except KeyError: pass if kwargs.get('orthogonal', None): name += 'o' save(name, slab) for site, symbol in adsorbates.items(): write('%s-site.png' % site, Atoms(symbol), radii=1.08, scale=10) fcc111_primitive = fcc111("Ag", (1, 1, 3)) fcc111_root = root_surface(fcc111_primitive, 27) save("fcc111_root", fcc111_root)
if not os.path.exists(folder): os.mkdir(folder) os.chdir(folder) slab = fcc111(symbol, size=(3,3,4), orthogonal=False) slab.center(vacuum=15.0, axis=2) c = FixAtoms(indices=[atom.index for atom in slab if atom.symbol == symbol]) slab.set_constraint(c) write('POSCAR', slab, vasp5=True, direct=True) os.chdir('..') folder = '02-h' if not os.path.exists(folder): os.mkdir(folder) os.chdir(folder) slab = fcc111(symbol, size=(3,3,4), orthogonal=False) add_adsorbate(slab, 'H', 1.0, 'fcc') slab.center(vacuum=15.0, axis=2) c = FixAtoms(indices=[atom.index for atom in slab if atom.symbol == symbol]) slab.set_constraint(c) write('POSCAR', slab, vasp5=True, direct=True) os.chdir('..') folder = '03-h2o' if not os.path.exists(folder): os.mkdir(folder) os.chdir(folder) slab = fcc111(symbol, size=(3,3,4), orthogonal=False) water = molecule('H2O') water.rotate(90, 'y') add_adsorbate(slab, water, 2.0, 'fcc') slab.center(vacuum=15.0, axis=2)
xc='PBE', gga='RP', lreal=False, ediff=1e-4, ispin=1, nelm=100, encut=400, lwave=False, lcharg=False, nsw=0, kpts=(1, 1, 1)) # Define initial set of images, can be as few as 1. If 1, make sure to slab = fcc100("Cu", size=(3, 3, 3)) ads = molecule("CO") add_adsorbate(slab, ads, 3, offset=(1, 1)) cons = FixAtoms(indices=[atom.index for atom in slab if (atom.tag == 3)]) slab.set_constraint(cons) slab.center(vacuum=13.0, axis=2) slab.set_pbc(True) slab.wrap(pbc=True) slab.set_calculator(copy.copy(dft_calc)) sample_energy = slab.get_potential_energy(apply_constraint=False) sample_forces = slab.get_forces(apply_constraint=False) slab.set_calculator( sp(atoms=slab, energy=sample_energy, forces=sample_forces)) ase.io.write("./slab.traj", slab) images = [slab] # Define symmetry functions
def test_atoms_formula(): from ase.build import fcc111, add_adsorbate import warnings # some random system slab = fcc111('Al', size=(2, 2, 3)) add_adsorbate(slab, 'C', 2.5, 'bridge') add_adsorbate(slab, 'C', 3.5, 'bridge') add_adsorbate(slab, 'H', 1.5, 'ontop') add_adsorbate(slab, 'H', 1.5, 'fcc') add_adsorbate(slab, 'C', 0.5, 'bridge') add_adsorbate(slab, 'C', 1.5, 'bridge') assert slab.get_chemical_formula(mode='hill') == 'C4H2Al12' assert slab.get_chemical_formula(mode='metal') == 'Al12C4H2' all_str = 'Al' * 12 + 'C' * 2 + 'H' * 2 + 'C' * 2 assert slab.get_chemical_formula(mode='all') == all_str reduce_str = 'Al12C2H2C2' assert slab.get_chemical_formula(mode='reduce') == reduce_str assert slab.get_chemical_formula(mode='hill', empirical=True) == 'C2HAl6' assert slab.get_chemical_formula(mode='metal', empirical=True) == 'Al6C2H' # check for warning if empirical formula is not available for mode in ('all', 'reduce'): with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter('always') # Trigger a warning. slab.get_chemical_formula(mode=mode, empirical=True) # Verify some things assert len(w) == 1 assert issubclass(w[-1].category, Warning)
import sys from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations sys.path.append("../..") from __init__ import AnharmonicModes slab = fcc111('Al', size=(2, 2, 2), vacuum=3.0) CH3 = molecule('CH3') add_adsorbate(slab, CH3, 2.5, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Al' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) dyn = QuasiNewton(slab) dyn.run(fmax=0.05) # Running vibrational analysis vib = Vibrations(slab, indices=[8, 9, 10, 11]) vib.run() vib.summary() print('\n >> Anharmonics <<\n')
# creates: io1.png io2.png io3.png from ase import Atoms from ase.build import fcc111, add_adsorbate from ase.io import write, read adsorbate = Atoms('CO') adsorbate[1].z = 1.1 a = 3.61 slab = fcc111('Cu', (2, 2, 3), a=a, vacuum=7.0) add_adsorbate(slab, adsorbate, 1.8, 'ontop') write('io1.png', slab * (3, 3, 1), rotation='10z,-80x') write('io2.pov', slab * (3, 3, 1), rotation='10z,-80x', transparent=False, display=False, run_povray=True) d = a / 2**0.5 write('io3.pov', slab * (2, 2, 1), bbox=(d, 0, 3 * d, d * 3**0.5), transparent=False, display=False, run_povray=True) write('slab.xyz', slab) a = read('slab.xyz') a.get_cell() a.get_pbc() write('slab.traj', slab) b = read('slab.traj') b.get_cell() b.get_pbc()
from ase.build import fcc100, add_adsorbate from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.dimer import DimerControl, MinModeAtoms, MinModeTranslate # Set up a small "slab" with an adatoms atoms = fcc100('Pt', size = (2, 2, 1), vacuum = 10.0) add_adsorbate(atoms, 'Pt', 1.611, 'hollow') # Freeze the "slab" mask = [atom.tag > 0 for atom in atoms] atoms.set_constraint(FixAtoms(mask = mask)) # Calculate using EMT atoms.set_calculator(EMT()) relaxed_energy = atoms.get_potential_energy() # Set up the dimer d_control = DimerControl(initial_eigenmode_method = 'displacement', \ displacement_method = 'vector', logfile = None, \ mask = [0, 0, 0, 0, 1]) d_atoms = MinModeAtoms(atoms, d_control) # Displace the atoms displacement_vector = [[0.0]*3]*5 displacement_vector[-1][1] = -0.1 d_atoms.displace(displacement_vector = displacement_vector) # Converge to a saddle point dim_rlx = MinModeTranslate(d_atoms, trajectory = 'dimer_method.traj', \ logfile = None)
xc='RPBE', kpts=(8, 6, 1), eigensolver='cg', spinpol=True, mixer=MixerSum(nmaxold=5, beta=0.1, weight=100), convergence={ 'energy': 100, 'density': 100, 'eigenstates': 1.0e-7, 'bands': -10 }, txt=filename + '.txt') # Import Slab with relaxed CO slab = fcc111('Pt', size=(1, 2, 3), orthogonal=True) add_adsorbate(slab, 'C', 2.0, 'ontop') add_adsorbate(slab, 'O', 3.15, 'ontop') slab.center(axis=2, vacuum=4.0) view(slab) molecule = slab.copy() del molecule[:-2] # Molecule molecule.set_calculator(c_mol) molecule.get_potential_energy() # H**o wavefunction wf_u = [kpt.psit_nG[4] for kpt in c_mol.wfs.kpt_u]
import sys from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations sys.path.append("../..") from __init__ import AnharmonicModes slab = fcc111('Al', size=(2, 2, 2), vacuum=3.0) CH3 = molecule('CH3') add_adsorbate(slab, CH3, 3.0, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Al' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) dyn = QuasiNewton(slab, trajectory='relax.traj') dyn.run(fmax=0.01) vib = Vibrations(slab, indices=[8, 9, 10, 11]) vib.run() vib.summary() vib.write_mode() print('\n >> Anharmonics <<\n')
def build(): p = OptionParser(usage='%prog [options] [ads@]surf [output file]', version='%prog 0.1', description='Example ads/surf: fcc-CO@2x2Ru0001') p.add_option('-l', '--layers', type='int', default=4, help='Number of layers.') p.add_option('-v', '--vacuum', type='float', default=5.0, help='Vacuum.') p.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=['sc', 'fcc', 'bcc', 'hcp']) p.add_option('-a', '--lattice-constant', type='float', help='Lattice constant in Angstrom.') p.add_option('--c-over-a', type='float', help='c/a ratio.') p.add_option('--height', type='float', help='Height of adsorbate over surface.') p.add_option('--distance', type='float', help='Distance between adsorbate and nearest surface atoms.') p.add_option('-M', '--magnetic-moment', type='float', default=0.0, help='Magnetic moment.') p.add_option('-G', '--gui', action='store_true', help="Pop up ASE's GUI.") p.add_option('-P', '--python', action='store_true', help="Write Python script.") opt, args = p.parse_args() if not 1 <= len(args) <= 2: p.error("incorrect number of arguments") if '@' in args[0]: ads, surf = args[0].split('@') else: ads = None surf = args[0] if surf[0].isdigit(): i1 = surf.index('x') n = int(surf[:i1]) i2 = i1 + 1 while surf[i2].isdigit(): i2 += 1 m = int(surf[i1 + 1:i2]) surf = surf[i2:] else: n = 1 m = 1 if surf[-1].isdigit(): if surf[1].isdigit(): face = surf[1:] surf = surf[0] else: face = surf[2:] surf = surf[:2] else: face = None Z = atomic_numbers[surf] state = reference_states[Z] if opt.crystal_structure: x = opt.crystal_structure else: x = state['symmetry'] if opt.lattice_constant: a = opt.lattice_constant else: a = estimate_lattice_constant(surf, x, opt.c_over_a) script = ['from ase.build import ', 'vac = %r' % opt.vacuum, 'a = %r' % a] if x == 'fcc': if face is None: face = '111' slab = fcc111(surf, (n, m, opt.layers), a, opt.vacuum) script[0] += 'fcc111' script += ['slab = fcc111(%r, (%d, %d, %d), a, vac)' % (surf, n, m, opt.layers)] r = a / np.sqrt(2) / 2 elif x == 'bcc': if face is None: face = '110' if face == '110': slab = bcc110(surf, (n, m, opt.layers), a, opt.vacuum) elif face == '100': slab = bcc100(surf, (n, m, opt.layers), a, opt.vacuum) script[0] += 'bcc' + face script += ['slab = bcc%s(%r, (%d, %d, %d), a, vac)' % (face, surf, n, m, opt.layers)] r = a * np.sqrt(3) / 4 elif x == 'hcp': if face is None: face = '0001' if opt.c_over_a is None: c = np.sqrt(8 / 3.0) * a else: c = opt.c_over_a * a slab = hcp0001(surf, (n, m, opt.layers), a, c, opt.vacuum) script[0] += 'hcp0001' script += ['c = %r * a' % (c / a), 'slab = hcp0001(%r, (%d, %d, %d), a, c, vac)' % (surf, n, m, opt.layers)] r = a / 2 elif x == 'diamond': if face is None: face = '111' slab = diamond111(surf, (n, m, opt.layers), a, opt.vacuum) script[0] += 'diamond111' script += ['slab = diamond111(%r, (%d, %d, %d), a, vac)' % (surf, n, m, opt.layers)] r = a * np.sqrt(3) / 8 else: raise NotImplementedError magmom = opt.magnetic_moment if magmom is None: magmom = {'Ni': 0.6, 'Co': 1.2, 'Fe': 2.3}.get(surf, 0.0) slab.set_initial_magnetic_moments([magmom] * len(slab)) if magmom != 0: script += ['slab.set_initial_magnetic_moments([%r] * len(slab))' % magmom] slab.pbc = 1 script += ['slab.pbc = True'] name = '%dx%d%s%s' % (n, m, surf, face) if ads: site = 'ontop' if '-' in ads: site, ads = ads.split('-') name = site + '-' + ads + '@' + name symbols = string2symbols(ads) nads = len(symbols) if nads == 1: script[:0] = ['from ase import Atoms'] script += ['ads = Atoms(%r)' % ads] ads = Atoms(ads) else: script[:0] = ['from ase.build import molecule'] script += ['ads = molecule(%r)' % ads] ads = molecule(ads) add_adsorbate(slab, ads, 0.0, site) d = opt.distance if d is None: d = r + covalent_radii[ads[0].number] / 2 h = opt.height if h is None: R = slab.positions y = ((R[:-nads] - R[-nads])**2).sum(1).min()**0.5 h = (d**2 - y**2)**0.5 else: assert opt.distance is None slab.positions[-nads:, 2] += h script[1] += ', add_adsorbate' script += ['add_adsorbate(slab, ads, %r, %r)' % (h, site)] if len(args) == 2: write(args[1], slab) script[1:1] = ['from ase.io import write'] script += ['write(%r, slab)' % args[1]] elif not opt.gui: write(name + '.traj', slab) script[1:1] = ['from ase.io import write'] script += ['write(%r, slab)' % (name + '.traj')] if opt.gui: view(slab) script[1:1] = ['from ase.visualize import view'] script += ['view(slab)'] if opt.python: print('\n'.join(script))
write(name + '.png', slab, show_unit_cell=2, radii=radii[name[:3]], scale=10) for name in surfaces: f = getattr(surface, name) for kwargs in [{}, {'orthogonal': False}, {'orthogonal': True}]: print(name, kwargs) try: slab = f(symbols[name[:3]], size=(3, 4, 5), vacuum=4, **kwargs) except (TypeError, NotImplementedError): continue try: for site in slab.info['adsorbate_info']['sites']: if site.endswith('bridge'): h = 1.5 else: h = 1.2 surface.add_adsorbate(slab, adsorbates.get(site, 'F'), h, site) except KeyError: pass if kwargs.get('orthogonal', None): name += 'o' save(name, slab) for site, symbol in adsorbates.items(): write('%s-site.png' % site, Atoms(symbol), radii=1.08, scale=10) fcc111_primitive = fcc111("Ag", (1, 1, 3)) fcc111_root = root_surface(fcc111_primitive, 27) save("fcc111_root", fcc111_root)
from ase import Atom, Atoms from ase.build import bulk, fcc100, add_adsorbate, add_vacuum from ase.calculators.vasp import Vasp from ase.calculators.kim.kim import KIM from ase.calculators.qmmm import ForceQMMM, RescaledCalculator from ase.constraints import StrainFilter from ase.optimize import LBFGS from ase.visualize import view atoms = bulk("Pd", "fcc", a=3.5, cubic=True) atoms.calc = KIM("MEAM_LAMMPS_JeongParkDo_2018_PdMo__MO_356501945107_000") opt = LBFGS(StrainFilter(atoms), logfile=None) opt.run(0.03, steps=30) length = atoms.cell.cellpar()[0] atoms = fcc100("Pd", (2,2,5), a=length, vacuum=10, periodic=True) add_adsorbate(atoms, Atoms([Atom("Mo")]), 1.2) qm_mask = [len(atoms)-1, len(atoms)-2] qm_calc = Vasp(directory="./qmmm") mm_calc = KIM("MEAM_LAMMPS_JeongParkDo_2018_PdMo__MO_356501945107_000") mm_calc = RescaledCalculator(mm_calc, 1, 1, 1, 1) qmmm = ForceQMMM(atoms, qm_mask, qm_calc, mm_calc, buffer_width=3) qmmm.initialize_qm_buffer_mask(atoms) atoms.pbc=True atoms.calc = qmmm print(atoms.get_forces())
def get_site(self, plot_voronoi_sites=False): """Return primaty (top, bridge, hollow, 4fold) and secondary (chemical elements in close environment) site designation""" if self.dissociated: return 'dissociated', '' if self.is_desorbed(): return 'desorbed', '' if self.is_subsurface(): return 'subsurface', '' C0 = self.B[-1:] * (3, 3, 1) ads_pos = C0.positions[4] C = self.B.copy() * (3, 3, 1) # Use top layer and adsorbate to map sites Dict = self.get_site_dict(ads_pos[:2]) primary_site = None dis = self.B.get_cell()[0][0] Kind = None values = [ np.linalg.norm(ads_pos[:2] - d['pos'][:2]) for d in list(Dict.values()) ] if len(values) == 0: return 'N/A', '' idx = np.argmin(values) dis = values[idx] kind = list(Dict.keys())[idx] self.ipos = Dict[kind]['ipos'] primary_site = kind.split('_')[0] if plot_voronoi_sites: # View sampled sites X = self.B.copy() X = X * (3, 3, 1) del X[-1] for pos in Dict.values(): add_adsorbate(X, 'X', position=(pos['pos'][:2]), height=0.2) view(X) if primary_site == 'top': site_type = Dict[kind]['sym'] if primary_site == 'bridge': site_type = Dict[kind]['sym'] + '|' + self.get_under_bridge() elif primary_site == 'hollow': site_type = Dict[kind]['sym'] + '|' + self.get_under_hollow() elif primary_site == '4fold': site_type = Dict[kind]['sym'] if dis > 0.5: primary_site += '-tilt' print('Warning: A strong site match could not be found!') print(' structure labeled as {}'.format(primary_site)) return primary_site, site_type
arrangements are established automatically. Predict outcomes of symmetry operations and form a sequence before attempting the operations to reduce computational time. ''' from carmm.examples.data.model_gen import get_example_slab from ase.build import molecule, add_adsorbate from ase import Atom from carmm.analyse.bonds import compare_structures from carmm.build.neb import switch_indices, switch_all_indices # Work case for automatic neb setup # initial geometry initial = get_example_slab() ad1 = molecule("CH3O") ad1.rotate(-90, 'x') add_adsorbate(initial, ad1, height=2.0) bridge = initial[12].position + ( (initial[13].position - initial[12].position) / 2) ad2 = Atom("H", position=bridge) initial += ad2 # final geometry final = get_example_slab() bridge2 = initial[13].position + ( (initial[16].position - initial[13].position) / 2) ad3 = molecule("CH3OH") ad3.rotate(60, 'x') add_adsorbate(final, ad3, 3.0, position=(bridge2[0], bridge[1])) # scramble indices to ensure compare_structures works final = switch_indices(final, 18, 19)
slab.set_calculator(calc1) dyn = QuasiNewton(slab, trajectory="slab.traj") dyn.run(fmax=0.05) e_slab = slab.get_potential_energy() os.system("rm dftb_in.hsd") molecule = Atoms("2N", positions=[(0.0, 0.0, 0.0), (0.0, 0.0, d)]) calc2 = Dftb( label="n2", Hamiltonian_MaxAngularMomentum_="", Hamiltonian_MaxAngularMomentum_N='"p"', Hamiltonian_SCC="YES" ) molecule.set_calculator(calc2) dyn = QuasiNewton(molecule, trajectory="n2.traj") dyn.run(fmax=0.05) e_N2 = molecule.get_potential_energy() slab2 = slab add_adsorbate(slab2, molecule, h, "ontop") constraint = FixAtoms(mask=[a.symbol != "N" for a in slab2]) slab2.set_constraint(constraint) calc3 = Dftb( label="slab2", kpts=[2, 2, 1], Hamiltonian_MaxAngularMomentum_="", Hamiltonian_MaxAngularMomentum_N='"p"', Hamiltonian_MaxAngularMomentum_Ni='"d"', Hamiltonian_SCC="YES", ) slab2.set_calculator(calc3) dyn = QuasiNewton(slab2, trajectory="slab2.traj") dyn.run(fmax=0.05) adsorption_energy = e_slab + e_N2 - slab2.get_potential_energy()
label = 'test' # for integration with AMPTorch module forcetraining = True # for integration with AMPTorch module. # if forcetraining is set to False, it will drop the derivatives of fingerprints. cores = 1 # Define Gs variables for fps. Gs = {} Gs["G2_etas"] = np.logspace(np.log10(0.05), np.log10(5.0), num=10) Gs["G2_rs_s"] = [0] * 10 Gs["G4_etas"] = np.logspace(np.log10(0.005), np.log10(0.5), num=4) Gs["G4_zetas"] = [1.0] Gs["G4_gammas"] = [+1.0, -1.0] Gs["cutoff"] = 6.5 # Generate ase.Atoms objects. slab = fcc111('Al', size=(2, 2, 4)) add_adsorbate(slab, 'H', 1.5, 'ontop') slab.center(vacuum=10.0, axis=2) # Define elements to calculate fps for elements = ['Al', 'H'] # Step 1: obtain output from cffi as cffi_out traj, calculated, cffi_out = make_simple_nn_fps(slab, Gs, elements=elements, label=label) # Step 2: reorganize into AMP input format fps, fp_primes = convert_simple_nn_fps(traj, Gs, cffi_out, forcetraining, cores, save=False) # Print the output if needed. print(fps) print(fp_primes)
middle = atoms.positions[upper_layer_idx, :2].max(axis=0) / 2 # the dissociating oxygen... fake some dissociation curve gas_dist = 1.1 max_height = 8. min_height = 1. max_dist = 6 # running index for the bonds index = len(atoms) for i, x in enumerate(np.linspace(0, 1.5, 6)): height = (max_height - min_height) * np.exp(-2 * x) + min_height d = np.exp(1.5 * x) / np.exp(1.5**2) * max_dist + gas_dist pos = middle + [0, d / 2] add_adsorbate(atoms, 'O', height=height, position=pos) pos = middle - [0, d / 2] add_adsorbate(atoms, 'O', height=height, position=pos) transmittances += [x / 2] * 2 # we want bonds for the first two molecules if i < 2: bonded_atoms.append([len(atoms) - 1, len(atoms) - 2]) textures = ['ase3' for a in atoms] # add some semi-transparent bath (only in x/y direction for this example) cell = atoms.cell idx = [a.index for a in atoms if a.symbol == 'Pt']
# creates: io1.png io2.png io3.png from ase import Atoms from ase.build import fcc111, add_adsorbate from ase.io import write, read adsorbate = Atoms('CO') adsorbate[1].z = 1.1 a = 3.61 slab = fcc111('Cu', (2, 2, 3), a=a, vacuum=7.0) add_adsorbate(slab, adsorbate, 1.8, 'ontop') write('io1.png', slab * (3, 3, 1), rotation='10z,-80x') write('io2.pov', slab * (3, 3, 1), rotation='10z,-80x', transparent=False, display=False, run_povray=True) d = a / 2**0.5 write('io3.pov', slab * (2, 2, 1), bbox=(d, 0, 3 * d, d * 3**0.5), transparent=False, display=False, run_povray=True) write('slab.xyz', slab) a = read('slab.xyz') a.get_cell() a.get_pbc()
from ase.build import fcc211, add_adsorbate from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton from ase.neb import NEBTools from ase.autoneb import AutoNEB # Pt atom adsorbed in a hollow site: slab = fcc211('Pt', size=(3, 2, 2), vacuum=4.0) add_adsorbate(slab, 'Pt', 0.5, (-0.1, 2.7)) # Fix second and third layers: slab.set_constraint(FixAtoms(range(6, 12))) # Use EMT potential: slab.set_calculator(EMT()) # Initial state: qn = QuasiNewton(slab, trajectory='neb000.traj') qn.run(fmax=0.05) # Final state: slab[-1].x += slab.get_cell()[0, 0] slab[-1].y += 2.8 qn = QuasiNewton(slab, trajectory='neb001.traj') qn.run(fmax=0.05) # Stops PermissionError on Win32 for access to # the traj file that remains open. del qn
import sys from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations sys.path.append("..") from __init__ import AnharmonicModes slab = fcc111('Au', size=(2, 2, 2), vacuum=4.0) H = molecule('H') add_adsorbate(slab, H, 3.0, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Au' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) QuasiNewton(slab).run(fmax=0.001) vib = Vibrations(slab, indices=[8]) vib.run() vib.summary() vib.clean() AM = AnharmonicModes( vibrations_object=vib, settings={
from ase.build import fcc100, add_adsorbate from ase.constraints import FixAtoms, FixedPlane from ase.calculators.emt import EMT from ase.optimize import QuasiNewton # 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) # Make sure the structure is correct: #from ase.visualize import view #view(slab) # Fix second and third layers: mask = [atom.tag > 1 for atom in slab] #print(mask) fixlayers = FixAtoms(mask=mask) # Constrain the last atom (Au atom) to move only in the yz-plane: plane = FixedPlane(-1, (1, 0, 0)) slab.set_constraint([fixlayers, plane]) # Use EMT potential: slab.set_calculator(EMT()) for i in range(5): qn = QuasiNewton(slab, trajectory='mep%d.traj' % i) qn.run(fmax=0.05)
def add_graphene_layer( slab, graphene_units=1, graph_surf_d=3.0, graph_bond_d_real=1.4237, ): """ Add graphene layer above surface of hexagonal unit cell slab. Args: slab: graphene_units: graph_surf_d: graph_bond_d_real: """ #| - add_graphene_layer slab = copy.deepcopy(slab) # num_graph_units = graphene_units + 1 graphene_units = int(graphene_units) num_graph_units = int(graphene_units) ngu = num_graph_units num_graph_bond_lengths = (2. + 1.) * ngu v1 = slab.cell[0] v2 = slab.cell[1] angle = angle_between(v1, v2) angle = math.degrees(angle) # print("Angle between lattice vectors: " + str(angle)) mag1 = np.linalg.norm(v1) mag2 = np.linalg.norm(v2) assert round(mag1) == round(mag2) graph_bond_d = mag1 / num_graph_bond_lengths xy_cell = slab.cell[0:2, 0:2] # x and y components of unit cell x_unit_v = xy_cell[0] y_unit_v = xy_cell[1] x_unit_v = x_unit_v / np.linalg.norm(x_unit_v) y_unit_v = y_unit_v / np.linalg.norm(y_unit_v) #| - STRAIN tmp = mag1 / num_graph_bond_lengths strain = 100. * (graph_bond_d_real - tmp) / graph_bond_d_real print("Strain: " + str(strain)) #__| patt_cnt_x = 0 patt_cnt_y = 0 C_pos_lst = [] for y_ind in range(graphene_units * 3): patt_cnt_x = patt_cnt_y for x_ind in range(graphene_units * 3): if patt_cnt_x == 0 or patt_cnt_x == 1: pos_x = x_ind * graph_bond_d * x_unit_v pos_y = y_ind * graph_bond_d * y_unit_v pos_i = np.array(pos_x) + np.array(pos_y) pos_i = np.append(pos_i, 0.) C_pos_lst.append(pos_i) # atom_cent = (origin[0] + x_ind * graph_bond_d # - graph_bond_d * y_ind * y_unit_v[0], origin[1] + y_ind # * graph_bond_d) add_adsorbate( slab, "C", graph_surf_d, position=(pos_i[0], pos_i[1]), ) patt_cnt_x += 1 elif patt_cnt_x == 2: patt_cnt_x = 0 if patt_cnt_y == 0: patt_cnt_y = 2 continue if patt_cnt_y == 2: patt_cnt_y = 1 continue elif patt_cnt_y == 1: patt_cnt_y = 0 continue C_pos_lst = np.array(C_pos_lst) return (slab)
import sys from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations sys.path.append("..") from __init__ import AnharmonicModes slab = fcc111('Au', size=(2, 2, 2), vacuum=4.0) H = molecule('H') add_adsorbate(slab, H, 3.0, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Au' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) QuasiNewton(slab).run(fmax=0.001) vib = Vibrations(slab, indices=[8]) vib.run() vib.summary() vib.clean() AM = AnharmonicModes(vibrations_object=vib, settings={ 'plot_mode': True, })
import sys sys.path.append("..") from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations from __init__ import AnharmonicModes slab = fcc111('Al', size=(2, 2, 2), vacuum=3.0) CH3 = molecule('CH3') add_adsorbate(slab, CH3, 2.5, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Al' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) dyn = QuasiNewton(slab, logfile='/dev/null') dyn.run(fmax=0.05) vib = Vibrations(slab, indices=[8, 9, 10, 11]) vib.run() vib.summary(log='/dev/null') vib.clean() AM = AnharmonicModes(vibrations_object=vib) rot_mode = AM.define_rotation( basepos=[0., 0., -1.], branch=[9, 10, 11],
from ase.build import fcc100, add_adsorbate from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton # 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) # Make sure the structure is correct: #view(slab) # Fix second and third layers: mask = [atom.tag > 1 for atom in slab] #print(mask) slab.set_constraint(FixAtoms(mask=mask)) # Use EMT potential: slab.set_calculator(EMT()) # Initial state: qn = QuasiNewton(slab, trajectory='initial.traj') qn.run(fmax=0.05) # Final state: slab[-1].x += slab.get_cell()[0, 0] / 2 qn = QuasiNewton(slab, trajectory='final.traj') qn.run(fmax=0.05)
from ase.build import surface, fcc100, add_adsorbate from ase.constraints import FixAtoms from ase.io import read import numpy as np from ase.visualize import view #bulk = read('../bulk/converged_bulk.traj') #a=3.89 #a = np.linalg.norm(bulk.cell[0]) vac = 6 #atoms = fcc100('Pd', (2,2,4), a=a, vacuum=10) atoms = fcc100('Pd', (2, 2, {l}), vacuum=vac) nitrate = read('nitrate.xyz') add_adsorbate(atoms, nitrate, 1.5, 'ontop') c = FixAtoms(mask=[a.z < vac + 2 for a in atoms]) atoms.set_constraint(c) #atoms *= (2,2,1) atoms.write('structure.traj')
# import calculator and set potential from ase.calculators.eam import EAM import os pot_file = os.environ.get('LAMMPS_POTENTIALS') + '/Al_zhou.eam.alloy' zhou = EAM(potential=pot_file) #create structure as FCC surface with addsorbate from ase.build import fcc111, add_adsorbate slab = fcc111('Al', size=(2, 2, 3)) add_adsorbate(slab, 'Al', 2, 'hcp') slab.center(vacuum=5.0, axis=2) #view and set calculator from ase.visualize import view view(slab, viewer='x3d') slab.set_calculator(zhou) slab.get_potential_energy() print(slab.get_calculator()) print(slab.get_potential_energy()) #relax structure from ase.optimize import BFGS dyn = BFGS(slab) dyn.run(fmax=0.0001) #make second endpoint structure, add adatom and relax slab_2 = fcc111('Al', size=(2, 2, 3)) add_adsorbate(slab_2, 'Al', 2, 'fcc') slab_2.center(vacuum=5.0, axis=2) slab_2.set_calculator(EAM(potential=pot_file))
from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixAtoms from ase.optimize import QuasiNewton from ase.build import fcc111, add_adsorbate h = 1.85 d = 1.10 slab = fcc111('Cu', size=(4, 4, 2), vacuum=10.0) slab.set_calculator(EMT()) e_slab = slab.get_potential_energy() molecule = Atoms('2N', positions=[(0., 0., 0.), (0., 0., d)]) molecule.set_calculator(EMT()) e_N2 = molecule.get_potential_energy() add_adsorbate(slab, molecule, h, 'ontop') constraint = FixAtoms(mask=[a.symbol != 'N' for a in slab]) slab.set_constraint(constraint) dyn = QuasiNewton(slab, trajectory='N2Cu.traj') dyn.run(fmax=0.05) print('Adsorption energy:', e_slab + e_N2 - slab.get_potential_energy())
for st in sites: ads_slab = slab.copy() par, chi = ads.split('-') print('Now working on system with the following spec:') print('metal: {} ads: {}, site: {}\n'.format(i, ads, st)) h_z = get_height(i, par, st) #add_adsorbate(ads_slab, par, h_z, st) #if chi == 'H' and not par == 'S': # add_adsorbate(ads_slab, chi, h_z+1.05, st) #elif chi == 'H' and par == 'S': # add_adsorbate(ads_slab, chi, h_z+1.30, st) if ads == 'C-H': molecule = Atoms('CH', positions=[(0., 0., 0.), (0., 0., 1.1)]) add_adsorbate(ads_slab, molecule, h_z, st) elif ads == 'O-H': molecule = Atoms('OH', positions=[(0., 0., 0.), (0., 0., 0.95)]) add_adsorbate(ads_slab, molecule, h_z, st) elif ads == 'N-H': molecule = Atoms('NH', positions=[(0., 0., 0.), (0., 0., 1.05)]) add_adsorbate(ads_slab, molecule, h_z, st) elif ads == 'S-H': molecule = Atoms('SH', positions=[(0., 0., 0.), (0., 0., 1.25)]) add_adsorbate(ads_slab, molecule, h_z, st)
import sys from ase.build import molecule, fcc111, add_adsorbate from ase.optimize import QuasiNewton from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.vibrations import Vibrations sys.path.append("../..") from __init__ import AnharmonicModes slab = fcc111('Au', size=(2, 2, 2), vacuum=4.0) H = molecule('H') add_adsorbate(slab, H, 3.0, 'bridge') constraint = FixAtoms(mask=[a.symbol == 'Au' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) dyn = QuasiNewton(slab) dyn.run(fmax=0.01) # Running vibrational analysis vib = Vibrations(slab, indices=[8]) vib.run() vib.summary() # Here the number of initial sampling points are increased such
INCAR_bare['MAGMOM'][x_list[0]:(x_list[-1]+1)] = [-5.0, -5.0, 5.0, -5.0, 5.0, 5.0, -5.0, 5.0, 5.0, -5.0, -5.0, 5.0] # activate if AFM """ INCAR_bare.write_file(file_path + 'INCAR') KPOINTS.write_file(file_path + '/KPOINTS') POTCAR_bare.write_file(file_path + 'POTCAR') write_vasp(file_path + 'POSCAR', slab) # jobscript copy job_file = os.getcwd() + '/jobscript_vasp.sh' shutil.copy(job_file, file_path) ###### adsorbate modeling ###### for ads_idx in range(len(adsorbates)): INCAR = Incar.from_file(file_path + 'INCAR') createFolder(file_path + '/' + adsorbate_names[ads_idx]) # Put AFM, def in the path if required add_adsorbate(slab = slab, adsorbate = adsorbates[ads_idx], height = 2.0, position = (slab[metal_index].position[0], slab[metal_index].position[0])) elements = [] for element in slab.get_chemical_symbols(): if element not in elements: elements.append(element) for n_atom_ads in range(len(adsorbates[ads_idx])): INCAR['MAGMOM'].append(0.6) mag_dic = dict(zip(slab.get_chemical_symbols(), INCAR['MAGMOM'])) INCAR['MAGMOM'] = [mag_dic[x] for x in sorted(slab.get_chemical_symbols())] """ AFM_adsorbate modeling
try: opts.size = tuple(map(int, opts.size.strip().split(','))) except: print("Error parsing size as three comma-separated integers") sys.exit() slab=fcc111(opts.electrode, opts.size) # Needed to prevent multilayer formation slab.info['adsorbate_info']['top layer atom index'] = len(slab.positions)-1 xyz = Parser(opts,opts.infile[0]) xyz.parseZmatrix() if opts.tilt > 0: xyz.zmat.rotateAboutAxis(opts.tiltaxis,opts.tilt) mol = xyz.getZmat() print(mol) for i in range(1,opts.size[0]-1,2): add_adsorbate(slab,mol,opts.height,position,offset=[0,i],mol_index=0) firstmol = len(slab.positions) for n in range(2,opts.size[0]-1,2): add_adsorbate(slab,mol,opts.height,position,offset=[n,i],mol_index=0) if opts.topcontact: top = fcc111(opts.electrode, opts.size) del(slab.info['adsorbate_info']['top layer atom index']) #slab.info['adsorbate_info']['top layer atom index'] = firstmol add_adsorbate(slab,top,opts.height,position,offset=[0,0],mol_index=0) write(opts.infile[0][:-4]+'_SAM.png',slab,rotation='80x,180z') write(opts.infile[0][:-4]+'_SAM.xyz',slab)
def test_thermochemistry(): """Tests of the major methods (HarmonicThermo, IdealGasThermo, CrystalThermo) from the thermochemistry module.""" # Ideal gas thermo. atoms = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(atoms).run(fmax=0.01) energy = atoms.get_potential_energy() vib = Vibrations(atoms, name='idealgasthermo-vib') vib.run() vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear', atoms=atoms, symmetrynumber=2, spin=0, potentialenergy=energy) thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.) # Harmonic thermo. atoms = fcc100('Cu', (2, 2, 2), vacuum=10.) atoms.set_calculator(EMT()) add_adsorbate(atoms, 'Pt', 1.5, 'hollow') atoms.set_constraint( FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Cu'])) QuasiNewton(atoms).run(fmax=0.01) vib = Vibrations( atoms, name='harmonicthermo-vib', indices=[atom.index for atom in atoms if atom.symbol != 'Cu']) vib.run() vib.summary() vib_energies = vib.get_energies() thermo = HarmonicThermo(vib_energies=vib_energies, potentialenergy=atoms.get_potential_energy()) thermo.get_helmholtz_energy(temperature=298.15) # Crystal thermo. atoms = bulk('Al', 'fcc', a=4.05) calc = EMT() atoms.set_calculator(calc) energy = atoms.get_potential_energy() # Phonon calculator N = 7 ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05) ph.run() ph.read(acoustic=True) phonon_energies, phonon_DOS = ph.dos(kpts=(4, 4, 4), npts=30, delta=5e-4) thermo = CrystalThermo(phonon_energies=phonon_energies, phonon_DOS=phonon_DOS, potentialenergy=energy, formula_units=4) thermo.get_helmholtz_energy(temperature=298.15) # Hindered translator / rotor. # (Taken directly from the example given in the documentation.) vibs = np.array([ 3049.060670, 3040.796863, 3001.661338, 2997.961647, 2866.153162, 2750.855460, 1436.792655, 1431.413595, 1415.952186, 1395.726300, 1358.412432, 1335.922737, 1167.009954, 1142.126116, 1013.918680, 803.400098, 783.026031, 310.448278, 136.112935, 112.939853, 103.926392, 77.262869, 60.278004, 25.825447 ]) vib_energies = vibs / 8065.54429 # Convert to eV from cm^-1. trans_barrier_energy = 0.049313 # eV rot_barrier_energy = 0.017675 # eV sitedensity = 1.5e15 # cm^-2 rotationalminima = 6 symmetrynumber = 1 mass = 30.07 # amu inertia = 73.149 # amu Ang^-2 thermo = HinderedThermo(vib_energies=vib_energies, trans_barrier_energy=trans_barrier_energy, rot_barrier_energy=rot_barrier_energy, sitedensity=sitedensity, rotationalminima=rotationalminima, symmetrynumber=symmetrynumber, mass=mass, inertia=inertia) helmholtz = thermo.get_helmholtz_energy(temperature=298.15) target = 1.593 # Taken from documentation example. assert (helmholtz - target) < 0.001
from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLengths from ase.optimize import BFGS from ase.build import fcc111, add_adsorbate for wrap in [False, True]: zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.set_calculator(calc) if wrap: # Remap into the cell so bond is actually wrapped: slab.set_scaled_positions(slab.get_scaled_positions() % 1.0) constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax_%d.traj' % wrap) dyn.run(fmax=0.05) assert abs(slab.get_distance(-3, -2, mic=1) - d0) < 1e-9 assert abs(slab.get_distance(-3, -1, mic=1) - d1) < 1e-9
from ase.build import fcc111, add_adsorbate from ase.atoms import Atoms from ase.build import bulk from ase.visualize import view from blase.tools import get_bondpairs, write_blender bulk = bulk('Pt') bulk.write('pt.in') adsorbate = Atoms('CO') adsorbate[1].z = 1.1 atoms = fcc111('Pt', (2, 2, 3), a=3.96, vacuum=7.0) add_adsorbate(atoms, adsorbate, 1.8, 'ontop') # atoms = atoms*[5, 5, 1] # view(atoms) kwargs = {'show_unit_cell': 0, 'radii': 0.6, 'bond_cutoff': 1.0, 'display': True, 'make_real': True, 'outfile': 'figs/pt-111-co', } write_blender(atoms, **kwargs)
from ase.optimize import QuasiNewton from ase.io import write # Find the initial and final states for the reaction. # Set up a (4 x 4) two layer slab of Cu: slab = fcc111('Cu',size=(4,4,2)) slab.set_pbc((1,1,0)) # Initial state. # Add the N2 molecule oriented at 60 degrees: d = 1.10 # N2 bond length N2mol = Atoms('N2',positions=[[0.0,0.0,0.0],[0.5*3**0.5*d,0.5*d,0.0]]) add_adsorbate(slab,N2mol,height=1.0,position='fcc') # Use the EMT calculator for the forces and energies: slab.set_calculator(EMT()) # We don't want to worry about the Cu degrees of freedom, # so fix these atoms: mask = [atom.symbol == 'Cu' for atom in slab] slab.set_constraint(FixAtoms(mask=mask)) # Relax the structure relax = QuasiNewton(slab) relax.run(fmax=0.05) print('initial state:', slab.get_potential_energy()) write('N2.traj', slab)