2

我正在寻找一种将代码分为两部分的好方法:通用库和应用程序代码,我使用的示例通常包含液体,我想让通用库独立于液体中的组件数量。这个想法是应用程序代码设置使用的液体介质,然后从通用库中导入设备,并使这些设备适应实际介质。

下面的示例是一个非常简洁的示例,它说明了进行这种代码划分的一种方法。在这里,我在部分包 MediumBase 中未定义组件数量的值 nc。稍后,当 EquipmentLib 适应实际的 Medium 时, nc 会得到一个值。这就是我所说的结构参数的“延迟”设置。该代码在 JModelica 和 OpenModelica 中运行良好。

    package DEMO_v30

        // Author: Jan Peter Axelsson

    //  ---------------------------------------------------------------------------------------------
    //     Interfaces  
    //  ---------------------------------------------------------------------------------------------

        import Modelica.Blocks.Interfaces.RealInput;
        import Modelica.Blocks.Interfaces.RealOutput;

        partial package MediumBase
            constant Integer nc                                    "Number of components";
            replaceable type Concentration = Real[nc]              "Component conc";        
        end MediumBase;

        package Medium3 
            extends MediumBase (nc=3);  
        end Medium3;

    //  ---------------------------------------------------------------------------------------------
    //     Equipment dependent on the medium  
    //  ---------------------------------------------------------------------------------------------

        package EquipmentLib
            replaceable package Medium = MediumBase                // formal parameter - EquipmentLib
                constrainedby MediumBase;
            model ReactorType
                parameter Medium.Concentration c_0 = ones(Medium.nc) "Initial component conc";
                Medium.Concentration c (start=c_0, each fixed=true)  "Component conc";  
            equation   
                for i in 1:Medium.nc loop
                    der(c[i]) = -c[i];
                end for;        
            end ReactorType;    
        end EquipmentLib;

    //  ---------------------------------------------------------------------------------------------
    //     Adaptation of package Equipment to Medium3
    //  ---------------------------------------------------------------------------------------------

        package Equipment
            import DEMO_v30.EquipmentLib;
            extends EquipmentLib(redeclare package Medium=Medium3);
        end Equipment;

    //  ---------------------------------------------------------------------------------------------
    //     Examples of systems 
    //  ---------------------------------------------------------------------------------------------

        model Test
            Equipment.ReactorType reactor;
        end Test;

    end DEMO_v30;

在具有相同代码结构的稍大示例中,我遇到了一些问题:

  • 在 JModelica 中,我收到“常量 nc 没有绑定表达式”的警告
  • 在 OpenModelica 中,我收到一个错误“无法评估结构参数(或常数).. nc,它给出了数组 c[MediumBase.nc] 的维度。数组维度必须在编译时知道'

该消息对我来说没有意义,因为 nc 在编译时已知,在 EquipmentLib 适应的级别。这个问题实际上可以通过在 MediumBase 中为 nc 赋予 Medium Base 中的“虚拟”值 nc=1 来解决,然后在编译期间将 nc 更改为适配 EquipmentLib 时提供的值。

所以我的问题是:

  1. 对我来说,最好保持 nc 未定义,然后确保在编译期间设置值,而在编译期间更改常量看起来有问题,但在 Modelica 中可能(仍然)允许。在 Modelica 语言规范中,我可以在附录 A 中看到,对常量的要求是(仅)它在模拟期间是常量,即在编译期间不是。在附录 E8.2 中,我看到也许应该对 nc 进行初始分配,但不确定。不过,希望对此发表一些评论。
  2. JModelica 和 OpenModelica 的示例编译器怎么会分别给出警告和错误?
  3. Modelica 规范对这里的内容有什么看法?

如果需要,我可以提供更大的示例,但我认为这可能是一个更普遍的答案。

4

2 回答 2

0

我现在已经确认我发布的代码确实是合理的,并且对于部分包(或模型),您可以定义没有值的变量或未确定大小的向量,前提是它们在编译时已完全定义。我提到的具有类似结构的更复杂的代码现在也得到了解决。该代码适用于 JModelica 2.14 和 OpenModelica 1.16 nightly build ...b48。有趣的是,该代码不适用于 1.15 或更早版本。感谢我在 Modelon 的联系人 Markus Olsson!

于 2020-02-26T13:23:49.193 回答
0

1)理论上我理解你的意思,但是modelica语言标准要求每个模型(除了连接器和部分模型)都是有效的。这似乎与您的情况无关,因为您定义了一个部分包,这里的问题是您在结构上依赖于此变量的同一范围内定义了一个数组。因此,我强烈建议提供一个可以检查的默认值。

2)我实际上无法重现该问题。使用 OpenModelica,即使对于nc=10000. 速度慢但有效(我们正在努力使数组/向量的东西在未来更快)。我正在使用夜间构建(OpenModelica 1.16.0~dev-102-g5c1a023)。

3) 见 1)。一般来说,我可以补充一点,您应该在非常组件上单独使用检查模型(绿色圆圈顶部中间的单个复选标记)来检查您所做的一切是否符合 modelica 语言。您还可以使用它旁边的实例化按钮来查看将从您的代码生成的平面模型。

此外,我建议使用编译标志-d=newInst(前提是您使用较新的版本之一)。这使用了新的实例化,它对 modelica 规范更严格,效率更高。

于 2020-02-24T15:25:38.470 回答