Entropyk/_bmad-output/implementation-artifacts/5-5-swappable-calibration-variables-inverse-calibration-one-shot.md

7.2 KiB

Story 5.5: Swappable Calibration Variables (Inverse Calibration One-Shot)

Status: done

Story

As a R&D engineer calibrating a machine model against test bench data, I want to swap calibration coefficients (f_m, f_ua, f_power, etc.) into unknowns and measured values (Tsat, capacity, power) into constraints, so that the solver directly computes the calibration coefficients in one shot without an external optimizer.

Acceptance Criteria

  1. Condenser Calibration

    • Given a Condenser with f_ua as a calibration factor
    • When I enable calibration mode and fix Tsat_cond to a measured value
    • Then f_ua becomes an unknown in the solver state vector
    • And a residual is added: Tsat_cond_computed - Tsat_cond_measured = 0
    • And the solver computes f_ua directly
  2. Evaporator Calibration

    • Given an Evaporator with f_ua as a calibration factor
    • When I enable calibration mode and fix Tsat_evap to a measured value
    • Then same swap mechanism: f_ua → unknown, Tsat_evap → constraint
  3. Compressor Power Calibration

    • Given a Compressor with f_power as a calibration factor
    • When I enable calibration mode and fix Power to a measured value
    • Then f_power becomes an unknown
    • And residual: Power_computed - Power_measured = 0
  4. Compressor Mass Flow Calibration

    • Given a Compressor with f_m as a calibration factor
    • When I enable calibration mode and fix mass flow to a measured value
    • Then f_m becomes an unknown
    • And residual: ṁ_computed - ṁ_measured = 0
  5. System Specific Modes

    • Given a machine in cooling mode calibration, when I impose evaporator cooling capacity Q_evap_measured, then Q_evap becomes a constraint (Q_evap_computed - Q_evap_measured = 0) and corresponding f_ (typically f_ua on evaporator) becomes an unknown.
    • Given a machine in heating mode calibration, when I impose condenser heating capacity Q_cond_measured, then Q_cond becomes a constraint and corresponding f_ (typically f_ua on condenser) becomes an unknown.

Tasks / Subtasks

  • Extend Component implementations to respect f_ calibration variables
    • Update Compressor to apply f_m (mass flow) and f_power (power) factors if provided.
    • Update Heat Exchangers (Condenser, Evaporator) to apply f_ua (heat transfer) factor if provided.
    • Update Pipes/Valves for f_m or f_dp where applicable.
  • Connect BoundedVariable for f_ factors
    • Use BoundedVariable to represent f_m, f_ua, etc. in the System state as control variables with min/max bounds (e.g., 0.5 to 2.0).
    • Allow components to extract their current calibration factors from the SystemState during compute_residuals.
  • Inverse Control Constraint Setup
    • Add ability to cleanly formulate targets like Target Capacity, Target Power, Target Tsat.
    • Test the solver for MIMO (Multi-Input Multi-Output) with these new variables mapping to these targets.
  • Write integration test for Swappable Calibration
    • Create a test with fixed component geometries, imposing a known capacity and power.
    • Check if the solver successfully converges to the required f_ua and f_power to match those targets.

Dev Notes

Architecture Context

This is Story 5.5 in Epic 5: Inverse Control & Optimization. It leverages the MIMO capability built in Story 5.4. Instead of traditional controls like Valve Opening targeting Superheat, this story treats the actual physical calibration parameters (like UA multiplier, mass flow multiplier) as the "Control Variables" and the test bench measurements (Capacity, Power) as the "Constraints".

Critical Numerical Challenge: The components must read from the solver's expanded SystemState (control vector section) to obtain their f_ multipliers instead of using hardcoded internal struct fields. If the multiplier is NOT part of the inverse control problem (regular forward simulation), it should default to 1.0.

Technical Stack Requirements:

  • Rust (edition 2021) with #![deny(warnings)]
  • nalgebra for linear algebra
  • thiserror for error handling
  • tracing for structured logging

Component → Calibration Factor Mapping:

Component f_ Factors Measurable Values (Constraints)
Condenser f_ua, f_dp Tsat_cond, Q_cond (capacity), ΔP_cond
Evaporator f_ua, f_dp Tsat_evap, Q_evap (capacity), ΔP_evap
Compressor f_m, f_power, f_etav ṁ, Power, η_v
Expansion Valve f_m
Pipe f_dp ΔP

Previous Story Intelligence

From Story 5.4 (Multi-Variable Control):

  • MIMO Jacobian calculation using cross-derivatives is fully working and tested.
  • extract_constraint_values_with_controls() accurately maps primary and secondary effects via component IDs using BoundedVariable::with_component().
  • Use BoundedVariable::with_component() to properly associate the calibration factor with the component so that the Jacobian builder can calculate perturbations accurately.

Technical Requirements

Critical Implementation Details:

  1. State Extraction in Components: Components like Condenser must query the SystemState for their specific BoundedVariable (like f_ua) during compute_residuals. If present, multiply the nominal UA by f_ua. If not, assume 1.0.
  2. Bounds definition: Calibration factors should be bounded to physically meaningful ranges (e.g. f_ua between 0.1 and 10.0) to prevent the solver from taking unphysical steps or diverging.
  3. MIMO Stability: Because swapping f_m and f_power simultaneously affects both mass flow and power, the Newton-Raphson solver will rely entirely on the cross-derivatives implemented in Story 5.4. Ensure that the component IDs strictly match between the constraint output extraction and the bounded variable.

Anti-Patterns to Avoid:

  • DON'T force components to store stateful f_ values locally that drift out of sync with the solver. Always compute dynamically from the solver state.
  • DON'T use exact 1.0 equality checks. Since these are floats, if not using a control variable, pass None.
  • DON'T use unwrap() or expect().

Project Structure Notes

  • Changes isolated to crates/components/src/ (modifying components to respect f_ factors)
  • May need minor additions to crates/solver/src/system.rs to allow components to extract their mapped controls.
  • Integration tests go in crates/solver/tests/inverse_calibration.rs.

References

  • [Source: epics.md Story 5.5] Swappable Calibration Variables acceptance criteria.
  • [Source: 5-4-multi-variable-control.md] Multi-Variable MIMO Jacobian and component-id linking logic.
  • [Source: architecture.md#Inverse-Control] Architecture decisions for one-shot inverse solving.

Dev Agent Record

Agent Model Used

z-ai/glm-5:free (Antigravity proxy)

Debug Log References

Completion Notes List

File List

  • crates/components/src/expansion_valve.rs
  • crates/components/src/compressor.rs
  • crates/components/src/heat_exchanger/exchanger.rs
  • crates/solver/tests/inverse_calibration.rs