【问题标题】:Modelica Expandable Connector Best PracticesModelica 可扩展连接器最佳实践
【发布时间】:2020-09-25 22:09:50
【问题描述】:

这是我的模型中出现的一些可扩展连接器使用的最小工作示例:

model TestExpandableConnector
  expandable connector ControlBus
    extends Modelica.Icons.SignalBus;
    Real signal1;
    Real signal2;
  end ControlBus;

  ControlBus controlBus;

  // example models to connect signals to
  Modelica.Blocks.Math.Gain gain1;
  Modelica.Blocks.Math.Gain gain2;
  // and so on
equation 
  connect(controlBus.signal1, gain1.u);
  connect(controlBus.signal2, gain2.u);
  // and so on
end TestExpandableConnector;

这很好用,这里不用担心。

请注意,通常此模型将在图表层中创建,其中包含图形对象以及总线和组件之间的连接(在本例中为增益)。

虽然上面的例子是微不足道的,但在许多现实世界的例子中,我从一个可扩展的连接器中产生了许多连接。这很快会在图表层变得混乱,我正在尝试在这里学习/开发一些最佳实践来清理图表。

一种选择似乎是以几乎等同于 Simulink 的 From/Goto 元素的方式使用 RealExpression 模块。例如:

model TestExpandableConnectorRevised
  expandable connector ControlBus
    extends Modelica.Icons.SignalBus;
    Real signal1;
    Real signal2;
  end ControlBus;

  ControlBus controlBus;

  // example models to connect signals to
  Modelica.Blocks.Math.Gain gain1;
  Modelica.Blocks.Math.Gain gain2;
  // and so on

  // using RealEpressions like goto tags
  Modelica.Blocks.Sources.RealExpression realExpression1(y=controlBus.signal1);
  Modelica.Blocks.Sources.RealExpression realExpression2(y=controlBus.signal2);
  // and so on
equation 
  connect(realExpression1.y, gain1.u);
  connect(realExpression2.y, gain2.u);
  // and so on
end TestExpandableConnectorRevised;

现在有了这个变化,Dymola 抱怨这是非法的,因为无法确定因果关系。我似乎可以通过以下方式解决最后一个问题:1)将“输入”前缀添加到总线中的 signal1 和 signal2 声明,或 2)将 realExpressions 的声明 before contolBus 声明(这第二个解决方案对我来说有点奇怪)。

总体而言,从整理图表的角度来看,我对这些解决方案相当满意,但它们也至少感觉有点“hacky”。我在这个问题上的基本目标是询问这种方法是否可行或是否是个坏主意?此外,如果关于如何处理大型模型中所有连接的组织(尤其是可扩展连接器)有任何其他建议,我会全力以赴。作为一个额外的想法,在我看来,Modelica 语言的一个更专用的“From/Goto”功能在 Modelica 中可能真的很好,纯粹是为了整理图表,但完全等同于引擎盖下的连接语句。

【问题讨论】:

    标签: modelica dymola


    【解决方案1】:

    Dymola 抱怨

    变量 controlBus.signal1 是可扩展连接器的一部分,仅用于 在连接之外。这是不合法的,因为我们无法确定其因果关系。

    只要您使用连接在某处写入信号,您修改后的解决方案就可以工作 陈述。下面我进一步将您的示例简化为仅包含signal1。一个额外的实数表达式用于设置它的值。

    model TestExpandableConnectorRevised
      expandable connector ControlBus
         Real signal1;
      end ControlBus;
    
      ControlBus controlBus;
      Modelica.Blocks.Math.Gain gain1;
      Modelica.Blocks.Sources.RealExpression realExpression1(y=controlBus.signal1);
    
      // Added to write the bus signal
      Modelica.Blocks.Sources.RealExpression realExpression3(y=1);
    
    equation 
      connect(realExpression1.y, gain1.u);
    
      // Added to write the bus signal
      connect(realExpression3.y, controlBus.signal1);
    end TestExpandableConnectorRevised;
    

    这个例子在 Dymola pedantic 模式和 OpenModelica 下编译,所以应该没问题。

    使用总线适配器的替代方法

    如您所见,可扩展连接器充满了陷阱。如果您决定将可扩展连接器上的signal1 重命名为mysignal,但忘记将连接语句更新为connect(realExpression3.y, controlBus.mysignal),则上述问题也很容易发生。

    因此,一些 Modelica 库决定仅通过总线适配器读取和写入总线信号。您必须为每个变量创建 2 个附加块:一个用于读取,一个用于写入其值。这是很多枯燥的工作,但它避免了上面的问题。

    这是一个读写signal1的最小示例。

    package BusAdapters
      partial block BusWriter
        // Dialog allows to set the value of y in the parameter window, like for the real expression
        Modelica.Blocks.Interfaces.RealInput u annotation (Dialog);
        ControlBus controlBus;
      end BusWriter;
    
      block Write_signal1
        extends BusWriter;
      equation 
        connect(u, controlBus.signal1);
      end Write_signal1;
    
      partial block BusReader
        Modelica.Blocks.Interfaces.RealOutput y;
        ControlBus controlBus;
      end BusReader;
    
      block Read_signal1
        extends BusReader;
      equation 
        connect(y, controlBus.signal1);
      end Read_signal1;
    
      expandable connector ControlBus
        extends Modelica.Icons.SignalBus;
        Real signal1;
      end ControlBus;
    
      model TestBusConnectors
        ControlBus controlBus;
        Modelica.Blocks.Math.Gain gain1;
    
        // setting bus variables: using modifiers in write blocks
        Write_signal1 write1(u=sin(time));
    
        // accessing bus variables part 1: creating instance of reader
        Read_signal1 read1;
      equation 
        // connect all read and write blocks to the same bus instance
        connect(write1.controlBus, controlBus);
        connect(read1.controlBus, controlBus);
    
        // accessing bus variables part 2: connecting reader with component of interest
        connect(read1.y, gain1.u);
      end TestBusConnectors;
    end BusAdapters;
    

    从图形上看,这将如下所示。 x 是直接使用总线适配器编写的。对于y,使用实数表达式,以减少较大模型中的行数。

    【讨论】:

    • 几个 cmets:1) 在我的示例中,我仍然可以在没有 connect 语句的情况下逃脱(没有来自 Dymola 的警告)a) 单独添加输入前缀或 b) 定位 realExpression 声明在 controlBus 声明之前。这是实现等效连接的预期/可接受的方式,还是我应该始终使用连接语句以确保安全?
    • 2) 虽然有帮助,但从组织的角度来看,它并没有我想要的那么有用。现在,我将在所有图表的角落拥有带有一堆输入/输出的总线。有什么方法可以隐藏/组织模型的这一部分(例如使用子模型等),这样我就可以将注意力集中在实际模型上,而不是输入/输出上。
    • 3) 最后,这适用于信号,但对于物理连接如何。对于与物理端口等效的 from/goto,您是否还有其他建议?
    • 1a) 添加输入对我来说没有多大意义。你的输出会在哪里?尝试写一个总线变量。在我的测试中如果失败。在您的代码中,您只需阅读它们。 1b)我想这是一个错误。声明的顺序不应该有区别。
    • 2) 和 3) 听起来像是您误用了总线概念,创建了非常难以理解的模型。我不建议这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2015-03-25
    相关资源
    最近更新 更多