Skip to main content

Analysis

Struct Analysis 

Source
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>
where NId: Key, E: ElementOps<NDIM, NDOF, NId> + Clone, E::Load: Clone,

Source

pub fn domain(&self) -> &Domain<NDIM, NDOF, NId, E>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.