Is there any difference between instantiating model where other models are inside that same model
model A
model B
end B;
model C
end C;
B b;
C c;
end A;
and instantiating models which are not in the same model
model A
B b;
C c;
end A;
model B
end B;
model C
end C;
Generally no. In fact, nesting model definitions inside other models is generally frowned upon and there are some restrictions in the lookup rules regarding this (I think you need to make the inner models encapsulated or something). So the second approach you show is really the preferred approach. Even better if they are organized inside a package hierarchy.
Related
I have used the Modelica "stream" concept for connectors for some time. What I understand the functions inStream() and actualStream() are designed for use
when the model has a volume. But here are important cases where there is no
volume and you need for convenience stick to the connectors you have. One example is a ProbeSensor that is mounted into a reactor volume and measures one of the species in the liquid, but does not "consume" any liquid.
The code below works using inStream(). However, I am inclined to instead use actualStream() since it "handles zero flow". But if I do the change the model does not compile and I get translation error that here are more variable than equations.
Is the code with inStream() after all correct?
Or how should it be modified?
LiquidCon
stream Real[2] c;
flow Real F;
Real p;
end LiquidCon;
block ProbeSensor
LiquidCon probe;
output RealOutput out;
constant Integer component = 2 "The liquidphase component measured index";
parameter Real T (unit="h") = 0.05 "Time constant of measurement";
parameter Real x_0 = 0.0 "Initial state of measurement device";
Real x(start=x_0, fixed=true) "State variable measurement device";
Real p (unit="bar") "Pressure";
equation
probe.F = 0;
p = probe.p;
for i in 1:2 loop
if (i==component) then
T*der(x) + x = inStream(probe.c[component]);
inStream(probe.c[component]) = probe.c[component];
out = x;
else
inStream(probe.c[i]) = probe.c[i];
end if;
end for;
end ProbeSensor;
Yes, inStream() is the best solution for this type of sensor/probe model.
inStream() gives you a value for the hypothetical case of fluid streaming into the component model. No matter what the real flow direction is (in this case 0 flow). And that's perfectly right for sensors.
As a general rule: If you can do something with inStream() than go for it. Only use actualStream() if you really need it.
Reason for that: actualStream() is basically an if expression. And that is always nonlinear, which can easily produce ugly nonlinear systems in the overall system model.
How could you determine the number of instances of a given class within this model at translation. This size is to be used to set the size of a vector.
model ModelToBeCounted
end ModelToBeCounted;
model Example
ModelToBeCounted A;
ModelToBeCounted B;
ModelToBeCounted C;
end Example;
So in this example I would like to like to determine the number instances of ModelToBeCounted. These instances could also be within instances of other classes. The code at the top level could be altered to do this and the ModelToBeCounted could also be altered.
I tried using external objects however I could not find a way to ensure that the external objects are all created before the function used to report the total number of external objects was run.
Any ideas?
Thanks
If you can modify the model ModelToBeCounted you can do this using inner/outer:
connector C
Real totalNum;
flow Real addNum;
end C;
model InnerObjectCounter
C c;
equation
c.totalNum+c.addNum=0 "Correct sign";
annotation(missingInnerMessage="Add inner component to count objects");
end InnerObjectCounter;
model FlowSource
C c;
equation
c.addNum=1;
end FlowSource;
model AddCounter
outer InnerObjectCounter objectCounter;
final Integer totalNum=integer(flowSource.c.totalNum);
FlowSource flowSource;
equation
connect(flowSource.c, objectCounter.c);
end AddCounter;
model ModelToBeCounted
AddCounter c;
end ModelToBeCounted;
All components are automatically connected to the inner object using inner/outer-mechanism, and they have a flow of 1 that is summed together.
If you cannot modify the model ModelToBeCounted, and you are willing to use non-standarized methods you can set the flag:
Hidden.AllowAutomaticInstanceOf=true;
and then use:
final parameter Integer m=sum(1 for m in P.ModelToBeCounted);
From:
https://github.com/modelica/ModelicaSpecification/blob/MCP/0021/RationaleMCP/0021/
The ModelManagement library can do that.
In fact, there is exactly what you need available as a function:
ModelManagement.Structure.Instantiated.CountUsedModels("Example", {"ModelToBeCounted"});
= {3}
The library is installed with Dymola and available with the standard license.
You just have to open it from the Libraries menu.
A problem could be, that this function has to translate your model. I am not sure how well this will work for your requirement:
This size is to be used to set the size of a vector.
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.
My model is currently roughly 2000 equations, and the simulation period is a couple of weeks. I'm using the OpenModelica Connection Editor.
The problem I'm facing is the huge amount of output variables, and I've had the plot window crash a couple of times.
The question is, therefore, how can I reduce the number of output variables?
I'm only really interested in 20-50 of them. I'm aware that I can remove parameter output by making them protected, but I haven't been able to locate any similar tricks for variables.
If you are simulating the model via command line then take a look at variableFilter argument of simulate command https://build.openmodelica.org/Documentation/OpenModelica.Scripting.simulate.html.
If you are using OMEdit then Simulation->Simulation Setup->Output->Variable Filter (Optional)
Actually, protected isn't limited to parameters. Here's an example duplicating Modelica.Mechanics.Translational.Examples.SignConvention and protecting everything but mass1
Tested in Dymola 2017FD01 with pedantic mode (so it should work in OpenModelica as well); it works fine, and gives only mass1 parameters and variables in the simulation results
model SignConvention "Examples for the used sign conventions."
extends Modelica.Icons.Example;
Modelica.Mechanics.Translational.Components.Mass mass1(
L=1,
s(fixed=true),
v(fixed=true),
m=1) a;
protected
Modelica.Mechanics.Translational.Sources.Force force1
a;
Modelica.Blocks.Sources.Constant constant1(k=1) a;
Modelica.Mechanics.Translational.Components.Mass mass2(
L=1,
s(fixed=true),
v(fixed=true),
m=1) a;
Modelica.Mechanics.Translational.Sources.Force force2
a;
Modelica.Blocks.Sources.Constant constant2(k=1) a;
Modelica.Mechanics.Translational.Components.Mass mass3(
L=1,
s(fixed=true),
v(fixed=true),
m=1) a;
Modelica.Mechanics.Translational.Sources.Force force3(useSupport=true)
a;
Modelica.Blocks.Sources.Constant constant3(k=1) a;
Modelica.Mechanics.Translational.Components.Fixed fixed
a;
equation
...
I have 2 Modelica models:
model parent
child dingus;
equation
dingus.a = 37;
dingus.c = 666;
end parent;
and
model child
Real a;
Real b;
Real c;
equation
a^3 + b^3 + c^3 = 1;
end child;
When I check the code, parent checks out okay, but child gives errors about the mismatch of unknowns and equations, as expected. Why does it work in parent, and is there a cleaner, best practice way of implementing this? I want to use child in multiple different parents, and I may want to change how I interface with it so I don't want to overly define it.
Well, it should be clear that child is not balanced since, as you point out, it doesn't have the same number of equations as unknowns. The parent model is ok since it does have the same number of equations as unknowns. It gets one equation from child and provides two of its own. Since there are exactly three variables child.a, child.b and child.c, the whole thing is balanced.
But the bigger picture issue (which I think is what you are trying to get at) is how to avoid issues where child looks like a "bad" model. A simple solution is:
model child
input Real a;
output Real b;
input Real c;
equation
a^3 + b^3 + c^3 = 1;
end child;
This conveys the idea that values for a and c will come from "outside" somewhere.
To anticipate your next question..."But what happens in cases when I want to specify b and c and solve for a? Surely I don't have to write another model with the same equations and variables but with the input and output qualifiers on different variables?"
You can use the above model without issues. The reason is that the input and output qualifiers only restrict how things are connected. We aren't actually making any connections, so we are ok. So you can provide equations for an output and solve for an input. While it may seem a little counter intuitive, that is perfectly legal in Modelica. The reason that input and output are useful here is that they implicitly specify how many equations we expect this model itself to provide (the outputs) and how many we expect to come from outside (the inputs). But they don't (and can't) restrict which variables we provide explicit equations for.
One final note, I suggest you add the equations for an instance of child in the declaration. I seem to recall there were some special rules in Modelica for handling this when determining whether something is balanced. So as far as I recall, the correct way to approach this would be:
model child
input Real a;
input Real b;
output Real c; // A bit arbitrary which one is output
equation
a^3 + b^3 + c^3 = 1;
end child;
model parent
child dingus(a=37, c=666);
end parent;
In this way, you can treat child as what amounts to a "named equation". Even better, you can make it replaceable which allows you to swap it for others. A typically application of this would be to substitute one equation of state for another or one equilibrium condition for another.
Hope that helps.