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>
133 lines
5.3 KiB
Markdown
133 lines
5.3 KiB
Markdown
# CLAUDE.md
|
||
|
||
Guidance for Claude Code (and any AI agent) working in this subdirectory.
|
||
|
||
See also: the parent repo's `CLAUDE.md` (living-documentation rule — update
|
||
this file when new knowledge is created) and `claude_memory/` for session
|
||
notes that haven't yet earned a place here.
|
||
|
||
## What this is
|
||
|
||
A 10-state point kinetic equation (PKE) model of a PWR coupled with
|
||
lumped-parameter thermal-hydraulics, plus mode-specific continuous
|
||
controllers. Implements the *plant* and the *tactical* layer of the HAHACS
|
||
methodology — see `../thesis/3-research-approach/approach.tex` sections on
|
||
transitory, stabilizing, and expulsory modes.
|
||
|
||
The model is being developed for hybrid-systems reachability analysis. The
|
||
end goal is barrier-certificate and reachability methods (in `../reachability/`)
|
||
to prove each continuous mode satisfies its obligations under bounded
|
||
`Q_sg(t)` variations.
|
||
|
||
## Naming convention (thesis-aligned)
|
||
|
||
Continuous state and control-theory notation matches the thesis:
|
||
|
||
| Symbol | Meaning |
|
||
|---|---|
|
||
| `t` | time [s] |
|
||
| `x` | continuous state vector, `[n; C1..C6; T_f; T_c; T_cold]` |
|
||
| `plant` | parameter struct from `pke_params()` (was `p` — renamed to avoid collision with `p_i` predicates) |
|
||
| `u` | control input: external rod reactivity [dk/k] |
|
||
| `Q_sg` | bounded disturbance: SG heat removal [W], as a function handle `Q_sg(t)` |
|
||
| `ref` | reference/setpoint struct (e.g. `ref.T_avg`) |
|
||
|
||
`T_avg = T_c` (algebraic alias); `T_hot = 2*T_c - T_cold` (linear coolant
|
||
profile assumption).
|
||
|
||
## Running
|
||
|
||
From inside MATLAB:
|
||
|
||
```matlab
|
||
main % runs the default closed-loop scenario
|
||
```
|
||
|
||
From a terminal (figures appear as their own windows):
|
||
|
||
```bash
|
||
matlab -nodesktop -nosplash -r "main" # drops at >> prompt; `exit` to quit
|
||
matlab -r "main" & # full IDE, backgrounded
|
||
matlab -batch "main" # headless sanity check (no figures shown)
|
||
```
|
||
|
||
`main.m` configures the scenario (plant, `Q_sg`, ref, tspan), picks a
|
||
controller, and calls `pke_solver`. Tested on MATLAB R2025b; works on any
|
||
MATLAB with `ode15s` (R2020b or newer).
|
||
|
||
## Architecture
|
||
|
||
```
|
||
plant-model/
|
||
pke_params.m plant parameters and derived steady state
|
||
pke_initial_conditions.m analytic equilibrium x0 from plant
|
||
pke_th_rhs.m dynamics: dx/dt = f(t, x, plant, Q_sg, u)
|
||
pke_solver.m closed-loop driver; takes a controller fn handle
|
||
plot_pke_results.m 4-panel results plot
|
||
load_profile.m canned Q_sg demand shapes
|
||
main.m entry point — scenario config + run
|
||
controllers/
|
||
ctrl_null.m u = 0 (baseline, no feedback)
|
||
ctrl_operation.m stabilizing: P on T_avg
|
||
(future: ctrl_heatup, ctrl_scram, ctrl_shutdown)
|
||
```
|
||
|
||
**Controller contract:**
|
||
|
||
```matlab
|
||
u = ctrl_<mode>(t, x, plant, ref)
|
||
```
|
||
|
||
Pure function. Returns scalar `u` (external rod reactivity in `dk/k`). All
|
||
four signature args are required even if unused — lets the solver swap
|
||
controllers by function handle without caring which one it is.
|
||
|
||
**Solver contract:**
|
||
|
||
```matlab
|
||
[t, X, U] = pke_solver(plant, Q_sg, ctrl_fn, ref, tspan)
|
||
```
|
||
|
||
Builds the closed-loop RHS internally, calls `ode15s`, then reconstructs the
|
||
control trajectory `U` by re-evaluating `ctrl_fn` at each returned time step.
|
||
For event-driven or hysteretic controllers, this reconstruction may miss
|
||
interior solver evaluations — revisit if / when that matters.
|
||
|
||
## Key design decisions
|
||
|
||
- **`Q_sg` is the disturbance, never an actuator.** Cold leg temperature is
|
||
a dynamic state resulting from SG heat removal — the reachability
|
||
formulation needs `Q_sg ∈ [Q_min, Q_max]` as a bounded disturbance, not a
|
||
control input.
|
||
- **`u` is explicit.** `pke_th_rhs` takes `u` directly instead of reading
|
||
`p.rho_ext(t)` from the params struct. This decouples plant from
|
||
controller and matches the thesis's `f(x, u)` formulation.
|
||
- **Controller gains live in the controller file.** Rough-out phase — we'll
|
||
lift to a config struct once we're tuning more than one mode. The gain
|
||
in `ctrl_operation` (`Kp = 1e-4 /K`) is chosen to roughly double the
|
||
effective moderator coefficient, not for precision tracking.
|
||
- **`ode15s` is required** because the system is stiff: `Lambda` (~10⁻⁴ s)
|
||
vs thermal time constants (~10–100 s).
|
||
|
||
## Conventions
|
||
|
||
- One function per file, each file has a single responsibility.
|
||
- Internal model uses SI (W, kg, °C); all printed/plotted temperatures in °F.
|
||
- Reference setpoints in SI (so `ref.T_avg` is in °C).
|
||
- Controllers are pure functions — no persistent state. If a mode ever
|
||
needs integral action, augment `x` rather than hiding state in globals.
|
||
|
||
## For reachability work (next chapter)
|
||
|
||
- `pke_th_rhs(t, x, plant, Q_sg, u)` is the `ẋ = f(x, u)` with `Q_sg` as the
|
||
disturbance `w`. For a given mode, substitute `u = ctrl_<mode>(t, x, plant, ref)`
|
||
to get the closed-loop `ẋ = f_cl(x, w)`.
|
||
- Linearize around `x0` from `pke_initial_conditions(plant)` for `A, B, B_w`
|
||
matrices when a linear reach set is enough.
|
||
- Safe regions come from the FRET spec's guards (see
|
||
`../fret-pipeline/specs/synthesis_config_v3.json`) — these define
|
||
`X_entry`, `X_exit`, `X_safe` per the thesis approach.
|
||
- Do NOT try to verify the whole hybrid system at once. Pick one mode,
|
||
compute its reach set, discharge the per-mode obligation. The
|
||
compositionality argument in the thesis is what makes this tractable.
|