pub enum Material {
Show 13 variants
Elastic {
e: f64,
},
ElasticPP {
e: f64,
eyp: f64,
ep: f64,
},
Gap {
e: f64,
gap: f64,
},
Ent {
e: f64,
},
Steel01 {Show 15 fields
fy: f64,
e0: f64,
b: f64,
a1: f64,
a2: f64,
a3: f64,
a4: f64,
min_strain: f64,
max_strain: f64,
shift_p: f64,
shift_n: f64,
loading: Steel01Loading,
strain: f64,
stress: f64,
tangent: f64,
},
Concrete01 {
fpc: f64,
epsc0: f64,
fpcu: f64,
epscu: f64,
min_strain: f64,
end_strain: f64,
unload_slope: f64,
strain: f64,
stress: f64,
tangent: f64,
},
Steel02 {Show 20 fields
fy: f64,
e0: f64,
b: f64,
r0: f64,
cr1: f64,
cr2: f64,
a1: f64,
a2: f64,
a3: f64,
a4: f64,
min_strain: f64,
max_strain: f64,
pl_strain: f64,
asymptote_strain: f64,
asymptote_stress: f64,
reversal_strain: f64,
reversal_stress: f64,
kon: Steel02Kon,
strain: f64,
stress: f64,
},
Concrete02 {
fc: f64,
epsc0: f64,
fcu: f64,
epscu: f64,
rat: f64,
ft: f64,
ets: f64,
min_strain: f64,
tension_strain: f64,
strain: f64,
stress: f64,
tangent: f64,
},
Hysteretic(Box<HystereticFields>),
Pinching4(Box<Pinching4Fields>),
Parallel(Vec<(Material, f64)>),
Series {
children: Vec<Material>,
child_strains: Vec<f64>,
stress: f64,
max_iter: usize,
tol: f64,
},
MinMax {
inner: Box<Material>,
min_strain: f64,
max_strain: f64,
failed: bool,
},
}Variants§
Elastic
ElasticPP
Elastic-perfectly-plastic, with real permanent-set tracking via the
committed plastic strain ep — standard 1D return-mapping
plasticity. Construct via Material::elastic_pp, not the struct
literal: ep is internal history, not a material parameter, and
must start at zero.
Gap
One-sided gap: zero stiffness until the strain closes the gap
(strain + gap < 0, i.e. compressive strain past the opening), then
linear elastic. Stateless — a genuine function of current strain
only (no permanent set to track), unlike ElasticPP.
Ent
“No tension”: zero stiffness in tension (strain >= 0), linear
elastic in compression. Equivalent to Gap { e, gap: 0.0 }, kept as
its own variant since OpenSees exposes it separately and it’s the
simplest possible nonlinear material (useful as the base case for
element wiring tests). Stateless, same reasoning as Gap.
Steel01
Bilinear kinematic hardening with isotropic hardening on load
reversal (Filippou 1983), ported from OpenSees’ Steel01. Construct
via Material::steel01.
min_strain/max_strain track the largest excursion ever committed
in each direction (used only to update shift_p/shift_n on a
reversal, so they lag one reversal behind, exactly like OpenSees’
CminStrain/CmaxStrain); shift_p/shift_n are the isotropic
hardening shifts applied to the bounding lines; strain/stress
are the last committed point (needed because the bounding formula
c = Cstress + E0*dStrain references it directly, not just the
“obvious” history fields).
Fields
loading: Steel01LoadingConcrete01
Kent-Scott-Park compression envelope with Karsan-Jirsa degrading
unload/reload and zero tensile strength, ported from OpenSees’
Concrete01. Construct via Material::concrete01 — fpc,
epsc0, fpcu, epscu are normalized negative (compression) at
construction, matching the OpenSees convention.
min_strain is the most negative strain ever committed (drives the
envelope); end_strain is where the current unload/reload line
would cross zero stress (needed by reload’s branch to tell
whether a trial strain is still on that line or must re-enter the
envelope); unload_slope is that line’s slope; strain/stress
are the last committed point (same reason as Steel01 above).
Fields
Steel02
Menegotto-Pinto transition curve with Filippou isotropic hardening,
ported from OpenSees’ Steel02. Unlike Steel01‘s piecewise-linear
bilinear rule, the loading/unloading branches are smooth curved
asymptotes to the elastic and strain-hardening lines (parameters
r0/cr1/cr2 control the transition sharpness). Construct via
Material::steel02 — sigini (OpenSees’ optional initial-stress
offset) is not supported, matching Material::steel01’s scope.
min_strain/max_strain are the peak strain reached on each side so
far (Steel02’s epsmaxP/epsminP — note the reversed initial
values vs. Steel01: Steel02 seeds them to ±fy/e0, not 0.0, so
the very first reversal has a nonzero isotropic-hardening baseline);
pl_strain/asymptote_strain/asymptote_stress are the strain at
the last reversal’s plastic-excursion bound and the strain/stress
where the current curve’s two asymptotes (elastic and
strain-hardening) intersect (Steel02’s epsplP/epss0P/sigs0P);
reversal_strain/reversal_stress are the point of the last load
reversal (epssrP/sigsrP) — the curve’s other anchor. kon
mirrors Steel02’s konP, minus its sigini-only pinned state.
Fields
kon: Steel02KonConcrete02
Concrete01‘s Kent-Scott-Park compression envelope plus linear
tension softening and a stiffer reloading rule, ported from
OpenSees’ Concrete02. Construct via Material::concrete02 —
fc/epsc0/fcu/epscu are normalized negative, same as
Concrete01.
min_strain is the most negative strain ever committed (Concrete02’s
ecminP, same role as Concrete01’s min_strain); tension_strain
is the peak tensile-excursion strain beyond the unload line’s
zero-stress crossing (Concrete02’s deptP — the tension-side
analogue of min_strain, with no Concrete01 equivalent since
Concrete01 carries no tension branch at all).
Fields
Hysteretic(Box<HystereticFields>)
Multi-linear (up to 3 points per side) backbone with pinching,
deformation/energy-based damage, and ductility-degraded unloading
stiffness, ported from OpenSees’ HystereticMaterial. Construct via
Material::hysteretic.
Boxed (HystereticFields bundles ~30 fields — see its own doc
comment) rather than inlined into the enum like every other leaf
variant: Material’s size is its largest variant’s size, and
without boxing this one, every Material — including the huge
majority that are a plain Elastic { e: f64 } — would pay for the
most field-heavy variant’s stack space, everywhere a Material
is stored (Fiber, ZeroLength’s per-DOF array, every composite’s
Vec<Material>). Pinching4 (stage 4’s other material) boxes the
same way, for the same reason.
Pinching4(Box<Pinching4Fields>)
Four-point-per-side backbone with a pinched trilinear unload/reload
path and three independent cyclic-damage rules (stiffness, strength,
and deformation-demand degradation), ported from OpenSees’
Pinching4Material. Construct via Material::pinching4.
The most involved material in this catalog: a genuine 5-state
machine (see Pinching4State) rather than the
positive/negative/interior split every other path-dependent variant
here uses, driven by an explicit strain bracket per state rather
than re-derived thresholds.
Boxed for the same reason Hysteretic is (see above) — this one is
larger still (~60 fields, including four 6-element envelope arrays).
Parallel(Vec<(Material, f64)>)
Composite: every child sees the same strain, stress/tangent are the
factor-weighted sum. Ported from OpenSees’ ParallelMaterial — the
factor defaults to 1.0 (see Material::parallel) but is kept
explicit per OpenSees’ API.
Series
Composite: every child sees the same stress, total strain is the
sum of the children’s individual strains. Not directly invertible
(unlike Parallel), so evaluate runs its own small internal
flexibility-based Newton loop, entirely self-contained within one
call — see the type’s doc for why this
doesn’t violate the trial/commit purity rule. child_strains
is the last converged per-child strain split, kept explicitly
(mirroring OpenSees’ own SeriesMaterial::strain[] array) since not
every leaf material tracks its own committed strain. Construct via
Material::series.
MinMax
Wraps one material with strain bounds: once a committed strain
exits [min_strain, max_strain], failed becomes (and permanently
stays) true — stress reads as 0.0, tangent as 1e-8 * inner.initial_tangent() (not exactly zero, to avoid handing back a
structurally singular row/column — see OpenSees’
MinMaxMaterial::getTangent). Once failed, the inner material’s
state is frozen (no further trial/commit reaches it), matching
OpenSees’ Cfailed short-circuit. Construct via
Material::min_max.
Implementations§
Source§impl Material
impl Material
Sourcepub fn parallel(materials: Vec<Material>) -> Self
pub fn parallel(materials: Vec<Material>) -> Self
Equal-factor (1.0 each) parallel composite. For custom factors,
build the Material::Parallel(Vec<(Material, f64)>) variant
directly.
Sourcepub fn series(children: Vec<Material>) -> Self
pub fn series(children: Vec<Material>) -> Self
Series composite with OpenSees’ default tolerance (1e-10) and a
generous internal iteration cap (30) — since, unlike OpenSees’
SeriesMaterial, evaluate can’t lean on many external Newton
calls to slowly converge a warm-started trial state (see the type’s
doc), the internal loop needs to reach convergence by itself.
pub fn min_max(inner: Material, min_strain: f64, max_strain: f64) -> Self
Source§impl Material
impl Material
Sourcepub fn concrete02(
fc: f64,
epsc0: f64,
fcu: f64,
epscu: f64,
rat: f64,
ft: f64,
ets: f64,
) -> Self
pub fn concrete02( fc: f64, epsc0: f64, fcu: f64, epscu: f64, rat: f64, ft: f64, ets: f64, ) -> Self
fc/epsc0/fcu/epscu are normalized to be negative
(compression), matching OpenSees’ Concrete02 constructor. rat is
the ratio between the unloading slope at epscu and the initial
slope; ft/ets are the tensile strength and tension-softening
modulus.
Source§impl Material
impl Material
Sourcepub fn hysteretic(
mom1p: f64,
rot1p: f64,
mom2p: f64,
rot2p: f64,
mom3p: f64,
rot3p: f64,
mom1n: f64,
rot1n: f64,
mom2n: f64,
rot2n: f64,
mom3n: f64,
rot3n: f64,
pinch_x: f64,
pinch_y: f64,
damfc1: f64,
damfc2: f64,
beta: f64,
) -> Self
pub fn hysteretic( mom1p: f64, rot1p: f64, mom2p: f64, rot2p: f64, mom3p: f64, rot3p: f64, mom1n: f64, rot1n: f64, mom2n: f64, rot2n: f64, mom3n: f64, rot3n: f64, pinch_x: f64, pinch_y: f64, damfc1: f64, damfc2: f64, beta: f64, ) -> Self
The 3-point-per-side backbone constructor (OpenSees also offers a
2-point constructor that derives the midpoint as the average of the
two given points — not ported, since a caller can just pass that
average as mom2p/rot2p/mom2n/rot2n directly).
Debug builds assert the backbone is monotonic and one-to-one
(0 < rot1p < rot2p < rot3p, rot1n < rot2n < rot3n < 0) —
OpenSees hard-exits the process on this same precondition failure,
which isn’t a library-appropriate response here.
Source§impl Material
impl Material
Sourcepub fn pinching4(
stress1p: f64,
strain1p: f64,
stress2p: f64,
strain2p: f64,
stress3p: f64,
strain3p: f64,
stress4p: f64,
strain4p: f64,
stress1n: f64,
strain1n: f64,
stress2n: f64,
strain2n: f64,
stress3n: f64,
strain3n: f64,
stress4n: f64,
strain4n: f64,
r_disp_p: f64,
r_force_p: f64,
u_force_p: f64,
r_disp_n: f64,
r_force_n: f64,
u_force_n: f64,
gamma_k_params: [f64; 4],
gamma_k_limit: f64,
gamma_d_params: [f64; 4],
gamma_d_limit: f64,
gamma_f_params: [f64; 4],
gamma_f_limit: f64,
gamma_e: f64,
dmg_cyc: Pinching4DmgCyc,
) -> Self
pub fn pinching4( stress1p: f64, strain1p: f64, stress2p: f64, strain2p: f64, stress3p: f64, strain3p: f64, stress4p: f64, strain4p: f64, stress1n: f64, strain1n: f64, stress2n: f64, strain2n: f64, stress3n: f64, strain3n: f64, stress4n: f64, strain4n: f64, r_disp_p: f64, r_force_p: f64, u_force_p: f64, r_disp_n: f64, r_force_n: f64, u_force_n: f64, gamma_k_params: [f64; 4], gamma_k_limit: f64, gamma_d_params: [f64; 4], gamma_d_limit: f64, gamma_f_params: [f64; 4], gamma_f_limit: f64, gamma_e: f64, dmg_cyc: Pinching4DmgCyc, ) -> Self
Ported from Pinching4Material‘s full (asymmetric-backbone)
constructor. OpenSees’ second overload — the one that mirrors the
positive backbone onto the negative side and copies
rDispP/rForceP/uForceP across — is not ported, for the same
reason Material::hysteretic skipped its 2-point overload: a caller
can pass the negated values directly.
The four-term damage parameter groups are taken as [f64; 4] arrays
(gammaK1..gammaK4 etc.) rather than 12 separate scalars — a purely
mechanical regrouping of OpenSees’ flat signature that keeps this
under 30 arguments instead of 39.
Debug builds assert the backbone is one-to-one (all positive strains
> 0, all negative strains < 0); OpenSees only prints a warning
and carries on with a nonsensical envelope.
Source§impl Material
impl Material
Sourcepub fn steel02(
fy: f64,
e0: f64,
b: f64,
r0: f64,
cr1: f64,
cr2: f64,
a1: f64,
a2: f64,
a3: f64,
a4: f64,
) -> Self
pub fn steel02( fy: f64, e0: f64, b: f64, r0: f64, cr1: f64, cr2: f64, a1: f64, a2: f64, a3: f64, a4: f64, ) -> Self
sigini (OpenSees’ optional initial-stress offset) is not
supported — see the variant’s doc comment. Ten parameters is
Steel02’s actual OpenSees signature (minus sigini/density),
not something to trim for its own sake.
Source§impl Material
impl Material
Sourcepub fn trial_stress_tangent(&self, strain: f64) -> (f64, f64)
pub fn trial_stress_tangent(&self, strain: f64) -> (f64, f64)
(stress, tangent) for a trial evaluation at strain — read-only,
safe to call any number of times from any Newton iteration. See the
type-level doc comment for why this must never mutate self.
Sourcepub fn commit(&self, strain: f64) -> Material
pub fn commit(&self, strain: f64) -> Material
The new committed Material if strain were accepted as the
converged state. Called once per converged step, by Domain::commit
— see the type-level doc comment.
Sourcepub fn initial_tangent(&self) -> f64
pub fn initial_tangent(&self) -> f64
The tangent modulus at zero history — OpenSees’ getInitialTangent.
Only needed by MinMax (for its post-failure tangent) and the
composites (to propagate it to a wrapping MinMax).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Material
impl RefUnwindSafe for Material
impl Send for Material
impl Sync for Material
impl Unpin for Material
impl UnsafeUnpin for Material
impl UnwindSafe for Material
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T, U> Imply<T> for U
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.