如何在其他函数中调用 Medium 函数?

How to call Medium functions inside other function?

考虑以下 MWE,其中一个模型有一个 rapleceable 函数来从多个选项中选择如何计算介质比热容,一些使用介质模型中的函数,一些不使用。因此,使用一个包来收集所有比热容函数。

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;

如果我要在另一个模型中模拟 Model,我必须选择要计算 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;

模拟得很好,但是,如果我选择 realCp 函数,那么错误会增加:

Function Medium.specificHeatCapacity is not known in (function Library.FunctionPackage.realCp)

这对我来说真的不足为奇,我知道在 Model 模型中声明的 Medium 包的 FunctionPackage "are not aware" 中声明的函数。因此,我的问题是:我如何让他们知道?是否可以将媒体作为函数的输入传递?

我知道在 Model 中声明来自 FunctionPackage 的函数会将它们置于与 Medium 相同的范围内,这样我就可以在函数内部调用它而不会出现任何问题。虽然这样做会让我失去 replaceable function 的下拉功能,但我真的需要它,所以失去它不是一个选择。

顺便说一句,不知道这个问题是否有用,但我在 Windows 10 64 位下使用 Dymola 2017(32 位)。

您不能将 Medium-package 作为普通函数输入直接传递。

一种解决方案如下:

添加 Medium 作为 LibraryFunction 的可替换包

package FunctionPackage
  replaceable package Medium =
      Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
      choicesAllMatching=true);
  ...

并在需要的地方创建一个新的 FunctionPackage:

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;

另一种变体是将其作为函数中的可替换包,如下所示(更短,但我发现它更令人困惑):

  function realCp
    extends baseCp;
    replaceable package Medium =
      Modelica.Media.Interfaces.PartialSimpleIdealGasMedium annotation (
      choicesAllMatching=true);
  algorithm 
    cp := Medium.specificHeatCapacityCp(p, T);
  end realCp;

并用作:

function cp = FunctionPackage.realCp(redeclare package Medium=Medium);

不是完整答案,但这是一个基于原始问题和 Hans 的答案(使用变体 2)的可模拟模型(在 Dymola 2019 中测试):

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;