Reputation: 237
Consider the following MWE, where a model has a rapleceable function to choose how to calculate the Medium specific heat capacity from a number of options, some uses functions from the Medium model, some don't. Therefore a package is used to gather all specific heat capacities functions.
package Library
model Model
replaceable package Medium =
Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation(choicesAllMatching=true);
replaceable function cp = FunctionPackage.baseCp annotation(choicesAllMatching=true);
parameter Real M;
parameter Real V;
parameter Real Qflow;
Real T;
Real p;
equation
M*cp(p,T)*der(T) = Qflow;
p*V = M*Medium.R_gas*T;
end Model;
package FunctionPackage
partial function baseCp
input Real p;
input Real T;
output Real cp;
end baseCp;
function realCp
extends baseCp;
algorithm
cp := Medium.specificHeatCapacity(p, T);
end realCp;
function linearCp
extends baseCp;
algorithm
cp :=0.1*T + 1000;
end linearCp;
end FunctionPackage;
end Library;
If I were to simulate Model
in another model I'd have to choose the function I want to compute the cp:
model Simulation
Library.Model Model(
redeclare package Medium = Modelica.Media.Air.SimpleAir,
M=1,
Qflow=1,
V=0.1,
redeclare function cp = Library.FunctionPackage.linearCp);
end Simulation;
Which simulates fine, however, if I were to choose the realCp
function, then the error rises:
Function Medium.specificHeatCapacity is not known in (function Library.FunctionPackage.realCp)
That's really no surprise to me, I know that the functions declared in FunctionPackage
"are not aware" of the Medium package declared in the Model
model. Therefore, my question is: how do I make them aware? Is it possible to pass the Medium as an input to the function?
I know that declaring the functions from FunctionPackage
inside Model
would place them in the same scope as Medium
making me able to call it inside the functions without any issues. Though doing so makes me lose the drop-down capabilities of replaceable function
, which I really need to have here so losing it is not an option.
BTW, don't know if it's any use to this issue but I'm using Dymola 2017 (32 bit) under Windows 10 64 bit.
Upvotes: 3
Views: 461
Reputation: 2696
Not a full answer, but here is a simulateable model (tested in Dymola 2019) based on the original question and Hans' answer (using variant 2):
package Library
model Model
replaceable package myMedium = Modelica.Media.Air.SimpleAir constrainedby
Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
choicesAllMatching=true);
function funMach = FunctionPackage.Mach(redeclare package funMedium=myMedium);
Real Mach;
parameter Modelica.SIunits.Temperature T=293.15;
parameter Modelica.SIunits.Pressure p=101325;
protected
Real TempTime = T + time;
equation
Mach = funMach(state=myMedium.setState_pT(p,TempTime), velo=300);
end Model;
package FunctionPackage
function Mach
replaceable package funMedium = Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
choicesAllMatching=true);
input funMedium.ThermodynamicState state;
input Modelica.SIunits.Velocity velo;
output Real Mach;
protected
Modelica.SIunits.Velocity souvel;
algorithm
souvel := funMedium.velocityOfSound(state);
Mach := velo/souvel;
end Mach;
end FunctionPackage;
end Library;
Upvotes: 1
Reputation: 12517
You cannot directly pass the Medium-package as an normal function input.
One solution is as follows:
Add Medium as a replacable package of LibraryFunction
package FunctionPackage
replaceable package Medium =
Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
choicesAllMatching=true);
...
And create a new FunctionPackage where you need it:
model Model
replaceable package Medium =
Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
choicesAllMatching=true);
replaceable function cp = MyFunctionPackage.baseCp annotation (
choicesAllMatching=true);
package MyFunctionPackage = FunctionPackage (redeclare package Medium =
Medium);
...
model Simulation
package MyFunctionPackage = Library.FunctionPackage(redeclare package Medium=
Modelica.Media.Air.SimpleAir);
Library.Model Model(
redeclare package Medium = Modelica.Media.Air.SimpleAir,
...
redeclare function cp = MyFunctionPackage.linearCp);
end Simulation;
Another variant would be to have it as replaceable package in the function as follows (shorter, but I find it more confusing):
function realCp
extends baseCp;
replaceable package Medium =
Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
choicesAllMatching=true);
algorithm
cp := Medium.specificHeatCapacityCp(p, T);
end realCp;
and use as:
function cp = FunctionPackage.realCp(redeclare package Medium=Medium);
Upvotes: 2