-
Notifications
You must be signed in to change notification settings - Fork 0
Integration Groups
How astrodyn maps JEOD's JeodIntegrationGroup concept onto Bevy's
schedule mechanics. Closes the documentation gap raised in
Audit-Findings B2.3 / UTL.10
and tracked as issue #210.
This page is the strategic explainer. The code-level surface lives in
the astrodyn_bevy::sets module rustdoc;
treat that as the source of truth for the API.
JeodIntegrationGroup (in models/utils/integration/) is a coordination
boundary. It collects a set of bodies that advance together under a
single shared cycle_dyndt, with one integrator stage that consumes the
group's force/torque accumulators and produces the next state for every
member. DynamicsIntegrationGroup (in models/dynamics/dyn_manager/)
is the JEOD-level subclass that adds the dyn-body-specific
prepare_for_integ_loop() / gravitation() / integrate_bodies()
sequencing.
A simulation can in principle hold multiple groups, each with its own
time_scale_factor and integrator constructor. JEOD's DynManager
orchestrates them; in practice every shipped JEOD scenario uses a single
group.
The relevant invariants are catalogued in
docs/JEOD_invariants.md:
IN.32 (the per-step IntegrableObject protocol), IG.31–IG.33
(integration-group invariants — note IG.33's "no runtime
integration-group membership" entry, which is exactly the Bevy
divergence captured below), and DM.04 (system-set ordering mirrors
JEOD's init/update pipeline).
The Bevy FixedUpdate schedule is the integration group. There is
no runtime "group" object, no membership registry, no cycle_dyndt
field on a group struct. Instead:
- One
FixedUpdatetick = one group advance at the schedule's fixeddt. Every entity matched by an integrating system's query participates by construction. - The seven
AstrodynSetstages run once per tick, in declaration order (TimeUpdate → EphemerisUpdate → Environment → Interaction → ForceCollection → Integration → DerivedState), mirroring JEOD's init/update pipeline. - The shared
dtis theTime<Fixed>resource. Time-dilation scenarios scale it viaSimulation::time_scale_factor; the same factor applies to every body in the schedule, matching JEOD's behaviour where every body in a group sees the samecycle_dyndt.
This collapses two JEOD concepts (DynManager orchestration and
DynamicsIntegrationGroup membership) into a single Bevy primitive —
the schedule.
A common point of confusion: a 4-stage RK4 does not run as four
FixedUpdate passes. The multi-stage loop is internal to
AstrodynSet::Integration
— the integration system steps through all four sub-stages for the same
outer tick before returning. Force/derivative re-evaluation between
stages happens inside that one system's body.
This matches JEOD: in DynamicsIntegrationGroup::integrate_bodies(),
the stage loop is a method call, not a schedule reentry.
Apollo (multi-stage launch), Earth–Moon (Clementine), and any other
multi-body scenario simply spawn every body as an ECS entity. The
integrating system's query catches them all; they all advance under the
same shared dt. There is no "register the body with the integration
group" call to remember.
This is the single biggest convenience win over JEOD's runtime model and
is the reason IG.33 is annotated n/a in the invariants catalogue:
there is no membership state to keep consistent.
A future scenario that legitimately needs separate groups — different bodies integrating at different cadences (e.g. a slow outer dynamics loop + a fast guidance/control loop) — can register a second Bevy schedule with its own tick rate and route the relevant systems and queries to it. This is plain Bevy mechanics; nothing JEOD-specific needs to change.
No current scenario in this workspace uses it. The single-FixedUpdate
model covers every shipped sim. If the need arises, prior art exists in
the broader Bevy ecosystem (custom schedules driven by their own time
resources); the JEOD pipeline maps to whichever schedule the systems
register on.
- Code-level rustdoc:
astrodyn_bevy::sets— module-level "Schedule as integration group" section, plusAstrodynPluginrustdoc for the user-facing entry point. - JEOD source:
models/utils/integration/include/jeod_integration_group.hh,models/dynamics/dyn_manager/include/dynamics_integration_group.hh. - Invariants:
docs/JEOD_invariants.mdrowsIN.32,IG.31–IG.33,DM.04. - Pipeline context: Strategy §4 Pipeline Stages
(engine-neutral stage order) and
Bevy-Adapter § Execution schedule
(the
FixedUpdateschedule and multi-stage integration mechanics).