MATLAB/Simulink code update
This commit is contained in:
parent
d2179071db
commit
d6b69acb17
28 changed files with 956 additions and 266 deletions
BIN
Simulink/Exp_CARNOT.mat
Normal file
BIN
Simulink/Exp_CARNOT.mat
Normal file
Binary file not shown.
BIN
Simulink/Exp_datasets_simid.sid
Normal file
BIN
Simulink/Exp_datasets_simid.sid
Normal file
Binary file not shown.
242
Simulink/Images/Exp1_simulation (1).svg
Normal file
242
Simulink/Images/Exp1_simulation (1).svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 96 KiB |
|
@ -133,14 +133,17 @@ classdef gp_mpc_system < matlab.System & matlab.system.mixin.Propagates
|
|||
real_p = vertcat(vec(DM(w)), vec(DM([obj.u_lags obj.y_lags])));
|
||||
disp("Starting optimization")
|
||||
tic
|
||||
%res = obj.casadi_solver('p', real_p, 'ubx', obj.ubx, 'lbx', obj.lbx);
|
||||
res = obj.casadi_solver('p', real_p, 'ubx', obj.ubx, 'lbx', obj.lbx);
|
||||
t = toc;
|
||||
disp(t)
|
||||
u = obj.Pel * full(res.x(1));
|
||||
u = 15000 * (20 - x);
|
||||
|
||||
% Update the u lags
|
||||
obj.u_lags = [u, obj.u_lags(2:end-1)];
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
function resetImpl(obj)
|
||||
|
|
|
@ -3,74 +3,58 @@ close all
|
|||
clc
|
||||
%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%% Load the experimental data
|
||||
exp_id = "Exp1";
|
||||
exp_path = strcat("../Data/Luca_experimental_data/", exp_id,".mat");
|
||||
wdb_path = strcat("../Data/Experimental_data_WDB/", exp_id, "_WDB.mat");
|
||||
|
||||
Exp_data = load(exp_path);
|
||||
load(wdb_path);
|
||||
|
||||
% Save the current WDB to the Simulink model import (since Carnot's input file is hardcoded)
|
||||
save('../Data/input_WDB.mat', 'Exp_WDB');
|
||||
|
||||
tin = Exp_WDB(:,1);
|
||||
|
||||
% The power trick: when the setpoint is larger than the actual temperature
|
||||
% the HVAC system is heating the room, otherwise it is cooling the room
|
||||
Setpoint = Exp_data.(exp_id).Setpoint.values;
|
||||
InsideTemp = mean([Exp_data.(exp_id).InsideTemp.values, Exp_data.(exp_id).LakeTemp.values], 2);
|
||||
OutsideTemp = Exp_data.(exp_id).OutsideTemp.values;
|
||||
|
||||
HVAC_COP = 3;
|
||||
Heating_coeff = sign(Setpoint - InsideTemp);
|
||||
Heating_coeff(Heating_coeff == -1) = -1 * HVAC_COP;
|
||||
|
||||
%% Set the run parameters
|
||||
|
||||
air_exchange_rate = tin;
|
||||
air_exchange_rate(:,2) = 1.0;
|
||||
|
||||
% Set the initial temperature to be the measured initial temperature
|
||||
t0 = Exp_data.(exp_id).InsideTemp.values(1);
|
||||
t0 = 23;
|
||||
|
||||
power = Exp_data.(exp_id).Power.values - 1.67 * 1000;
|
||||
runtime1 = 161400;
|
||||
runtime2 = 136200;
|
||||
runtime3 = 208200;
|
||||
runtime4 = 208200;
|
||||
runtime5 = 208200;
|
||||
runtime6 = 208200;
|
||||
runtime7 = 553800;
|
||||
|
||||
power = [tin Heating_coeff .* power];
|
||||
runtime = 24 * 3600;
|
||||
set_param('polydome', 'StopTime', int2str(runtime))
|
||||
Tsample = 900;
|
||||
steps = runtime/Tsample;
|
||||
tin = Tsample *(0:steps)';
|
||||
|
||||
prbs_sig = 2*prbs(8, steps+1)' - 1;
|
||||
COP = 5.0;
|
||||
Pel = 6300;
|
||||
|
||||
|
||||
% Turn down the air exchange rate when the HVAC is not running
|
||||
night_air_exchange_rate = 0.5;
|
||||
air_exchange_rate(abs(power(:, 2)) < 100, 2) = night_air_exchange_rate;
|
||||
power = [tin COP*Pel*prbs_sig(1:steps+1)];
|
||||
|
||||
%% Run the simulation
|
||||
% Note: The simlulink model loads the data separately, includes the
|
||||
% calculated solar position and radiations from pvlib
|
||||
load_system("polydome");
|
||||
set_param('polydome', 'StopTime', int2str(tin(end)));
|
||||
simout = sim("polydome");
|
||||
%% Simulate the model
|
||||
out = sim('polydome');
|
||||
|
||||
SimulatedTemp = simout.SimulatedTemp;
|
||||
%% Compare the simulation results with the measured values
|
||||
figure; hold on; grid minor;
|
||||
plot(tin, InsideTemp);
|
||||
plot(tin, OutsideTemp);
|
||||
plot(SimulatedTemp, 'LineWidth', 2);
|
||||
legend('InsideTemp', 'OutsideTemp', 'SimulatedTemp');
|
||||
%% For manual simulation running
|
||||
WeatherMeasurement = struct;
|
||||
WeatherMeasurement.data = squeeze(out.WeatherMeasurement.data)';
|
||||
WeatherMeasurement.time = out.WeatherMeasurement.time;
|
||||
|
||||
input = [power(:, 2:end) WeatherMeasurement.data];
|
||||
|
||||
x0=500;
|
||||
y0=300;
|
||||
width=1500;
|
||||
height=500;
|
||||
set(gcf,'position',[x0,y0,width,height]);
|
||||
title(exp_id);
|
||||
%title(sprintf('Night Air exchange rate %f', night_air_exchange_rate));
|
||||
Exp7_data = iddata(out.SimulatedTemp.data, input);
|
||||
|
||||
hold off;
|
||||
Exp7_table = array2table([input out.SimulatedTemp.data], 'VariableNames', {'Power', 'SolRad', 'OutsideTemp', 'SimulatedTemp'});
|
||||
|
||||
saveas(gcf, strcat(exp_id, '_simulation'), 'svg')
|
||||
writetable(Exp7_table, 'Exp7_table.csv')
|
||||
|
||||
%% Export simulated temperature to a .mat file for further use
|
||||
carnot_output_dir = strcat("../Data/CARNOT_output/",exp_id,"_carnot_temp.mat");
|
||||
save(carnot_output_dir, 'SimulatedTemp');
|
||||
%%
|
||||
save('Exp_CARNOT.mat', ...
|
||||
'Exp1_data', 'Exp1_table', ...
|
||||
'Exp2_data', 'Exp2_table', ...
|
||||
'Exp3_data', 'Exp3_table', ...
|
||||
'Exp4_data', 'Exp4_table', ...
|
||||
'Exp5_data', 'Exp5_table', ...
|
||||
'Exp6_data', 'Exp6_table', ...
|
||||
'Exp7_data', 'Exp7_table' ...
|
||||
)
|
||||
|
||||
data_train = merge(Exp1_data, Exp3_data, Exp5_data);
|
||||
data_test = merge(Exp2_data, Exp4_data, Exp6_data, Exp7_data);
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
classdef casadi_block < matlab.System & matlab.system.mixin.Propagates
|
||||
% untitled Add summary here
|
||||
%
|
||||
% This template includes the minimum set of functions required
|
||||
% to define a System object with discrete state.
|
||||
|
||||
properties
|
||||
% Public, tunable properties.
|
||||
|
||||
end
|
||||
|
||||
properties (DiscreteState)
|
||||
end
|
||||
|
||||
properties (Access = private)
|
||||
% Pre-computed constants.
|
||||
casadi_solver
|
||||
x0
|
||||
lbx
|
||||
ubx
|
||||
lbg
|
||||
ubg
|
||||
end
|
||||
|
||||
methods (Access = protected)
|
||||
function num = getNumInputsImpl(~)
|
||||
num = 2;
|
||||
end
|
||||
function num = getNumOutputsImpl(~)
|
||||
num = 1;
|
||||
end
|
||||
function dt1 = getOutputDataTypeImpl(~)
|
||||
dt1 = 'double';
|
||||
end
|
||||
function dt1 = getInputDataTypeImpl(~)
|
||||
dt1 = 'double';
|
||||
end
|
||||
function sz1 = getOutputSizeImpl(~)
|
||||
sz1 = [1,1];
|
||||
end
|
||||
function sz1 = getInputSizeImpl(~)
|
||||
sz1 = [1,1];
|
||||
end
|
||||
function cp1 = isInputComplexImpl(~)
|
||||
cp1 = false;
|
||||
end
|
||||
function cp1 = isOutputComplexImpl(~)
|
||||
cp1 = false;
|
||||
end
|
||||
function fz1 = isInputFixedSizeImpl(~)
|
||||
fz1 = true;
|
||||
end
|
||||
function fz1 = isOutputFixedSizeImpl(~)
|
||||
fz1 = true;
|
||||
end
|
||||
function setupImpl(obj,~,~)
|
||||
% Implement tasks that need to be performed only once,
|
||||
% such as pre-computed constants.
|
||||
|
||||
import casadi.*
|
||||
|
||||
T = 10; % Time horizon
|
||||
N = 20; % number of control intervals
|
||||
|
||||
% Declare model variables
|
||||
x1 = SX.sym('x1');
|
||||
x2 = SX.sym('x2');
|
||||
x = [x1; x2];
|
||||
u = SX.sym('u');
|
||||
|
||||
% Model equations
|
||||
xdot = [(1-x2^2)*x1 - x2 + u; x1];
|
||||
|
||||
% Objective term
|
||||
L = x1^2 + x2^2 + u^2;
|
||||
|
||||
% Continuous time dynamics
|
||||
f = casadi.Function('f', {x, u}, {xdot, L});
|
||||
|
||||
% Formulate discrete time dynamics
|
||||
% Fixed step Runge-Kutta 4 integrator
|
||||
M = 4; % RK4 steps per interval
|
||||
DT = T/N/M;
|
||||
f = Function('f', {x, u}, {xdot, L});
|
||||
X0 = MX.sym('X0', 2);
|
||||
U = MX.sym('U');
|
||||
X = X0;
|
||||
Q = 0;
|
||||
for j=1:M
|
||||
[k1, k1_q] = f(X, U);
|
||||
[k2, k2_q] = f(X + DT/2 * k1, U);
|
||||
[k3, k3_q] = f(X + DT/2 * k2, U);
|
||||
[k4, k4_q] = f(X + DT * k3, U);
|
||||
X=X+DT/6*(k1 +2*k2 +2*k3 +k4);
|
||||
Q = Q + DT/6*(k1_q + 2*k2_q + 2*k3_q + k4_q);
|
||||
end
|
||||
F = Function('F', {X0, U}, {X, Q}, {'x0','p'}, {'xf', 'qf'});
|
||||
|
||||
% Start with an empty NLP
|
||||
w={};
|
||||
w0 = [];
|
||||
lbw = [];
|
||||
ubw = [];
|
||||
J = 0;
|
||||
g={};
|
||||
lbg = [];
|
||||
ubg = [];
|
||||
|
||||
% "Lift" initial conditions
|
||||
X0 = MX.sym('X0', 2);
|
||||
w = {w{:}, X0};
|
||||
lbw = [lbw; 0; 1];
|
||||
ubw = [ubw; 0; 1];
|
||||
w0 = [w0; 0; 1];
|
||||
|
||||
% Formulate the NLP
|
||||
Xk = X0;
|
||||
for k=0:N-1
|
||||
% New NLP variable for the control
|
||||
Uk = MX.sym(['U_' num2str(k)]);
|
||||
w = {w{:}, Uk};
|
||||
lbw = [lbw; -1];
|
||||
ubw = [ubw; 1];
|
||||
w0 = [w0; 0];
|
||||
|
||||
% Integrate till the end of the interval
|
||||
Fk = F('x0', Xk, 'p', Uk);
|
||||
Xk_end = Fk.xf;
|
||||
J=J+Fk.qf;
|
||||
|
||||
% New NLP variable for state at end of interval
|
||||
Xk = MX.sym(['X_' num2str(k+1)], 2);
|
||||
w = {w{:}, Xk};
|
||||
lbw = [lbw; -0.25; -inf];
|
||||
ubw = [ubw; inf; inf];
|
||||
w0 = [w0; 0; 0];
|
||||
|
||||
% Add equality constraint
|
||||
g = {g{:}, Xk_end-Xk};
|
||||
lbg = [lbg; 0; 0];
|
||||
ubg = [ubg; 0; 0];
|
||||
end
|
||||
|
||||
% Create an NLP solver
|
||||
prob = struct('f', J, 'x', vertcat(w{:}), 'g', vertcat(g{:}));
|
||||
options = struct('ipopt',struct('print_level',0),'print_time',false);
|
||||
solver = nlpsol('solver', 'ipopt', prob, options);
|
||||
|
||||
obj.casadi_solver = solver;
|
||||
obj.x0 = w0;
|
||||
obj.lbx = lbw;
|
||||
obj.ubx = ubw;
|
||||
obj.lbg = lbg;
|
||||
obj.ubg = ubg;
|
||||
end
|
||||
|
||||
function u = stepImpl(obj,x,t)
|
||||
disp(t)
|
||||
tic
|
||||
w0 = obj.x0;
|
||||
lbw = obj.lbx;
|
||||
ubw = obj.ubx;
|
||||
solver = obj.casadi_solver;
|
||||
lbw(1:2) = x;
|
||||
ubw(1:2) = x;
|
||||
sol = solver('x0', w0, 'lbx', lbw, 'ubx', ubw,...
|
||||
'lbg', obj.lbg, 'ubg', obj.ubg);
|
||||
|
||||
u = full(sol.x(3));
|
||||
toc
|
||||
end
|
||||
|
||||
function resetImpl(obj)
|
||||
% Initialize discrete-state properties.
|
||||
end
|
||||
end
|
||||
end
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Simulink/polydome_python.slx
Normal file
BIN
Simulink/polydome_python.slx
Normal file
Binary file not shown.
|
@ -1,10 +0,0 @@
|
|||
clear all
|
||||
close all
|
||||
clc
|
||||
%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%% Load the existing GP
|
||||
addpath("../../Gaussiandome/Identification/Computation results/")
|
||||
load("Identification_Validation.mat")
|
||||
load("Gaussian_Process_models.mat")
|
|
@ -29,17 +29,20 @@ classdef weather_predictor < matlab.System
|
|||
num = 2;
|
||||
end
|
||||
function num = getNumOutputsImpl(~)
|
||||
num = 1;
|
||||
num = 2;
|
||||
end
|
||||
function dt1 = getOutputDataTypeImpl(~)
|
||||
function [dt1, dt2] = getOutputDataTypeImpl(~)
|
||||
dt1 = 'double';
|
||||
dt2 = 'double';
|
||||
|
||||
end
|
||||
function [dt1, dt2] = getInputDataTypeImpl(~)
|
||||
dt1 = 'double';
|
||||
dt2 = 'double';
|
||||
end
|
||||
function sz1 = getOutputSizeImpl(obj)
|
||||
sz1 = [obj.N 2];
|
||||
function [sz1, sz2] = getOutputSizeImpl(obj)
|
||||
sz1 = [1 2];
|
||||
sz2 = [obj.N 2];
|
||||
end
|
||||
function sz1 = getInputSizeImpl(~)
|
||||
sz1 = 1;
|
||||
|
@ -47,14 +50,16 @@ classdef weather_predictor < matlab.System
|
|||
function cp1 = isInputComplexImpl(~)
|
||||
cp1 = false;
|
||||
end
|
||||
function cp1 = isOutputComplexImpl(~)
|
||||
function [cp1, cp2] = isOutputComplexImpl(~)
|
||||
cp1 = false;
|
||||
cp2 = false;
|
||||
end
|
||||
function fz1 = isInputFixedSizeImpl(~)
|
||||
fz1 = true;
|
||||
fz1 = true;
|
||||
end
|
||||
function fz1 = isOutputFixedSizeImpl(~)
|
||||
function [fz1, fz2] = isOutputFixedSizeImpl(~)
|
||||
fz1 = true;
|
||||
fz2 = true;
|
||||
end
|
||||
|
||||
|
||||
|
@ -63,13 +68,29 @@ classdef weather_predictor < matlab.System
|
|||
% Perform one-time calculations, such as computing constants
|
||||
end
|
||||
|
||||
function w = stepImpl(obj,wdb_mat,timestamp)
|
||||
function [w, w_hat] = stepImpl(obj,wdb_mat,timestamp)
|
||||
disp(timestamp)
|
||||
% Implement algorithm. Calculate y as a function of input u and
|
||||
% discrete states.
|
||||
curr_idx = find(wdb_mat(:, 1) == timestamp);
|
||||
N_idx = (1:obj.N) + curr_idx;
|
||||
w = [wdb_mat(N_idx, 18) + wdb_mat(N_idx, 19), wdb_mat(N_idx, 7)];
|
||||
|
||||
|
||||
forecast_start = timestamp + obj.TimeStep;
|
||||
forecast_end = timestamp + obj.N * obj.TimeStep;
|
||||
|
||||
xq = forecast_start:obj.TimeStep:forecast_end;
|
||||
|
||||
weather_start_idx = find(wdb_mat(:, 1) <= timestamp, 1);
|
||||
weather_end_idx = find(wdb_mat(:, 1) >= forecast_end, 1);
|
||||
weather_idx = weather_start_idx:weather_end_idx;
|
||||
|
||||
solar_direct = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 18), timestamp);
|
||||
solar_diffuse = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 19), timestamp);
|
||||
outside_temp = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 7), timestamp);
|
||||
w = [solar_direct + solar_diffuse, outside_temp];
|
||||
|
||||
solar_direct = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 18), xq)';
|
||||
solar_diffuse = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 19), xq)';
|
||||
outside_temp = interp1(wdb_mat(weather_idx, 1), wdb_mat(weather_idx, 7), xq)';
|
||||
|
||||
w_hat = [solar_direct + solar_diffuse, outside_temp];
|
||||
end
|
||||
|
||||
function resetImpl(obj)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
function w = weather_predictor2(wdb_mat,timestamp, N)
|
||||
%WEATHER_PREDICTOR2 Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
curr_idx = find(wdb_mat(:, 1) == timestamp);
|
||||
N_idx = (1:N) + curr_idx;
|
||||
w = [wdb_mat(N_idx, 18) + wdb_mat(N_idx, 19), wdb_mat(N_idx, 7)];
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue