Modelica Coding Standards / Modelica When Statement - modelica

Greeting Everyone,
Happy New Year 2020
I am using Openmodelica 1.14 release version on 64 bit windows 7 system.
I am facing some trouble with ‘when’ statement in OMSimulator. While searching for solution, I came across a closed ticket #2664 in Openmodelica. I can still see the reported issue in the current release version of Openmodelica.
I am including the relevant files of ticket # 2664.
model SimpleTest "just a simple model - Compilation etc."
Modelica.Blocks.Interfaces.IntegerInput u annotation(Placement(visible = true, transformation(origin = {-100, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Interfaces.IntegerOutput y annotation(Placement(visible = true, transformation(origin = {100, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
algorithm
when change(u) then
y := y + 2;
end when;
annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2})), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2}), graphics = {Rectangle(origin = {-6.15, 2.93}, fillColor = {0, 133, 199}, fillPattern = FillPattern.HorizontalCylinder, extent = {{-77.89, 83.75}, {88.14, -92.53}})}));
end SimpleTest;
Is SimpleTest.mo as per Modelica standards?
While compilation of SimpleTest.mo , it throws a Translation Warning
Assuming fixed start value for the following 1 variables:
y:DISCRETE(flow=false fixed = false ) SimpleTest type: Integer
How to avoid this error?

It is just a warning. When you define a discrete variable like this such that it depends on it's previous value in a when condition, it has to have a fixed start value. Just providing a start value kind of is a guess value for the compiler, when you fix it you tell the compiler that it has to use this value for the initialization.
If you don't provide a start value it is set to zero, if you don't fix it, the compiler fixes it automatically (resulting in the warning).
Simple example:
Integer y(start=0, fixed=true);
Applied on your model:
model SimpleTest "just a simple model - Compilation etc."
Modelica.Blocks.Interfaces.IntegerInput u annotation(Placement(visible = true, transformation(origin = {-100, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Interfaces.IntegerOutput y(start=0, fixed=true) annotation(Placement(visible = true, transformation(origin = {100, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
algorithm
when change(u) then
y := y + 2;
end when;
annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2})), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2}), graphics = {Rectangle(origin = {-6.15, 2.93}, fillColor = {0, 133, 199}, fillPattern = FillPattern.HorizontalCylinder, extent = {{-77.89, 83.75}, {88.14, -92.53}})}));
end SimpleTest;

Related

Modelica integerChange block not working as intended?

I'm trying to use the integerChange block from the Modelica Standard library
It doesn't seem to work however. What am i doing wrong? I would have expected a spike at each change,but i get a constant "false". I'm using OpenModelica 1.17
Here is the simple model
model integerChangeTest
Modelica.Blocks.Math.IntegerChange integerChange annotation(
Placement(visible = true, transformation(origin = {26, 24}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Math.RealToInteger realToInteger annotation(
Placement(visible = true, transformation(origin = {-6, 24}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Sine sine(amplitude = 5, freqHz = 5) annotation(
Placement(visible = true, transformation(origin = {-48, 26}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
connect(realToInteger.y, integerChange.u) annotation(
Line(points = {{5, 24}, {13, 24}}, color = {255, 127, 0}));
connect(sine.y, realToInteger.u) annotation(
Line(points = {{-37, 26}, {-19, 26}, {-19, 24}}, color = {0, 0, 127}));
annotation(
uses(Modelica(version = "3.2.3")));
end integerChangeTest;
The block works, but plotting change(x) is complicated in many Modelica tools.
The reason is that at an event there are a number of intermediate values, and to avoid plotting too many values one common solution is to just store the first and last; that also simplifies the implementation since it avoids a callback for storing values during the event iteration. Unfortunately change is only true in intermediate values during event iterations - and thus plotting it becomes meaningless.
I don't know if OpenModelica has some special mode for including them as well.
If you want to see that it changes you can use the code in the comment or graphically add not+OnDelay
model integerChangeTest
Modelica.Blocks.Math.IntegerChange integerChange annotation (
Placement(visible = true, transformation(origin = {26, 24}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Math.RealToInteger realToInteger annotation (
Placement(visible = true, transformation(origin = {-6, 24}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Sine sine(amplitude = 5, freqHz = 5) annotation (
Placement(visible = true, transformation(origin = {-48, 26}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Logical.Not not1
annotation (Placement(transformation(extent={{46,14},{66,34}})));
Modelica.Blocks.MathBoolean.OnDelay onDelay(delayTime=1e-3)
annotation (Placement(transformation(extent={{82,20},{90,28}})));
equation
connect(realToInteger.y, integerChange.u) annotation (
Line(points={{5,24},{14,24}}, color = {255, 127, 0}));
connect(sine.y, realToInteger.u) annotation (
Line(points={{-37,26},{-18,26},{-18,24}}, color = {0, 0, 127}));
connect(integerChange.y, not1.u)
annotation (Line(points={{37,24},{44,24}}, color={255,0,255}));
connect(onDelay.u, not1.y)
annotation (Line(points={{80.4,24},{67,24}}, color={255,0,255}));
annotation (
uses(Modelica(version="3.2.2")));
end integerChangeTest;

Modelica.Blocks.Tables.CombiTable1Ds

I want to connect the output of a Combitable to the signal current source as shown in the code below, but it is not possible because the output of table is an array but the input of current source is a scalar.
model TableTest
Modelica.Blocks.Tables.CombiTable1Ds combiTable1Ds1(table = [0, 0; 1, 1; 2, 4; 4, 16]) annotation(
Placement(visible = true, transformation(origin = {-4, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Constant const(k = -5) annotation(
Placement(visible = true, transformation(origin = {-46, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Electrical.Analog.Sources.SignalCurrent signalCurrent1 annotation(
Placement(visible = true, transformation(origin = {48, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
equation
connect(const.y, combiTable1Ds1.u) annotation(
Line(points = {{-35, 0}, {-17, 0}}, color = {0, 0, 127}));
annotation(
uses(Modelica(version = "3.2.3")));end TableTest;
In your case, the CombiTable1Ds only has one output in its vector. Simply connect it to the current source with:
connect(combiTable1Ds1.y[1], signalCurrent1.u);
If you use Dymola, when you draw a connection select y[1] instead of the default y[:]
Best regards
Rene Just Nielsen

How to connect from an output block to an input block in openmodelica?

I have an openmodelica interface.
block InputInterfaceBlock
CPSModel.ConnectionObjects.SocketConnection con = CPSModel.ConnectionObjects.SocketConnection("/pathToSocket/rpcSocket");
Modelica.Blocks.Interfaces.RealOutput y annotation(
Placement(visible = true, transformation(origin = {194, 2}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {106, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
algorithm
while true loop
y := CPSModel.Functions.readFromSocket(con);
print("Message from server : " + String(y) + "\n");
end while;
annotation(
__OpenModelica_simulationFlags(jacobian = "coloredNumerical", s = "dassl", lv = "LOG_STATS"),
uses(Modelica(version = "3.2.2")),
Icon(graphics = {Text(origin = {4, -1}, extent = {{-62, 73}, {62, -73}}, textString = "Input\nInterface", fontName = "DejaVu Sans Mono Bold")}));
annotation(
Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
end InputInterfaceBlock;
I have an interface block (InputInterfaceBlock) which reads from a socket which is defined in the path. I want this interface block to connect to another block (OutputInterfaceBlock).
block OutputInterfaceBlock
CPSModel.ConnectionObjects.SocketConnection con = CPSModel.ConnectionObjects.SocketConnection("pathToModel/rpcSocket");
Modelica.Blocks.Interfaces.RealInput y annotation(
Placement(visible = true, transformation(origin = {194, 2}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {106, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
algorithm
print("Trying to send : " + String(y) + "\n");
CPSModel.Functions.writeToSocket(con, y);
print("Message send to server." + "\n");
annotation(
__OpenModelica_simulationFlags(jacobian = "coloredNumerical", s = "dassl", lv = "LOG_STATS"),
uses(Modelica(version = "3.2.2")),
Icon(graphics = {Text(origin = {4, -1}, extent = {{-62, 73}, {62, -73}}, textString = "Output\nInterface", fontName = "DejaVu Sans Mono")}));
annotation(
Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
end OutputInterfaceBlock;
My model is as follows.
model MechatronicSystem
CPSModel.Models.InputInterfaceBlock Input annotation(
Placement(visible = true, transformation(origin = {-90, 8}, extent = {{-28, -28}, {28, 28}}, rotation = 0)));
CPSModel.Models.OutputInterfaceBlock Output annotation(
Placement(visible = true, transformation(origin = {72, 12}, extent = {{28, 28}, {-28, -28}}, rotation = 0)));
equation
connect(Input.y, Output.y) annotation(
Line(points = {{-60, 8}, {44, 8}, {44, 12}, {42, 12}}, color = {0, 0, 127}));
annotation(
uses(Modelica(version = "3.2.2")));
end MechatronicSystem;
I can receive the data in the InputInterfaceBlock from the socket to the model, but when I try to send that data to OutputInterfaceBlock. It is not getting received in the OutputInterfaceBlock.
How can I fix it ?
You are using a while true loop in InputInterfaceBlock, but the different algorithms in Modelica are not co-routines but normal algorithms.
You could replace that with when sample(0.1,0.1) then ... end when; or similarly, which will run the code every 0.1s seconds.
The while-loop causes the model should be stuck in InputInterfaceBlock and OutputInterfaceBlock not be called.

How correct redeclare of Medium in OpenModelica?

I used OpenModelica 1.9.4~dev-675-gb524b08
And try to create model for simulate gas plant.
When I try to redeclare a Medium according examples
model Block_Prep_ASIDGAS
import Modelica.Fluid.Interfaces;
import SI=Modelica.SIunits;
redeclare replaceable package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater constrainedby Modelica.Media.Interfaces.PartialMedium "Medium in the component" annotation(choicesAllMatching = true);
Interfaces.FluidPort_a port_a (redeclare package Medium = Medium) "Порт ввода газа" annotation(Placement(visible = true, transformation(origin = {-584, 42}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Interfaces.FluidPort_b port_b annotation(Placement(visible = true, transformation(origin = {586, 46}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {102, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2}), graphics = {Text(origin = {-92, 91}, extent = {{190, 1}, {-8, -1}}, textString = "Блок подготовки кислого газа", fontSize = 40), Rectangle(lineThickness = 2, borderPattern = BorderPattern.Engraved, extent = {{-100, 98}, {100, -98}}, radius = 2), Text(origin = {-8, -3}, lineColor = {255, 0, 0}, extent = {{-70, 79}, {96, -77}}, textString = "B_PAG", fontSize = 200)}), Diagram(coordinateSystem(extent = {{-600, -400}, {600, 400}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2})), experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-06, Interval = 0.02));
end Block_Prep_ASIDGAS;
I got errors:
[1] Translation Error
[Seneca.BlockModels.Block_Prep_ASIDGAS.Medium: 10:26-10:92]: Illegal redeclare of element Medium, no inherited element with that name exists.
[2] Translation Error
Error occurred while flattening model Seneca.BlockModels.Block_Prep_ASIDGAS
I find two request in OpenModelica trac #2959 and #2079
Advice me how to correct my model for correct simulation in OpenModelica?
It should work as you do it but without a full model is hard to debug and see where the problem is.
you missed redeclaring the package in port_b, the rest seems to be ok.

Modelica spring-pendulum

I want to model a simple "spring-pendulum" in modelica:
model Pendulum
parameter Boolean animation=true "= true, if animation shall be enabled";
inner Modelica.Mechanics.MultiBody.World world(axisLength=0.6)
Modelica.Mechanics.MultiBody.Parts.Body body1(
m=1,
animation=animation,
I_11=1,
I_22=1,
I_33=1,
r_CM={0,0,0},
cylinderDiameter=0.05,
sphereDiameter=0.2)
Modelica.Mechanics.MultiBody.Forces.Spring spring1(
coilWidth=0.01,
numberOfWindings=5,
c=20,
s_unstretched=0.2) ;
Modelica.Mechanics.MultiBody.Joints.Revolute revolute(phi(fixed=true), w(
fixed=true));
equation
connect(world.frame_b, revolute.frame_a)
connect(spring1.frame_a, revolute.frame_a)
connect(spring1.frame_b, body1.frame_a)
connect(revolute.frame_b, body1.frame_a
end Pendulum;
Trying to simulate the simulation fail - no error message.
Do i need a revolulte for a spring-pendulum? Thank you very much for your help!
Not exactly sure of what you're trying to model. If you make a drawing of your system you'll see that it won't represent what you're trying to model (I think).
Here's a pendulum with a spring:
model pendulum2
inner Modelica.Mechanics.MultiBody.World world annotation(Placement(visible = true, transformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.MultiBody.Joints.Revolute revolute annotation(Placement(visible = true, transformation(origin = {-41.539, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.MultiBody.Joints.Prismatic prismatic(s.start = .5) annotation(Placement(visible = true, transformation(origin = {-10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.MultiBody.Parts.Body body annotation(Placement(visible = true, transformation(origin = {25, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.MultiBody.Forces.Spring spring(c = 100, s_unstretched = .5) annotation(Placement(visible = true, transformation(origin = {-10, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
connect(spring.frame_b, prismatic.frame_b) annotation(Line(visible = true, origin = {0, 10}, points = {{0, 10}, {0, -10}}));
connect(spring.frame_a, prismatic.frame_a) annotation(Line(visible = true, origin = {-20, 10}, points = {{0, 10}, {0, -10}}));
connect(prismatic.frame_b, body.frame_a) annotation(Line(visible = true, origin = {7.5, 0}, points = {{-7.5, -0}, {7.5, 0}}));
connect(revolute.frame_b, prismatic.frame_a) annotation(Line(visible = true, origin = {-25.77, 0}, points = {{-5.77, 0}, {5.77, 0}}));
connect(world.frame_b, revolute.frame_a) annotation(Line(visible = true, origin = {-60.77, 0}, points = {{-9.23, 0}, {9.23, 0}}));
annotation(Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})));
end pendulum2;