Invalid Modelica model works fine when instantiated in another model. Why? - instantiation

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.

Related

What is the difference between check a model and tranlate a model in Dymola

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.

Clean methodology for running a function for a large set of input parameters (in Matlab)

I have a differential equation that's a function of around 30 constants. The differential equation is a system of (N^2+1) equations (where N is typically 4). Solving this system produces N^2+1 functions.
Often I want to see how the solution of the differential equation functionally depends on constants. For example, I might want to plot the maximum value of one of the output functions and see how that maximum changes for each solution of the differential equation as I linearly increase one of the input constants.
Is there a particularly clean method of doing this?
Right now I turn my differential-equation-solving script into a large function that returns an array of output functions. (Some of the inputs are vectors & matrices). For example:
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
Here I loop through the function. The function solves a differential equation, and then returns the set of solution functions for that input parameter, and then each is appended as a row to a matrix.
There are a few issues I have with my method:
If I want to see the solution to the differential equation for a different parameter, I have to redefine the function so that it is an input of one of the thirty other parameters. For the sake of code readability, I cannot see myself explicitly writing all of the input parameters as individual inputs. (Although I've read that structures might be helpful here, but I'm not sure how that would be implemented.)
I typically get lost in parameter space and often have to update the same parameter across multiple scripts. I have a script that runs the differential-equation-solving function, and I have a second script that plots the set of simulated data. (And I will save the local variables to a file so that I can load them explicitly for plotting, but I often get lost figuring out which file is associated with what set of parameters). The remaining parameters that are not in the input of the function are inside the function itself. I've tried making the parameters global, but doing so drastically slows down the speed of my code. Additionally, some of the inputs are arrays I would like to plot and see before running the solver. (Some of the inputs are time-dependent boundary conditions, and I often want to see what they look like first.)
I'm trying to figure out a good method for me to keep track of everything. I'm trying to come up with a smart method of saving generated figures with a file tag that displays all the parameters associated with that figure. I can save such a file as a notepad file with a generic tagging-number that's listed in the title of the figure, but I feel like this is an awkward system. It's particularly awkward because it's not easy to see what's different about a long list of 30+ parameters.
Overall, I feel as though what I'm doing is fairly simple, yet I feel as though I don't have a good coding methodology and consequently end up wasting a lot of time saving almost-identical functions and scripts to solve fairly simple tasks.
It seems like what you really want here is something that deals with N-D arrays instead of splitting up the outputs.
If all of the OutputArray_ variables have the same number of rows, then the line
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
seems to suggest that what you really want your function to return is an M x K array (where in this case, K = 5), and you want to pack that output into an M x K x N array. That is, it seems like you'd want to refactor your DE_Simulation to give you something like
for i = 1:N
OutputArray(:,:,i) = DE_Simulation(Parameter1Array(i));
end
If they aren't the same size, then a struct or a table is probably the best way to go, as you could assign to one element of the struct array per loop iteration or one row of the table per loop iteration (the table approach would assume that the size of the variables doesn't change from iteration to iteration).
If, for some reason, you really need to have these as separate outputs (and perhaps later as separate inputs), then what you probably want is a cell array. In that case you'd be able to deal with the variable number of inputs doing something like
for i = 1:N
[OutputArray{i, 1:K}] = DE_Simulation(Parameter1Array(i));
end
I hesitate to even write that, though, because this almost certainly seems like the wrong data structure for what you're trying to do.

Using coupled system of PDEs in modelica

Just few questions, i hope someone will find time to answer :).
What if we have COUPLED model example: system of n indepedent variables X and n nonlinear partial differential equations PDEf(X,PDEf(X)) with respect to TIME that depends of X,PDEf(X)(partial differential equation depending of variables X ). Can you give some advice? Here is one example:
Let’s say that c is output, or desired variable. Let’s say that r is independent variable.Partial differential equation looks like:
∂c/∂t=D*1/r+∂c/∂r+2(D* (∂^2 c)/(∂r^2 ))
D=constant
r=0:0.1:Rp- Matlab syntaxis, how to represent same in Modelica (I use integrator,but didn't work)?
Here is a code (does not work):
model PDEtest
/* Boundary conditions
1. delta(c)/delta(r)=0 for r=0
2. delta(c)/delta(r)=-j*d for r=Rp*/
parameter Real Rp=88*1e-3; // length
parameter Real initialConc=1000;
parameter Real Dp=1e-14;
parameter Integer np=10; // num. of points
Real cp[np](start=fill(initialConc,np));
Modelica.Blocks.Continuous.Integrator r(k=1); // independent x1
Real j;
protected
parameter Real dr=Rp/np;
parameter Real ts= 0.01; // for using when loop (sample(0,ts) )
algorithm
j:=sin(time); // this should be indepedent variable like x2
r.u:=dr;
while r.y<=Rp loop
for i in 2:np-1 loop
der(cp[i]):=2*Dp/r.y+(cp[i]-cp[i-1])/dr+2*(Dp*(cp[i+1]-2*cp[i]+cp[i-1])/dr^2);
end for;
if r.y==Rp then
cp[np]:=-j*Dp;
end if;
cp[1]:=if time >=0 then initialConc else initialConc;
end while;
annotation (uses(Modelica(version="3.2")));
end PDEtest;
Here are more questions:
This code don’t work in OpenModelica 1.8.1, also don’t work in Dymola 2013demo. How can we have continuos function of variable c, not array of functions ?
Can we place values of array cp in combiTable? And how?
If instead “algorithm” stay “equation” code can’t be succesfull checked.Why? In OpenModelica, error is :could not flattening model :S.
Is there any simplified way to use a set of equation (PDE’s) that are coupled? I know for PDEs library in Modelica, but I think they are complicated. I want to write a function for solving PDE and call these function in “main model”, so that output of function be continuos function of “c”.I don’t know what for doing with array of functions.
Can you give me advice how to understand Modelica language, if we “speak” like in Matlab? For example: Values of independent variable r,we can specife in Matlab, like r=0:TimeStep:Rp…How to do same in Modelica? And please explain me how section “equation” works, is there similarity with Matlab, and is there necessary sequancial approach?
Cheers :)
It's hard to answer your question, since you assuming that Modelica ~ Matlab, but that's not the case. So I won't comment your code, since it's really wrong. Let me give you an example model to the burger equation. Maybe you could use it as starting point.
model burgereqn
Real u[N+2](start=u0);
parameter Real h = 1/(N+1);
parameter Integer N = 10;
parameter Real v = 234;
parameter Real Pi = 3.14159265358979;
parameter Real u0[N+2]={((sin(2*Pi*x[i]))+0.5*sin(Pi*x[i])) for i in 1:N+2};
parameter Real x[N+2] = { h*i for i in 1:N+2};
equation
der(u[1]) = 0;
for i in 2:N+1 loop
der(u[i]) = - ((u[i+1]^2-u[i-1]^2)/(4*(x[i+1]-x[i-1])))
+ (v/(x[i+1]-x[i-1])^2)*(u[i+1]-2*u[i]+u[i+1]);
end for;
der(u[N+2]) = 0;
end burgereqn;
Your further questions:
cp is an continuous variable and the array is representing
every discretization point.
Why you should want to do that, as far as I understand cp is
your desired solution variable.
You should try to use almost always equation section
algorithm sections are usually used in functions. I'm pretty
sure you can represent your desire behaviour with equations.
I don't know that library, but the hard thing on a pde is the
discretization and the solving it self. You may run into issues
while solving the pde with a modelica tool, since usually
a Modelica tool has no specialized solving algorithm for pdes.
Please consider for that question further references. You could
start with Modelica.org.

Modelica - Modeling a slider element in OpenModelica

Rheological models are usually build using three (or four) basics elements, which are :
The spring (existing in Modelica.Mechanics.Translational.Components for example). Its equation is f = c * (s_rel - s_rel0);
The damper (dashpot) (also existing in Modelica.Mechanics.Translational.Components). Its equation is f = d * v_rel; for a linear damper, an could be easily modified to model a non-linear damper : f = d * v_rel^(1/n);
The slider, not existing (as far as I know) in this library... It's equation is abs(f)<= flim. Unfortunately, I don't really understand how I could write the corresponding Modelica model...
I think this model should extend Modelica.Mechanics.Translational.Interfaces.PartialCompliant, but the problem is that f (the force measured between flange_b and flange_a) should be modified only when it's greater than flim...
If the slider extends PartialCompliant, it means that it already follows the equations flange_b.f = f; and flange_a.f = -f;
Adding the equation f = if abs(f)>flim then sign(f)*flim else f; gives me an error "An independent subset of the model has imbalanced number of equations and variables", which I couldn't really explain, even if I understand that if abs(f)<=flim, the equation f = f is useless...
Actually, the slider element doesn't generate a new force (just like the spring does, depending on its strain, or just like the damper does, depending on its strain rate). The force is an input for the slider element, which is sometime modified (when this force becomes greater than the limit allowed by the element). That's why I don't really understand if I should define this force as an input or an output....
If you have any suggestion, I would greatly appreciate it ! Thanks
After the first two comments, I decided to add a picture that, I hope, will help you to understand the behaviour I'm trying to model.
On the left, you can see the four elements used to develop rheological models :
a : the spring
b : the linear damper (dashpot)
c : the non-linear damper
d : the slider
On the right, you can see the behaviour I'm trying to reproduce : a and b are two associations with springs and c and d are respectively the expected stress / strain curves. I'm trying to model the same behaviour, except that I'm thinking in terms of force and not stress. As i said in the comment to Marco's answer, the curve a reminds me the behaviour of a diode :
if the force applied to the component is less than the sliding limit, there is no relative displacement between the two flanges
if the force becomes greater than the sliding limit, the force transmitted by the system equals the limit and there is relative displacement between flanges
I can't be sure, but I suspect what you are really trying to model here is Coulomb friction (i.e. a constant force that always opposes the direction of motion). If so, there is already a component in the Modelica Standard Library, called MassWithStopAndFriction, that models that (and several other flavors of friction). The wrinkle is that it is bundled with inertia.
If you don't want the inertia effect it might be possible to set the inertia to zero. I suspect that could cause a singularity. One way you might be able to avoid the singularity is to "evaluate" the parameter (at least that is what it is called in Dymola when you set the Evaluate flat to be true in the command line). No promises whether that will work since it is model and tool dependent whether such a simplification can be properly handled.
If Coulomb friction is what you want and you really don't want inertia and the approach above doesn't work, let me know and I think I can create a simple model that will work (so long as you don't have inertia).
A few considerations:
- The force is not an input and neither an output, but it is just a relation that you add into the component in order to define how the force will be propagated between the two translational flanges of the component. When you deal with acausal connectors I think it is better to think about the degrees of freedom of your component instead of inputs and outputs. In this case you have two connectors and independently at which one of the two frames you will recieve informations about the force, the equation you implement will define how that information will be propagated to the other frame.
- I tested this:
model slider
extends
Modelica.Mechanics.Translational.Interfaces.PartialCompliantWithRelativeStates;
parameter Real flim = 1;
equation
f = if abs(f)>flim then sign(f)*flim else f;
end slider;
on Dymola and it works. It is correct modelica code so it should be work also in OpenModelica, I can't think of a reason why it should be seen as an unbalance mathematical model.
I hope this helps,
Marco

Modelica execution order

Just starting with Modelica and having trouble understanding how it works.
In the below 'method' of the model, qInflow and qOutflow are used in the second line to evaluate der(h), but they have not received a value yet! (they were not defined in the 'data' of the method)? In what order is the code executed.
equation
assert(minV >= 0, "minV must be greater or equal to zero");
der(h)=(qInflow - qOutflow)/area;
qInflow=if time > 150 then 3*flowLevel else flowLevel;
qOutflow=Functions.LimitValue(minV, maxV, -flowGain*outCtr);
error=ref - h;
der(x)=error/T;
outCtr=K*(error + x);
end FlatTank;
From http://www.mathcore.com/resources/documents/ie_tank_system.pdf
This is an understandable point of confusion when coming from languages and systems that utilize imperative semantics. But Modelica doesn't work like that.
When working with Modelica it is important to understand that an equation section contains equations, not assignments. Consider this, if I gave you the following equations:
x + y = 3;
x + 2*y = 5;
If you understand that this is a mathematical context, you can then determine that x must have a value of 1 and y must have a value of 2. In other words, you have to solve a system of simultaneous equations. You'll note that the left hand side of these equations are not variables (in general), they are expressions. An equation is simply a relationship that equates one expression, on the left hand side, with another expression, on the right hand side. Furthermore, this relationship is always true and so order is irrelevant.
This is quite different from imperative programming languages with imperative semantics. But it is also very powerful because you can state these relationships (linear systems of equations, non-linear systems of equations, implicit equations, etc) and the compiler will work out the most efficient way to solve them.
Getting back to your example, when you look at the code in your question you are interpreting those equations as assignment statements. This notion is reinforced because they just happen to have variables on the left hand sides. But they are really equations. In an equation based system, you do not worry about whether a given variable has been assigned to previously. Instead, the requirement is simply that for every variable there exists (somewhere) an equation and that there are no extra equations. In other words, you should have the same number of variables as unknowns and that the system of equations has a unique solution. That is all that Modelica requires.
Now, Modelica supports the kind of imperative semantics you are used to. But they are only to be used in special cases because they constrain the interpretation of the mathematical behavior in such a way that it interferes with the symbolic manipulation that allows Modelica compilers to generate really fast code. So it is more than a question of style. You should use equations if at all possible and algorithms in Modelica should only be used as a last resort.
One last note. Some people may be wondering "Are you telling me that these equations will be put into some giant system of equations and solved by matrix inversion or Newton-Raphson or something? Why make it so complicated when it could obviously be solved in a much easier way!" But it will not be solved as a giant system of equations. If it can be solved as a simple set of assignments it will. That is one (among many) of the different symbolic manipulation techniques that will be applied. In fact, this is a key point about Modelica...you don't need to worry about optimizing the solution method, the tool will take care of that. And more importantly, if you connect components in such a way that a simultaneous system does arise, you don't need to worry about that either. Modelica tools can handle such "algebraic loops" for you, they will optimize it to find the most computationally efficient formulation and won't depend on you reformulating your model for those cases.
Does that help?
You cannot know the execution order of the equations in a Modelica model until you run a Modelica tool on it (you can re-order any equation in the source model and get the same result). And then the order is only true for this tool with the settings you used.
This was the order chosen by the OpenModelica compiler (omc +s +simCodeTarget=Dump model.mo):
error = ref - h;
outCtr = K * (error + x);
der(x) = DIVISION(error, T, #SHARED_LITERAL_2(String#);
qOutflow = LimitValue(minV, maxV, (-flowGain) * outCtr);
qInflow = if time > 150.0 then 3.0 * flowLevel else flowLevel;
der(h) = DIVISION(qInflow - qOutflow, area, #SHARED_LITERAL_3(String#);
This example was a little boring because the left and right sides of no equation changed place (h = error - ref would be viable if h was not chosen as a state variable, etc).