Repository navigation
Conversation
…aling (#758) UWexpression.__add__ summed the two operands' values eagerly whenever the left one was not a bare quantity, and a quantity's value is its dimensional magnitude: the quantity entered a non-dimensional sum unscaled. smooth_max(a, b, 0) = (a + b + |a - b|)/2 hit it in its a + b term, so a yield-stress floor of 0.35 MPa compiled as 0.175 or 175000 instead of 0.0221 (in the issue's model, a floor 83x below the yield stress stopped yielding entirely). The same eager arithmetic sat in UWexpression + UWQuantity, UWexpression.__rsub__ and UWQuantity.__sub__(UWexpression). The sums are now symbolic unless both operands are quantities (Pint adds those exactly), so each term is non-dimensionalised by its own units; _quantity_as_expression wraps a bare quantity as its own atom (the block __sub__ already had). evaluate() and the compiled kernels share the path, so both are fixed. Test: test_1059_yield_stress_min_units -- five spellings of the same floor (unset, plain float, quantity in Pa, in MPa, product with a dimensional cohesion), inert and active, against the closed form eta = max(tau_y, tau_min)/(2R); and the sum itself, both orders. 7 of 10 fail on development; all pass here. Underworld development team with AI support from Claude Code
…er bump (#782) #759: a yield stress that reads a field (Drucker-Prager through the pressure, a cohesion weakening with damage) floored at the zero default gives eta_pl = tau_y/(2 edot_II) = 0 wherever it is cut off in tension, a singular operator. The viscoelastic-plastic, viscoplastic and transversely isotropic models now refuse it until yield_stress_min, the residual strength, is stated (> 0, in stress units), or set to -oo for a yield stress positive by construction (maintainer ruling 2026-10-18). Tests whose yield stress is positive by construction take the opt-out; the tension and tension-cutoff tests state a residual strength. #782: selecting yield_smoother="powermean" bumped a zero yield_softness to 1.0 -- the harmonic mean, a distinct law -- without a word. A family switch now leaves the stated softness alone (delta = 0 is s = 1000, near the exact Min); the tests that pinned the bump now pin its absence. Regression tests fail on development and pass here: test_1057::test_a_field_dependent_yield_needs_a_residual_strength, test_1055::test_dp_model_smoother_optin. Underworld development team with AI support from Claude Code
… needs (#759) Nine examples and pages set a yield stress that reads a field with the floor at the zero default; each now states yield_stress_min -- a residual strength where the yield can reach zero, -sympy.oo with the reason where it is positive by construction (fault-network damage_yield / band_yield, the influence-function fault yields). Ex_Shear_Band_Plasticity_SS misspelled the floor as yield_min (it could not have run); restored as yield_stress_min = C. The plasticity guide's opening snippet and floors section state the rule. Underworld development team with AI support from Claude Code
- test_1059's no-floor control read a field with the zero default and tripped #759 on its own branch: it now states -oo; one level marker. - The residual-strength check refuses any floor that is not positive (a negative floor leaves the same singular corner), and names the model, its material and the fields the yield stress reads. - test_1057: the stated strength is checked against its closed form in tension (eta = tau_res / (2 edot_II)); a negative floor is refused. - test_0106 (new): a sum of two expressions stays live -- changing one operand rescales a Poisson solve exactly. The eager sum #758 removes also froze the operand's value into the kernel (fails on development). - fault_network docstring examples and the nonlinear-solver trap list state the rule; the split TI model's lagged estimate gets a TODO(BUG) (it reads the unfloored yield stress). Underworld development team with AI support from Claude Code
Second review round: a floor of uw.expression(..., -oo) was refused with a message asking for -oo, and before this branch evaluated to NaN as a floor. _floor_is_off reads -oo bare or wrapped, at the check and at every site that applies the floor (VP, VEP, TI-VEP, the rate-strengthening probe). The message prints the floor as given and the variables by name; a floor that is itself a field expression is documented as trusted. Underworld development team with AI support from Claude Code
|
Internal adversarial review — two rounds, probes against a build without the branch. Round 1:
Round 2 (no blockers): a wrapped Attacks that failed: 25 arithmetic combinations × units / no-units models all unwrap correctly (a units-model Left: in a model without reference scales, mixed-unit sums still add magnitudes (29.1 MPa + 350 kPa unwraps to 379.1 on both builds) — predates the branch, separate from #758. Generated by Claude Code |
Three yield-law defects, each with the regression test that fails on development.
#758: a dimensional constant in a sum entered unscaled.
UWexpression.__add__(andUWexpression + UWQuantity,__rsub__,UWQuantity.__sub__(UWexpression)) summed operand values eagerly; a quantity's value is its dimensional magnitude, so it entered a non-dimensional sum unscaled.smooth_max(a, b, 0) = (a + b + |a - b|)/2hit it ina + b: a 0.35 MPa yield-stress floor compiled as 0.175 or 175000 instead of 0.0221 (in the issue's model a floor 83x below the yield stress stopped yielding). The sums are now symbolic unless both operands are quantities, so each term is non-dimensionalised by its own units. The same eager sum also froze an operand's value into the compiled kernel: changingaina + bafter the first solve changed nothing (test_0106).#759: a tension cut-off at zero gave a singular operator. A yield stress that reads a field (Drucker-Prager through the pressure, a cohesion weakening with damage) floored at the zero default gives
eta_pl = tau_y/(2 edot_II) = 0wherever it is cut off. Per the maintainer ruling (2026-10-18), the VP, VEP and TI-VEP models now refuse it until the residual strengthyield_stress_min > 0is stated;-sympy.oo(bare or wrapped) is the opt-out for a yield stress positive by construction. The message names the model, its material and the fields read. Tests and examples whose yield stress reads a field now state a floor or the opt-out (15 tests, 9 docs/examples;Ex_Shear_Band_Plasticity_SSalso had the floor misspelledyield_min, silently ignored).#782: selecting
yield_smoother="powermean"bumped a zero softness to 1.0, the harmonic mean, without a word. A family switch now leaves the stated softness alone; at delta = 0 the power mean runs at s = 1000, close to the exact Min. This is not the issue's preferred option (raise): a zero softness with the power mean is a legitimate, deliberate setting (test_1059_yield_anchoruses it), so the defect was only the silent change.#776 is already fixed on development (VP and VEP started from rest converge: VP in 31 iterations, VEP in 3); not changed here.
Tests:
test_1059_yield_stress_min_units(five spellings of one floor against the closed form eta = max(tau_y, tau_min)/(2R), inert and active; 7 of 10 fail on development),test_0106_a_sum_of_expressions_stays_live(fails on development: error 0.12 against 7e-10),test_1057::test_a_field_dependent_yield_needs_a_residual_strength(refusal, negative floor, closed form in tension, both opt-out spellings),test_1055::test_dp_model_smoother_optin. Tier A/B levels 1-2: 2621 passed; the one failure,test_1079_diffusion_disk_restart, fails on development too (#848).Internal adversarial review, two rounds (findings in the comment below).
Closes #758
Closes #759
Closes #782
Checklist (UW3 Style Charter — docs/developer/UW3_STYLE_CHARTER.md)
level_*andtier_*markers (S8)maybe_/try_/do_) and no commented-out code (S3, S4).array/mesh.X.coords— nowith ....access(...), nomesh.data(S7)pixi.toml/pixi.lockor other dependency changes riding in an unrelated PRUnderworld development team with AI support from Claude Code