% --------------------------------------------------------------------------- % 2026-04-17 --- Controllers + linearization + operation-mode linear reach % Deep / A-style invention-log entry. % --------------------------------------------------------------------------- \session{2026-04-17}{full afternoon, $\sim$5 hr}{Build out the three missing DRC controllers (shutdown, heatup, scram), add a numerical linearization, design an LQR, and discharge the operation-mode safety obligation with a hand-rolled zonotope reach. Try a Lyapunov-ellipsoid barrier certificate; find it fundamentally too coarse for this plant.} \section{2026-04-17 --- Controllers, linearization, operation-mode reach} \label{sec:20260417} \subsection*{Starting state} Coming into this session the repository had: \begin{itemize} \item A 10-state PKE + thermal-hydraulics plant model (\texttt{plant-model/pke\_th\_rhs.m}) and its parameters (\texttt{plant-model/pke\_params.m}). \item Two controllers: \texttt{ctrl\_null.m} (u=0 baseline) and \texttt{ctrl\_operation.m} (plain P on $T_{\mathrm{avg}}$). \item A FRET synthesis pipeline producing a discrete controller (DRC) with four modes (\texttt{q\_shutdown}, \texttt{q\_heatup}, \texttt{q\_operation}, \texttt{q\_scram}) and seven transitions. \item An empty \texttt{reachability/} directory. The thesis calls for per-mode reach analysis; nothing has been done yet. \end{itemize} \subsection*{Goal} Move the reachability thrust from zero to a first working artifact. To do that, the continuous side needs all four modes' controllers built out (can't reach-analyze a mode with no controller), a linearization tool (for LQR design and for linear reach set propagation), and a choice of reach tool. Build all that, then discharge one mode's safety obligation. \subsection*{Plant-model recap (what we're controlling)} The plant is a lumped point-kinetic reactor coupled to a three-node thermal loop. State vector $x \in \mathbb{R}^{10}$: $$x = \bigl[\,n,\; C_1,\; C_2,\; C_3,\; C_4,\; C_5,\; C_6,\; T_f,\; T_c,\; T_{\mathrm{cold}}\,\bigr]^\top$$ with $n$ normalized power, $C_i$ the six delayed-neutron precursor concentrations, $T_f$ fuel temperature, $T_c$ average coolant temperature, $T_{\mathrm{cold}}$ cold-leg coolant temperature. Hot-leg temperature is algebraic: $T_{\mathrm{hot}} = 2T_c - T_{\mathrm{cold}}$ (linear coolant profile). \begin{derivation} The full RHS $\dot x = f(x, u, w)$ is: \begin{align*} \rho &= u + \alpha_f(T_f - T_{f0}) + \alpha_c(T_c - T_{c0}) \\ \dot n &= \frac{\rho - \beta}{\Lambda} n + \sum_{i=1}^{6} \lambda_i C_i \\ \dot C_i &= \frac{\beta_i}{\Lambda} n - \lambda_i C_i \quad (i = 1,\dots,6) \\ \dot T_f &= \frac{P_0 n - hA(T_f - T_c)}{M_f c_f} \\ \dot T_c &= \frac{hA(T_f - T_c) - 2 W c_c (T_c - T_{\mathrm{cold}})}{M_c c_c} \\ \dot T_{\mathrm{cold}} &= \frac{W c_c (T_{\mathrm{hot}} - T_{\mathrm{cold}}) - Q_{\mathrm{sg}}(t)}{M_{\mathrm{sg}} c_c} \end{align*} $u$ is external rod-worth reactivity (the control input). $Q_{\mathrm{sg}}(t)$ is the steam-generator heat-removal disturbance. All other symbols are plant constants (see \texttt{plant-model/pke\_params.m} for sourcing; most are representative of a 2-loop Westinghouse-class PWR). \end{derivation} \subsection*{Part 1: The three new controllers} The DRC has four modes; we had only one mode's continuous controller written. Need to fill in shutdown, heatup, and scram. \subsubsection*{Shutdown and scram --- trivial, picked for physical defensibility} Both modes are passive: the reactor is parked deeply subcritical, rods are fully in, no feedback control is applied. Each is a one-liner. \begin{lstlisting}[language=Matlab,caption={\texttt{plant-model/controllers/ctrl\_shutdown.m}}] u = -5 * plant.beta; % ~5 $ subcritical \end{lstlisting} \begin{lstlisting}[language=Matlab,caption={\texttt{plant-model/controllers/ctrl\_scram.m}}] u = -8 * plant.beta; % ~8 $, typical regulatory 8-10 $ rod worth \end{lstlisting} \begin{decision} Constants, not feedback laws. Rationale: \begin{itemize} \item Real shutdown/scram behavior is ``rods fully inserted, worth $\sim$5--10~\$, no further action.'' A feedback law would be un-physical. \item Constants are trivial to reach-analyze. Closed-loop matrix $A_{\mathrm{cl}} = A$ (controller adds nothing to dynamics). \item At cold-start conditions ($T = T_{\mathrm{cold0}} \approx 290\,^\circ\mathrm{C}$), the linearized feedback from $\alpha_f, \alpha_c$ is about $+2.79\,\$$ of ``wants-to-be-supercritical'' reactivity. So $u = -5\,\$$ gives total $\rho \approx -2.2\,\$$, comfortably subcritical with margin for uncertainty. $-8\,\$$ on scram gives $\sim$$-5\,\$$ total --- conservative. \item We could tighten to $-3\,\$$ and still be subcritical at warm temperatures, but the thesis wants a safety margin robust to any plausible state. \end{itemize} \end{decision} \subsubsection*{Heatup --- the interesting controller} Heatup is the one transition mode that does real control work: drive $T_{\mathrm{avg}}$ from hot-standby conditions up to operating conditions while keeping the reactor bounded. This one needs design. The structure I landed on: \begin{equation} u(t, x) = \mathrm{sat}\Bigl(u_{\mathrm{ff}}(x) + K_p\bigl(T_{\mathrm{ref}}(t) - T_c\bigr),\; u_{\min},\; u_{\max}\Bigr) \end{equation} with three ingredients: \textbf{Feedback linearization.} Cancel the intrinsic temperature feedback exactly: \begin{equation} u_{\mathrm{ff}}(x) = -\alpha_f(T_f - T_{f0}) - \alpha_c(T_c - T_{c0}) \end{equation} so that after substitution into the $\rho$ equation, \begin{equation} \rho_{\mathrm{total}} = u_{\mathrm{ff}} + K_p(T_{\mathrm{ref}} - T_c) + \underbrace{\alpha_f(T_f - T_{f0}) + \alpha_c(T_c - T_{c0})}_{\text{cancels } u_{\mathrm{ff}}} = K_p \cdot e \end{equation} where $e = T_{\mathrm{ref}} - T_c$. The cancellation is exact only if the controller's $(\alpha_f, \alpha_c)$ match the plant's. This is the seat of the controller's robustness risk; see \cref{sub:alpha-drift}. \textbf{Ramped reference.} \begin{equation} T_{\mathrm{ref}}(t) = \min\bigl(T_{\mathrm{start}} + r \cdot t,\; T_{\mathrm{target}}\bigr) \end{equation} with $r$ = 28~\unit{\celsius/\hour} (\num{7.78e-3}~\unit{\celsius/\second}), the tech-spec heatup rate. Clamped at $T_{\mathrm{target}}$ once the ramp reaches operating conditions. \textbf{Saturation on $u$.} Cap $|u|$ at $0.5\beta$ on the positive side and $5\beta$ on the negative side. The upper cap keeps $\rho < \beta$ (the prompt-criticality line) under any plausible state, which bounds the neutron-kinetics excursion rate for later reach analysis. \begin{deadend} \textbf{First-pass heatup controller, before saturation was added.} The initial design was just feedback-linearization + P with no saturation, starting from an initial condition $n = 10^{-6}$ (decay-heat level) at $T_{\mathrm{cold0}} = 290\,^\circ\mathrm{C}$ everywhere. What went wrong: at that cold IC, the feedback terms give about $+2.79\,\$$ of positive reactivity. With $u_{\mathrm{ff}}$ cancelling those, $u = K_p \cdot e$ with $K_p = \num{1e-4}$. Error grows as $T_{\mathrm{ref}}$ ramps away from $T_c$ (which is still cold because the reactor has no power to heat it yet). Reactivity builds slowly, but because $n$ is tiny, power is tiny; the system takes \textbf{about 20 minutes} to generate enough power to heat the coolant, during which $T_c$ stays at 290~\unit{\celsius} while $T_{\mathrm{ref}}$ ramps to 297. Once power catches up, the large accumulated error produces a power spike (visible in the first-pass figure: $n$ peaks near $0.018 = 1.8\%$), and the thermal mass overshoots $T_{\mathrm{target}}$ by about 7~\unit{\celsius} before the controller pulls it back. Why it doesn't actually match physics: real plant heatup doesn't start from $n \approx 0$. Operators take the reactor critical at low power \emph{in shutdown mode}, by slowly withdrawing rods, then the DRC transitions to heatup with $n \sim 0.1\,\%$ already established. Two fixes landed: \begin{enumerate} \item Saturation on $u$: prevents the accumulated-error spike. \item Start heatup sims from a ``critical-at-low-power'' IC ($n = 10^{-3}$). \texttt{main\_mode\_sweep.m} uses this IC. \end{enumerate} The feedback-linearization controller alone doesn't know any of this --- it just does what the math says. The fixes are a controller design change (saturation) and an IC assumption. A fancier heatup controller would also include ramp-rate feedforward, but we don't need it yet. \end{deadend} \begin{decision} \textbf{No integrator.} We stay with P-only (no PI), even knowing there will be structural ramp-tracking lag on the order of $r/K_p/\omega_{\mathrm{thermal}}$. Rationale: \begin{itemize} \item The plant already has strong integrators via thermal mass ($M_c c_c$, $M_{\mathrm{sg}} c_c$). PI would double-integrate. \item PI adds state, turning the 10-state reach problem into 11 states. Modest cost by itself. \item The dealbreaker: \textbf{anti-windup saturation makes PI a hybrid system}. Each saturation region (unsat / low-sat / high-sat) is its own continuous mode with its own dynamics. Our outer hybrid automaton is the DRC; nesting an inner hybrid system inside each DRC mode doubles the verification complexity. \item The DRC exits heatup on a predicate window (\texttt{t\_avg\_in\_range} $\wedge$ \texttt{p\_above\_crit}), not on zero steady-state error. So the structural lag is acceptable. \end{itemize} \end{decision} Final controller (after iteration) lives in \texttt{plant-model/controllers/ctrl\_heatup.m}. The relevant body: \begin{lstlisting}[language=Matlab,caption={\texttt{ctrl\_heatup.m} body (abbreviated)}] Kp = 1e-4; T_f = x(8); T_c = x(9); T_avg = T_c; u_ff = -plant.alpha_f*(T_f - plant.T_f0) ... -plant.alpha_c*(T_avg - plant.T_c0); T_ref = min(ref.T_start + ref.ramp_rate * t, ref.T_target); e = T_ref - T_avg; u_unsat = u_ff + Kp * e; u = min(max(u_unsat, -5*plant.beta), 0.5*plant.beta); \end{lstlisting} \subsection*{Part 2: Linearization} We need $(A, B, B_w)$ matrices for (a) LQR gain synthesis and (b) linear reach set propagation. \begin{derivation} Central finite differences on $f(x, u, w)$ at a chosen operating point $(x^\star, u^\star, w^\star)$: \begin{align*} A_{:,k} &\approx \frac{f(x^\star + h_k e_k, u^\star, w^\star) - f(x^\star - h_k e_k, u^\star, w^\star)}{2 h_k} \\ B &\approx \frac{f(x^\star, u^\star + h_u, w^\star) - f(x^\star, u^\star - h_u, w^\star)}{2 h_u} \\ B_w &\approx \frac{f(x^\star, u^\star, w^\star + h_w) - f(x^\star, u^\star, w^\star - h_w)}{2 h_w} \end{align*} with $h_k = \max(\epsilon_{\mathrm{rel}} |x^\star_k|,\; \epsilon_{\mathrm{abs}})$ to handle the wildly different magnitudes in $x$ (e.g.\ $n \sim 1$ vs.\ $C_1 \sim 10^2$ vs.\ $T_f \sim 3 \times 10^2$). \end{derivation} Validation: simulate the linear model and the nonlinear model in parallel under a small $Q_{\mathrm{sg}}$ step and compare deviations from $x^\star$. \Cref{fig:linearize-sanity} shows the result. \begin{figure}[h] \centering \includegraphics[width=0.85\linewidth]{linearize_sanity.png} \caption{Linear vs.\ nonlinear sanity check under a 5\% $Q_{\mathrm{sg}}$ down-step at $t = 30$~\unit{\second}, $u = 0$. Linear (red dashed) tracks nonlinear (blue solid) within $4 \times 10^{-4}$ relative error at 60~\unit{\second}, improving to $5 \times 10^{-6}$ by 300~\unit{\second} as the system relaxes. The match is best on $n$ (tightly coupled), loosest on $C_3$ (slow precursor). Eigenvalues of $A$ span $[-65.93, -0.0124]$~\unit{\per\second} --- stiffness ratio $\sim$5000. Conclusion: linearization is quantitatively trustworthy for perturbations around $x^\star$ in a $\pm 50\,^\circ\mathrm{C}$ window.} \label{fig:linearize-sanity} \end{figure} The code is a straightforward loop (see \texttt{plant-model/pke\_linearize.m}); nothing subtle, but the magnitude-aware step size matters --- using a uniform $h = 10^{-6}$ either loses precision on the small states or truncates on the big ones. \subsection*{Part 3: LQR controller for operation mode} With $(A, B)$ in hand, design a linear quadratic regulator around the operating point. \begin{derivation} Solve the continuous-time algebraic Riccati equation (CARE) for $X \succeq 0$: $$A^\top X + X A - X B R^{-1} B^\top X + Q = 0$$ then set gain $K = R^{-1} B^\top X$. The closed-loop control law $u = -K(x - x^\star)$ minimizes $$\int_0^\infty \left[(x - x^\star)^\top Q (x - x^\star) + u^\top R u\right] dt$$ and guarantees $A_{\mathrm{cl}} = A - BK$ is Hurwitz whenever $(A,B)$ is stabilizable and $Q \succeq 0$. \end{derivation} Weight choices: \begin{lstlisting}[language=Matlab,caption={LQR weights, from \texttt{ctrl\_operation\_lqr.m}}] Q = diag([1, % n 1e-3, 1e-3, 1e-3, 1e-3, 1e-3, 1e-3, % precursors C_1..C_6 1e-2, % T_f 1e2, % T_c (the primary objective) 1]); % T_cold R = 1e6; \end{lstlisting} \begin{decision} $Q(9,9) = 10^2$ for $T_c$ is the primary design knob --- heavy because we care about the coolant average deviation. Precursor weights at $10^{-3}$ because they're informational (not directly regulated). $T_{\mathrm{cold}}$ at 1 because it's secondary but couples to $T_c$. $R = 10^6$ balances so $|u|$ stays in the few-cent range --- below prompt, above sensor noise. Ballpark numbers; we can retune if the reach tube comes out too tight or too loose. \end{decision} Head-to-head against plain P on the same 100\% $\to$ 80\% $Q_{\mathrm{sg}}$ step (\cref{fig:p-vs-lqr}): \begin{figure}[h] \centering \includegraphics[width=0.85\linewidth]{mode_sweep_op_P_vs_LQR.png} \caption{P vs.\ LQR on operation mode under a 100\%$\to$80\% $Q_{\mathrm{sg}}$ step at $t = 30$~\unit{\second}. Plain P (\texttt{ctrl\_operation.m}) has a 5~\unit{\degreeFahrenheit} peak overshoot and 0.8~\unit{\degreeFahrenheit} steady-state lag. LQR (\texttt{ctrl\_operation\_lqr.m}) holds $T_{\mathrm{avg}}$ essentially at setpoint throughout. Zero extra state in either; LQR is just using all ten state measurements instead of one.} \label{fig:p-vs-lqr} \end{figure} \subsection*{Part 4: Running all modes end-to-end} \texttt{plant-model/main\_mode\_sweep.m} exercises all five controllers (null, shutdown, heatup, operation-P, operation-LQR, scram) back-to-back from mode-appropriate ICs, and saves figures. The normalized-power overview (\cref{fig:power-overview}) captures the whole sweep: \begin{figure}[h] \centering \includegraphics[width=0.95\linewidth]{mode_sweep_power_overview.png} \caption{Normalized power $n(t)$ across the four DRC modes plus baseline. \emph{Shutdown} (top left, log scale): $n$ decays from $10^{-6}$ to $10^{-12}$ over 10~\unit{\minute}. \emph{Heatup} (top right): small power burst around minute 22 as the reactor goes critical and heats. \emph{Operation} (bottom left): $Q_{\mathrm{sg}}$ step at 30~\unit{\second} drops $n$ to 78\% briefly before settling at 80\%. \emph{Scram} (bottom right, log scale): $n$ drops $1 \to 10^{-6}$ via prompt jump + delayed-neutron tail over 10~\unit{\minute}. All four behave as textbook would predict.} \label{fig:power-overview} \end{figure} \subsection*{Part 5: Tool choice for reach analysis} Three candidate tools were evaluated: \begin{itemize} \item \textbf{CORA} (MATLAB) --- mature, stays in the existing language, handles linear + nonlinear. Downside: $\sim$0.5~GB install, heavy. \item \textbf{JuliaReach} --- newer, faster for large reach sets, rigorous Taylor-model support. Downside: requires porting the plant model to Julia. \item \textbf{Flow* / SpaceEx} --- C++ / no-longer-maintained, both add toolchain friction. \end{itemize} \begin{decision} For this first artifact: \textbf{write the reach tube by hand in pure MATLAB}. Rationale: linear reach with bounded disturbance has a clean analytic form --- matrix exponential on state, augmented-matrix integral for the disturbance contribution --- that compiles to about 50 lines of MATLAB. No toolbox install, no language switch. The result is a sound box-shaped over-approximation. If/when we need nonlinear reach, that's the point to stand up JuliaReach. (Spoiler for the reader: this did happen in the \texttt{2026-04-20-evening} session.) \end{decision} \subsection*{Part 6: The zonotope reach propagator} For the LQR-closed-loop linear system $\dot{\delta x} = A_{\mathrm{cl}} \delta x + B_w w$ with $\delta x(0) \in X_0$ (axis-aligned box) and $w \in [w_{\mathrm{lo}}, w_{\mathrm{hi}}]$, the analytic solution splits into a homogeneous piece and a disturbance integral: \begin{derivation} \begin{equation} \delta x(t) = e^{A_{\mathrm{cl}} t} \delta x(0) + \int_0^t e^{A_{\mathrm{cl}}(t-s)} B_w w(s)\, ds. \end{equation} Discretize with step $\Delta t$ and let $A_{\Delta} = e^{A_{\mathrm{cl}} \Delta t}$. The disturbance integral over one step is $$G_\Delta = \int_0^{\Delta t} e^{A_{\mathrm{cl}} s} B_w \, ds.$$ \textbf{Van Loan's trick (1978):} expand the matrix exponential of an augmented matrix, \begin{equation} \exp\!\left(\begin{bmatrix} A & B_w \\ 0 & 0 \end{bmatrix} \Delta t\right) = \begin{bmatrix} e^{A \Delta t} & G_\Delta \\ 0 & 1 \end{bmatrix}. \end{equation} Read the upper-right block --- $G_\Delta$ is exact to machine precision without numerical quadrature. \end{derivation} Now propagate a box $\delta x \in [c - h,\ c + h]$ (center $c$, halfwidth $h$) through the linear map $M$: \begin{derivation} If $y = M \delta x$ and $\delta x_j \in [c_j - h_j,\ c_j + h_j]$, then $$y_i = \sum_j M_{ij} \delta x_j \quad \Longrightarrow \quad y_i \in \bigl[\,M c \mp |M| h\,\bigr]_i.$$ The $\pm$ signs of $M_{ij}$ align with opposite corners of the input box, so the sum extremum takes the absolute value of each coefficient times the halfwidth. Conclusion: box propagation uses \emph{elementwise} $|M|$, not signed $M$. \end{derivation} \begin{deadend} \textbf{First version of \texttt{reach\_linear.m} used signed $A_\Delta$ for halfwidth propagation.} Result: the reach tube came out suspiciously tight --- maximum $|T_c - T_{c0}|$ over 600~\unit{\second} was exactly equal to the initial halfwidth, as if the disturbance wasn't contributing at all. Diagnosed after about 15~\unit{\minute} of confusion: when I wrote $S_{\mathrm{half}} \leftarrow A_\Delta S_{\mathrm{half}} + G_\Delta w_{\mathrm{half}}$ with \emph{signed} $A_\Delta$, the positive and negative entries of $A_\Delta$ across successive steps happened to cancel, so $S_{\mathrm{half}}$ stayed near zero. The fix is to use elementwise absolute values per the derivation above: $$S_{\mathrm{half}} \leftarrow |A_\Delta| S_{\mathrm{half}} + |G_\Delta| w_{\mathrm{half}}.$$ Once the abs was added the disturbance halfwidth grew monotonically as expected, and the reach tube gained a sensible envelope. This is a case of ``the bug is easy to catch in the math, harder to catch when you copy-pasted from the center-propagation code.'' \end{deadend} The final propagator is the core of \texttt{reachability/reach\_linear.m} (about 50~lines). The per-step update is compact: \begin{lstlisting}[language=Matlab,caption={Halfwidth-propagation core of \texttt{reach\_linear.m}}] A_step = expm(A_cl * dt); A_abs_step = abs(A_step); M_aug = expm([A_cl, B_w; zeros(1, n+1)] * dt); G_step = M_aug(1:n, n+1); G_abs_step = abs(G_step); for k = 2:M x_center_now = A_step * x_center_now; halfwidth_now = A_abs_step * halfwidth_now; S_center = A_step * S_center + G_step * w_mid; S_half = A_abs_step * S_half + G_abs_step * w_half; center(:, k) = x_center_now + S_center; R_lo(:, k) = center(:, k) - halfwidth_now - S_half; R_hi(:, k) = center(:, k) + halfwidth_now + S_half; end \end{lstlisting} \subsection*{Part 7: Operation-mode reach --- discharging the safety obligation} Entry box around $x_{\mathrm{op}}$: \begin{itemize} \item $n$: $\pm 1\%$ of nominal. \item $C_i$: $\pm 0.1\%$ of equilibrium (precursors equilibrate fast; tight entry). \item $T_f,\ T_c,\ T_{\mathrm{cold}}$: $\pm 0.1$~\unit{\kelvin}. \end{itemize} Disturbance: $Q_{\mathrm{sg}} \in [0.85 P_0,\ 1.00 P_0]$ --- a 15\% load-down envelope (grid-following). Horizon: 600~\unit{\second}. The reach envelope on $T_c$ is shown in \cref{fig:reach-tc}. \begin{figure}[h] \centering \includegraphics[width=0.95\linewidth]{reach_operation_Tc.png} \caption{Operation-mode reach tube on $T_{\mathrm{avg}}$, two views. \emph{Left:} safety-band scale --- reach tube (pink) is barely visible because LQR holds it tight against the dashed $\pm 5$~\unit{\celsius} safety band. \emph{Right:} zoomed to reveal the actual tube. Halfwidth at $t=0$ is 0.1~\unit{\kelvin} (the entry box); halfwidth at $t=600$~\unit{\second} is 0.033~\unit{\kelvin}. The tube \emph{contracts} on the regulated direction --- the signature of tight feedback control. Max $|\delta T_c|$ over the horizon: 0.1~\unit{\kelvin} (the initial halfwidth dominates).} \label{fig:reach-tc} \end{figure} Per-halfspace margins against \texttt{inv2\_holds} (the operation-mode safety envelope): \begin{lstlisting}[style=terminal] === Operation-mode reach vs inv2_holds safety limits === [fuel_centerline] a'x <= 1200.000 | max a'x = 328.934 | margin = +871.066 OK [t_avg_high_trip] a'x <= 320.000 | max a'x = 308.449 | margin = +11.551 OK [t_avg_low_trip] a'x <= -280.000 | max a'x = -308.249 | margin = +28.249 OK [n_high_trip] a'x <= 1.150 | max a'x = 1.012 | margin = +0.138 OK [n_low_operation] a'x <= -0.150 | max a'x = -0.842 | margin = +0.692 OK [cold_leg_subcooled] a'x <= 305.000 | max a'x = 292.852 | margin = +12.148 OK \end{lstlisting} All six safety halfspaces pass. Tightest margin is \texttt{n\_high\_trip} --- LQR lets $n$ swing up to $\sim$1.01 to compensate for load variation, leaving 12\% margin to the high-flux trip. Temperatures have 10--870~\unit{\kelvin} margin each. \textbf{Operation-mode obligation discharged}, subject to the linearization caveat in \cref{sec:limitations-17}. Per-state reach-set evolution (final halfwidth vs.\ initial): \begin{center} \small \begin{tabular}{l r r r} \hline state & init halfwidth & final halfwidth & ratio \\ \hline $n$ & $0.010$ & $0.083$ & 8.3$\times$ expand \\ $C_1 \dots C_6$ & varies & varies & 160--200$\times$ expand \\ $T_f$ & 0.1~\unit{\kelvin} & 2.08~\unit{\kelvin} & 21$\times$ expand \\ $\boldsymbol{T_c}$ & $\mathbf{0.1}$~\unit{\kelvin} & $\mathbf{0.033}$~\unit{\kelvin} & $\mathbf{0.33\times}$ \textbf{contract} \\ $T_{\mathrm{cold}}$ & 0.1~\unit{\kelvin} & 1.47~\unit{\kelvin} & 15$\times$ expand \\ \hline \end{tabular} \end{center} $T_c$ \emph{contracts} --- LQR drags the regulated direction toward setpoint faster than disturbance can push it. Uncontrolled states drift. Precursor expansion ($\sim$$200\times$) is immaterial for safety (no predicate uses them). \subsection*{Part 8: Lyapunov barrier attempt} A reach tube is a numerical certificate: compute, check. A \emph{barrier certificate} is analytic: produce a function $B(x)$ such that $B \leq 0$ on the initial set, $B > 0$ on the unsafe set, and $\dot B \leq 0$ when $B = 0$. Forward-invariance of the safe set follows from the dynamics without iterating them. For linear systems with bounded disturbance, the canonical candidate is a Lyapunov quadratic. \begin{derivation} Let $V(\delta x) = \delta x^\top P \delta x$ with $P \succ 0$ solving $A_{\mathrm{cl}}^\top P + P A_{\mathrm{cl}} + \bar Q = 0$. Along trajectories of $\dot{\delta x} = A_{\mathrm{cl}} \delta x + B_w w$: \begin{align} \dot V &= -\delta x^\top \bar Q \delta x + 2 \delta x^\top P B_w w. \end{align} Bound each piece. The dissipation term using the generalized eigenvalue $\mu = \lambda_{\min}\bigl(P^{-1/2} \bar Q P^{-1/2}\bigr)$: $$-\delta x^\top \bar Q \delta x \leq -\mu V.$$ The disturbance kick, Cauchy-Schwarz in the $P$-metric: $$2 \delta x^\top P B_w w \leq 2 \bar w \sqrt{B_w^\top P B_w}\sqrt{V}.$$ Combining: $$\dot V \leq -\mu V + 2 \bar w \sqrt{B_w^\top P B_w}\sqrt{V}.$$ Set $s = \sqrt{V}$, requiring $\dot s \leq 0$: $$s \geq \frac{2 \bar w \sqrt{B_w^\top P B_w}}{\mu} \quad \Longleftrightarrow \quad V \geq \left(\frac{2 \bar w \sqrt{B_w^\top P B_w}}{\mu}\right)^2 =: c_{\mathrm{inv}}.$$ The sub-level set $\{ V \leq c_{\mathrm{inv}} \}$ is forward-invariant under any admissible disturbance. \end{derivation} So the recipe is: solve Lyapunov, compute $c_{\mathrm{inv}}$, compute the worst-case deviation of $T_c$ (or any linear functional of state) on the resulting ellipsoid, and check whether it fits inside the safety slab. \begin{derivation} Max of a linear functional $a^\top \delta x$ over the ellipsoid $\{\delta x : \delta x^\top P \delta x \leq \gamma\}$: $$\max a^\top \delta x = \sqrt{\gamma \cdot a^\top P^{-1} a}.$$ (Lagrange multipliers: the maximum is achieved at $\delta x = \sqrt{\gamma / a^\top P^{-1} a} \cdot P^{-1} a$.) \end{derivation} \textbf{Result:} the best quadratic barrier --- across a sweep of $\bar Q(9,9)$ from 10 to $10^6$ --- allows max $|T_c - T_{c0}| \approx 33$~\unit{\kelvin}, more than six times the 5~\unit{\kelvin} safety band. On the hard safety halfspaces (\texttt{inv2\_holds}), it says $n$ could deviate by $\pm 1242$~$\times$ nominal --- physically meaningless. \begin{limitation} \textbf{The quadratic Lyapunov barrier fails on this plant. This is a structural finding, not a tuning failure.} The safety spec is anisotropic: a thin slab $|T_c| \leq 5$~\unit{\kelvin} in a 10-D state space where $T_c$ is one direction and the other nine are precursors / fuel temperature / cold-leg. Any quadratic $V$ yields axis-uniform ellipsoidal level sets. To contain the disturbance-driven invariant set, the ellipsoid must be \emph{fat in the slow directions} (precursors, where Lyapunov dissipation is weakest). Projecting that fat ellipsoid back onto $T_c$ yields a range much larger than the physical $T_c$ behavior. Confirmed the issue is not controller tuning by running the barrier open-loop (no LQR): the bound becomes $\pm 27{,}000{,}000\,n$. LQR helps by $\sim$20{,}000$\times$, but still leaves a 3-4 order-of-magnitude gap to usability. The ceiling is plant anisotropy: prompt-neutron timescale $\Lambda = 10^{-4}$~\unit{\second} vs.\ thermal timescales $\sim$10--100~\unit{\second}, a factor-of-$10^4$ spread that forces $P$ to be ill-conditioned regardless of controller design. \textbf{Fix:} non-quadratic barrier. Two candidate approaches: \begin{itemize} \item \textbf{Polytopic barrier:} $B(\delta x) = \max_i (a_i^\top \delta x - b_i)$. Piecewise-linear, can match a slab shape directly. Requires polyhedral-set tooling. \item \textbf{SOS polynomial barrier:} $B$ a polynomial of degree $\geq 4$, coefficients found by sum-of-squares optimization. Requires an SOS solver (Mosek, SDPT3). \end{itemize} Neither is implemented; both are in-scope for the thesis chapter. The quadratic-Lyapunov failure, stated quantitatively, is the clean motivation. \end{limitation} \subsection*{Session result} Artifacts landing, in order: \begin{enumerate} \item \texttt{plant-model/controllers/ctrl\_shutdown.m}, \texttt{ctrl\_scram.m}, \texttt{ctrl\_heatup.m} (three new controllers). \item \texttt{plant-model/pke\_linearize.m} and \texttt{plant-model/test\_linearize.m}. \item \texttt{plant-model/controllers/ctrl\_operation\_lqr.m}. \item \texttt{plant-model/main\_mode\_sweep.m}. \item \texttt{reachability/reach\_linear.m} and \texttt{reachability/reach\_operation.m}. \item \texttt{reachability/barrier\_lyapunov.m}. \item Eleven figures in \texttt{docs/figures/}. \end{enumerate} Key claims established: \begin{itemize} \item LQR closed-loop operation mode satisfies the safety obligation under $\pm 15\%$ $Q_{\mathrm{sg}}$ variation (approximate, via linear reach). \item Quadratic Lyapunov barrier insufficient on this plant (open-loop or closed-loop). Need polytopic or SOS. \item LQR adds zero state, dominates plain P by $\sim 5\times$ on tracking. \end{itemize} \subsection*{Limitations recorded at close} \label{sec:limitations-17} \begin{limitation} All reach results are \emph{approximate}, not sound: they are reach tubes of the \emph{linearized} closed-loop. The linearization error --- the gap between $f_{\mathrm{nl}}(x, u)$ and $(A x + B u)$ --- is not propagated into the tube. For a real safety claim, either (a)~nonlinear reach directly or (b)~linear reach plus Taylor-remainder inflation. Neither is done. \end{limitation} \begin{limitation} \label{sub:alpha-drift} The feedback-linearization in \texttt{ctrl\_heatup} assumes exact $\alpha_f, \alpha_c$. Real PWRs have $\alpha$ drift: $\sim$20\% over burnup; $\sim$10$\times$ across soluble-boron dilution; xenon transients worth 2--3~\$. Robust version would treat $\alpha$ as parametric interval and propagate through reach. \end{limitation} \begin{limitation} Saturation in \texttt{ctrl\_heatup} is formally a 3-mode piecewise-affine sub-system. Operation-mode LQR is dormant-saturated (trivially); a rigorous heatup reach would need explicit region decomposition or a dormancy proof. \end{limitation} \begin{limitation} The model's $\alpha_f, \alpha_c$ are linearized at the hot full-power operating point. Trust region is $\pm 50$~\unit{\celsius} around $x^\star$. True cold shutdown ($\sim$50~\unit{\celsius}) is out of scope. What the DRC calls \texttt{q\_shutdown} we interpret as hot standby ($\sim$290~\unit{\celsius}). \end{limitation} \subsection*{Open at close} \begin{itemize} \item Nonlinear reach, at minimum on one mode, to retire the soundness asterisk. \item Polytopic or SOS barrier to retire the analytic-certificate asterisk. \item Parametric $\alpha$ uncertainty in the reach machinery. \item Heatup reach --- ramped reference needs LTV or nonlinear treatment. \item Shutdown + scram reach (trivial forever-invariance / bounded-time respectively, but not yet done). \end{itemize}