def gen_edge_dislocation(self): screw_slab_unit = BodyCenteredCubic(directions = [self.x, self.y, self.z], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.83) screw_slab_unit = Atoms(screw_slab_unit) n_x = int(self.l_x/screw_slab_unit.get_cell()[0,0]) n_y = int(self.l_y/screw_slab_unit.get_cell()[1,1]) n_z = 1 screw_slab_super = supercell(screw_slab_unit, n_x, n_y, n_z) screw_slab_unit.write('ref_slab.xyz') b = screw_slab_unit.get_cell()[0,0] brg_vec = b*np.array([1,0,0]) vacuum = 70. screw_slab_super.lattice[1,1] += vacuum disloc_l = np.array([0,0,1]) screw_slab_super.set_lattice(screw_slab_super.get_cell(), scale_positions=False) super_slab = screw_slab_super.copy() L_x = screw_slab_super.lattice[0,0] L_y = screw_slab_super.lattice[1,1] L_z = screw_slab_super.lattice[2,2] #Maintain Periodicity along x and z for an edge dislocation: core = np.array([(L_x)/2., (L_y-vacuum)/2., (L_z)/2.]) screw_slab_super.set_cutoff(3.0) screw_slab_super.calc_connect() disloc_noam(screw_slab_super, core, disloc_l, brg_vec) screw_slab_super.info['core'] = core screw_slab_super.write('e{0}.xyz'.format(self.name))
def gen_screw_dislocation_quad(self): # Easy core screw_slab_unit = BodyCenteredCubic(directions = [self.x, self.y, self.z], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = alat) screw_slab_unit = Atoms(screw_slab_unit) # set the supercell: n_x = int(18.0/screw_slab_unit.get_cell()[0,0]) n_y = int(18.0/screw_slab_unit.get_cell()[1,1]) n_z = 2 ref_slab = screw_slab_unit*(n_x,n_y,n_z) ref_slab.write('ref_slab.xyz') screw_slab_super = supercell(screw_slab_unit, n_x, n_y, n_z) b = screw_slab_unit.get_cell()[2,2] brg_vec = b*np.array([0,0,1]) disloc_l = np.array([0,0,1]) super_slab = screw_slab_super.copy() L_x = screw_slab_super.lattice[0,0] L_y = screw_slab_super.lattice[1,1] L_z = screw_slab_super.lattice[2,2] core = [(np.array([(L_x)/2., (L_y)/2., L_z/2.]), brg_vec), np.array([(L_x)/2., (L_y)/2., L_z/2.]), np.array([(L_x)/2., (L_y)/2., L_z/2.]), np.array([(L_x)/2., (L_y)/2., L_z/2.])]
def gen_impurity(symbol='H', tetrahedral=True, sup_cell=[5, 5, 5]): """ Add an element of type symbol to a supercell defined by the size sup_cell. If tetrahedral is true the element is initially placed in a tetrahedral position otherwise it is placed in an octahedral position. """ #Molybdenum is 42!!! alat = 2.82893 atomic_number_dict = {'H': 1, 'B': 5, 'C': 6, 'P': 15, 'Mn': 25, 'Mo': 42} tetra_pos = alat * np.array([0.5, 0.0, 0.75]) octa_pos = alat * np.array([0.5, 0.5, 0.0]) #Structures ats = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(sup_cell[0], sup_cell[1], sup_cell[2]), symbol='Fe', pbc=(1, 1, 1), latticeconstant=alat) mid_point = 0.5 * (np.diag(ats.get_cell())) mid_point = [((sup_cell[0] - 1) / 2.) * alat for sp in sup_cell] if tetrahedral: tetra_pos += mid_point ats.append(Atom(position=tetra_pos, symbol=symbol)) else: octa_pos += mid_point ats.append(Atom(position=octa_pos, symbol=symbol)) return ats
def build_tilt_sym_frac(self, bp=[-1,1,12], v=[1,1,0], c_space=None): bpxv = [(bp[1]*v[2]-v[1]*bp[2]),(bp[2]*v[0]-bp[0]*v[2]),(bp[0]*v[1]- v[0]*bp[1])] grain_a = BodyCenteredCubic(directions = [bpxv, bp, v], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.85) n_grain_unit = len(grain_a) n = 2 # Slightly different from slabmaker since in the fracture # Simulations we want the grainboundary plane to be normal to y. while(grain_a.get_cell()[1,1] < 120.0): grain_a = BodyCenteredCubic(directions = [bpxv, bp, v], size = (1,n,2), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.85) n += 1 print '\t {0} repeats in z direction'.format(n) grain_b = grain_a.copy() grain_c = grain_a.copy() print '\t', '{0} {1} {2}'.format(v[0],v[1],v[2]) print '\t', '{0} {1} {2}'.format(bpxv[0],bpxv[1],bpxv[2]) print '\t', '{0} {1} {2}'.format(bp[0], bp[1], bp[2]) if c_space==None: s1 = surface('Fe', (map(int, bp)), n) c_space = s1.get_cell()[2,2]/float(n) #-s1.positions[:,2].max() s2 = surface('Fe', (map(int, v)), 1) x_space = s2.get_cell()[0,0] #-s1.positions[:,2].max() s3 = surface('Fe', (map(int, bpxv)), 1) y_space = s3.get_cell()[1,1] #-s1.positions[:,2].max() print '\t Interplanar spacing: ', x_space.round(2), y_space.round(2), c_space.round(2), 'A' # Reflect grain b in z-axis (across mirror plane): print grain_a.get_cell()[1,1]-grain_a.positions[:,1].max() grain_b.positions[:,1] = -1.0*grain_b.positions[:,1] grain_c.extend(grain_b) grain_c.set_cell([grain_c.get_cell()[0,0], 2*grain_c.get_cell()[1,1], grain_c.get_cell()[2,2]]) grain_c.positions[:,1] += abs(grain_c.positions[:,1].min()) pos = [grain.position for grain in grain_c] pos = sorted(pos, key= lambda x: x[2]) dups = get_duplicate_atoms(grain_c) # now center fracture cell with plenty of vacuum grain_c.center(vacuum=10.0,axis=1) return grain_c
def gen_screw_dislocation(self): screw_slab_unit = BodyCenteredCubic(directions = [self.x, self.y, self.z], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.83) screw_slab_unit = Atoms(screw_slab_unit) # set the supercell: n_x = int(self.l_x/screw_slab_unit.get_cell()[0,0]) n_y = int(self.l_y/screw_slab_unit.get_cell()[1,1]) n_z = 2 screw_slab_super = supercell(screw_slab_unit, n_x, n_y, n_z) ref_slab = screw_slab_unit*(n_x,n_y,n_z) ref_slab.write('ref_slab.xyz') #Burgers vector modulus: b = screw_slab_unit.get_cell()[2,2] brg_vec = b*np.array([0,0,1]) print b vacuum = 70. screw_slab_super.lattice[0,0] += vacuum screw_slab_super.lattice[1,1] += vacuum disloc_l = np.array([0,0,1]) screw_slab_super.set_lattice(screw_slab_super.get_cell(), scale_positions=False) super_slab = screw_slab_super.copy() L_x = screw_slab_super.lattice[0,0] L_y = screw_slab_super.lattice[1,1] L_z = screw_slab_super.lattice[2,2] core = np.array([(L_x-vacuum)/2., (L_y-vacuum)/2., L_z/2.]) screw_slab_super.set_cutoff(3.0) screw_slab_super.calc_connect() disloc_noam(screw_slab_super, core, disloc_l, brg_vec) screw_slab_super.info['core'] = core screw_slab_super.write('s{0}.xyz'.format(self.name))
def build_surface(self, bp=[-1,1,12], v=[1,1,0]): ''' Build Surface unit cell ''' bpxv = [(bp[1]*v[2]-v[1]*bp[2]), (bp[2]*v[0]-bp[0]*v[2]), (bp[0]*v[1]- v[0]*bp[1])] surf_cell = BodyCenteredCubic(directions = [v, bpxv, bp], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.85) n = 2 while(surf_cell.get_cell()[2,2]< 20.0 ): surf_cell = BodyCenteredCubic(directions = [v, bpxv, bp], size = (1,1,n), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.85) n += 1 surf_cell.center(vacuum=20.0, axis=2) return surf_cell
# use one of the routines from utilities module to relax the initial # unit cell and atomic positions bulk = relax_atoms_cell(bulk, tol=fmax, traj_file=None) else: bulk = model.bulk_reference.copy() bulk.set_calculator(model.calculator) a0 = bulk.cell[0,0] # get lattice constant from relaxed bulk bulk = Diamond(symbol="Si", latticeconstant=a0, directions=[[1,-1,0],[0,0,1],[1,1,0]]) bulk.set_calculator(model.calculator) # set up supercell bulk *= (1, 1, 10) # flip coord system for ASE (precon minim?) c = bulk.get_cell() t_v = c[0,:].copy() c[0,:] = c[1,:] c[1,:] = t_v bulk.set_cell(c) ase.io.write(sys.stdout, bulk, format='extxyz') def surface_energy(bulk, z_offset): Nat = bulk.get_number_of_atoms() # shift so cut is through shuffle plane bulk.positions[:,2] += z_offset bulk.wrap() # relax atom positions, holding cell fixed
POT_DIR = os.environ['POTDIR'] eam_pot = os.path.join(POT_DIR, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential('IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) #alat = 2.82893 #could just use the proper one as well.... alat = 2.837666 sup_cell = args.supercellsize tetra_pos = alat*np.array([0.5, 0.0, 0.75]) octa_pos = alat*np.array([0.5, 0.5, 0.0]) #Structures gb = BodyCenteredCubic(directions = [[1,0,0], [0,1,0], [0,0,1]], size = (sup_cell[0],sup_cell[1],sup_cell[2]), symbol='Fe', pbc=(1,1,1), latticeconstant = alat) mid_point = 0.5*(np.diag(gb.get_cell())) mid_point = [((sup_cell[0]-1)/2.)*alat for sp in sup_cell] gb = Atoms(gb) if args.tetra: print 'Tetrahedral Defect' tetra_pos += mid_point gb.add_atoms(tetra_pos, 1) gb.write('bcc_h.xyz') elif args.octa: print 'Octahedral Defect' octa_pos += mid_point gb.add_atoms(octa_pos, 1) gb.write('bcc_h.xyz') else: gb.write('bcc.xyz')
print '\tDislocation Type: ', dis_type, ' dislocation.' print '\tCalculate Dynamics: ', run_dyn print '\tCalculate Nye Tensor: ', calc_nye print '\tInput File: ', input_file print '\tPotential: ', pot_type if pot_type == 'EAM': global potdir potdir = os.environ['POTDIR'] eam_pot = os.path.join(potdir, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential('IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) elif pot_type == 'TB': tb = TightBindingPot(alat= 1.00, nk=12) screw_slab_unit = Atoms(screw_slab_unit) center_cell = np.diag(screw_slab_unit.get_cell())/2. screw_slab_unit.add_atoms(center_cell,1) #screw_slab_unit.add_atoms(center_cell*0.76, 6) screw_slab_unit.set_atoms(screw_slab_unit.Z) print len(screw_slab_unit) tb.write_control_file('ctrl.fe', screw_slab_unit) pot = Potential('IP LMTO_TBE', param_str=""" <params> <LMTO_TBE_params n_types="2" control_file="ctrl.fe"> <per_type_data type="1" atomic_num="26"/> <per_type_data type="2" atomic_num="1"/> </LMTO_TBE_params> </params>""") #If there is an initial strain energy increment that here: pot.print_()
print '\tCalculate Nye Tensor: ', calc_nye print '\tInput File: ', input_file print '\tPotential: ', pot_type if pot_type == 'EAM': global potdir potdir = os.environ['POTDIR'] eam_pot = os.path.join(potdir, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential( 'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) elif pot_type == 'TB': tb = TightBindingPot(alat=1.00, nk=12) screw_slab_unit = Atoms(screw_slab_unit) center_cell = np.diag(screw_slab_unit.get_cell()) / 2. screw_slab_unit.add_atoms(center_cell, 1) #screw_slab_unit.add_atoms(center_cell*0.76, 6) screw_slab_unit.set_atoms(screw_slab_unit.Z) print len(screw_slab_unit) tb.write_control_file('ctrl.fe', screw_slab_unit) pot = Potential('IP LMTO_TBE', param_str=""" <params> <LMTO_TBE_params n_types="2" control_file="ctrl.fe"> <per_type_data type="1" atomic_num="26"/> <per_type_data type="2" atomic_num="1"/> </LMTO_TBE_params> </params>""") #If there is an initial strain energy increment that here:
from ase.utils.eos import EquationOfState from ase.lattice.cubic import BodyCenteredCubic from ase import Atom a = 2.87 cell = [[1,0,0],[0,1,0],[0,0,1]] bcc = BodyCenteredCubic('Fe', directions=cell) bcc.set_initial_magnetic_moments([5,5]) carbon = Atom('C', position=(0,0.5*a,0.5*a), charge=0.4) bcc = bcc*(2,2,2) + carbon #atoms = atoms*(2,2,2) constraint = FixAtoms(indices=[5,7,8,10,12,13,14,15,16]) bcc.set_constraint(constraint) view(bcc) def save( filename, arg ): f = open(filename, 'a+t') f.write('{0} \n'.format(arg)) f.close() os.system('mkdir result') print bcc.get_cell()
def screw_cyl_octahedral(alat, C11, C12, C44, scan_r=15, symbol="W", imp_symbol='H', hard_core=False, center=(0., 0., 0.)): """Generates a set of octahedral positions with `scan_r` radius. Applies the screw dislocation displacement for creating an initial guess for the H positions at dislocation core. Parameters ---------- alat : float Lattice constant of the material. C11 : float C11 elastic constant of the material. C12 : float C12 elastic constant of the material. C44 : float C44 elastic constant of the material. symbol : string Symbol of the element to pass to ase.lattuce.cubic.SimpleCubicFactory default is "W" for tungsten imp_symbol : string Symbol of the elemnt to pass creat Atoms object default is "H" for hydrogen symbol : string Symbol of the elemnt to pass creat Atoms object hard_core : float Type of the dislocatino core if True then -u (sign of displacement is flipped) is applied. Default is False i.e. soft core is created. center : tuple of floats Coordinates of dislocation core (center) (x, y, z). Default is (0., 0., 0.) Returns ------- ase.Atoms object Atoms object with predicted tetrahedral positions around dislocation core. """ # TODO: Make one function for impurities and pass factory to it: # TODO: i.e. octahedral or terahedral axes = np.array([[1, 1, -2], [-1, 1, 0], [1, 1, 1]]) unit_cell = BodyCenteredCubic(directions=axes.tolist(), size=(1, 1, 1), symbol=symbol, pbc=(False, False, True), latticeconstant=alat) BCCOctas = BodyCenteredCubicOctahedralFactory() impurities = BCCOctas(directions=axes.tolist(), size=(1, 1, 1), symbol=imp_symbol, pbc=(False, False, True), latticeconstant=alat) impurities = impurities[impurities.positions.T[2] < alat*1.2] impurities.set_cell(unit_cell.get_cell()) impurities.wrap() disloCenterY = alat * np.sqrt(2.)/6.0 disloCenterX = alat * np.sqrt(6.)/6.0 impurities.positions[:, 0] -= disloCenterX impurities.positions[:, 1] -= disloCenterY L = int(round(2.0*scan_r/(alat*np.sqrt(2.)))) + 1 bulk_octa = impurities * (L, L, 1) # make 0, 0, at the center bulk_octa.positions[:, 0] -= L * alat * np.sqrt(6.)/2. - center[0] bulk_octa.positions[:, 1] -= L * alat * np.sqrt(2.)/2. - center[1] x, y, z = bulk_octa.positions.T radius_x_y_zero = np.sqrt(x**2 + y**2) mask_zero = radius_x_y_zero < scan_r radius_x_y_center = np.sqrt((x - center[0])**2 + (y - center[1])**2) mask_center = radius_x_y_center < scan_r final_mask = mask_center | mask_zero # leave only atoms inside the cylinder bulk_octa = bulk_octa[final_mask] # Create a Stroh ojbect with junk data stroh = am.defect.Stroh(am.ElasticConstants(C11=141, C12=110, C44=98), np.array([0, 0, 1])) c = am.ElasticConstants(C11=C11, C12=C12, C44=C44) burgers = alat * np.array([1., 1., 1.])/2. # Solving a new problem with Stroh.solve stroh.solve(c, burgers, axes=axes) dislo_octa = bulk_octa.copy() impurities_u = stroh.displacement(bulk_octa.positions - center) impurities_u = -impurities_u if hard_core else impurities_u dislo_octa.positions += impurities_u return dislo_octa
from numpy import * from ase.utils.eos import EquationOfState from ase.lattice.cubic import BodyCenteredCubic from ase import Atom a = 2.87 cell = [[1,0,0],[0,1,0],[0,0,1]] bcc = BodyCenteredCubic('Fe', directions=cell) bcc.set_initial_magnetic_moments([5,5]) carbon = Atom('C', position=(0,0.5*a,0.75*a), charge=0.4) bcc = bcc*(2,2,2) + carbon #atoms = atoms*(2,2,2) constraint = FixAtoms(indices=[5,7,8,10,12,13,14,15,16]) bcc.set_constraint(constraint) view(bcc) def save( filename, arg ): f = open(filename, 'a+t') f.write('{0} \n'.format(arg)) f.close() os.system('mkdir result') print bcc.get_cell()
n_sup_z = 8 pot_file = os.path.join(pot_dir, 'PotBH.xml') pot = Potential('IP EAM_ErcolAd', param_filename=pot_file) #Set paths for phonon band structures: #paths = [np.array([0,0,-0.5]), np.array([0,0,0]), np.array([0,0,0.5]), np.array([0,0.5,0.5])] b1 = 1.0 #Nice plot for phonon: paths = [np.array([0,0,0.0]), np.array([b1/2.0, b1/2.0, 0.0]), np.array([b1/2.0,b1/2.0,b1])] paths = calc_band_paths(paths) unit_cell = BodyCenteredCubic(directions = [[1,0,0], [0,1,0],[0,0,1]], size = (1,1,1), symbol='Fe', pbc=(1,1,1), latticeconstant = 2.83) symbols = unit_cell.get_chemical_symbols() cell = unit_cell.get_cell() scaled_positions = unit_cell.get_scaled_positions() THZ_to_mev = 4.135665538536 unit_cell = PhonopyAtoms(symbols=symbols, cell=cell, scaled_positions=scaled_positions) phonon = Phonopy(unit_cell, [[n_sup_x,0,0],[0,n_sup_y,0],[0,0,n_sup_z]]) phonon.generate_displacements(distance=0.05) supercells = phonon.get_supercells_with_displacements() #We need to get the forces on these atoms... forces = [] print 'There are', len(supercells), 'displacement patterns' for sc in supercells: cell = aseAtoms(symbols=sc.get_chemical_symbols(), scaled_positions=sc.get_scaled_positions(), cell=sc.get_cell(), pbc=(1,1,1)) cell = Atoms(cell)
from ase.lattice.cubic import BodyCenteredCubic import numpy as np bulk = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(2, 2, 2), latticeconstant=2.87, symbol='Fe') newbasis = 2.87 * np.array([[-0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5]]) pos = bulk.get_positions() s = np.dot(np.linalg.inv(newbasis.T), pos.T).T print 'atom positions in primitive basis' print s #let us see the unit cell in terms of the primitive basis too print 'unit cell in terms of the primitive basis' print np.dot(np.linalg.inv(newbasis.T), bulk.get_cell().T).T
cell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] atoms = BodyCenteredCubic('Fe', directions=cell) atoms.set_initial_magnetic_moments([5, 5]) atoms.set_cell([a, a, a], scale_atoms=True) carbon = Atom('C', position=(0, 0.5 * a, 0.75 * a), charge=0.4) atoms = atoms * (2, 2, 2) + carbon constraint = FixAtoms(indices=[8, 10, 12, 14, 16]) atoms.set_constraint(constraint) atoms[-1].position = [0, 0.5 * a, 0.75 * a] init = atoms.copy() view(init) atoms[-1].position = [0, 0.75 * a, 0.5 * a] final = atoms.copy() # view(final) def save(filename, arg): f = open(filename, 'a+t') f.write('{0} \n'.format(arg)) f.close() os.system('mkdir result') print atoms.get_cell()
'forcing': 'Concentration', 'calc_method': 'LAMMPS', 'pair_style':'eam/fs', 'pot_file':'Fe_mm.eam.fs', 'lammps_thermo_steps':100, 'keep_Lammps_files': True, 'ase_min': False, 'lammps_min': mincomd, 'lammps_min_style': 'cg\nmin_modify line quadratic', 'genealogy': True, 'output_format': 'FormationEnergyPerInt', 'allenergyfile':True, 'bestindslist': True, 'finddefects':True, 'parallel' : True, 'algorithm_type' : 'lambda+mu', 'debug':['None']} bsfe = BCC('Fe', size=parameters['supercell']) rank = MPI.COMM_WORLD.Get_rank() if rank==0: write(parameters['SolidFile'],bsfe) cell=numpy.maximum.reduce(bsfe.get_cell()) parameters['SolidCell']=cell A = Optimizer(parameters) A.algorithm_parallel() if __name__ == "__main__": main()
from ase.lattice.cubic import BodyCenteredCubic import numpy as np bulk = BodyCenteredCubic(directions=[[1,0,0], [0,1,0], [0,0,1]], size=(2,2,2), latticeconstant=2.87, symbol='Fe') newbasis = 2.87*np.array([[-0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5]]) pos = bulk.get_positions() s = np.dot(np.linalg.inv(newbasis.T), pos.T).T print('atom positions in primitive basis') print(s) # let us see the unit cell in terms of the primitive basis too print('unit cell in terms of the primitive basis') print(np.dot(np.linalg.inv(newbasis.T), bulk.get_cell().T).T)
def calc_bulk_dissolution(args): """Calculate the bulk dissolution energy for hydrogen in a tetrahedral position in bcc iron. Args: args(list): determine applied strain to unit cell. """ POT_DIR = os.path.join(app.root_path, 'potentials') eam_pot = os.path.join(POT_DIR, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential( 'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) alat = 2.83 gb = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(6, 6, 6), symbol='Fe', pbc=(1, 1, 1), latticeconstant=alat) cell = gb.get_cell() print 'Fe Cell', cell e1 = np.array([1, 0, 0]) e2 = np.array([0, 1, 0]) e3 = np.array([0, 0, 1]) if args.hydrostatic != 0.0: strain_tensor = np.eye(3) + args.hydrostatic * np.eye(3) cell = cell * strain_tensor gb.set_cell(cell, scale_atoms=True) print 'Hydrostatic strain', args.hydrostatic print 'strain tensor', strain_tensor print gb.get_cell() elif args.stretch != 0.0: strain_tensor = np.tensordot(e2, e2, axes=0) strain_tensor = np.eye(3) + args.stretch * strain_tensor cell = strain_tensor * cell print 'Stretch strain' print 'Cell:', cell gb.set_cell(cell, scale_atoms=True) elif args.shear != 0.0: strain_tensor = np.tensordot(e1, e2, axes=0) strain_tensor = np.eye(3) + args.shear * strain_tensor cell = strain_tensor.dot(cell) print 'Shear Strain', strain_tensor print 'Cell:', cell gb.set_cell(cell, scale_atoms=True) gb.write('sheared.xyz') else: print 'No strain applied.' tetra_pos = alat * np.array([0.25, 0.0, 0.5]) h2 = aseAtoms('H2', positions=[[0, 0, 0], [0, 0, 0.7]]) h2 = Atoms(h2) gb = Atoms(gb) gb_h = gb.copy() gb_h.add_atoms(tetra_pos, 1) #caclulators gb.set_calculator(pot) h2.set_calculator(pot) gb_h.set_calculator(pot) gb_h.write('hydrogen_bcc.xyz') #Calc Hydrogen molecule energy opt = BFGS(h2) opt.run(fmax=0.0001) E_h2 = h2.get_potential_energy() h2.write('h2mol.xyz') #strain_mask = [1,1,1,0,0,0] strain_mask = [0, 0, 0, 0, 0, 0] ucf = UnitCellFilter(gb_h, strain_mask) #opt = BFGS(gb_h) opt = FIRE(ucf) opt.run(fmax=0.0001) E_gb = gb.get_potential_energy() E_gbh = gb_h.get_potential_energy() E_dis = E_gbh - E_gb - 0.5 * E_h2 print 'E_gb', E_gb print 'E_gbh', E_gbh print 'H2 Formation Energy', E_h2 print 'Dissolution Energy', E_dis
def make_screw_quadrupole(alat, left_shift=0, right_shift=0, n1u=5, symbol="W"): """Generates a screw dislocation dipole configuration for effective quadrupole arrangement. Works for BCC systems. Parameters ---------- alat : float Lattice parameter of the system in Angstrom. left_shift : float, optional Shift of the left dislocation core in number of dsitances to next equivalent disocation core positions needed for creation for final configuration for NEB. Default is 0. right_shift : float, optional shift of the right dislocation core in number of dsitances to next equivalent disocation core positions needed for creation for final configuration for NEB. Default is 0. n1u : int, odd number odd number! length of the cell a doubled distance between core along x. Main parameter to calculate cell vectors symbol : string Symbol of the element to pass to ase.lattuce.cubic.SimpleCubicFactory default is "W" for tungsten Returns ------- disloc_quadrupole : ase.Atoms Resulting quadrupole configuration. W_bulk : ase.Atoms Perfect system. dislo_coord_left : list of float Coodrinates of left dislocation core [x, y] dislo_coord_right : list of float Coodrinates of right dislocation core [x, y] Notes ----- Calculation of cell vectors +++++++++++++++++++++++++++ From [1]_ we take: - Unit vectors for the cell are: .. math:: u = \frac{1}{3}[1 \bar{2} 1]; .. math:: v = \frac{1}{3}[2 \bar{1} \bar{1}]; .. math:: z = b = \frac{1}{2}[1 1 1]; - Cell vectors are: .. math:: C_1 = n^u_1 u + n^v_1 v + C^z_1 z; .. math:: C_2 = n^u_2 u + n^v_2 v + C^z_2 z; .. math:: C_3 = z - For quadrupole arrangement n1u needs to be odd number, for 135 atoms cell we take n1u=5 - To have quadrupole as as close as possible to a square one has to take: .. math:: 2 n^u_2 + n^v_2 = n^u_1 .. math:: n^v_2 \approx \frac{n^u_1}{\sqrt{3}} - for n1u = 5: .. math:: n^v_2 \approx \frac{n^u_1}{\sqrt{3}} = 2.89 \approx 3.0 .. math:: n^u_2 = \frac{1}{2} (n^u_1 - n^v_2) \approx \frac{1}{2} (5-3)=1 - Following [2]_ cell geometry is optimized by ading tilt compomemts Cz1 and Cz2 for our case of n1u = 3n - 1: Easy core .. math:: C^z_1 = + \frac{1}{3} .. math:: C^z_2 = + \frac{1}{6} Hard core .. math:: C^z_1 = + \frac{1}{3} .. math:: C^z_2 = + \frac{1}{6} may be typo in the paper check the original! References: +++++++++++ .. [1] Ventelon, L. & Willaime, F. J 'Core structure and Peierls potential of screw dislocations in alpha-Fe from first principles: cluster versus dipole approaches' Computer-Aided Mater Des (2007) 14(Suppl 1): 85. https://doi.org/10.1007/s10820-007-9064-y .. [2] Cai W. (2005) Modeling Dislocations Using a Periodic Cell. In: Yip S. (eds) Handbook of Materials Modeling. Springer, Dordrecht https://link.springer.com/chapter/10.1007/978-1-4020-3286-8_42 """ unit_cell = BodyCenteredCubic(directions=[[1, -2, 1], [2, -1, -1], [1, 1, 1]], symbol=symbol, pbc=(True, True, True), latticeconstant=alat, debug=0) unit_cell_u, unit_cell_v, unit_cell_z = unit_cell.get_cell() # calculate the cell vectors according to the Ventelon paper # the real configrution depends on rounding check it here n2v = int(np.rint(n1u/np.sqrt(3.0))) # when the n1u - n2v difference is odd it is impossible to have # perfect arrangemt of translation along x with C2 equal to 0.5*n1u # choice of rounding between np.ceil() and np.trunc() makes a different # configuration but of same quality of arrangement of quadrupoles (test) n2u = np.ceil((n1u - n2v) / 2.) n1v = 0 print("Not rounded values of C2 componets: ") print("n2u: %.2f, n2v: %.2f" % ((n1u - n2v) / 2., n1u/np.sqrt(3.0))) print("Calculated cell vectors from n1u = %i" % n1u) print("n1v = %i" % n1v) print("n2u = %i" % n2u) print("n2v = %i" % n2v) bulk = unit_cell.copy()*[n1u, n2v, 1] # add another periodic shift in x direction to c2 vector # for proper periodicity (n^u_2=1) of the effective quadrupole arrangement bulk.cell[1] += n2u * unit_cell_u C1_quadrupole, C2_quadrupole, C3_quadrupole = bulk.get_cell() # calulation of dislocation cores positions # distance between centers of triangles along x # move to odd/even number -> get to upward/downward triangle x_core_dist = alat * np.sqrt(6.)/6.0 # distance between centers of triangles along y y_core_dist = alat * np.sqrt(2.)/6.0 # separation of the cores in a 1ux1v cell nx_left = 2 nx_right = 5 if n2v % 2 == 0: # check if the number of cells in y direction is even # Even: then introduce cores between two equal halfes of the cell ny_left = -2 ny_right = -1 else: # Odd: introduce cores between two equal halfes of the cell ny_left = 4 ny_right = 5 nx_left += 2.0 * left_shift nx_right += 2.0 * right_shift dislo_coord_left = np.array([nx_left * x_core_dist, ny_left * y_core_dist, 0.0]) dislo_coord_right = np.array([nx_right * x_core_dist, ny_right * y_core_dist, 0.0]) # caclulation of the shifts of the inital cores coordinates for the final # quadrupole arrangements # different x centering preferences for odd and even values if n2v % 2 == 0: # check if the number of cells in y direction is even # Even: dislo_coord_left += (n2u - 1) * unit_cell_u dislo_coord_right += (n2u - 1 + np.trunc(n1u/2.0)) * unit_cell_u else: # Odd: dislo_coord_left += n2u * unit_cell_u dislo_coord_right += (n2u + np.trunc(n1u/2.0)) * unit_cell_u dislo_coord_left += np.trunc(n2v/2.0) * unit_cell_v dislo_coord_right += np.trunc(n2v/2.0) * unit_cell_v u_quadrupole = dipole_displacement_angle(bulk, dislo_coord_left, dislo_coord_right) # get the image contribution from the dipoles around # (default value of N images to scan n_img=10) u_img = get_u_img(bulk, dislo_coord_left, dislo_coord_right) u_sum = u_quadrupole + u_img # calculate the field of neghbouring cell to estimate # linear u_err along C1 and C2 (see. Cai paper) # u_err along C2 n1_shift = 0 n2_shift = 1 shift = n1_shift*C1_quadrupole + n2_shift*C2_quadrupole u_quadrupole_shifted = dipole_displacement_angle(bulk, dislo_coord_left + shift, dislo_coord_right + shift, shift=shift) u_img_shifted = get_u_img(bulk, dislo_coord_left, dislo_coord_right, n1_shift=n1_shift, n2_shift=n2_shift) u_sum_shifted = u_quadrupole_shifted + u_img_shifted delta_u = u_sum - u_sum_shifted delta_u_C2 = delta_u.T[2].mean() print("delta u c2: %.2f " % delta_u_C2) # u_err along C1 n1_shift = 1 n2_shift = 0 shift = n1_shift*C1_quadrupole + n2_shift*C2_quadrupole u_quadrupole_shifted = dipole_displacement_angle(bulk, dislo_coord_left + shift, dislo_coord_right + shift, shift=shift) u_img_shifted = get_u_img(bulk, dislo_coord_left, dislo_coord_right, n1_shift=n1_shift, n2_shift=n2_shift) u_sum_shifted = u_quadrupole_shifted + u_img_shifted delta_u = u_sum - u_sum_shifted delta_u_C1 = delta_u.T[2].mean() print("delta u c1: %.3f" % delta_u_C1) x_scaled, y_scaled, __ = bulk.get_scaled_positions(wrap=False).T u_err_C2 = (y_scaled - 0.5)*delta_u_C2 u_err_C1 = delta_u_C1*(x_scaled - 0.5) u_err = u_err_C1 + u_err_C2 # Calculate the u_tilt to accomodate the stress (see. Cai paper) burgers = bulk.cell[2][2] u_tilt = 0.5 * burgers * (y_scaled - 0.5) final_u = u_sum final_u.T[2] += u_err - u_tilt disloc_quadrupole = bulk.copy() disloc_quadrupole.positions += final_u # tilt the cell according to the u_tilt disloc_quadrupole.cell[1][2] -= burgers/2.0 bulk.cell[1][2] -= burgers/2.0 return disloc_quadrupole, bulk, dislo_coord_left, dislo_coord_right
cell = [[1,0,0],[0,1,0],[0,0,1]] atoms = BodyCenteredCubic('Fe', directions=cell) atoms.set_initial_magnetic_moments([5,5]) atoms.set_cell([a, a, a], scale_atoms=True) carbon = Atom('C', position=(0,0.5*a,0.75*a), charge=0.4) atoms = atoms*(2,2,2) + carbon constraint = FixAtoms(indices=[8,10,12,14,16]) atoms.set_constraint(constraint) atoms[-1].position = [0, 0.5*a, 0.75*a] init = atoms.copy() # view(init) atoms[-1].position = [0, 0.75*a, 0.5*a] final = atoms.copy() # view(final) def save( filename, arg ): f = open(filename, 'a+t') f.write('{0} \n'.format(arg)) f.close() os.system('mkdir result') print atoms.get_cell()
class System(): def __init__(self, setting): self.setting = setting self.elsProps = [] # elements properties self.setting['nAt'] = [] # number of atoms per specie self.px = self.setting['period'][0] self.py = self.setting['period'][1] self.pz = self.setting['period'][2] self.a0 = self.setting['a'] self.box =[[0, self.px*self.a0],\ [0,self.py*self.a0],\ [0,self.pz*self.a0]] self.setElsProps() self.setCrystal() if self.setting['positions'] == 'rnd': self.setRandomStructure() self.setNumbers() self.bulk.set_atomic_numbers(self.numbers) def setNumbers(self): self.numbers = [] for e in self.t1_: self.numbers.append( self.elsProps[e - 1]['number']) def setElsProps(self): for e in self.setting['elements']: a = ase.Atom(e) mass = a.mass / _Nav number = a.number form = pt.formula(a.symbol) e_ = form.structure[0][1] crys = e_.crystal_structure['symmetry'] a_ = e_.crystal_structure['a'] self.elsProps.append({'ase':a, 'mass': mass, 'structure': crys, 'a':a_ , 'number':number}) def setCrystal(self): crys = self.setting['structure'] if crys == 'rnd': print 'rnd implemented' self.genRandomPositions() d = 1.104 # N2 bondlength formula = 'Cu'+str(len(self.pos)) cell =[(self.px*self.a0,0,0),(0,self.py*self.a0,0),(0,0,self.pz*self.a0)] self.bulk = ase.Atoms(formula, self.pos, pbc=True, cell=cell) if crys == 'fcc': print 'fcc implemented' from ase.lattice.cubic import FaceCenteredCubic self.bulk = FaceCenteredCubic(directions=[[1,0,0], [0,1,0], [0,0,1]], size=(self.px,self.py,self.pz), symbol='Cu', pbc=(1,1,1), latticeconstant=self.a0) if crys == 'bcc': print 'bcc implemented' from ase.lattice.cubic import BodyCenteredCubic self.bulk = BodyCenteredCubic(directions=[[1,0,0], [0,1,0], [0,0,1]], size=(self.px,self.py,self.pz), symbol='Cu', pbc=(1,1,1), latticeconstant=self.a0) if self.setting['structure'] == 'hcp': print 'hcp no implemented' sys.exit(0) self.setting['nAtoms'] = self.bulk.get_number_of_atoms() self.calcAtoms2() self.genStructure() self.pos = self.bulk.get_positions() def update (self): cell = self.bulk.get_cell() self.box =[[0, cell[0][0]],[0, cell[1][1]],[0, cell[2][2]]] self.pos = self.bulk.get_positions() def genStructure(self): self.t1_ = [] for i,e in enumerate(self.setting['nAt']): [self.t1_.append(i+1) for j in range(e)] def setRandomStructure(self): x = [int(random.random()*len(self.t1_)) for i in range(len(self.t1_))] for i in range(len(x) - 1): t1 = self.t1_[x[i]] t2 = self.t1_[x[i+1]] self.t1_[x[i]] = t2 self.t1_[x[i+1]] = t1 return self.pos, self.t1_, self.box def genRandomPositions(self): Lx = self.box[0][1] Ly = self.box[1][1] Lz = self.box[2][1] self.pos =[] for i in range(self.setting['nAtoms']): x = random.random() * Lx y = random.random() * Ly z = random.random() * Lz self.pos.append([x,y,z]) def getAtoms(self): return self.elsProps def Interaction (self): if self.setting['pot'] == 'lj': ljp = ljParameters.LjParameters() str_ = ljp.lammpsInteraction(self.elsProps) if self.setting['pot'] == 'zhou': gz = zhou.calcPotentials(self.setting['elements']) gz.createPot() str_ = gz.lammpsZhouEam() return str_ def calcAtoms2(self): nAt = [] sum_ = 0 sumpc = 0.0000001 len_elements = len(self.setting['elements']) len_pca = len(self.setting['pca']) print 'calcAtom2', len_pca, len_elements if len_elements != len_pca + 1: print 'error len' sys.exit(0) for p in self.setting['pca']: sumpc +=p if sumpc >= 100 or sumpc <= 0: print 'error pc' sys.exit(0) sumpc = 0 for i in range(len(self.setting['elements']) - 1): p = self.setting['pca'][i] sumpc +=p t = int(p * self.setting['nAtoms'] / 100.0) sum_ +=t nAt.append(t) nAt.append(self.setting['nAtoms'] - sum_) self.setting['nAtoms'] = 0 for e in nAt: self.setting['nAtoms'] +=e print 'pca', self.setting['pca'] self.setting['nAt'] = nAt def getMasess(self): str_ ='' i = 1 for e in self.elsProps: str_ += 'mass ' + str(i) + ' ' +str(e['mass']) + '\n' i+=1 return str_