forked from 1b-agent/fieldcraft-upstream
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
c983987c64
commit
4a5d897782
1 file changed
+21
-1
@@ -131,6 +131,9 @@ impl Session {
|
|||||||
// Models without elements (point masses, fluid domains) need no material or section.
|
// Models without elements (point masses, fluid domains) need no material or section.
|
||||||
let elementless = analysable && m.elements().is_empty();
|
let elementless = analysable && m.elements().is_empty();
|
||||||
let modal_only = !m.steps().is_empty() && m.steps().iter().all(|st| matches!(st.procedure, Procedure::Frequency { .. }));
|
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.
|
// A model driven by a prescribed displacement or temperature needs no load either.
|
||||||
let driven = m.boundary_conditions().values().any(|bc| bc.drives());
|
let driven = m.boundary_conditions().values().any(|bc| bc.drives());
|
||||||
let mut next_given = false;
|
let mut next_given = false;
|
||||||
@@ -142,7 +145,8 @@ impl Session {
|
|||||||
let optional = match stage {
|
let optional = match stage {
|
||||||
Stage::Prepare => true,
|
Stage::Prepare => true,
|
||||||
Stage::Material | Stage::Section => elementless,
|
Stage::Material | Stage::Section => elementless,
|
||||||
Stage::Loads => modal_only || driven,
|
Stage::BoundaryConditions => dynamic_only,
|
||||||
|
Stage::Loads => modal_only || driven || dynamic_only,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
let command = r.provider();
|
let command = r.provider();
|
||||||
@@ -282,6 +286,22 @@ mod tests {
|
|||||||
assert_eq!(status(&s, Stage::Solve), Next, "{:?}", s.progress());
|
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).
|
/// A seed added after meshing marks the mesh out of date, until a remesh (#342).
|
||||||
#[test]
|
#[test]
|
||||||
fn a_seed_after_the_mesh_marks_it_outdated() {
|
fn a_seed_after_the_mesh_marks_it_outdated() {
|
||||||
|
|||||||
Reference in new issue
Block a user