Introduction to atomman: Point defect generation
Lucas M. Hale, lucas.hale@nist.gov, Materials Science and Engineering Division, NIST.
1. Introduction
This Notebook provides an introduction to tools in atomman for generating point defects.
Library Imports
[1]:
# Standard libraries
import datetime
# http://www.numpy.org/
import numpy as np
# https://github.com/usnistgov/atomman
import atomman as am
import atomman.unitconvert as uc
# Show atomman version
print('atomman version =', am.__version__)
# Show date of Notebook execution
print('Notebook executed on', datetime.date.today())
atomman version = 1.4.10
Notebook executed on 2023-07-28
Define 2x2x2 CsCl supercell for testing
[2]:
atoms = am.Atoms(atype=[1,2], pos=[[0.0, 0.0, 0.0],[0.5, 0.5, 0.5]], charge=[-1.0, 1.0])
alat = uc.set_in_units(4.11, 'angstrom')
box = am.Box(a=alat, b=alat, c=alat)
ucell = am.System(atoms=atoms, box=box, scale=True)
system = ucell.supersize(2,2,2)
# Print system information
print(system.box)
print('natoms =', system.natoms)
print('natypes =', system.natypes)
system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 16
natypes = 2
[2]:
atype | pos[0] | pos[1] | pos[2] | charge | |
---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 |
1 | 2 | 2.055 | 2.055 | 2.055 | 1.0 |
2 | 1 | 4.110 | 0.000 | 0.000 | -1.0 |
3 | 2 | 6.165 | 2.055 | 2.055 | 1.0 |
4 | 1 | 0.000 | 4.110 | 0.000 | -1.0 |
5 | 2 | 2.055 | 6.165 | 2.055 | 1.0 |
6 | 1 | 4.110 | 4.110 | 0.000 | -1.0 |
7 | 2 | 6.165 | 6.165 | 2.055 | 1.0 |
8 | 1 | 0.000 | 0.000 | 4.110 | -1.0 |
9 | 2 | 2.055 | 2.055 | 6.165 | 1.0 |
10 | 1 | 4.110 | 0.000 | 4.110 | -1.0 |
11 | 2 | 6.165 | 2.055 | 6.165 | 1.0 |
12 | 1 | 0.000 | 4.110 | 4.110 | -1.0 |
13 | 2 | 2.055 | 6.165 | 6.165 | 1.0 |
14 | 1 | 4.110 | 4.110 | 4.110 | -1.0 |
15 | 2 | 6.165 | 6.165 | 6.165 | 1.0 |
[3]:
am.plot.py3Dmol.view_3d(system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol
2. atomman.defect.vacancy()
Generates a new system by adding a vacancy point defect.
Removes the indicated atom from the system
Adds per-atom property old_id if it doesn’t exist corresponding to the atom ids in the original system.
Parameters
system (atomman.System) The base System to add the defect to.
pos (array-like object, optional) Position of the atom to be removed. Either pos or ptd_id must be given.
ptd_id (int, optional) Id of the atom to be removed. Either pos or ptd_id must be given.
scale (bool, optional) Indicates if pos is Cartesian (False) or box-relative (True). Default value is False.
atol (float, optional) Absolute tolerance for position-based searching. Default value is 1e-3 angstroms.
Returns
(atomman.System) A new system with the vacancy added.
[4]:
# Add a vacancy by deleting atom 5
d_system = am.defect.vacancy(system, ptd_id=5)
# Add a second vacancy by deleting atom at position [0.00, 4.110, 4.110]
d_system = am.defect.vacancy(d_system, pos=[0.00, 4.11, 4.11])
# Print system information
print(d_system.box)
print('natoms =', d_system.natoms)
print('natypes =', d_system.natypes)
d_system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 14
natypes = 2
[4]:
atype | pos[0] | pos[1] | pos[2] | charge | old_id | |
---|---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 | 0 |
1 | 2 | 2.055 | 2.055 | 2.055 | 1.0 | 1 |
2 | 1 | 4.110 | 0.000 | 0.000 | -1.0 | 2 |
3 | 2 | 6.165 | 2.055 | 2.055 | 1.0 | 3 |
4 | 1 | 0.000 | 4.110 | 0.000 | -1.0 | 4 |
5 | 1 | 4.110 | 4.110 | 0.000 | -1.0 | 6 |
6 | 2 | 6.165 | 6.165 | 2.055 | 1.0 | 7 |
7 | 1 | 0.000 | 0.000 | 4.110 | -1.0 | 8 |
8 | 2 | 2.055 | 2.055 | 6.165 | 1.0 | 9 |
9 | 1 | 4.110 | 0.000 | 4.110 | -1.0 | 10 |
10 | 2 | 6.165 | 2.055 | 6.165 | 1.0 | 11 |
11 | 2 | 2.055 | 6.165 | 6.165 | 1.0 | 13 |
12 | 1 | 4.110 | 4.110 | 4.110 | -1.0 | 14 |
13 | 2 | 6.165 | 6.165 | 6.165 | 1.0 | 15 |
[5]:
am.plot.py3Dmol.view_3d(d_system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol
3. atomman.defect.interstitial()
Generates a new system by adding a vacancy point defect.
Adds a new atom to the end of the Atoms list.
Adds per-atom property old_id if it doesn’t exist corresponding to the atom ids in the original system.
Sets any of the new atom’s per-atom properties to values given as kwargs. Any undefined properties are given zero values except atype, which is set to 1.
Parameters
system (atomman.System) The base System to add the defect to.
pos (array-like object) Position of the atom being added.
scale (bool, optional) Indicates if pos is Cartesian (False) or box-relative (True). Default value is False.
atol (float, optional) Absolute tolerance for position-based searching. Default value is 1e-3 angstroms.
**kwargs (any, optional) Keyword arguments corresponding to per-atom property values for the new atom. By default, atype==1 and all other properties are set to be all zeros for the property’s shape.
Returns
(atomman.System) A new system with the interstitial added.
[6]:
# Add interstitial at pos = [1.515, 1.515, 0.000] without defining atype, charge
d_system = am.defect.interstitial(system, pos=[1.515, 1.515, 0.0])
# Add second interstitial at pos = [1.515, 4.545, 0.000] with defining atype, charge
d_system = am.defect.interstitial(d_system, pos=[1.515, 4.545, 0.0], atype=2, charge=1)
# Print system information
print(d_system.box)
print('natoms =', d_system.natoms)
print('natypes =', d_system.natypes)
d_system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 18
natypes = 2
[6]:
atype | pos[0] | pos[1] | pos[2] | charge | old_id | |
---|---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 | 0 |
1 | 2 | 2.055 | 2.055 | 2.055 | 1.0 | 1 |
2 | 1 | 4.110 | 0.000 | 0.000 | -1.0 | 2 |
3 | 2 | 6.165 | 2.055 | 2.055 | 1.0 | 3 |
4 | 1 | 0.000 | 4.110 | 0.000 | -1.0 | 4 |
5 | 2 | 2.055 | 6.165 | 2.055 | 1.0 | 5 |
6 | 1 | 4.110 | 4.110 | 0.000 | -1.0 | 6 |
7 | 2 | 6.165 | 6.165 | 2.055 | 1.0 | 7 |
8 | 1 | 0.000 | 0.000 | 4.110 | -1.0 | 8 |
9 | 2 | 2.055 | 2.055 | 6.165 | 1.0 | 9 |
10 | 1 | 4.110 | 0.000 | 4.110 | -1.0 | 10 |
11 | 2 | 6.165 | 2.055 | 6.165 | 1.0 | 11 |
12 | 1 | 0.000 | 4.110 | 4.110 | -1.0 | 12 |
13 | 2 | 2.055 | 6.165 | 6.165 | 1.0 | 13 |
14 | 1 | 4.110 | 4.110 | 4.110 | -1.0 | 14 |
15 | 2 | 6.165 | 6.165 | 6.165 | 1.0 | 15 |
16 | 1 | 1.515 | 1.515 | 0.000 | 0.0 | 16 |
17 | 2 | 1.515 | 4.545 | 0.000 | 1.0 | 17 |
[8]:
am.plot.py3Dmol.view_3d(d_system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol
4. atomman.defect.substitutional()
Generates a new system by adding a substitutional point defect.
Moves the indicated atom to the end of the list and changes its atype to the value given.
Adds per-atom property old_id if it doesn’t exist corresponding to the atom ids in the original system.
Sets any of the moved atom’s per-atom properties to values given as kwargs. Any undefined properties are left unchanged.
Parameters
system (atomman.System) The base System to add the defect to.
pos (array-like object, optional) Position of the atom being modified. Either pos or ptd_id must be given.
ptd_id (int, optional) Id of the atom to be modified. Either pos or ptd_id must be given.
atype (int, optional) Integer atomic type to change the identified atom to. Must be different than the atom’s current id. Default value is 1.
scale (bool, optional) Indicates if pos is Cartesian (False) or box-relative (True). Default value is False.
atol (float, optional) Absolute tolerance for position-based searching. Default value is 1e-3 angstroms.
**kwargs (any, optional) Keyword arguments corresponding to per-atom property values for the modified atom. By default, all properties (except atype) are left unchanged.
Returns
(atomman.System) A new system with the substitutional added.
[9]:
# Make atom 1 a substitutional without changing charge
d_system = am.defect.substitutional(system, ptd_id=1, atype=3)
# Add second substitutional at pos = [0.00, 4.11, 4.11] and change charge
d_system = am.defect.substitutional(d_system, pos=[0.00, 4.11, 4.11], atype=2, charge=1)
# Print system information
print(d_system.box)
print('natoms =', d_system.natoms)
print('natypes =', d_system.natypes)
d_system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 16
natypes = 3
[9]:
atype | pos[0] | pos[1] | pos[2] | charge | old_id | |
---|---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 | 0 |
1 | 1 | 4.110 | 0.000 | 0.000 | -1.0 | 2 |
2 | 2 | 6.165 | 2.055 | 2.055 | 1.0 | 3 |
3 | 1 | 0.000 | 4.110 | 0.000 | -1.0 | 4 |
4 | 2 | 2.055 | 6.165 | 2.055 | 1.0 | 5 |
5 | 1 | 4.110 | 4.110 | 0.000 | -1.0 | 6 |
6 | 2 | 6.165 | 6.165 | 2.055 | 1.0 | 7 |
7 | 1 | 0.000 | 0.000 | 4.110 | -1.0 | 8 |
8 | 2 | 2.055 | 2.055 | 6.165 | 1.0 | 9 |
9 | 1 | 4.110 | 0.000 | 4.110 | -1.0 | 10 |
10 | 2 | 6.165 | 2.055 | 6.165 | 1.0 | 11 |
11 | 2 | 2.055 | 6.165 | 6.165 | 1.0 | 13 |
12 | 1 | 4.110 | 4.110 | 4.110 | -1.0 | 14 |
13 | 2 | 6.165 | 6.165 | 6.165 | 1.0 | 15 |
14 | 3 | 2.055 | 2.055 | 2.055 | 1.0 | 1 |
15 | 2 | 0.000 | 4.110 | 4.110 | 1.0 | 12 |
[10]:
am.plot.py3Dmol.view_3d(d_system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol
5. atomman.defect.dumbbell()
Generates a new system by adding a dumbbell interstitial point defect.
Copies the indicated atom and moves both the original and copy to the end of the Atoms list.
Displaces the dumbbell atoms position’s by +-db_vect.
Adds per-atom property old_id if it doesn’t exist corresponding to the atom ids in the original system.
Sets any of the new atom’s per-atom properties to values given as kwargs. Any undefined properties are left unchanged.
Parameters
system (atomman.System) The base System to add the defect to.
pos (array-like object, optional) Position of the atom being modified. Either pos or ptd_id must be given.
ptd_id (int, optional) Id of the atom to be modified. Either pos or ptd_id must be given.
db_vect (array-like object) Vector shift to apply to the atoms in the dumbbell.
scale (bool, optional) Indicates if pos and db_vect are Cartesian (False) or box-relative (True). Default value is False.
atol (float, optional) Absolute tolerance for position-based searching. Default value is 1e-3 angstroms.
**kwargs (any, optional) Keyword arguments corresponding to per-atom property values for the new atom in the dumbbell. By default, all properties are left unchanged (i.e. same as atom that was copied).
Returns
(atomman.System) A new system with the dumbbell added.
[11]:
# Turn atom 5 into a dumbbell
d_system = am.defect.dumbbell(system, ptd_id=5, db_vect=[0.5, 0.5, 0.5])
# Print system information
print(d_system.box)
print('natoms =', d_system.natoms)
print('natypes =', d_system.natypes)
d_system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 17
natypes = 2
[11]:
atype | pos[0] | pos[1] | pos[2] | charge | old_id | |
---|---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 | 0 |
1 | 2 | 2.055 | 2.055 | 2.055 | 1.0 | 1 |
2 | 1 | 4.110 | 0.000 | 0.000 | -1.0 | 2 |
3 | 2 | 6.165 | 2.055 | 2.055 | 1.0 | 3 |
4 | 1 | 0.000 | 4.110 | 0.000 | -1.0 | 4 |
5 | 1 | 4.110 | 4.110 | 0.000 | -1.0 | 6 |
6 | 2 | 6.165 | 6.165 | 2.055 | 1.0 | 7 |
7 | 1 | 0.000 | 0.000 | 4.110 | -1.0 | 8 |
8 | 2 | 2.055 | 2.055 | 6.165 | 1.0 | 9 |
9 | 1 | 4.110 | 0.000 | 4.110 | -1.0 | 10 |
10 | 2 | 6.165 | 2.055 | 6.165 | 1.0 | 11 |
11 | 1 | 0.000 | 4.110 | 4.110 | -1.0 | 12 |
12 | 2 | 2.055 | 6.165 | 6.165 | 1.0 | 13 |
13 | 1 | 4.110 | 4.110 | 4.110 | -1.0 | 14 |
14 | 2 | 6.165 | 6.165 | 6.165 | 1.0 | 15 |
15 | 2 | 1.555 | 5.665 | 1.555 | 1.0 | 5 |
16 | 2 | 2.555 | 6.665 | 2.555 | 1.0 | 16 |
[12]:
# Show that dumbbell atoms are separated by 2 * db_vect
print("(d_system.atoms.pos[-1] - d_system.atoms.pos[-2]) / 2 ->", (d_system.atoms.pos[-1] - d_system.atoms.pos[-2]) / 2)
(d_system.atoms.pos[-1] - d_system.atoms.pos[-2]) / 2 -> [0.5 0.5 0.5]
[13]:
am.plot.py3Dmol.view_3d(d_system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol
6. atomman.defect.point()
Generates a new System where a point defect has been inserted. Provides a common interface for the vacancy(), interstitial(), substitutional() and dumbbell() functions.
Parameters
system (atomman.System) The base System to add the defect to.
ptd_type (str, optional) Key indicating which type of defect to add. Default value is ‘v’:
‘v’ : vacancy.
‘i’ : positional interstitial.
‘s’ : substitutional.
‘db’ : dumbbell interstitial.
pos (array-like object, optional) Position for adding the defect atom (all styles).
ptd_id (int, optional) Atom id where defect is added. Alternative to using pos (‘v’, ‘s’, ‘db’ styles).
db_vect (array-like object, optional) Vector associated with the dumbbell interstitial (‘db’ style).
scale (bool, optional) Indicates if pos and db_vect are Cartesian (False) or box-relative (True). Default value is False.
atol (float, optional) Absolute tolerance for position-based searching. Default value is 1e-3 angstroms.
**kwargs (any, optional) Keyword arguments corresponding to per-atom property values for the new/modified atom (‘i’, ‘s’, ‘db’ styles).
Raises
(AssertionError) If parameters are given for styles that don’t allow them.
(ValueError) If an invalid ptd_type is given.
Returns
(atomman.System) A new system containing the defect.
[14]:
# Use point() to make atom 7 a dumbbell of two atoms of atype 3
# ptd_type 's' changes atom 7 and moves to last atom
d_system = am.defect.point(system, 's', ptd_id=7, atype=3, charge=-0.5)
# ptd_type 'db' turns last atom into dumbbell, copying per-atom properties
d_system = am.defect.point(d_system, 'db', ptd_id=-1, db_vect=[0.6, 0.0, 0.6])
# Print system information
print(d_system.box)
print('natoms =', d_system.natoms)
print('natypes =', d_system.natypes)
d_system.atoms_df()
avect = [ 8.220, 0.000, 0.000]
bvect = [ 0.000, 8.220, 0.000]
cvect = [ 0.000, 0.000, 8.220]
origin = [ 0.000, 0.000, 0.000]
natoms = 17
natypes = 3
[14]:
atype | pos[0] | pos[1] | pos[2] | charge | old_id | |
---|---|---|---|---|---|---|
0 | 1 | 0.000 | 0.000 | 0.000 | -1.0 | 0 |
1 | 2 | 2.055 | 2.055 | 2.055 | 1.0 | 1 |
2 | 1 | 4.110 | 0.000 | 0.000 | -1.0 | 2 |
3 | 2 | 6.165 | 2.055 | 2.055 | 1.0 | 3 |
4 | 1 | 0.000 | 4.110 | 0.000 | -1.0 | 4 |
5 | 2 | 2.055 | 6.165 | 2.055 | 1.0 | 5 |
6 | 1 | 4.110 | 4.110 | 0.000 | -1.0 | 6 |
7 | 1 | 0.000 | 0.000 | 4.110 | -1.0 | 8 |
8 | 2 | 2.055 | 2.055 | 6.165 | 1.0 | 9 |
9 | 1 | 4.110 | 0.000 | 4.110 | -1.0 | 10 |
10 | 2 | 6.165 | 2.055 | 6.165 | 1.0 | 11 |
11 | 1 | 0.000 | 4.110 | 4.110 | -1.0 | 12 |
12 | 2 | 2.055 | 6.165 | 6.165 | 1.0 | 13 |
13 | 1 | 4.110 | 4.110 | 4.110 | -1.0 | 14 |
14 | 2 | 6.165 | 6.165 | 6.165 | 1.0 | 15 |
15 | 3 | 5.565 | 6.165 | 1.455 | -0.5 | 7 |
16 | 3 | 6.765 | 6.165 | 2.655 | -0.5 | 16 |
[15]:
am.plot.py3Dmol.view_3d(d_system, height=400, width=400)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol