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 am using Dymola, but I am not sure about the difference between check a model and translate a model.
So I did a test.
Here is the code of the connector and the model file
connector Port
flow Real Q;
Real P;
Real T;
end Port;
model Inlet
parameter Real Q = 1;
parameter Real P = 2;
parameter Real T = 3;
Port a;
equation
a.Q = Q;
a.P = P;
a.T = T;
end Inlet;
If I check the model, Dymola would generate a .mof file:
model lab.Inlet
parameter Real Q = 1;
parameter Real P = 2;
parameter Real T = 3;
Real a.Q;
Real a.P;
Real a.T;
// Equations and algorithms
// Component
// class lab.Inlet
equation
a.Q = Q;
a.P = P;
a.T = T;
end lab.Inlet;
If I translate the model, the .mof file is like the following:
model lab.Inlet
parameter Real Q = 1;
parameter Real P = 2;
parameter Real T = 3;
Real a.Q;
Real a.P;
Real a.T;
// Equations and algorithms
// Component
// class lab.Inlet
equation
a.Q = Q;
a.P = P;
a.T = T;
a.Q = 0.0;
end lab.Inlet;
I could see that in the .mof file generated by translation there is one more line: a.Q = 0.0;.
So, my question is what is the detailed difference between check and translation? Is there a detailed document for this topic?
Checking a model should just create a small intermediate model that can be checked for logical errors (#eqs == #unknowns, etc.) but is not used for symbolic manipulations afterwards.
Instantiating a model should create a flat model that can be used for symbolic manipulations.
Translating a model should first run instantiation and afterwards perform symbolic manipulations (BLT, etc.) and actually create simulation code.
OpenModelica kind of does it this way, i can't for sure tell what dymola does, but i guess this gives you an idea. I don't know if there is any further documented explanation for this.
Adding to the other answer.
TL:DR;
Check normally assumes the model will be a sub-component of a larger model.
Translates is intended for running the model, i.e. the model should be complete in itself.
Longer version:
For "Check" the component is normally checked assuming a generic connection to the connector a (in general generic connections to all connectors). That connection will add one equation, and thus there will be one equation too many in this model - but we don't know exactly which one.
There are also some additional checks for instantiation, but normally missing modifiers (parameter values and redeclarations of partial models) is seen as a non-issue - since it is not a complete model.
For "Translate" it is assumed that you are translating a complete model, and non-causal connectors such as a will be default-connected, i.e. flows set to zero - which gives the specific error message you see. (And public top-level inputs would be read from dsu.txt.) Additionally the model is translated to C-code, which requires a bit more.
Normally "Check" stops before "Translate" by e.g., not solving systems of equations as indicated in the other answer.
However, in recent versions of Dymola if the model has "experiment" annotation a "Check" will also check that (it is assumed you are checking a complete model) - ignoring the normally above.
Recent versions of Dymola will also report issues for the connector Port:
The connector is not balanced, it has 1 flow variables and 2
non-causal non-flow variables (including possible over-determined
ones).
For "Check" that will be a problem for some models, as Dymola has to add 1 or 2 equations per Port-connector.