【问题标题】:How to construct a balanced connector for liquids in Modelica?如何在 Modelica 中构建液体平衡连接器?
【发布时间】:2020-06-06 14:37:43
【问题描述】:

帖子状态:

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

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

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

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

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

200224 我收到了一些关于帖子的一般性和详细信息。详细的 cmets 价值较低,部分原因是对问题的误解。 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;

【问题讨论】:

  • 注意,如果我们采取一种方式,LiquidCon 和 HarvesttankType 中的前缀流不使用 inStream,而是写: der(m[i] = inlet.c[i]*inlet.F then系统工作。所以错误是关于我的使用和缺乏对流和流(或实际流)的理解
  • 相关的平衡物理连接器:modelica.org/events/modelica2008/Proceedings/sessions/… 据我了解,流连接器应该只有一个潜在变量和一个流变量,以及任意数量的流变量。
  • 相关,流连接器论文:doi.org/10.3384/ecp09430078
  • 感谢阅读参考资料,我认为这很重要。实际上,几周前我已经简短地阅读了它们,现在再次阅读。如果我们将焓转换为浓度,则第 3 节中的最后一篇论文“流连接器……”有一个像我这样的连接器。因此,在我的情况下,能量平衡被质量平衡所取代。我的示例是我们在第 3 节中的一个退化版本,类似于图 3。但是,我仍然不清楚如何在代码 DEMO_v41 中以正确的方式使用 inStream()。

标签: modelica openmodelica jmodelica


【解决方案1】:

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

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

不过,您将面临一些挑战:

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

【讨论】:

  • 我考虑“一路走下去”,但从 Fritzsons 的写作和对原始论文的简要阅读来看,引入流的动机似乎是描述流逆转,对我来说不太感兴趣。也许我误解了。我认为用“流”的概念来制作我的小例子是很有趣的,至少出于教育目的。我也会看看你的材料。
  • stream 连接器的好处是:1) 能量守恒(流动时间焓的混合)。 2) 质量分数守恒(流动时间质量分数的混合)。 3) 质量分数/浓度不需要相应的流量/势变量。 4) 只有一个势变量和一个流量变量。
【解决方案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 Language Specification 第 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

【讨论】:

  • > 一些背景信息:连接器永远不会平衡,假设它提供的方程数量是其未知数的一半。每当您将连接器添加到组件时,该组件都必须对其进行平衡。我对此感到好奇:关于组件中“适当”数量的方程,它告诉您什么 - 什么时候“正确”,尤其是在涉及流体时?例如。检查 MSL Modelica.Fluid.Valves.ValveIncompressible (不是部分)时,我得到 18 个方程和 16 个变量,这似乎是错误的?但它是一个 MSL 模型,所以这不正确吗?
  • > 我意识到您的连接器有 3 个未知数和 1 个非法方程(正如我所说的应该是 2:1 比率)。嗯,当我检查 MSL Modelica.Fluid.Interfaces.FluidPort 时,那个连接器也有 1 个方程和 3 个变量,但我怀疑它不会是非法的(因为它被广泛使用)。这背后是什么?
  • 看来我只是不知道对 (2:1) 规则的以下限制。对于每个非部分连接器类,流变量的数量应等于既不是参数、常量、输入、输出、流也不是流的变量的数量。 (Modelica Specification v3.4 第 9.3.1 章)看来您的连接器实际上是正确的,对不起!问题似乎是组件HarvesttankType 不平衡。
  • 1) 我认为您对这个问题有些误解。让我澄清一下。我们正在使用的液体溶解了几种不同的物质,浓度列在向量 c 中。这对于描述化学过程是非常典型的。 2)这里的流量-电位对通常是流量,压力和浓度与此无关。据我了解,流旨在用于此类属性变量。 3)简要看看你的 github-materai 表明它包含流势变量,但没有使用流,这就是我正在寻找的。​​span>
  • 是的,你是对的,不幸的是我对这些流连接器并不熟悉。我的建议是查看HarvesttankType 并尝试看看你是否在这里错过了一个等式。正如我所说,连接器不应该是平衡的(如果它们包含流量变量),所以它们必须由使用它的组件来平衡。如果您在组件中使用连接器,则需要为该连接器中的每个流量变量提供额外的方程。对于流变量,您似乎还需要为每个变量提供额外的方程,因为它们被认为是未知的。
【解决方案3】:

经过一番思考,我相信以下是您转换为直接使用流变量的示例(尽管我同意使其与 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 来获得流动中的实际浓度。

【讨论】:

  • 我想澄清一下,DEMO_v42 和 DEMO_v41 中的收获罐中的变量 c 代表相同的变量。变量inletC,顾名思义,表示在收获罐中混合之前入口的浓度,即进料罐中的浓度。
猜你喜欢
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
相关资源
最近更新 更多