Skip to content

hencky_elasticity: linear elasticity in the logarithmic strain - #141

Draft
petlenz wants to merge 4 commits into
feature/voigt-compositefrom
feature/hencky-elasticity
Draft

petlenz wants to merge 4 commits into
feature/voigt-compositefrom
feature/hencky-elasticity

Conversation

@petlenz

@petlenz petlenz commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Closes #113. Part of the uvwmaterial port (#94); stacked on #140.

materials/hencky_elasticity.h (hencky_elasticity): ε = ln V = ½ ln b with b = FFᵀ, τ = C : (ε − ε_eig), P = τ F⁻ᵀ, dP/dF = (C : d ln V/dF)·F⁻ᵀ − P ⊠̄ F⁻¹ with d ln V/dF = ½ (d ln b/db) : (I⊠F + F⊠̄I); the stiffness a consumed property (tangent_source, e.g. an isotropic_tangent of produced K and G — so cure-dependent moduli are a wiring), optional eigenstrain_source (thermal or chemical eigenstrain in the log strain), output log_strain. Dim generic. Replaces hencky_strains_linear_elastic and its thermo / thermo-chemo variants (the latter are hencky_elasticity plus thermal_eigenstrain).

tmech pin → main 46d8fdd (tmech#38). The report of this PR found that tmech's log and polar_decomposition were wrong at near-repeated eigenvalues (petlenz/tmech#37); the first version of this PR carried an interim core/log_strain.h on Eigen. With the fix merged the material uses tmech::log(b) and .derivative() directly, and the interim file, its tests and the Eigen include are gone. A tag would be preferable to the commit; FIND_PACKAGE_ARGS 1.2 still accepts an installed 1.2.0, which lacks the fix — the next tmech release should raise it.

Reports: load_case::fd_step is std::optional; a case may set it, otherwise the driver default applies instead of being overwritten. The finite-strain standard's fd_step: 1e-6 workaround is dropped; report_hencky_elasticity, report_neo_hooke and report_saint_venant_kirchhoff pass at 1e-7. docs/materials/hencky_elasticity/report.json: the finite-strain standard plus the uniaxial, volumetric and simple-shear closed forms.

Tests (test_hencky_elasticity, 7): dilatation P = 3K ln λ/λ exactly; the small-strain limit is linear elasticity; under uniaxial stress ln F₂₂ = −ν ln F₁₁ exactly and P₁₁ = E ln λ/λ, tangent against central differences at λ = 1.1, 1.5, 0.7 and in simple shear; the tangent at exactly and nearly repeated stretches (the tmech#37 symptom: (1.15, 1.15, 1), (1.2, 1.2, 1.2), (1.15, 1.15 + 1e-9, 1), (1.204, 0.9458, 0.9458)); objectivity P(RU) = R P(U) and P(R) = 0; constrained heating and free expansion with an eigenstrain; JSON.

Docs: docs/uvwmaterial-mapping.md row for the Hencky family; the card converter points hencky_strains_linear_* at hencky_elasticity (like saint_venant_kirchhoff, a finite-strain card needs an external_deformation_gradient_source written by hand).

907/907 tests pass (GCC 14, reports on).

JSON input

New material types: hencky_elasticity. A json_model document that loads (the FromJson test of the PR):

{"materials": [
  {"type": "external_deformation_gradient_source", "name": "F"},
  {"type": "constant_scalar", "name": "K", "value": 166.67},
  {"type": "constant_scalar", "name": "G", "value": 76.92},
  {"type": "isotropic_tangent", "name": "stiffness", "K_source": "K", "G_source": "G"},
  {"type": "hencky_elasticity", "name": "h", "deformation_gradient_source": "F", "tangent_source": "stiffness"}
]}

tangent_source a produced small-strain stiffness (cure-dependent moduli are a wiring); optional eigenstrain_source (a thermal_eigenstrain); outputs stress (P), tangent (dP/dF), log_strain.

@petlenz petlenz mentioned this pull request Oct 17, 2026
32 tasks
@petlenz

petlenz commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

The cause behind core/log_strain.h is fixed in tmech: petlenz/tmech#38 (Jacobi eigenpairs, projector eigenbases, closes petlenz/tmech#37). With that tmech, tmech::log(polar_decomposition(F).V()) and its derivative chain are exact at repeated stretches (central difference with h = 1e-7: 2e-9 instead of 0.46).

Plan for this PR once tmech#38 is merged and tagged: bump the tmech pin, drop core/log_strain.h and test_log_strain, and let hencky_elasticity use tmech::log(V) with log_V.derivative() : V().derivative() directly (the first version of this branch). Until then the Eigen-based evaluation keeps the material correct against the pinned tmech.

@petlenz

petlenz commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Review findings (design, tmech expressions instead of component loops, modern C++, comments, tests, correctness). Severity: must = wrong result, hang, build break or unreachable feature; should = design, duplication, accuracy; nit = style.

hencky_elasticity — needs changes

  • [must] core/log_strain.h:17-23 hard-codes tensor<T,3,2>; hencky_elasticity<Traits> passes Dim → ill-formed for Dim ≠ 2… i.e. only 3D compiles while neo_hooke/SVK are Dim-generic. Template on Dim.
  • [should] component loops marshalling to/from Eigen → Eigen::Map<Matrix<T,3,3> const>(b.raw_data()) (precedent unknown_layout.h:307) and tmech::adaptor<T const,3,1,full<3>> on eigenvector columns + otimes(n,n).
  • [should] divided-difference switch at 1e-8·mean sits where the loss is worst; use sqrt(eps) or log1p(d/λ)/(2d) for every d.
  • [should] mapping doc and converter still say Hencky is unported (hencky_elasticity: linear elasticity in logarithmic strain with thermal and chemical eigenstrain #113).
  • [should] case_runner.h:123 opts.fd_step = c.fd_step discards a caller's option → std::optional + value_or.
  • [should] swap plan: simpler than log(V) + polar derivative is ln_b = tmech::log(b); strain = ½ ln_b; derivative = ½ dcontract(ln_b.derivative(), db_dF) (what uvwmaterial did; db_dF is already a tmech expression).
  • [should] no objectivity test (P(RU) = R P(U), P(R) = 0).
  • [nit] deformation_gradient_source fetched twice; <array> missing; [[nodiscard]]; 6-line header; fd_step 1e-6 rationale.

@petlenz

petlenz commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Review findings addressed in the last commit (tmech#38 is merged, pin → main 46d8fdd):

  • must, Dim 3 only: core/log_strain.h is deleted; the material uses tmech::log(b) and .derivative(), which exist for Dim 2 and 3, and has no 3D code left.
  • should, Eigen marshalling loops: gone with the file.
  • should, divided-difference switch at 1e-8: gone with the file; tmech decides by the cancellation of f(λᵢ) − f(λⱼ) (tmech#38).
  • should, mapping doc / converter: row for hencky_strains_linear_elastic and the thermo variants → hencky_elasticity (+ thermal_eigenstrain); the converter raises the same hand-written hint as for saint_venant_kirchhoff.
  • should, opts.fd_step overwritten: load_case::fd_step is std::optional<T>, value_or(opts.fd_step); test_report_case covers unset and set.
  • should, swap plan: done as suggested, ln_b = tmech::log(b), strain = ½ ln_b, derivative = ½ (ln_b.derivative() : db/dF).
  • should, objectivity test: Hencky.IsObjective (P(RU) = R P(U) to 1e-12, P(R) = 0); plus TangentIsConsistentAtRepeatedStretches for the tmech#37 cases.
  • nit, source fetched twice: m_F_name like neo_hooke; update → compute; header comment 2 lines; fd_step 1e-6 removed from the finite-strain standard (all three finite-strain reports pass at 1e-7).

Not done here: a 2D runtime test — external_deformation_gradient_source is 3D only (static_assert at external_state_source.h:97), so a 2D Hencky point has no F provider yet.

@petlenz
petlenz force-pushed the feature/voigt-composite branch from 3d2fd8e to 4e92931 Compare October 17, 2026 15:01
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from 0a1f33c to 3506d30 Compare October 17, 2026 15:01
@petlenz
petlenz force-pushed the feature/voigt-composite branch from 4e92931 to bf49f47 Compare October 17, 2026 16:16
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from 3506d30 to 1300c84 Compare October 17, 2026 16:26
@petlenz
petlenz force-pushed the feature/voigt-composite branch from bf49f47 to e5e56ce Compare October 17, 2026 17:22
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from 1300c84 to 1d9084a Compare October 17, 2026 17:34
@petlenz

petlenz commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Producer/consumer pass: hencky_elasticity consumes its stiffness (tangent_source, tangent_property; an isotropic_tangent of produced K and G in the tests and the report) instead of carrying K/G parameters — the chemo variant of uvwmaterial with cure-dependent moduli is then a wiring, not a new material. The thermal eigenstrain in the fixture consumes alpha_source. Mapping row and converter hint updated. 929/929.

@petlenz
petlenz force-pushed the feature/voigt-composite branch from e5e56ce to 3693657 Compare October 17, 2026 21:44
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from 1d9084a to cf75acb Compare October 17, 2026 21:54
@petlenz
petlenz force-pushed the feature/voigt-composite branch from 3693657 to d067a3e Compare October 17, 2026 22:46
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from cf75acb to ec31ebe Compare October 17, 2026 22:58
@petlenz
petlenz force-pushed the feature/voigt-composite branch from d067a3e to a586b3c Compare October 18, 2026 13:25
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from ec31ebe to ebfb2d6 Compare October 18, 2026 13:37
@petlenz
petlenz force-pushed the feature/voigt-composite branch from a586b3c to 6cd5670 Compare October 18, 2026 13:38
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from ebfb2d6 to df4dddb Compare October 18, 2026 13:38
@petlenz
petlenz force-pushed the feature/voigt-composite branch from 6cd5670 to 8a28695 Compare October 18, 2026 18:55
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from df4dddb to a0b41e5 Compare October 18, 2026 18:55
@petlenz
petlenz force-pushed the feature/voigt-composite branch from 8a28695 to 11c29c7 Compare October 18, 2026 20:03
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from a0b41e5 to 2e918d1 Compare October 18, 2026 20:03
@petlenz
petlenz force-pushed the feature/voigt-composite branch from 11c29c7 to a5df503 Compare October 18, 2026 20:22
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from 2e918d1 to d2a423f Compare October 18, 2026 20:22
core/log_strain.h: ln V and d ln V / dF from an eigendecomposition of
F F^T (Eigen) with the divided-difference derivative, continuous through
repeated eigenvalues; tmech's log of V gives wrong values at eigenvalue
splits of about 1e-7 (petlenz/tmech#37). hencky_elasticity: tau = C :
(ln V - eps_eig), P = tau F^-T, consistent dP/dF, optional eigenstrain.
Report with the exact uniaxial and volumetric closed forms; reports take
a per-case fd_step.
…he phase materials

The composite is split into two nodes. mean_field_strain consumes the composite
strain increment and the phases' tangents, fractions and Eshelby tensors and
produces one strain per phase (history) and the concentration tensors, for
the voigt, reuss, hill, dilute and mori_tanaka kernels. The phase materials
consume those strains through strain_source / strain_property like any other
strain. mean_field_stress averages the stresses and tangents they produce with
the concentrations and reports a residual, the difference between the tangent
a phase node carried and its material's current one.

With linear phases every edge is global, one pass is exact and the result
equals mean_field_tangent with a linear_stress to round-off, the phase strains
and stresses available as properties. docs/mean_field.md describes the
composite layer.
tmech main (46d8fdd, after tmech#38) is exact at repeated eigenvalues, so the
material uses ln b from tmech::log(b) and its derivative, is Dim generic, and
core/log_strain.h with its Eigen dependency goes away. The per-case fd_step of
the reports is optional and no longer overrides the driver default; the 1e-6
workaround in the finite-strain standard is dropped (all three finite-strain
reports pass at 1e-7). New tests: tangent at repeated and nearly repeated
stretches (the tmech#37 symptom), objectivity P(RU) = R P(U) and P(R) = 0.
Mapping document and card converter list the Hencky family.
@petlenz
petlenz force-pushed the feature/voigt-composite branch from a5df503 to 53d3c19 Compare October 19, 2026 04:07
@petlenz
petlenz force-pushed the feature/hencky-elasticity branch from d2a423f to 72adaf0 Compare October 19, 2026 04:07
…rain

mean_field_strain and mean_field_stress: strain localisation around the phase materials (linear)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant