Repository navigation
inclusion and mean_field_composite: dilute, Mori-Tanaka and self-consistent - #131
Conversation
b6b98af to
ed86d1b
Compare
aef4718 to
d159bc3
Compare
|
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. inclusion + mean_field_composite — needs changes
|
ed86d1b to
46c99de
Compare
d159bc3 to
3188477
Compare
|
Rebased on the Eshelby-node refactor of #128:
Still open from the review (not part of the refactor): symmetrising the self-consistent tangent for mixed shapes, the ½ relaxation, dilute's |
46c99de to
cced83c
Compare
3188477 to
a4f0b0a
Compare
cced83c to
7d5a01f
Compare
a4f0b0a to
9c83c8c
Compare
|
Producer/consumer pass: |
7d5a01f to
1a2e21a
Compare
9c83c8c to
2bcebfa
Compare
1a2e21a to
13a8bd0
Compare
2bcebfa to
c88bed0
Compare
13a8bd0 to
f64e188
Compare
5434109 to
7bd385b
Compare
f64e188 to
6528f13
Compare
7bd385b to
c23516a
Compare
6528f13 to
5d53585
Compare
c23516a to
4e04cb7
Compare
5d53585 to
57ada14
Compare
make_report.py is the entry point of reports/numsim_report. Expressions own the document; Raw marks unescaped cells; ReportSummary replaces the index tuples; axis labels show tensor components as symbols. Tests per module in reports/tests (ctest report_script discovers them).
parse_point and parse_columns live in report_json.h; step_record and the step_sink concept in step_record.h, so csv_sink no longer includes the model builder. load_path::at checks its range, include nesting is capped at 16 levels, and the finite-difference step of tangent_error is a driver option (fd_step).
A plain output "iterations", so reports can record the return-map convergence of the material next to the driver's own Newton.
A check with "plot" draws value and expected per case next to its error against the tolerance (relative for relative checks); the separate closed-form figures are gone. Cases take tangent_every (default 1, 0 = never); the standard cases check every fifth step. The J2 reports record solver::iterations and show the return map next to the driver's Newton.
…n_property)
Every small-strain consumer took the strain from the fixed property "strain"
of its source. The composites that follow produce one strain per phase
("strain_matrix", "strain_<phase>"), and the phase materials have to read
those. strain_property (default "strain") names the property next to the
existing strain_source / strain_producer_name, the same way tangent_property
and nu_property do; nothing changes for existing documents.
linear_elasticity, linear_stress, j2_plasticity, drucker_prager_plasticity and
the three state functions; tests wire a material to another's stress under
the new name and check the default and a missing property.
"studies" rerun a case with several step counts; the error of a final quantity against the finest run is fitted with a power of the step size, and errors below ten times the driver tolerance count as exact. Cases take "points" (strain states in order) for non-proportional paths; the load step carries its segment and fraction. The J2 reports show the radial return exact on a proportional path and first order on tension followed by shear.
core/elliptic_integrals.h: R_F, R_C, R_D, R_J by Carlson's duplication algorithm and the complete integrals K, E, so the Eshelby tensors of ellipsoids and the orientation averaging need no Boost. core/elastic_constants.h: K, G, E, nu, lambda conversions, the isotropic stiffness, rotation of rank-2 and rank-4 tensors, rotations from axis and angle and onto a direction.
umat/deformation_gradient_driver.h drives a material point by F under mixed F / P control, Newton on the full nine components with dP/dF; deformation_control names them (21, 31, 32 included). A report whose point has a deformation_gradient_source records F and P with nine components, the Cauchy stress as stress_11..23 and J; tensors in cases may have nine components. Reports for neo_hooke and saint_venant_kirchhoff with exact checks (S = F^-1 P under uniaxial stress, simple shear, volumetric).
core/eshelby.h: sphere in closed form from the projectors; elliptic and circular cylinders along any axis or direction (Mura 11.21); ellipsoids with any semi-axes from Mura's I-integrals through Carlson's R_D, the degenerate pairs (spheroid, sphere) from the sum rules, an infinite axis dispatching to the cylinder. Tests against the closed forms, the limits, uvwmaterial's spheroid formula and the identity S_iikk = (1 + nu)/(1 - nu).
…ses, projectors of the controls, load path accessors
…n tensor, float-safe rotation_to The elliptic integrals come from Boost.Math where they are first used (the Eshelby tensors). rotation() builds [axis]_x as -(epsilon . axis); rotation_to() uses 8 eps of the scalar type instead of 1e-14, which did not compile for float and would have been c > 1 there. [[nodiscard]] on the pure helpers.
…per shape eshelby_sphere, eshelby_cylinder, eshelby_spheroid and eshelby_ellipsoid consume nu_source / nu_property and publish the output "tensor"; the engine orders and re-evaluates them with nu. Two scalar producers feed them: poisson_ratio_from_moduli (K_source, G_source -> value) and isotropic_moduli (tangent_source -> K, G, poisson_ratio through isotropize, rejecting an anisotropic tangent). Composites hold a node through eshelby_tensor_interface (tensor() at the wired nu, tensor(nu) for the self-consistent iterate). core/eshelby.h keeps the closed forms: the integrals come from Boost.Math (ellint_rd), the tensors are assembled on the eigenprojectors, equal axes are detected at sqrt(eps).
core/isotropize.h: K = Pvol::C / Dim, G = Pdev::C / (2 (Dim(Dim+1)/2 - 1)), and the isotropic part built from them. core/lebedev.h with generated tables (tools/extract_lebedev.py from uvwmaterial's rule, precisions 3 to 23, up to 194 points): spherical means and integrals of tensor-valued functions of the direction. eshelby::depolarisation for ellipsoids via Carlson's R_J, the elliptic cylinder in closed form, and the cylinder along a direction.
Phases are materials providing a tangent, with volume fractions; outputs the effective tangent, the stress and the strain concentration tensors (sum c_i A_i = Isym). Report with the closed forms of the three kernels and their ordering. Report generator: derived values resolve in dependency order, independent of the key order.
…ent producer over phases The composite consumes the phases' produced tangents, fractions and Eshelby tensors and produces the effective tangent and the concentrations; the stress is a linear_stress on the tangent. It reaches into no other node: no material_ref, no eshelby(nu), no isotropisation of the matrix. Self-consistent is a graph cycle closed by one local edge: isotropic_moduli on the composite tangent produces nu of the effective medium, the Eshelby nodes read it with nu_edge = local (from nu_initial on the first pass), and one update() is one relaxed Picard step with "residual" as its error. The matrix is a phase with its own Eshelby node, so its shape is no longer a hard-coded sphere. material_point_evaluator closes the fixed point per host call (residual_property, residual_tolerance, max_passes; the report point names them). isotropic_moduli with a non-positive tolerance projects without the isotropy check, which the effective medium needs.
57ada14 to
6520437
Compare
c43505c to
655efa4
Compare
…ls-and-constants # Conflicts: # tests/CMakeLists.txt
…eshelby-tensors # Conflicts: # tests/CMakeLists.txt
…v-depolarisation # Conflicts: # tests/CMakeLists.txt
…/rule-of-mixture # Conflicts: # tests/CMakeLists.txt
# Conflicts: # include/numsim-materials/report/report_json.h # tests/CMakeLists.txt
residual_source, residual_tolerance and max_passes are driver parameters (material_point's defaults) and keys of the report's "point"; the mean-field tangent report uses them for the self-consistent fixed point.
Closes #107, closes #143. Part of the uvwmaterial port (#94); stacked on #130.
mean_field_tangent: dilute, Mori–Tanaka and self-consistent effective stiffness as a tangent producer overphasenodes (#130).matrixandphasesare phases (produced tangent, fraction and Eshelby tensor);kerneldilute | mori_tanaka | self_consistent. Outputstangent,concentration_<phase>for every phase (the matrix included) andresidual; the stress is alinear_stresson the tangent. Dilute: Tᵢ = (I + Sᵢ : Cₘ⁻¹ : (Cᵢ − Cₘ))⁻¹; Mori–Tanaka: Aᵢ = Tᵢ : (cₘ I + Σ cⱼ Tⱼ)⁻¹. The Eshelby tensors come in as properties, so their Poisson's ratio is whatever node produces it (isotropic_moduliof the matrix tangent, or a constant) — the composite reaches into no other node and isotropises nothing.Self-consistent as a graph cycle. Every phase, the matrix included (its own Eshelby node — closes #143), is embedded in the effective medium, whose ν is
isotropic_modulion this node'stangent(tolerance: 0, the projection without the isotropy check). The Eshelby nodes consume that ν over a local edge ("nu_edge": "local", starting fromnu_initial):EdgeKind::Localimposes no ordering, so oneupdate()is one relaxed Picard step (relaxation, default 0.5) on the tangent of the previous pass, andresidual= ‖C_new − C‖/‖C_new‖. The fixed point is run by whoever callsupdate():material_point_evaluatorgetsresidual_property,residual_tolerance,max_passesand repeats the graph update per host call until the residual is below tolerance (report documents:"point": {..., "residual": "scs::residual", "tolerance": 1e-10, "max_passes": 200}).The old version iterated inside the node with
material_refcallseshelby(nu)into the inclusions and a hard-coded sphere for the matrix; both are gone.isotropic_moduliwith a non-positivetoleranceprojects without the check (needed for the effective medium).Tests (
test_mean_field_tangent, 13): a phase republishes sphere, cylinder and spheroid tensors from its node; a phase without a shape is rejected atfinalize(); Mori–Tanaka spheres match the analytic K and G (= Hashin–Shtrikman lower bound) at c = 0.05, 0.3, 0.6 to 1e-10 with zero residual; dilute matches its closed-form K and the Mori–Tanaka limit as c → 0; two phases of one material equal one; voids soften with the exact K; Σ c A = I and thelinear_stressgives C : ε for every kernel; the self-consistent fixed point is symmetric under swapping matrix and inclusion (1e-8) and stiffer than Mori–Tanaka, converges within the pass loop and stays put on another pass; the evaluator closes the fixed point in one call; aligned fibres are transversely isotropic with E_L near Voigt; overfull composites and unknown kernels throw; JSON.Report
docs/materials/mean_field_tangent/report.json: Mori–Tanaka, dilute, self-consistent (its own Eshelby node at ν_eff over the local edge, converged per step through the point'sresidual) and unidirectional on one point, the closed forms as checks.862/862 tests pass (GCC 14, reports on).
JSON input
New material type:
mean_field_tangent. Ajson_modeldocument that loads (theFromJsontest of the PR):{"materials": [ {"type": "external_strain_source", "name": "strain"}, {"type": "constant_scalar", "name": "Km", "value": 3.0}, {"type": "constant_scalar", "name": "Gm", "value": 1.0}, {"type": "constant_scalar", "name": "Ki", "value": 60.0}, {"type": "constant_scalar", "name": "Gi", "value": 30.0}, {"type": "isotropic_tangent", "name": "Cm", "K_source": "Km", "G_source": "Gm"}, {"type": "isotropic_tangent", "name": "Ci", "K_source": "Ki", "G_source": "Gi"}, {"type": "isotropic_moduli", "name": "moduli", "tangent_source": "Cm"}, {"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": "spheres", "tangent_source": "Ci", "fraction_source": "c", "eshelby_source": "sphere"}, {"type": "phase", "name": "matrix", "tangent_source": "Cm", "fraction_source": "cm"}, {"type": "mean_field_tangent", "name": "mf", "matrix": "matrix", "phases": ["spheres"], "kernel": "mori_tanaka"}, {"type": "linear_stress", "name": "composite", "tangent_source": "mf", "strain_source": "strain"} ]}Self-consistent: the matrix phase carries an Eshelby node too, both nodes read ν of the effective medium over a local edge, and the point closes the fixed point:
{"materials": [ {"type": "isotropic_moduli", "name": "moduli_eff", "tangent_source": "mf", "tolerance": 0}, {"type": "eshelby_sphere", "name": "sphere", "nu_source": "moduli_eff", "nu_property": "poisson_ratio", "nu_edge": "local", "nu_initial": 0.35}, {"type": "phase", "name": "spheres", "tangent_source": "Ci", "fraction_source": "c", "eshelby_source": "sphere"}, {"type": "phase", "name": "matrix", "tangent_source": "Cm", "fraction_source": "cm", "eshelby_source": "sphere"}, {"type": "mean_field_tangent", "name": "mf", "matrix": "matrix", "phases": ["spheres"], "kernel": "self_consistent", "relaxation": 0.5}, {"type": "linear_stress", "name": "composite", "tangent_source": "mf", "strain_source": "strain"} ], "point": {"strain_source": "strain", "stress_source": "composite", "tangent_source": "mf", "residual": "mf::residual", "tolerance": 1e-10, "max_passes": 200}}Outputs
tangent,concentration_<phase>(matrix included),residual. Several inclusions: morephaseentries (each with its own Eshelby node) inphases.Update after main (#199–#205)
The report's
"point"now builds the driver's parameters, so this PR carries #210: the drivers takeresidual_source,residual_toleranceandmax_passes(material_point's defaults) and pass them to the material point, and"point"accepts the same keys.docs/materials/mean_field_tangent/report.jsonnow uses"residual_source": "scs::residual", "residual_tolerance": 1e-10instead of"residual"/"tolerance"(which is the driver's Newton tolerance on main). New tests:MaterialPointDriver.PassesTheResidualSettingsToThePoint,DeformationGradientDriver.PassesTheResidualSettingsToThePoint, and the residual keys andmax_passes >= 1intest_report_case.Closes #210.