def crack_strain_energy_release_rate(at, bulk=None, f_min=.8, f_max=.9, stem=None, avg_pos=False): """ Compute strain energy release rate G from elastic potential energy in a strip """ print 'Analytical effective elastic modulus E\' = ', at.YoungsModulus/(1-at.PoissonRatio_yx**2), 'GPa' print 'Analytical energy release rate G = ', crack_measure_g(at, at.YoungsModulus, at.PoissonRatio_yx, at.OrigHeight), 'J/m^2' if bulk is None: if stem is None: raise ValueError('Either "bulk" or "stem" must be present') bulk = Atoms(stem+'_bulk.xyz') if not hasattr(at, 'local_energy') or not hasattr(bulk, 'energy'): if stem is None: raise ValueError('local_energy property not found in Atoms and "stem" is missing') xmlfile = stem+'.xml' params = CrackParams(xmlfile) pot = Potential(params.classical_args, param_filename=stem+'.xml') pot.print_() if not hasattr(at, 'local_energy'): if avg_pos: tmp_pos = at.pos.copy() at.pos[...] = at.avgpos at.set_cutoff(pot.cutoff()+1.) at.calc_connect() pot.calc(at, args_str="local_energy") if avg_pos: at.pos[...] = tmp_pos if not hasattr(bulk, 'energy'): bulk.set_cutoff(pot.cutoff()+1.) bulk.calc_connect() pot.calc(bulk, args_str='energy') h = at.pos[2,:].max() - at.pos[2,:].min() h0 = at.OrigHeight strain = (h - h0)/h0 print 'Applied strain', strain x_min = f_min*at.OrigWidth - at.OrigWidth/2. x_max = f_max*at.OrigWidth - at.OrigWidth/2. strip = np.logical_and(at.move_mask == 1, np.logical_and(at.pos[1,:] > x_min, at.pos[1,:] < x_max)) at.add_property('strip', strip, overwrite=True) strip_depth = at.lattice[3,3] strip_width = at.pos[1,strip].max() - at.pos[1,strip].min() strip_height = at.pos[2,strip].max() - at.pos[2,strip].min() strip_volume = strip_width*strip_height*strip_depth print 'Strip contains', strip.sum(), 'atoms', 'width', strip_width, 'height', strip_height, 'volume', strip_volume strain_energy_density = (at.local_energy[strip].sum() - bulk.energy/bulk.n*strip.sum())/strip_volume print 'Strain energy density in strip', strain_energy_density, 'eV/A**3' E_effective = 2*strain_energy_density/strain**2*GPA print 'Effective elastic modulus E =', E_effective, 'GPa' G_effective = strain_energy_density*strip_height*J_PER_M2 print 'Effective energy release rate G =', G_effective, 'J/m^2' return G_effective
print 'Input File', args.input_file r_scale = 1.0 if args.pot_type == 'EAM': pot = Potential('IP EAM_ErcolAd do_rescale_r=T r_scale=1.0', r_scale=r_scale, param_filename=args.input_file) elif args.pot_type == 'GAP': pot = Potential('IP GAP', param_filename='gp33b.xml') #pot.set_calc_args({'local_gap_variance': False}) else: sys.exit('Invalid pot type.') fe_bulk.set_calculator(pot) print pot.cutoff() initial_a0 = fe_bulk.get_cell()[0][0] print 'Before Relaxation' print 'Energy', fe_bulk.get_potential_energy() / len(fe_bulk) print fe_bulk.get_cell().round(5) #fe_bulk.set_array('local_gap_variance', pot.results['local_gap_variance']) print fe_bulk.properties.keys() print fe_bulk.properties fe_bulk.rattle() trajectory = AtomsWriter('minim.xyz') def traj_writer(dynamics):
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)
def molecular_dynamics(system, potential, potential_filename=None, temperature=300, total_steps=1100000, timestep=1.0, connect_interval=200, write_interval=20000, equilibration_steps=100000, out_of_plane=None, random_seed=None): """ Run very simple molecular dynamics to generate some configurations. Writes configurations out as xyz and CASTEP files. """ info("Inside MD.") if random_seed is None: random_seed = random.SystemRandom().randint(0, 2**63) quippy.system.system_set_random_seeds(random_seed) info("Quippy Random Seed {0}.".format(random_seed)) system = Atoms(system) # Can take Potential objects, or just use a string if not isinstance(potential, Potential): if potential_filename: potential = Potential(potential, param_filename=potential_filename) else: potential = Potential(potential) system.set_calculator(potential) dynamical_system = DynamicalSystem(system) with Capturing(debug_on_exit=True): dynamical_system.rescale_velo(temperature) if out_of_plane is not None: # Stop things moving vertically in the cell dynamical_system.atoms.velo[3, :] = 0 base_dir = os.getcwd() run_path = '{0}_{1:g}/'.format(system.info['name'], temperature) info("Putting files in {0}.".format(run_path)) os.mkdir(run_path) os.chdir(run_path) trajectory = 'traj_{0}_{1:g}.xyz'.format(system.info['name'], temperature) out = AtomsWriter(trajectory) dynamical_system.atoms.set_cutoff(potential.cutoff() + 2.0) dynamical_system.atoms.calc_connect() potential.calc(dynamical_system.atoms, force=True, energy=True, virial=True) structure_count = 0 # Basic NVE molecular dynamics for step_number in range(1, total_steps + 1): dynamical_system.advance_verlet1(timestep, virial=dynamical_system.atoms.virial) potential.calc(dynamical_system.atoms, force=True, energy=True, virial=True) dynamical_system.advance_verlet2(timestep, f=dynamical_system.atoms.force, virial=dynamical_system.atoms.virial) # Maintenance of the system if not step_number % connect_interval: debug("Connect at step {0}".format(step_number)) dynamical_system.atoms.calc_connect() if step_number < equilibration_steps: with Capturing(debug_on_exit=True): dynamical_system.rescale_velo(temperature) if not step_number % write_interval: debug("Status at step {0}".format(step_number)) # Print goes to captured stdout with Capturing(debug_on_exit=True): dynamical_system.print_status( epot=dynamical_system.atoms.energy) dynamical_system.rescale_velo(temperature) if step_number > equilibration_steps: debug("Write at step {0}".format(step_number)) out.write(dynamical_system.atoms) sp_path = '{0:03d}'.format(structure_count) write_filename = '{0}_{1:g}.{2:03d}'.format( system.info['name'], temperature, structure_count) os.mkdir(sp_path) os.chdir(sp_path) castep_write(dynamical_system.atoms, filename=write_filename) espresso_write(dynamical_system.atoms, prefix=write_filename) write_extxyz("{0}.xyz".format(write_filename), dynamical_system.atoms) info("Wrote a configuration {0}.".format(write_filename)) os.chdir('..') structure_count += 1 out.close() os.chdir(base_dir) info("MD Done.")
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 # if TEMPERATURE == 1000: bulk.set_lattice(bulk.lattice*1.003, scale_positions=True) elif TEMPERATURE == 3000: bulk.set_lattice(bulk.lattice*(1.11**(1.0/3)), scale_positions=True)