Skip to main content

Crystallographic stress-strain analysis with Voigt-Mandel notation and mechanical equilibrium constraints

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 correction
  • stress_corrected — per-grain stress after correction
  • hydrostatic_corrected, deviatoric, von_mises — decomposition
  • hydrostatic_shift — the d0 correction that was applied
  • uncertainty — 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

midas_stress-0.2.3.tar.gz (81.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

midas_stress-0.2.3-py3-none-any.whl (66.4 kB view details)

Uploaded Python 3

File details

Details for the file midas_stress-0.2.3.tar.gz.

File metadata

  • Download URL: midas_stress-0.2.3.tar.gz
  • Upload date:
  • Size: 81.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for midas_stress-0.2.3.tar.gz
Algorithm Hash digest
SHA256 c8ffb4be236e38ebcb3892500026a32c149270b507fd583843a653ffbeed5f98
MD5 0f90c55615a68874ba4ff2cd18429c23
BLAKE2b-256 2eaa8899d4c527bb82e18f7082c0e08e5ce1cf1e40b049b371f61a04963967a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for midas_stress-0.2.3.tar.gz:

Publisher: python-packages.yml on marinerhemant/MIDAS

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file midas_stress-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: midas_stress-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 66.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for midas_stress-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 76091fffad727e3a9c31ffb2038de809f61d9cbbc78cc5372da7b6aedfaa0e56
MD5 5ef89d34f379e7ac7bc2877c5c6960e7
BLAKE2b-256 b4576c6b4df23aa02361bec7d9690991a0dcbe2dff5c8096e3e816e6455898b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for midas_stress-0.2.3-py3-none-any.whl:

Publisher: python-packages.yml on marinerhemant/MIDAS

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page