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

113 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```matlab
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.