Search code examples
functionmodelica

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.


Solution

  • 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);