Infer the layout instead of passing it as a value #23

Closed
opened 2026-09-30 12:48:49 -04:00 by connor · 1 comment
Owner

Propagation::new(epoch, Orbit, y0, &forces) takes the layout marker as an argument so that L can be inferred. It works but reads oddly.

The dynamics list cannot supply it: a spec is deliberately layout-free so one spec serves every layout. The initial state gives D but not L, since layouts can share a dimension.

Proposed: a State<T, D, L> wrapping the vector with its layout, built by a provided method on Layout, so the layout is named once where it belongs:

let y0 = Orbit.zeros().with_position(r).with_velocity(v);
Propagation::new(epoch, y0, &forces)

with_position requires L: HasPosition<D>, so a layout without one is a compile error. Also removes the positional Vector6::new(x, y, z, vx, vy, vz) constructor, which is a silent-bug shape. This is where Spacecraft (#7) plugs in later.

`Propagation::new(epoch, Orbit, y0, &forces)` takes the layout marker as an argument so that `L` can be inferred. It works but reads oddly. The dynamics list cannot supply it: a spec is deliberately layout-free so one spec serves every layout. The initial state gives `D` but not `L`, since layouts can share a dimension. Proposed: a `State<T, D, L>` wrapping the vector with its layout, built by a provided method on `Layout`, so the layout is named once where it belongs: let y0 = Orbit.zeros().with_position(r).with_velocity(v); Propagation::new(epoch, y0, &forces) `with_position` requires `L: HasPosition<D>`, so a layout without one is a compile error. Also removes the positional `Vector6::new(x, y, z, vx, vy, vz)` constructor, which is a silent-bug shape. This is where `Spacecraft` (#7) plugs in later.
connor added this to the M1 milestone 2026-09-30 12:48:49 -04:00
connor added the size/M label 2026-09-30 12:48:49 -04:00
Author
Owner

Done in 77a1539. State<T, D, L> carries its layout. Each capability trait has a with_ method that starts a state, so a script chains from the component it has rather than opening with zeros().

DynamicsModel::contribution takes a State for the same reason, which also lets a model read components by name.

A macro-generated positional constructor (Full::state(r, v, sigma, omega, m, e)) was considered and rejected: four consecutive Vector3 positionals make swapping sigma and omega a silent bug, which is what the typed state was for. Could be added alongside later if per-layout completeness is wanted.

Done in 77a1539. `State<T, D, L>` carries its layout. Each capability trait has a `with_` method that starts a state, so a script chains from the component it has rather than opening with `zeros()`. `DynamicsModel::contribution` takes a `State` for the same reason, which also lets a model read components by name. A macro-generated positional constructor (`Full::state(r, v, sigma, omega, m, e)`) was considered and rejected: four consecutive `Vector3` positionals make swapping sigma and omega a silent bug, which is what the typed state was for. Could be added alongside later if per-layout completeness is wanted.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: connor/astrokit#23