PWR-HYBRID-3/plant-model/plot_pke_results.m
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

77 lines
2.6 KiB
Matlab

function plot_pke_results(t, X, U, plant, Q_sg, plot_title)
% PLOT_PKE_RESULTS Standard 4-panel plot of PKE + T/H simulation results.
%
% Inputs:
% t - time vector from ODE solver
% X - state matrix (M x 10): [n, C1..C6, T_f, T_c, T_cold]
% U - control input trajectory (M x 1): scalar u at each time
% plant - parameter struct from pke_params()
% Q_sg - function handle Q_sg(t) used in the simulation
% plot_title - (optional) string used in the figure name and first subplot
if nargin < 6 || isempty(plot_title)
plot_title = 'PKE + T/H closed-loop';
end
% --- Extract states ---
n = X(:, 1);
T_f = X(:, 8);
T_c = X(:, 9);
T_cold = X(:, 10);
T_hot = 2 * T_c - T_cold;
% --- Convert temperatures to Fahrenheit for display ---
CtoF = @(T) T * 9/5 + 32;
T_f_F = CtoF(T_f);
T_c_F = CtoF(T_c);
T_cold_F = CtoF(T_cold);
T_hot_F = CtoF(T_hot);
% --- Derived quantities ---
power_MW = n * plant.P0 / 1e6;
Q_sg_MW = arrayfun(Q_sg, t) / 1e6;
rho_fb = plant.alpha_f * (T_f - plant.T_f0) + plant.alpha_c * (T_c - plant.T_c0);
rho_tot = U + rho_fb;
% --- Plot ---
figure('Position', [100 50 1000 950], 'Name', plot_title);
% Power & SG demand
subplot(4, 1, 1);
plot(t, power_MW, 'b-', 'LineWidth', 1.5); hold on;
plot(t, Q_sg_MW, 'r--', 'LineWidth', 1.2);
xlabel('Time [s]'); ylabel('Power [MW_{th}]');
legend('Reactor Power', 'Q_{sg}', 'Location', 'east');
title(sprintf('%s — Power and SG Heat Demand', plot_title));
grid on;
% Reactivity: controller u, feedback, total
subplot(4, 1, 2);
plot(t, U / plant.beta, 'k-', 'LineWidth', 1.5); hold on;
plot(t, rho_fb / plant.beta, 'b-.', 'LineWidth', 1.2);
plot(t, rho_tot / plant.beta, 'm:', 'LineWidth', 1.5);
xlabel('Time [s]'); ylabel('\rho [$]');
legend('u (controller)', 'Feedback', 'Total', 'Location', 'east');
title('Reactivity');
grid on;
% Coolant temperatures
subplot(4, 1, 3);
plot(t, T_hot_F, 'r-', 'LineWidth', 1.5); hold on;
plot(t, T_c_F, 'm--', 'LineWidth', 1.2);
plot(t, T_cold_F, 'b-', 'LineWidth', 1.5);
xlabel('Time [s]'); ylabel('Temperature [F]');
legend('T_{hot}', 'T_{avg}', 'T_{cold}', 'Location', 'east');
title('Coolant Temperatures');
grid on;
% Fuel temperature
subplot(4, 1, 4);
plot(t, T_f_F, 'Color', [0.85 0.33 0.1], 'LineWidth', 1.5);
xlabel('Time [s]'); ylabel('Temperature [F]');
title('Fuel Temperature');
grid on;
end