I tried to connect a 2-dimensional component array to a 1-dimensional component array including 1-dimensional connectors, but when checking the model, there is an error showing unmatched dimensions.
But I could connect a 1-dimensional component array to a component including 1-dimensional connectors,
So Why can't this work for multi-dimensional situations?
Did I do it wrong?
I checked the code, it seems I can't use
connect(tubeWall.port_b,surface.q_port);
but if I use the following code, it works fine.
for i in 1:x loop
for j in 1:y loop
connect(tubeWall[i].port_b[j], surface[i,j].q_port);
end for;
end for;
I did more test, here is the test code which worked fine:
model Unnamed
gain_1[3] gain_1_1
Modelica.Blocks.Sources.Sine[3,3] sine
Modelica.Blocks.Math.Cos[3,3] cos
equation
connect(sine.y, gain_1_1.u);
connect(gain_1_1.y, cos.u);
end Unnamed;
model gain_1
Modelica.Blocks.Math.Gain[3] gain
Modelica.Blocks.Interfaces.RealOutput[3] y
Modelica.Blocks.Interfaces.RealInput[3] u
equation
connect(gain.y, y)
connect(u, gain.u)
end gain_1;
Here is the screenshot of the connections:
So it seems the idea is right, but I am not sure why it doesn't work in my model. Hope someone could give a hint or direction of the unmatched error in my model.
Quoting Fritzon's Principles of object-oriented modeling and simulation with Modelica 3.3:
The connect contruct can be used to directly connect arrays of
connectors. For such array connections the following holds:
The array dimensions of the connected arrays of connectors must match
Each corresponding pair of elements is connected as a pair of scalar connectors
That is, referring to connect(tubeWall.port_b,surface.q_port);
it does not know which dimension of surface[:,:] goes to tubeWall[:] and which to port_b[:]
the for loop works, because you are taking over the task of connecting the pair of elements as scalar connectors
My suggestion for your modeling task is that you create an interface block to put between surface and tubeWall, in which you implement the element-wise connections the way they should be. The connection between surface and interface might then look like:
connect(surface, interface.surfacePort);
I played around to see if I can figure it out. Here three points that might bring you closer to a canonical answer on why there's a different behavior between physical connections (thermal, in your case) and signal connections (Real input/output, in your case):
Real input/output are causal, and declared differently than physical connectors
connector RealInput = input Real "'input Real' as connector" annotation (...);
connector PhysConnector
Real pt;
flow Real flw;
annotation (...);
end PhysConnector;
Real input/output look more like functions than connectors. I suppose the rule The array dimensions of the connected arrays of connectors must match does not apply/is not enforced for them. I can think of different reasons for this; two of them could be:
There's a general accepted framework to deal with tables, the same way the majority of us agree that looking at a geographical map the top-left corner is north-west. So the connections are sorted automatically according to the sequence: 1st dim, 2nd dim, 3rd dim,... Multidimensional physical connections on the other hand might represent all sorts of scenarios. Better leave the model designer the responsibility to build it up correctly
Real input/output generate one assignment instead of a set of equations, therefore they don't mess up too much with the sorting algorithms when figuring out the causality of the system
I tried eventually to test a standard connector with only a potential variable, to see if the problem was due to the two equations generated when also a flow variable is present. The flat Modelica shows there's only one equation generated (as expected), but still the connection matrix[:,:],array[:].array[:] is not allowed.
package MultidimConnections
connector RealConnector
Real r;
annotation(Icon(coordinateSystem(preserveAspectRatio=false)),Diagram(coordinateSystem(preserveAspectRatio=false)));
end RealConnector;
partial model RealInterface
RealConnector realConnector annotation(Placement(transformation(extent={{90,-10},{110,10}})));
annotation(Icon(coordinateSystem(preserveAspectRatio=false),graphics={Rectangle(extent={{-100,100},{100,-100}},lineColor={28,108,200},fillColor={170,213,255},fillPattern=FillPattern.None)}),Diagram(coordinateSystem(preserveAspectRatio=false)));
end RealInterface;
model Source
extends RealInterface;
parameter Real k = 0;
equation
k = realConnector.r;
annotation(Icon(coordinateSystem(preserveAspectRatio=false),graphics={Rectangle(extent={{-80,80},{80,-60}},lineColor={28,108,200},fillColor={151,226,75},fillPattern=FillPattern.Solid), Text(extent={{-100,-60},{100,-100}},lineColor={28,108,200},fillColor={151,226,75},fillPattern=FillPattern.Solid,textString="%name")}),Diagram(coordinateSystem(preserveAspectRatio=false)));
end Source;
model User
extends RealInterface;
Real double;
equation
double = 2*realConnector.r;
annotation(Icon(coordinateSystem(preserveAspectRatio=false), graphics={Rectangle(extent={{-80,80},{80,-60}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid), Text(extent={{-100,-60},{100,-100}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid,textString="%name")}),Diagram(coordinateSystem(preserveAspectRatio=false)));
end User;
model User_multi
MultidimConnections.User user annotation(Placement(transformation(extent={{-10,40},{10,60}})));
MultidimConnections.User user1 annotation(Placement(transformation(extent={{-10,-10},{10,10}})));
MultidimConnections.User user2 annotation(Placement(transformation(extent={{-10,-60},{10,-40}})));
RealConnector realConnector[3] annotation(Placement(transformation(extent={{110,-10},{90,10}})));
equation
connect(user.realConnector, realConnector[1]) annotation(Line(points={{10,50},{98,50},{98,-6.66667},{100,-6.66667}}, color={0,0,0}));
connect(user1.realConnector, realConnector[2]) annotation(Line(points={{10,0},{98,0},{98,4.44089e-16},{100,4.44089e-16}}, color={0,0,0}));
connect(user2.realConnector, realConnector[3]) annotation(Line(points={{10,-50},{98,-50},{98,6.66667},{100,6.66667}}, color={0,0,0}));
annotation(Icon(coordinateSystem(preserveAspectRatio=false), graphics={Rectangle(extent={{-80,80},{80,40}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid),Text(extent={{-100,-60},{100,-100}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid,textString="%name"),Rectangle(extent={{-80,28},{80,-12}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid),Rectangle(extent={{-80,-20},{80,-60}},lineColor={28,108,200},fillColor={85,170,255},fillPattern=FillPattern.Solid),Rectangle(extent={{-100,100},{100,-102}}, lineColor={28,108,200})}),Diagram(coordinateSystem(preserveAspectRatio=false)));
end User_multi;
model TestCustomReal
extends Modelica.Icons.Example;
Source source(k=1) annotation(Placement(transformation(extent={{-60,40},{-40,60}})));
User user annotation(Placement(transformation(extent={{60,40},{40,60}})));
User_multi user_multi annotation(Placement(transformation(extent={{60,-10},{40,10}})));
Source source_arr[3](k=1) annotation(Placement(transformation(extent={{-60,-10},{-40,10}})));
User_multi user_multi_array[3] annotation(Placement(transformation(extent={{60,-60},{40,-40}})));
Source source_mat[3,3](k=1) annotation(Placement(transformation(extent={{-60,-60},{-40,-40}})));
equation
connect(source.realConnector, user.realConnector) annotation(Line(points={{-40,50},{40,50}}, color={0,0,0}));
connect(source_arr.realConnector, user_multi.realConnector) annotation(Line(points={{-40,0},{40,0}}, color={0,0,0}));
connect(source_mat.realConnector, user_multi_array.realConnector) annotation(Line(points={{-40,-50},{40,-50}}, color={0,0,0}));
end TestCustomReal;
annotation(uses(Modelica(version="3.2.3")));
end MultidimConnections;
The connect construct works only if the array dimensions match.
You could provide indices on the create connection window, to make the connection right between tubeWall and surface. which is exactly what the code is doing.
The model Unnammed works because gain_1_1.u is a connector with sizes [3,3]. If you change the size of the instance gain_1, you will see the difference.
Therefore you can either connect same size arrays or explicitly mention the indices during the connection.
Hope this helps.
I'm familiarizing myself with Pyspark and SparkML at the moment. To do so I use the titanic dataset to train a GLM for predicting the 'Fare' in that dataset.
I'm following closely the Spark documentation. I do get a working model (which I call glm_fare) but when I try to assess the trained model using summary I get the following error message:
RuntimeError: No training summary available for this GeneralizedLinearRegressionModel
Why is this?
The code for training was as such:
glm_fare = GeneralizedLinearRegression(
labelCol="Fare",
featuresCol="features",
predictionCol='prediction',
family='gamma',
link='log',
weightCol='wght',
maxIter=20
)
glm_fit = glm_fare.fit(training_df)
glm_fit.summary
Just in case someone comes across this question, I ran into this problem as well and it seems that this error occurs when the Hessian matrix is not invertible. This matrix is used in the maximization of the likelihood for estimating the coefficients.
The matrix is not invertible if one of the eigenvalues is 0, which occurs when there is multicollinearity in your variables. This means that one of the variables can be predicted with a linear combination of the other variables. Consequently, the effect of each of the variables cannot be identified with any significance.
A possible solution would be to find the variables that are (multi)collinear and remove one of them from the regression. Note however that multicollinearity is only a problem if you want to interpret the coefficients and not when the model is used for prediction.
It is documented possibly there could be no summary available for a model in GeneralizedLinearRegressionModel docs.
However you can do an initial check to avoid the error:
glm_fit.hasSummary() which is a public boolean method.
Using it as
if glm_fit.hasSummary():
print(glm_fit.summary)
Here is a direct like to the Pyspark source code
and the GeneralizedLinearRegressionTrainingSummary class source code and where the error is thrown
Make sure your input variables for one hot encoder starts from 0.
One error I made that caused summary not created is, I put quarter(1,2,3,4) directly to one hot encoder, and get a vector of length 4, and one column is 0. I converted quarter to 0,1,2,3 and problem solved.
I want to know if a model can be inversed in modelica. (here inverse means: if in causal statement y= x +a; x and a are input and y is output; but if I want to find 'x' as output and 'y' and 'a' as input, the model is called reversed/inversed model) For example, if I have compressor with input air port and output air port, and port has variables associated with it are pressure(P), temperature(T) and mass flow rate(mdot). I have simple steady state model containing three equations as follow:
OutPort.mdot = InPort.mdot
OutPort.P = rc * InPort.P
OutPort.T = InPort.T * (1 + rc[ (gamma-1)/gamma) - 1][/sup] / eta);
Here, rc, gamma and eta are compression ratio, ratio of specific heat capacitites and efficiency of compressor respectively.
I want to know, if I know values of : gamma, eta, OutPort.mdot, OutPort.P and OutPort.T and InPort.P and InPort.T, can I find the value of rc.
Can I find values of rc and how should be the model of compressor with above equation in Modelica. As far as I know, there are some variables designated as parameters which can not be changed during simulation. How the modelica model should be with above equations
Thanks
Yes, this should not be a problem as long as you make sure that rc is not a parameter, but a normal variable, and you supply the appropriate number of known quantities to achieve a balanced system (roughly, number of unknowns matches number of equations).
E.g. in your case if you know/supply OutPort.P and InPort.P, rc is already determined from eq 2. Then, in the third equation, there are no unknowns left, so either the temperature values are consistent with the equation or you (preferably) leave one temperature value undetermined.
In addition if you only want to compute the parameter rc during steady-state initialization i.e. that nothing changes with time that is also possible:
...
parameter Real rc(fixed=false);
initial equation
Inport.mdot=12; // Or something else indirectly determining rc.
The fixed=false means that rc is indirectly determined from the initialization. However, if the model is not completely stationary it will only find the correct rc during the initialization and then use that afterwards.
Objective
Currently I am trying to create an uncertain system based on a family of statespace models using ucover. For this I am basing my script on the documentation "Modeling a Family of Responses as an Uncertain System" which shows the technique for creating an uncertain system based on a single-input-single-output system (SISO) explicitly but makes it clear that this is fully useable for MIMO systems as well.
Technical details
Specifically it is stated with the documentation of ucover that it supports MIMO systems:
USYS = ucover(PARRAY,PNOM,ORD1,ORD2,UTYPE) returns an uncertain
system USYS with nominal value PNOM and whose range of behaviors
includes all LTI responses in the LTI array PARRAY. PNOM and PARRAY
can be SS, TF, ZPK, or FRD models. USYS is of class UFRD if PNOM
is an FRD model and of class USS otherwise.
ORD1 and ORD2 specify the order (number of states) of each diagonal
entry of W1 and W2. If PNOM has NU inputs and NY outputs, ORD1 and ORD2
should be vectors of length:
UTYPE ORD1 ORD2
InputMult NU-by-1 NU-by-1
OutputMult NY-by-1 NY-by-1
Additive NY-by-1 NU-by-1
In my case I am using both 2 inputs and 2 outputs so both ORD1 adn ORD2 should be 2 by 1. I am using 8 as the number of states used by W1 and W2 (just because, I will try adjusting that once this issue is sorted).
The Attempt
Based on the SISO example I have attempted to create a MIMO example, this is shown below
noInputs=2;
noOutputs=2;
noOfStates=4;
Anom=rand(noOfStates,noOfStates);
Bnom=rand(noOfStates,noInputs);
Cnom=rand(noOutputs,noOfStates);
Dnom=rand(noOutputs,noInputs);
Pnom=ss(Anom, Bnom, Cnom, Dnom);
p1 = Pnom*tf(1,[.06 1]); % extra lag
p2 = Pnom*tf([-.02 1],[.02 1]); % time delay
p3 = Pnom*tf(50^2,[1 2*.1*50 50^2]);
Parray = stack(1,p1,p2,p3);
Parrayg = frd(Parray,logspace(-1,3,60));
[P,Info] = ucover(Parrayg,Pnom,[8 8]',[8 8]','InputMult');
Wt = Info.W1;
bodemag((Pnom-Parray)/Pnom,'b--',Wt,'r'); grid
title('Relative Gaps vs. Magnitude of Wt')
The problem
Unlike the image in the documentation my uncertain model (when put through a bode plot) only shows a response on the lead diagonal. See the screenshot for what I mean:
Where blue is the individual models and red is the uncertain model
Question
How can I create an uncertain system based on a family of MIMO statespace models that correctly covers responses between all inputs and outputs?
If you use [8,8]' as your uncertainty order structure ord1,ord2, matlab will try to have two diagonal blocks in your uncertainty block each.
However matlab only supports diagonal weighting functions (due to some complications about nonconvex search) and what you are plotting is the diagonal weighting that will multiply the 2x2 full block LTI dynamic uncertainty. W1 affects the rows and W2 affects the columns of the uncertainty.
Hence you should check the samples of that uncertainty multiplied by the weights and then the plant. Then you can compare it with the uncertain model stack. Notice that your off-diagonal entries are practically zero (<1e-10) hence almost decoupled. But W1, W2 search looks for the H-infinity norm hence you don't get to see perfect covering at each block of the Bode plot. It combines the rows/columns of the required minimum uncertainty amount (see the examples on the help file). That's why you see 1 plot per each weight in the demos.
If you would like to model the each uncertainty affecting each block separately then you need to form a new augmented LFT such that the uncertainty is four 1x1(scalar) LTI dynamic uncertainty on the diagonal then you can have four entries in ord1 and ord2.
Since this is a MIMO system, you shouldn't compare things element-by-element. You are using the input-multiplicative form, so the uncertain system being created is of the form
Pnom*(I + W1*Delta*W2), where Delta is any stable (2-by-2, in this case) system, with ||Delta|| <= 1. So, to verify that the produced uncertain model "covers" your array of system, you should think of the equation
Parray = Pnom*(I + W1*Delta*W2)
and solve for Delta. Plot it (with SIGMA, say), and you will see that it is less than 1 in magnitude, for all frequencies. The Matlab code would be (multiply everything listed below, in order - my mulitplication symbol is not showing up in the posted answer...)
sigma(inv(W1)*inv(Pnom)*(Parrayg-Pnom)*inv(W2))
Now, using the syntax you specified, you are using weights W1 and W2 of the following form:
W1 = [W1_11 0;
0 W1_22]
and
W2 = [W2_11 0;
0 W2_22]
where you've specified 8th-order fits for all nonzero entries. Certainly for your example, this is overkill (although on a richer problem, it might be fine).
I would try much simpler, like
ucover(Parrag,Pnom,3,[],'InputMult')
That syntax will make an uncertain model of the form
Pnom*(I + w1*Delta)
where w1 is a scalar, 3rd order system. You could still see the covering by plotting SIGMA(Delta), namely
sigma((1/w1)*inv(Pnom)*(Parrayg-Pnom))
I hope that helps.
In order to create discrete or continuous time uncertain systems you can use uss associated with ureal.
Quick example
Define an uncertain propeller radius
% Propeller radius (m)
rp = ureal('rp',13.4e-2,'Range',[0.08 0.16]);
Define uncertain continuous time system
tenzo_unc = uss(A,Bw,Clocal,D,'statename',states,'inputname',inputs,'outputname',outputsLocal);
Simulate step response:
N = 5;
% Prende alcuni campioni del sistema incerto e calcola bound su incertezze
for i=1:1:N
sys{i} = usample(tenzo_unc);
step(sys{i})
hold on
cprintf('text','.');
end
Complete example
Quadcopter uncertain linearized model control with LQR. Code is available here
Step response
Closed Loop Step response
<script src="https://gist.github.com/GiovanniBalestrieri/f90a20780eb2496e730c8b74cf49dd0f.js"></script>
NB:
If you don't have the utility cprintf, include this script in your folder and use it.
I'd like to model a closed hydraulic cycle as one can find in the Modelica Standard Library/Fluid/Examples/HeatingSystem. With the heating system as well as with my (minimalistic) example I've got the same problem: The system is overdetermined.
You can find the HeatingSystem as a "bad example" in the following lecture, so I guess this is a well known problem, but I don't really get the point.
http://www.modprod.liu.se/MODPROD2011/1.252944/modprod2011-day2-talk3-Keynote-Francesco-Casella-Control-and-Modelica.pdf (page 20)
My example is:
a pump
model producer
pipe_flange w,k;
parameter Real a,b,c;
equation
w.p = k.p + a * k.Vp ^ 2 + b * k.Vp + c;
end producer;
a resistence
model consumer
pipe_flange w,k;
parameter Real rho;
parameter Real d_i;
parameter Real zeta;
equation
k.p = w.p - rho / 2 * ((w.Vp * 4) / 3.14 * d_i ^ 2) ^ 2 * zeta;
end consumer;
they are connected with a
connector pipe_flange
Real p;
flow Real Vp;
end pipe_flange;
The whole system is:
model System
consumer consumer1(rho = 1000, d_i = 0.06, zeta = 0.5);
producer producer1(a = -740741, b = -19630, c = 1070);
equation
connect(consumer1.w,producer1.w);
connect(consumer1.k,producer1.k);
end System;
Can anybody give me a hint what the problem is all about?
Are you sure your system is overdetermined? I'm; not sure how this can be since both your producer and consumer models are underdetermined.
As a general rule, the number of equations you need in a component will be equal to the number of flow variables across all its connectors + the number of internal variables (parameters do not count) + the number of outputs.
By this method, your producer model should have 2 equations (because it has 2 flow variable across all its connectors). Similarly, your consumer model should have 2 equations (Because it has two flow variables across all its connectors). So I don't see how you can generate too many equations.
Your model is also tricky because you are modeling the flow of momentum through your system (indicated by the presence of velocity on your connector as a flow variable). But your potential variable is pressure. There is no tracking of mass in your problem (as there usually is).
So, in summary, your component models definitely have an issue because they are "unbalanced" (according to the Modelica Specification) since they do not have the right number of equations. But even on a "physical" level, your formulation (pressure and velocity) is unusual in my experience and it seems to me that it could lead to problems as well once the equation balance issue is overcome.
Maybe it helps to introduce a so called loop-breaker component.
For a closed hydraulic cycle this could be an expansion vessel or storage tank with a variable level
(such a component will also exist in reality).