ALLSHIFT/docs/04-simulations/matlab-live-scripts.md
pepe 72dd781dbc Organize documentation into docs/ and superseded/
Audit every document in the repository, convert the non-markdown ones into
markdown reports, and split current documentation from outdated material.

docs/ — 31 markdown documents in seven numbered sections. Twenty are new
reports generated from .docx / .pdf / .xlsx / .mlx / .m sources that were
previously unreadable in the browser and undiffable in git. Each report
carries a provenance block (source path, format, MD5) and links back to its
original; all 13 recorded checksums verify against the files on disk.
Machine-extraction losses (PDF table column interleaving, Word OMML
equations, embedded figures) are called out explicitly rather than silently
smoothed over.

superseded/ — outdated material with a documented reason per entry:
two byte-identical ClickUp re-exports, an older revision of the BIDMC/UCSD
energy-flow doc (the retained copy adds the SoC Violation Rate KPI), a
duplicate of Shift input data.docx, the May 2026 simulation plan, the
root PV+Battery.md now covered by a fuller report, GitHub's stock
demo-repository template, and a zero-byte placeholder. Its README also
records what was deliberately NOT retired and why — the "Old Frameworks"
and "Old Simulations" folders hold unique Simulink revisions, and
"Big Ugly Folder" holds the only copy of framework revision 1.3.

Findings worth flagging, all documented in the reports:
- Simulink lineage recovered from each .slx's internal coreProperties.xml
  revision counter. The current model is
  Current Framework/Bobert0206_Initial_Simulation_Framework.slx (rev 2.7);
  the top-level copy is rev 1.3, five revisions behind.
- Simulations/Constants.m is a truncated byte-prefix of the Current
  Framework copy, silently missing H2_leak, H2_cap and E_H2_vol_h.
- The PEM electrolyser and fuel cell are unmodified MathWorks Simscape
  examples still at vendor defaults; the "10x bigger" sizing TODO recorded
  in Constants.m was never carried out.
- controller-claude.m does not compile — undefined P_Electro_max, outputs
  unassigned on several paths.
- The specification set uses two incompatible variable naming conventions
  and disagrees on action-space size (5 vs 16).
- MA_hourly_load.csv (13.7 MB) is the same 35,040 rows as 89993-0.parquet
  (2.4 MB).
- Clinical data is the MIMIC-IV *demo* (ODbL, 100 patients), not full
  MIMIC-IV — redistributable, but the licence and citation are unrecorded.

Housekeeping: untrack 21 Simulink build artefacts (slprj/, *.slxc) and add
ignore rules for them. Root README rewritten around the new layout.

Recruitment notes naming individual candidates are excluded from version
control via .gitignore rather than committed; the generic question template
is kept in docs/07-team-and-operations/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 21:20:33 -07:00

7.7 KiB

MATLAB Live Scripts (.mlx) Inventory

Markdown report of non-markdown source files.

Sources All five .mlx MATLAB Live Scripts in Shift Matlab Drive/
Format MATLAB Live Script — an OPC (zip) package; matlab/document.xml holds the code
Status Current inventory
Report generated 2026-07-25

MATLAB Live Scripts are binary-ish packages, so their contents are invisible to git diff and to anyone browsing the repository on the web. This report transcribes all five.

Summary

File Cluster folder Content Verdict
Simulations/PV+Battery Simulink/Constants.mlx Simulations 13 parameter assignments Substantive
Simulations/PV+Battery Simulink/PVBatteryRead.mlx Simulations ~110-line Excel→Simulink importer Substantive
RL_ML/Empty.mlx AI & Control Systems 'Test' Placeholder
Energy_Managment/Emptier.mlx Energy Management 'Exam' Placeholder
Business_Economics/Emptiest.mlx Business & Economics 'Attempt' Placeholder

The three placeholder files

Empty.mlx, Emptier.mlx and Emptiest.mlx each contain a single string literal and nothing else:

File Entire contents
RL_ML/Empty.mlx 'Test'
Energy_Managment/Emptier.mlx 'Exam'
Business_Economics/Emptiest.mlx 'Attempt'

The escalating names are deliberate. These are directory placeholders — MATLAB Drive, like many sync services, will not preserve an empty folder, so a token file was added to each of the three non-Simulations cluster folders to keep the structure alive.

The consequence is worth stating plainly: of the four SHIFT clusters, only Simulations has any MATLAB code in this repository at all. RL_ML/, Energy_Managment/ and Business_Economics/ contain nothing else — Energy Management's actual output is the document and dataset set covered in 03-energy-management, and AI & Control Systems' output is the specifications in 02-specifications plus controller-claude.m, which sits at the Shift Matlab Drive/ root rather than in RL_ML/.

These three files are retained in place — they are structural, not content, and deleting them would drop the folders.

Constants.mlx

Parameter definitions for the PV + Battery Simulink models. Must be run before the models.

A_PV     = 3060;            % PV Area (m2)
mu_PV    = 0.2;             % Panel Efficiency (%)
V_PV     = 24;              % PV Voltage (V)

P_ele    = 1500000;         % Electrolyzer Power Consumption (W)
E_t0     = 0;               % Initial Battery Energy (Wh)
E_rated  = 170000;          % Battery Rated Energy (W)
Q_rated  = 100000;          % Battery Rated Charge Capacity (W)
Charge_max   = 1;           % Maximum Charge (%)
Disharge_max = 2;           % Maximum Discharge (%)
SoC_max  = 1;               % SoC limit (%)
SoC_t0   = 0;               % Initial SoC (%)

P_B_int  = 0;               % Initial Battery power (W)
I_B_int  = 0;               % Initial Battery current (A)

These duplicate the constants block in the Generation Profiles Workbook, which is deliberate — PVBatteryRead.mlx was meant to read them from the spreadsheet but that path does not work, so they were transcribed here. See PV + Battery Simulink for the parameter cross-check against the project specification (three unit-comment errors and one value that contradicts the spec).

PVBatteryRead.mlx

Reads the Fake Simulink Data sheet out of Profiles SHIFT(Generators Factors + Battery).xlsx and pushes Simulink-ready signals into the base workspace.

close all; clear all
%% File settings
filename = 'Profiles SHIFT(Generators Factors + Battery).xlsx';
sheet = 'Fake Simulink Data';

%% Read Excel while preserving headers
T = readtable(filename, ...
    'Sheet', sheet, ...
    'HeaderLines', 1, ...
    'VariableNamingRule', 'preserve');

%% Remove completely empty columns
T = T(:, ~all(ismissing(T)));

headers = T.Properties.VariableNames;

Step 1 — convert data types. For each column: cell-text numbers are converted to double, first replacing , with . so European decimal commas parse; duration columns are converted to hours.

for i = 1:length(headers)
    col = T.(headers{i});
    if iscell(col)
        col = strrep(col, ',', '.');
        col = cellfun(@str2double, col);
    end
    if isduration(col)
        col = hours(col);
    end
    T.(headers{i}) = col;
end

Step 2 — detect last valid signal row. Numeric columns are stacked into signalMatrix (skipping any column whose header contains Date); rows are valid where any signal is non-NaN and the date is after 2000-01-01. The table is truncated at the last valid row.

Step 3 — extract variables and constants. Variable names are parsed out of headers of the form Name - var (unit):

token = regexp(header, '-\s*(.*?)\s*\(', 'tokens');
varName = matlab.lang.makeValidName(strtrim(token{1}{1}));

Time is special-cased and normalised to seconds:

if strcmpi(varName, 't')
    if isduration(values)
        t = seconds(values);
    elseif isnumeric(values)
        if max(values) <= 1
            t = values * 24 * 3600;   % fraction of day -> seconds
        else
            t = values * 3600;        % hours -> seconds
        end
    end
    assignin('base', 't', t);
end

Every other column is classified by cardinality — a column with exactly one unique non-NaN value becomes a scalar constant, otherwise a time series:

u = unique(values(~isnan(values)));
if numel(u) == 1
    assignin('base', varName, double(u));
else
    assignin('base', varName, double(values));
end

Step 4 — create Simulink-ready signals. Every numeric workspace variable whose length matches t gets a companion <name>_simulink = [t, values] — the two-column [time, data] matrix a Simulink From Workspace block expects.

val = evalin('base', v);
if isnumeric(val) && numel(val) == n
    simData = [t val(:)];
    assignin('base', [v '_simulink'], simData);
end

Notes on this script

  • The time-unit conversion here is the prime suspect for the known model bug. Step 3 emits t in seconds; if the Simulink models' stop time is configured in hours, the simulated window covers only the first few samples and every signal looks constant. That matches the symptom recorded in PV + Battery Simulink exactly.
  • clear all at the top wipes the workspace — including anything Constants.mlx set. The documented run order (PVBatteryRead then Constants, per PV+Battery.docx: "Remember to run both this and the previous code") is therefore load-bearing, and running them in the other order silently loses the constants.
  • The filename is unqualified, so MATLAB resolves it against the current working directory. The script only works when run from a folder containing the workbook — which is why the workbook is duplicated into PV+Battery Simulink/.
  • The constants-detection heuristic is fragile: any genuine time series that happens to hold a single repeated value (e.g. an all-zero night-time signal over a short window) would be silently collapsed to a scalar.