Skip to content

feat(constitutive): power-mean yield soft-min smoother + rampable delta constant - #380

Closed
lmoresi wants to merge 1 commit into
developmentfrom
feature/yield-powermean
Closed

feat(constitutive): power-mean yield soft-min smoother + rampable delta constant#380
lmoresi wants to merge 1 commit into
developmentfrom
feature/yield-powermean

Conversation

@lmoresi

@lmoresi lmoresi commented Jul 22, 2026

Copy link
Copy Markdown
Member

What

Adds the power-mean soft-min yield smoother and makes the soft-min softness δ a constants[] atom (runtime-rampable with no JIT recompile) on the ViscousFlowModel base class, so the visco-plastic subclasses inherit one implementation. This is the generalisable, scalable substrate for a yield homotopy toward the sharp Min surface (companion to the solver difficulty/bounded-solve tooling in #377).

Base class (ViscousFlowModel):

  • _combine_yield(eta_ve, eta_pl) -- the shared viscous/plastic combination, keyed on yield_mode: "min" (exact hard Min), "harmonic", or "softmin" (the δ soft-min in the family chosen by yield_smoother). Development's tri-modal yield_mode semantics are preserved exactly (the source branch had collapsed "softmin" into "min"; that is deliberately NOT adopted).
  • _get_yield_softness / _get_yield_offset -- δ and the onset offset held as constants[] UWexpression atoms (the offset defined symbolically in terms of δ = one symbol in the stress tensor, no tensor blow-up; one δ update repacks both). Ramping δ via the atom + solver._update_constants() forces no recompile.
  • yield_smoother property/setter -- "sqrt" (default; overshoots τ_y in the transition) or "powermean" (undershoots τ_y -- eta_eff <= Min always -- overflow-safe on geodynamic ranges).

Models (Stage 1 -- isotropic, test-covered):

  • ViscoPlasticFlowModel (Drucker-Prager): defaults to yield_mode="min" == today's exact hard Min (zero behaviour change), and gains yield_mode / yield_softness knobs so it can opt into the softmin / power-mean homotopy -- the model the hard-case DP homotopy needs.
  • ViscoElasticPlasticFlowModel (VEP): its inline sqrt soft-min routed through _combine_yield; δ moves float -> atom (value-identical); yield_softness setter syncs the atom.

Why

The power-mean smoother is the preferred, physically-admissible (undershoot) homotopy family; holding δ as a rampable constant is what makes a scalable δ-continuation cheap (no recompile per step).

Safety -- zero behaviour change at stock settings

_combine_yield at default settings is bit-identical to the previous inline law (verified numerically, diff 0.00e+00) -- δ merely moves from a baked float to a constants[] symbol evaluated to the same number. Power-mean and runtime-δ are entirely opt-in. The distrusted in-solve enable_yield_homotopy ramp driver is intentionally not part of this PR.

Scope

Stage 1 (this PR): base helper + δ-atom + power-mean, wired to the DP and VEP models. Stage 2 (follow-up): the TI-VEP / TI-VEP-Split anisotropic sites (4 sites feeding rank-4 split/lagged tensors), gated by the TI solver tests.

Tests

tests/test_1055_yield_smoother.py: δ=0 exact Min; power-mean undershoot + overflow-safety + ->Min as δ->0; smoother validation/default; runtime δ ramp no-recompile; DP opt-in.

level_1 and tier_a gate green: 402 passed, 0 failed, 0 errors (1 pre-existing unrelated xfail).

Note: 3 test_1052_VEP_stability_regression (level_2) tests are red, but they fail identically on the development baseline without this change (bisected) -- pre-existing, unrelated.

Underworld development team with AI support from Claude Code

…ta constant

Add the power-mean soft-min yield smoother and make the soft-min softness delta a
constants[] atom (runtime-rampable with no JIT recompile) on the ViscousFlowModel base
class, so the visco-plastic subclasses inherit one implementation. This is the
generalisable, scalable substrate for a yield homotopy toward the sharp Min surface.

Base class (ViscousFlowModel):
- _combine_yield(eta_ve, eta_pl): the shared viscous/plastic combination, keyed on
  yield_mode -- "min" (exact hard Min), "harmonic", or "softmin" (the delta soft-min in
  the family chosen by yield_smoother). Development's tri-modal yield_mode semantics are
  preserved exactly (unlike the source branch, which collapsed "softmin" into "min").
- _get_yield_softness / _get_yield_offset: delta and the onset offset held as constants[]
  UWexpression atoms (the offset defined symbolically in terms of delta -- one symbol in
  the stress tensor, so no tensor blow-up -- so one delta update repacks both). Ramping
  delta via the atom + solver._update_constants() forces no recompile.
- yield_smoother property/setter: "sqrt" (default; overshoots tau_y in the transition) or
  "powermean" (undershoots tau_y -- eta_eff <= Min always -- overflow-safe on geodynamic
  viscosity ranges). Selecting "powermean" from delta=0 bumps delta to 1 (s=1 harmonic
  mean), since delta=0 is the singular Min limit.

Models (Stage 1 -- isotropic, test-covered):
- ViscoPlasticFlowModel (Drucker-Prager): defaults to yield_mode="min" == today's exact
  hard Min (zero behaviour change), and GAINS yield_mode / yield_softness knobs so it can
  opt into the softmin / power-mean homotopy -- the model the hard-case DP homotopy needs.
- ViscoElasticPlasticFlowModel (VEP): its inline sqrt soft-min routed through _combine_yield;
  delta moves float -> atom (value-identical); yield_softness setter syncs the atom.

Zero behaviour change at stock settings: _combine_yield at default settings is
bit-identical to the previous inline law (delta merely moves from a baked float to a
constants[] symbol evaluated to the same number). Power-mean and runtime-delta are opt-in.
The distrusted in-solve enable_yield_homotopy ramp driver is intentionally NOT part of
this PR. TI-VEP / TI-VEP-Split (4 anisotropic sites) are a Stage-2 follow-up.

Tests: tests/test_1055_yield_smoother.py -- delta=0 exact Min; power-mean undershoot +
overflow-safety + ->Min; smoother validation/default; runtime delta ramp no-recompile;
DP opt-in. level_1/tier_a gate green (402 passed, 0 failed). VEP _combine_yield verified
bit-identical to the prior float law at defaults.

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings July 22, 2026 01:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@lmoresi

lmoresi commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Closed as fully superseded — audit against current development (698d89a):

  • The power-mean soft-min smoother, δ and onset-offset as rampable constants[] atoms, _combine_yield tri-modal semantics, the yield_smoother property, and tests/test_1055_yield_smoother.py all landed on development (via the Nonlinear solver: automatic warm start, model-advertised yield homotopy, and an inf-safe power-mean yield law #441 line of work), so everything this PR introduced is already merged.
  • Development's power-mean is the inf-safe harmonic-normalised form (constitutive_models.py ~1010-1024, with the inf/inf-at-rigid-points rationale documented inline); this branch still carries the older product-over-sum form that NaNs on a cold start — merging would regress that fix.
  • The remaining lines unique to this branch are pre-refactor remnants development deliberately replaced (old -oo defaults, old Max(yield_stress_min, …) guards superseded by the smooth_max floor, old flux_jacobian docstring superseded by the settable version from fix(constitutive_model): make flux_jacobian settable for custom Jacobian tangents #362).

Nothing of value is lost by closing.

Underworld development team with AI support from Claude Code

@lmoresi lmoresi closed this Jul 28, 2026
@lmoresi
lmoresi deleted the feature/yield-powermean branch July 28, 2026 06:24
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.

2 participants