forked from 1b-agent/fieldcraft-upstream
solver, model, engine: linear buckling steps
Procedure::Buckle {modes, shift}: the step's loads as a linear preload, K_σ from its stresses,
and (K + λ K_σ) φ = 0 by block Lanczos in the K inner product: K⁻¹(−K_σ) on Cholesky without a
shift, the buckling transformation (K + σ K_σ)⁻¹ K on LDLᵀ with one, whose inertia counts the
load factors below σ (Grimes–Lewis–Simon 1994). Lanczos gains an operand and an eigenvalue map
(defaults keep frequency steps bit for bit) and reports converged negative eigenvalues. Results
are frequency results with a `buckling` part; modes display with their load factor.
solve.buckle (in the Static drop-down); Abaqus *BUCKLE, Nastran SOL 105 and LS-DYNA refuse it by
name. Euler columns of hex20 within 0.18 % of Engesser's load.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
9a8ae50bca
commit
1b57e2e672
20 files changed
+511
-27
No files matched your search
@@ -470,8 +470,8 @@ pub static CATALOGUE: &[Capability] = &[
|
||||
"Static",
|
||||
Solve,
|
||||
"Implicit",
|
||||
"Linear static (or coupled temperature–displacement) solve of a step with FieldCraft's own solver; nonlinear static and heat transfer in the drop-down",
|
||||
&["solve.nonlinear", "solve.heat"],
|
||||
"Linear static (or coupled temperature–displacement) solve of a step with FieldCraft's own solver; nonlinear static, buckling and heat transfer in the drop-down",
|
||||
&["solve.nonlinear", "solve.buckle", "solve.heat"],
|
||||
),
|
||||
ready("solve.frequency", "Frequency", Solve, "Implicit", "Natural frequencies and mode shapes of a frequency step"),
|
||||
ready(
|
||||
|
||||
@@ -109,6 +109,7 @@ pub static ALL: &[CommandSpec] = &[
|
||||
solve::STATIC,
|
||||
solve::NONLINEAR,
|
||||
solve::FREQUENCY,
|
||||
solve::BUCKLE,
|
||||
solve::HEAT,
|
||||
solve::EXPLICIT,
|
||||
solve::HISTORY,
|
||||
|
||||
@@ -7,8 +7,8 @@ use fieldcraft_mesh::surface::{BoundarySurface, SurfaceOptions};
|
||||
use fieldcraft_model::FluidDomain;
|
||||
use fieldcraft_parallel as parallel;
|
||||
use fieldcraft_solver::{
|
||||
FrequencyOptions, Limits, Location, MassKind, StaticResult, StepResult as ImplicitResult, solve_frequency, solve_heat, solve_nonlinear,
|
||||
solve_static,
|
||||
FrequencyOptions, Limits, Location, MassKind, StaticResult, StepResult as ImplicitResult, solve_buckle, solve_frequency, solve_heat,
|
||||
solve_nonlinear, solve_static,
|
||||
};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
@@ -60,6 +60,14 @@ pub const FREQUENCY: CommandSpec = CommandSpec {
|
||||
run: run_frequency,
|
||||
};
|
||||
|
||||
pub const BUCKLE: CommandSpec = CommandSpec {
|
||||
id: "solve.buckle",
|
||||
label: "Solve Buckling Step",
|
||||
params: r#"{"step": "Buckle", "max_dofs": 6000000, "max_factor_entries": 400000000, "max_iterations": 3000, "threads": 8} — linear buckling of a buckling step (the only one when `step` is left out): the step's loads as a linear preload, then the lowest load factors λ with (K + λ K_σ) φ = 0 and their mode shapes (largest component 1), or those above the step's shift (whose LDLᵀ factor counts the load factors below it); negative load factors found are reported; the result stays in the session and its modes display like frequency modes; `threads` as for solve.static"#,
|
||||
kind: CommandKind::Model,
|
||||
run: run_buckle,
|
||||
};
|
||||
|
||||
pub const EXPLICIT: CommandSpec = CommandSpec {
|
||||
id: "solve.explicit",
|
||||
label: "Solve Explicit Dynamic Step",
|
||||
@@ -159,6 +167,7 @@ fn run_all(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
Procedure::Static {} | Procedure::CoupledTemperatureDisplacement {} => run_static,
|
||||
Procedure::HeatTransfer { .. } => run_heat,
|
||||
Procedure::Frequency { .. } => run_frequency,
|
||||
Procedure::Buckle { .. } => run_buckle,
|
||||
Procedure::ExplicitDynamic(_) => run_explicit,
|
||||
Procedure::Fluid { .. } => run_fluid,
|
||||
Procedure::NonlinearStatic(_) => run_nonlinear,
|
||||
@@ -292,6 +301,24 @@ fn run_frequency(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(summary)
|
||||
}
|
||||
|
||||
fn run_buckle(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let limits = limits(p)?;
|
||||
let step = opt::<String>(p, "step")?;
|
||||
let model = &s.model;
|
||||
let r = parallel::with_threads(threads(s, p)?, || solve_buckle(model, step.as_deref(), &limits))?;
|
||||
let summary = json!({
|
||||
"step": r.step,
|
||||
"dofs": r.stats.dofs,
|
||||
"equations": r.stats.equations,
|
||||
"lanczos_vectors": r.stats.lanczos_vectors,
|
||||
"modes": r.modes.iter().enumerate().map(|(i, m)| json!({"mode": i + 1, "load_factor": m.eigenvalue})).collect::<Vec<_>>(),
|
||||
"buckling": r.buckling,
|
||||
"warnings": r.warnings,
|
||||
});
|
||||
s.store_result(StepResult::Implicit(ImplicitResult::Frequency(r)));
|
||||
Ok(summary)
|
||||
}
|
||||
|
||||
fn run_explicit(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
use fieldcraft_explicit::Limits as ExplicitLimits;
|
||||
let limits = ExplicitLimits {
|
||||
|
||||
Reference in new issue
Block a user