engine: a free body in explicit dynamics needs no boundary condition in the setup checklist

The drop-test and impact samples have no supports, by design, yet the browser marked Loads &
BCs as the next stage with an Add boundary condition row even after they were solved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 11:53:52 -04:00
1 parent c983987c64
commit 4a5d897782
1 file changed
+21 -1
+21 -1
View File
@@ -131,6 +131,9 @@ impl Session {
// Models without elements (point masses, fluid domains) need no material or section.
let elementless = analysable && m.elements().is_empty();
let modal_only = !m.steps().is_empty() && m.steps().iter().all(|st| matches!(st.procedure, Procedure::Frequency { .. }));
// Transient dynamics may leave a body free and unloaded (a drop, a flight onto a wall: initial
// velocities drive it): no support or load needed.
let dynamic_only = !m.steps().is_empty() && m.steps().iter().all(|st| st.procedure.is_dynamic());
// A model driven by a prescribed displacement or temperature needs no load either.
let driven = m.boundary_conditions().values().any(|bc| bc.drives());
let mut next_given = false;
@@ -142,7 +145,8 @@ impl Session {
let optional = match stage {
Stage::Prepare => true,
Stage::Material | Stage::Section => elementless,
Stage::Loads => modal_only || driven,
Stage::BoundaryConditions => dynamic_only,
Stage::Loads => modal_only || driven || dynamic_only,
_ => false,
};
let command = r.provider();
@@ -282,6 +286,22 @@ mod tests {
assert_eq!(status(&s, Stage::Solve), Next, "{:?}", s.progress());
}
/// A free body in transient dynamics (drop-test: no support, only gravity and the floor)
/// needs no boundary condition, nor a load (impact): the checklist offers the solve next.
#[test]
fn a_free_body_in_explicit_dynamics_needs_no_boundary_condition() {
let mut s = Session::default();
s.execute("file.sample", &json!({"name": "drop-test"})).unwrap();
assert!(s.model.boundary_conditions().is_empty());
assert_eq!(status(&s, Stage::BoundaryConditions), Optional);
assert_eq!(status(&s, Stage::Solve), Next, "{:?}", s.progress());
// impact: no support and no load, only an initial velocity onto a rigid wall.
s.execute("file.sample", &json!({"name": "impact"})).unwrap();
assert!(s.model.loads().is_empty() && s.model.boundary_conditions().is_empty());
assert_eq!((status(&s, Stage::BoundaryConditions), status(&s, Stage::Loads)), (Optional, Optional));
assert_eq!(status(&s, Stage::Solve), Next, "{:?}", s.progress());
}
/// A seed added after meshing marks the mesh out of date, until a remesh (#342).
#[test]
fn a_seed_after_the_mesh_marks_it_outdated() {