Skip to content

Theoretical Reference: Monoidal Forces Architecture

1. Philosophical Grounding

In classical mechanics, the principle of superposition states that the net force on an object is the vector sum of all individual forces. This physical law directly maps to the algebraic structure of a Monoid.

A Monoid for Forces requires:

  1. Binary Operation (Combine): An associative operation to sum two force/torque patches.
  2. Identity Element (Neutral): A "Zero Force" state where adding it to any force $F$ results in $F$.

By treating Forces as a Monoid, we align our software architecture with the underlying physics, enabling safer parallelization and better extensibility.

2. The Algebraic Structure

Identity ($\epsilon$)

Defined as Forces::zero(), where all vector components are zero and all scalar rates (mass flux) are zero.

Combination ($\oplus$)

For any two force patches $F_1$ and $F_2$: $$ F_{total} = F_1 \oplus F_2 $$ Implemented via operator+, which performs element-wise addition of forces, moments, gravity vectors, and mass flow rates.

3. Implementation Strategy (The 3-Layer Lift)

Layer 1: Monoid Definition

The Forces struct is upgraded from a simple data container to a Monoid by implementing operator+ and operator+=.

Layer 2: Functional Lifting

Since different physics kernels return different specialized types (e.g., ThrustAndMassFlux, ForceAndTorque), we use "Lift" functions to convert these into a unified Forces patch.

  • Thrust Lift: Maps thrust vector and mass flux to a Forces object.
  • Aero Lift: Maps aerodynamic force and moment to a Forces object.
  • Gravity Lift: Maps gravity acceleration to the gravity_lic field.

Layer 3: Monoidal Composition (mconcat)

The PhysicalRegistry utilizes an mconcat pattern to aggregate all force sources. This replaces nested lambda chains with a declarative list.

cpp
auto pipeline = mconcat_forces({
    lift_thrust(engine_effects),
    lift_aero(dyn_in),
    lift_gravity()
});

4. Design Benefits

a. Open-Closed Principle

Adding a new force source (e.g., Solar Radiation Pressure, Magnetic Torquers) no longer requires modifying the orchestration logic in PhysicalRegistry.cpp. One simply writes a new kernel and adds its "lifted" version to the mconcat list.

b. Parallelization via Associativity

Because Monoid addition is associative, the computation of force patches can be executed in parallel within a single Body's update cycle. The final result is guaranteed to be identical regardless of the calculation order, provided the kernels are side-effect free relative to the RocketBody state.

c. Mathematical Verifiability

The correctness of the force accumulation can be verified using algebraic properties (Identity law, Associativity law) in unit tests, independent of the actual physics values.

5. Constraints and Considerations

  1. Side Effects: Kernels must not modify the RocketBody state during the calculation phase to ensure parallel safety.
  2. State Synchronization: Non-monoidal results (like individual engine operational states) must be handled through a secondary channel or a product monoid if order-dependency is required.
  3. Coordinate Rigor: All patches must be expressed in the same reference frame (usually the Body frame for forces/moments and the LIC frame for gravity) before being combined.