- Nghiên cứu, cải thiện chất lượng bộđiều khiển trước tác động của nhiễu đo. - Sử dụng mạng nơron để xấp xỉ mô hình chu trình PSA, so sánh với kết quả khi
sử dụng System Identification Toolbox.
- Sử dụng các giải thuật di truyền (GA) hay giải thuật bầy đàn (PSO) để tìm giá trị tối ưu thay vì sử dụng hàm fmincon.
- Vì chu trình PSA hoạt động mang tính chu kì và động học hệ thống diễn biễn theo sự kiện và thời điểm đóng mở các van, nghiên cứu và mở rộng với hệ rời rạc, hệ lai.
35
TÀI LIỆU THAM KHẢO
[1] PSE, “gPROMS - Home - Process Systems Enterprise” [Online]. Đường dẫn: https://www.psenterprise.com/products/gproms.
[2] AspenTech, “Aspen Adsorption” [Online]. Đường dẫn:
https://www.aspentech.com/en/products/pages/aspen-adsorption.
[3] Lennart Ljung, “System Identification Toolbox™ User's Guide”, MathWork, March 2018
[4] MATLAB, “Identifying Hammerstein-Wiener Models” [Online]. Đường dẫn: https://www.mathworks.com/help/ident/ug/identifying-hammerstein- wiener-models.html
[5] Victor H. B. Teles, Jornandes, Danilo Silva; “Pressure Swing Adsorption Technology using 5A Zeolite for the Removal of H2S in Fixed Bed Reactor”, Allen Institute for Artificial Intelligence, 2015
[6] ETH Zurich, “Multiparametric Toolbox 3.0 Function Reference”, December 9, 2013
[7] TS. Vũ Đình Tiến, “Thiết bị tạo khí Nitơ theo chu trình hấp phụthay đổi áp suất” [Poster], Viện Kĩ thuật hóa học, Đại học Bách Khoa Hà Nội.
[8] Hà Văn Hảo, Vũ Đình Tiến, “Mô phỏng quá trình làm việc của thiết bị tạo
khí nitơ bằng chu trình hấp phụthay đổi áp suất”, Tạp chí Xúc tác và Hấp phụ, No.3 (2015) 165-169
[9] Vũ Đình Tiến, Bài giảng về hấp phụ và chu trình hấp phụ, 2017
[10] Bitzer, M., “Model-based nonlinear tracking control of pressure swing adsorption plants.” In: Meurer, T., Graichen, K., Gilles, E.-D. (Eds.), Control and Observer Design for Nonlinear Finite and Infinite Dimensional Systems. Vol. 322/2005 of Lecture Notes in Control and Information Sciences, Springer Berlin / Heidelberg, pp. 403–418
[11]Bitzer, M., Zeitz, M., “Design of a nonlinear distributed parameter observer for a pressure swing adsorption plant”, Journal of Process Control 12 (4), 2002, 533 – 543
[12] Torre, V. D. L., Fox, V. G., Bandoni, J. A., Biegler, L. T., “Modelpredictive controller for periodic adsorption processes”. In: ENPROMER,2nd Mercosur Congress on Chemical Engineering 2005
[13] Harish Khajuria, Efstratios N. Pistikopoulos, “Dynamic modeling and explicit/multi-parametric MPC control of pressure swing adsorption systems”, Journal of Process Control 21 (2011) 151–163
[14] Nguyễn Doãn Phước, “Điều khiển dự báo theo mô hình”, Slide bài giảng, [Online]
36 [15]Jesse Y. Rumbo Morales,Guadalupe López López, Víctor M. Alvarado Martínez, Felipe de J. Sorcia Vázquez, Jorge A. Brizuela Mendoza, Mario Martínez García, “Parametric study and control of a pressure swing adsorption process to separate the water-ethanol mixture under disturbances”, Separation and Purification Technology 2020, 236 , 116214 [16] Dan Simon, “Optimal State Estimation: Kalman, H∞, and Nonlinear
Approaches”, Wiley-Interscience; 1st edition (June 23, 2006)
[17] Hoàng Minh Sơn, “Bài giảng Điều khiển quá trình nâng cao, Chương 4: Điều khiển dự báo (Model-based Predictive Control)", 2009
[18] Eisa Bashier M. Tayeb and A. Taifour Ali, “Comparison of some Classical PID and Fuzzy Logic Controllers”, International Journal of Scientific & Engineering Research, Volume 3, Issue 9, September-2012
[19] Phạm Văn Chính, Vũ Đình Tiến, Lê Quang Tuấn, “Nghiên cứu mô phỏng thiết bịtách khí ni tơ theo chu trình hấp phụ áp suất thay đổi (PSA) bằng phần mềm Aspen Adsorption”, Tạp chí Công Thương số 5 + 6 tháng 4/2018.
[20] Liang Tong, Pierre Bénard, Yi Zong, Richard Chahine, Kun Liu, Jinsheng Xiao, “Artificial neural network based optimization of a six-step two-bed pressure swing adsorption system for hydrogen purification”, Energy and AI 2021, 5 , 100075
37
PHỤ LỤC
A1. Các phương trình đặc trưng chính của mô hình động học hệ
thống PSA
Các phương trình đặc trưng chính của mô hình động học hệ thống PSA được sử dụng để lập trình chương trình trong gPROMS, được liệt kê dưới đây.
Phương trình cân bằng khối lượng:
�𝜀𝜀+ (1− 𝜀𝜀)𝜀𝜀𝑝𝑝�𝜕𝜕𝐶𝐶𝑖𝑖 𝜕𝜕𝜕𝜕 + 𝜕𝜕𝜕𝜕𝐶𝐶𝑖𝑖 𝜕𝜕𝜕𝜕 +𝜌𝜌𝑝𝑝(1− 𝜀𝜀)𝜕𝜕𝑞𝑞𝑖𝑖 𝜕𝜕𝜕𝜕 =𝜀𝜀𝐷𝐷𝑎𝑎𝑝𝑝 𝜕𝜕2𝐶𝐶𝑖𝑖 𝜕𝜕𝜕𝜕2
Phương trình cân bằng năng lượng:
𝜕𝜕�𝑇𝑇 ∑𝑁𝑁𝑐𝑐𝑐𝑐𝑐𝑐𝑎𝑎𝑖𝑖=1 𝐶𝐶𝑖𝑖�𝐶𝐶𝑎𝑎𝑖𝑖−𝑅𝑅�� 𝜕𝜕𝑡𝑡 +𝜕𝜕�𝑈𝑈𝑇𝑇 ∑𝑁𝑁𝑐𝑐𝑐𝑐𝑐𝑐𝑎𝑎𝑖𝑖=1 𝐶𝐶𝑖𝑖𝐶𝐶𝑎𝑎𝑖𝑖� 𝜕𝜕𝜕𝜕 +𝜌𝜌𝑝𝑝𝐶𝐶𝑝𝑝𝑠𝑠1−𝜀𝜀𝜀𝜀 𝜕𝜕𝑇𝑇𝜕𝜕𝑡𝑡 +𝜌𝜌𝑝𝑝1−𝜀𝜀𝜀𝜀 ∑ 𝜕𝜕𝑚𝑚𝑖𝑖 𝜕𝜕𝑡𝑡 ∆𝐻𝐻𝑖𝑖 𝑁𝑁𝑐𝑐𝑐𝑐𝑐𝑐𝑎𝑎 𝑖𝑖=1 = 𝜆𝜆𝜕𝜕𝜕𝜕𝜕𝜕2𝑇𝑇2
Trong đó, 𝐶𝐶𝑝𝑝 là nhiệt dung đẳng áp pha khí [J/mol.K]. 𝐶𝐶𝑝𝑝 là nhiệt dung riêng chất hấp phụ [J/kg.K]. 𝑅𝑅 là hằng số khí lý tưởng [J/mol.K]. 𝜆𝜆 là hệ số phân tán nhiệt dọc trục [W/m.K]. ∆𝐻𝐻 là nhiệt của quá trình hấp phụ[J/mol].
Phương trình cân bằng động lượng:
−𝜕𝜕𝑀𝑀𝜕𝜕𝜕𝜕 =150𝜇𝜇(1− 𝜀𝜀)2 𝜀𝜀3𝐷𝐷𝑝𝑝3 𝜕𝜕 +1.75(1− 𝜀𝜀)∑ 𝐶𝐶𝑖𝑖𝑀𝑀𝑀𝑀𝑖𝑖 𝑁𝑁𝑐𝑐𝑐𝑐𝑐𝑐𝑎𝑎 𝑖𝑖=1 𝜀𝜀3𝐷𝐷𝑝𝑝 |𝜕𝜕|𝜕𝜕 Phương trình tốc độ hấp phụ: 𝜕𝜕𝑞𝑞𝑖𝑖 𝜕𝜕𝜕𝜕 =𝐾𝐾𝐿𝐿𝐷𝐷𝐹𝐹𝑖𝑖(𝑞𝑞𝑖𝑖∗− 𝑞𝑞𝑖𝑖) Với 𝐾𝐾𝐿𝐿𝐷𝐷𝐹𝐹 =𝐾𝐾 là hằng số tỷ lệ LDF
Phương trình đẳng nhiệt hấp phụ Langmuir:
𝑞𝑞𝑖𝑖∗ 𝑞𝑞𝑖𝑖𝑚𝑚𝑎𝑎𝑥𝑥 =𝑀𝑀𝑖𝑖𝐾𝐾𝑖𝑖𝐶𝐶𝑖𝑖𝑅𝑅𝑇𝑇 �1− � �𝑞𝑞𝑞𝑞𝑖𝑖∗ 𝑖𝑖𝑚𝑚𝑎𝑎𝑥𝑥� 𝑁𝑁𝑐𝑐𝑐𝑐𝑐𝑐𝑎𝑎 𝑖𝑖=1 � 𝑎𝑎𝑖𝑖
Với 𝑞𝑞𝑖𝑖𝑚𝑚𝑎𝑎𝑥𝑥 là tải lượng hấp phụcân bằng lớn nhất [mol/kg].
A2. Bộ dữ liệu chạy trên Aspen Adosorption để huấn luyện mạng
nơron ANN xấp xỉ
Áp suất hấp
phụ (p – bar) Thphụời gian hấ (t - s) p (Pur) Độ tinh khiết Độ%) thu hồi (Rec -
3.045 120 0.949470788 82.4645 3.045 110 0.9503 80.8887 3.045 130 0.948542083 84.1332 3.045 135 0.948041475 85.0099 3.045 105 0.950675028 80.1324 3.145 120 0.949336749 80.712
38 3.245 120 0.949172203 79.1436 3.345 120 0.948982181 77.7346 3.445 120 0.948760442 76.4643 2.945 120 0.949593795 84.4313 2.845 120 0.949682595 86.6744 2.745 120 0.94973753 89.0329 2.645 120 0.949765994 91.662 2.645 110 0.950394109 90.372 2.745 110 0.950416756 87.6557 2.845 110 0.950412564 85.2182 2.945 110 0.950373893 82.9096 3.145 110 0.950212681 79.0892 3.245 110 0.950093038 77.4789 3.345 110 0.949945833 76.0325 3.445 110 0.949765482 74.7286 3.445 130 0.947644609 78.2999 3.345 130 0.947909791 79.5346 3.245 130 0.948145094 80.9044 3.145 130 0.94835747 82.4293 2.945 130 0.948717702 86.0449 2.845 130 0.948861027 88.2227 2.745 130 0.948971507 90.503 2.645 130 0.949056211 93.046 2.645 135 0.948671822 93.781 2.745 135 0.948557491 91.28 2.845 135 0.948417506 89.0381 2.945 135 0.948245124 86.8935 3.145 135 0.947830001 83.3311 3.245 135 0.947592 81.8288 3.345 135 0.947333747 80.4796 3.445 135 0.947046339 79.2636 3.445 105 0.950224241 73.8945 3.345 105 0.950384846 75.2145 3.245 105 0.950511744 76.679 3.145 105 0.950610201 78.3098 2.945 105 0.950726556 82.1801
39
2.845 105 0.95074194 84.5217
2.745 105 0.950722664 87.0004
2.645 105 0.95067647 89.761
A3. AMSimulation để kết nối Aspen Adsorption với MATLAB
function AMSimulation(block)
%%
%% Block parameters are:
%% 1. Input file name (string wrapped in single quotes) i.e. 'SumDyn.acmf'
%%
%% 2. AM application type (string wrapped in single quotes): %% Aspen Custom Modeler = 'ACM Application'
%% Aspen Dynamics = 'AD Application' %% Aspen Adsim = 'ADS Application' %% Aspen Chromatography = 'CHM Application' %%
%% 3. Number of inputs to block (integer) i.e. 2 %%
%% 4. Backslash \ separated list of AM variable names in input port number
%% order (string wrapped in single quotes) i.e. 'B1.T,B3.SubBlock.Flow'
%% The variable must exist or the run will be terminated.
%% If in a specific unit of measurement use the pipe symbol to append
%% the units i.e. 'B1.T|K,B3.SubBlock.Flow|kmol/hr'
%% The units of measurement must exists or the run will be terminated.
%%
%% 5. Number of outputs from block (integer) i.e. 1 %%
%% 6. Backslash \ separated list of AM variable names in output port %% number order (string wrapped in single quotes) i.e. 'B3.OutFlow' %% If in a specific unit of measurement use the pipe symbol to append
%% the units i.e. 'B3.OutFlow|lbmol/min' %%
%% 7. Make AM application visible during run (logical) i.e. true %%
%% 8. Filter for variables marked as inputs/outputs (logical) i.e. true
%%
%% 9. Always open Aspen Modeler on simulink model open (logical) i.e. true %% setup(block); %endfunction %% Function: setup =================================================== %% Abstract:
%% Set up the S-function block's basic characteristics such as: %% - Input ports
%% - Output ports %% - Dialog parameters %% - Options
%%
%% C-Mex S-function counterpart: mdlInitializeSizes %%
40
%disp('AMSimulation: Setup called...');
%global AMObjects[10]
% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic; block.SetPreCompOutPortInfoToDynamic;
% Do not persist UserData in input file
%set_param ( gcb, 'UserDataPersistent', 'off' );
% Register parameters
block.NumDialogPrms = 9; % Input file, Application type, #Inputs, InputVarList, #Outputs, OutputVarList, VisibleAM, FilterVars,
OpenAMOnOpen
block.DialogPrmsTunable =
{'Nontunable','Nontunable','Nontunable','Nontunable','Nontunable','Non tunable','Nontunable','Nontunable','Nontunable'};
% Register number of ports
block.NumInputPorts = fix(block.DialogPrm(3).Data); block.NumOutputPorts = fix(block.DialogPrm(5).Data);
% Override input port properties
for ii = 1:fix(block.DialogPrm(3).Data) block.InputPort(ii).DatatypeID = 0; %double block.InputPort(ii).Complexity = 'Real'; block.InputPort(ii).SamplingMode = 0; block.InputPort(ii).Dimensions = 1; end
% Override output port properties
for ii = 1:fix(block.DialogPrm(5).Data) block.OutputPort(ii).DatatypeID = 0; %double block.OutputPort(ii).Complexity = 'Real'; block.OutputPort(ii).SamplingMode = 0; block.OutputPort(ii).Dimensions = 1; end %% --- %% Register sample times
%% ---
% [0 offset] : Continuous sample time
% [positive_num offset] : Discrete sample time
%
% [-1, 0] : Port-based sample time
% [-2, 0] : Variable sample time
block.SampleTimes = [-1, 0];
%% --- %% Options
%% ---
% Specify if Accelerator should use TLC or call back into
% M-file
block.SetAccelRunOnTLC(false);
%% --- %% Register methods called during update diagram/compilation
%% ---
block.RegBlockMethod('CheckParameters', @CheckUserParameters);
%% --- %% Register methods called at run-time
%% ---
%block.RegBlockMethod('InitializeConditions',
@InitializeConditions);
block.RegBlockMethod('Start', @Start); block.RegBlockMethod('Outputs', @Outputs);
block.RegBlockMethod('SimStatusChange', @SimStatusChange); block.RegBlockMethod('Terminate', @Terminate);
41 %endfunction %% --- %% Local functions %% --- function CheckUserParameters(block) %% %% CheckParameters: %% Required : No
%% Functionality : Called in order to allow validation of %% block's dialog parameters. User is %% responsible for calling this method
%% explicitly at the start of the setup method %% C-Mex counterpart: mdlCheckParameters
%% %endfunction function Start(block) %% %% Start: %% Required : No
%% Functionality : Called in order to initalize state and work %% area values
%% C-Mex counterpart: mdlStart %%
%disp('AMSimulation: Start called...');
%last check
% if strcmp( get_param(gcb,'Parameters'), '' )
% error( 'AMSimulation: Blank block parameters, open configure form!' );
% end
if strcmp( block.DialogPrm(1).Data, '<inputfilepath>' )
error( 'AMSimulation: Aspen Modeler input file not defined!' ); end
if strcmp( block.DialogPrm(4).Data, '[Undefined]' )
error( 'AMSimulation: Aspen Modeler input variables not defined!'
); end
if strcmp( block.DialogPrm(6).Data, '[Undefined]' )
error( 'AMSimulation: Aspen Modeler output variables not defined!'
); end
% Create instance of Aspen Modeler controller if not already loaded
global AMControl
if ~strcmp( class(AMControl), 'COM.AMSimulation_Control' ) AMControl = actxserver ( 'AMSimulation.Control' );
end
% Persist the AM controller for other calls
%(why does UserData get changed when you open another block?)
%set_param( gcb, 'UserData', AMControl );
%AMObjects(block.DialogPrm(8).Data) = AMControl;
% Start up the AM application and set up input/output variables
%disp('AMSimulation: Loading model...');
try
bRet = invoke( AMControl, 'StartRun', pwd, block.DialogPrm(1).Data, block.DialogPrm(2).Data, block.DialogPrm(3).Data, block.DialogPrm(4).Data, block.DialogPrm(5).Data, block.DialogPrm(6).Data, block.DialogPrm(7).Data );
42
error( lasterr ); end
%disp('AMSimulation: Loaded model...');
%endfunction
function Outputs(block)
%%
%% Outputs:
%% Required : Yes
%% Functionality : Called to generate block outputs in %% simulation step
%% C-Mex counterpart: mdlOutputs %%
%disp(strcat('AMSimulation: Output called...
',num2str(block.CurrentTime)));
% Get persisted AM controller
global AMControl
%global AMObjects[10]
%(why does UserData get changed when you open another block?)
%AMControl = get_param( gcb, 'UserData' );
%AMControl = AMObjects(block.DialogPrm(8).Data);
%do we have a valid block stored
if strcmp(class(AMControl),'COM.AMSimulation_Control') try
% Send new input values
invoke( AMControl, 'UpdateInputs', block.DialogPrm(1).Data ); for ii = 1:fix(block.DialogPrm(3).Data)
if invoke( AMControl, 'SetInputValue', ii,
block.InputPort(ii).Data, block.DialogPrm(1).Data ) == false error( 'AMSimulation: Could not send new inputs!' ); end
end
% Execute run
if invoke( AMControl, 'Run', block.CurrentTime, block.DialogPrm(1).Data ) == false
error( 'AMSimulation: Could not execute run!' ); end
% Get new output values
for ii = 1:fix(block.DialogPrm(5).Data)
block.OutputPort(ii).Data = invoke( AMControl,
'GetOutputValue', ii, block.DialogPrm(1).Data ); end
catch
error( lasterr ); end
else
error( 'AMSimulation: Invalid object in store!' ); end %endfunction function SimStatusChange(block, s) %% %% SimStatusChange: %% Required : No
%% Functionality : Called when simulation goes to pause mode %% or continnues from pause mode
%% C-Mex counterpart: mdlSimStatusChange %%
% if s == 0
% disp('AMSimulation: Pause has been called...'); % elseif s == 1
% disp('AMSimulation: Continue has been called...'); % end
43 %endfunction function Terminate(block) %% %% Terminate: %% Required : Yes
%% Functionality : Called at the end of simulation for cleanup %% C-Mex counterpart: mdlTerminate
%%
%disp('AMSimulation: Terminate called...');
% Get persisted AM controller
global AMControl
%global AMObjects[10]
%(why does UserData get changed when you open another block?)
%AMControl = get_param( gcb, 'UserData' );
%AMObjects(block.DialogPrm(8).Data) = AMControl;
if strcmp(class(AMControl),'COM.AMSimulation_Control')
% Shutdown AM instance
invoke( AMControl, 'Terminate', block.DialogPrm(1).Data );
% Delete control object if no other sessions are loaded
if invoke( AMControl, 'SessionCount' ) == 0 AMControl.delete
end
end
%endfunction
A4. Chương trình bộđiều khiển MPC trên MATLAB
Chương trình chính:
clear; clc; close all;
global LinearParams;
load('LinearParamsData.mat');
global PSA_Ident InputNonLinear OutputNonLinear; load('PSA_Model.mat'); PSA_Ident = PSA.PSA_Ident; InputNonLinear = PSA.InputNonLinear; OutputNonLinear= PSA.OutputNonLinear; global MPC KF ref_line; MPC = MPC_Parameters; KF = KF_Params; ref_line = 0.955; Ts = 1; Tend = 20;
global xk uk ukm1 y0_linear uk_NonLinear ref_lin; xk = 0; x_hat_km1 = KF.xhat0; P_km1 = KF.P0; ukm1 = 0; uk = 0; uk_NonLinear = InverseInputNonLinear(uk); num = cell2mat(PSA_Ident.B); den = cell2mat(PSA_Ident.F); y0_linear = 0; y_store = []; u_store = [uk_NonLinear]; sys = 'test01_2015b';
44 load_system(sys); ref = 0.955; ref_lin = InverseOutputNonLinear(ref); for (k = 1 : Tend) sim(sys); y_lin_k = InverseOutputNonLinear(y_linear(end)); MPC.y_lin_store = [MPC.y_lin_store, y_lin_k];
[x_hat_k, P_k] = KalmanFilter(x_hat_km1, P_km1); MPC.x_new = [x_hat_k-x_hat_km1; y_lin_k(end)];
uk = MPC_Controller;
MPC.u_store = [MPC.u_store, uk];
uk_NonLinear = InverseInputNonLinear(uk); u_store = [u_store, uk_NonLinear];
x_hat_km1 = x_hat_k; P_km1 = P_k; y0_linear = y_linear(end);
y_store = [y_store, y_real(end)];
end
sim(sys);
y_store = [y_store, y_real(end)]; figure;
time_k = [0, 1:Tend];
plot(time_k, ref*ones(size(y_store)), '--','linewidth', 2); hold on;
plot(time_k, y_store, 'linewidth', 2); grid on;
title('Purity')
legend('Setpoint', 'Actual'); figure;
stairs(time_k, u_store, 'linewidth', 2); title('Control input')
grid on;
Thống số bộ lọc Kalman
function KF = KF_Params() Q = diag([0.01 0.01 0.01]); R = 1e-4;
xhat0 = [1e-3; 1e-3; 1e-3]; P0 = diag([1e-4 1e-4 1e-4]); KF.Q = Q; KF.R = R; KF.xhat0 = xhat0; KF.P0 = P0; end Tính toán bộ lọc Kalman
function [x_hat_k, P_k] = KalmanFilter(x_hat_km1, P_km1)
global KF MPC LinearParams; Q = KF.Q; R = KF.R; u_km1 = MPC.u_store(end); y_lin_k = MPC.y_lin_store(end); nx = LinearParams.nx; A_lin = LinearParams.A_lin; B_lin = LinearParams.B_lin; C_lin = LinearParams.C_lin;
45
% time update
x_hat_k_minus = A_lin * x_hat_km1 + B_lin * u_km1; P_k_minus = A_lin * P_km1 * A_lin' + Q;
% measurement update
Kk = P_k_minus * C_lin' * inv(C_lin*P_k_minus*C_lin' + R); x_hat_k = x_hat_k_minus + Kk * (y_lin_k - C_lin*x_hat_k_minus); P_k = (eye(nx) - Kk * C_lin)*P_k_minus; end Bộđiều khiển MPC function uk = MPC_Controller() global MPC LinearParams; Ny = MPC.Ny; Nu = MPC.Nu; nx = LinearParams.nx; ny = LinearParams.ny; nu = LinearParams.nu; u_km1 = MPC.u_store(end); % cost function CostFunc = @MPC_CostFunc;
% solve cost function
% Delta_U_vec = fminsearch(CostFunc, repmat(u_km1, Nu, 1));
nonlcon = @MPC_Contranints;
Delta_U_vec = fmincon(CostFunc, zeros(nu*Nu, 1), [], [], [], [], [], [], nonlcon);
delta_u_k = Delta_U_vec(1:nu); uk = u_km1 + delta_u_k;
end
function [c, ceq] = MPC_Contranints(Delta_U_vec) Delta_U_vec = Delta_U_vec(:);
global MPC LinearParams; Nu = MPC.Nu;
u_km1 = MPC.u_store(end); nu = LinearParams.nu;