pub struct Analysis<const NDIM: usize = PLANAR_NDIM, const NDOF: usize = NDF, NId = NodeId, E = Element>where
NId: Key,
E: ElementOps<NDIM, NDOF, NId>,{ /* private fields */ }Expand description
A fully-wired analysis (only buildable via AnalysisBuilder<Ready>::build).
Generic over the same kinematic profile as Domain (see its doc
comment) — Analysis’s step/iteration logic doesn’t care about element
physics either, only about Domain’s generic assembly interface, so one
implementation covers both profiles. Defaults to the planar profile, so
bare Analysis keeps working unchanged; Analysis3 (spatial) is a type
alias below.
Implementations§
Source§impl<const NDIM: usize, const NDOF: usize, NId, E> Analysis<NDIM, NDOF, NId, E>
impl<const NDIM: usize, const NDOF: usize, NId, E> Analysis<NDIM, NDOF, NId, E>
pub fn domain(&self) -> &Domain<NDIM, NDOF, NId, E>
Sourcepub fn into_domain(self) -> Domain<NDIM, NDOF, NId, E>
pub fn into_domain(self) -> Domain<NDIM, NDOF, NId, E>
Ends this phase and hands back the Domain (nodal state, committed
material history, load-pattern freeze state, all intact) so a
caller can compose the next phase — a fresh AnalysisBuilder::build
(a different Integrator/Algorithm/ConvergenceTest allowed) or
TransientAnalysis::new for a dynamic phase. Typically preceded by
domain_mut().hold_pattern_constant(pattern, load_factor) on
whichever pattern(s) should stop ramping (e.g. gravity) before the
next phase starts.
Sourcepub fn domain_mut(&mut self) -> &mut Domain<NDIM, NDOF, NId, E>
pub fn domain_mut(&mut self) -> &mut Domain<NDIM, NDOF, NId, E>
Mutable access to the domain mid-analysis — needed to call
Domain::hold_pattern_constant right before into_domain() (the
pattern must be frozen while self.load_factor, the pseudo-time to
freeze at, is still known).
Granting mutable access discards arc-length continuation history and cached factorizations: the caller may change loads or the model, so the next arc step re-validates equilibrium and load sensitivity.
Sourcepub fn set_integrator(&mut self, integrator: Integrator<NId>)where
NId: PartialEq,
pub fn set_integrator(&mut self, integrator: Integrator<NId>)where
NId: PartialEq,
Swap the integrator without rebuilding Analysis — no
Domain::number_dofs, no new SparseSolver, step_count/
load_factor carry over unchanged. This is what makes a cyclic/
quasi-static protocol (many small DisplacementControl legs with
varying sign/magnitude) cheap: build one Analysis, then loop
analysis.set_integrator(Integrator::DisplacementControl { increment: next, .. }); analysis.step()?;
over the protocol’s prescribed excursions — the protocol itself
(a Vec<f64> of signed increments) is caller-side data, not
something Analysis needs to model. For a bigger phase transition
(e.g. gravity → pushover, where Algorithm/ConvergenceTest also
typically change and a pattern needs freezing), use
into_domain() + a fresh AnalysisBuilder instead.
Arc-length continuation history survives only a switch between two
ArcLength configurations with the same path definition (scales,
direction, seed, predictor) — e.g. new radius bounds or stop
criteria. Anything else starts the next arc step afresh.
Sourcepub fn step(&mut self) -> Result<StepResult, AnalysisError>
pub fn step(&mut self) -> Result<StepResult, AnalysisError>
Advance one step: the integrator predicts this step’s load factor, then the algorithm resolves equilibrium at that (fixed) load factor.
On failure, the domain (nodal displacement — mutated eagerly every
Newton iteration, which is correct Newton behavior, but shouldn’t
be left half-applied if the step as a whole doesn’t converge) is
restored to its state before this call. Materials never need this:
see Material’s doc comment for why they’re never mutated until
Domain::commit, which only runs on the success path below.
Sourcepub fn step_prescribed(
&mut self,
targets: &[(NId, usize, f64)],
) -> Result<StepResult, AnalysisError>
pub fn step_prescribed( &mut self, targets: &[(NId, usize, f64)], ) -> Result<StepResult, AnalysisError>
step, after first imposing (node, dof, value) displacements on
fixed DOFs (non-homogeneous single-point constraints, see
Domain::prescribe_displacement): the free DOFs then equilibrate
against the displaced supports at this step’s load factor. Pair it
with Integrator::LoadControl { increment: 0.0 } for a pure
prescribed-displacement step that needs no reference load and no
tangent at the imposed DOF — unlike DisplacementControl, it is
well-defined on a zero-tangent branch. Read the force back with
Domain::reaction.
Targets are validated before anything changes: an unfixed DOF or
nonfinite value is InvalidConstraint and leaves the analysis
untouched. Once validated, the update is atomic with the step — on
failure the imposed displacements are rolled back along with the
rest of the domain, so the last committed state stays intact for a
retry. Arc-length continuation has no meaningful prescribed-value
step and rejects any targets.
Auto Trait Implementations§
impl<const NDIM: usize = PLANAR_NDIM, const NDOF: usize = NDF, NId = NodeId, E = Element> !Freeze for Analysis<NDIM, NDOF, NId, E>
impl<const NDIM: usize, const NDOF: usize, NId, E> RefUnwindSafe for Analysis<NDIM, NDOF, NId, E>where
NId: RefUnwindSafe,
E: RefUnwindSafe,
<E as ElementOps<NDIM, NDOF, NId>>::Id: RefUnwindSafe,
<E as ElementOps<NDIM, NDOF, NId>>::Load: RefUnwindSafe,
impl<const NDIM: usize, const NDOF: usize, NId, E> Send for Analysis<NDIM, NDOF, NId, E>where
NId: Send,
E: Send,
<E as ElementOps<NDIM, NDOF, NId>>::Id: Send,
<E as ElementOps<NDIM, NDOF, NId>>::Load: Send,
impl<const NDIM: usize, const NDOF: usize, NId, E> Sync for Analysis<NDIM, NDOF, NId, E>where
NId: Sync,
E: Sync,
<E as ElementOps<NDIM, NDOF, NId>>::Id: Sync,
<E as ElementOps<NDIM, NDOF, NId>>::Load: Sync,
impl<const NDIM: usize, const NDOF: usize, NId, E> Unpin for Analysis<NDIM, NDOF, NId, E>where
NId: Unpin,
E: Unpin,
<E as ElementOps<NDIM, NDOF, NId>>::Id: Unpin,
<E as ElementOps<NDIM, NDOF, NId>>::Load: Unpin,
impl<const NDIM: usize, const NDOF: usize, NId, E> UnsafeUnpin for Analysis<NDIM, NDOF, NId, E>where
NId: UnsafeUnpin,
impl<const NDIM: usize, const NDOF: usize, NId, E> UnwindSafe for Analysis<NDIM, NDOF, NId, E>where
NId: UnwindSafe,
E: UnwindSafe,
<E as ElementOps<NDIM, NDOF, NId>>::Id: UnwindSafe,
<E as ElementOps<NDIM, NDOF, NId>>::Load: UnwindSafe,
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
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.