【问题标题】:Solving Component Staging in Steady-State Modelica Model求解稳态 Modelica 模型中的组件分级
【发布时间】:2017-04-24 09:22:53
【问题描述】:

我正在尝试使用 Modelica 解决我认为应该是简单的稳态组件分段问题,但我正在努力寻找解决方案。

我准备了一个示例案例,其中两个并联泵必须向系统提供目标总流量 (vTotal)。一个泵是变频泵,其流量 (v1) 与指令频率 (fPump1) 成正比,可在 0 和 fMax 之间变化。另一台泵为定速泵,运行时输出固定流量(v2IfRunning),不运行时输出零流量。

目标是求解正在运行的泵的数量和变速泵的频率。变速泵始终在运行,而定速泵仅在变速泵需要以大于 fMax 的频率运行时使用。我的示例代码如下:

model TwoPumpCode
  // Pump 1
  Modelica.SIunits.Frequency fPump1 "pump 1 frequency";
  Modelica.SIunits.Frequency fMax = 50 "maximum frequency";
  Modelica.SIunits.VolumeFlowRate v1;

  // Pump 2
  // Boolean runPump2(start=false) "true if pump 2 should run";
  Modelica.SIunits.VolumeFlowRate v2IfRunning = 30;
  Modelica.SIunits.VolumeFlowRate v2 
    "actual flow through pump 2";

  Integer nPumpsRunning(start = 1) "number of pumps running";

  // Total flow
  Modelica.SIunits.VolumeFlowRate vTotal = 70;

equation 
  // Calculate the flow through pump 1 as a function of frequency
  v1 = fPump1;

  // Calculate the flow through pump 2 based upon running state
  if fPump1 > fMax then
    nPumpsRunning = 2;
    v2 = v2IfRunning;
  else
    nPumpsRunning = 1;
    v2 = 0;
  end if;

  // Calculate the total flow
  vTotal = v1 + v2;

end TwoPumpCode;

同样,这是一个稳态模型。我尝试过使用 if、when、reinit、用于 pumpRunning 状态的布尔变量、用于运行泵数量的整数变量等,但我仍然无法解决稳态解决方案。

任何建议将不胜感激。

谢谢, 贾斯汀

【问题讨论】:

  • 您可以将控制逻辑从泵模型中分离出来,例如在 MSL 模型中。然后你有一个泵模型,它有一个开/关开关和一个控制器。在控制器中,使用滞后来避免抖动。
  • 感谢您的反馈。系统的其余部分是纯稳态的,所以如果可能的话,我宁愿避免控制器的动态。您能推荐一个 MSL 中的特定示例供我查看吗?
  • Modelica.Blocks.Logical.OnOffController 这样的控制器不添加动态,因为没有存储/集成等,它使用if 条件,就像您的代码一样。也许我不应该称它为控制器,最好称它为逻辑块!?您可能会在 github 上找到用法示例:git.io/v9IGP

标签: modelica dymola openmodelica


【解决方案1】:

我现在更明白了。问题是我们需要分隔变量。

model TwoPumpCode
  Modelica.SIunits.VolumeFlowRate vTotal = 70-40*time;
  model TwoPumpSimple
  // Pump 1
  Modelica.SIunits.Frequency fPump1 "pump 1 frequency";
  Modelica.SIunits.Frequency fMax = 50 "maximum frequency";
  Modelica.SIunits.VolumeFlowRate v1;

  // Pump 2
  // Boolean runPump2(start=false) "true if pump 2 should run";
  Modelica.SIunits.VolumeFlowRate v2IfRunning = 30;
  Modelica.SIunits.VolumeFlowRate v2 
    "actual flow through pump 2";

  Integer nPumpsRunning(start = 1) "number of pumps running";
    // Total flow
  input Modelica.SIunits.VolumeFlowRate vTotal;
  input Boolean activeSecond;
  equation
     // Calculate the flow through pump 1 as a function of frequency
  v1 = fPump1;

  // Calculate the flow through pump 2 based upon running state
  if activeSecond  then
    nPumpsRunning = 2;
    v2 = v2IfRunning;
  else
    nPumpsRunning = 1;
    v2 = 0;
  end if;

  // Calculate the total flow
  vTotal = v1 + v2;
  end TwoPumpSimple;
  //TwoPumpSimple first(vTotal=vTotal,activeSecond=first.fPump1>first.fMax);
  TwoPumpSimple first(vTotal=vTotal,activeSecond=false);
  TwoPumpSimple second(vTotal=vTotal,activeSecond=first.fPump1>first.fMax);
end TwoPumpCode;

注释掉的行与第一个解决方案相同,并将其更改为离散问题 - 但该问题有时缺乏解决方案。

新变体执行以下操作: 1 没有第二个泵需要多高的频率?

2 我们应该激活第二个泵吗?

3 计算新频率 - 基于此。

在决策中添加一些滞后会产生类似的效果。

【讨论】:

  • 汉斯,我试过你的方法,你是对的,它在 Dymola 中模拟。但是,得到的解决方案结果似乎不正确。我的最终结果包括:activeSecond = true, nPumpsRunning = 2, v2 = 0, v1 = 70, fPump1 = 70。这些结果似乎彼此不一致。
  • 啊,我明白了 - 问题是条件 fPump1>fMax。如果我们用 vTotal>fMax 替换它,这个模拟就可以了。
【解决方案2】:

根据来自 matth 的反馈,我能够使用基于 Modelica.Blocks.Logical.OnOffController 示例的 pre() 运算符。功能代码如下,供参考。

model TwoPumpCode_matth
  // Pump 1
  Modelica.SIunits.Frequency fPump1 "pump 1 frequency";
  Modelica.SIunits.Frequency fMax = 50 "maximum frequency";
  Modelica.SIunits.VolumeFlowRate v1;

  // Pump 2
  parameter Boolean runPump2InitialValue = false;
  Boolean runPump2(start=runPump2InitialValue) "true if pump 2 should run";
  Modelica.SIunits.VolumeFlowRate v2IfRunning = 30;
  Modelica.SIunits.VolumeFlowRate v2 "actual flow through pump 2";

  // Total flow
  Modelica.SIunits.VolumeFlowRate vTotal = 70;

initial equation 
  pre(runPump2) = runPump2InitialValue;

equation 
  // Calculate the flow through pump 1 as a function of frequency
  v1 = fPump1;

  // Calculate the flow through pump 2 based upon running state
  runPump2 = pre(runPump2) or (fPump1 > fMax);
  if runPump2 then
    v2 = v2IfRunning;

  else
    v2 = 0;

  end if;

  // Calculate the total flow
  vTotal = v1 + v2;

end TwoPumpCode_matth;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    相关资源
    最近更新 更多