def del_atoms(x=None): rcut = 2.0 #x = Atoms('crack.xyz') if x == None: x = Atoms('1109337334_frac.xyz') else: pass x.set_cutoff(3.0) x.calc_connect() x.calc_dists() rem=[] r = farray(0.0) u = fzeros(3) print len(x) for i in frange(x.n): for n in frange(x.n_neighbours(i)): j = x.neighbour(i, n, distance=3.0, diff=u) if x.distance_min_image(i, j) < rcut and j!=i: rem.append(sorted([j,i])) if i%10000==0: print i rem = list(set([a[0] for a in rem])) if len(rem) > 0: print rem x.remove_atoms(rem) else: print 'No duplicate atoms in list.' x.write('crack_nodup.xyz') return x
def gen_super(self, grain=None, rbt=None, sup_v=6, sup_bxv=2, rcut=2.0): """ :method:`gen_super` Creates a :class:SubGrainBoundary super cell according to conventions described in Rittner and Seidman (PRB 54 6999). Args: grain(:class:`ase.Atoms`): atoms object passed from gen_super_rbt. rbt (list): rigid body translation as fractional translations of the supercell. sup_v(int): Size of supercell along v. sup_bxv(int): Size of supercell along boundary_plane_normal crossed with v. rcut(float): Atom deletion criterion in angstrom. """ io = ImeallIO() if rbt == None: x = Atoms('{0}.xyz'.format(os.path.join(self.grain_dir, self.gbid))) else: x = Atoms(grain) struct_dir = os.path.join(self.grain_dir, 'structs') self.name = '{0}_v{1}bxv{2}_tv{3}bxv{4}_d{5}z'.format(self.gbid, str(sup_v), str(sup_bxv), '0.0', '0.0', str(rcut)) #TODO fix this so it is more transparent. #if rcut = 0 then only a super cell is generated with no deletion of atoms. if rcut > 0.0: x.set_cutoff(2.4) x.calc_connect() x.calc_dists() rem = [] u = np.zeros(3) for i in range(x.n): for n in range(x.n_neighbours(i)): j = x.neighbour(i, n, distance=3.0, diff=u) if x.distance_min_image(i,j) < rcut and j != i: rem.append(sorted([j,i])) rem = list(set([a[0] for a in rem])) if len(rem) > 0: x.remove_atoms(rem) else: print 'No duplicate atoms in list.' else: x = x*(sup_v, sup_bxv, 1) x.set_scaled_positions(x.get_scaled_positions()) if rbt == None: self.struct_file = self.name self.subgrain_dir = io.make_dir(self.calc_dir, self.name) try: with open('{0}/subgb.json'.format(self.subgrain_dir), 'r') as f: j_dict = json.load(f) except IOError: j_dict = {} j_dict['name'] = self.name j_dict['param_file'] = self.param_file j_dict['rbt'] = [0.0, 0.0] j_dict['rcut'] = rcut with open('{0}/subgb.json'.format(self.subgrain_dir), 'w') as f: json.dump(j_dict, f, indent=2) else: return sup_v, sup_bxv, x
def delete_atoms(self, grain=None, rcut=2.0): """ Delete atoms below a certain distance threshold. Args: grain(:class:`quippy.Atoms`): Atoms object of the grain. rcut(float): Atom deletion criterion. Returns: :class:`quippy.Atoms` object with atoms nearer than deletion criterion removed. """ io = ImeallIO() if grain == None: x = Atoms('{0}.xyz'.format(os.path.join(self.grain_dir, self.gbid))) else: x = Atoms(grain) x.set_cutoff(2.4) x.calc_connect() x.calc_dists() rem = [] u = fzeros(3) for i in frange(x.n): for n in frange(x.n_neighbours(i)): j = x.neighbour(i, n, distance=3.0, diff=u) if x.distance_min_image(i, j) < rcut and j != i: rem.append(sorted([j, i])) rem = list(set([a[0] for a in rem])) if len(rem) > 0: x.remove_atoms(rem) else: print 'No duplicate atoms in list.' if grain == None: self.name = '{0}_d{1}'.format(self.gbid, str(rcut)) self.subgrain_dir = io.make_dir(self.calc_dir, self.name) self.struct_file = gbid + '_' + 'n' + str( len(rem)) + 'd' + str(rcut) x.write('{0}.xyz'.format( os.path.join(self.subgrain_dir, self.struct_file))) return len(rem) else: return x
z = [0, 1, 1] s_system = list(x) s_system.extend(y) name = ''.join(map(str, s_system)).replace('-', '') print x, y, z disloc = Dislocation(x=x, y=y, z=z, name=name) disloc.gen_edge_dislocation() POT_DIR = '/Users/lambert/pymodules/imeall/imeall/potentials' eam_pot = os.path.join(POT_DIR, 'Fe_Mendelev.xml') print 'Open Atoms' at = Atoms('e{0}.xyz'.format(name)) at.set_cutoff(3.0) at.calc_connect() print 'Delete atoms' at = gbr.delete_atoms(grain=at, rcut=1.5) at.info['OrigHeight'] = at.positions[:, 1].max() - at.positions[:, 1].min() r_scale = 1.00894848312 rem = [] for atom in at: if atom.position[0] <= 0.00 and atom.position[1] <= 100.0: rem.append(atom.index + 1) print 'Removing ', len(rem), ' atoms.' if len(rem) > 0: at.remove_atoms(rem) else: print 'No atoms displaced from unitcell'
def pp_nye_tensor(at, rr=15.0, dis_type='edge'): # Post Processing routine to append nye tensor information # to atoms object. # Load reference slab and calculate connectivity ref_slab = Atoms('./ref_slab.xyz') at.set_cutoff(3.0) at.calc_connect() ref_slab.set_cutoff(3.0) ref_slab.calc_connect() core = np.zeros(3) # To save time it is possible to only # calculate the nye tensor for a 'core' region # determined by cutting out a cluster: if dis_type in ['edge','screw']: try: core = at.info['core'] except: sys.exit('No Core Info') print '\t Core Position: ', core elif dis_type == 'crack': core = at.info['CrackPos'] print '\t Crack Position: ', core fixed_mask = (np.sqrt((at.positions[:,0]-core[0])**2 + (at.positions[:,1]-core[1])**2) < rr) if dis_type in ['edge','screw']: at.add_property('edgex', 0.0) at.add_property('edgey', 0.0) at.add_property('screw', 0.0) #Going to append full nye tensor to the crack tip: elif dis_type == 'crack': at.add_property('nye', 0.0, n_cols=9, overwrite=True) cl = at.select(mask=fixed_mask, orig_index=True) print '\t Size of cluster: ', len(cl) # Append screw and edge information # Probably should just pass an array at this stage? alpha = calc_nye_tensor(cl, ref_slab, 3, 3, cl.n) cl.edgex = alpha[2,0,:] cl.edgey = alpha[2,1,:] cl.screw = alpha[2,2,:] # Update quantum region according to the # position of the dislocation core: if dis_type in ['edge', 'screw']: if dis_type == 'screw': defect_pos = cl.screw elif dis_type == 'edge': defect_pos = cl.edgex total_def = 0. c = np.array([0.,0.,0.]) for i in range(len(cl)): total_def = total_def + defect_pos[i] c[0] = c[0] + cl.positions[i,0]*defect_pos[i] c[1] = c[1] + cl.positions[i,1]*defect_pos[i] c[0] = c[0]/total_def c[1] = c[1]/total_def c[2] = cl.lattice[2,2]/2. core[:] = c.copy() if dis_type in ['edge', 'screw']: for index, screw, edgex, edgey in zip(cl.orig_index, cl.screw, cl.edgex, cl.edgey): # Now thread atoms back in looks like select will have indices in the fortran convention. at.screw[index-1] = screw at.edgex[index-1] = edgex at.edgey[index-1] = edgey elif dis_type == 'crack': for orig_index, index in zip(cl.orig_index, range(len(cl))): at.nye[:, orig_index-1] = alpha[:,:,index].T.reshape(9) return core
defect.info['OrigHeight'] = orig_height strain_atoms = fix_edges_defect(defect) xpos = defect.positions[:,0] ypos = defect.positions[:,1] seed = 0.0 tip = 0.0 if False: strain = G_to_strain(initial_G, E, nu, orig_height) print 'Applied strain: ', strain*100., '%' defect.info['strain'] = strain defect.info['G'] = initial_G defect.positions[:,1] += thin_strip_displacement_y(xpos, ypos, strain, seed, tip) defect.set_cutoff(3.0) defect.calc_connect() xlen = defect.positions[:,0].max() - defect.positions[:,0].min() ylen = defect.positions[:,2].max() - defect.positions[:,2].min() defect_object = {} defect_object['x'] = x defect_object['y'] = y defect_object['z'] = z defect_object['T'] = sim_T/units.kB defect_json(**defect_object) if run_dyn: # Load atoms and set potential # If tight-binding need to re-initialize potential
def pp_nye_tensor(at, rr=15.0, dis_type='edge'): # Post Processing routine to append nye tensor information # to atoms object. # Load reference slab and calculate connectivity ref_slab = Atoms('./ref_slab.xyz') at.set_cutoff(3.0) at.calc_connect() ref_slab.set_cutoff(3.0) ref_slab.calc_connect() core = np.zeros(3) # To save time it is possible to only # calculate the nye tensor for a 'core' region # determined by cutting out a cluster: if dis_type in ['edge', 'screw']: try: core = at.info['core'] except: sys.exit('No Core Info') print '\t Core Position: ', core elif dis_type == 'crack': core = at.info['CrackPos'] print '\t Crack Position: ', core fixed_mask = (np.sqrt((at.positions[:, 0] - core[0])**2 + (at.positions[:, 1] - core[1])**2) < rr) if dis_type in ['edge', 'screw']: at.add_property('edgex', 0.0) at.add_property('edgey', 0.0) at.add_property('screw', 0.0) #Going to append full nye tensor to the crack tip: elif dis_type == 'crack': at.add_property('nye', 0.0, n_cols=9, overwrite=True) cl = at.select(mask=fixed_mask, orig_index=True) print '\t Size of cluster: ', len(cl) # Append screw and edge information # Probably should just pass an array at this stage? alpha = calc_nye_tensor(cl, ref_slab, 3, 3, cl.n) cl.edgex = alpha[2, 0, :] cl.edgey = alpha[2, 1, :] cl.screw = alpha[2, 2, :] # Update quantum region according to the # position of the dislocation core: if dis_type in ['edge', 'screw']: if dis_type == 'screw': defect_pos = cl.screw elif dis_type == 'edge': defect_pos = cl.edgex total_def = 0. c = np.array([0., 0., 0.]) for i in range(len(cl)): total_def = total_def + defect_pos[i] c[0] = c[0] + cl.positions[i, 0] * defect_pos[i] c[1] = c[1] + cl.positions[i, 1] * defect_pos[i] c[0] = c[0] / total_def c[1] = c[1] / total_def c[2] = cl.lattice[2, 2] / 2. core[:] = c.copy() if dis_type in ['edge', 'screw']: for index, screw, edgex, edgey in zip(cl.orig_index, cl.screw, cl.edgex, cl.edgey): # Now thread atoms back in looks like select will have indices in the fortran convention. at.screw[index - 1] = screw at.edgex[index - 1] = edgex at.edgey[index - 1] = edgey elif dis_type == 'crack': for orig_index, index in zip(cl.orig_index, range(len(cl))): at.nye[:, orig_index - 1] = alpha[:, :, index].T.reshape(9) return core
defect.info['OrigHeight'] = orig_height strain_atoms = fix_edges_defect(defect) xpos = defect.positions[:, 0] ypos = defect.positions[:, 1] seed = 0.0 tip = 0.0 if False: strain = G_to_strain(initial_G, E, nu, orig_height) print 'Applied strain: ', strain * 100., '%' defect.info['strain'] = strain defect.info['G'] = initial_G defect.positions[:, 1] += thin_strip_displacement_y( xpos, ypos, strain, seed, tip) defect.set_cutoff(3.0) defect.calc_connect() xlen = defect.positions[:, 0].max() - defect.positions[:, 0].min() ylen = defect.positions[:, 2].max() - defect.positions[:, 2].min() defect_object = {} defect_object['x'] = x defect_object['y'] = y defect_object['z'] = z defect_object['T'] = sim_T / units.kB defect_json(**defect_object) if run_dyn: # Load atoms and set potential # If tight-binding need to re-initialize potential
def NetCDFReader(source, frame=None, start=0, stop=None, step=1): opened = False if isinstance(source, str): opened = True source = netcdf_file(source) from quippy import Atoms DEG_TO_RAD = pi/180.0 remap_names = {'coordinates': 'pos', 'velocities': 'velo', 'cell_lengths': None, 'cell_angles': None, 'cell_lattice': None, 'cell_rotated': None} prop_type_to_value = {PROPERTY_INT: 0, PROPERTY_REAL: 0.0, PROPERTY_STR: "", PROPERTY_LOGICAL: False} prop_dim_to_ncols = {('frame','atom','spatial'): 3, ('frame','atom','label'): 1, ('frame', 'atom'): 1} if frame is not None: start = frame stop = frame+1 step = 1 else: if stop is None: stop = source.variables['cell_lengths'].shape[0] for frame in range(start, stop, step): cl = source.variables['cell_lengths'][frame] ca = source.variables['cell_angles'][frame] lattice = make_lattice(cl[0],cl[1],cl[2],ca[0]*DEG_TO_RAD,ca[1]*DEG_TO_RAD,ca[2]*DEG_TO_RAD) at = Atoms(n=netcdf_dimlen(source, 'atom'), lattice=lattice, properties={}) for name, var in source.variables.iteritems(): name = remap_names.get(name, name) if name is None: continue name = str(name) # in case it's a unicode string if 'frame' in var.dimensions: if 'atom' in var.dimensions: # It's a property value = var[frame] if value.dtype.kind != 'S': value = value.T at.add_property(name, value) else: # It's a param if var.dimensions == ('frame','string'): # if it's a single string, join it and strip it at.params[name] = ''.join(var[frame]).strip() else: if name == 'cutoff': at.set_cutoff(var[frame], at.cutoff_break) elif name == 'cutoff_factor': at.set_cutoff_factor(var[frame], at.cutoff_break) elif name == 'cutoff_break': at.set_cutoff(at.cutoff, var[frame]) elif name == 'cutoff_factor_break': at.set_cutoff_factor(var[frame], at.cutoff_break) elif name == 'nneightol': at.nneightol = var[frame] else: at.params[name] = var[frame].T if 'cell_rotated' in source.variables: cell_rotated = source.variables['cell_rotated'][frame] orig_lattice = source.variables['cell_lattice'][frame] #if cell_rotated == 1: at.set_lattice(orig_lattice, True) yield at def close(self): if self.opened: source.close()
print 'Running WITH EAM as embedded cluster' qm_pot_file = os.path.join(pot_dir, 'PotBH_fakemod.xml') print qm_pot_file mm_init_args = 'IP EAM_ErcolAd do_rescale_r=T r_scale=1.01' # Classical potential qm_pot = Potential(mm_init_args, param_filename=qm_pot_file, cutoff_skin=cutoff_skin) qmmm_pot = set_qmmm_pot(atoms, atoms.params['CrackPos'], mm_pot, qm_pot) strain_atoms = fix_edges(atoms) print 'Setup dynamics' #If input_file is crack.xyz the cell has not been thermalized yet. #Otherwise it will recover temperature from the previous run. print 'Attaching trajectories to dynamics' trajectory = AtomsWriter(traj_file) #Only wriates trajectory if the system is in the LOTFDynamicas #Interpolation atoms.wrap() atoms.set_cutoff(3.0) atoms.calc_connect() print 'Running Crack Simulation' RELAXATION = False if RELAXATION: dynamics = FIRE(atoms) dynamics.attach(pass_trajectory_context(trajectory, dynamics), traj_interval, dynamics) dynamics.run(fmax=0.1) else: dynamics = LOTFDynamics(atoms, timestep, extrapolate_steps) dynamics.attach(pass_trajectory_context(trajectory, dynamics), traj_interval, dynamics) nsteps = 2000 dynamics.run(nsteps)
supercell = int(sys.argv[3]) structure_2d = Atoms( sheet(species, fs_lattice_parameter, gamma=angle, supercell=supercell, orthorhombic=True)) structure_2d.name = "W_{0}_{1:.0f}_{2}x{2}".format(sheet_type, angle, supercell) relax_cell = True # structure_2d.translate((0, 0, -structure_2d.get_center_of_mass()[2])) # castep_write(structure_2d, structure_2d.name, optimise=False, fix_lattice=False) structure_2d.set_cutoff(fs_potential.cutoff() + 2.0) structure_2d.set_calculator(fs_potential) minimiser = Minim(structure_2d, relax_positions=True, relax_cell=relax_cell) minimiser.run() castep_write(structure_2d, structure_2d.name, optimise=False, fix_lattice=True) # From 10.1007/BF01184339, thermal expansion of tungsten is small, but for # different temperatures we can expand a bit: # 3000 K V/V0 = 1.11; # 5000 K V/V0 = 1.29 # if temperature == 1000: structure_2d.set_lattice(structure_2d.lattice * 1.003, scale_positions=True)
ats.info['adsorbate_info']=None with open('crack_info.pckl','r') as f: crack_dict= pickle.load(f) print 'G: {}, H_d: {}, sim_T {}'.format(crack_dict['initial_G']*(units.m**2/units.J), crack_dict['H_d'], crack_dict['sim_T']/units.kB) h_list = hydrify.hydrogenate_gb(ats, mode='CrackTip', d_H=crack_dict['H_d'][0], tetrahedral=True, crackpos_fix=ats.params['CrackPos']) for h in h_list: ats.add_atoms(h,1) #ats.wrap() ats.write('crackH.xyz') ats = None ats = Atoms('crackH.xyz') ats.set_cutoff(2.4) ats.calc_connect() ats.calc_dists() filter_mask = (ats.get_atomic_numbers()==1) h_atoms = ats.select(filter_mask, orig_index=True) rem=[] u = np.zeros(3) for i in h_atoms.orig_index: print 'hindex', i print 'nneighbs', ats.n_neighbours(i) for n in range(ats.n_neighbours(i)): j = ats.neighbour(i, n+1, distance=2.4, diff=u) print 'neighb index', j if ats.distance_min_image(i,j) < 1.1 and j!=i: rem.append(i) rem = list(set(rem))