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

51 lines
1.8 KiB
Matlab

%% main.m — closed-loop entry point
%
% Scenario: a 100% → 80% SG demand step. Compare the plant's intrinsic
% feedback response (ctrl_null) against the stabilizing operation-mode
% controller (ctrl_operation) holding T_avg at the nominal setpoint.
%
% Controller signature (thesis naming):
% u = ctrl_<mode>(t, x, plant, ref)
% where x is the continuous state vector and u is the external rod reactivity.
clear; clc; close all;
addpath('controllers');
%% ===== Plant =====
plant = pke_params();
%% ===== Scenario =====
% SG heat removal: step down to 80% at t = 30s, hold.
Q_sg = @(t) plant.P0 * (1.0 - 0.2 * (t >= 30));
% Reference for the operation-mode controller.
ref = struct();
ref.T_avg = plant.T_c0; % hold T_avg at steady-state value
% Simulation window.
tspan = [0, 600];
%% ===== Baseline: unforced feedback response =====
fprintf('\n----- Run 1: ctrl_null (plant feedback only) -----\n');
[t1, X1, U1] = pke_solver(plant, Q_sg, @ctrl_null, [], tspan);
%% ===== Closed loop: operation mode =====
fprintf('\n----- Run 2: ctrl_operation (P on T_avg) -----\n');
[t2, X2, U2] = pke_solver(plant, Q_sg, @ctrl_operation, ref, tspan);
%% ===== Plots =====
plot_pke_results(t1, X1, U1, plant, Q_sg, 'ctrl_null (baseline)');
plot_pke_results(t2, X2, U2, plant, Q_sg, 'ctrl_operation (P on T_avg)');
%% ===== Quick comparison figure =====
CtoF = @(T) T*9/5 + 32;
figure('Position', [100 50 1000 450], 'Name', 'T_avg comparison');
plot(t1, CtoF(X1(:,9)), 'b-', 'LineWidth', 1.5); hold on;
plot(t2, CtoF(X2(:,9)), 'r-', 'LineWidth', 1.5);
yline(CtoF(plant.T_c0), 'k--', 'LineWidth', 1.0);
xlabel('Time [s]'); ylabel('T_{avg} [F]');
legend('ctrl\_null', 'ctrl\_operation', 'setpoint', 'Location', 'best');
title('T_{avg} tracking: baseline vs stabilizing controller');
grid on;