Repository navigation
Conversation
petlenz
force-pushed
the
feature/mean-field-local-strain
branch
from
October 18, 2026 18:55
4506dbc to
f17f10d
Compare
petlenz
force-pushed
the
feature/mean-field-local-nonlinear
branch
from
October 18, 2026 18:55
5f16f95 to
6540b58
Compare
petlenz
force-pushed
the
feature/mean-field-local-strain
branch
from
October 18, 2026 20:03
f17f10d to
a0a7d3b
Compare
petlenz
force-pushed
the
feature/mean-field-local-nonlinear
branch
from
October 18, 2026 20:03
6540b58 to
e9c11c8
Compare
petlenz
force-pushed
the
feature/mean-field-local-strain
branch
from
October 18, 2026 20:22
a0a7d3b to
7f55103
Compare
petlenz
force-pushed
the
feature/mean-field-local-nonlinear
branch
from
October 18, 2026 20:22
e9c11c8 to
58314fd
Compare
… phase, passes to the fixed point A phase whose tangent depends on its own strain closes a cycle through mean_field_strain: the concentrations need the algorithmic tangent, the tangent needs the local strain. The phase node reads that tangent with tangent_edge = local (no ordering, the value of the previous pass; the initial_tangent_source on the first pass), so one update() is one pass and mean_field_stress::residual says when the passes agree. The evaluator closes the fixed point per host call through residual_property. Tests with an isotropic-damage matrix and stiff spheres: below the threshold the chain equals the linear composite; after damage the local strains partition the composite strain, the state function saw the matrix strain, the stress is the phase average, the tangent is the concentration-weighted sum and matches central differences on a vanishing step; the residual decreases over the passes of a large step; stress control through the driver converges; the Reuss kernel ends with equal stresses in both phases. The report mean_field_damage runs the standard cases with the point closing the fixed point; the card converter maps a rule-of-mixture card with a nonlinear phase to the pair for every kernel.
…se with a hardening J2 matrix mean_field_damage records the intact Mori-Tanaka next to the local pair (composite and phase stresses, damage, local strains under strain and stress control; on first loading the damaged composite is softer, after a reversal the incremental localisation leaves a residual stress, noted). The new case mean_field_reuss_plastic runs the Reuss kernel through the passes with a J2 matrix: the phases carry the same stress to first order in the step.
petlenz
force-pushed
the
feature/mean-field-local-strain
branch
from
October 19, 2026 04:07
7f55103 to
427f671
Compare
petlenz
force-pushed
the
feature/mean-field-local-nonlinear
branch
from
October 19, 2026 04:07
58314fd to
d8789ec
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #116 (the nonlinear half; the linear localisation is #144). Part of the uvwmaterial port (#94); stacked on #144.
A phase whose tangent depends on its own strain closes a cycle through
mean_field_strain: the concentrations need the algorithmic tangent, the tangent needs the local strain. This PR adds the one piece that closes it and the tests that exercise it with an isotropic-damage matrix.The local edge. a phase whose tangent depends on its own strain closes a cycle. Its
phasenode reads the tangent over a local edge ("tangent_edge": "local", starting frominitial_tangent_sourceon the first pass):EdgeKind::Localimposes no ordering, so oneupdate()is one pass with the algorithmic tangent of the previous pass, and the fixed point is run by whoever callsupdate()— the evaluator per host call (residual_propertyof #131, the report point's"residual": "mt::residual"), a solver's Newton loop, or awhile (residual > tol) update()in a test. Isotropic damage keeps Poisson's ratio, so the Eshelby node reads ν of the undamaged tangent; an anisotropic algorithmic tangent would useisotropic_moduliwith a localnu_edgethe same way.Tests (
test_mean_field_damage, 9, stiff elastic spheres in a damaging matrix): below the threshold the damage chain reproduces the linear composite to 1e-10; after damage the local strains partition the composite strain (c_m ε_m + c_i ε_i = ε to 1e-12), the state function saw exactly the matrix strain, the spheres' stress is their tangent at their strain, the residual is converged, the stress is the phase average and the matrix softened below the intact composite; the tangent is Σ c_r C_r : A_r; the residual decreases over the passes of a large damaging step and reaches 1e-10; the tangent matches central differences on a vanishing step through the evaluator (< 1e-2); stress control through the driver converges and damages; the Reuss kernel with a hardening J2 matrix equalises the phase stresses to first order in the step (a softening phase in series is a snap-back problem, noted in the docs); a local edge without an initial tangent and non-parallel source lists are rejected; JSON.Converter: a rule-of-mixture card with a nonlinear phase becomes the local pair for every kernel (the damage chain reads
strain_<phase>, the damage phase carries the local edge from its elastic tangent except for Voigt, the point gets the residual) — the Reuss/Hill cases that raised #117 before.Docs: the nonlinear section and the fixed-point section of
docs/mean_field.md.Reports
docs/materials/mean_field_damage(the local pair with a damaging matrix against the intact Mori–Tanaka: composite and phase stresses, damage, local strains under strain and stress control; partition, phase-average, residual and softer-on-first-loading checks — after a reversal the incremental localisation leaves a residual stress, noted) anddocs/materials/mean_field_reuss_plastic(the Reuss kernel through the passes with a hardening J2 matrix: equal phase stresses to first order in the step). Their finite-difference tangent checks are off: the tangents are first order in Δε.966/966 tests pass (GCC 14, reports on).
JSON input
{"materials": [ {"type": "external_strain_source", "name": "strain"}, {"type": "constant_scalar", "name": "Km", "value": 3333.33}, {"type": "constant_scalar", "name": "Gm", "value": 1153.85}, {"type": "constant_scalar", "name": "Ki", "value": 166666.67}, {"type": "constant_scalar", "name": "Gi", "value": 76923.08}, {"type": "isotropic_tangent", "name": "C_m", "K_source": "Km", "G_source": "Gm"}, {"type": "isotropic_tangent", "name": "C_i", "K_source": "Ki", "G_source": "Gi"}, {"type": "isotropic_moduli", "name": "moduli", "tangent_source": "C_m"}, {"type": "eshelby_sphere", "name": "sphere", "nu_source": "moduli", "nu_property": "poisson_ratio"}, {"type": "constant_scalar", "name": "c", "value": 0.3}, {"type": "constant_scalar", "name": "cm", "value": 0.7}, {"type": "phase", "name": "matrix", "tangent_source": "damage", "tangent_property": "damaged_tangent", "tangent_edge": "local", "initial_tangent_source": "C_m", "fraction_source": "cm"}, {"type": "phase", "name": "spheres", "tangent_source": "C_i", "fraction_source": "c", "eshelby_source": "sphere"}, {"type": "mean_field_strain", "name": "mt_strain", "strain_source": "strain", "matrix": "matrix", "phases": ["spheres"], "kernel": "mori_tanaka"}, {"type": "linear_elasticity", "name": "elastic", "strain_producer_name": "mt_strain", "strain_property": "strain_matrix", "K": 3333.33, "G": 1153.85}, {"type": "von_mises_state_function", "name": "state", "strain_source": "mt_strain", "strain_property": "strain_matrix"}, {"type": "strain_threshold_yield", "name": "yield", "state_source": "state", "kappa_critical": 0.002}, {"type": "exponential_damage_law", "name": "law", "yield_source": "yield", "kappa_0": 0.002, "beta": 30.0}, {"type": "isotropic_damage", "name": "damage", "elastic_source": "elastic", "damage_source": "law", "state_source": "state", "yield_source": "yield"}, {"type": "linear_stress", "name": "stiff", "tangent_source": "C_i", "strain_source": "mt_strain", "strain_property": "strain_spheres"}, {"type": "mean_field_stress", "name": "mt", "concentration_source": "mt_strain", "matrix": "matrix", "phases": ["spheres"], "matrix_stress_source": "damage", "matrix_stress_property": "damaged_stress", "matrix_tangent_property": "damaged_tangent", "stress_sources": ["stiff"], "tangent_sources": ["C_i"]} ], "point": {"strain_source": "strain", "stress_source": "mt", "residual": "mt::residual", "tolerance": 1e-10, "max_passes": 200}}Linear phases are #144: the same two nodes without the local edge.