Extracting State-Space Matrices
Use state-space export to create a linearized state-space model corresponding to a COMSOL Multiphysics model. You can export the matrices of the state-space form directly to the MATLAB® workspace with the command mphstate.
This section includes information about The State-Space System, how to Extract State-Space Matrices and Set Linearization Points and has an Extracting State-Space Matrices.
The State-Space System
A state-space system is the mathematical representation of a physical model. The system consistent in an ODE linking input, output, and state-space variable. A dynamic system can be represented with the following system:
An alternative representation of the dynamic system is:
where x is the state variable vector.
If the components of the mass matrix MC are small, it is possible to approximate the dynamic state-space model with a static model, where :
Let Null be the PDE constraint null-space matrix and ud a particular solution fulfilling the constraints. The solution vector U for the PDE problem can then be written
where u0 is the linearization point, which is the solution stored in the sequence once the state-space export feature is run.
Choosing the Input
The input parameters should contain all parameters that are of interest as input to the model. Moreover, if you have any settings in a model that are connected to the degrees of freedom, like a constraint condition or a spring condition. These have to be declared as input in your state-space system. When solving the state-space system in MATLAB, subtract to these inputs the initial value of the corresponding DOF, as it is done in the example Extracting State-Space Matrices.
Extract State-Space Matrices
The function mphstate requires that the input variables, output variables, and the list of the matrices to extract in the MATLAB workspace are all defined:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out);
where <soltag> is the solver node tag used to assemble the system matrices listed in the cell array out, and <input> and <output> are cell arrays containing the list of the input and output variables, respectively.
The output data str returned by mphstate is a MATLAB structure and the fields correspond to the assembled system matrices.
The input variables need to be defined as parameters in the COMSOL model. The output variables are defined as domain point probes or global probes in the COMSOL model.
The system matrices that can be extracted with mphstate are listed in the table:
To extract sparse matrices set the property sparse to on:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'sparse', 'on')
To keep the state-space feature node, set the property keepfeature to on:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'keepfeature', 'on')
Set Linearization Points
mphstate uses linearization points to assemble the state-space matrices. The default linearization point is the current solution provided by the solver node, to which the state-space feature node is associated. If there is no solver associated to the solver configuration, a null solution vector is used as a linearization point unless you manually set the linearization point to an existing solution.
You can manually select the linearization point to use. Use the initmethod property to select a linearization point:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'initmethod', method)
where method corresponds to the type of linearization point — the initial value expression ('init') or a solution ('sol').
To set the solution to use for the linearization point, use the property initsol:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'initsol', <initsoltag>)
where <initsoltag> is the solver tag to use for a linearization point. You can also set the initsol property to 'zero', which corresponds to using a null solution vector as a linearization point. The default is the current solver node where the assemble node is associated.
For continuation, time-dependent, or eigenvalue analyses you can set which solution number to use as a linearization point. Use the solnum property:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'solnum', <solnum>)
where <solnum> is an integer value corresponding to the solution number. The default value is the last solution number available with the current solver configuration.
If there is a solver associated to the solver configuration <soltag>, you need to extract the matrices after the Dependent Variables node in the solver configuration, to proceed use the property extractafter as in the command below:
str = mphstate(model, <soltag>, 'input', <input>, ...
'output', <output>, 'out', out, 'solnum', <solnum>, ...
'extractafter', <vtag>)
where <vtag> is the tag of the Dependent Variable node.
Simulation Using the Control System Toolbox
The Control System Toolbox makes it possible to analyze state-space models in MATLAB for control design and to simulate such systems.
State-space models can be defined using the ss and sparss functions. The sparss function can be used if the state-space matrices are sparse. The system can be simulated using the lsim function. In order to create a reduced-order system using MATLAB, you can use the balred function. This function only accepts the use of full matrices. Hence, the function ss is used for defining the state-space system in MATLAB. Note that calling the function ss with argument matrices that are sparse results in a set of warnings. These warnings can be ignored.
The code below show how to use the Control System Toolbox to solve a dynamic system from the A, B, C, and D matrices obtained using mphstate:
sys = ss(M.A, M.B, M.C, M.D);
u = repmat(<input>, length(<tspan>), 1);
[y,t] = lsim(sys, u, t);
where <input> is the input vector of the state space system, and <tspan> is the time step list.
You can obtain a reduced-order model using the balred function.
redsys = balred(sys, <order>);
[y,t] = step(redsys, <tfinal>);
where <order> is the desired order reduction, and <tfinal> the simulation end time.
Extracting State-Space Matrices
In this section you will find an example that illustrates how to use the mphstate function to extract the state-space matrices.
The problem studied here is a heat transfer model set with a heat source. In the expected state-space system, the heat source is set as an input. The temperature at a specified location is used as the output. This tutorial shows how to extract the state-space matrices and solve the system using the MATLAB functions.
This is the same problem solved as in Extracting Reduced-Order State-Space Matrices, so you can compare the solution and computational performance when solving the problem with reduced-order model state-space system matrices.
First, load the model model_tutorial_llmatlab from the Application Library:
model = mphopen('model_tutorial_llmatlab');
This model is used as the base model for the documentation tutorial. The geometry, mesh, and physics are set, but for this specific problem you need to edit the model to use parameters for the initial and external temperatures because they will be used later in the state-space matrices export:
power = 30; Temp = 300; Text = 300; T0 = 293.15;
model.param.set('power', power);
model.param.set('Temp', Temp);
model.param.set('T0', T0);
model.param.set('Text', Text);
comp1 = model.component('comp1');
ht = comp1.physics('ht');
ht.feature('init1').set('Tinit', 'T0');
ht.feature('hf1').set('Text', 'Text');
Set the mesh size in order to keep the size of the matrices low:
comp1.mesh('mesh1').autoMeshSize(7);
Next, add a time-dependent study:
std = model.study.create('std');
time = std.feature.create('time','Transient');
time.set('tlist','range(0,1,20)');
time.set('usertol',true);
time.set('rtol','1e-4');
Add a domain point probe plot, which will define the output of the state-space system:
pdom = comp1.probe.create('pdom', 'DomainPoint');
pdom.model('comp1');
pdom.set('coords3',[1e-2 1e-2 1e-2]);
Run the study and create a plot group to display the probe:
mphrun(model);
pg1 = model.result.create('pg1', 'PlotGroup1D');
glob1 = pg1.create('glob1', 'Global');
glob1.set('expr', 'comp1.ppb1');
Extract the state-space system matrices Mc, MA, MB, C, and D of the model, with power, Temp, and Text as inputs and the probe evaluation comp1.ppb1 as the output:
M = mphstate(model,'sol1','out',{'Mc','MA','MB','C','D'},...
'input',{'power','Temp','Text'},...
   'output','comp1.ppb1');
Set the input power parameter and the reference temperature:
input = [power Temp-T0 Text-T0];
Notice that some of the input value are subtracted with the initial condition. This is because these inputs are directly linked to the temperature degree of freedom using a constraint condition.
func = @(t,x) M.MA*x + M.MB*input';
Set the solver options for the mass and the Jacobian:
opt = odeset('mass',M.Mc,'jacobian',M.MA);
It is not required to define the Jacobian, but doing so speeds up the simulation.
The state-space formulation that uses the mass matrix is prepared to use sparse matrices and can often be simulated much faster. In order to simulate systems that involve a mass matrix on the left-hand side, you must switch to one of the simulation functions that support a mass matrix. Such MATLAB functions are ode15s, ode23s, and ode23t. ode15s and ode23t can solve problems with a singular mass matrix. Compute the state-space system with the extracted matrices,
[t,x] = ode23s(func,0:1:20,zeros(size(M.MA,1),1),opt);
y = M.C*x';
y = y+T0;
Compare the solution computed with the system and the one computed with COMSOL Multiphysics (see Figure 4-1):
plot(t,y,'r+');
hold on;
mphplot(model,'pg1');
Figure 4-1: Temperature distribution computed with the state-space system (red marker) and COMSOL Multiphysics (blue line).
Evaluate the steady-state temperature value:
G = M.D-M.C*(inv(M.MA))*M.MB;
y_inf = full(G*input');
y_inf = y_inf + T0
For some types of control system design, the use of the matrices A, B, C, and D are commonly used. Extract the state-space system matrices A, B, C, and D of the model with power, Temp, and Text as inputs and the probe evaluation comp1.ppb1 as the output:
M2 = mphstate(model,'sol1','out',{'A','B','C','D'},...
'input',{'power','Temp','Text'},...
   'output','comp1.ppb1');
Compute the state-space system with the extracted matrices,
func = @(t,x) M2.A*x + M2.B*input';
[t,x] = ode45(func,0:1:20,zeros(size(M2.A,1),1));
y2 = M2.C*x';
y2 = y2+T0;
Compare the solution computed with the previous system (see Figure 4-2):
plot(t,y2,'k.')
Figure 4-2: Temperature distribution computed with the state-space system 1 (red '+' marker), state-space system without mass matrix (black '.' marker), and COMSOL Multiphysics (blue line).
Code for use with MATLAB®
model = mphopen('model_tutorial_llmatlab');
power = 30; Temp = 300; Text = 300; T0 = 293.15;
model.param.set('power', power);
model.param.set('Temp', Temp);
model.param.set('T0', T0);
model.param.set('Text', Text);
comp1 = model.component('comp1');
ht = comp1.physics('ht');
ht.feature('init1').set('Tinit', 'T0');
ht.feature('hf1').set('Text', 'Text');
std = model.study.create('std');
comp1.mesh('mesh1').autoMeshSize(7);
time = std.feature.create('time','Transient');
time.set('tlist','range(0,1,20)');
time.set('usertol',true);
time.set('rtol','1e-4');
pdom = comp1.probe.create('pdom', 'DomainPoint');
pdom.model('comp1');
pdom.set('coords3',[1e-2 1e-2 1e-2]);
std.run;
pg1 = model.result.create('pg1', 'PlotGroup1D');
glob1 = pg1.create('glob1', 'Global');
glob1.set('expr', 'comp1.ppb1');
M = mphstate(model,'sol1','out',{'Mc','MA','MB','C','D'},...
'input',{'power','Temp','Text'},'output','comp1.ppb1');
input = [power Temp-T0 Text-T0];
func = @(t,x) M.MA*x + M.MB*input';
opt = odeset('mass',M.Mc,'jacobian',M.MA);
[t,x] = ode23s(func,0:1:20,zeros(size(M.MA,1),1),opt);
y = M.C*x';
y = y+T0;
plot(t,y,'r+');
hold on;
mphplot(model,'pg1');
G = M.D-M.C*(inv(M.MA))*M.MB;
y_inf = full(G*input');
y_inf = y_inf + T0
M2 = mphstate(model,'sol1','out',{'A','B','C','D'},...
'input',{'power','Temp','Text'},...
   'output','comp1.ppb1');
func = @(t,x) M2.A*x + M2.B*input';
[t,x] = ode45(func,0:1:20,zeros(size(M2.A,1),1));
y2 = M2.C*x';
y2 = y2+T0;
plot(t,y2,'k.')