Skip to content

Integration Groups

Test User edited this page May 30, 2026 · 3 revisions

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.

What JEOD does

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.31IG.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).

What astrodyn does

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 FixedUpdate tick = one group advance at the schedule's fixed dt. Every entity matched by an integrating system's query participates by construction.
  • The seven AstrodynSet stages run once per tick, in declaration order (TimeUpdate → EphemerisUpdate → Environment → Interaction → ForceCollection → Integration → DerivedState), mirroring JEOD's init/update pipeline.
  • The shared dt is the Time<Fixed> resource. Time-dilation scenarios scale it via Simulation::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 same cycle_dyndt.

This collapses two JEOD concepts (DynManager orchestration and DynamicsIntegrationGroup membership) into a single Bevy primitive — the schedule.

Multi-stage integrators are an inner loop, not multiple ticks

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.

Multi-body sims need no extra wiring

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.

Escape hatch: separate groups

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.

Cross-references

Clone this wiki locally