PWR-HYBRID-3/claude_memory/2026-04-16-controllers-roughout.md
Dane Sabo cebf8c167a Initial umbrella repo: thesis + FRET pipeline + plant model with first controllers
Folds three previously-separate pieces into one preliminary-example repo
for the HAHACS thesis:

- thesis/ (submodule) → gitea Thesis.git — the PhD proposal
- fret-pipeline/ — FRET requirements to AIGER controller (was
  ~/Documents/fret_processing/; prior single-commit history abandoned
  per user decision)
- plant-model/ — 10-state PKE + lumped T/H PWR model (was
  ~/Documents/PKE_Playground/; never version-controlled before)
- presentations/2026DICE/ (submodule) → gitea 2026DICE.git
- reachability/, hardware/ — empty placeholders for Thrust 3 and HIL
- docs/architecture.md — how the discrete and continuous layers compose
- claude_memory/ — session notes and scratch knowledge pattern

Plant model refactored to thesis naming (x, plant, u, ref); pke_th_rhs
now takes u as an explicit arg instead of reading rho_ext from the
params struct. First two controllers built to the contract
u = ctrl_<mode>(t, x, plant, ref): ctrl_null (baseline) and
ctrl_operation (stabilizing, proportional on T_avg). Validated under a
100% -> 80% Q_sg step: ctrl_operation reduces steady-state T_avg drift
~47% vs. the unforced plant.

Root CLAUDE.md emphasizes that CLAUDE.md files are living documents and
that any knowledge not captured before a session ends is lost forever;
claude_memory/ holds the session-level notes that haven't stabilized
enough to graduate into a CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 16:24:11 -04:00

4.9 KiB
Raw Permalink Blame History

2026-04-16 — controllers scaffold and ctrl_operation rough-out

First continuous controller. Established the controller contract, refactored the plant to thesis naming, and got a closed-loop sim running end-to-end with a meaningful comparison against the unforced baseline.

Naming convention (locked in)

Thesis-aligned. Applied to plant and controllers:

  • t — time
  • x — continuous state vector [n; C1..C6; T_f; T_c; T_cold]
  • plant — params struct (was p; renamed to avoid collision with p_i predicates from the thesis)
  • u — control input: external rod reactivity (scalar, dk/k)
  • ref — reference/setpoint struct (e.g. ref.T_avg)
  • Q_sg — bounded disturbance (SG heat removal, W), a function handle of time

Captured in plant-model/CLAUDE.md under "Naming convention" — any future file in plant-model/ or controllers/ uses these names.

Controller contract

u = ctrl_<mode>(t, x, plant, ref)

Pure function. Returns scalar u. All four args required even if unused (so pke_solver can swap controllers by function handle without branching).

Plant refactor

Four files touched. Non-cosmetic changes:

  • pke_th_rhs.m now takes u as an explicit argument instead of reading p.rho_ext(t) from the params struct. This decouples plant from controller and matches the thesis's f(x, u) form. Old rho_ext field on the params struct is gone.
  • pke_solver.m signature changed: [t, X, U] = pke_solver(plant, Q_sg, ctrl_fn, ref, tspan). Returns U (the control trajectory), reconstructed post-hoc by re-evaluating ctrl_fn at each returned time step.
  • plot_pke_results.m takes (t, X, U, plant, Q_sg, title) — reactivity panel now shows u, feedback, and total separately rather than relying on a p.rho_ext handle.
  • pke_initial_conditions.m trivial rename p → plant, output x0.

ctrl_operation

Proportional-only for now. Kp = 1e-4 /K, chosen to roughly double the effective moderator coefficient (alpha_c ≈ -1e-4 /K). Not tuned for precision — this is rough-out. PI upgrade would require augmenting state with integral error; deferred until we actually need tighter tracking.

Validation run (100% → 80% Q_sg step at t=30s, 600s horizon):

Metric ctrl_null ctrl_operation
Final T_avg drift from setpoint +1.5 °F +0.8 °F
Final u 0 $ -0.0068 $
Final power 800 MW ✓ 800 MW ✓

Sign polarity: T_avg > ref → e < 0 → u < 0 (rods in). Correct for a PWR. Controller reduces steady-state offset by ~47%. Expected result — gain is modest; the point is the plumbing works, not that the tuning is final.

What's deferred (on purpose)

  • Integral action in ctrl_operation. P-only for now. If we want to hit ref.T_avg exactly (zero steady-state error), augment state with int_e and upgrade to PI.
  • Gain config. Gains hardcoded in the controller file. Fine for one mode; once we tune 34 modes we should lift to a ctrl_params.m or similar.
  • Mode dispatcher. No ctrl_dispatch.m yet because there's only one real controller. Will introduce when we add the second mode and need to switch based on discrete state.
  • ctrl_heatup, ctrl_scram, ctrl_shutdown. Next. Each is a separate design problem with its own verification method (reachability, parametric reach, trivial).
  • Invariants and X_safe regions. User explicitly said: rough out controllers first, then come back to invariants. Per the thesis, we're not trying to verify the whole hybrid system at once — one mode's reach set at a time.

Things worth remembering

  • addpath('controllers') is required in main.m — MATLAB won't find @ctrl_operation otherwise. Putting controllers in a subfolder is ergonomically clean but the path has to be set.
  • U is reconstructed post-hoc in pke_solver. If a future controller has hysteresis or switching behavior, this reconstruction may not match the ODE's internal trajectory (the solver might have evaluated ctrl_fn at interior points that don't appear in the returned t). For smooth controllers (P, PI) this is fine; for event-driven / hybrid controllers we'll need to log u during the solve instead.
  • MATLAB -batch mode runs main.m cleanly without a display — figures are created off-screen but the script completes. Good for CI or sanity checks without opening the IDE.
  • T_avg is literally T_c in the state vector (x(9)). Don't let the two names confuse future debugging — T_avg is the nuclear-industry term, T_c is the code variable, they're the same quantity.

Paths touched

  • Modified: plant-model/pke_th_rhs.m, pke_solver.m, pke_initial_conditions.m, plot_pke_results.m, main.m, README.md, CLAUDE.md
  • Created: plant-model/controllers/ctrl_null.m, plant-model/controllers/ctrl_operation.m
  • Nothing outside plant-model/ was touched this session.