stacking_fault_static - Methodology and code

Python imports

[1]:
# Standard library imports
from pathlib import Path
import shutil
import datetime
from copy import deepcopy
from math import floor
from typing import Optional, Tuple, Union

# http://www.numpy.org/
import numpy as np

# https://ipython.org/
from IPython.display import display, Markdown

# https://github.com/usnistgov/atomman
import atomman as am
import atomman.lammps as lmp
import atomman.unitconvert as uc
from atomman.tools import filltemplate

# https://github.com/usnistgov/iprPy
import iprPy
from iprPy.tools import read_calc_file

print('Notebook last executed on', datetime.date.today(), 'using iprPy version', iprPy.__version__)
Notebook last executed on 2023-07-31 using iprPy version 0.11.6

1. Load calculation and view description

1.1. Load the calculation

[2]:
# Load the calculation being demoed
calculation = iprPy.load_calculation('stacking_fault_static')

1.2. Display calculation description and theory

[3]:
# Display main docs and theory
display(Markdown(calculation.maindoc))
display(Markdown(calculation.theorydoc))

stacking_fault_static calculation style

Lucas M. Hale, lucas.hale@nist.gov, Materials Science and Engineering Division, NIST.

Introduction

The stacking_fault_static calculation style evaluates the energy of a single generalized stacking fault shift along a specified crystallographic plane.

Version notes
  • 2018-07-09: Notebook added.

  • 2019-07-30: Description updated and small changes due to iprPy version.

  • 2020-05-22: Version 0.10 update - potentials now loaded from database.

  • 2020-09-22: Calculation updated to use atomman.defect.StackingFault class. Setup and parameter definition streamlined.

  • 2022-03-11: Notebook updated to reflect version 0.11.

Additional dependencies
Disclaimers
  • NIST disclaimers

  • The system’s dimension perpendicular to the fault plane should be large to minimize the interaction of the free surface and the stacking fault.

Method and Theory

First, an initial system is generated. This is accomplished using atomman.defect.StackingFault, which

  1. Starts with a unit cell system.

  2. Generates a transformed system by rotating the unit cell such that the new system’s box vectors correspond to crystallographic directions, and filled in with atoms to remain a perfect bulk cell when the three boundaries are periodic.

  3. All atoms are shifted by a fractional amount of the box vectors if needed.

  4. A supercell system is constructed by combining multiple replicas of the transformed system.

  5. The system is then cut by making one of the box boundaries non-periodic. A limitation placed on the calculation is that the normal to the cut plane must correspond to one of the three Cartesian (\(x\), \(y\), or \(z\)) axes. If true, then of the system’s three box vectors (\(\vec{a}\), \(\vec{b}\), and \(\vec{c}\)), two will be parallel to the plane, and the third will not. The non-parallel box vector is called the cutboxvector, and for LAMMPS compatible systems, the following conditions can be used to check the system’s compatibility:

    • cutboxvector = ‘c’: all systems allowed.

    • cutboxvector = ‘b’: the system’s yz tilt must be zero.

    • cutboxvector = ‘a’: the system’s xy and xz tilts must be zero.

A LAMMPS simulation performs an energy/force minimization on the system where the atoms are confined to only relax along the Cartesian direction normal to the cut plane.

A mathematical fault plane parallel to the cut plane is defined in the middle of the system. A generalized stacking fault system can then be created by shifting all atoms on one side of the fault plane by a vector, \(\vec{s}\). The shifted system is then relaxed using the same confined energy/force minimization used on the non-shifted system. The generalized stacking fault energy, \(\gamma\), can then be computed by comparing the total energy of the system, \(E_{total}\), before and after \(\vec{s}\) is applied

\[\gamma(\vec{s}) = \frac{E_{total}(\vec{s}) - E_{total}(\vec{0})}{A},\]

where \(A\) is the area of the fault plane, which can be computed using the two box vectors, \(\vec{a_1}\) and \(\vec{a_2}\), that are not the cutboxvector.

\[A = \left| \vec{a_1} \times \vec{a_2} \right|,\]

Additionally, the relaxation normal to the glide plane is characterized using the center of mass of the atoms above and below the cut plane. Notably, the component of the center of mass normal to the glide/cut plane is calculated for the two halves of the the system, and the difference is computed

\[\delta = \left<x\right>^{+} - \left<x\right>^{-}.\]

The relaxation normal is then taken as the change in the center of mass difference after the shift is applied.

\[\Delta\delta = \delta(\vec{s}) - \delta(\vec{0}).\]

2. Define calculation functions and generate files

This section defines the calculation functions and associated resource files exactly as they exist inside the iprPy package. This allows for the code used to be directly visible and modifiable by anyone looking to see how it works.

2.1. stackingfault()

This is the primary function for the calculation. The version of this function built in iprPy can be accessed by calling the calc() method of an object of the associated calculation class.

[4]:
def stackingfault(lammps_command: str,
                  ucell: am.System,
                  potential: lmp.Potential,
                  hkl: Union[list, np.ndarray],
                  mpi_command: Optional[str] = None,
                  sizemults: Union[list, tuple, None] = None,
                  minwidth: float = None,
                  even: bool = False,
                  a1vect_uvw: Union[list, np.ndarray, None] = None,
                  a2vect_uvw: Union[list, np.ndarray, None] = None,
                  conventional_setting: str = 'p',
                  cutboxvector: str = 'c',
                  faultpos_rel: Optional[float] = None,
                  faultpos_cart: Optional[float] = None,
                  a1: float = 0.0,
                  a2: float = 0.0,
                  atomshift: Union[list, np.ndarray, None] = None,
                  shiftindex: Optional[int] = None,
                  etol: float = 0.0,
                  ftol: float = 0.0,
                  maxiter: int = 10000,
                  maxeval: int = 100000,
                  dmax: float = uc.set_in_units(0.01, 'angstrom')) -> dict:
    """
    Computes the generalized stacking fault value for a single faultshift.

    Parameters
    ----------
    lammps_command :str
        Command for running LAMMPS.
    ucell : atomman.System
        The crystal unit cell to use as the basis of the stacking fault
        configurations.
    potential : atomman.lammps.Potential
        The LAMMPS implemented potential to use.
    hkl : array-like object
        The Miller(-Bravais) crystal fault plane relative to ucell.
    mpi_command : str, optional
        The MPI command for running LAMMPS in parallel.  If not given, LAMMPS
        will run serially.
    sizemults : list or tuple, optional
        The three System.supersize multipliers [a_mult, b_mult, c_mult] to use on the
        rotated cell to build the final system. Note that the cutboxvector sizemult
        must be an integer and not a tuple.  Default value is [1, 1, 1].
    minwidth : float, optional
        If given, the sizemult along the cutboxvector will be selected such that the
        width of the resulting final system in that direction will be at least this
        value. If both sizemults and minwidth are given, then the larger of the two
        in the cutboxvector direction will be used.
    even : bool, optional
        A True value means that the sizemult for cutboxvector will be made an even
        number by adding 1 if it is odd.  Default value is False.
    a1vect_uvw : array-like object, optional
        The crystal vector to use for one of the two shifting vectors.  If
        not given, will be set to the shortest in-plane lattice vector.
    a2vect_uvw : array-like object, optional
        The crystal vector to use for one of the two shifting vectors.  If
        not given, will be set to the shortest in-plane lattice vector not
        parallel to a1vect_uvw.
    conventional_setting : str, optional
        Allows for rotations of a primitive unit cell to be determined from
        (hkl) indices specified relative to a conventional unit cell.  Allowed
        settings: 'p' for primitive (no conversion), 'f' for face-centered,
        'i' for body-centered, and 'a', 'b', or 'c' for side-centered.  Default
        behavior is to perform no conversion, i.e. take (hkl) relative to the
        given ucell.
    cutboxvector : str, optional
        Indicates which of the three system box vectors, 'a', 'b', or 'c', to
        cut with a non-periodic boundary (default is 'c').
    faultpos_rel : float, optional
        The position to place the slip plane within the system given as a
        relative coordinate along the out-of-plane direction.  faultpos_rel
        and faultpos_cart cannot both be given.  Default value is 0.5 if
        faultpos_cart is also not given.
    faultpos_cart : float, optional
        The position to place the slip plane within the system given as a
        Cartesian coordinate along the out-of-plane direction.  faultpos_rel
        and faultpos_cart cannot both be given.
    a1 : float, optional
        The fractional coordinate to evaluate along a1vect_uvw.
        Default value is 0.0.
    a2 : float, optional
        The fractional coordinate to evaluate along a2vect_uvw.
        Default value is 0.0.
    atomshift : array-like object, optional
        A Cartesian vector shift to apply to all atoms.  Can be used to shift
        atoms perpendicular to the fault plane to allow different termination
        planes to be cut.  Cannot be given with shiftindex.
    shiftindex : int, optional
        Allows for selection of different termination planes based on the
        preferred shift values determined by the underlying fault generation.
        Cannot be given with atomshift. If neither atomshift nor shiftindex
        given, then shiftindex will be set to 0.
    etol : float, optional
        The energy tolerance for the structure minimization. This value is
        unitless. (Default is 0.0).
    ftol : float, optional
        The force tolerance for the structure minimization. This value is in
        units of force. (Default is 0.0).
    maxiter : int, optional
        The maximum number of minimization iterations to use (default is
        10000).
    maxeval : int, optional
        The maximum number of minimization evaluations to use (default is
        100000).
    dmax : float, optional
        The maximum distance in length units that any atom is allowed to relax
        in any direction during a single minimization iteration (default is
        0.01 Angstroms).

    Returns
    -------
    dict
        Dictionary of results consisting of keys:

        - **'E_gsf'** (*float*) - The stacking fault formation energy.
        - **'E_total_0'** (*float*) - The total potential energy of the
          system before applying the faultshift.
        - **'E_total_sf'** (*float*) - The total potential energy of the
          system after applying the faultshift.
        - **'delta_disp'** (*float*) - The change in the center of mass
          difference between before and after applying the faultshift.
        - **'disp_0'** (*float*) - The center of mass difference between atoms
          above and below the fault plane in the cutboxvector direction for
          the system before applying the faultshift.
        - **'disp_sf'** (*float*) - The center of mass difference between
          atoms above and below the fault plane in the cutboxvector direction
          for the system after applying the faultshift.
        - **'A_fault'** (*float*) - The area of the fault surface.
        - **'dumpfile_0'** (*str*) - The name of the LAMMMPS dump file
          associated with the relaxed system before applying the faultshift.
        - **'dumpfile_sf'** (*str*) - The name of the LAMMMPS dump file
          associated with the relaxed system after applying the faultshift.
    """
    # Construct stacking fault configuration generator
    gsf_gen = am.defect.StackingFault(hkl, ucell, cutboxvector=cutboxvector,
                                      a1vect_uvw=a1vect_uvw, a2vect_uvw=a2vect_uvw,
                                      conventional_setting=conventional_setting)

    # Check shift parameters
    if shiftindex is not None:
        assert atomshift is None, 'shiftindex and atomshift cannot both be given'
        atomshift = gsf_gen.shifts[shiftindex]
    elif atomshift is None:
        atomshift = gsf_gen.shifts[0]

    # Generate the free surface (zero-shift) configuration
    sfsystem = gsf_gen.surface(shift=atomshift, minwidth=minwidth,
                               sizemults=sizemults, even=even,
                               faultpos_rel=faultpos_rel,
                               faultpos_cart=faultpos_cart)

    abovefault = gsf_gen.abovefault
    cutindex = gsf_gen.cutindex
    A_fault = gsf_gen.surfacearea

    # Identify lammps_date version
    lammps_date = lmp.checkversion(lammps_command)['date']


    # Evaluate the zero shift configuration
    zeroshift = stackingfaultrelax(lammps_command, sfsystem, potential,
                                   mpi_command=mpi_command,
                                   cutboxvector=cutboxvector,
                                   etol=etol, ftol=ftol, maxiter=maxiter,
                                   maxeval=maxeval, dmax=dmax,
                                   lammps_date=lammps_date)

    # Extract terms
    E_total_0 = zeroshift['E_total']
    pos_0 = zeroshift['system'].atoms.pos
    shutil.move('log.lammps', 'zeroshift-log.lammps')
    shutil.move(zeroshift['dumpfile'], 'zeroshift.dump')

    # Evaluate the system after shifting along the fault plane
    sfsystem = gsf_gen.fault(a1=a1, a2=a2)
    shifted = stackingfaultrelax(lammps_command, sfsystem, potential,
                                 mpi_command=mpi_command,
                                 cutboxvector=cutboxvector,
                                 etol=etol, ftol=ftol, maxiter=maxiter,
                                 maxeval=maxeval, dmax=dmax,
                                 lammps_date=lammps_date)

    # Extract terms
    E_total_sf = shifted['E_total']
    pos_sf = shifted['system'].atoms.pos
    shutil.move('log.lammps', 'shifted-log.lammps')
    shutil.move(shifted['dumpfile'], 'shifted.dump')

    # Compute the stacking fault energy
    E_gsf = (E_total_sf - E_total_0) / A_fault

    # Compute the change in displacement normal to fault plane
    disp_0 = (pos_0[abovefault, cutindex].mean()
            - pos_0[~abovefault, cutindex].mean())
    disp_sf = (pos_sf[abovefault, cutindex].mean()
             - pos_sf[~abovefault, cutindex].mean())
    delta_disp = disp_sf - disp_0

    # Return processed results
    results = {}
    results['E_gsf'] = E_gsf
    results['E_total_0'] = E_total_0
    results['E_total_sf'] = E_total_sf
    results['delta_disp'] = delta_disp
    results['disp_0'] = disp_0
    results['disp_sf'] = disp_sf
    results['A_fault'] = A_fault
    results['dumpfile_0'] = 'zeroshift.dump'
    results['dumpfile_sf'] = 'shifted.dump'

    return results

2.2. stackingfaultrelax()

[5]:
def stackingfaultrelax(lammps_command: str,
                       system: am.System,
                       potential: lmp.Potential,
                       mpi_command: Optional[str] = None,
                       sim_directory: Optional[str] = None,
                       cutboxvector: str = 'c',
                       etol: float = 0.0,
                       ftol: float = 0.0,
                       maxiter: int = 10000,
                       maxeval: int = 100000,
                       dmax: float = uc.set_in_units(0.01, 'angstrom'),
                       lammps_date: Optional[datetime.date] = None) -> dict:
    """
    Perform a stacking fault relaxation simulation for a single faultshift.

    Parameters
    ----------
    lammps_command :str
        Command for running LAMMPS.
    system : atomman.System
        The system containing a stacking fault.
    potential : atomman.lammps.Potential
        The LAMMPS implemented potential to use.
    mpi_command : str, optional
        The MPI command for running LAMMPS in parallel.  If not given, LAMMPS
        will run serially.
    sim_directory : str, optional
        The path to the directory to perform the simulation in.  If not
        given, will use the current working directory.
    cutboxvector : str, optional
        Indicates which of the three system box vectors, 'a', 'b', or 'c', has
        the non-periodic boundary (default is 'c').  Fault plane normal is
        defined by the cross of the other two box vectors.
    etol : float, optional
        The energy tolerance for the structure minimization. This value is
        unitless. (Default is 0.0).
    ftol : float, optional
        The force tolerance for the structure minimization. This value is in
        units of force. (Default is 0.0).
    maxiter : int, optional
        The maximum number of minimization iterations to use (default is
        10000).
    maxeval : int, optional
        The maximum number of minimization evaluations to use (default is
        100000).
    dmax : float, optional
        The maximum distance in length units that any atom is allowed to relax
        in any direction during a single minimization iteration (default is
        0.01 Angstroms).
    lammps_date : datetime.date or None, optional
        The date version of the LAMMPS executable.  If None, will be identified
        from the lammps_command (default is None).

    Returns
    -------
    dict
        Dictionary of results consisting of keys:

        - **'logfile'** (*str*) - The filename of the LAMMPS log file.
        - **'dumpfile'** (*str*) - The filename of the LAMMPS dump file
          of the relaxed system.
        - **'system'** (*atomman.System*) - The relaxed system.
        - **'E_total'** (*float*) - The total potential energy of the relaxed
          system.

    Raises
    ------
    ValueError
        For invalid cutboxvectors.
    """
    # Give correct LAMMPS fix setforce command
    if cutboxvector == 'a':
        fix_cut_setforce = 'fix cut all setforce NULL 0 0'
    elif cutboxvector == 'b':
        fix_cut_setforce = 'fix cut all setforce 0 NULL 0'
    elif cutboxvector == 'c':
        fix_cut_setforce = 'fix cut all setforce 0 0 NULL'
    else:
        raise ValueError('Invalid cutboxvector')

    if sim_directory is not None:
        # Create sim_directory if it doesn't exist
        sim_directory = Path(sim_directory)
        if not sim_directory.is_dir():
            sim_directory.mkdir()
        sim_directory = sim_directory.as_posix()+'/'
    else:
        # Set sim_directory if is None
        sim_directory = ''

    # Get lammps units
    lammps_units = lmp.style.unit(potential.units)

    #Get lammps version date
    if lammps_date is None:
        lammps_date = lmp.checkversion(lammps_command)['date']

    # Define lammps variables
    lammps_variables = {}
    system_info = system.dump('atom_data',
                              f=Path(sim_directory, 'system.dat').as_posix(),
                              potential=potential)
    lammps_variables['atomman_system_pair_info'] = system_info
    lammps_variables['fix_cut_setforce'] = fix_cut_setforce
    lammps_variables['sim_directory'] = sim_directory
    lammps_variables['etol'] = etol
    lammps_variables['ftol'] = uc.get_in_units(ftol, lammps_units['force'])
    lammps_variables['maxiter'] = maxiter
    lammps_variables['maxeval'] = maxeval
    lammps_variables['dmax'] = uc.get_in_units(dmax, lammps_units['length'])

    # Set dump_modify format based on dump_modify_version
    if lammps_date < datetime.date(2016, 8, 3):
        lammps_variables['dump_modify_format'] = '"%i %i %.13e %.13e %.13e %.13e"'
    else:
        lammps_variables['dump_modify_format'] = 'float %.13e'

    # Write lammps input script
    lammps_script = Path(sim_directory, 'sfmin.in')
    template = read_calc_file('iprPy.calculation.stacking_fault_static',
                              'sfmin.template')
    with open(lammps_script, 'w') as f:
        f.write(filltemplate(template, lammps_variables, '<', '>'))

    # Run LAMMPS
    output = lmp.run(lammps_command, script_name=lammps_script.as_posix(),
                     mpi_command=mpi_command,
                     logfile=Path(sim_directory, 'log.lammps').as_posix())

    # Extract output values
    thermo = output.simulations[-1]['thermo']
    logfile = Path(sim_directory, 'log.lammps').as_posix()
    dumpfile = Path(sim_directory, f'{thermo.Step.values[-1]}.dump').as_posix()
    E_total = uc.set_in_units(thermo.PotEng.values[-1],
                              lammps_units['energy'])

    # Load relaxed system
    system = am.load('atom_dump', dumpfile, symbols=system.symbols)

    # Return results
    results_dict = {}
    results_dict['logfile'] = logfile
    results_dict['dumpfile'] = dumpfile
    results_dict['system'] = system
    results_dict['E_total'] = E_total

    return results_dict

2.3. sfmin.template file

[6]:
with open('sfmin.template', 'w') as f:
    f.write("""#LAMMPS input script that performs an energy minimization
#for a system with a stacking fault

box tilt large

<atomman_system_pair_info>

<fix_cut_setforce>

thermo_style custom step lx ly lz pxx pyy pzz pe
thermo_modify format float %.13e

compute peatom all pe/atom

min_modify dmax <dmax>

dump dumpit all custom <maxeval> <sim_directory>*.dump id type x y z c_peatom
dump_modify dumpit format <dump_modify_format>

minimize <etol> <ftol> <maxiter> <maxeval>""")

3. Specify input parameters

3.1. System-specific paths

  • lammps_command is the LAMMPS command to use (required).

  • mpi_command MPI command for running LAMMPS in parallel. A value of None will run simulations serially.

[7]:
lammps_command = 'lmp'
mpi_command = None

# Optional: check that LAMMPS works and show its version
print(f'LAMMPS version = {am.lammps.checkversion(lammps_command)["version"]}')
LAMMPS version = 15 Sep 2022

3.2. Interatomic potential

  • potential_name gives the name of the potential_LAMMPS reference record in the iprPy library to use for the calculation.

  • potential is an atomman.lammps.Potential object (required).

[8]:
potential_name = '1999--Mishin-Y--Ni--LAMMPS--ipr1'

# Retrieve potential and parameter file(s) using atomman
potential = am.load_lammps_potential(id=potential_name, getfiles=True)

3.3. Initial unit cell system

  • ucell is an atomman.System representing a fundamental unit cell of the system (required). Here, this is generated using the load parameters and symbols.

[9]:
# Create ucell by loading prototype record
ucell = am.load('crystal', potential=potential, family='A1--Cu--fcc')

print(ucell)
avect =  [ 3.520,  0.000,  0.000]
bvect =  [ 0.000,  3.520,  0.000]
cvect =  [ 0.000,  0.000,  3.520]
origin = [ 0.000,  0.000,  0.000]
natoms = 4
natypes = 1
symbols = ('Ni',)
pbc = [ True  True  True]
per-atom properties = ['atype', 'pos']
     id   atype  pos[0]  pos[1]  pos[2]
      0       1   0.000   0.000   0.000
      1       1   0.000   1.760   1.760
      2       1   1.760   0.000   1.760
      3       1   1.760   1.760   0.000

3.4. Defect parameters

  • hkl gives the Miller (hkl) or Miller-Bravais (hkil) plane to create the free surface on.

  • cutboxvector specifies which of the three box vectors (‘a’, ‘b’, or ‘c’) is to be made non-periodic to create the free surface.

  • shiftindex can be used for complex crystals to specify different termination planes.

  • a1vect_uvw, a2vect_uvw specify two non-parallel Miller crystal vectors within the fault plane corresponding to full planar shifts from one perfect crystal configuration to another.

  • a1, a2 are the fractional shifts along a1vect_uvw, a2vect_uvw to apply to the system.

[10]:
hkl = [1, 1, 1]
cutboxvector = 'c'
shiftindex = 0
a1vect_uvw = [ 0.0,-0.5, 0.5]
a2vect_uvw = [ 0.5,-0.5, 0.0]
a1 = 1/3
a2 = 1/3

3.5. System modifications

  • sizemults list of three integers specifying how many times the ucell vectors of \(a\), \(b\) and \(c\) are replicated in creating system.

  • minwidth specifies a minimum width that the system should be along the cutboxvector direction. The given sizemult in that direction will be increased if needed to ensure that the system is at least this wide.

[11]:
sizemults = [5, 5, 10]
minwidth = uc.set_in_units(0.0, 'angstrom')

3.6. Calculation-specific parameters

  • energytolerance is the energy tolerance to use during the minimizations. This is unitless.

  • forcetolerance is the force tolerance to use during the minimizations. This is in energy/length units.

  • maxiterations is the maximum number of minimization iterations to use.

  • maxevaluations is the maximum number of minimization evaluations to use.

  • maxatommotion is the largest distance that an atom is allowed to move during a minimization iteration. This is in length units.

[12]:
energytolerance = 1e-8
forcetolerance = uc.set_in_units(0.0, 'eV/angstrom')
maxiterations = 10000
maxevaluations = 100000
maxatommotion = uc.set_in_units(0.01, 'angstrom')

4. Run calculation and view results

4.1. Run calculation

All primary calculation method functions take a series of inputs and return a dictionary of outputs.

[13]:
results_dict = stackingfault(lammps_command, ucell, potential, hkl,
                             mpi_command = mpi_command,
                             sizemults = sizemults,
                             minwidth = minwidth,
                             a1vect_uvw = a1vect_uvw,
                             a2vect_uvw = a2vect_uvw,
                             cutboxvector = cutboxvector,
                             shiftindex = shiftindex,
                             a1 = a1,
                             a2 = a2,
                             etol = energytolerance,
                             ftol = forcetolerance,
                             maxiter = maxiterations,
                             maxeval = maxevaluations,
                             dmax = maxatommotion)
print(results_dict.keys())
dict_keys(['E_gsf', 'E_total_0', 'E_total_sf', 'delta_disp', 'disp_0', 'disp_sf', 'A_fault', 'dumpfile_0', 'dumpfile_sf'])

4.2. Report results

Values returned in the results_dict:

  • ‘E_gsf’ (float) - The stacking fault formation energy.

  • ‘E_total_0’ (float) - The total potential energy of the system before applying the faultshift.

  • ‘E_total_sf’ (float) - The total potential energy of the system after applying the faultshift.

  • ‘delta_disp’ (float) - The change in the center of mass difference between before and after applying the faultshift.

  • ‘disp_0’ (float) - The center of mass difference between atoms above and below the fault plane in the cutboxvector direction for the system before applying the faultshift.

  • ‘disp_sf’ (float) - The center of mass difference between atoms above and below the fault plane in the cutboxvector direction for the system after applying the faultshift.

  • ‘A_fault’ (float) - The area of the fault surface.

  • ‘dumpfile_0’ (str) - The name of the LAMMMPS dump file associated with the relaxed system before applying the faultshift.

  • ‘dumpfile_sf’ (str) - The name of the LAMMMPS dump file associated with the relaxed system after applying the faultshift.

[14]:
length_unit = 'nm'
area_unit = 'nm^2'
energy_unit = 'eV'
energyperarea_unit = 'mJ/m^2'

print('Values for fractional shift = (%f, %f)' % (a1, a2))
print('A_fault =    ', uc.get_in_units(results_dict['A_fault'], area_unit), area_unit)
print('E_gsf =      ', uc.get_in_units(results_dict['E_gsf'], energyperarea_unit), energyperarea_unit)
print('delta_disp = ', uc.get_in_units(results_dict['delta_disp'], length_unit), length_unit)
Values for fractional shift = (0.333333, 0.333333)
A_fault =     5.365198866947918 nm^2
E_gsf =       125.2326094533902 mJ/m^2
delta_disp =  -0.004556012054242586 nm
[15]:
# Zero shift system
print('E_total_0 = ', uc.get_in_units(results_dict['E_total_0'], energy_unit), energy_unit)
print('disp_0 =    ', uc.get_in_units(results_dict['disp_0'], length_unit), length_unit)
print('config saved as', results_dict['dumpfile_0'] )
E_total_0 =  -13240.841174415 eV
disp_0 =     3.048407407287553 nm
config saved as zeroshift.dump
[16]:
# Specified shift system
print('E_total_sf = ', uc.get_in_units(results_dict['E_total_sf'], energy_unit), energy_unit)
print('disp_sf =    ', uc.get_in_units(results_dict['disp_sf'], length_unit), length_unit)
print('config saved as', results_dict['dumpfile_sf'] )
E_total_sf =  -13236.64751786 eV
disp_sf =     3.04385139523331 nm
config saved as shifted.dump