Crystallographic stress-strain analysis with Voigt-Mandel notation and mechanical equilibrium constraints; torch-native API across orientation/frames/tensor/equilibrium/materials/plasticity/elastic_inverse
Project description
midas-stress
Crystallographic stress-strain analysis with Voigt-Mandel notation and mechanical equilibrium constraints.
A pure-Python library (NumPy + SciPy) for computing stress from strain in polycrystalline materials measured by High-Energy Diffraction Microscopy (HEDM), neutron diffraction, synchrotron strain scanning, or EBSD. Optional PyTorch backend for differentiable analysis.
Part of the MIDAS toolkit.
Installation
pip install midas-stress
For the PyTorch backend (GPU-accelerated, differentiable):
pip install midas-stress[torch]
Quick start — with any HEDM code
The library works with numpy arrays from any source — MIDAS, hexrd, ImageD11, DAXM, or your own scripts. Just provide orientations, strains, and volumes:
import numpy as np
import midas_stress as ms
# Your data (from hexrd, ImageD11, or any source):
orientations = np.array(...) # (N, 3, 3) orientation matrices
strains = np.array(...) # (N, 3, 3) strain tensors (lab frame)
volumes = np.array(...) # (N,) grain volumes
# One function does everything:
result = ms.compute_stress(
strain=strains,
stiffness=ms.get_stiffness("Cu"),
orient=orientations,
volumes=volumes,
)
print(f"Mean von Mises: {result['von_mises'].mean():.1f} GPa")
print(f"d0 correction: {result['hydrostatic_shift']:.1f} GPa")
print(f"Correction SE: {result['uncertainty']['hydrostatic_se_MPa']:.1f} MPa")
The returned result dict contains:
stress_raw— per-grain stress before equilibrium correctionstress_corrected— per-grain stress after correctionhydrostatic_corrected,deviatoric,von_mises— decompositionhydrostatic_shift— the d0 correction that was applieduncertainty— statistical uncertainty of the correction
Quick start — with MIDAS output
import midas_stress as ms
grains = ms.read_grains("Grains.csv")
# Optional: convert MIDAS -> APS frame
sam = ms.grains_midas_to_sample(
grains['orientations'], grains['positions'],
grains['strain'], target_frame="aps",
)
result = ms.compute_stress(
strain=sam['strains'],
stiffness=ms.get_stiffness("Cu"),
orient=sam['orientations'],
volumes=(4/3) * 3.14159 * grains['radii']**3,
confidences=grains.get('confidences'),
min_confidence=0.5,
)
Why equilibrium constraints matter
Every HEDM experiment has an unknown strain-free lattice parameter (d0). A tiny error in d0 causes a large systematic error in hydrostatic stress — identical for every grain and therefore invisible in grain-to-grain comparisons:
| Material | d0 error (ppm) | Hydrostatic stress error (MPa) |
|---|---|---|
| Cu | 100 | 41 |
| Fe | 100 | 50 |
| Ni | 100 | 54 |
| W | 100 | 93 |
midas-stress is the only library that fixes this via mechanical equilibrium:
- FF-1: Volume-average stress constraint (forces macroscopic balance)
- FF-2: Force-balance d0 (determines hydrostatic component from equilibrium, not from d0)
- Confidence weighting: handles incomplete grain populations
- Uncertainty estimation: reports how reliable the correction is
Features
Voigt-Mandel tensor algebra
voigt = ms.tensor_to_voigt(strain_3x3) # (3,3) -> (6,)
tensor = ms.voigt_to_tensor(voigt_6) # (6,) -> (3,3)
M = ms.rotation_voigt_mandel(orient) # 6x6 rotation in Voigt space
p = ms.hydrostatic(stress) # scalar pressure
s = ms.deviatoric(stress) # deviatoric tensor
vm = ms.von_mises(stress) # von Mises equivalent
All operations are vectorized: pass (N, 3, 3) arrays for batch computation.
Hooke's law with stiffness database
# Built-in stiffness for 9 materials: Au, Cu, Al, Fe, Ni, Ti, W, Si, CeO2
C = ms.get_stiffness("Fe")
# Or build your own
C = ms.cubic_stiffness(C11=231.4, C12=134.7, C44=116.4)
C = ms.hexagonal_stiffness(C11=162.4, C12=92.0, C13=69.0, C33=180.7, C44=46.7)
# d0 sensitivity analysis
sens = ms.d0_sensitivity("Cu")
print(f"Cu: {sens['sensitivity_MPa_per_100ppm']:.1f} MPa per 100 ppm d0 error")
Coordinate frame conversions
# MIDAS (X=beam, Y=OB, Z=up) <-> APS (X=OB, Y=up, Z=beam)
sam = ms.grains_midas_to_sample(orientations, positions, strains,
target_frame="aps", omega_deg=0)
Orientation and misorientation
angle, axis = ms.misorientation(euler1, euler2, space_group=225)
# All 230 space groups supported
# C-accelerated when MIDAS is built; pure-Python fallback otherwise
I/O
grains = ms.read_grains("Grains.csv") # MIDAS CSV format
grains = ms.read_grains("output.h5") # Consolidated HDF5
PyTorch backend (optional)
import midas_stress.torch_backend as mst
stress = mst.hooke_stress(strain_tensor, stiffness, orient, frame="lab")
Voigt-Mandel convention
v = [T_xx, T_yy, T_zz, sqrt(2)*T_xy, sqrt(2)*T_xz, sqrt(2)*T_yz]
The sqrt(2) scaling preserves the Frobenius norm: ||T||_F == ||v||_2.
Citation
@article{midas_stress,
title = {Determination of the strain-free lattice parameter from
mechanical equilibrium in grain-resolved diffraction stress analysis},
author = {Sharma, Hemant and Park, Jun-Sang and Kenesei, Peter},
journal = {submitted},
year = {2026},
}
License
BSD-3-Clause. See LICENSE.
For maintainers
See RELEASING.md for the release workflow
(./release.sh <version> --publish handles everything end-to-end).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file midas_stress-0.6.0.tar.gz.
File metadata
- Download URL: midas_stress-0.6.0.tar.gz
- Upload date:
- Size: 105.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4249a76ee77e219ec0a5b353ca63c2df82bd9d2486b9d524a8ad610b5f77dff
|
|
| MD5 |
f6e25dc0021e93ff7881bf5d3418acfa
|
|
| BLAKE2b-256 |
be07ddae9c56f926d6f68f3cb8c8693c50300ce1f8fc08285d62c37fa8840060
|
Provenance
The following attestation bundles were made for midas_stress-0.6.0.tar.gz:
Publisher:
python-packages.yml on marinerhemant/MIDAS
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
midas_stress-0.6.0.tar.gz -
Subject digest:
e4249a76ee77e219ec0a5b353ca63c2df82bd9d2486b9d524a8ad610b5f77dff - Sigstore transparency entry: 1399156883
- Sigstore integration time:
-
Permalink:
marinerhemant/MIDAS@239f03fd1ecd21a4c5d5019d16eb6cf30f41a107 -
Branch / Tag:
refs/tags/midas-stress-v0.6.0 - Owner: https://github.com/marinerhemant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-packages.yml@239f03fd1ecd21a4c5d5019d16eb6cf30f41a107 -
Trigger Event:
release
-
Statement type:
File details
Details for the file midas_stress-0.6.0-py3-none-any.whl.
File metadata
- Download URL: midas_stress-0.6.0-py3-none-any.whl
- Upload date:
- Size: 83.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02ed009cc4e587a82453a62d80dde2fbb5ec74c67a8d57e69b090e411141c4a2
|
|
| MD5 |
3a5482e7c9cd822146741e599c34c6cd
|
|
| BLAKE2b-256 |
c0d709ef98c1c36191c990f239b64c406ac015f92df40bf3cbd447e565fc590f
|
Provenance
The following attestation bundles were made for midas_stress-0.6.0-py3-none-any.whl:
Publisher:
python-packages.yml on marinerhemant/MIDAS
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
midas_stress-0.6.0-py3-none-any.whl -
Subject digest:
02ed009cc4e587a82453a62d80dde2fbb5ec74c67a8d57e69b090e411141c4a2 - Sigstore transparency entry: 1399156905
- Sigstore integration time:
-
Permalink:
marinerhemant/MIDAS@239f03fd1ecd21a4c5d5019d16eb6cf30f41a107 -
Branch / Tag:
refs/tags/midas-stress-v0.6.0 - Owner: https://github.com/marinerhemant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-packages.yml@239f03fd1ecd21a4c5d5019d16eb6cf30f41a107 -
Trigger Event:
release
-
Statement type: