Guilherme Z. Santos
Guilherme Z. Santos

Reputation: 237

How to call Medium functions inside other function?

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

Answers (2)

matth
matth

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

Hans Olsson
Hans Olsson

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

Related Questions