4

问题描述

我正在构建一个库来支持系统动力学 (SD),例如 Modelica 中的建模。与Cellier 等人免费提供的库不同。我相信人们可以很好地利用非因果连接器:通过连接器将库存价值作为“潜在”传输可以构建紧凑的组件(例如流程 = 流程)。

在 SD 中,我们可能会将物质(“大众”)股票与可能变为负数的信息股票区分开来。为了支持这一点,我对质量端口使用以下定义(这里给出 a 的定义StockPort- 它的对应物 aFlowPort将简单地具有布尔输入变量而不是输出变量,稍后给出):

 connector StockPort "Used to represent stock and flow connections"
    Real stock "Current value of material in the stock";
    flow Real rate "Flow that affects the stock";
    // Boolean switches
    output Boolean stopInflow "True indicates that nothing can flow into the stock";
    output Boolean stopOutflow "True indicates that nothing can flow out of the stock";
 end StockPort;

布尔开关指示原料的每个端口是否允许填充或排放。

对于“材料库存”,该stopOutflow开关应防止库存被排空到零以下。不幸的是,在下面的示例中,这将无法解决:库存将在略低于零的情况下耗尽。

使用连接器的最小示例

以下TestModel使用这些构建块:

  • function constrainedRate( indicated rate, stopInflow, stopOutflow)用于返回符合给定约束的速率(即布尔开关)

  • connector StockPort如上所述

  • connector FlowPort对应的StockPort
  • model MaterialStock一种库存成分,其成分StockPort不得低于零
  • model LinearDecline一个带有一个FlowPort(即 Sink)的流量元素,它模拟以恒定速率(此处设置为 1)排出连接的库存

模型简单地启动一个stockinitialValue = 5连接到process线性下降的一个declineRate = 1

model TestModel "Stop draining a stock below zero"

  function constrainedRate "Set rate for a port according to signals from stock" 
    input Real indicatedRate "Proposed rate for port of flow element";
    input Boolean stopInflow "Signal from connected stock";
    input Boolean stopOutflow "Signal from connected stock";
    output Real actualRate "The rate to use";
  protected
    // check whether indicated rate is negative (e.g. an inflow to the connected stock)
    Boolean indRateIsInflow = indicatedRate < 0;
  algorithm
    // set rate to zero if stopSignal matches character of flow
    actualRate := if indRateIsInflow and stopInflow 
          then 0 
        elseif not indRateIsInflow and stopOutflow 
          then 0 
        else indicatedRate;
  end constrainedRate;

  connector FlowPort "Used to represent stock and flow connections"
    Real stock "The current stock level (e.g. Potential) of a connected stock or flow data for special stocks";
    flow Real rate "Flows that affect the material stock";
    input Boolean stopInflow "True indicates that nothing can flow into the stock";
    input Boolean stopOutflow "True indicates that nothing can flow out of the stock";
  end FlowPort;

  connector StockPort "Used to represent stock and flow connections"
    Real stock "Current value of stock";
    flow Real rate "Flow that affects the stock";
    output Boolean stopInflow "True indicates that nothing can flow into the stock";
    output Boolean stopOutflow "True indicates that nothing can flow out of the stock";
  end StockPort;

  model MaterialStock "Stock that cannot be drained below zero"
    StockPort outflow;
    parameter Real initialValue;
  protected
    Real x(start = initialValue);
  equation
    // rate of change for the stock
    der(x) = outflow.rate;
    // ports shall have level information for stock
    outflow.stock = x;
    // inflow to stock is unrestricted
    outflow.stopInflow = false;
    // provide Boolean signal in case of negative stock
    outflow.stopOutflow = x <= 0;
  end MaterialStock;

  model LinearDecline "Decline of stock at a constant rate"
    FlowPort massPort;
    parameter Real declineRate(min = 0) "Rate of decline (positive rate diminishes stock)";
  protected
    // a positive rate should drain the stock (which here matches Modelica's rule for flows)
    Real rate(min = 0);
  equation
    rate = declineRate;
    // observe stock signals and constraints
    assert(rate >= 0, "Rate must be positive and will be set to zero", level = AssertionLevel.warning);
  // set the rate according to constraints given by stock
    massPort.rate = constrainedRate( max(rate, 0), massPort.stopInflow, massPort.stopOutflow );
  end LinearDecline;

  // main model
  MaterialStock stock( initialValue = 5 );
  LinearDecline process( declineRate = 1 );
equation
  connect( stock.outflow, process.massPort );
end TestModel;

使用 DASSL 从 模拟模型StartTime = 0揭示StopTime = 10变量的预期行为stock.outflow.stock

股票价值

不幸的是,该值略低于零t = 5.0

不知何故,事件(股票价值 <= 0)被检测到太晚了。我能做些什么?

(到目前为止,imo 不优雅的解决方法是使用when事件(状态事件)reinit将库存值归零。我在语句和布尔条件上使用noEvent包装器的实验if也没有成功。)

4

1 回答 1

2

你能测试一下这个解决方案吗?使用 Modelica.Constants.eps 对我有用。我还使用了 Dassl,它适用于不同的步长。我更改了以下行:

// provide Boolean signal in case of negative stock
outflow.stopOutflow = x <= 0;

// provide Boolean signal in case of negative stock
outflow.stopOutflow = x <= Modelica.Constants.eps;

然后,输出数组(在 python 中查看这篇文章):

Output using a zero instead of eps:
[ 5.00000000e+00  4.00000000e+00  3.00000000e+00  2.00000000e+00
  1.00000000e+00  0.00000000e+00 -7.37276906e-12 -7.37276906e-12
 -7.37276906e-12 -7.37276906e-12 -7.37276906e-12 -7.37276906e-12
 -7.37276906e-12 -7.37276906e-12]
Output using eps:
[5. 4. 3. 2. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
于 2019-02-18T19:40:27.887 回答