[連載]Modelicaによる熱流体の世界の歩き方・CoolingSystem_ex01

*執筆途中だが公開ポリシーに則り公開。
 今回,単純ではあるが循環と熱の収支を持つ流体回路を作成する.手計算で陽的に行うことは出来ず,Excelで実施しても,ソルバ/循環参照/VBAを用いてiterationを含む計算が必要となる問題である.この様な回路を扱うには,Modelicaの様な汎用化された解析ツールが力を発揮する.

例題の目的・習得事項

 本例題が目的としていることは大きく下記の2つ。
  • 循環を持つ流体回路を作る.(ただし,完全な循環回路ではなく,信号受渡を通じた間接的な実装によるもの.)
  • 循環流体回路に熱の出入りを設け,熱収支計算を出来るようになる.

手書きスケッチと作成対象物の整理

 作ろうとしているものを手書きで書き下すのは、今回も定型作業として実施しておこう。
 本例題に似た実例を挙げるとすれば,ピストンエンジンの冷却液回路や産業機械の潤滑・冷却システム.循環する流体が発熱部の熱を受け取り,熱交換器で別流体(冷却水や空気)に排熱する.


 同じく定型作業として、モデル化対象物についての情報を纏める。極力簡潔に、箇条書きを並べるのがお勧め。

    内包する物理現象:

    1. ポンプによる,循環回路流体の圧送.
    2. 循環回路流体の受熱.
    3. 循環回路の流路圧力損失.
    4. 熱交換器を介した,循環回路から冷媒流体への排熱.
    5. 各所の流体温度が,循環回路の熱収支が成り立つように陰的に決定される.
    6. 循環回路の流体はグリコール47.
    7.  何か具体的な実在の機器を模擬するシミュレーションではないので,常温前後の範囲で液体なら何でも良い.水以外のModelcia Standard Libraryに標準収録されている物性パッケージを利用してみるという意図で選んだ.
       Documentationの記述によると,グリコール47というのは,47%が1,2-プロピレングリコールの水との混合液との事.そして,プロピレングリコールは潤滑剤や不凍液に用いられる有機化合物.
       余談だが,液冷エンジンでは冷却液(循環回路流体)にジエチレングリコールを混ぜた水を用い,その液から熱交換器で空気に排熱させる事が一般的.なので,グリコール47は液冷エンジン用冷却液と似た液体で有る可能性は高い.
    8. 冷媒流体は水.

    境界条件(Input):

    1. 循環回路タンクの圧力.
    2. ポンプ機械回転数.
    3. 循環回路への入熱量.
    4. 冷媒流体の質量流量.
    5. 冷媒流体の供給温度.
    6. 冷媒流体回路の出口圧力.

    Output(注目する出力):

    1. 下記に示す,代表点の流体温度
      • タンク内流体温度.
      • 熱交換器出口,循環流体温度.
      • 受熱部通過後の循環流体温度.
      • 熱交換器出口,冷媒温度.
    2. 熱交換器内部について下記温度.
      • 入口最寄り計算要素,循環流体温度.
      • 中間部計算要素, 循環流体温度.
      • 出口最寄り計算要素,循環流体温度
      • 入口最寄り計算要素,冷媒温度.
      • 中間部計算要素, 冷媒温度.
      • 出口最寄り計算要素,冷媒温度
    3. 循環流体受熱量と熱交換器を介する排熱量(受熱=排熱,の確認).
    4. 循環回路の質量保存の確認.

model(とpackage)ファイルの作成

 過去記事でも述べたように、必須ではないが、演習例題用のpackageは作成しておこう。過去記事の例で既に作成済みなら、そのpackageにmodelを作成すればOK。

コンポーネントの配置

 下図の通りにコンポーネントを配置、接続する。
 インスタンス名はコンポーネントを配置する際に自動で命名される(標準設定では名前を尋ねるウィンドウが出てくる)が、筆者は適宜、名前をつけた方が後々判りやすいものだけ命名している。下図のものだと解りにくければ、解りやすいように名前を変えてくれて構わない。
 なお,テキストボックスやコンポーネント以外の観易さのための図形は必須ではない.
  
 下図を真似て配置と接続を行うだけでシステムモデルは作成できる筈だが,今回,循環を持つ回路を間接的に作成する方法を習得するのが本例題の主目的の1つなので,循環回路側の,始点と終点の繋ぎ方には注目しておいて欲しい.
 まず,回路自体は循環させず入口と出口を持つ流路からなる.始点(最上流)・終点(最下流)共に,圧力を拘束する形式のboundaryを用い,回路中の圧力を1点(タンク圧力)任意の値に定めている.これで,ポンプの作動と各流路圧力損失で総ての点の圧力が一意に決まる(圧力を一点拘束しないと,”圧力の解が無数に存在する方程式”を解く事になる.).
 そして,循環による熱量保存をどのように再現するか.終点boundary手前に比エンタルピを計測するセンサを置く.その計測値を,始点boundaryの比エンタルピ入力コネクタ(始点側boudaryはpとhを与える形式のもの)に接続する.以上.これで発熱を受けた流体状態を流れの始点に返す事になり,実質循環回路を作ったのと等価となる.

    使用コンポーネントリスト

     必要なコンポーネントを見つけるのは慣れていないと意外と苦労する作業なので、総てのコンポーネントをリストアップしておく。数が多い事もあり,説明は省略する。
    1. Modelica.Fluid.System


    2. Modelica.Fluid.Vessels.ClosedVolume


    3. Modelica.Fluid.Machines.Pump


    4. Modelica.Fluid.Pipes.DynamicPipe


    5. Modelica.Fluid.Sources.Boundary_ph


    6. Modelica.Fluid.Sources.MassFlowSource_T

    7. Modelica.Fluid.Sources.Boundary_pT


    8. Modelica.Fluid.Sensors.TemperatureTwoPort

    9. Modelica.Fluid.Sensors.Pressure


    10. Modelica.Fluid.Sensors.VolumeFlowRate


    11. Modelica.Fluid.Sensors.SpecificEnthalpy

    12. Modelica.Mechanics.Rotational.Sources.Speed

    13. Modelica.Mechanics.Rotational.Sensors.PowerSensor

    14. Modelica.Thermal.HeatTransfer.Components.Convection

    15. Modelica.Thermal.HeatTransfer.Components.HeatCapacitor

    16. Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow

    17. Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor

    18. Modelica.Blocks.Routing.Replicator


    19. Modelica.Blocks.Math.Sum


    20. Modelica.Blocks.Math.UnitConversions.From_rpm


    21. Modelica.Blocks.Sources.Ramp


    22. Modelica.Blocks.Sources.Constant


    23. Modelica.Blocks.Interaction.Show.RealValue


    Attribute設定:配列定義

     FlowWithHeating_ex02の回で初登場した,後述のparameterとは別の設定.解説はそちらを参照頂くとして,ここでは今回のモデル作成で対象となるコンポーネントと設定内容を示す.
     設定内容:
     下記コンポーネント総て同じで, Dimensions: に [cooler_hside.nNodes] を設定する.これで,”cooler_hside”のparameter, nNodesの値を変更すると,対応して配列インスタンスの設定も変わってくれる.
     配列によるインスタンス化を行うのは,簡易熱交換器モデル部分の熱交換計算を1つのコンポーネントでではなく,複数のコンポーネントに分けて行い,温度勾配を持たせるため.3DCFDのメッシュと同じで,細かく分割する程,内部の温度分布の再現性が高まる事を期待できる.(向上するのは,内部の温度分布の再現性であり,絶対値については当然,inputしている熱伝達率の値の正確さに依るところが大きい.)
    1. convection1
    2. heatCapacitor1
    3. convection2
    4. heatFlowSensor

parameterの設定

 各コンポーネントのparameter設定を示す。コンポーネントを右クリックしてparametersを選択するか、ダブルクリックするとparametersウィンドウが現れるので、必要箇所に値を設定する。
 下記リスト中で ” :: ” 表記をしているものは,タブやタブ内のグループによる階層構造を示す.表記が無いものは「general」タブ内のものだ.
 尚、デフォルト設定のままにしておいて済むコンポーネント、parameterは記載を省略する。また、parameterの意味も特別説明が必要な者でないものを除き省略する.
  1. boundary
    1. use_p_in : true
    2. use_h_in : true
  2. tank
    1. V : 20*0.001
    2. use_portsData : false
    3. Assumptions::use_HeatTransfer : false
    4. Initialization::T_start : 15+273.15
  3. pump1
    1. N_nominal : 1000
    2. Assumptions::checkValve : true
    3. Assumptions::V : 1
    4. Assumptions::energyDynamics : Modelica.FluidTypes.Dynamics.DynamicFreeInitial
    5. Assumptions::massDynamics : Modelica.FluidTypes.Dynamics.DynamicFreeInitial
    6. Initialization::p_b_start : 10*system.p_start
    7. Initialization::m_flow_start : 10
  4. cooler_hside
    1. length : 2
    2. diameter : 0.02
    3. Assumptions::use_HeatTransfer : true
    4. Advanced::nNodes : 10
    5. Advanced::modelStructure : Modelica.Fluid.Types.ModelStructure.a_vb
  5. pipe
    1. length : 2
    2. diameter : 0.02
    3. Assumptions::use_HeatTransfer : false
    4. Advanced::nNodes : 2
    5. Advanced::modelStructure : Modelica.Fluid.Types.ModelStructure.a_vb
  6. volume
    1. V : 1*0.001
    2. use_portsData : false
    3. Assumptions::use_HeatTransfer : true
  7. pipe1
    1. length : 2
    2. diameter : 0.02
    3. Assumptions::use_HeatTransfer : false
    4. Advanced::nNodes : 2
    5. Advanced::modelStructure : Modelica.Fluid.Types.ModelStructure.a_vb
  8. boundary1
    1. use_p_in : true
  9. const_p_tank
    1. k : 101.325*1000
  10. ramp_heat_generation
    1. height : 10*1000
    2. duration : 10
    3. offset : 100*1000
    4. startTime : 100
  11. ramp_pump_N
    1. height : 0
    2. duration : 10
    3. offset : 500
    4. startTime : 30
  12. heatCapacitor1
    1. C : 10
  13. sum1
    1. nin : cooler_hside.nNodes
  14. replicator1
    1. nout : cooler_hside.nNodes
  15. replicator2
    1. nout : cooler_hside.nNodes
  16. const
    1. k : 5000
  17. ramp_m_flow_coolant
    1. height : 0.2
    2. duration : 10
    3. offset : 2
    4. startTime : 160
  18. boundary2
    1. use_m_flow_in : true
    2. T : 15+273.15
  19. cooler_cside
    1. length : 2
    2. diameter : 0.02
    3. Assumptions::use_HeatTransfer : true
    4. Initialization::T_start : 15+273.15
    5. Advanced::nNodes : cooler_hside.nNodes
    6. Advanced::modelStructure : Modelica.Fluid.Types.ModelStructure.a_vb
  20. volume1
    1. V : 1 * 0.001
    2. use_portsData : false
    3. Assumptions::use_HeatTransfer : false
    4. Initialization::T_start : 15+273.15

ソースコード

 上記までを行うとOpenModelicaがソースコードを自動生成してくれている。一部ソースコードを直接書かなければならない箇所が有るのと、エラーが生じた場合の比較のために、本モデルの完成状態のソースコードを示す。尚、ソースコードを直書きする作業が残っているが、その解説はソースコードの後に記載する。

    完成状態のソースコード(チェック用)

     コンパイルエラーや、計算結果が意図通りのものとならないような場合に比較・チェック用に参照して欲しい。尚、annotation()の部分はGUI上の配置位置や向きで値が変わるものなので、比較する必要は無い。
    ——————————————————————————-
    within WalkingInWorldOfThermoFluid.Easy;
    
    model CoolingSystem_ex01
      extends Modelica.Icons.Example;
      //----------
      //replaceable package fluid1 = Modelica.Media.Water.StandardWaterOnePhase;
      //replaceable package fluid1 = Modelica.Media.Incompressible.Examples.Glycol47;
      //replaceable package fluid1 = Modelica.Media.Incompressible.Examples.Essotherm650;
      //redeclare package Medium = fluid1
      //-----
      //replaceable package fluid2 = Modelica.Media.Water.StandardWaterOnePhase;
      //redeclare package Medium = fluid2
      //----------
      inner Modelica.Fluid.System system annotation(
        Placement(visible = true, transformation(origin = {-90, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_pump_N(duration = 10, height = 0, offset = 500, startTime = 30) annotation(
        Placement(visible = true, transformation(origin = {-130, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Math.UnitConversions.From_rpm from_rpm1 annotation(
        Placement(visible = true, transformation(origin = {-100, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Machines.Pump pump1(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, redeclare function flowCharacteristic = Modelica.Fluid.Machines.BaseClasses.PumpCharacteristics.quadraticFlow(V_flow_nominal = {0, 0.25, 0.5}, head_nominal = {100, 60, 0}), redeclare function efficiencyCharacteristic = Modelica.Fluid.Machines.BaseClasses.PumpCharacteristics.constantEfficiency(eta_nominal = 0.9), N_nominal = 1000, V(displayUnit = "l") = 0.001, checkValve = true, energyDynamics = Modelica.Fluid.Types.Dynamics.DynamicFreeInitial, m_flow_start = 10, massDynamics = Modelica.Fluid.Types.Dynamics.DynamicFreeInitial, nParallel = 1, p_b_start = 10 * system.p_start) annotation(
        Placement(visible = true, transformation(origin = {-50, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sources.Speed speed1(phi(fixed = false)) annotation(
        Placement(visible = true, transformation(origin = {-70, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sensors.PowerSensor powerSensor1 annotation(
        Placement(visible = true, transformation(origin = {-50, 18}, extent = {{-10, 10}, {10, -10}}, rotation = -90)));
      Modelica.Fluid.Sensors.VolumeFlowRate volumeFlowRate1(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {30, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Pipes.DynamicPipe cooler_hside(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, diameter = 0.02, length = 2, modelStructure = Modelica.Fluid.Types.ModelStructure.a_vb, nNodes = 10, use_HeatTransfer = true) annotation(
        Placement(visible = true, transformation(origin = {120, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Pipes.DynamicPipe pipe(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, diameter = 0.02, length = 2, modelStructure = Modelica.Fluid.Types.ModelStructure.a_vb, nNodes = 2, use_HeatTransfer = false) annotation(
        Placement(visible = true, transformation(origin = {184, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sources.MassFlowSource_T boundary2(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase, T = 15 + 273.15, m_flow = 5, nPorts = 1, use_m_flow_in = true) annotation(
        Placement(visible = true, transformation(origin = {10, 110}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Pipes.DynamicPipe cooler_cside(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase, T_start = 15 + 273.15, diameter = 0.02, length = 2, modelStructure = Modelica.Fluid.Types.ModelStructure.a_vb, nNodes = cooler_hside.nNodes, use_HeatTransfer = true) annotation(
        Placement(visible = true, transformation(origin = {120, 76}, extent = {{-10, 10}, {10, -10}}, rotation = 0)));
      Modelica.Fluid.Sources.Boundary_pT boundary3(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase, nPorts = 1) annotation(
        Placement(visible = true, transformation(origin = {220, 110}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Thermal.HeatTransfer.Components.Convection convection1[cooler_hside.nNodes] annotation(
        Placement(visible = true, transformation(origin = {120, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 90)));
      Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heatCapacitor1[cooler_hside.nNodes](C = 10) annotation(
        Placement(visible = true, transformation(origin = {130, -6}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
      Modelica.Thermal.HeatTransfer.Components.Convection convection2[cooler_hside.nNodes] annotation(
        Placement(visible = true, transformation(origin = {120, 18}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
      Modelica.Blocks.Routing.Replicator replicator1(nout = cooler_hside.nNodes) annotation(
        Placement(visible = true, transformation(origin = {90, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Routing.Replicator replicator2(nout = cooler_cside.nNodes) annotation(
        Placement(visible = true, transformation(origin = {90, 18}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Constant const(k = 5000) annotation(
        Placement(visible = true, transformation(origin = {60, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Vessels.ClosedVolume volume(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, V = 1 * 0.001, nPorts = 2, use_HeatTransfer = true, use_portsData = false) annotation(
        Placement(visible = true, transformation(origin = {210, -70}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
      Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow prescribedHeatFlow1 annotation(
        Placement(visible = true, transformation(origin = {210, -38}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
      Modelica.Blocks.Sources.Ramp ramp_heat_generation(duration = 10, height = 10 * 1000, offset = 100 * 1000, startTime = 100) annotation(
        Placement(visible = true, transformation(origin = {198, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Pipes.DynamicPipe pipe1(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, diameter = 0.02, length = 2, modelStructure = Modelica.Fluid.Types.ModelStructure.a_vb, nNodes = 2, use_HeatTransfer = false) annotation(
        Placement(visible = true, transformation(origin = {170, -110}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Fluid.Sources.Boundary_ph boundary(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, nPorts = 1, p = 101.325 * 1000, use_h_in = true, use_p_in = true) annotation(
        Placement(visible = true, transformation(origin = {-110, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
      Modelica.Fluid.Vessels.ClosedVolume tank(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, T_start = 15 + 273.15, V = 20 * 0.001, nPorts = 2, use_HeatTransfer = false, use_portsData = false) annotation(
        Placement(visible = true, transformation(origin = {-110, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sources.Boundary_pT boundary1(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47, nPorts = 1, p = 101.325 * 1000, use_p_in = true) annotation(
        Placement(visible = true, transformation(origin = {70, -100}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.SpecificEnthalpy specificEnthalpy(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {110, -120}, extent = {{-10, -10}, {10, 10}}, rotation = 180)));
      Modelica.Fluid.Vessels.ClosedVolume volume1(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase, T_start = 15 + 273.15, V = 1 * 0.001, nPorts = 2, use_HeatTransfer = false, use_portsData = false) annotation(
        Placement(visible = true, transformation(origin = {180, 120}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_m_flow_coolant(duration = 10, height = 0.2, offset = 2, startTime = 160) annotation(
        Placement(visible = true, transformation(origin = {-30, 120}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.Pressure pressure(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase) annotation(
        Placement(visible = true, transformation(origin = {4, -60}, extent = {{-10, 10}, {10, -10}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue(significantDigits = 4, use_numberPort = true)  annotation(
        Placement(visible = true, transformation(origin = {-10, 27}, extent = {{-12, -9}, {12, 9}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue1(significantDigits = 5, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {-66, -28}, extent = {{-12, -8}, {12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue2(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {-22, -32}, extent = {{12, -8}, {-12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue3(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {32, -28}, extent = {{-12, -8}, {12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue4(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {2, -76}, extent = {{12, -7}, {-12, 7}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue5(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {90, 100}, extent = {{-12, -8}, {12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue6(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {160, 100}, extent = {{-12, -8}, {12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue7(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {156, -30}, extent = {{12, -8}, {-12, 8}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue8(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {219, -109}, extent = {{-13, -7}, {13, 7}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue9(significantDigits = 4, use_numberPort = true) annotation(
        Placement(visible = true, transformation(origin = {144, -92}, extent = {{-12, -8}, {12, 8}}, rotation = 0)));
      Modelica.Blocks.Sources.Constant const_p_tank(k = 101.325 * 1000) annotation(
        Placement(visible = true, transformation(origin = {-140, -110}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {-80, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature1(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {-20, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature2(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {158, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature3(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {200, -100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature4(redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47) annotation(
        Placement(visible = true, transformation(origin = {130, -110}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature5(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase) annotation(
        Placement(visible = true, transformation(origin = {60, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
      Modelica.Fluid.Sensors.TemperatureTwoPort temperature6(redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase) annotation(
        Placement(visible = true, transformation(origin = {130, 100}, extent = {{10, -10}, {-10, 10}}, rotation = -90)));
      Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heatFlowSensor[cooler_hside.nNodes] annotation(
        Placement(visible = true, transformation(origin = {120, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
      Modelica.Blocks.Math.Sum sum1(nin = cooler_hside.nNodes)  annotation(
        Placement(visible = true, transformation(origin = {150, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
    equation
      connect(volume1.ports[1], boundary3.ports[1]) annotation(
        Line(points = {{180, 110}, {210, 110}}, color = {0, 127, 255}, thickness = 0.5));
      connect(const.y, replicator1.u) annotation(
        Line(points = {{71, -10}, {73, -10}, {73, -30}, {78, -30}}, color = {0, 0, 127}));
      connect(const.y, replicator2.u) annotation(
        Line(points = {{71, -10}, {73, -10}, {73, 18}, {78, 18}}, color = {0, 0, 127}));
      connect(replicator2.y, convection2.Gc) annotation(
        Line(points = {{101, 18}, {110, 18}}, color = {0, 0, 127}, thickness = 0.5));
      connect(heatCapacitor1.port, convection2.solid) annotation(
        Line(points = {{120, -6}, {120, 8}}, color = {191, 0, 0}, thickness = 0.5));
      connect(replicator1.y, convection1.Gc) annotation(
        Line(points = {{101, -30}, {110, -30}}, color = {0, 0, 127}, thickness = 0.5));
      connect(heatCapacitor1.port, convection1.solid) annotation(
        Line(points = {{120, -6}, {120, -20}}, color = {191, 0, 0}, thickness = 0.5));
      connect(convection1.fluid, cooler_hside.heatPorts) annotation(
        Line(points = {{120, -40}, {120, -46}}, color = {191, 0, 0}, thickness = 0.5));
      connect(speed1.flange, powerSensor1.flange_a) annotation(
        Line(points = {{-60, 50}, {-50, 50}, {-50, 28}}));
      connect(powerSensor1.flange_b, pump1.shaft) annotation(
        Line(points = {{-50, 8}, {-50, -40}}));
      connect(from_rpm1.y, speed1.w_ref) annotation(
        Line(points = {{-89, 50}, {-83, 50}, {-83, 50}, {-83, 50}}, color = {0, 0, 127}));
      connect(ramp_pump_N.y, from_rpm1.u) annotation(
        Line(points = {{-119, 70}, {-116, 70}, {-116, 50}, {-113, 50}}, color = {0, 0, 127}));
      connect(ramp_heat_generation.y, prescribedHeatFlow1.Q_flow) annotation(
        Line(points = {{209, -10}, {210, -10}, {210, -28}}, color = {0, 0, 127}));
      connect(prescribedHeatFlow1.port, volume.heatPort) annotation(
        Line(points = {{210, -48}, {210, -60}}, color = {191, 0, 0}));
      connect(pipe.port_b, volume.ports[1]) annotation(
        Line(points = {{194, -50}, {200, -50}, {200, -70}}, color = {0, 127, 255}));
      connect(boundary.ports[1], tank.ports[1]) annotation(
        Line(points = {{-110, -70}, {-110, -50}}, color = {0, 127, 255}, thickness = 0.5));
      connect(boundary1.ports[1], specificEnthalpy.port) annotation(
        Line(points = {{80, -100}, {95, -100}, {95, -110}, {110, -110}}, color = {0, 127, 255}));
      connect(volumeFlowRate1.port_b, cooler_hside.port_a) annotation(
        Line(points = {{40, -50}, {110, -50}}, color = {0, 127, 255}));
      connect(ramp_m_flow_coolant.y, boundary2.m_flow_in) annotation(
        Line(points = {{-19, 120}, {-17, 120}, {-17, 118}, {-1, 118}}, color = {0, 0, 127}));
      connect(pressure.port, volumeFlowRate1.port_a) annotation(
        Line(points = {{4, -50}, {20, -50}}, color = {0, 127, 255}));
      connect(powerSensor1.power, realValue.numberPort) annotation(
        Line(points = {{-39, 26}, {-25.75, 26}, {-25.75, 27}, {-24, 27}}, color = {0, 0, 127}));
      connect(volumeFlowRate1.V_flow, realValue3.numberPort) annotation(
        Line(points = {{30, -39}, {30, -34}, {18, -34}, {18, -28}}, color = {0, 0, 127}));
      connect(pressure.p, realValue4.numberPort) annotation(
        Line(points = {{15, -60}, {15, -76}}, color = {0, 0, 127}));
      connect(const_p_tank.y, boundary1.p_in) annotation(
        Line(points = {{-129, -110}, {-33.5, -110}, {-33.5, -92}, {58, -92}}, color = {0, 0, 127}));
      connect(const_p_tank.y, boundary.p_in) annotation(
        Line(points = {{-128, -110}, {-118, -110}, {-118, -92}}, color = {0, 0, 127}));
      connect(specificEnthalpy.h_out, boundary.h_in) annotation(
        Line(points = {{100, -120}, {-114, -120}, {-114, -92}}, color = {0, 0, 127}));
      connect(tank.ports[2], temperature.port_a) annotation(
        Line(points = {{-110, -50}, {-90, -50}}, color = {0, 127, 255}));
      connect(temperature.port_b, pump1.port_a) annotation(
        Line(points = {{-70, -50}, {-60, -50}}, color = {0, 127, 255}));
      connect(temperature.T, realValue1.numberPort) annotation(
        Line(points = {{-80, -38}, {-80, -28}}, color = {0, 0, 127}));
      connect(pump1.port_b, temperature1.port_a) annotation(
        Line(points = {{-40, -50}, {-30, -50}}));
      connect(temperature1.port_b, pressure.port) annotation(
        Line(points = {{-10, -50}, {4, -50}}, color = {0, 127, 255}));
      connect(temperature1.T, realValue2.numberPort) annotation(
        Line(points = {{-20, -38}, {-8, -38}, {-8, -32}}, color = {0, 0, 127}));
      connect(cooler_hside.port_b, temperature2.port_a) annotation(
        Line(points = {{130, -50}, {148, -50}}, color = {0, 127, 255}));
      connect(temperature2.port_b, pipe.port_a) annotation(
        Line(points = {{168, -50}, {174, -50}}, color = {0, 127, 255}));
      connect(temperature2.T, realValue7.numberPort) annotation(
        Line(points = {{158, -38}, {170, -38}, {170, -30}}, color = {0, 0, 127}));
      connect(pipe1.port_a, temperature3.port_b) annotation(
        Line(points = {{180, -110}, {200, -110}}, color = {0, 127, 255}));
      connect(volume.ports[2], temperature3.port_a) annotation(
        Line(points = {{200, -70}, {200, -90}}, color = {0, 127, 255}));
      connect(temperature3.T, realValue8.numberPort) annotation(
        Line(points = {{212, -100}, {212, -106.5}, {204, -106.5}, {204, -109}}, color = {0, 0, 127}));
      connect(temperature4.port_a, pipe1.port_b) annotation(
        Line(points = {{140, -110}, {160, -110}}, color = {0, 127, 255}));
      connect(specificEnthalpy.port, temperature4.port_b) annotation(
        Line(points = {{110, -110}, {120, -110}}, color = {0, 127, 255}));
      connect(temperature4.T, realValue9.numberPort) annotation(
        Line(points = {{130, -98}, {130, -92}}, color = {0, 0, 127}));
      connect(boundary2.ports[1], temperature5.port_a) annotation(
        Line(points = {{20, 110}, {60, 110}}, color = {0, 127, 255}));
      connect(temperature5.T, realValue5.numberPort) annotation(
        Line(points = {{71, 100}, {75, 100}}, color = {0, 0, 127}));
      connect(temperature5.port_b, cooler_cside.port_a) annotation(
        Line(points = {{60, 90}, {60, 76}, {110, 76}}, color = {0, 127, 255}));
      connect(cooler_cside.port_b, temperature6.port_a) annotation(
        Line(points = {{130, 76}, {130, 90}}, color = {0, 127, 255}));
      connect(temperature6.port_b, volume1.ports[2]) annotation(
        Line(points = {{130, 110}, {180, 110}}, color = {0, 127, 255}));
      connect(temperature6.T, realValue6.numberPort) annotation(
        Line(points = {{141, 100}, {145, 100}}, color = {0, 0, 127}));
      connect(heatFlowSensor.port_b, cooler_cside.heatPorts) annotation(
        Line(points = {{120, 60}, {120, 72}}, color = {191, 0, 0}, thickness = 0.5));
      connect(heatFlowSensor.port_a, convection2.fluid) annotation(
        Line(points = {{120, 40}, {120, 28}}, color = {191, 0, 0}, thickness = 0.5));
      connect(heatFlowSensor.Q_flow, sum1.u) annotation(
        Line(points = {{130, 50}, {138, 50}}, color = {0, 0, 127}, thickness = 0.5));
      annotation(
        experiment(StartTime = 0, StopTime = 260, Tolerance = 1e-06, Interval = 0.05),
        __OpenModelica_simulationFlags(lv = "LOG_STATS", s = "dassl"),
        Diagram(coordinateSystem(extent = {{-160, -140}, {240, 140}}, initialScale = 0.1), graphics = {Rectangle(origin = {108, 28}, extent = {{-62, 96}, {40, -101}}), Text(origin = {94, 128}, extent = {{-34, 4}, {34, -4}}, textString = "Heat Exchanger"), Text(origin = {2, 96}, extent = {{-34, 4}, {34, -4}}, textString = "coolant flow line")}),
        __OpenModelica_commandLineOptions = "");
    end CoolingSystem_ex01;
    
    ——————————————————————————-

    mediumのredeclare; 黄色ハイライト部

     *OpenModelica ver 1.16.0 以降ではparameterウィンドウから設定出来るようになっている。しかし,現状この機能を有効化すると動作が遅いので,本連載ではソースコードに直接記入する方式を続ける.
     OpenModelica の表示を、text viewに切り替える。そして、モデルソースコード内に、前項に示したソースコード中で黄色ハイライトで示されている記述を直接書き足す。これらの記述で、使用する物性モデルを指定する。
     本例題では,循環流路の流体にグリコールを,冷却流体に水を使うよう設定する.

    pumpの揚程 vs. 体積流量、断熱効率の特性設定; 赤色ハイライト部

     設定すべき事項、設定値共にpumpingSystem_ex01の回のpumpと同一なのでコピー&ペーストすれば良い。解説も省略する。

シミュレーション実行&結果評価

 それでは、観たいvariableの値や動きを評価してゆこう。
 本連載はOpenModelicaでモデルを組む演習が主目的なのでサクサク観てゆく。本記事では答え合わせとして軽い解説で進めるが、実用としてModelica,1DCAEを実物/試験を再現したり、設計予測に使えるようになったら、本来はこの段階の考察が最も重要かつ時間をかけるべきところだ。その点は憶えておいて頂きたい。

    Input

    意図通りの操作を与えられているか・反映されているかを,rampのoutout connector以外のvariableで確認する.
    1. 循環回路流体(グリコール47)への熱量投入

    2.   
    3. 冷媒(水)の質量流量

    4.   

    Output

    1. 両流体回路の各部の温度
    2.  下記に図中の各線がどの温度意味しているかを示す.
      1. tank.medium: 循環回路流体,タンク内温度(供給ポンプ入口温度)
      2. temperature2.T: 循環回路流体,熱交換器出口温度
      3. temperature3.T: 循環回路流体,受熱後温度
      4. temperature5.T: 冷媒,供給温度
      5. volume1.medium.T: 冷媒,熱交換器出口温度
        
       熱交換器を境に循環流体の温度が下がり,冷媒温度が上がって熱平衡状態が出来ていることが読み取れる.また,循環流体と冷媒の出口温度は非常に近く,熱交換器は冷媒の熱容量をほぼ総て使い尽くして熱を受け渡していることも判る.
       なお,一時的にタンク内温度と受熱後温度に差が出るのは,タンクおよび流路各所に体積があることによる遅れ.

        
    3. 熱交換器内の計算要素温度
    4.  下記に図中の各線がどの温度意味しているかを示す.
      1. cooler_hside.mediums[1].T: 高温側,入口最寄り要素
      2. cooler_hside.mediums[5].T: 高温側,中間地点要素
      3. cooler_hside.mediums[10].T: 高温側,出口最寄り要素
      4. cooler_cside.mediums[1].T: 低温側,入口最寄り要素
      5. cooler_cside.mediums[5].T: 低温側,中間地点要素
      6. cooler_cside.mediums[10].T: 低温側,出口最寄り要素
        
       高温側で入口から出口に向かって温度が下がっていき,低温側で温度が上がりゆくのが読み取れる.当然,高温側・低温側の温度は近づくが一致することは無い.前述した通り,この例では出口温度は極めて近くなっており,熱交換器は冷媒の熱容量をほぼ使い切っている(供給する冷媒の量・温度に対して,熱交換器の熱透過率(伝熱面積と熱伝達率の積)が十分大きい.).
       また,温度変化は両側共に入口に近い所ほど大きく,出口に向かうに従い小さく,飽和してゆく.出口に向かうほど高温側・低温側の温度差が小さく,伝熱量が小さくなってゆくためだ.

        
    5. 循環回路の受熱・排熱
    6.  定常状態では一致しており,熱収支が成立しているのが読み取れる.過渡状態では,一時的に熱量の一部が各所Volumeの流体温度,個体部の温度を上昇される為に使われるため,受熱量と排熱量に差が生じる.受熱増加に対しては排熱量は増えるのが遅れ,冷媒流量増加に対しては一時的に排熱過多となっている.

        
    7. 始点質量流量(タンク流入)と終点質量流量
    8.  循環回路をなす流路で,定常状態では始点と終点で質量保存が成立していることが読み取れる.過渡状態では,温度の変化に伴う(と若干の圧縮性)による密度変化が各部で違いが有る為に出口と入口に若干差が生じる.

        
    9. [参考]循環回路各部の流体圧力
    10.  参考に示しておく.温度に対応して粘度が変わる事により,熱交換器出口と受熱後の圧力がそれぞれ僅かだが変化しているのが判る.

        

      [参考]Result Diagram

       参考に,代表3状態の温度分布をモデルのdiagramと共に示す.(この結果表示は,OpenModelicaでは ver1.19のbeta版以降)
      1. 時刻98 [s],初期化後静定・受熱量増加前

      2.   
      3. 時刻158 [s], 受熱量増加後静定・冷媒増加前

      4.   
      5. 時刻260 [s], 冷媒増加後静定

      6.   

最後に

 本例題で,循環した流路を持つ流体回路の作成と,熱収支が成立するよう陰的に各部温度が決まる流体回路の計算を習得して頂けたかと思う.これらのモデリングスキル(+これ以前の記事で習得した内容)を駆使すれば,ピストンエンジンの冷却水のようなシステムのシミュレーションが出来ることを期待できる.是非活かしてモデリング&シミュレーションのレパートリーを増やしてほしい.
 本例題は以上。

例モデルに関する情報

 本記事で取り上げたモデルは専用の「WalkingInWorldOfThermoFluid」ライブラリに公開しており、その情報を記しておく。ソースコードは本記事にも記載したが、直接OpenModelicaで読み込みたい方はダウンロードしてGPL3の範囲内で自由に使っていただいて構わない。
リンク:[連載]Modelicaによる熱流体の世界の歩き方 の記事一覧ページ
以上

コメント

タイトルとURLをコピーしました