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
a = 5.7885/2 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()
from matplotlib import mlab from numpy import * from ase.utils.eos import EquationOfState from ase.lattice.cubic import BodyCenteredCubic from ase import Atom a = 2.8920 cell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] atoms = BodyCenteredCubic('Fe', directions=cell) atoms.set_initial_magnetic_moments([5, 5]) carbon = Atom('C', position=(0, 0.5 * a, 0.5 * a), charge=0.4) atoms = atoms * (2, 2, 2) + carbon init = atoms.copy() final = atoms.copy() final[-1].position = [0, 0.5 * a, (0.5 + 1.0) * a] images = [init] for i in range(9): os.system('mkdir 0{0}'.format(i + 1)) os.chdir('0{0}'.format(i + 1)) atoms = read('POSCAR') # atoms[-1].position = [0,0.5*a,(0.5+(1./10.*i))*a] # view(atoms) images.append(atoms.copy()) # write('POSCAR', atoms) os.chdir('..')
def make_edge_cyl(alat, C11, C12, C44, cylinder_r=10, cutoff=5.5, symbol='W'): ''' makes edge dislocation using atomman library cylinder_r - radius of cylinder of unconstrained atoms around the dislocation in angstrom cutoff - potential cutoff for marinica potentials for FS cutoff = 4.4 symbol : string Symbol of the element to pass to ase.lattuce.cubic.SimpleCubicFactory default is "W" for tungsten ''' # Create a Stroh ojbect with junk data stroh = am.defect.Stroh(am.ElasticConstants(C11=141, C12=110, C44=98), np.array([0, 0, 1])) axes = np.array([[1, 1, 1], [1, -1, 0], [1, 1, -2]]) c = am.ElasticConstants(C11=C11, C12=C12, C44=C44) burgers = alat * np.array([1., 1., 1.])/2. # Solving a new problem with Stroh.solve # Does not work with the new version of atomman stroh.solve(c, burgers, axes=axes) unit_cell = BodyCenteredCubic(directions=axes.tolist(), size=(1, 1, 1), symbol='W', pbc=(False, False, True), latticeconstant=alat) bulk = unit_cell.copy() # shift to make the zeros of the cell betweem the atomic planes # and under the midplane on Y axes X_midplane_shift = (1.0/3.0)*alat*np.sqrt(3.0)/2.0 Y_midplane_shift = 0.25*alat*np.sqrt(2.0) bulk_shift = [X_midplane_shift, Y_midplane_shift, 0.0] bulk.positions += bulk_shift tot_r = cylinder_r + cutoff + 0.01 Lx = int(round(tot_r/(alat*np.sqrt(3.0)/2.0))) Ly = int(round(tot_r/(alat*np.sqrt(2.)))) # factor 2 to make shure odd number of images is translated # it is important for the correct centering of the dislocation core bulk = bulk * (2*Lx, 2*Ly, 1) center_shift = [Lx * alat * np.sqrt(3.0)/2., Ly * alat * np.sqrt(2.), 0.0] bulk.positions -= center_shift ED = bulk.copy() disp = stroh.displacement(ED.positions) ED.positions += disp x, y, z = ED.positions.T radius_x_y_zero = np.sqrt(x**2 + y**2) mask = radius_x_y_zero < tot_r ED = ED[mask] bulk = bulk[mask] bulk.write("before.xyz") ED.write("after_disp.xyz") x, y, z = ED.positions.T radius_x_y_zero = np.sqrt(x**2 + y**2) mask_zero = radius_x_y_zero > cylinder_r fix_atoms = FixAtoms(mask=mask_zero) ED.set_constraint(fix_atoms) x, y, z = bulk.positions.T # move lower left segment bulk.positions[(y < 0.0) & (x < X_midplane_shift)] -= \ [alat * np.sqrt(3.0) / 2.0, 0.0, 0.0] # make the doslocation extraplane center bulk.positions += [(1.0/3.0)*alat*np.sqrt(3.0)/2.0, 0.0, 0.0] return ED, bulk
def make_edge_cyl_001_100(a0, C11, C12, C44, cylinder_r, cutoff=5.5, tol=1e-6, symbol="W"): """Function to produce consistent edge dislocation configuration. 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. cylinder_r : float Radius of cylinder of unconstrained atoms around the dislocation in angstrom. cutoff : float Potential cutoff for determenition of size of fixed atoms region (2*cutoff) tol : float Tolerance for generation of self consistent solution. symbol : string Symbol of the element to pass to ase.lattuce.cubic.SimpleCubicFactory default is "W" for tungsten Returns ------- bulk : ase.Atoms object Bulk configuration. disloc : ase.Atoms object Dislocation configuration. disp : np.array Correstonding displacement. """ # Create a Stroh ojbect with junk data stroh = am.defect.Stroh(am.ElasticConstants(C11=141, C12=110, C44=98), np.array([0, 0, 1])) axes = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) c = am.ElasticConstants(C11=C11, C12=C12, C44=C44) burgers = a0 * np.array([1., 0., 0.]) # Solving a new problem with Stroh.solve # Does not work with the new version of atomman stroh.solve(c, burgers, axes=axes) unit_cell = BodyCenteredCubic(directions=axes.tolist(), size=(1, 1, 1), symbol=symbol, pbc=(False, False, True), latticeconstant=a0) bulk = unit_cell.copy() # shift to make the zeros of the cell betweem the atomic planes # and under the midplane on Y axes X_midplane_shift = -0.25*a0 Y_midplane_shift = -0.25*a0 bulk_shift = [X_midplane_shift, Y_midplane_shift, 0.0] bulk.positions += bulk_shift tot_r = cylinder_r + 2*cutoff + 0.01 Lx = int(round(tot_r/a0)) Ly = int(round(tot_r/a0)) # factor 2 to make sure odd number of images is translated # it is important for the correct centering of the dislocation core bulk = bulk * (2*Lx, 2*Ly, 1) center_shift = [Lx * a0, Ly * a0, 0.0] bulk.positions -= center_shift # bulk.write("before.xyz") disp1 = stroh.displacement(bulk.positions) disloc = bulk.copy() res = np.inf i = 0 while res > tol: disloc.positions = bulk.positions + disp1 disp2 = stroh.displacement(disloc.positions) res = np.abs(disp1 - disp2).max() disp1 = disp2 print 'disloc SCF', i, '|d1-d2|_inf =', res i += 1 if i > 10: raise RuntimeError('Self-consistency did \ not converge in 10 cycles') disp = disp2 x, y, z = disloc.positions.T radius_x_y_zero = np.sqrt(x**2 + y**2) mask = radius_x_y_zero < tot_r disloc = disloc[mask] bulk = bulk[mask] # disloc.write("after_disp.xyz") x, y, z = disloc.positions.T radius_x_y_zero = np.sqrt(x**2 + y**2) mask_zero = radius_x_y_zero > cylinder_r fix_atoms = FixAtoms(mask=mask_zero) disloc.set_constraint(fix_atoms) return bulk, disloc, disp
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
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
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) #atoms.set_cell([a,a,a]) carbon = Atom('C', position=(0,0.5*a,0.5*a), charge=0.4) atoms = atoms*(2,2,2) + carbon constraint = FixAtoms(indices=[8,10]) atoms.set_constraint(constraint) init = atoms.copy() final = atoms.copy() final[-1].position = [0, 0.5*a, (0.5+0.25)*a] for i in range(0,18): os.system('mkdir {:02d}'.format(i)) os.chdir('{:02d}'.format(i)) atoms[-1].position = [0,0.5*a,(0.5+(0.25/17.*i))*a] # view(atoms) write('POSCAR', atoms) os.chdir('..') view(init) view(final)
from numpy import * from ase.utils.eos import EquationOfState from ase.lattice.cubic import BodyCenteredCubic from ase import Atom a = 2.8920 cell = [[1,0,0],[0,1,0],[0,0,1]] atoms = BodyCenteredCubic('Fe', directions=cell) atoms.set_initial_magnetic_moments([5,5]) carbon = Atom('C', position=(0,0.5*a,0.5*a), charge=0.4) atoms = atoms*(2,2,2) + carbon init = atoms.copy() final = atoms.copy() final[-1].position = [0, 0.5*a, (0.5+1.0)*a] images = [init] for i in range(9): os.system('mkdir 0{0}'.format(i+1)) os.chdir('0{0}'.format(i+1)) atoms = read('POSCAR') # atoms[-1].position = [0,0.5*a,(0.5+(1./10.*i))*a] # view(atoms) images.append(atoms.copy()) # write('POSCAR', atoms) os.chdir('..')
# NB: order of types must match order in control file tb_pot = Potential('IP LMTO_TBE', param_str=""" <params> <LMTO_TBE_params n_types="3" control_file="ctrl.fe"> <per_type_data type="1" atomic_num="26"/> <per_type_data type="2" atomic_num="6"/> <per_type_data type="3" atomic_num="1"/> </LMTO_TBE_params> </params>""") print tb_pot # compute energies and forces for a range of lattice constants if True: a = np.linspace(2.5, 3.0, 5) e = [] f = [] configs = [] for aa in a: atoms = BodyCenteredCubic(symbol='Fe', latticeconstant=aa) atoms *= [n, n, n] atoms.set_calculator(tb_pot) e.append(atoms.get_potential_energy()) f.append(atoms.get_forces()[0, 0]) configs.append(atoms.copy()) # print lattice constants, energies and forces print 'a = ', list(a) print 'e = ', list(e) print 'f = ', list(f)
param_filename=eam_pot) alat = 2.83 #Structures gb = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(4, 4, 4), symbol='Fe', pbc=(1, 1, 1), latticeconstant=alat) 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() strain_mask = [1, 1, 1, 0, 0, 0] ucf = UnitCellFilter(gb_h, strain_mask)
def gamma_surf(h_pos=np.array([1.41, 1.500, 22.48])): """ :method:`gamma_surf` generates a set of directories with the upper half unit cell displaced along a certain distance along a particular lattice vector. Hydrogens can be added by setting vector in h_pos. TODO: h_pos should be a list of vectors and atom type for this to be more general. """ vasp_exe = '/projects/SiO2_Fracture/iron/vasp.bgq' crack_geom = { 'cleavage_plane': (1, 1, 0), 'crack_front': (1, -1, 0), 'crack_direction': (0, 0, 1) } crack_direction = crack_geom['crack_direction'] crack_front = crack_geom['crack_front'] cleavage_plane = crack_geom['cleavage_plane'] fe_unit = BodyCenteredCubic( directions=[crack_direction, crack_front, cleavage_plane], size=(1, 1, 1), symbol='Fe', pbc=(1, 1, 1), latticeconstant=2.83) nunits = 8 fe_bulk = BodyCenteredCubic( directions=[crack_direction, crack_front, cleavage_plane], size=(2, 2, nunits), symbol='Fe', pbc=(1, 1, 1), latticeconstant=2.83) fe_unit = Atoms(fe_unit) fe_bulk = Atoms(fe_bulk) ycut = 5.0 + float(nunits) / 2.0 * fe_unit.lattice[2, 2] fe_bulk.center(vacuum=5.0, axis=2) print 'lattice', fe_bulk.lattice[1, 1] print 'ycut', ycut a1 = fe_unit.lattice[0, 0] a2 = fe_unit.lattice[1, 1] POT_DIR = os.environ['POTDIR'] eam_pot = os.path.join(POT_DIR, 'PotBH.xml') r_scale = 1.00894848312 #eam_pot = os.path.join(POT_DIR, 'iron_mish.xml') #r_scale = 1.0129007626 pot = Potential( 'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) fe_bulk.set_calculator(pot) print 'Bulk Energy', fe_bulk.get_potential_energy() refen = fe_bulk.get_potential_energy() A = fe_bulk.get_volume() / fe_bulk.lattice[2, 2] vasp_args = dict( xc='PBE', amix=0.01, amin=0.001, bmix=0.001, amix_mag=0.01, bmix_mag=0.001, kpts=[8, 8, 1], kpar=32, lreal='auto', ibrion=2, nsw=40, nelmdl=-15, ispin=2, nelm=100, algo='VeryFast', npar=8, lplane=False, lwave=False, lcharg=False, istart=0, voskown=1, ismear=1, sigma=0.1, isym=2) # possibly try iwavpr=12, should be faster if it works dir_name = 'b111shiftsym' #dir_name = 'b001shiftsym' f = open('_patdon123{0}H1.dat'.format(dir_name), 'w') WRITEVASP = True a0 = 2.83 for inum, ashift in enumerate(np.arange(0, 1.10, 0.10)): try: os.mkdir('{0}{1}'.format(dir_name, ashift)) except: pass print 'Directory already exists' os.chdir('{0}{1}'.format(dir_name, ashift)) fe_shift = fe_bulk.copy() fe_shift.set_calculator(pot) for at in fe_shift: if at.position[2] > ycut: #[00-1](110) # at.position += ashift*np.array([-a1,0,0]) #[1-11](110) at.position += 0.5 * ashift * np.array([a1, a2, 0]) # print >> fil1, ashift, (units.m**2/units.J)*(fe_shift.get_potential_energy()-refen)/A line = [] for at in fe_shift: line.append(FixedLine(at.index, (0, 0, 1))) #Now add Hydrogen # fe_shift.add_atoms(np.array([0.53*a0, 0.53*a0, 21.0+a0/2]),1) # at relaxed position: fe_shift.add_atoms(h_pos, 1) fix_atoms_mask = [at.number == 1 for at in fe_shift] fixedatoms = FixAtoms(mask=fix_atoms_mask) fe_shift.set_constraint(line + [fixedatoms]) opt = LBFGS(fe_shift) opt.run(fmax=0.1, steps=1000) if inum == 0: print 'Setting Reference Energy' refen = fe_shift.get_potential_energy() print >> f, ashift, (units.m**2 / units.J) * ( fe_shift.get_potential_energy() - refen) / A fe_shift.write('feb{0}.xyz'.format(ashift)) if WRITEVASP: vasp = Vasp(**vasp_args) vasp.initialize(fe_shift) write_vasp('POSCAR', vasp.atoms_sorted, symbol_count=vasp.symbol_count, vasp5=True) vasp.write_incar(fe_shift) vasp.write_potcar() vasp.write_kpoints() os.chdir('../') f.close()