def build_crack_cell(self, unit_slab, pot, fix_dist=1.0): """ Creates a CrackCell of the desired size and orientation with the top and bottom layer of atoms constrained. Returns: :class:`Atoms` - the relaxed crack_cell. """ self.nx = int(self.width/unit_slab.get_cell()[0,0]) self.ny = int(self.height/unit_slab.get_cell()[1,1]) if self.ny %2 == 1: self.ny +=1 #self.ny = 1 print 'number of unit cells', self.nx, self.ny crack_slab = unit_slab*(self.nx, self.ny,self.nz) write('ref_slab.xyz', crack_slab) crack_slab.center(self.vacuum, axis=0) crack_slab.center(self.vacuum, axis=1) crack_slab.positions[:, 0] -= crack_slab.positions[:, 0].mean() crack_slab.positions[:, 1] -= crack_slab.positions[:, 1].mean() self.orig_width = (crack_slab.positions[:, 0].max() - crack_slab.positions[:, 0].min()) self.orig_height = (crack_slab.positions[:, 1].max() - crack_slab.positions[:, 1].min()) print(('Made slab with %d atoms, original width and height: %.1f x %.1f A^2' % (len(crack_slab), self.orig_width, self.orig_height))) top = crack_slab.positions[:,1].max() bottom = crack_slab.positions[:,1].min() left = crack_slab.positions[:,0].min() right = crack_slab.positions[:,0].max() #Constrain top and bottom layer of atoms: fixed_mask = ((abs(crack_slab.positions[:, 1] - top) < 1.0) | (abs(crack_slab.positions[:, 1] - bottom) < 1.0)) const = FixAtoms(mask=fixed_mask) crack_slab.set_constraint(const) #Strain is a dimensionless ratio we require elastic tensor #to translate the initial energy flow to the tip into a strain. self.E = youngs_modulus(self.cij, self.cleavage_plane) self.nu = poisson_ratio(self.cij, self.cleavage_plane, self.crack_direction) self.strain = G_to_strain(self.initial_G, self.E, self.nu, self.orig_height) seed = left + self.crack_seed_length tip = left + self.crack_seed_length + self.strain_ramp_length xpos = crack_slab.positions[:,0] ypos = crack_slab.positions[:,1] crack_slab.positions[:,1] += thin_strip_displacement_y(xpos, ypos, self.strain, seed, tip) write('crack_slab_init.xyz', crack_slab) print('Applied initial load: strain=%.4f, G=%.2f J/m^2' % (self.strain, self.initial_G / (units.J / units.m**2))) pot_dir = os.environ['POTDIR'] crack_slab.set_calculator(pot) #Initial crack pos print 'crack_pos before relaxations' print find_crack_tip_stress_field(crack_slab, calc=mm_pot) print('Relaxing slab...') slab_opt = PreconFIRE(crack_slab) slab_opt.run(fmax=self.relax_fmax) return crack_slab
def check_if_cracked(atoms): orig_crack_pos = atoms.info['CrackPos'].copy() crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) if not atoms.info['is_cracked'] and (crack_pos[0] - orig_crack_pos[0]) > tip_move_tol: atoms.info['is_cracked'] = True del atoms.constraints[atoms.constraints.index(strain_atoms)]
def update_qm_region_H(atoms): """ Set quantum region around the Hydrogen. Also records crackpos. """ mm_pot = Potential(mm_init_args, param_filename = param_file, cutoff_skin = cutoff_skin) crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) #set quantum region to first hydrogen atom in list. h_pos = atoms[h_list[0]].position old_qm_list = atoms.hybrid_vec.nonzero()[0] new_qm_list = update_hysteretic_qm_region(atoms, old_qm_list, h_pos, qm_inner_radius, qm_outer_radius, update_marks=False) #lets try setting the atoms object properties by hand? atoms.hybrid[:] = 0 atoms.hybrid[new_qm_list] = 1 #Distributed Force Mixing Properties: atoms.hybrid_vec[:] = 0 atoms.hybrid_vec[new_qm_list] = 1 atoms.hybrid_1[:] = atoms.hybrid_vec[:] atoms.params['core'] = h_pos atoms.params['CrackPos'] = crack_pos return
def printstatus(): if (dynamics.nsteps % 10) == 0: print """ State Time/fs Temp/K Strain G/(J/m^2) CrackPos/A D(CrackPos)/A ---------------------------------------------------------------------------------""" log_format = ( '%(label)-4s%(time)12.1f%(temperature)12.6f' + '%(strain)12.5f%(G)12.4f%(crack_pos_x)12.2f (%(d_crack_pos_x)+5.2f)' ) log_format2 = ('%(label)-4s%(time)12.1f%(temperature)12.6f') try: atoms.info[ 'label'] = dynamics.state_label # Label for the status line except AttributeError: atoms.info['label'] = 'classical' # Label for the status line atoms.info['time'] = dynamics.get_time() / units.fs atoms.info['temperature'] = (atoms.get_kinetic_energy() / (1.5 * units.kB * len(atoms))) atoms.info['strain'] = get_strain(atoms) try: atoms.info['G'] = get_energy_release_rate(atoms) / (units.J / units.m**2) except: atoms.info['G'] = 0.0 try: orig_crack_pos = atoms.info['CrackPos'].copy() crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) atoms.info['crack_pos_x'] = crack_pos[0] atoms.info['d_crack_pos_x'] = crack_pos[0] - orig_crack_pos[0] print log_format % atoms.info except KeyError: print log_format2 % atoms.info
def printstatus(): if (dynamics.nsteps%10)==0: print """ State Time/fs Temp/K Strain G/(J/m^2) CrackPos/A D(CrackPos)/A ---------------------------------------------------------------------------------""" log_format = ('%(label)-4s%(time)12.1f%(temperature)12.6f'+ '%(strain)12.5f%(G)12.4f%(crack_pos_x)12.2f (%(d_crack_pos_x)+5.2f)') log_format2 = ('%(label)-4s%(time)12.1f%(temperature)12.6f') try: atoms.info['label'] = dynamics.state_label # Label for the status line except AttributeError: atoms.info['label'] = 'classical' # Label for the status line atoms.info['time'] = dynamics.get_time()/units.fs atoms.info['temperature'] = (atoms.get_kinetic_energy() / (1.5*units.kB*len(atoms))) atoms.info['strain'] = get_strain(atoms) try: atoms.info['G'] = get_energy_release_rate(atoms)/(units.J/units.m**2) except: atoms.info['G'] = 0.0 try: orig_crack_pos = atoms.info['CrackPos'].copy() crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) atoms.info['crack_pos_x'] = crack_pos[0] atoms.info['d_crack_pos_x'] = crack_pos[0] - orig_crack_pos[0] print log_format % atoms.info except KeyError: print log_format2 % atoms.info
def check_if_cracked(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) # stop straining if crack has advanced more than tip_move_tol if not atoms.info['is_cracked'] and (crack_pos[0] - orig_crack_pos[0]) > tip_move_tol: atoms.info['is_cracked'] = True del atoms.constraints[atoms.constraints.index(strain_atoms)]
def printstatus(): if dynamics.nsteps == 1: print """ State Time/fs Temp/K Strain G/(J/m^2) CrackPos/A D(CrackPos)/A ---------------------------------------------------------------------------------""" log_format = ( '%(label)-4s%(time)12.1f%(temperature)12.6f' + '%(strain)12.5f%(G)12.4f%(crack_pos_x)12.2f (%(d_crack_pos_x)+5.2f)' ) atoms.info['label'] = dynamics.state_label # Label for the status line atoms.info['time'] = dynamics.get_time() / units.fs atoms.info['temperature'] = (atoms.get_kinetic_energy() / (1.5 * units.kB * len(atoms))) atoms.info['strain'] = get_strain(atoms) atoms.info['G'] = get_energy_release_rate(atoms) / (units.J / units.m**2) crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot, avg_sigma=avg_sigma) atoms.info['crack_pos_x'] = crack_pos[0] atoms.info['d_crack_pos_x'] = crack_pos[0] - orig_crack_pos[0] print log_format % atoms.info
def check_if_cracked(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) # stop straining if crack has advanced more than tip_move_tol if not atoms.info['is_cracked'] and (crack_pos[0] - orig_crack_pos[0]) > tip_move_tol: atoms.info['is_cracked'] = True del atoms.constraints[atoms.constraints.index(strain_atoms)]
def atom_straining(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) # keep straining until the crack tip has advanced to tip_move_tol if not atoms.info['is_cracked'] and (crack_pos[0] - orig_crack_pos[0]) < tip_move_tol: strain_atoms.apply_strain(atoms) elif not atoms.info['is_cracked']: atoms.info['is_cracked'] = True
def update_qm_region(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot, avg_sigma=avg_sigma) qm_list = qmmm_pot.get_qm_atoms(atoms) qm_list = update_hysteretic_qm_region(atoms, qm_list, crack_pos, qm_inner_radius, qm_outer_radius) qmmm_pot.set_qm_atoms(qm_list, atoms)
def update_qm_region(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) qm_list = qmmm_pot.get_qm_atoms() qm_list = update_hysteretic_qm_region(atoms, qm_list, crack_pos, qm_inner_radius, qm_outer_radius, update_marks=True) qmmm_pot.set_qm_atoms(qm_list) #lets try setting the atoms object properties by hand? atoms.hybrid[:] = HYBRID_NO_MARK atoms.hybrid[qm_list] = HYBRID_ACTIVE_MARK
def update_qm_region(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) qm_list = qmmm_pot.get_qm_atoms() qm_list = update_hysteretic_qm_region(atoms, qm_list, crack_pos, qm_inner_radius, qm_outer_radius, update_marks=True) qmmm_pot.set_qm_atoms(qm_list) #lets try setting the atoms object properties by hand? atoms.hybrid[:] = HYBRID_NO_MARK atoms.hybrid[qm_list] = HYBRID_ACTIVE_MARK
def update_qm_region_crack(atoms): mm_pot = Potential(params.mm_init_args, param_filename=params.param_file, cutoff_skin=params.cutoff_skin) crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) old_qm_list = atoms.hybrid_vec.nonzero()[0] new_qm_list = update_hysteretic_qm_region(atoms, old_qm_list, crack_pos, params.qm_inner_radius, params.qm_outer_radius, update_marks=False) #lets try setting the atoms object properties by hand? atoms.hybrid[:] = 0 atoms.hybrid[new_qm_list] = 1 #Distributed Force Mixing Properties: atoms.hybrid_vec[:] = 0 atoms.hybrid_vec[new_qm_list] = 1 atoms.hybrid_1[:] = atoms.hybrid_vec[:] atoms.params['core'] = crack_pos atoms.params['CrackPos'] = crack_pos return
def printstatus(): if dynamics.nsteps == 1: print """ State Time/fs Temp/K Strain G/(J/m^2) CrackPos/A D(CrackPos)/A ---------------------------------------------------------------------------------""" log_format = ('%(label)-4s%(time)12.1f%(temperature)12.6f'+ '%(strain)12.5f%(G)12.4f%(crack_pos_x)12.2f (%(d_crack_pos_x)+5.2f)') atoms.info['label'] = 'D' # Label for the status line atoms.info['time'] = dynamics.get_time()/units.fs atoms.info['temperature'] = (atoms.get_kinetic_energy() / (1.5*units.kB*len(atoms))) atoms.info['strain'] = get_strain(atoms) atoms.info['G'] = get_energy_release_rate(atoms)/(units.J/units.m**2) crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) atoms.info['crack_pos_x'] = crack_pos[0] atoms.info['d_crack_pos_x'] = crack_pos[0] - orig_crack_pos[0] print log_format % atoms.info
def write_crack_cell(self, crack_slab, mm_pot): print crack_slab.get_cell() crack_slab.info['nneightol'] = 1.30 # set nearest neighbour tolerance crack_slab.info['LatticeConstant'] = self.a0 crack_slab.info['C11'] = self.cij[0, 0] crack_slab.info['C12'] = self.cij[0, 1] crack_slab.info['C44'] = self.cij[3, 3] crack_slab.info['YoungsModulus'] = self.E crack_slab.info['PoissonRatio_yx'] = self.nu crack_slab.info['G'] = self.initial_G crack_slab.info['OrigWidth'] = self.orig_width crack_slab.info['OrigHeight'] = self.orig_height crack_slab.info['CrackDirection'] = self.crack_direction crack_slab.info['CleavagePlane'] = self.cleavage_plane crack_slab.info['CrackFront'] = self.crack_front crack_slab.info['strain'] = self.strain #Initial guess for crack_pos crack_slab.info['CrackPos'] = np.array([1.5, 1.5, 1.5]) crack_pos = find_crack_tip_stress_field(crack_slab, calc=mm_pot) print 'Found crack tip at position %s' % crack_pos crack_slab.info['CrackPos'] = crack_pos crack_slab.info['is_cracked'] = False write('crack.xyz', crack_slab)
def write_crack_cell(self, crack_slab, mm_pot): print crack_slab.get_cell() crack_slab.info['nneightol'] = 1.30 # set nearest neighbour tolerance crack_slab.info['LatticeConstant'] = self.a0 crack_slab.info['C11'] = self.cij[0, 0] crack_slab.info['C12'] = self.cij[0, 1] crack_slab.info['C44'] = self.cij[3, 3] crack_slab.info['YoungsModulus'] = self.E crack_slab.info['PoissonRatio_yx'] = self.nu crack_slab.info['G'] = self.initial_G crack_slab.info['OrigWidth'] = self.orig_width crack_slab.info['OrigHeight'] = self.orig_height crack_slab.info['CrackDirection'] = self.crack_direction crack_slab.info['CleavagePlane'] = self.cleavage_plane crack_slab.info['CrackFront'] = self.crack_front crack_slab.info['strain'] = self.strain #Initial guess for crack_pos crack_slab.info['CrackPos'] = np.array([1.5, 1.5, 1.5]) crack_pos = find_crack_tip_stress_field(crack_slab, calc=mm_pot) print 'Found crack tip at position %s' % crack_pos crack_slab.info['CrackPos'] = crack_pos crack_slab.info['is_cracked'] = False write('crack.xyz', crack_slab)
def check_if_cracked(atoms): orig_crack_pos = atoms.info['CrackPos'].copy() crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) if not atoms.info['is_cracked'] and (crack_pos[0] - orig_crack_pos[0]) > tip_move_tol: atoms.info['is_cracked'] = True del atoms.constraints[atoms.constraints.index(strain_atoms)]
crack_slab.positions[:, 0], crack_slab.positions[:, 1], strain, left + crack_seed_length, left + crack_seed_length + strain_ramp_length) print('Applied initial load: strain=%.4f, G=%.2f J/m^2' % (strain, initial_G / (units.J / units.m**2))) crack_slab.set_calculator(mm_pot) minim = Minim(crack_slab, relax_positions=True, relax_cell=False) minim.run(fmax=relax_fmax) # Find initial position of crack tip crack_pos = find_crack_tip_stress_field(crack_slab, calc=mm_pot) print 'Found crack tip at position %s' % crack_pos # Save all calculated materials properties inside the Atoms object crack_slab.info['nneightol'] = 1.3 # nearest neighbour tolerance crack_slab.info['LatticeConstant'] = 5.431 crack_slab.info['C11'] = c[0, 0] crack_slab.info['C12'] = c[0, 1] crack_slab.info['C44'] = c[3, 3] crack_slab.info['YoungsModulus'] = E crack_slab.info['PoissonRatio_yx'] = nu crack_slab.info['SurfaceEnergy'] = gamma crack_slab.info['OrigWidth'] = orig_width crack_slab.info['OrigHeight'] = orig_height crack_slab.info['CrackDirection'] = crack_direction crack_slab.info['CleavagePlane'] = cleavage_plane
crack_slab.positions[:, 0], crack_slab.positions[:, 1], strain, left + crack_seed_length, left + crack_seed_length + strain_ramp_length) print('Applied initial load: strain=%.4f, G=%.2f J/m^2' % (strain, initial_G / (units.J / units.m**2))) # ***** Relaxation of crack slab ***** # optionally, relax the slab, keeping top and bottom rows fixed print('Relaxing slab...') crack_slab.set_calculator(mm_pot) minim = Minim(crack_slab, relax_positions=True, relax_cell=False) minim.run(fmax=0.01) # Find initial position of crack tip crack_pos = find_crack_tip_stress_field(crack_slab, calc=mm_pot) crack_pos = find_crack_tip_coordination(crack_slab, edge_tol=10.0, strip_height=30.0, nneightol=1.3) print 'Found crack tip at position %s' % crack_pos # Save all calculated materials properties inside the Atoms object crack_slab.info['CrackPos'] = crack_pos crack_slab.info['is_cracked'] = False # ******** Save output file ********** # save results in extended XYZ format, including extra properties and info print('Writing crack slab to file %s' % output_file)
pred_corr_logfile.close() else: mm_pot = Potential(mm_init_args, param_filename=pot_file, cutoff_skin=cutoff_skin) atoms = AtomsReader(args.input_file)[-1] atoms.set_calculator(mm_pot) if args.restart: #delete certain keys so they don't cause problem in write_xyz. del_keys = ['force','forces', 'forces0'] array_keys = atoms.arrays.keys() prop_keys = atoms.properties.keys() for key in del_keys: if key in array_keys: del(atoms.arrays[key]) strain_atoms = fix_edges(atoms) current_crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot) print 'Current Crack Position: ', current_crack_pos if not args.restart: print 'Thermalizing Atoms' MaxwellBoltzmannDistribution(atoms, 2.0*sim_T) dynamics = VelocityVerlet(atoms, timestep) def print_context(ats=atoms, dyn=dynamics): print 'steps, T', dyn.nsteps, ats.get_kinetic_energy()/(1.5*units.kB*len(ats)) print 'G', get_energy_release_rate(ats)/(units.J/units.m**2) print 'strain', get_strain(ats) #for 0.25 fs time step we have an image every half #phonon cycle which is plenty dynamics.attach(print_context, interval=32)
def update_qm_region(atoms): crack_pos = find_crack_tip_stress_field(atoms, calc=mm_pot, avg_sigma=avg_sigma) qm_list = qmmm_pot.get_qm_atoms(atoms) qm_list = update_hysteretic_qm_region(atoms, qm_list, crack_pos, qm_inner_radius, qm_outer_radius) qmmm_pot.set_qm_atoms(qm_list, atoms)
def build_crack_cell(self, unit_slab, pot, fix_dist=1.0): """ Creates a CrackCell of the desired size and orientation with the top and bottom layer of atoms constrained. Returns: :class:`Atoms` - the relaxed crack_cell. """ self.nx = int(self.width / unit_slab.get_cell()[0, 0]) self.ny = int(self.height / unit_slab.get_cell()[1, 1]) if self.ny % 2 == 1: self.ny += 1 #self.ny = 1 print 'number of unit cells', self.nx, self.ny crack_slab = unit_slab * (self.nx, self.ny, self.nz) write('ref_slab.xyz', crack_slab) crack_slab.center(self.vacuum, axis=0) crack_slab.center(self.vacuum, axis=1) crack_slab.positions[:, 0] -= crack_slab.positions[:, 0].mean() crack_slab.positions[:, 1] -= crack_slab.positions[:, 1].mean() self.orig_width = (crack_slab.positions[:, 0].max() - crack_slab.positions[:, 0].min()) self.orig_height = (crack_slab.positions[:, 1].max() - crack_slab.positions[:, 1].min()) print(( 'Made slab with %d atoms, original width and height: %.1f x %.1f A^2' % (len(crack_slab), self.orig_width, self.orig_height))) top = crack_slab.positions[:, 1].max() bottom = crack_slab.positions[:, 1].min() left = crack_slab.positions[:, 0].min() right = crack_slab.positions[:, 0].max() #Constrain top and bottom layer of atoms: fixed_mask = ((abs(crack_slab.positions[:, 1] - top) < 1.0) | (abs(crack_slab.positions[:, 1] - bottom) < 1.0)) const = FixAtoms(mask=fixed_mask) crack_slab.set_constraint(const) #Strain is a dimensionless ratio we require elastic tensor #to translate the initial energy flow to the tip into a strain. self.E = youngs_modulus(self.cij, self.cleavage_plane) self.nu = poisson_ratio(self.cij, self.cleavage_plane, self.crack_direction) self.strain = G_to_strain(self.initial_G, self.E, self.nu, self.orig_height) seed = left + self.crack_seed_length tip = left + self.crack_seed_length + self.strain_ramp_length xpos = crack_slab.positions[:, 0] ypos = crack_slab.positions[:, 1] crack_slab.positions[:, 1] += thin_strip_displacement_y( xpos, ypos, self.strain, seed, tip) write('crack_slab_init.xyz', crack_slab) print('Applied initial load: strain=%.4f, G=%.2f J/m^2' % (self.strain, self.initial_G / (units.J / units.m**2))) pot_dir = os.environ['POTDIR'] crack_slab.set_calculator(pot) #Initial crack pos print 'crack_pos before relaxations' print find_crack_tip_stress_field(crack_slab, calc=mm_pot) print('Relaxing slab...') slab_opt = PreconFIRE(crack_slab) slab_opt.run(fmax=self.relax_fmax) return crack_slab