用Modelica/Dymola模拟加热管道

4

我目前正在学习化学工程,我的学士论文要求我建立一个通过热口连接两个管道的加热管,可用于超热器。尽管我很努力地理解如何在Modelica中正确编码,但我的代码仍然无法正常工作,我变得非常绝望。

因此,该模型基本上必须适用于水和过热蒸汽两种流体,即非稳态条件下的单相流动。传热应该是对流传热。此外,在此模型中忽略摩擦引起的压力损失。

这是我对模型如何工作的想法: 我基本上正在尝试构建类似于MSL中“Dynamic Pipe”的模型,只是更简单,以便研究同一主题的学生能够快速理解我的代码。因此,我将管道分成了若干节点n,第一个体积是入口状态,因此该状态实际上并不属于管道。之后,平衡方程式适用。我对动量方程式不是很确定,因此对它们的任何帮助都会受到高度赞赏。对流传热由MSL中的“Convection”模型定义,Thermal.HeatTransfer.Components。 在使用流量源、固定压力边界和壁面固定温度测试模型时,我也会出现“无法降低DAE指数”的错误,我绝对不知道这是什么意思。

此外,这是我的代码:

        model Pipe_base3
      //Import

      import Modelica.SIunits.*;
      import Modelica.Constants.pi;
      replaceable package Medium =
          Modelica.Media.Interfaces.PartialTwoPhaseMedium                          annotation (choicesAllMatching = true);

  parameter Integer n=2;
  parameter Integer np=1;

  // Geometry==================================================================//

  parameter Diameter d_pipe = 0.05 "Inner diameter of pipe"
                      annotation (Dialog(tab="Geometry"));
  parameter Length L = 1 "Length of unit"
                   annotation (Dialog(tab="Geometry"));
  parameter Area A_hex = pi * d_pipe * L
    "Shell surface of pipe for heat exchange"                                                 annotation (Dialog(tab="Geometry"));
  parameter Area A_q = (pi/4)*d_pipe^2
                       annotation (Dialog(tab="Geometry"));

  //Initialisation=============================================================//

  parameter Medium.Temperature T_start = 403.15 annotation (Dialog(tab="Initialization"));
  parameter Medium.SpecificEnthalpy h_start = Medium.specificEnthalpy_pT(p_start, T_start) annotation (Dialog(tab="Initialization"));
  parameter AbsolutePressure p_start = Medium.saturationPressure(T_start) annotation (Dialog(tab="Initialization"));
  parameter Medium.MassFlowRate m_flow_start = 0.5 annotation (Dialog(tab="Initialization"));

  //Temperature, pressure, energy==============================================//

  Medium.Temperature T[n+1]( each start=T_start, fixed=false);
  Medium.SpecificEnthalpy h[n+1]( each start=h_start, fixed=false);
  Medium.AbsolutePressure p[n+1](each start=p_start, fixed=false);

  HeatFlowRate Q_flow[n](fixed = false);
  Energy U[n](min=0);
  Energy KE[n]; //Kinetic Energy
  Medium.ThermodynamicState state[n+1];

  // Nondimensional Variables + HeatTransfer===================================//

  Medium.PrandtlNumber Pr[n](fixed=false);
  ReynoldsNumber Re[n](fixed=false);
  Real Xi[n];
  NusseltNumber Nu[n];
  CoefficientOfHeatTransfer alpha[n];

  // Thermodynamic properties==================================================//

  Medium.SpecificInternalEnergy u[n](fixed=false);
  Medium.DynamicViscosity eta[n];
  Density rho[n+1];
  Medium.SpecificHeatCapacity cp[n];
  Medium.ThermalConductivity lambda_fluid[n];

  //Segmental properties

  Mass ms[n]; //Mass per Segment
  MassFlowRate m_flow[n+1]( each start=m_flow_start/np, fixed=false);
  Velocity w[n+1](fixed=false);

  // Momentum

  Force F_p[n];
  Momentum I[n];
  Force Ib_flow[n];

  parameter Boolean init = false;

  Modelica.Fluid.Interfaces.FluidPort_a fluidin( redeclare package Medium = Medium, m_flow(start = m_flow_start, min = 0), p(start = p_start))
    annotation (Placement(transformation(extent={{-90,-100},{-70,-80}}),
        iconTransformation(extent={{-90,-100},{-70,-80}})));
  Modelica.Fluid.Interfaces.FluidPort_b fluidout( redeclare package Medium = Medium, m_flow(start = -m_flow_start, max = 0), p(start = p_start), h_outflow(start=h_start))
    annotation (Placement(transformation(extent={{70,-100},{90,-80}}),
        iconTransformation(extent={{70,-100},{90,-80}})));
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a[n] heatport
    annotation (Placement(transformation(extent={{-10,60},{10,80}}),
        iconTransformation(extent={{-10,60},{10,80}})));
  Modelica.Blocks.Interfaces.RealOutput[n] alpha_output annotation (Placement(
        transformation(extent={{-100,38},{-140,78}}), iconTransformation(extent={{-100,
            38},{-140,78}})));

protected 
  parameter Volume vn = (A_q * L) / n; //Volume per segment
  parameter Real x[n] = linspace((L/n), L, n);
  parameter Length length = L/n;

initial equation 

    for i in 1:(n+1) loop
      //h[i] = Medium.specificEnthalpy_pTX(p_start, T_start, {1});
      p[i] = p_start;
    end for;

equation 

  //Port equations=============================================================//

  fluidout.p = p[n];
  //fluidin.p-fluidout.p=p[1]-p[n+1];
  fluidout.h_outflow = h[n];
  fluidout.m_flow = -m_flow[n+1];

  //===========================================================================//

  h[1]=inStream(fluidin.h_outflow);
  p[1]=fluidin.p;
  state[1]=Medium.setState_ph(p[1],h[1]);
  T[1]=Medium.temperature(state[1]);
  rho[1]=Medium.density(state[1]);
  m_flow[1]=fluidin.m_flow/np;
  m_flow[1]=A_q*rho[1]*w[1];

  for i in 1:(n) loop

    // Heatport equations======================================================//

    T[i] = heatport[i].T;
    Q_flow[i] = heatport[i].Q_flow;

    // Momentum Balance =======================================================//

    der(I[i]) = Ib_flow[i] - F_p[i];
    I[i]=m_flow[i]*length;
    Ib_flow[i] = (p[i+1]*w[i+1]*w[i+1] - p[i]*w[i]*w[i])*A_q*np;
    F_p[i] = (A_q*p[i+1]-A_q*p[i]);

    // Energy Balance=========================================================//

    U[i] = ms[i] * u[i];
    KE[i] = 0.5*ms[i]*w[i+1]*w[i+1];

    der(U[i]+KE[i])=m_flow[i]*(h[i]+0.5*w[i]) - m_flow[i+1]*(h[i+1]+0.5*w[i+1]) + Q_flow[i];

    der(rho[i+1])= -((rho[i+1]-rho[i])*w[i+1] + (w[i+1]-w[i])*rho[i+1]); //Konti


     ms[i]=vn*rho[i+1];

     T[i+1]=Medium.temperature(state[i+1]);

     state[i+1] = Medium.setState_ph(p[i+1], h[i+1], 1); //Sets thermodynamic state from which other properties can be determined
     u[i] = Medium.specificInternalEnergy(state[i+1]);
     cp[i] = Medium.specificHeatCapacityCp(state[i+1]);
     rho[i+1] = Medium.density(state[i+1]);
     eta[i] = Medium.dynamicViscosity(state[i+1]);
     lambda_fluid[i] = Medium.thermalConductivity(state[i+1]);


     Re[i] * eta[i] = (rho[i+1] * abs(w[i+1]) * d_pipe);
     Pr[i] *lambda_fluid[i] = (eta[i] * cp[i]);
     Xi[i] = (1.8 * log10(abs(Re[i])+1) - 1.5)^(-2);
     Nu[i] = ((Xi[i]/8)*Re[i]*Pr[i])/(1+12.7*sqrt(Xi[i]/8)*((Pr[i])^(2/3)-1))*(1+(1/3)*(d_pipe/x[i])^(2/3));

     Nu[i] = Modelica.Fluid.Pipes.BaseClasses.CharacteristicNumbers.NusseltNumber(alpha[i], d_pipe, lambda_fluid[i]);

     alpha_output[i] = alpha[i] * (A_hex/n);

     m_flow[i+1] = A_q * w[i+1] * rho[i+1];

    // der(p[i]) = - w[i]*der(w[i]) * rho[i];

    // 0 = m_flow[i-1] - m_flow[i];

    // der(rho[i]) = -((rho[i]-rho[i-1])*w[i] + (v[i]-v[i-1])*rho[i]);

    //m_flow[i] = A_q * w[i] * rho[i]; //Calculation of flow velocity

    //ms[i] = vn * rho[i]; //Mass per segment

    //Calculation of thermodynamic properties for each segment=================//



    //Heat Transfer============================================================//



  end for;

  fluidin.h_outflow = h[1]; //

  annotation (Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},
            {100,100}}), graphics={Line(
          points={{-80,-80},{-80,94},{-80,100},{0,20},{80,100},{80,-80}},
          color={0,0,255},
          smooth=Smooth.None), Line(
          points={{-60,-60},{-60,-48},{-60,0},{60,0},{60,-60},{48,-40},{72,-40},
              {60,-60}},
          color={0,0,255},
          smooth=Smooth.None)}), __Dymola_selections);
end Pipe_base3;

非常感谢您的支持!

2个回答

6
当我开始使用Modelica时,我也遇到了同样的情况:我想要使用Modelica.Fluid.Pipes.DynamicPipe的特性,但是希望代码更易读且层次结构更少。因此,像你一样,我开始从头构建自己的管道模型。然而,由于我希望能够替换压降和传热相关性并具有很大的灵活性,最终得到的模型几乎与Modelica.Fluid.Pipes.DynamicPipe的复杂度相同。
我的建议是:
1. 构建自己的简单动态管道模型,不包含任何复杂特性。这仅适用于教育目的(例如让其他学生了解您的编码原则)。 2. 学习如何使用Modelica.Fluid.Pipes.DynamicPipe解决需要不同模型复杂度(段数、可替换的压降和传热方法等)的问题。Modelica.Fluid.Examples.HeatExchanger是一个示例,展示了如何使用Modelica.Fluid.Pipes.DynamicPipe对类似您请求的热交换器进行建模。

这里我分享了一个非常简单的动态管道示例,可用作换热器。该管道由n个管段制成,并利用了您可以实例化组件数组并在for循环中连接元素的事实。

至于动量平衡,正确/完整的方法是通过对每个控制体上作用的所有力进行求和来计算动量变化(牛顿第二定律)。但是,在大多数集总模型中,稳态动量平衡已足够,这将使方程式化为质量流率和压降之间的线性或二次关系。Modelica.Fluid.Pipes.DynamicPipe有许多不同的压力/流量相关性可供选择。

此致,

Rene Just Nielsen


1
感谢你的帮助,Rene!我也注意到提供的模型之所以那么复杂是有充分理由的。我对标准库中的模型存在的问题在于需要花费很长时间才能理解模型实际在做什么。特别是流模型(av_vb、av_b等)的概念对于刚开始使用Modelica的人来说相当难以理解。在我看来,这个库绝对需要更好的文档说明。 - Pascal Messmer

1
我已经建立了一个使用您的模型的小例子/测试。这应该是您的模型的一个非常简单的应用程序。不幸的是,我收到了相同的错误信息:
无法找到微分函数:Modelica.Media.Water.IF97_Utilities.waterBaseProp_ph(boundary1.p, pipe_base3_1.h[2], 0, 1) 关于时间
指标约减基本上意味着该模型包含没有未知变量的方程。这可以通过对这些方程式进行关于时间的微分(可能会发生多次)来解决。有关更多信息,请查看https://www.inf.ethz.ch/personal/cellier/Lect/NSDS/Ppt/nsds_ppt_engl.html,特别是第16讲和可能之前的讲座。
因此,Modelica工具必须知道如何进行微分。对于方程式,这通常是自动完成的,但对于函数,则必须由开发人员指定。似乎没有为 Modelica.Media.Water.IF97_Utilities.waterBaseProp_ph() 进行指定,这就是为什么您会收到错误消息的原因。

解决这个问题基本上有两种可能性:

  1. 更改模型以消除或修改约束方程(其中一个没有未知数的方程)。它应该是错误消息中显示的那个:
     der(pipe_base3_1.rho[2]) = ... 
  2. 将微分函数添加到介质中(我不太了解流体/介质,所以不知道这有多复杂,因此我建议先尝试第一种方法)。如何完成在 https://modelica.org/documents/ModelicaSpec33Revision1.pdf 第12.7节中有说明。

这里是示例代码:

model PipeTest
  Pipe_base3 pipe_base3_1(redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
    annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
  Modelica.Fluid.Sources.FixedBoundary boundary(
    nPorts=1,
    p=100000,
    redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
    annotation (Placement(transformation(extent={{-60,-40},{-40,-20}})));
  Modelica.Fluid.Sources.FixedBoundary boundary1(
    nPorts=1,
    p=100000,
    redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
    annotation (Placement(transformation(extent={{60,-40},{40,-20}})));
  Modelica.Thermal.HeatTransfer.Sources.FixedHeatFlow fixedHeatFlow[2](Q_flow={0,0})
    annotation (Placement(transformation(extent={{-40,20},{-20,40}})));
equation 
  connect(boundary.ports[1], pipe_base3_1.fluidin) annotation (Line(points={{-40,-30},{-8,-30},{-8,-9}}, color={0,127,255}));
  connect(boundary1.ports[1], pipe_base3_1.fluidout) annotation (Line(points={{40,-30},{8,-30},{8,-9}}, color={0,127,255}));
  connect(fixedHeatFlow.port, pipe_base3_1.heatport) annotation (Line(points={{-20,30},{0,30},{0,7}}, color={191,0,0}));
  annotation (
    Icon(coordinateSystem(preserveAspectRatio=false)),
    Diagram(coordinateSystem(preserveAspectRatio=false)),
    uses(Modelica(version="3.2.2")));
end PipeTest;

希望这有所帮助...

非常感谢你,马库斯!在解决问题时得到不同的观点总是很有帮助的。由于我有一个演示文稿,没有时间用你提出的方法解决问题,我会在尝试后告诉你结果。 - Pascal Messmer
1
注意:通常在使用自己的函数并使用导数注释之前,应首先查看18.3中的smoothOrder-注释。基本上,不是自己编写导数函数,而是自动完成。 (自Dymola 2018 FD01以来,有一个全局标志可启用所有函数的此功能。)但是,waterBaseProp_ph的使用方式使我认为对该函数进行微分没有意义(它已经计算了一些导数等)。 - Hans Olsson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接