def build_GB(unit_GB_up, unit_GB_down, tx, tz): ny = int(ceil(height / unit_GB_up.cell[1, 1])) # print ny ny2 = ny * 2. GB_up = supercell(unit_GB_up, 2, ny2, 6) GB_up = GB_up.select(GB_up.positions[:, 1] >= GB_up.positions[:, 1].mean()) print "created %d atoms in up grain" % (len(GB_up)) GB_down = supercell(unit_GB_down, 2, ny2, 6) GB_down = GB_down.select( GB_down.positions[:, 1] <= ny * unit_GB_down.cell[1, 1]) print "created %d atoms in down grain" % (len(GB_down)) # GB_up.positions[:,1]+= GB_up.positions[:, 1].max() GB_down.positions[:, 0] += tx GB_down.positions[:, 2] += tz GB = GB_down + GB_up # GB.set_cell([GB_down.cell[0],GB_down.cell[1]*2,GB_down.cell[2]]) return GB
def makecrack_main(params, stem): """Given a CrackParams object `param`, construct and return a new crack slab Atoms object.""" xmlfilename = stem+'.xml' print_title('Initialisation') verbosity_push(params.io_verbosity) params.print_() print("Initialising classical potential with args " + params.classical_args.strip() + " from file " + xmlfilename) classicalpot = Potential(params.classical_args, param_filename=xmlfilename) classicalpot.print_() mpi_glob = MPI_context() crack_slab, width, height, E, v, v2, bulk = crack_make_slab(params, classicalpot) if params.crack_free_surfaces: depth = crack_slab.pos[3,:].max() - crack_slab.pos[3,:].min() else: depth = crack_slab.lattice[3,3] # Save bulk cube (used for qm_rescale_r parameter in crack code) if params.qm_args.startswith('TB'): bigger_bulk = supercell(bulk, 2, 2, 2) bulk = bigger_bulk bulk.write(stem+'_bulk.xyz') crack_slab.write(stem+'_slab.xyz') crack_slab.params['OrigWidth'] = width crack_slab.params['OrigHeight'] = height crack_slab.params['OrigDepth'] = depth crack_slab.params['YoungsModulus'] = E crack_slab.params['PoissonRatio_yx'] = v crack_slab.params['PoissonRatio_yz'] = v2 # Open surfaces, remain periodic in z direction (normal to plane) # and optionally also in x direction if crack_double_ended is true if not params.crack_double_ended: crack_slab.lattice[1,1] = crack_slab.lattice[1,1] + params.crack_vacuum_size crack_slab.lattice[2,2] = crack_slab.lattice[2,2] + params.crack_vacuum_size crack_slab.set_lattice(crack_slab.lattice, False) # 3D crack with free surfaces at z = +/- depth/2 if params.crack_free_surfaces: crack_slab.pos[3,:] -= crack_slab.pos[3,:].mean() # center on z=0 crack_slab.lattice[3,3] = crack_slab.lattice[3,3] + params.crack_vacuum_size crack_slab.set_lattice(crack_slab.lattice, False) # Map atoms into cell AFTER changing to the new lattice crack_slab.map_into_cell() miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max() assert abs((maxy-miny) - height) < 1e-5 # be sure that remapping didn't change height of slab # Add various properties to crack_slab crack_slab.add_property('hybrid', 0) crack_slab.add_property('hybrid_mark', HYBRID_NO_MARK) crack_slab.add_property('changed_nn', 0) crack_slab.add_property('move_mask', 0) crack_slab.add_property('nn', 0) crack_slab.add_property('old_nn', 0) crack_slab.add_property('md_old_changed_nn', 0) crack_slab.add_property('edge_mask', 0) crack_slab.add_property('crack_surface', False) crack_slab.add_property('crack_front', False) if params.crack_fix_dipoles: crack_slab.add_property('fixdip', False) print_title('Fixing Atoms') # Fix top and bottom edges - anything within crack_edge_fix_tol of ymax or ymin is fixed miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max() crack_slab.move_mask[:] = 1 crack_slab.move_mask[(abs(crack_slab.pos[2,:]-maxy) < params.crack_edge_fix_tol) | (abs(crack_slab.pos[2,:]-miny) < params.crack_edge_fix_tol)] = 0 if params.crack_fix_sides: maxx, minx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max() crack_slab.move_mask[(abs(crack_slab.pos[1,:]-maxx) < params.crack_edge_fix_tol) | (abs(crack_slab.pos[1,:]-minx) < params.crack_edge_fix_tol)] = 0 print('%d atoms. %d fixed atoms' % (crack_slab.n, crack_slab.n - crack_slab.move_mask.sum())) print_title('Setting edge mask') crack_slab.edge_mask[:] = 0 minx, maxx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max() crack_slab.edge_mask[(abs(crack_slab.pos[1,:]-minx) < params.selection_edge_tol) | (abs(crack_slab.pos[1,:]-maxx) < params.selection_edge_tol)] = 1 miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max() crack_slab.edge_mask[(abs(crack_slab.pos[2,:]-miny) < params.selection_edge_tol) | (abs(crack_slab.pos[2,:]-maxy) < params.selection_edge_tol)] = 1 if params.crack_free_surfaces: # Open surfaces at +/- z minz, maxz = crack_slab.pos[3,:].min(), crack_slab.pos[3,:].max() crack_slab.edge_mask[(abs(crack_slab.pos[3,:]-minz) < params.selection_edge_tol) | (abs(crack_slab.pos[3,:]-maxz) < params.selection_edge_tol)] = 1 if params.crack_fix_dipoles: print_title('Fixing dipoles') crack_slab.fixdip[(abs(crack_slab.pos[2,:]-maxy) < params.crack_fix_dipoles_tol) | (abs(crack_slab.pos[2,:]-miny) < params.crack_fix_dipoles_tol)] = 1 if params.crack_fix_sides: maxx, minx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max() crack_slab.fixdip[(abs(crack_slab.pos[1,:]-maxx) < params.crack_fix_dipoles_tol) | (abs(crack_slab.pos[1,:]-minx) < params.crack_fix_dipoles_tol)] = 1 if params.crack_curved_front: crack_make_seed_curved_front(crack_slab, params) else: crack_make_seed(crack_slab, params) if params.crack_apply_initial_load: crack_calc_load_field(crack_slab, params, classicalpot, params.crack_loading, overwrite_pos=True, mpi=mpi_glob) crack_slab.write('dump.xyz') crack_update_connect(crack_slab, params) if not params.simulation_classical: if (params.selection_method.strip() == 'crack_front' or params.crack_tip_method.strip() == 'local_energy'): classicalpot.calc(crack_slab, local_energy=True) crack_setup_marks(crack_slab, params) crack_update_selection(crack_slab, params) if params.any_per_atom_tau(): # Set up per_atom_tau property for ramped Langevin thermostat: # # tau # ^ # |\ /| |\ /| max_tau # | \ / | | \ / | # | \ / | constant E | \ / | # | \ / | (tau = 0) | \ / | # | \/ | | \/ | # +----------+---------------------+----------+---> x # -w/2 -w/2+r w/2-r w/2 w_by_2 = crack_slab.OrigWidth/2. ramp_len = params.crack_thermostat_ramp_length max_tau = params.crack_thermostat_ramp_max_tau print 'Adding thermostat ramp with length', ramp_len, 'max_tau', max_tau @np.vectorize def tau(x): if x < -w_by_2 + ramp_len/2: q = (x+w_by_2)/(ramp_len/2.) return max_tau*(1.- q) elif (x > -w_by_2 + ramp_len/2 and x < -w_by_2 + ramp_len): q = (x+w_by_2-ramp_len/2.)/(ramp_len/2.) return max_tau*q elif (x > -w_by_2 + ramp_len and x < w_by_2 - ramp_len): return 0. elif (x > w_by_2 - ramp_len and x < w_by_2 - ramp_len/2): q = (x-w_by_2+ramp_len)/(ramp_len/2.) return max_tau*(1.- q) else: q = (x-w_by_2+ramp_len/2.)/(ramp_len/2.) return max_tau*q crack_slab.add_property('per_atom_tau', tau(crack_slab.pos[1,:])) return crack_slab
print 'Starting threaded quippy server on %s:%d with N_JOBS=%d' % (ip, port, N_JOBS) server_thread.start() t_init = time.time() # we need an input Queue for each client: this is so that we can # exploit wavefunction reuse by sending consecutive clusters belonging # to the same atom to the same QM partition input_qs = [Queue() for i in range(N_JOBS)] output_q = Queue() cluster_map = {} # setup clusters to be calculated d = diamond(5.44, 14) at = supercell(d, 2, 2, 2) at.rattle(0.05) at.calc_connect() clusters = list( iter_atom_centered_clusters(at, buffer_hops=4, randomise_buffer=False)) pot = Potential('IP SW', param_filename='params.xml') for i, c in enumerate(clusters): client_id, nstep = i % N_JOBS, i // N_JOBS data = pack_atoms_to_reftraj_str(c, nstep) cluster_map[(client_id, nstep)] = (c, i) input_qs[client_id].put(data) pot.calc(c, args_str='energy force virial') t_clus = time.time()
configs = AtomsReader(infile, start=opt.range.start, stop=opt.range.stop, step=opt.range.step) for frame, q0 in enumerate(configs): print 'Read %d atoms from file %s frame %d' % (q0.n, infile, frame) diameter = farray(0, dtype=np.int32) ring_sizes = range(1, opt.max_ring_size + 1) if opt.supercell is None: q = q0 else: print 'Forming %d x %d x %d supercell' % tuple(opt.supercell) q = supercell(q0, opt.supercell[0], opt.supercell[1], opt.supercell[2]) q.map_into_cell() q.set_cutoff(opt.si_o_cutoff) q.calc_connect() if opt.tetra: print 'Converting topology from Si-O-Si to Si-Si' si_si, si_o, si_si_cutoff = tetrahedra_to_bonds(q) if opt.si_si_cutoff is None: opt.si_si_cutoff = si_si_cutoff dm = distance_map(q, q.n, q.n, diameter=diameter) print 'Distance map diameter %d' % diameter print 'Max ring size %d' % opt.max_ring_size
fs_lattice_parameter = 3.18 species = 74 lattice = quippy.bcc # This is a little bit higher as python sometimes truncates 3.99 max_atoms = 512 if lattice.func_name == 'sc': lattice_parameter = fs_lattice_parameter*0.5*(2**0.5) else: lattice_parameter = fs_lattice_parameter # Make a cubic supercell with up to max_atoms in it bulk = lattice(lattice_parameter, species) n_supercell = int((float(max_atoms)/bulk.n)**(1.0/3.0)) bulk = supercell(bulk, n_supercell, n_supercell, n_supercell) fs_potential = Potential('IP FS') fs_potential.set_calc_args({'E_scale': 0.99519, 'r_scale': 0.99302}) bulk.set_cutoff(fs_potential.cutoff() + 2.0) bulk.set_calculator(fs_potential) minimiser = Minim(bulk, relax_positions=True, relax_cell=True) minimiser.run() TEMPERATURE = 5000 # 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