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>
4.9 KiB
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— timex— continuous state vector[n; C1..C6; T_f; T_c; T_cold]plant— params struct (wasp; renamed to avoid collision withp_ipredicates 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.mnow takesuas an explicit argument instead of readingp.rho_ext(t)from the params struct. This decouples plant from controller and matches the thesis'sf(x, u)form. Oldrho_extfield on the params struct is gone.pke_solver.msignature changed:[t, X, U] = pke_solver(plant, Q_sg, ctrl_fn, ref, tspan). ReturnsU(the control trajectory), reconstructed post-hoc by re-evaluatingctrl_fnat each returned time step.plot_pke_results.mtakes(t, X, U, plant, Q_sg, title)— reactivity panel now showsu, feedback, and total separately rather than relying on ap.rho_exthandle.pke_initial_conditions.mtrivial renamep → plant, outputx0.
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_avgexactly (zero steady-state error), augment state withint_eand upgrade to PI. - Gain config. Gains hardcoded in the controller file. Fine for one
mode; once we tune 3–4 modes we should lift to a
ctrl_params.mor similar. - Mode dispatcher. No
ctrl_dispatch.myet 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_saferegions. 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 inmain.m— MATLAB won't find@ctrl_operationotherwise. Putting controllers in a subfolder is ergonomically clean but the path has to be set.Uis reconstructed post-hoc inpke_solver. If a future controller has hysteresis or switching behavior, this reconstruction may not match the ODE's internal trajectory (the solver might have evaluatedctrl_fnat interior points that don't appear in the returnedt). For smooth controllers (P, PI) this is fine; for event-driven / hybrid controllers we'll need to loguduring the solve instead.- MATLAB
-batchmode runsmain.mcleanly without a display — figures are created off-screen but the script completes. Good for CI or sanity checks without opening the IDE. T_avgis literallyT_cin the state vector (x(9)). Don't let the two names confuse future debugging —T_avgis the nuclear-industry term,T_cis 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.