I continue work on understanding how to best divide code in library and application. In a few previous posts I have worked with a toy example DEMO_xx library with application dxx_app7. Below is a slightly updated version to cover the question here. I have included the possibility to add a sensor to the harvest tank.
Now I want to understand how to in application code bring in information from the application Medium7 that is extended from the library Medium2 and use that fully in a new component model in the application.
What I understand is that if you import a package that is extended from another package you only get what is the “latest” package and NOT what is built up from through extensions and what is aggregated total Medium7 information.
This fact is illustrated in the example by changing the constant SensorX.component from C that works to A or B that does not work.
However, if I make a local instance of Medium7 THEN I get the complete information of Medium7. I can do that in SensorX as marked Question 1 - alt 2. I can also do this choice of substrate to measure out in the configuration of the system and marked Question 1 alt 3. This is more readable code I think.
But how do I make all of the content of Medium7 available locally? Must I define locally a new constant for every constant I need as I show here with sensorX.component? Generally you may want to in a model have access to various properties of the medium and that is convenient to put in the package Medium
Also I wish I could import a connector LiquidCon adapted for Medium7 instead of writing that code once again in package Sensor7. Import as suggested does not work. Is there another way? I have only tested the code in JModelica 2.4 and it might be a bug?
Would appreciate some input on these two questions. / Jan Peter
Below the application code d12_app7 that is of interest for the questions and then the associated library DEMO_v12. I have marked up with comments changes of code for the two questions and as the code stands it is for question 1 alt 1.
encapsulated package d12_app7
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v12.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
// ---------------------------------------------------------------------------------------------
// New sensor introduced in this application for measurement of substance A
// ---------------------------------------------------------------------------------------------
package Sensor7
connector LiquidCon
Medium7.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
model SensorX
// import d12_app7.Equipment7.LiquidCon; // Question 2
import d12_app7.Medium7.*; // Question 1 - alt 1
constant Integer component = C; // Question 1 - alt 1
// constant Integer component = d12_app7.Medium7.A; // Question 1 - alt 2
LiquidCon probe;
RealOutput out;
equation
probe.F = 0;
out = probe.c[component];
end SensorX;
end Sensor7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v12 to Medium7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v12.Equipment;
extends Equipment(redeclare package Medium=Medium7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v12.Control;
model Test
Equipment7.Medium medium; // Instance not necessary but helpful for user interface
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Sensor7.SensorX sensor; // Question 1 alt 1 and 2
// Sensor7.SensorX sensor(component = medium.A); // Question 1 alt 3
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
connect(sensor.probe, harvesttank.port);
end Test;
end d12_app7;
And finally the library code DEMO_v12
package DEMO_v12
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v12.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
replaceable package Medium
end Medium;
connector LiquidCon
Medium.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
LiquidCon inlet, port;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] c "Substance conc";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F;
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
// package Equipment3 = Equipment(redeclare package Medium=Medium3); // Just shorter version
package Equipment3
import DEMO_v12.Equipment;
extends Equipment(redeclare package Medium=Medium3);
end Equipment3;
model Test
Equipment3.Medium medium;
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank;
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v12;
Thank you Adeel! The Dymola error log made me do the following changes to the code:
The updated code DEMO_v22 and d22_app7 now works with both JModelica and OpenModelica. Would be good to have it tested in Dymola too 🙂
Updated code DEMO_v22.mo
package DEMO_v22
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
partial package MediumBase
constant String name "Medium name";
constant Integer nc "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
end MediumBase;
package Medium2
extends MediumBase
(name="Two components",
nc=2);
constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v22.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight");
constant Integer C = 3 "Substance index";
end Medium3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
replaceable package Medium = MediumBase
constrainedby MediumBase;
connector LiquidCon
Medium.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
parameter Real[Medium.nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:Medium.nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:Medium.nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
LiquidCon inlet, port;
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[Medium.nc] m_0
(each unit="kg/m3") = zeros(Medium.nc) "Initial substance mass";
Real[Medium.nc] c "Substance conc";
Real[Medium.nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:Medium.nc loop
der(m[i]) = inlet.c[i]*inlet.F;
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of package Equipment to Medium3
// ---------------------------------------------------------------------------------------------
package Equipment3
extends DEMO_v22.Equipment(redeclare package Medium=Medium3);
end Equipment3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
package medium = DEMO_v22.Medium3; // Not accessible in FMU though
constant String name = medium.name; // But name here is now accessible
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank;
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v22;
and updated application code d22_app7.mo
encapsulated package d22_app7
// Here I put together an application for 7 substances - print 8 pt
// and import code from the library DEMO.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v22.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v22 to Medium7 and including a new model SensorX
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v22.Equipment;
extends Equipment(redeclare package Medium=Medium7);
model SensorX
LiquidCon probe;
RealOutput out;
constant Integer component "Component measured";
equation
probe.F = 0;
out = probe.c[component];
end SensorX;
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v22.Control;
model Test
package medium = Medium7; // Not accessible in FMU though
constant String name = medium.name; // But name here is accessible
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Equipment7.SensorX sensor(component = medium.G);
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
connect(sensor.probe, harvesttank.port);
end Test;
end d22_app7;