Atomic strain¶
AtomicStrain measures the local deformation of each atom between a
reference configuration and the current one: the von Mises shear and
volumetric strains and, when asked for, the strain tensor and the
non-affine displacement \(D^2_\text{min}\).
import numpy as np
import mdapy as mp
from mdapy.analysis import AtomicStrain
from mdapy.build import build_crystal
a = 3.615
reference = build_crystal("fcc", a, elements="Cu", repeat=(4, 4, 4))
# the crystal sheared by 2 % with its box
shear = np.array([[1, 0.02, 0], [0, 1, 0], [0, 0, 1]])
current = reference.with_box(
mp.Box(reference.box.matrix @ shear.T), scale_positions=True
)
strain = AtomicStrain(reference, cutoff=3.0)
result = strain.compute(current)
result.shear # von Mises shear strain, the same for every atom here
current = current.with_columns(result) # shear_strain, volumetric_strain
# also the strain tensor and the non-affine displacement
result = AtomicStrain(reference, 3.0, strain_tensor=True, d2min=True).compute(current)
result.strain_tensor[0] # (3, 3) of the first atom
# many frames against one reference: find its neighbors once
neighbors = mp.NeighborList.build(reference, 3.0)
strain = AtomicStrain(reference, cutoff=3.0, neighbors=neighbors)
A rod of copper twisted about its axis shears more the farther from the axis:
from mdapy.build import build_crystal
from mdapy.visualization import render
crystal = build_crystal("fcc", a, elements="Cu", repeat=(10, 10, 20))
center = crystal.box.matrix.diagonal() / 2
p = crystal["positions"] - center
rod = crystal.filter(np.hypot(p[:, 0], p[:, 1]) < 15)
rod = rod.with_box(mp.Box(crystal.box.matrix, pbc=False))
p = rod["positions"] - center
angle = 0.004 * p[:, 2] # radians, growing along the axis
twisted = rod.with_columns(positions=center + np.column_stack([
p[:, 0] * np.cos(angle) - p[:, 1] * np.sin(angle),
p[:, 0] * np.sin(angle) + p[:, 1] * np.cos(angle),
p[:, 2],
])) # fmt: skip
shear = AtomicStrain(rod, cutoff=3.0).compute(twisted).shear
render(twisted, "images/atomic-strain.png", atoms=p[:, 1] < 0, color=shear, colormap="plasma",
box=False, view=(0.5, -1, -0.3), width=900, height=600, legend="shear strain") # fmt: skip

The rod cut along its axis: the von Mises shear strain grows from zero on the axis (dark) to about 0.03 at the surface (yellow), half the twist of 0.004 rad/Å times the distance from the axis.
Parameters¶
| Name | Type | Default | Unit | Meaning |
|---|---|---|---|---|
reference |
System |
the reference configuration, with the same atoms as the systems to compare: matched by the id column where both have one, else in the same order |
||
cutoff |
float64 | Å | the neighbors closer than it in the reference define the neighbor vectors | |
affine |
bool | False |
measure the current vectors in the reference box, which removes the homogeneous deformation of the box | |
strain_tensor |
bool | False |
also give the strain tensor of each atom | |
d2min |
bool | False |
also compute the non-affine squared displacement of each atom | |
neighbors |
NeighborList |
None |
neighbors of the reference within at least cutoff, used for every configuration; without, compute finds them as it goes each time |
compute(system, *, progress=None, cancel=None) takes the current
configuration: the atoms of the reference, each moved by less than half
the box. Positions may be wrapped back into the box.
Results¶
A StrainResult:
| Attribute | Type | Unit | Meaning |
|---|---|---|---|
shear |
(N,) float64 | the von Mises shear strain \(\eta_\text{s}\), NaN where the reference neighbors do not span three dimensions; its column shear_strain |
|
volumetric |
(N,) float64 | the volumetric strain \(\operatorname{tr}\eta / 3\); its column volumetric_strain |
|
strain_tensor |
(N, 3, 3) float64 | the Green–Lagrange strain \(\eta\), with strain_tensor, else None |
|
d2min |
(N,) float64 | Ų | the non-affine squared displacement \(D^2_\text{min}\), with d2min, else None; its column d2min |
Errors¶
The constructor raises InvalidParameter for a cutoff that is not positive;
compute raises it for a system with another number of atoms or other
periodic directions than the reference, or repeated ids;
MissingProperty for an
atom whose id the reference does not have.
Definition¶
The neighbors of atom \(i\) are the atoms closer than the cutoff in the
reference, periodic images included, at the vectors \(\mathbf d^0_j\). Their
current vectors \(\mathbf d_j\) follow from each atom's displacement, taken by
the nearest periodic image in fractional coordinates, in the current box or,
with affine, in the reference box. The deformation gradient minimizes
\(\sum_j |\mathbf d_j - F \mathbf d^0_j|^2\):
See also¶
- OVITO Atomic strain.
Please cite
Shimizu et al. (2007); for \(D^2_\text{min}\), Falk and Langer (1998).