def fcc211(symbol, size, a=None, vacuum=None, orthogonal=True): """FCC(211) surface. Does not currently support special adsorption sites. Currently only implemented for *orthogonal=True* with size specified as (i, j, k), where i, j, and k are number of atoms in each direction. i must be divisible by 3 to accommodate the step width. """ if not orthogonal: raise NotImplementedError('Only implemented for orthogonal ' 'unit cells.') if size[0] % 3 != 0: raise NotImplementedError('First dimension of size must be ' 'divisible by 3.') atoms = FaceCenteredCubic(symbol, directions=[[1, -1, -1], [0, 2, -2], [2, 1, 1]], miller=(None, None, (2, 1, 1)), latticeconstant=a, size=(1, 1, 1), pbc=True) z = (size[2] + 1) // 2 atoms = atoms.repeat((size[0] // 3, size[1], z)) if size[2] % 2: # Odd: remove bottom layer and shrink cell. remove_list = [atom.index for atom in atoms if atom.z < atoms[1].z] del atoms[remove_list] dz = atoms[0].z atoms.translate((0., 0., -dz)) atoms.cell[2][2] -= dz atoms.cell[2] = 0.0 atoms.pbc[2] = False if vacuum: atoms.center(vacuum, axis=2) # Renumber systematically from top down. orders = [(atom.index, round(atom.x, 3), round(atom.y, 3), -round(atom.z, 3), atom.index) for atom in atoms] orders.sort(key=itemgetter(3, 1, 2)) newatoms = atoms.copy() for index, order in enumerate(orders): newatoms[index].position = atoms[order[0]].position.copy() # Add empty 'sites' dictionary for consistency with other functions newatoms.info['adsorbate_info'] = {'sites': {}} return newatoms
def fcc211(symbol, size, a=None, vacuum=None, orthogonal=True): """FCC(211) surface. Does not currently support special adsorption sites. Currently only implemented for *orthogonal=True* with size specified as (i, j, k), where i, j, and k are number of atoms in each direction. i must be divisible by 3 to accommodate the step width. """ if not orthogonal: raise NotImplementedError('Only implemented for orthogonal ' 'unit cells.') if size[0] % 3 != 0: raise NotImplementedError('First dimension of size must be ' 'divisible by 3.') atoms = FaceCenteredCubic(symbol, directions=[[1, -1, -1], [0, 2, -2], [2, 1, 1]], miller=(None, None, (2, 1, 1)), latticeconstant=a, size=(1, 1, 1), pbc=True) z = (size[2] + 1) // 2 atoms = atoms.repeat((size[0] // 3, size[1], z)) if size[2] % 2: # Odd: remove bottom layer and shrink cell. remove_list = [atom.index for atom in atoms if atom.z < atoms[1].z] del atoms[remove_list] dz = atoms[0].z atoms.translate((0., 0., -dz)) atoms.cell[2][2] -= dz atoms.cell[2] = 0.0 atoms.pbc[1] = False if vacuum: atoms.center(vacuum, axis=2) # Renumber systematically from top down. orders = [(atom.index, round(atom.x, 3), round(atom.y, 3), -round(atom.z, 3), atom.index) for atom in atoms] orders.sort(key=itemgetter(3, 1, 2)) newatoms = atoms.copy() for index, order in enumerate(orders): newatoms[index].position = atoms[order[0]].position.copy() return newatoms
def test_center(): # flake8: noqa "Test that atoms.center() works when adding vacuum ()" import numpy as np from math import pi, sqrt, cos from ase import data from ase.lattice.cubic import FaceCenteredCubic def checkang(a, b, phi): "Check the angle between two vectors." cosphi = np.dot(a, b) / sqrt(np.dot(a, a) * np.dot(b, b)) assert np.abs(cosphi - cos(phi)) < 1e-10 symb = "Cu" Z = data.atomic_numbers[symb] a0 = data.reference_states[Z]['a'] # (100) oriented block atoms = FaceCenteredCubic(size=(5, 5, 5), symbol="Cu", pbc=(1, 1, 0)) assert len(atoms) == 5 * 5 * 5 * 4 c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 2) checkang(c[1], c[2], pi / 2) assert np.abs(5 * a0 - c[2, 2]) < 1e-10 # Add vacuum in one direction vac = 10.0 atoms.center(axis=2, vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 2) checkang(c[1], c[2], pi / 2) assert np.abs(4.5 * a0 + 2 * vac - c[2, 2]) < 1e-10 # Add vacuum in all directions vac = 4.0 atoms.center(vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 2) checkang(c[1], c[2], pi / 2) assert np.abs(4.5 * a0 + 2 * vac - c[0, 0]) < 1e-10 assert np.abs(4.5 * a0 + 2 * vac - c[1, 1]) < 1e-10 assert np.abs(4.5 * a0 + 2 * vac - c[2, 2]) < 1e-10 # Now a general unit cell atoms = FaceCenteredCubic(size=(5, 5, 5), directions=[[1, 0, 0], [0, 1, 0], [1, 0, 1]], symbol="Cu", pbc=(1, 1, 0)) assert len(atoms) == 5 * 5 * 5 * 2 c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 4) checkang(c[1], c[2], pi / 2) assert np.abs(2.5 * a0 - c[2, 2]) < 1e-10 # Add vacuum in one direction vac = 10.0 atoms.center(axis=2, vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 4) checkang(c[1], c[2], pi / 2) assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10 # Recenter without specifying vacuum atoms.center() c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 4) checkang(c[1], c[2], pi / 2) assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10 a2 = atoms.copy() # Add vacuum in all directions vac = 4.0 atoms.center(vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 4) checkang(c[1], c[2], pi / 2) assert np.abs(4.5 * a0 + 2 * vac - c[1, 1]) < 1e-10 assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10 # One axis at the time: for i in range(3): a2.center(vacuum=vac, axis=i) assert abs(atoms.positions - a2.positions).max() < 1e-12 assert abs(atoms.cell - a2.cell).max() < 1e-12
def get_structure(self, name, elements, a=None, c=None, l=None): # Check number of elements if name[:3] in ['fcc', 'hcp']: if len(elements) != 1: raise ValueError("Tuple of elements must be of length one") if name[:3] in ['l12', 'l10'] or name[:2] == 'B2': if len(elements) != 2: raise ValueError("Tuple of elements must be of length two") # Get lattice constants if a is None: if name[:2] == 'B2': a = self.get_lattice_constant_a(name[:2], elements) elif name[:3] in ['fcc', 'hcp', 'bcc', 'l12', 'l10']: a = self.get_lattice_constant_a(name[:3], elements) if c is None: if name[:3] in ['hcp', 'l10']: c = self.get_lattice_constant_c(name[:3], elements) # Get size if name in ['fcc', 'hcp', 'bcc', 'l12', 'l10', 'B2']: size = self.properties[name + '_size'] elif name in ['fcc100', 'fcc111', 'hcp0001']: size = self.properties[name + '_size'][:2] + (l, ) # Make structure if name == 'fcc': atoms = FaceCenteredCubic(symbol=elements[0], size=size, latticeconstant=a) elif name == 'hcp': atoms = HexagonalClosedPacked(symbol=elements[0], size=size, directions=[[2, -1, -1, 0], [0, 1, -1, 0], [0, 0, 0, 1]], latticeconstant=(a, c)) elif name == 'bcc': atoms = BodyCenteredCubic(symbol=elements[0], size=size, latticeconstant=a) elif name == 'B2': atoms = B2(symbol=elements, size=size, latticeconstant=a) elif name == 'l12': atoms = L1_2(symbol=elements, size=size, latticeconstant=a) elif name == 'l10': atoms = L1_0(symbol=elements, size=size, latticeconstant=(a, c)) elif name == 'fcc100': atoms = fcc100(symbol=elements[0], size=size, a=a, vacuum=10.0) elif name == 'fcc111': atoms = fcc111(symbol=elements[0], size=size, a=a, vacuum=10.0, orthogonal=True) elif name == 'hcp0001': atoms = hcp0001(symbol=elements[0], size=size, a=a, c=c, vacuum=10.0, orthogonal=True) elif name == 'hcp1010A': raise ValueError("Structure '%s' not supported" % (name, )) atoms = None elif name == 'hcp1010B': raise ValueError("Structure '%s' not supported" % (name, )) atoms = None elif name == 'l12100': n = (l + 1) / 2 atoms = L1_2(symbol=elements, size=(8, 8, n), latticeconstant=a) atoms.set_pbc([True, True, False]) # Remove layers atoms = atoms[atoms.get_positions()[:, 2] > 0.1 * a] # Set vacuum atoms.center(axis=2, vacuum=10.0) elif name == 'l12111': if l % 3 == 0: n = l / 3 c = 0 else: n = l / 3 + 1 c = 3 - l % 3 atoms = L1_2( symbol=elements, size=(8, 4, n), #directions=[[1,-1,0],[1,0,-1],[1,1,1]], latticeconstant=a) directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]], latticeconstant=a) atoms.set_pbc([True, True, False]) # Wrap positions scpos = atoms.get_scaled_positions() scpos[scpos > (1.0 - 1e-12)] = 0.0 atoms.set_scaled_positions(scpos) # Remove layers if c > 0: atoms = atoms[atoms.get_positions()[:, 2] > (c - 0.5) * a / np.sqrt(3.0)] # Set vacuum atoms.center(axis=2, vacuum=10.0) else: raise ValueError("Structure '%s' not supported" % (name, )) return atoms
if rank == 0: print("#"*60) print("GPAW benchmark: Copper Sheet") print(" dimensions: x=%d, y=%d, z=%d" % (x, y, z)) print(" grid spacing: h=%f" % h) print(" Brillouin-zone sampling: kpts=" + str(kpts)) print(" MPI task: %d out of %d" % (rank, size)) print(" using MICs: " + str(use_mic)) print("#"*60) print("") # setup the system atoms = FaceCenteredCubic(directions=[[1,-1,0], [1,1,-2], [1,1,1]], size=(x,y,z), symbol='Cu', pbc=(1,1,0)) #add_vacuum(atoms, 10.0) atoms.center(vacuum=6.0, axis=2) calc = GPAW(h=h, nbands=-20, width=0.2, kpts=kpts, xc='PBE', maxiter=maxiter, txt=txt, eigensolver=RMM_DIIS(niter=2), parallel={'sl_auto': True}, mixer=Mixer(0.1, 5, 100), ) atoms.set_calculator(calc) # execute the run try: atoms.get_potential_energy() except ConvergenceError: pass
symb = "Cu" Z = data.atomic_numbers[symb] a0 = data.reference_states[Z]['a'] # (100) oriented block atoms = FaceCenteredCubic(size=(5,5,5), symbol="Cu", pbc=(1,1,0)) assert len(atoms) == 5*5*5*4 c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(5 * a0 - c[2,2]) < 1e-10 # Add vacuum in one direction vac = 10.0 atoms.center(axis=2, vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(4.5 * a0 + 2* vac - c[2,2]) < 1e-10 # Add vacuum in all directions vac = 4.0 atoms.center(vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(4.5 * a0 + 2* vac - c[0,0]) < 1e-10 assert np.abs(4.5 * a0 + 2* vac - c[1,1]) < 1e-10
from ase.io import write, read from ase import units from ase.lattice.cubic import FaceCenteredCubic from ase.md.verlet import VelocityVerlet from ase.optimize import FIRE from ase.md.langevin import Langevin # Parameters for the Morse potential for Cu D = 0.3429 r0 = 2.866 alpha = 1.3588 atoms = FaceCenteredCubic(latticeconstant=1.5, symbol='Cu', pbc=False, size=(3,3,3)) atoms.center(vacuum=100) atoms.set_calculator(MorsePotential(D=D, alpha=alpha, r0=r0)) dyn = FIRE(atoms, trajectory='relax.traj') dyn.run(fmax=0.01) write('relax.xyz', read('relax.traj@:')) # uncomment this line for Task 2 open('langevin.log', 'w').close() # clean current log file # dyn = VelocityVerlet(atoms, dt=1 * units.fs, # trajectory='md.traj', logfile='md.log') # dyn.run(1000)
from gpaw.mpi import size, rank from gpaw import GPAW, Mixer, ConvergenceError from gpaw.occupations import FermiDirac from gpaw.eigensolvers.rmmdiis import RMMDIIS from gpaw.test import equal # no. of replicates in each dimension (increase to scale up the system) x = 2 y = 2 z = 4 # setup the system atoms = FaceCenteredCubic(directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]], size=(x, y, z), symbol='Cu', pbc=(0, 0, 1)) atoms.center(vacuum=6.0, axis=0) atoms.center(vacuum=6.0, axis=1) # Simulation parameters h = 0.22 kpts = (1, 1, 8) txt = 'output_M_%i.txt' % size maxiter = 15 # output benchmark parameters if rank == 0: print("#" * 60) print("GPAW benchmark: Copper Filament") print(" dimensions: x=%d, y=%d, z=%d" % (x, y, z)) print(" grid spacing: h=%f" % h) print(" Brillouin-zone sampling: kpts=" + str(kpts))
radius = 15 size = [14, 10, 100] # radius = 30 # size = [28, 20, 100] # 51500 atoms a = FaceCenteredCubic('Au', directions=[[1, 0, -1], [0, 1, 0], [1, 0, 1]], size=size) c = a.cell.diagonal() / 2 dir1 = [sqrt(2), 1, 0] dir2 = [sqrt(2), -1, 0] dir3 = [0, 1, 0] dir1 = np.array(dir1) / np.linalg.norm(dir1) dir2 = np.array(dir2) / np.linalg.norm(dir2) dir3 = np.array(dir3) / np.linalg.norm(dir3) r = a.get_positions() - c m = np.abs(r.dot(dir1)) > radius m = np.logical_or(m, np.abs(r.dot(dir2)) > radius) m = np.logical_or(m, np.abs(r.dot(dir3)) > radius) del a[m] a.center() a.set_pbc([False, False, True]) io.write('whisker.xyz', a) io.write('whisker.data', a, format='lammps-data')
fast = False #AsapThreads() cpulayout = (1, 1, 2) element = 'Pt' size = (20, 20, 100) master = world.rank == 0 if master: atoms = FaceCenteredCubic(symbol=element, size=size, pbc=(True, True, False)) atoms.center(vacuum=10.0, axis=2) atoms.set_momenta(np.zeros((len(atoms), 3))) # Select an atom to get a kick r = atoms.get_positions() uc = atoms.get_cell() x = r[:, 0] - 0.5 * uc[0, 0] y = r[:, 1] - 0.5 * uc[1, 1] z = r[:, 2] zprime = z - 0.01 * (x * x + y * y) n = np.argmax(zprime) #a = atoms[n] #dp = np.sqrt(2 * a.mass * 1000.0) #a.momentum = np.array([0, 0, dp]) t = np.zeros(len(atoms), int) t[n] = 1 atoms.set_tags(t)
from MorseCalculator import MorsePotential from ase.io import write, read from ase import units from ase.lattice.cubic import FaceCenteredCubic from ase.md.verlet import VelocityVerlet # Parameters for the Morse potential for Cu D = 0.3429 r0 = 2.866 alpha = 1.3588 atoms = FaceCenteredCubic(latticeconstant=1.5, symbol='Cu', pbc=False, size=(3, 3, 3)) atoms.center(vacuum=100) #size of box atoms.set_calculator(MorsePotential(D=D, alpha=alpha, r0=r0)) # write('relax.xyz', read('relax.traj@:')) # uncomment this line for Task 2 open('md.log', 'w').close() # clean current log file dyn = VelocityVerlet(atoms, dt=1 * units.fs, trajectory='md.traj', logfile='md.log') dyn.run(1000) write('md.xyz', read('md.traj@:')) # write('langevin.xyz', read('langevin.traj@:')) # uncomment this line for Task 3
def main(element, T_up, T_low, T_expect, bulkmodulus, makepot): def set_temp_fric(dyn, atoms): z = atoms.get_positions()[:,2] zmax = atoms.get_cell()[2,2] zmin = 0 T = T_low + (T_up - T_low) * (z - zmin) / (zmax - zmin) dyn.set_temperature(T * units.kB) rnd = world.sum(random.randint(0,2**32)) # Insures the same number on all nodes. prefix = "melt-%s-%s" % (element, hex(rnd)[2:]) if master: print "Using output directory", prefix os.mkdir(prefix) else: while not os.path.exists(prefix): time.sleep(1) if master: atoms = FaceCenteredCubic(symbol=element, size=size, pbc=(True, True, False)) atoms.center(vacuum=10.0, axis=2) else: atoms = None atoms = MakeParallelAtoms(atoms, cpulayout1) print world.rank, '-', len(atoms), atoms.get_number_of_atoms() atoms.set_calculator(makepot()) #view(atoms) dyn = Langevin(atoms, 5*units.fs, 0.0, friction) logger = MDLogger(dyn, atoms, prefix+'/Melt-phase1.log', stress=True, peratom=True) dyn.attach(logger, interval=100) set_temp_fric(dyn, atoms) unstress = Inhomogeneous_NPTBerendsen(atoms, 50*units.fs, 0, taup=500*units.fs, compressibility=1/bulkmodulus) dyn.attach(unstress.scale_positions_and_cell, interval=10) #traj = PickleTrajectory("melting-phase1.traj", "w", atoms) fn1 = prefix + "/Melt-phase1.bundle" if master: print "Opening file", fn1 traj = BundleTrajectory(fn1, "w", atoms, split=True) dyn.attach(traj, interval=500) therm = Thermometer(atoms, prefix+"/TempProfile-phase1.dat") dyn.attach(therm.update, interval=500) for i in range(steps1 / 100): dyn.run(100) set_temp_fric(dyn, atoms) if master: print "Closing file", fn1 traj.close() del traj, atoms # Reread the bundle atoms = BundleTrajectory(fn1).get_atoms(-1, cpulayout2) atoms.set_calculator(makepot()) dyn = VelocityVerlet(atoms, 5*units.fs) logger = MDLogger(dyn, atoms, prefix+'/PtMelt-phase2.log', stress=True, peratom=True) dyn.attach(logger, interval=1000) unstress = Inhomogeneous_NPTBerendsen(atoms, 50*units.fs, 0, taup=5000*units.fs, compressibility=1/bulkmodulus) dyn.attach(unstress.scale_positions_and_cell, interval=10) fn2 = prefix + "/Melt-phase2.bundle" if master: print "Opening file", fn2 traj = BundleTrajectory(fn2, "w", atoms) dyn.attach(traj, interval=steps2/100) therm = Thermometer(atoms, prefix+"/TempProfile-phase2.dat") dyn.attach(therm.update, interval=steps2/10) dyn.run(steps2 - takedata) therm2 = AveragingThermometer(atoms) dyn.attach(therm2.update, interval=100) dyn.run(takedata) # Run the last part T = therm2.get_temp() if master: print "Melting temperature:", T ReportTest("Melting temperature", T, T_expect, 3) if cleanup: world.barrier() # Cleanup may fail due to the directory not being updated from # writes on the other nodes. Wait for NFS file system. time.sleep(60) if master: shutil.rmtree(prefix) world.barrier() ReportTest.Summary()