Full toolchain port. Numerical equivalence verified against MATLAB:
- main_mode_sweep.jl: every mode's final state matches MATLAB to 3-4 dp
- reach_operation.jl: per-halfspace margins match MATLAB exactly
- barrier_lyapunov.jl: per-halfspace bounds match (best Qbar from sweep
yields max|dT_c| = 33.228 K either side)
- barrier_compare_OL_CL.jl: OL gamma 1.038e13, CL gamma 1.848e4
matching the MATLAB result; LQR helps by ~20,000x on every halfspace.
Phase summary:
Phase 1: pke_solver.jl, plot_pke_results.jl (Plots.jl), main_mode_sweep.jl
Phase 2: reach_linear.jl, reach_operation.jl, barrier_lyapunov.jl,
barrier_compare_OL_CL.jl, load_predicates.jl
Phase 3 (this commit): delete plant-model/ entirely, delete reach
code from reachability/ keeping predicates.json + docs,
git mv julia-port/ -> code/, update root README + CLAUDE,
write code/CLAUDE.md and code/README.md, update reach
README + WALKTHROUGH file paths, journal preamble note
that pre-port entries reference MATLAB paths.
Why now: prompt-neutron stiffness in nonlinear reach made it clear we
need TMJets, which is Julia. Already had the Julia plant model
working and matching MATLAB. Two languages = two sources of truth =
two places to drift. One language, one truth.
Manifest.toml gitignored. .mat results gitignored.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.9 KiB
CLAUDE.md
Guidance for Claude Code (and any AI agent) working in this repository.
Living documentation — update these files
CLAUDE.md files are living. This one and the ones in subdirectories.
When you learn something new about the system that a future agent would
benefit from, update the appropriate CLAUDE.md before the session ends.
Context that exits a session uncaptured is lost forever — treat this as
the single most important rule in this repo.
Where to write:
- Stable, authoritative knowledge (architecture, conventions, interfaces,
design decisions) → the relevant
CLAUDE.md. Root for cross-cutting; subdirectory for layer-specific. - Session-level findings, in-progress investigations, paths that didn't pan
out →
claude_memory/YYYY-MM-DD-topic.md. Seeclaude_memory/README.mdfor the pattern.
When to write:
- After a non-trivial debugging session (what broke, root cause, how you knew).
- After an architectural or structural decision (what we chose, what we rejected, why).
- After discovering a non-obvious fact (subtle constraint, undocumented tool behavior, counterintuitive data format).
- Before ending a session where you explored paths that didn't pan out — so the next agent doesn't waste effort redoing them.
Over time, session notes that stabilize get distilled up into the relevant
CLAUDE.md; the rest get archived or deleted. This is a discipline, not
automation — do the graduation explicitly when knowledge becomes authoritative.
What this is
The preliminary example for the HAHACS thesis — a PWR startup controller demonstrating the full pipeline from written operating procedures to verified hybrid controller. This repo composes three layers of the same story:
| Layer | Location | Role | Thesis mapping |
|---|---|---|---|
| Story | thesis/ (submodule) |
The PhD proposal: math, prose, claims | Motivates and defines the methodology |
| Discrete | fret-pipeline/ |
FRET requirements → LTL → ltlsynt → AIGER circuit → state machine | Implements Thrust 1 + 2 |
| Continuous + Verification | code/ + reachability/ |
10-state PKE + thermal-hydraulics PWR model, controllers, reach machinery (all Julia) plus predicates.json and WALKTHROUGH.md |
Plant + Thrust 3 (reachability / barrier certs) |
| Journal | journal/ |
LaTeX invention log, dated entries | Project history / re-derivability |
| App | app/ |
Pluto.jl predicate explorer | FRET-adjacent UI for hybrid-systems groups |
| Hardware | hardware/ |
Ovation HIL artifacts | Integration milestone — currently empty |
| Deliverables | presentations/ |
Conference papers and talks (submodules) | Dissemination |
Running example: the PWR_HYBRID_3 controller. The discrete automaton it
synthesizes is literally the state machine drawn in thesis/3-research-approach/approach.tex
Figure 1 (Cold Shutdown → Heatup → Power Operation, with SCRAM).
How changes flow
- Requirement change. Edit the FRET export (
fret-pipeline/pwr_hybrid_3.json) → runfret-pipeline/scripts/fret_to_synth.py→ re-synthesize viasynthesize.sh→ re-trace viatrace_aiger.py. New.svg/.dot/.pngland infret-pipeline/diagrams/. Copy the figure you want to cite intodocs/figures/so the thesis can pick it up. - Plant change. Edit
code/src/pke_params.jlor dynamics incode/src/pke_th_rhs.jl→ re-runcode/scripts/main_mode_sweep.jlto verify behavior. Steady-state values feed theT_avg,P_critthresholds viareachability/predicates.json— if you change parameters here, the predicate concretization may need to follow. - Verification work. Continuous-mode verification reads the
FRET-side predicates from
reachability/predicates.jsonand the dynamics fromcode/src/pke_th_rhs.jl. Reach scripts incode/scripts/reach_*.jlandbarrier_*.jl. Results land back inreachability/*.mat(gitignored). - Thesis edit.
cd thesis && <edit> && git commit && git push origin main, then from the umbrella root:git add thesis && git committo bump the submodule pointer.
Where to look for what
- Reactor physics, steady-state, ODE dynamics, controllers, reach, barrier →
code/ - Predicate concretizations (the seam between FRET and reach) →
reachability/predicates.json - Reach analysis writeup →
reachability/WALKTHROUGH.md - Controller synthesis, requirements, state machines →
fret-pipeline/ - Research narrative, math, claims, citations →
thesis/ - Shared figures (for the thesis or talks) →
docs/figures/ - How the layers compose →
docs/architecture.md - Project history / invention log →
journal/ - Predicate-explorer GUI →
app/
Submodule rituals
- Fresh clone:
git clone <url> && git submodule update --init --recursive(orgit clone --recurse-submodules <url>). Without this,thesis/andpresentations/2026DICE/are empty directories. - Editing the thesis:
cd thesis && git checkout mainfirst — submodules default to detached HEAD. Then edit, commit, push inside the submodule, thencd ..and commit the new submodule pointer in the umbrella. - Pulling upstream thesis changes:
cd thesis && git pull origin main, then commit the new pointer in the umbrella.
Conventions
- FRET variables:
control_<group> = q_<value>for modes; everything else is an environment input. Seefret-pipeline/README.mdfor the full naming rule. - Plant model units: internal SI (W, kg, °C); printed/plotted in °F.
- Continuous state vector:
x = [n; C1..C6; T_f; T_c; T_cold]. Guards in FRET should reference the algebraic outputs (T_hot,T_avg) or direct states, not derived quantities. Q_sg(t)is the bounded disturbance — never treatT_coldas an input.- The continuous toolchain is Julia. The earlier MATLAB implementation was ported on 2026-04-20 and deleted; recover via git history if archaeologically needed.
What's deliberately missing (so you don't go looking)
- LTL-to-Stateflow translator — there's a known pain point in the thesis workflow where AIGER circuits still need to become Stateflow. Not yet automated. Current path: generate AIGER → eyeball the state machine diagram → hand-translate to Stateflow. Roadmapped.
- Hardware bring-up (Ovation DCS) — scheduled for the integration thrust.
hardware/is a placeholder. - Continuous-mode verification — partial. Linear reach for operation
mode discharges all 6
inv2_holdshalfspaces (approximate, not sound). Lyapunov-ellipsoid barrier fails structurally (anisotropy ceiling — seereachability/WALKTHROUGH.md). Nonlinear reach (TMJets) functional to 10 s; needs reduced-order PKE for hours-long horizons. - Polytopic / SOS barriers — flagged in WALKTHROUGH as the next-step alternative to the failing quadratic Lyapunov barrier.
- Reduced-order (prompt-jump) PKE — known remedy for nonlinear reach stiffness, not yet implemented.