6

帖子状态:

200313 得到了代码 DEMO_v42 的答案,我接受了赏金!

200310 我对昨天提出的两篇重要论文发表评论。还是不明白如何更新DEMO_v41。

200309 我想强调一下,关键问题是如何在代码DEMO_v41(如果可能的话)中引入流的概念,从而使连接器平衡。作为浓度的变量 c 应该被声明为流,但是应该如何使用 inStream 或 actualStream 更新方程 - 我很高兴看到!

200226 添加了后示例 DEMO_v41,它是一个简化的,我希望比第一个 DEMO_v40 更具可读性的代码。

200225 我对给出的答案进行了一些评论,并试图让读者将注意力集中在实际问题上,但几乎没有发生。

200224 我收到了一些关于帖子的一般性和详细信息。详细的评论价值较低,部分是误解了问题的结果。Rene 的更一般的回答很好,但过于笼统。在考虑使用 Modelica.Media 等之前,我真的很想通过小示例了解如何使用流的概念。这是一个学习过程。


我想知道如何正确定义液体的连接器,该液体在溶液中具有多种不同浓度的成分,然后该溶液具有流速。液体中的压力可以忽略不计。我长期使用的标准连接器是:

connector LiquidCon
   nc=5;
   Real c[nc]        “Component concentrations”;
   flow Real F       “Flow rate”;
end LiquidCon;

该连接器在 JModelica 和 OpenModelica 中运行良好,但我在 OpenModelica 中收到连接器不平衡的警告。在 Modelica 语言规范第 9.3.1 节中,我看到我的构造实际上是不合法的,请参阅https://www.modelica.org/documents/ModelicaSpec34.pdf。如何制作满足需求的连接器?

我花了一些时间阅读 Fritzons book 2n 版中关于“流”概念的第 5.10 章,但我需要更详细地研究它。

我的简单连接器带来警告的原因是,当您声明流变量时,编译器假定另一个变量是该流变量的潜在变量,即至少连接器中的流和潜在变量的数量必须相同。那么当然在我的情况下,成分浓度不是一个潜在的变量,而是编译器无法检测到的。

在第 5.10 章的介绍部分,“流”概念的范围似乎是“……应用具有相关属性的双向物质流……”。在我的应用领域,我怀疑我是否需要考虑双向流动。这意味着使用流是一种“矫枉过正”。但这似乎也意味着我也不应该使用“流”的概念,这有点可惜。我们真的应该停止使用“流”这个概念吗? ?

无论如何,我试图整理一个比 Fritzson 的书中关于这个主题的更基本的例子,看看如何使用“流”的概念,以及你得到的计算时间等开销。在下面的示例中,我模拟了液体从进料罐到收获罐的流动。流量现在由压力差控制。代码 DEMO_v41 工作并给出连接器不平衡的警告。如果我现在将底物浓度 c 声明为“流”,我现在应该如何使用 inStream 和 actualStream 更新代码以使其以相同的方式工作,但现在使用这个平衡的连接器?

package DEMO_v41

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

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

//  ---------------------------------------------------------------------------------------------
//     Equipment
//  ---------------------------------------------------------------------------------------------

    package EquipmentLib

        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F                                        "Flow rate";
            Real c                                             "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = -area^2*(inlet.P - outlet.P);           // Linearized Bernoulli equation
            outlet.c = inlet.c;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 = 100                           "Initial feed volume";         
            parameter Real c_in = 1.0                          "Feedtank conc"; 
            Real V(start=V_0, fixed=true)                      "Feed volume";
        equation    
            outlet.c = c_in;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 = 1.0                           "Initial harvest liquid volume";
            parameter Real m_0 = 0.0                           "Initial substance mass";
            Real V(start=V_0, fixed=true)                      "Harvest liquid volume";
            Real m(start=m_0, fixed=true)                      "Substance mass";
            Real c                                             "Substance conc"; 
        equation
            inlet.P = P;
            der(V) = inlet.F;
            der(m) = inlet.c*inlet.F;
            c = m/V;            
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Example of system 
//  ---------------------------------------------------------------------------------------------

    model Test
        EquipmentLib.FeedtankType feedtank;
        EquipmentLib.HarvesttankType harvesttank;
        EquipmentLib.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v41;

下面的较旧示例 DEMO_v40 更通用且更难阅读,但由于围绕此示例的一个早期答案,因此保留供参考。

我收到的编译(JModelica 2.14)错误消息是:“扁平模型中的错误:系统结构单一。以下变量无法与方程匹配:harvestertank.inlet.c[1]、pipe.outlet.c[1]。OpenModelica (1.16) 给出了大致相同的信息。这里有什么问题?

package DEMO_v40

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

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

    partial package MediumBase
        constant String name                                   "Medium name";
        constant Integer nc                                    "Number of substances";
        replaceable type Concentration = Real[nc]              "Substance conc";        
    end MediumBase;

    package Medium1 
        extends MediumBase
            (name="One component medium",
             nc=1);
        constant Real[nc] mw = {10}                            "Substance weight";  
        constant Integer A = 1                                 "Substance index";
    end Medium1;

    record Medium_data
        constant String name = Medium1.name;
        constant Integer nc = Medium1.nc;
        constant Real[nc] mw = Medium1.mw;
        constant Integer A = Medium1.A;
    end Medium_data;

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

    package EquipmentLib
        replaceable package Medium = MediumBase                // formal parameter - EquipmentLib
            constrainedby MediumBase;

        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F (unit="m3/s")                          "Flow rate";
            stream Medium.Concentration c                      "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = area^2*(inlet.P - outlet.P);            // Linearized Bernoulli equation
            for i in 1:Medium.nc loop
                outlet.c[i] = inlet.c[i];
            end for;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 (unit="m3") = 100               "Initial feed volume";         
            parameter Real[Medium.nc] c_in (each unit="kg/m3") 
                            = {1.0*k for k in 1:Medium.nc}     "Feed inlet conc";                        
            Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
        equation    
            for i in 1:Medium.nc loop
                outlet.c[i] = c_in[i];
            end for;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 (unit="m3") = 1.0               "Initial harvest liquid volume";
            parameter Real[Medium.nc] m_0 
                  (each unit="kg/m3") = zeros(Medium.nc)       "Initial substance mass";
            Real[Medium.nc] m 
                  (start=m_0, each fixed=true)                 "Substance mass";
            Real[Medium.nc] c                                  "Substance conc"; 
            Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
        equation
            inlet.P = P;
            der(V) = inlet.F;
            for i in 1:Medium.nc loop
                der(m[i]) = inStream(inlet.c[i])*inlet.F;
                c[i] = m[i]/V;
            end for;               
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Adaptation of package Equipment to Medium1 
//  ---------------------------------------------------------------------------------------------

    package Equipment
        import DEMO_v40.EquipmentLib;
        extends EquipmentLib(redeclare package Medium=Medium1);
    end Equipment;

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

    model Test
        Medium_data medium;
        Equipment.FeedtankType feedtank;
        Equipment.HarvesttankType harvesttank;
        Equipment.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v40;
4

3 回答 3

4

就个人而言,我会“一路走来”并使用流连接器,原因如下:

  1. 在过去的 15 到 20 年中,已经进行了许多尝试以在 Modelica 中创建良好的热液连接器。这项工作stream在 2008 年推出了连接器,目前在 Modelica 中是最先进的。它允许您使用一个flow变量传输特定的焓和物质分数(或物质浓度),并实现流动逆转。使用stream连接器并不过分。
  2. 坚持例如Modelica.Fluid.Interfaces.FluidPort,您的工作将与许多现有的库和模型兼容,您不需要自己制作泵、管道、阀门、罐模型等。

但是,您将面临几个挑战:

  1. 您需要学习stream连接器的语法和工作原理。您可以在https://github.com/justnielsen/ModelicaTutorials中找到灵感
  2. Modelica.Media您必须根据您将在流连接器中传输的流体实施介质模型。例如,如果您可以假设密度和/或比热容恒定,则介质模型不必非常复杂。如果介质模型很简单,当您指定边界条件(源/汇)时,在计算上很容易在体积/质量流量之间切换。
于 2020-02-24T17:11:39.137 回答
2

正确的方法是

connector LiquidCon
   nc=5;
   Real c[nc]        “Component concentrations”;
   flow Real F[nc]       “Flow rate”;
end LiquidCon;

或者

connector LiquidCon
   Real c        “Component concentrations”;
   flow Real F       “Flow rate”;
end LiquidCon;

取决于您要建模的内容。经验法则是:number of potentials = number of flows。由于您只使用一种流量和多种浓度,这意味着您有多个罐状组件,每个都有一定的浓度,由允许流量的管道状组件连接。

对于这些,我会推荐我发布的第二个版本!

一些背景信息: 连接器永远不会平衡,与未知数相比,它假定提供的方程数量是一半。每当您将连接器添加到组件时,该组件都必须对其进行平衡。原因很简单:例如,一个连接器具有一个电位和一个流。信息流动的方向尚不清楚,但可以肯定的是,要么flow变量被认为是已知的,要么被认为potential是已知的,另一个将由组件的方程计算。对于储罐,浓度由其自己的方程计算,流量通过连接器(管道反之亦然)。

每当连接两个或多个连接器时,所有电位都设置为相等,并且所有流总和为零(Modelica 语言规范第 9.2 节)。

我更改了您的示例,以便我可以实际单独测试组件。请注意,我添加了一个默认值nc,否则无法检查单个组件的一致性。

package DEMO_v40

//  ---------------------------------------------------------------------------------------------

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

    partial package MediumBase
        constant String name                                   "Medium name";
        constant Integer nc = 1                           "Number of substances";
        replaceable type Concentration = Real[nc]              "Substance conc";        
    end MediumBase;

    package Medium1 
        extends MediumBase
            (name="One component medium",
             nc=1);
        constant Real[nc] mw = {10}                            "Substance weight";  
        constant Integer A = 1                                 "Substance index";
    end Medium1;

    record Medium_data
        constant String name = Medium1.name;
        constant Integer nc = Medium1.nc;
        constant Real[nc] mw = Medium1.mw;
        constant Integer A = Medium1.A;
    end Medium_data;

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

    package EquipmentLib

        replaceable package Medium = MediumBase                "formal parameter EquipmentLib";


        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F (unit="m3/s")                          "Flow rate";
            stream Medium.Concentration c                      "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = area^2*(inlet.P - outlet.P);            // Linearized Bernoulli equation
            for i in 1:Medium.nc loop
                outlet.c[i] = inlet.c[i];
            end for;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 (unit="m3") = 100               "Initial feed volume";         
            parameter Real[Medium.nc] c_in (each unit="kg/m3") 
                            = {1.0*k for k in 1:Medium.nc}     "Feed inlet conc";                        
            Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
        equation    
            for i in 1:Medium.nc loop
                outlet.c[i] = c_in[i];
            end for;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 (unit="m3") = 1.0               "Initial harvest liquid volume";
            parameter Real[Medium.nc] m_0 
                  (each unit="kg/m3") = zeros(Medium.nc)       "Initial substance mass";
            Real[Medium.nc] m 
                  (start=m_0, each fixed=true)                 "Substance mass";
            Real[Medium.nc] c                                  "Substance conc"; 
            Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
        equation
            inlet.P = P;
            der(V) = inlet.F;
            for i in 1:Medium.nc loop
                der(m[i]) = inStream(inlet.c[i])*inlet.F;
                c[i] = m[i]/V;
            end for;               
        end HarvesttankType;

    end EquipmentLib;

  //  ---------------------------------------------------------------------------------------------
  //     Adaptation of package Equipment to Medium1
  //  ---------------------------------------------------------------------------------------------

    package Equipment
        import DEMO_v40.EquipmentLib;
        extends EquipmentLib(redeclare package Medium=Medium1);
    end Equipment;

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

    model Test
        Medium_data medium;
        Equipment.FeedtankType feedtank;
        Equipment.HarvesttankType harvesttank;
        Equipment.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v40;

有了这个,我去了 OMEdit 并使用 CheckModel 按钮单独检查了每个组件(OMEdit 顶部中间绿色圆圈上的单个复选标记)。我意识到您的连接器有 3 个未知数和 1 个非法方程(正如我所说的应该是 2:1 比率)。这也会导致您的所有其他组件都是非法的。

由于调试所有东西将是一项相当艰巨的工作,我只能提供我前一段时间为学生项目制作的东西,但它应该展示必须完成的工作。您不需要同时通过两者pressureconcentration因为无论如何它们都应该是代数连接的。我改用了height

请参阅以下模型答案,它不适合此(我无法在此处添加文件)。

编辑:我刚刚创建了一个 git 存储库。实际上要容易得多:

HTTPS:https ://github.com/kabdelhak/TankSystem

SSH:git@github.com:kabdelhak/TankSystem.git

于 2020-02-24T14:08:46.900 回答
1

经过一番思考,我相信以下是将您的示例转换为直接使用流变量(尽管我同意使其与 MSL 兼容会很好,正如@ReneJustNielsen 所建议的那样)。

package DEMO_v42

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

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

//  ---------------------------------------------------------------------------------------------
//     Equipment
//  ---------------------------------------------------------------------------------------------

    package EquipmentLib

        connector LiquidCon
            Real P                                             "Pressure";
            flow Real F                                        "Flow rate";
      stream Real c_outflow "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation 
            inlet.F = -outlet.F;
            outlet.F = -area^2*(inlet.P - outlet.P);           // Linearized Bernoulli equation
            outlet.c_outflow = inStream(inlet.c_outflow);
            inlet.c_outflow=inStream(outlet.c_outflow);
        end PipeType;

        model FeedtankType
            LiquidCon outlet;
            parameter Real P = 0.1                             "Pressure";
            parameter Real V_0 = 100                           "Initial feed volume";
            parameter Real c_in = 1.0                          "Feedtank conc";
            Real V(start=V_0, fixed=true)                      "Feed volume";
        equation 
            outlet.c_outflow = c_in;
            outlet.P = P;
            der(V) = outlet.F;
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";
            parameter Real V_0 = 1.0                           "Initial harvest liquid volume";
            parameter Real m_0 = 0.0                           "Initial substance mass";
            Real V(start=V_0, fixed=true)                      "Harvest liquid volume";
            Real m(start=m_0, fixed=true)                      "Substance mass";
            Real c                                             "Substance conc";
            Real inletC=actualStream(inlet.c_outflow);
        equation 
            inlet.P = P;
            inlet.c_outflow=c;
            der(V) = inlet.F;
            der(m) = actualStream(inlet.c_outflow)*inlet.F;
            c = m/V;
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Example of system 
//  ---------------------------------------------------------------------------------------------

    model Test
        EquipmentLib.FeedtankType feedtank;
        EquipmentLib.HarvesttankType harvesttank;
        EquipmentLib.PipeType pipe;
    equation 
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v42;

我添加了入口C,以便能够将浓度与以前的模型进行比较。

主要变化是对于流变量 c_outflow,实际上有两个/三个不同的变量可供使用:

  • 如果您想在介质流出时使用浓度c_outflow
  • 如果你想要浓度,如果介质在使用中流动inStream(c_outflow)
  • 如果您只想要流量中的实际浓度,请使用actualStream(c_outflow)

因此,对于您写的管道,从一个端口流出的浓度等于流入另一个端口的浓度,反之亦然。对于储罐,您只需编写 的方程式c_outflow,但使用它actualStream来获得流量中的实际浓度。

于 2020-03-13T11:31:15.547 回答