Beispiel #1
0
def relax_gb(gb_file='file_name',
             traj_steps=120,
             total_steps=1200,
             force_tol=0.05):
    """Method to relax a grain_boundary bicrystal structure. Requires a .json
    file with at a minimum the 'param_file' variable specified.

    Args:
      gb_file(str): gbid.
      traj_steps(int): number of steps between print trajectories.
      total_steps(int): total number of force relaxation steps.
      force_tol(float): Force relaxation criterion in ev/A.

    Returns:
      :class:`ase.Atoms` Object
    """
    def converged(grain, smax, fmax):
        maxstress = max(grain.get_stress().ravel())
        rmsforces = np.sum(grain.get_forces()**2, axis=1)**0.5
        maxforce = max(rmsforces)
        if maxforce < fmax and maxstress < smax:
            return True
        return False

    with open('subgb.json', 'r') as outfile:
        j_dict = json.load(outfile)
    try:
        POT_DIR = os.path.join(app.root_path, 'potentials')
    except KeyError:
        sys.exit(
            "Please set POTDIR in os environment. `export POTDIR='path/to/potfiles/`"
        )
    try:
        param_file = j_dict['param_file']
        if param_file == 'iron_mish.xml':
            eam_pot = os.path.join(POT_DIR, 'iron_mish.xml')
            r_scale = 1.0129007626
        elif param_file == 'Fe_Mendelev.xml':
            eam_pot = os.path.join(POT_DIR, 'Fe_Mendelev.xml')
            r_scale = 1.00894848312
        elif param_file == 'PotBH.xml':
            eam_pot = os.path.join(POT_DIR, 'PotBH.xml')
            r_scale = 1.00894848312
        elif param_file == 'Fe_Ackland.xml':
            eam_pot = os.path.join(POT_DIR, 'Fe_Ackland.xml')
            r_scale = 1.00894185389
        elif param_file == 'Fe_Dudarev.xml':
            eam_pot = os.path.join(POT_DIR, 'Fe_Dudarev.xml')
            r_scale = 1.01279093417
        elif param_file == 'gp33b.xml':
            eam_pot = os.path.join(POT_DIR, 'gp33b.xml')
            sparse_file = 'gp33b.xml.sparseX.GAP_2016_10_3_60_19_29_10_8911'
            eam_pot_sparse = os.path.join(POT_DIR, sparse_file)
            shutil.copy(eam_pot, './')
            shutil.copy(eam_pot_sparse, './')
        else:
            print 'No paramfile found!'
            sys.exit()
    except KeyError:
        print 'No EAM potential file with that name. Relax failed.'
        sys.exit()

    print 'Using: ', eam_pot
    pot_file = eam_pot.split('/')[-1]
    print '{0}.xyz'.format(gb_file)
    print os.getcwd()
    grain = io.read('{0}.xyz'.format(gb_file), index='-1')
    if param_file != 'gp33b.xml':
        pot = Potential(
            'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale),
            param_filename=eam_pot)
    else:
        pot = Potential('IP GAP', param_filename=eam_pot)

    grain.set_calculator(pot)
    grain.info['adsorbate_info'] = None
    E_gb_init = grain.get_potential_energy()
    traj_file = gb_file
    if 'traj' in traj_file:
        out = AtomsWriter('{0}'.format('{0}.xyz'.format(traj_file)))
    else:
        out = AtomsWriter('{0}'.format('{0}_traj.xyz'.format(traj_file)))
    strain_mask = [0, 0, 1, 0, 0, 0]
    ucf = UnitCellFilter(grain, strain_mask)
    opt = FIRE(ucf)
    cell = grain.get_cell()
    A = cell[0][0] * cell[1][1]
    H = cell[2][2]
    #Calculation dumps total energyenergy and grainboundary area data to json file.
    with open('subgb.json', 'r') as f:
        gb_dict = json.load(f)

    #Write an initial dict so we know if the system has been initialized but the calculation is not finished.
    with open('subgb.json', 'w') as outfile:
        for key, value in gb_dict.items():
            j_dict[key] = value
        json.dump(j_dict, outfile, indent=2)

    CONVERGED = False
    FORCE_TOL = force_tol

    #default to 5 if traj_steps = 120, otherwise increases
    num_iters = int(float(total_steps) / float(traj_steps))
    logging.debug('num_iters: {}'.format(num_iters))
    for i in range(num_iters):
        opt.run(fmax=FORCE_TOL, steps=traj_steps)
        out.write(grain)
        force_array = grain.get_forces()
        max_force_II = max([max(f) for f in force_array])
        max_forces = [
            np.sqrt(fx**2 + fy**2 + fz**2) for fx, fy, fz in zip(
                grain.properties['force'][0], grain.properties['force'][1],
                grain.properties['force'][2])
        ]
        if max(max_forces) <= FORCE_TOL:
            CONVERGED = True
            break
    out.close()

    gb_dict['converged'] = CONVERGED
    E_gb = grain.get_potential_energy()
    gb_dict['E_gb'] = E_gb
    gb_dict['E_gb_init'] = E_gb_init
    gb_dict['area'] = A
    with open('subgb.json', 'w') as outfile:
        for key, value in gb_dict.items():
            j_dict[key] = value
        json.dump(j_dict, outfile, indent=2)

    if param_file == 'gp33b.xml':
        os.remove(param_file)
        os.remove(sparse_file)
    else:
        pass
    return grain
Beispiel #2
0
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.")
Beispiel #3
0
  bulk.set_calculator(pot)
  ener_per_atom = bulk.get_potential_energy()/len(bulk)
  surf_cell.set_calculator(pot)
  surf_ener = surf_cell.get_potential_energy()
  cell  = surf_cell.get_cell()
  A     = cell[0][0]*cell[1][1]
  gamma = (surf_ener- len(surf_cell)*ener_per_atom)/A

  print '2*gamma ev/A2', gamma
  print '2*gamma J/m2',  gamma/(units.J/units.m**2)
  j_dict = {'or_axis':or_axis, 'bp':bp, 'gamma':gamma}
  with open('gbfrac.json','w') as f:
    json.dump(j_dict, f)
  out = AtomsWriter('{0}'.format('{0}_surf.xyz'.format(gbid)))
  out.write(Atoms(surf_cell))
  out.close()
  frac_cell = gb_frac.build_tilt_sym_frac()

#Unit cell for grain boundary fracture cell:
  print frac_cell.get_cell().round(2)

  frac_cell = Atoms(frac_cell)
  frac_cell = del_atoms(frac_cell)

#Relax grainboundary crack cell unit cell:
  pot      = Potential('IP EAM_ErcolAd', param_filename='Fe_Mendelev.xml')
  frac_cell.set_calculator(pot)
  slab_opt          = FIRE(frac_cell)
  slab_opt.run(fmax = (0.02*units.eV/units.Ang))

#Print frac_cell to file:
Beispiel #4
0
class ParamWriter(object):
    """
    Write out configurations to a trajectory and castep files to
    individual subdirectories.

    """
    def __init__(self, atoms, name, potential, calc_energy=True):
        """
        Initialise the writer with the templating atoms and
        potential.
        """
        self.atoms = atoms
        self.name = name
        self.potential = potential
        self.calc_energy = calc_energy
        self.counter = 0

        # TODO: check naming
        self.base_dir = os.getcwd()
        run_path = '{0}'.format(atoms.info['name'])
        info("Putting files in {0}.".format(run_path))
        os.mkdir(run_path)
        os.chdir(run_path)

        trajectory = 'traj_{0}.xyz'.format(atoms.info['name'])
        self.out = AtomsWriter(trajectory)

    def write_config(self, params):
        cell_params = params[:6]
        # Make a list of 3 item lists
        atom_params = [self.atoms[0].position] + zip(*[iter(params[6:])] * 3)

        new_atoms = self.atoms.copy()
        new_atoms.set_cell([[cell_params[0], 0.0, 0.0],
                            [cell_params[1], cell_params[2], 0.0],
                            [cell_params[3], cell_params[4], cell_params[5]]])

        new_atoms.set_positions(atom_params)
        info("Cell volume: {0}".format(new_atoms.get_volume()))
        if self.calc_energy:
            self.potential.calc(new_atoms,
                                energy=True,
                                forces=True,
                                virial=True)
        # Add to the xyz
        self.out.write(new_atoms)
        sp_path = '{0:03d}'.format(self.counter)
        write_filename = '{0}.{1:03d}'.format(self.atoms.info['name'],
                                              self.counter)
        os.mkdir(sp_path)
        os.chdir(sp_path)
        castep_write(new_atoms, filename=write_filename, kpoint_spacing=0.015)
        info("Wrote a configuration {0}.".format(write_filename))
        os.chdir('..')
        self.counter += 1

    def close(self):
        """
        Clean up.
        """
        self.out.close()
        os.chdir(self.base_dir)