Repository navigation
Conversation
The exponential integrator's alpha = exp(-dt/tau) and phi lived once on the DFDt, written by each model's pre-solve hook from its own Maxwell time. Two models sharing one history (the constituents of a multi-material model) therefore both relaxed on whichever Maxwell time was written last: 60 % error in the other material. Each VEP / TI-VEP / TI-VEP-split model now owns its (alpha, phi) (_ExponentialCoefficients), created like the DDt's and refreshed with _update_exp_values from its own Maxwell time, keeping the dt_symbol path for field Maxwell times; the ETD-1 reduction phi = alpha is applied to the model's own pair. Nothing in the library reads the DDt's coefficients any more; they are kept for outside callers of update_exp_coefficients (TODO(DESIGN) at their allocation). Single-material results are bit-identical (velocity, history, sampled stress) for VEP BDF-1/2, ETD-1/2, ETD with a field viscosity, TI-VEP BDF and ETD, and the TI split model. Underworld development team with AI support from Claude Code
… viscosity Before the solver sets a step, dt_elastic is infinite. With a finite modulus, eta mu dt / (c0 eta + mu dt) then evaluates to inf/inf = nan: - ViscoElasticPlasticFlowModel.ve_effective_viscosity guarded mu = inf but not dt = inf; it now returns the viscosity for either. - TransverseIsotropicVEPFlowModel: the same guard in ve_effective_viscosity and in _eta_for_tensor. Its tensor is cached (_is_setup), and a model given its parameters before it meets a solver was built at dt = inf and kept the nan tensor once the step became finite; the dt_elastic setter now resets the model when the step crosses between infinite and finite. Regression tests are in tests/test_1054_multimaterial_viscoelastic.py (next commit). Single-material results with the parameters set after assignment are unchanged bit for bit. Underworld development team with AI support from Claude Code
…stituents MultiMaterialConstitutiveModel took none of the stress-history interface from its constituents: it reported requires_stress_history = False (so the solver made no history), had no Parameters.dt_elastic (the VE solve raised), and never called the constituents' history hooks, so a viscoelastic constituent kept dt_elastic = inf -- nan (BDF) or a purely viscous response (ETD), silently. The composite now forwards: requires_stress_history (any constituent); order (highest) and effective_order (highest: the solver rebuilds when it changes, so it must follow the ramp of the highest-order constituent); stress_history_ddt_kwargs (union; contradictory requests raise); Parameters.dt_elastic (set on every viscoelastic constituent); _update_history_coefficients / _update_history_post_solve; history_flux (level-set sum of each constituent's history_flux or flux, sharing one weighting helper with flux); Parameters._solver and _solver_is_setup, so a constituent's parameter change rebuilds the solver's functions. Mixed integrators and orders are allowed: the history stores the composite stress, which inside each material is its own stress, and each constituent reads it through its own scheme and coefficients (its own ETD alpha, phi since the previous commits). The log-conformation refusal moves into _validate_model_compatibility, which now states what combines. tests/test_1054_multimaterial_viscoelastic.py: pure shear, two materials, closed forms away from the interface -- identical constituents (5.6e-12), two Maxwell times BDF and ETD (5.6e-4, interface smearing of the projected history), BDF-1 beside ETD-1, BDF-2 beside BDF-1, VEP beside TI-VEP, yield in one constituent, a constituent's parameter change between steps; plus the single-material TI-VEP parameters-before-assignment and infinite-step regressions. 15 of 18 fail on the base build; all pass serial and on two ranks. Subsystem doc gains the combination rules. Underworld development team with AI support from Claude Code
Since each viscoelastic model owns its (alpha, phi), nothing in src, tests, examples or notebooks read the DDt's _exp_coeffs, _exp_alpha, _exp_phi or update_exp_coefficients. Remove them, and the with_exp switch of _init_coefficient_expressions; _create_exp_coefficients now names its owner as the constitutive model. EXPONENTIAL_VE_INTEGRATOR.md no longer says the coefficients live on the DDt. (docs/docstrings/review_queue.md still lists them; it is generated by docstring_sweep.py.) Single-material results stay bit-identical to the base build (VEP BDF-1/2, ETD-1/2, ETD with a field viscosity, TI-VEP BDF/ETD, TI split). Underworld development team with AI support from Claude Code
The solver passes its history's order to a model it is given again (constitutive_model.order = self._order). The composite forwarded that to every viscoelastic constituent, so reassigning it, or a VE_Stokes(order=2) or user history, silently turned a BDF-1 constituent into BDF-2 (error against its BDF-1 closed form 3e-4 -> 9.2e-2). The setter now leaves the constituents alone and refuses a history of lower order than a constituent integrates at. Tests (test_1054): - reassigning the composite keeps orders (2, 1) and each closed form; fails with the previous forwarding setter. - the constituent-change test now makes a structural change (a yield stress given to B between steps); the previous viscosity change was a rampable constant that needs no rebuild. Fails with the rebuild forwarding disabled (B [0.976, 1.18] against tau_y = 0.5). - viscous beside VEP, tolerance from the measured 7.9e-3. - the TI parameters-before test names its three controls. constitutive-models.md: the smearing error grows with the stress jump against the local stress; measured cases stated, including three materials in thirds (4.1e-2). Underworld development team with AI support from Claude Code
…' into feature/multimaterial-ve
- The solver sets an explicit history order on a model before assigning it, so a composite whose constituent needs a higher-order history is refused and the solver keeps the model it had (it was left holding the refused one). - With #851's scaled Maxwell time merged in, each constituent's ETD coefficient comes from its own scaled tau when eta, mu and dt carry units (test; the units test from #851 reads alpha from the model, where this branch keeps it). - Stale comments about the history's exponential coefficients removed; the guide states how a composite and a single model take the solver's order. Underworld development team with AI support from Claude Code
Member
Author
Internal adversarial review: two roundsEach round had independent reviewers working against a build of the base (#851). Probes are kept in the session scratchpad. Round 1 (at 45b6d58)
Round 2 (at 83e8b76)
Attacks that failed (round 2)
Interactions
Generated by Claude Code |
This branch has not been deployed
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.
Viscoelastic constituents in
MultiMaterialConstitutiveModel, so a fault material (TI-VEP, or a weak VEP) can sit beside an isotropic VEP bulk under a level set or an index variable. This is item A of the VE/plastic gap closure. Stacked on #851; review and merge #851 first, then this PR retargets todevelopment.What was broken
A composite with any viscoelastic constituent ran without error and gave wrong results:
requires_stress_history,order, the history kwargs,dt_elastic, the pre- and post-solve hooks orhistory_flux. The run was silently viscous or produced NaN.What changed
_ExponentialCoefficientsmixin). Each constituent relaxes on its own Maxwell time. The history's own coefficients are removed; nothing reads them, and snapshots never carried them.orderis the highest order of any constituent. Each constituent keeps its own order, and a history of lower order than a constituent needs is refused.effective_order, the history kwargs (contradictory requests raise),dt_elastic, the hooks, andhistory_flux.constitutive-models.md;EXPONENTIAL_VE_INTEGRATOR.md.A single-material run is bit-identical to the base.
Tests
tests/test_1054_multimaterial_viscoelastic.py(23 tests) uses pure shear with prescribed walls, against closed forms for each material:The errors elsewhere are the projected history smearing the stress jump at the interface, 2e-4 to 8e-3. The tolerances are about three times those values, and the measurements are in the module docstring. On the base, 15 of the first 18 tests fail.
Run:
test_1054serial and np2 (23/23); the VE and constitutive tier a/b subset (test_005*,0017,0019,0070,0610,0857,test_10*): 874 passed. Two failures, both on the base too:test_1079(#848), andtest_0017aftertest_1057(its pluginTensorTransportstays in the family registry, the same order dependence astest_0016).Review
Two internal adversarial review rounds, both posted below. The second found a units bug in the base PR (#851's ETD read parameter magnitudes, not scaled values), which is now fixed there (189aa88) and merged here.
Checklist (UW3 Style Charter)
level_*andtier_*markers (S8).array/mesh.X.coords(S7)Underworld development team with AI support from Claude Code