solver, model: imperfections from buckling modes in nonlinear steps

NonlinearStatic.imperfection {step, mode, scale}: the buckling step's mode, scaled to a largest
component of `scale`, is added to the node coordinates before the step is solved, with a warning
naming it; Abaqus and LS-DYNA decks refuse it by name. A clamped–free column with its first mode
as imperfection under half its buckling load amplifies it by 1/(1 − α) within 2.8 %.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-14 13:30:59 -04:00
1 parent 788edbbddd
commit 0bb1c2462f
7 files changed
+119 -6

No files matched your search

+1 -1
View File
@@ -67,7 +67,7 @@ pub use mesh::{
pub use sections::{BeamProfile, Extent, Formulation, Integration, Section, SectionKind};
pub use sets::Set;
pub use steps::{
BulkViscosity, ExplicitDynamic, Hourglass, HourglassKind, InitialVelocity, MAX_LOAD_PATH_POINTS, MAX_NONLINEAR_INCREMENTS,
BulkViscosity, ExplicitDynamic, Hourglass, HourglassKind, Imperfection, InitialVelocity, MAX_LOAD_PATH_POINTS, MAX_NONLINEAR_INCREMENTS,
MAX_NONLINEAR_ITERATIONS, NonlinearStatic, OutputVariable, Procedure, RigidWall, Step, StressRate, Tolerances, Transient,
};
pub use units::UnitSystem;
+21
View File
@@ -145,6 +145,20 @@ pub struct NonlinearStatic {
/// them (cyclic loading). Increments end at every point of the path.
#[serde(skip_serializing_if = "Option::is_none")]
pub load_path: Option<Vec<[f64; 2]>>,
/// A geometric imperfection: the mode shape of a buckling step, scaled, added to the node
/// coordinates before this step is solved (the step and its results are on that geometry).
#[serde(skip_serializing_if = "Option::is_none")]
pub imperfection: Option<Imperfection>,
}
/// Mode `mode` (from 1) of buckling step `step`, scaled so its largest component is `scale`
/// (a length), as an initial imperfection.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Imperfection {
pub step: String,
pub mode: u32,
pub scale: f64,
}
/// Most points of a nonlinear step's load path.
@@ -181,6 +195,7 @@ impl Default for NonlinearStatic {
tolerances: Tolerances::default(),
line_search: false,
load_path: None,
imperfection: None,
}
}
}
@@ -190,6 +205,12 @@ impl NonlinearStatic {
let fraction = |what: &str, v: f64| {
if v > 0.0 && v <= 1.0 { Ok(v) } else { Err(Error::Invalid(format!("the {what} is a fraction of the step in (0, 1], got {v}"))) }
};
if let Some(imp) = &self.imperfection {
if !(1..=MAX_MODES).contains(&imp.mode) {
return Err(Error::Invalid(format!("an imperfection takes mode 1 to {MAX_MODES}, got {}", imp.mode)));
}
finite("imperfection scale", imp.scale)?;
}
let initial = fraction("initial increment", self.initial_increment)?;
let min = fraction("minimum increment", self.min_increment)?;
let max = fraction("maximum increment", self.max_increment)?;