Exemple #1
0
 def test_calc_args_4(self):
     pot2 = Potential('IP SW',
                      param_str=self.xml,
                      calc_args={
                          'do_rescale_E': True,
                          'E_scale': 1.01
                      })
     f = pot2.get_forces(self.at)
     self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06)
Exemple #2
0
 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
Exemple #3
0
    def test_get_potential_energy(self):
        np.random.seed(0)
        ats = [
            Atoms('Al4',
                  cell=(5, 5, 5),
                  scaled_positions=np.random.uniform(size=(4, 3)),
                  pbc=[True] * 3) for _ in range(2)
        ]

        LJ_str = """<LJ_params n_types="1" label="default">
        <!-- dummy paramters for testing purposes, no physical meaning -->
        <per_type_data type="1" atomic_num="13" />
        <per_pair_data type1="1" type2="1" sigma="2.0" eps6="1.0" eps12="1.0" cutoff="6.0" energy_shift="T" linear_force_shift="F" />
        </LJ_params>
        """

        calc = Potential(param_str=LJ_str, args_str='IP LJ')
        E1 = []
        for at in ats:
            at.calc = calc
            at.calc.calculate(at, properties=['energy'])
            E1.append(at.calc.results['energy'])

        E2 = []
        for at in ats:
            at.calc = calc
            E2.append(at.get_potential_energy())

        self.assertAlmostEqual(E1, E2)
Exemple #4
0
def fit_gap(atoms: List[Atoms],
            energies: List[float],
            forces: Optional[np.ndarray] = None,
            **kwargs) -> Potential:
    """Fit a GAP potential using MAL and return a ready-to-use QUIPPy object
    
    Args:
        atoms: List of molecules to use for training
        energies: List of energies for each structure
        forces: If available, forces acting on each atom
        output_dir: Directory in which to store potential
        kwargs: Passed to the :meth:`GAPotential.train` method
    Returns:
        ase Potential object instantiated with a model fit to the data
    """

    # Convert all of the structures to periodic
    atoms = [make_periodic(a.copy()) for a in atoms]

    # Conver them to PyMatgen objects
    conv = AseAtomsAdaptor()
    strcs = [conv.get_structure(a) for a in atoms]

    # Fit using maml
    gap = GAPotential()
    gap.train(strcs, energies, forces, **kwargs)

    # Save to disk and return the QUIPy object
    gap.write_param()
    return Potential(param_filename="gap.xml")
Exemple #5
0
def relax_structure(system,
                    potential,
                    potential_filename=None,
                    relax_positions=True,
                    relax_cell=True):
    """
    Run a geometry optimisation on the structure to find the energy minimum.

    Parameters
    ----------
    system : ase.Atoms
        A system of atoms to run the minimisation on. The structure is
        altered in-place.
    potential : Potential or str
        A quippy Potential object with the desired potential, or a
        potential_str to initialise a new potential.

    Returns
    -------
    minimised_structure : Atoms
        The geometry optimised structure.
    """
    info("Inside minimiser.")

    qsystem = Atoms(system)

    if not isinstance(potential, Potential):
        if potential_filename:
            potential = Potential(potential, param_filename=potential_filename)
        else:
            potential = Potential(potential)
    qsystem.set_calculator(potential)

    minimiser = Minim(qsystem,
                      relax_positions=relax_positions,
                      relax_cell=relax_cell)

    with Capturing(debug_on_exit=True):
        minimiser.run()

    system.set_cell(qsystem.cell)
    system.set_positions(qsystem.positions)
    system.energy = qsystem.get_potential_energy()

    info("Minimiser done.")

    return system
Exemple #6
0
 def setUp(self):
     p0 = []
     for i in range(2):
         for j in range(2):
             for k in range(2):
                 p0.append([i * 2 - 1, j * 2 - 1, k * 2 - 1])
     self.p0 = np.array(p0)
     self.sw_pot = Potential('IP SW', param_str=xml_string)
Exemple #7
0
def load_gap_model(self, path):
    from quippy.potential import Potential

    ind = np.load(os.path.join(path, "training_indices.npy"),
                  allow_pickle=True)

    gap_path = os.path.join(path, "model.xml")

    return Potential(param_filename=gap_path), ind
Exemple #8
0
    def proto_qm_pot_callback(unit_cell):
      global qm_pot
      tb = tb_pot.TightBindingPot(alat=1.00, nk=1)
      tb.write_control_file('ctrl.fe', unit_cell)

      qm_pot = Potential('IP LMTO_TBE', param_str="""
<params>
  <LMTO_TBE_params n_types="2" control_file="ctrl.fe">
    <per_type_data type="1" atomic_num="26"/>
    <per_type_data type="2" atomic_num="1"/>
  </LMTO_TBE_params>
</params>""")
      unit_cell.add_property('forces', 0.0, n_cols=3)
Exemple #9
0
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
Exemple #10
0
###########################

parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input_file', help='name of input file')
parser.add_argument('-pt', '--pot_type', help='Potential type, GAP. EAM.')
args = parser.parse_args()

fe_bulk = bcc(2.83)
fe_bulk.set_atoms(26)

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'])
import itertools
import sys
from quippy.atoms import Atoms
from quippy.atomslist import AtomsList
from quippy.potential import Potential
from glob import glob
from pylab import figure, plot, legend, draw, clf, xlabel, ylabel

do_calc = False
do_plot = False

extra_args = {'molpro': {'template': 'dft'}}

codes = ['castep', 'cp2k', 'gpaw', 'molpro', 'vasp']

castep = Potential('FilePot', command='./castep-driver.sh')
cp2k = Potential('FilePot', command='./cp2k-driver.sh')
gpaw = Potential('FilePot', command='./gpaw-driver.sh')
molpro = Potential('FilePot', command='./molpro-driver.sh')
vasp = Potential('FilePot', command='./vasp-driver.sh')

potentials = [globals()[code] for code in codes]


def h2_molecule(a, vacuum=10.0):
    h2 = Atoms(n=2, lattice=np.diag([vacuum, vacuum, vacuum]))
    h2.set_atoms([1, 1])
    h2.params['bond_length'] = a
    h2.pos[1, 1] = -a / 2.0
    h2.pos[1, 2] = +a / 2.0
    return h2
Exemple #12
0
 def test_calc_args_3(self):
     pot2 = Potential('IP SW',
                      param_str=self.xml,
                      calc_args="do_rescale_E E_scale=1.01")
     f = pot2.get_forces(self.at)
     self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06)
Exemple #13
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import ase.io
from ase import Atom, Atoms

from ase.optimize import BFGS
from ase.constraints import StrainFilter  # optimize the unit cell while keeping scaled positiions fixed
from ase.constraints import FixAtoms

from quippy.potential import Potential
from quippy import descriptors

if __name__ == '__main__':
    # load GAP and frames
    gap = Potential(param_filename='./gap-2/GAP.xml')
    train_frames = ase.io.read('./train.xyz', ':')  # ase atom frames
    print(len(train_frames))
    """
    # check lattice optimization
    atoms = train_frames[6].copy()
    atoms.set_calculator(gap)

    #print(atoms.get_stress(voigt=False))
    #print(atoms.get_calculator().get_virial(atoms))
    #print(atoms.get_potential_energy())
    print(atoms.get_cell())

    sf = StrainFilter(atoms)
    opt = BFGS(sf)
    opt.run(0.005)
Exemple #14
0
from quippy.potential import Potential
calculator = Potential("TB NRL-TB", param_filename="./quip_params.xml")

import utilities
import vacancy

from ase.io import read

at = read("NRLTB_hcp3.xyz")
at.rattle(0.001)
at.set_calculator(calculator)
properties = vacancy.do_one_vacancy(at, calculator)

print(properties[4])
Exemple #15
0
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
Exemple #16
0
# ******* End of parameters *************

set_fortran_indexing(False)

# ********** Build unit cell ************

# 8-atom diamond cubic unit cell for silicon, with guess at lattice
# constant of 5.44 A
si_bulk = bulk('Si', 'diamond', a=5.44, cubic=True)


# ********** Setup potential ************

# Stillinger-Weber (SW) classical interatomic potential, from QUIP
mm_pot = Potential(mm_init_args,
                   param_filename=param_file)


# ***** Find eqm. lattice constant ******

# find the equilibrium lattice constant by minimising atoms wrt virial
# tensor given by SW pot (possibly replace this with parabola fit in
# another script and hardcoded a0 here)
si_bulk.set_calculator(mm_pot)

print('Minimising bulk unit cell...')
minim = Minim(si_bulk, relax_positions=True, relax_cell=True)
minim.run(fmax=1e-4)
    
a0 = si_bulk.cell[0, 0]
print('Lattice constant %.3f A\n' % a0)
Exemple #17
0
width = 200.0*units.Ang              # Width of crack slab
height = 100.0*units.Ang             # Height of crack slab
vacuum = 100.0*units.Ang             # Amount of vacuum around slab
crack_seed_length = 40.0*units.Ang   # Length of seed crack
strain_ramp_length = 30.0*units.Ang  # Distance over which strain is ramped up
initial_G = 5.0*(units.J/units.m**2) # Initial energy flow to crack tip

relax_fmax = 0.025*units.eV/units.Ang  # Maximum force criteria for relaxation

output_file = 'crack.xyz'            # File to which structure will be written

set_fortran_indexing(False)

si_bulk = bulk('Si', 'diamond', a=5.431, cubic=True)
mm_pot = Potential("IP SW")
si_bulk.set_calculator(mm_pot)

c = mm_pot.get_elastic_constants(si_bulk)
E = youngs_modulus(c, cleavage_plane)
nu = poisson_ratio(c, cleavage_plane, crack_direction)

unit_slab = Diamond(directions=[crack_direction,
                                cleavage_plane,
                                crack_front],
                    size=(1, 1, 1),
                    symbol='Si',
                    pbc=True,
                    latticeconstant=5.431)

Exemple #18
0
# ******* End of parameters *************


# ********** Build unit cell ************

# 8-atom diamond cubic unit cell for silicon, with guess at lattice
# constant of 5.44 A
si_bulk = bulk('Si', 'diamond', a=5.44, cubic=True)


# ********** Setup potential ************

# Stillinger-Weber (SW) classical interatomic potential, from QUIP
mm_pot = Potential(mm_init_args,
                   param_filename=param_file,
                   fortran_indexing=False)


# ***** Find eqm. lattice constant ******

# find the equilibrium lattice constant by minimising atoms wrt virial
# tensor given by SW pot (possibly replace this with parabola fit in
# another script and hardcoded a0 here)
si_bulk.set_calculator(mm_pot)

print('Minimising bulk unit cell...')
minim = Minim(si_bulk, relax_positions=True, relax_cell=True)
minim.run(fmax=1e-4)
    
a0 = si_bulk.cell[0, 0]
Exemple #19
0
    def __init__(self,
                 mm_clients,
                 qm_clients,
                 ip,
                 port=0,
                 rundir=None,
                 bulk_scale=None,
                 mpi_obj=None,
                 callback=None,
                 calculator=None,
                 cutoff_skin=1.0,
                 atoms=None,
                 qm_list=None,
                 fpointer=None,
                 finalise=True,
                 error=None,
                 cluster_args=None,
                 test_mode=False,
                 save_clusters=False,
                 force_restart=False,
                 **kwargs):
        def callback_factory(force_prop_name):
            def callback(at):
                at.add_property('force',
                                getattr(at, force_prop_name),
                                overwrite=True)

            return callback

        if isinstance(mm_clients, Potential):
            self.mm_local = True
            self.pot1 = mm_clients
            self.mm_clients = []
        else:
            self.mm_local = False
            self.mm_clients = mm_clients

        if isinstance(qm_clients, Potential):
            self.qm_pot = qm_clients
            self.qm_clients = []
        else:
            self.qm_clients = qm_clients

        clients = self.mm_clients + self.qm_clients
        print 'Clients', clients
        if len(clients) > 0:
            self.server = AtomsServerAsync((ip, port),
                                           AtomsRequestHandler,
                                           clients,
                                           bgq=True)
            self.server_thread = threading.Thread(
                target=self.server.serve_forever)
            self.server_thread.daemon = True
            self.server_thread.start()

        if rundir is None:
            rundir = os.getcwd()
        self.rundir = rundir

        self.label = 1
        self.cluster_args = {}
        if cluster_args is not None:
            self.cluster_args = cluster_args

        if not self.mm_local:
            self.pot1 = Potential('CallbackPot',
                                  callback=callback_factory('mm_force'))
        self.pot2 = Potential('CallbackPot',
                              callback=callback_factory('qm_force'))

        self.test_mode = test_mode
        self.save_clusters = save_clusters
        self.force_restart = force_restart

        ForceMixingPotential.__init__(self,
                                      self.pot1,
                                      self.pot2,
                                      bulk_scale=bulk_scale,
                                      mpi_obj=mpi_obj,
                                      cutoff_skin=cutoff_skin,
                                      atoms=atoms,
                                      qm_list=qm_list,
                                      fpointer=fpointer,
                                      finalise=finalise,
                                      error=error,
                                      **kwargs)
Exemple #20
0
fixed_mask = ((abs(atoms.positions[:, 1] - top) < 1.0) |
              (abs(atoms.positions[:, 1] - bottom) < 1.0))
fix_atoms = FixAtoms(mask=fixed_mask)
print('Fixed %d atoms\n' % fixed_mask.sum())

# Increase epsilon_yy applied to all atoms at constant strain rate

strain_atoms = ConstantStrainRate(orig_height, strain_rate*timestep)

atoms.set_constraint([fix_atoms, strain_atoms])


# ******* Set up potentials and calculators ********

mm_pot = Potential(mm_init_args,
                   param_filename=param_file,
                   cutoff_skin=cutoff_skin)

# Request Potential to compute per-atom stresses whenever we
# compute forces, to save time when locating the crack tip
mm_pot.set_default_quantities(['stresses'])

# Density functional tight binding (DFTB) potential
qm_pot = Potential(qm_init_args,
                   param_filename=param_file)

# Parameters which control how the QM calculation is carried out:
# we use a single cluster, periodic in the z direction and terminated
# with hydrogen atoms. The positions of the outer layer of buffer atoms
# are not randomised.
qm_args_str = ('single_cluster cluster_periodic_z '+
Exemple #21
0
# ******* End of parameters *************


# ********** Build unit cell ************

# 8-atom diamond cubic unit cell for silicon, with guess at lattice
# constant of 5.44 A
si_bulk = bulk('Si', 'diamond', a=5.44, cubic=True)


# ********** Setup potential ************

# Stillinger-Weber (SW) classical interatomic potential, from QUIP
mm_pot = Potential(mm_init_args,
                   param_filename=param_file,
                   fortran_indexing=False)


# ***** Find eqm. lattice constant ******

# find the equilibrium lattice constant by minimising atoms wrt virial
# tensor given by SW pot (possibly replace this with parabola fit in
# another script and hardcoded a0 here)
si_bulk.set_calculator(mm_pot)

print('Minimising bulk unit cell...')
minim = Minim(si_bulk, relax_positions=True, relax_cell=True)
minim.run(fmax=1e-4)
    
a0 = si_bulk.cell[0, 0]
Exemple #22
0
right = atoms.positions[:, 0].max()

# fix atoms in the top and bottom rows
fixed_mask = ((abs(atoms.positions[:, 1] - top) < 1.0) |
              (abs(atoms.positions[:, 1] - bottom) < 1.0))
fix_atoms = FixAtoms(mask=fixed_mask)
print('Fixed %d atoms\n' % fixed_mask.sum())
atoms.set_constraint([fix_atoms])

# Increase epsilon_yy applied to all atoms at constant strain rate
strain_atoms = ConstantStrainRate(orig_height, strain_rate * timestep)

# ******* Set up potentials and calculators ********

mm_pot = Potential(mm_init_args,
                   param_filename=param_file,
                   cutoff_skin=cutoff_skin)

# Density functional tight binding (DFTB) potential
qm_pot = Potential(qm_init_args, param_filename=param_file)

# Construct the QM/MM potential, which mixes QM and MM forces.
# The qm_args_str parameters control how the QM calculation is carried out:
# we use a single cluster, periodic in the z direction and terminated
# with hydrogen atoms. The positions of the outer layer of buffer atoms
# are not randomised.
qmmm_pot = ForceMixingPotential(
    pot1=mm_pot,
    pot2=qm_pot,
    qm_args_str='single_cluster cluster_periodic_z carve_cluster ' +
    'terminate cluster_hopping=F randomise_buffer=F',
Exemple #23
0
            default='PDOS_USER.dat', help='PDOS Data File')
    parser.add_argument('-v', '--valid', \
            default='DOS.png', help='DOS Figure')
    parser.add_argument('-g', '--gap', \
            default='DOS.png', help='DOS Figure')

    args = parser.parse_args()

    # read structures
    #train_frames = ase.io.read('./train.xyz', ':')
    #valid_frames = ase.io.read('./validate.xyz', ':')
    #gap = Potential(param_filename='./GAP.xml')

    train_frames = ase.io.read(args.train, ':')
    valid_frames = ase.io.read(args.valid, ':')
    gap = Potential(param_filename=args.gap)

    # read energy using vasp
    train_forces_vasp, train_forces_gap, train_energies_vasp, train_energies_gap = \
            extract_energy_and_forces(train_frames,calc=gap)
    
    valid_forces_vasp, valid_forces_gap, valid_energies_vasp, valid_energies_gap = \
            extract_energy_and_forces(valid_frames,calc=gap)
    
    # plot
    fig, axarr = plt.subplots(nrows=2, ncols=2, \
            gridspec_kw={'hspace': 0.3}, figsize=(12,8))
    axarr = axarr.flat[:]

    plt.suptitle('Electronic Free Energy and Hellman-Feynman Forces')
Exemple #24
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.")
Exemple #25
0
output_file = 'crack.xyz'  # File to which structure will be written

# ******* End of parameters *************

set_fortran_indexing(False)

# ********** Build unit cell ************

# 8-atom diamond cubic unit cell for silicon, with guess at lattice
# constant of 5.44 A
si_bulk = bulk('Si', 'diamond', a=5.44, cubic=True)

# ********** Setup potential ************

# Stillinger-Weber (SW) classical interatomic potential, from QUIP
mm_pot = Potential(mm_init_args, param_filename=param_file)

# ***** Find eqm. lattice constant ******

# find the equilibrium lattice constant by minimising atoms wrt virial
# tensor given by SW pot (possibly replace this with parabola fit in
# another script and hardcoded a0 here)
si_bulk.set_calculator(mm_pot)

print('Minimising bulk unit cell...')
minim = Minim(si_bulk, relax_positions=True, relax_cell=True)
minim.run(fmax=1e-4)

a0 = si_bulk.cell[0, 0]
print('Lattice constant %.3f A\n' % a0)
Exemple #26
0
    def setUp(self):
        self.xml = """
      <SW_params n_types="2" label="PRB_31_plus_H">
      <comment> Stillinger and Weber, Phys. Rev. B  31 p 5262 (1984), extended for other elements </comment>
      <per_type_data type="1" atomic_num="1" />
      <per_type_data type="2" atomic_num="14" />
      <per_pair_data atnum_i="1" atnum_j="1" AA="0.0" BB="0.0"
      p="0" q="0" a="1.0" sigma="1.0" eps="0.0" />
      <per_pair_data atnum_i="1" atnum_j="14" AA="8.581214" BB="0.0327827"
      p="4" q="0" a="1.25" sigma="2.537884" eps="2.1672" />
      <per_pair_data atnum_i="14" atnum_j="14" AA="7.049556277" BB="0.6022245584"
      p="4" q="0" a="1.80" sigma="2.0951" eps="2.1675" />

      <!-- triplet terms: atnum_c is the center atom, neighbours j and k -->
      <per_triplet_data atnum_c="1"  atnum_j="1"  atnum_k="1"
      lambda="21.0" gamma="1.20" eps="2.1675" />
      <per_triplet_data atnum_c="1"  atnum_j="1"  atnum_k="14"
      lambda="21.0" gamma="1.20" eps="2.1675" />
      <per_triplet_data atnum_c="1"  atnum_j="14" atnum_k="14"
      lambda="21.0" gamma="1.20" eps="2.1675" />

      <per_triplet_data atnum_c="14" atnum_j="1"  atnum_k="1"
      lambda="21.0" gamma="1.20" eps="2.1675" />
      <per_triplet_data atnum_c="14" atnum_j="1"  atnum_k="14"
      lambda="21.0" gamma="1.20" eps="2.1675" />
      <per_triplet_data atnum_c="14" atnum_j="14" atnum_k="14"
      lambda="21.0" gamma="1.20" eps="2.1675" />
      </SW_params>
      """

        quippy.system_module.system_reseed_rng(2065775975)
        self.pot_calculator = Potential('IP SW', param_str=self.xml)

        self.at = Atoms('Si8',
                        positions=diamond_pos,
                        pbc=True,
                        cell=[5.44, 5.44, 5.44])

        self.f = np.zeros((3, len(self.at)), order='F')
        self.df = np.zeros((3, len(self.at)), order='F')
        self.v = np.zeros((3, 3), order='F')

        self.energy_ref = -34.5038375509

        self.forces_ref = np.array([[0.89920374, -0.38025157, -0.38727027],
                                    [0.36623356, -0.52403757, 0.7200206],
                                    [-0.36952654, 0.12899529, 0.00458111],
                                    [-0.19912365, -0.1632057, 1.08509495],
                                    [-0.67565314, -0.59410498, -0.47921521],
                                    [0.17097454, 0.5847822, -0.31088749],
                                    [0.43613712, 0.90811269, 0.1600328],
                                    [-0.62824563, 0.03970963, -0.79235649]])

        self.virial_ref = np.array([[-0.34103601, 0.60925144, -0.02138795],
                                    [0.60925144, -0.36145702, -0.19375487],
                                    [-0.02138795, -0.19375487, -0.34640615]]).T

        # Voigt notation by hand from virial
        self.stress_ref = -np.array([
            -0.34103601, -0.36145702, -0.34640615, -0.19375487, -0.02138795,
            0.60925144
        ]) / self.at.get_volume()

        self.at.set_calculator(self.pot_calculator)
Exemple #27
0
# A module defining a module needs to define only one variable,
# named `calculator`, which should be an instance of the ase.calculator.Calculator,
# a subclass of this, or a compatible class implementing the calculator interface.

calculator = Potential('IP Tersoff',
                       param_str="""
<Tersoff_params n_types="3" label="PRB_39">
<comment> Tersoff, Phys. Rev. B v 39, p 5566 (1989) </comment>
<per_type_data type="1" atomic_num="6" 
  A="1393.6" B="346.7" lambda="3.4879" mu="2.2119" beta="0.00000015724" 
  n="0.72751" c="38049" d="4.384" h="-0.57058" R="1.8" S="2.1" />
<per_type_data type="2" atomic_num="14"
 A="1830.8" B="471.18" lambda="2.4799" mu="1.7322" beta="0.0000011"
 n="0.78734" c="100390" d="16.217" h="-0.59825" R="2.7" S="3.0" />
<per_type_data type="3" atomic_num="32"
  A="1769" B="419.23" lambda="2.4451" mu="1.7047" beta="0.00000090166"
  n="0.75627" c="106430" d="15.652" h="-0.43884" R="2.8" S="3.1" />
<per_pair_data type1="1" type2="1" chi="1.0" />
<per_pair_data type1="2" type2="1" chi="0.9776" />
<per_pair_data type1="2" type2="2" chi="1.0" />
<per_pair_data type1="3" type2="1" chi="1.0" />
<per_pair_data type1="3" type2="2" chi="1.00061" />
<per_pair_data type1="3" type2="3" chi="1.0" />
</Tersoff_params>
""")

no_checkpoint = True

name = 'Tersoff'
Exemple #28
0
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
Exemple #29
0
  print restart
  if restart:
    print 'Restarting job'
  input_file = args.input_file
  pot_file   = args.pot_file
  if args.output_file:
    traj_file = args.output_file
  print 'Output_file: ', traj_file
  print 'POT FILE', pot_file
#Need to add an arg parser here
  learn_on_the_fly = True
  if learn_on_the_fly:
    print 'Initialize Potentials'
    atoms = Atoms(input_file)
    cluster = Atoms('cluster.xyz')
    mm_pot = Potential(mm_init_args, param_filename=pot_file, cutoff_skin=cutoff_skin)
    unit_cell = BodyCenteredCubic(directions = [[1,0,0], [0,1,0],[0,0,1]],
                                size = (4,4,4), symbol='Fe', pbc=(1,1,1),
                                latticeconstant = 2.87)

    def proto_qm_pot_callback(unit_cell):
      global qm_pot
      tb = tb_pot.TightBindingPot(alat=1.00, nk=1)
      tb.write_control_file('ctrl.fe', unit_cell)

      qm_pot = Potential('IP LMTO_TBE', param_str="""
<params>
  <LMTO_TBE_params n_types="2" control_file="ctrl.fe">
    <per_type_data type="1" atomic_num="26"/>
    <per_type_data type="2" atomic_num="1"/>
  </LMTO_TBE_params>
Exemple #30
0
 def __init__(self, fpointer=None, finalise=True, error=None):
     Potential.__init__(self, callback=self.do_cp2k_calc)
Exemple #31
0
         last_traj = traj_files[-1]
         input_file = last_traj + '@-1'
 
 # loading reference configuration for Nye tensor evaluation
 # convert to quippy Atoms - FIXME in long term, this should not be necesary
 x0 = Atoms(params.reference_file)
 x0 = Atoms(x0)
 x0.set_cutoff(3.0)
 x0.calc_connect()
 
 print params.param_file
 # ******* Set up potentials and calculators ********
 system_timer('init_fm_pot')
 pot_file = os.path.join(params.pot_dir, params.param_file)
 mm_pot = Potential(params.mm_init_args,
                    param_filename=params.param_file,
                    cutoff_skin=params.cutoff_skin)
 
 cluster_args = params.cluster_args.copy()
 
 if params.test_mode:
     # dummy QM potential made by swapping Ni and Al species in MM potential               
     qm_pot = Potential(params.mm_init_args,
                        param_filename='m2004flipNiAl.xml',
                        cutoff_skin=params.cutoff_skin)
     qm_clients = qm_pot
     
     # convergence of EAM forces with buffer size is suprisingly slow,
     # so we need to use a big buffer to avoid messing up predictor/corrector
     # error plot
     cluster_args['hysteretic_buffer_inner_radius'] = 12.0
orig_height = atoms.info['OrigHeight']
orig_crack_pos = atoms.info['CrackPos'].copy()

top = atoms.positions[:, 1].max()
bottom = atoms.positions[:, 1].min()
left = atoms.positions[:, 0].min()
right = atoms.positions[:, 0].max()

fixed_mask = ((abs(atoms.positions[:, 1] - top) < 1.0) |
              (abs(atoms.positions[:, 1] - bottom) < 1.0))
fix_atoms = FixAtoms(mask=fixed_mask)

strain_atoms = ConstantStrainRate(orig_height, strain_rate*timestep)
atoms.set_constraint([fix_atoms, strain_atoms])

mm_pot = Potential("IP SW", cutoff_skin=cutoff_skin)
mm_pot.set_default_properties(['stresses'])

atoms.set_calculator(mm_pot)

# ********* Setup and run MD ***********

MaxwellBoltzmannDistribution(atoms, 2.0*sim_T)

dynamics = VelocityVerlet(atoms, timestep)

def printstatus():
    if dynamics.nsteps == 1:
        print """
State      Time/fs    Temp/K     Strain      G/(J/m^2)  CrackPos/A D(CrackPos)/A 
---------------------------------------------------------------------------------"""
Exemple #33
0
fixed_mask = ((abs(atoms.positions[:, 1] - top) < 1.0) |
              (abs(atoms.positions[:, 1] - bottom) < 1.0))
fix_atoms = FixAtoms(mask=fixed_mask)
print('Fixed %d atoms\n' % fixed_mask.sum())

# Increase epsilon_yy applied to all atoms at constant strain rate

strain_atoms = ConstantStrainRate(orig_height, strain_rate*timestep)

atoms.set_constraint([fix_atoms, strain_atoms])


# ******* Set up potentials and calculators ********

mm_pot = Potential(mm_init_args,
                   param_filename=param_file,
                   cutoff_skin=cutoff_skin)

# Request Potential to compute per-atom stresses whenever we
# compute forces, to save time when locating the crack tip
mm_pot.set_default_quantities(['stresses'])

atoms.set_calculator(mm_pot)

# ********* Setup and run MD ***********

# Set the initial temperature to 2*simT: it will then equilibriate to
# simT, by the virial theorem
MaxwellBoltzmannDistribution(atoms, 2.0*sim_T)

# Initialise the dynamical system