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

目的

 本例題が目的としていることは大きく下記の2つ。
  • Modelcia Standard Libraryのコンポーネントのみを使って,熱機関の一つ,ガスタービンエンジンの最も簡素な形態のものをモデル化する事を学ぶ.
  •  *ただし,個々の要素特性の挙動は疑似的なものであり,圧縮機やタービンのマップを完全に模擬したものではない.
  • 計算結果から,ブレイトンサイクルの簡易p-v線図を作る.
  • Modelcia Standard Libraryのpumpコンポーネントを圧縮機,タービンとして使う.

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

作ろうとしているものを手書きで書き下すのは、今回も定型作業として実施しておこう。
  
 こちらは圧縮機の特性マップと呼ばれるもの.ガスタービン/ターボチャージャーの作動状態を示すのによく使われる.
 縦軸が圧力比(=圧縮機の仕事=翼の揚力係数),横軸に流量(質量流量ではなく,修正流量というものなのだがここでは割愛)をとり,そこに等回転線と呼ばれる,回転数(機械回転数ではなく,修正流量というもの.割愛)一定の線が引かれた絵となる.
 等回転線は右肩下がり曲線となっており,回転が一定の時,昇圧が大きくなると吸い込める流量が減る事を意味する.(回転する翼を中心に考えると,流入してくる流れが減ると,流れと翼の相対的な角度が大きくなって翼揚力が大きくなる,とも解釈できる.)これはガスタービン/ターボ圧縮機を備えたシステムの挙動を考えるときに重要となる.
  
 一方で,タービンもターボ機械であり,通過流量と膨張の圧力比についての関係を示すマップが存在するが,圧縮機に比べるとシンプルで定性的に理解が容易なもの.
 順圧力勾配なので,オリフィス,バルブと同じように圧力比が大きくなると流量は増える.圧縮性流体なのでチョークが発生し,あるところから修正流量(図の縦軸)が増加しなくなる.
 圧縮機同様に,回転数毎に圧力比-vs.-フローの線が有る.しかし,異なるのはチョークに達していない作動領域であり,アイドリングのような非常に圧力比が小さい作動状態でなければタービンはチョークしている事が大半なので圧縮機ほど意識する必要は無い.
  
同じく定型作業として、モデル化対象物についての情報を纏める。極力簡潔に、箇条書きを並べるのがお勧め。

    モデル化対象のシステム

       今回モデリングするのはガスタービンエンジン(ターボシャフトエンジン).
       圧縮機が外気を吸い込み,断熱圧縮する.その圧縮された高圧空気に燃料を投入,燃焼させ加熱する.そして加熱された高温・高圧のガスがタービンと呼ばれる噴流を生むノズルと羽根車からなる機械を通過し,流体のエネルギを機械の回転エネルギに変換して取り出す.
       タービンで取り出された機械動力はシャフトを通して,一部が前述の圧縮機を駆動するのに使われる.それで残った機械動力が同様にシャフトで繋がるジェネレータを駆動したり,任意の機械を動かしたりして自由に使える動力とそして取り出される.
       取り扱うのは構成が最も単純な,1軸ガスタービンで,圧縮機・タービン・回転軸がそれぞれ1つで,動力取出しの軸も圧縮機の軸と1繋ぎとなっているもの.発電用の,機械回転数が外部から調速機で拘束されているものを想定する(ターボプロップやヘリコプタエンジンでも,プロペラ・ロータの機械回転数は調速機で一定に保って作動させる).

    内包する物理現象・前提:

    1. 作動流体は乾燥空気.燃焼による物性変化は含めない.
    2. 作動流体の断熱圧縮.
    3. 等圧加熱.
    4. 燃料投入による作動流体の質量流量増加は無視する.
    5. 断熱膨張による作動流体からの仕事の取り出し.
    6. 圧縮機,タービン共に,断熱効率は一定.
    7. 回転機械回路を通した,仕事の熱機関へのフィードバック(取り出した仕事の一部が熱機関の駆動そのものに使われる.)
    8. PI制御:燃焼器(等圧加熱)出口のガス温度を目標値にし,投入熱量を制御器が決定する.
    9. エンジン・ジェネレータ軸の機械回転数は外部から拘束される.
    10.  発電用エンジン・ヘリコプタ発動機・ターボプロップエンジンは,基本,機械回転数をgovernerで一定に保って運用する.
       軸の回転が一定に保たれていて,その軸が圧縮機とひと繋ぎになっている事で興味深い挙動が生じる.前述の圧縮機マップの等回転ラインを見れば当たり前の事だが,エンジンのパワーを上げる(投入燃料を増やす)と,圧縮機の昇圧が大きくなると共に,エンジンを流れる空気の流量は減るという動きとなる.
       この動きは他の多くの別形態のエンジン(ピストンなど)でも,同じガスタービンを用いた機関でもジェットエンジンでは生じない,かなり特有なものなので是非押さえておきたい.
        
       因みに,タービンの作動点の動きは下図の通り.特に理解が難しい所は無い動きである.(実際には,タービンによっては,チョーク後の等回転線が完全には重ならず,チョーク領域でも上下に動きが有ったりする.1D計算では,特性線が物理式から算出されるものではなく,カーブデータ/テーブルを直接与える以上,そこはどんな特性線を与えるか次第.)
        

    境界条件(Input):

    1. 圧縮機入口圧力
    2. 圧縮機入口温度
    3. タービン出口圧力
    4. 燃焼器出口ガス温度目標値
    5. これを操作し応答を観る.
    6. エンジン・ジェネレータ軸の機械回転数

    Output(注目する出力):

    1. ジェネレータ発生出力
    2. 圧縮機,タービン,ジェネレータのpower
    3. 熱効率
    4. 燃焼器出口及び排気の温度
    5. 圧縮機昇圧量
    6. 圧縮機(エンジン)通過質量流量
    7. 圧縮機作動点変化(昇圧vs.通過質量流量)
    8. これが今回で一番重要,と言うか,”ガスタービンエンジンらしさ”の挙動を示すもの.
       種々のガスタービン系の熱機関において,出力を変動させるべく熱量投入量を増減させると,通過空気質量流量,ターボ機械(圧縮機/タービン)のパワー,機械回転数が変動するものなのだが,機械回転を一定に保って作動させるガスタービンエンジンでは,通過空気質量流量とターボ機械の
    9. タービン入口修正流量
    10. 熱サイクルp-v diagram

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

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

コンポーネントの配置

 下図の通りにコンポーネントを配置、接続する。
 コンポーネントインスタンスの名前については、適宜解りやすい名前に変えてくれて構わない。
また,接続線の太さや実践/点線の表示も個人の好みで決めれば良いので模倣する必要は無い.
 

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

     必要なコンポーネントを見つけるのは慣れていないと意外と苦労する作業なので、使用する総てのコンポーネントをリストアップしておく。なお,別途コンポーネント一覧と概要を解説したページを設けるので解説は省略する。
    1. Modelica.Fluid.System
    2. Modelica.Fluid.Sources.Boundary_pT
    3. Modelica.Fluid.Machines.Pump
    4. Modelica.Fluid.Vessels.ClosedVolume
    5. Modelica.Fluid.Machines.ControlledPump
    6. Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow
    7. Modelica.Mechanics.Rotational.Sources.Speed
    8. Modelica.Mechanics.Rotational.Sources.Torque
    9. Modelica.Blocks.Continuous.PI
    10. Modelica.Blocks.Math.Feedback
    11. Modelica.Blocks.Sources.Ramp
    12. Modelica.Blocks.Math.Division
    13. Modelica.Blocks.Math.Gain
    14. Modelica.Blocks.Math.UnitConversions.From_rpm
    15. Modelica.Blocks.Sources.RealExpression
    16. Modelica.Blocks.Interaction.Show.RealValue
    17. Modelica.Mechanics.Rotational.Sensors.SpeedSensor
    18. Modelica.Mechanics.Rotational.Sensors.PowerSensor
    19. Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor
    20. Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor
    21. Modelica.Fluid.Sensors.Pressure
    22. Modelica.Fluid.Sensors.Temperature
    23. Modelica.Fluid.Sensors.SpecificEnthalpy
    24. Modelica.Fluid.Sensors.MassFlowRate

parameterの設定

 各コンポーネントのparameter設定を示す。コンポーネントを右クリックしてparametersを選択するか、ダブルクリックするとparametersウィンドウが現れるので、必要箇所に値を設定する。
 尚、デフォルト設定のままにしておいて済むコンポーネント、parameterは記載を省略する。また、parameterの意味もparameterウィンドウ上の記載から意味が理解可能なものは省略/簡潔に済ます。
 下記リスト中で ” :: ” 表記をしているものは,タブやタブ内のグループによる階層構造を示す.表記が無いものは「general」タブ内のものである.
  1. boundary
    1. use_p_in: true
    2. use_T_in: true
  2. ramp_p1
    1. height: 0
    2. duration: 0
    3. offset: 101.325*1000
    4. startTime: 10 (値を動かさないので何でも良い)
  3. ramp_T1
    1. height: 0
    2. duration: 10
    3. offset: 288.15
    4. startTime: 10 (値を動かさないので何でも良い)
  4. PR3q1
    1. y: p3.p/p1.p (他インスタンスを参照した計算式を記述)
  5. Wc1
    1. y: m_flow_1.m_flow * sqrt(T1.T / 288.15) / (p1.p / (101.325 * 1000)) (他インスタンスを参照した計算式を記述) 
  6. CmpByPump
    1. N_nominal: 10000
    2. Assumptions::allowFlowReversal: true
    3. Assumptions::V: 1
    4. Assumptions::energyDynamics: SteadyState
    5. Assumptions::massDynamics: SteadyState
    6. Initialization::T_start: 500
    7. Initialization::p_b_start: 2*system.p_start
    8. Initialization::m_flow_start: 2
  7. Brn
    1. V: 0.01
    2. use_portsData: false
    3. Assumptions::use_HeatTransfer: true
  8. PR4q5
    1. y: p4.p / p5.p
  9. Wc4
    1. y: TrbByPump.port_b.m_flow * sqrt(T4.T / 288.15) / (p4.p / (101.325 * 1000))
  10. TrbByPump
    1. p_a_nominal: 500 * 1000
    2. p_b_nominal: 100 * 1000
    3. m_flow_nominal: -5 (負の値を入力しておく事が重要)
    4. control_m_flow: true
    5. use_m_flow_set: true
    6. N_nominal: -1000 (負の値を入力しておく事が重要)
    7. Assumptions::V: 0.01
    8. Assumptions::energyDynamics: SteadyState
    9. Assumptions::massDynamics: SteadyState
  11. calc_Wc_Trb
    1. y: kFlowTrb * (1 – exp(-(PRtrb.y – 1) / kFlowChokeTrb))
    2.  タービンの圧力比から入口の修正流量を算出する為の式.上述した修正流量-vs.-圧力比の曲線形状を指数関数で近似する(1階線形微分方程式の解の曲線形状).
  12. calc_m_flow_Trb
    1. y: calc_Wc_Trb.y * (p4.p / (101.325 * 1000)) / sqrt(T4.T / 288.15)
    2.  指数関数式で算出した入口修正流量と入口状態量から,流入する質量流量を算出する.
  13. gain
    1. k: -1
  14. calc_Trb_trq
    1. y: -TrbByPump.W_total / w_Trb.w
  15. boundary_pT
    1. p: 100*1000
    2. T: 288.15
  16. ramp_N
    1. height: 0
    2. duration: 5
    3. offset: 10000
    4. startTime: 20
  17. ctrlHeatPI
    1. k: 1000
    2. T: 0.01
    3. initType: Modelica.BlocksTypes.Init.SteadyState
    4. x_start: 1000
  18. ramp_TbrnOut_tgt
    1. height: 1000
    2. 燃焼器出口温度を1500[k]まで上昇させる.専門書の例題等で出てくる妥当な範囲の値.
    3. duration: 5
    4. offset: 500
    5. 最初はエンジンが自立する程度の温度を目標値にする.
    6. startTime: 10
  19. calcWfuel
    1. k: 1 / (43 * 10 ^ 6)

ソースコード

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

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

     コンパイルエラーや、計算結果が意図通りのものとならないような場合に比較・チェック用に参照して欲しい。尚、annotation()の部分はGUI上の配置位置や向きで値が変わるものなので、比較する必要は無い。
    ——————————————————————————-
    model GasTurbineEngine_1sp_ByCtrldPump_ex01
      extends Modelica.Icons.Example;
      //--------------------
      import units= Modelica.SIunits;
      //--------------------
      package engineFluid = Modelica.Media.Air.DryAirNasa;
      //redeclare package Medium = fluid1
      //----------
      parameter Real kFlowCmp = 1;
      parameter Real kHeadCmp = 1;
      parameter Real arrFlowCmp[2] = {kFlowCmp * 0.0, kFlowCmp * 35.0};
      parameter Real arrHeadCmp[2] = {kHeadCmp * 12000, kHeadCmp * 0};
      //---
      parameter Real kFlowTrb = 5.5;
      parameter Real kFlowChokeTrb = 0.11;
      //--------------------
      units.Pressure arr_p[5];
      units.SpecificVolume arr_v[5];
      //--------------------
      inner Modelica.Fluid.System system(energyDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, massDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, momentumDynamics = Modelica.Fluid.Types.Dynamics.SteadyState) annotation(
        Placement(visible = true, transformation(origin = {-272, 28}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sources.Boundary_pT boundary(redeclare package Medium = Modelica.Media.Air.DryAirNasa, T = 1000, nPorts = 4, p = 101.325 * 1000, use_T_in = true, use_p_in = true) annotation(
        Placement(visible = true, transformation(origin = {-250, 76}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_N(duration = 5, height = 0, offset = 10000, startTime = 20) annotation(
        Placement(visible = true, transformation(origin = {222, -74}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sources.Speed speed1 annotation(
        Placement(visible = true, transformation(origin = {158, -74}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_p1(duration = 10, height = 0 * 101.325 * 1000, offset = 101.325 * 1000, startTime = 10) annotation(
        Placement(visible = true, transformation(origin = {-290, 96}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_T1(duration = 10, height = 0, offset = 288.15, startTime = 10) annotation(
        Placement(visible = true, transformation(origin = {-290, 66}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Math.UnitConversions.From_rpm from_rpm1 annotation(
        Placement(visible = true, transformation(origin = {190, -74}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Fluid.Machines.Pump CmpByPump(redeclare package Medium = Modelica.Media.Air.DryAirNasa, redeclare function flowCharacteristic = Modelica.Fluid.Machines.BaseClasses.PumpCharacteristics.linearFlow(V_flow_nominal = arrFlowCmp, head_nominal = arrHeadCmp), redeclare function efficiencyCharacteristic = Modelica.Fluid.Machines.BaseClasses.PumpCharacteristics.constantEfficiency(eta_nominal = 0.9), N_nominal = 10000, T_start = 500, V(displayUnit = "l") = 0.001, allowFlowReversal = true, checkValve = false, energyDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, m_flow_start = 2, massDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, nParallel = 1, p_b_start = 2 * system.p_start) annotation(
        Placement(visible = true, transformation(origin = {-160, 76}, extent = {{-20, 20}, {20, -20}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sensors.PowerSensor pwrCmp annotation(
        Placement(visible = true, transformation(origin = {-128, -74}, extent = {{-6, 6}, {6, -6}}, rotation = 180)));
      Modelica.Fluid.Sensors.MassFlowRate m_flow_1(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-205, 76}, extent = {{-5, 5}, {5, -5}}, rotation = 0)));
      Modelica.Fluid.Sensors.Pressure p3(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-123, 76}, extent = {{-6, -6}, {6, 6}}, rotation = 270)));
      Modelica.Fluid.Sensors.Pressure p1(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-227, 68}, extent = {{-5, -5}, {5, 5}}, rotation = 270)));
      Modelica.Blocks.Interaction.Show.RealValue realValue(significantDigits = 6) annotation(
        Placement(visible = true, transformation(origin = {-151, -92}, extent = {{17, -10}, {-17, 10}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue2(significantDigits = 6) annotation(
        Placement(visible = true, transformation(origin = {-227, 52}, extent = {{15, -10}, {-15, 10}}, rotation = 0)));
      Modelica.Blocks.Interaction.Show.RealValue realValue3(significantDigits = 6) annotation(
        Placement(visible = true, transformation(origin = {-101, 34}, extent = {{-15, -10}, {15, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.Temperature T3(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-98, 71}, extent = {{-6, -5}, {6, 5}}, rotation = 180)));
      Modelica.Blocks.Interaction.Show.RealValue realValue11(significantDigits = 6) annotation(
        Placement(visible = true, transformation(origin = {-86, 44}, extent = {{-16, -10}, {16, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.Temperature T1(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-235, 95}, extent = {{-5, -5}, {5, 5}}, rotation = 0)));
      Modelica.Blocks.Sources.RealExpression Wc1(y = m_flow_1.m_flow * sqrt(T1.T / 288.15) / (p1.p / (101.325 * 1000))) annotation(
        Placement(visible = true, transformation(origin = {-220, 100}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.RealExpression PR3q1(y = p3.p / p1.p) annotation(
        Placement(visible = true, transformation(origin = {-220, 116}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.SpecificEnthalpy h1(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-215, 89}, extent = {{-5, -5}, {5, 5}}, rotation = 0)));
      Modelica.Fluid.Sensors.SpecificEnthalpy h3(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {-107, 87}, extent = {{-5, -5}, {5, 5}}, rotation = 0)));
      Modelica.Fluid.Sensors.Pressure p5(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {108, 60}, extent = {{-4, -4}, {4, 4}}, rotation = 180)));
      Modelica.Blocks.Sources.RealExpression calc_Wc_Trb(y = kFlowTrb * (1 - exp(-(PRtrb.y - 1) / kFlowChokeTrb))) annotation(
        Placement(visible = true, transformation(origin = {46, 12}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.Temperature T5(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {132, 61}, extent = {{-8, -7}, {8, 7}}, rotation = 180)));
      Modelica.Blocks.Math.Gain gain(k = -1) annotation(
        Placement(visible = true, transformation(origin = {86, 34}, extent = {{-6, -6}, {6, 6}}, rotation = 90)));
      Modelica.Blocks.Sources.RealExpression calc_m_flow_Trb(y = calc_Wc_Trb.y * (p4.p / (101.325 * 1000)) / sqrt(T4.T / 288.15)) annotation(
        Placement(visible = true, transformation(origin = {66, 18}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Fluid.Machines.ControlledPump TrbByPump(redeclare package Medium = Modelica.Media.Air.DryAirNasa, N_nominal = -1000, V = 0.01, control_m_flow = true, energyDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, m_flow_nominal = -5, massDynamics = Modelica.Fluid.Types.Dynamics.SteadyState, p_a_nominal = 500 * 1000, p_b_nominal = 100 * 1000, use_m_flow_set = true) annotation(
        Placement(visible = true, transformation(origin = {76, 76}, extent = {{20, 20}, {-20, -20}}, rotation = 0)));
      Modelica.Blocks.Math.Division PRtrb annotation(
        Placement(visible = true, transformation(origin = {59, 39}, extent = {{-5, 5}, {5, -5}}, rotation = -90)));
      Modelica.Fluid.Sensors.Temperature T4(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {16, 61}, extent = {{-8, -7}, {8, 7}}, rotation = 180)));
      Modelica.Fluid.Sources.Boundary_pT boundary_pT(redeclare package Medium = Modelica.Media.Air.DryAirNasa, T = 288.15, nPorts = 1, p = 100 * 1000) annotation(
        Placement(visible = true, transformation(origin = {188, 76}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Fluid.Sensors.MassFlowRate m_flow_5(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {147, 76}, extent = {{-5, 5}, {5, -5}}, rotation = 0)));
      Modelica.Fluid.Sensors.Pressure p4(redeclare package Medium = Modelica.Media.Air.DryAirNasa) annotation(
        Placement(visible = true, transformation(origin = {41, 60}, extent = {{4, -4}, {-4, 4}}, rotation = 180)));
      Modelica.Fluid.Vessels.ClosedVolume Brn(redeclare package Medium = Modelica.Media.Air.DryAirNasa, V = 0.01, use_HeatTransfer = true, use_portsData = false, nPorts = 2) annotation(
        Placement(visible = true, transformation(origin = {-46, 56}, extent = {{-20, 20}, {20, -20}}, rotation = 0)));
      Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow prescribedHeatFlow annotation(
        Placement(visible = true, transformation(origin = {-76, 148}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.Ramp ramp_TbrnOut_tgt(duration = 5, height = 1000, offset = 500, startTime = 10) annotation(
        Placement(visible = true, transformation(origin = {-183, 148}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temperatureSensor annotation(
        Placement(visible = true, transformation(origin = {-76, 174}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
      Modelica.Blocks.Math.Feedback feedback annotation(
        Placement(visible = true, transformation(origin = {-153, 148}, extent = {{-10, 10}, {10, -10}}, rotation = 0)));
      Modelica.Blocks.Continuous.PI ctrlHeatPI(T = 0.01, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1000, x_start = 1000) annotation(
        Placement(visible = true, transformation(origin = {-121, 148}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sensors.SpeedSensor w_Trb annotation(
        Placement(visible = true, transformation(origin = {54, -24}, extent = {{-6, -6}, {6, 6}}, rotation = 180)));
      Modelica.Mechanics.Rotational.Sensors.PowerSensor pwrTrb annotation(
        Placement(visible = true, transformation(origin = {74, -57}, extent = {{5, -5}, {-5, 5}}, rotation = 90)));
      Modelica.Blocks.Sources.RealExpression calc_Trb_trq(y = -TrbByPump.W_total / w_Trb.w) annotation(
        Placement(visible = true, transformation(origin = {48, -6}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Mechanics.Rotational.Sources.Torque torque_Trb annotation(
        Placement(visible = true, transformation(origin = {74, -15}, extent = {{-7, -7}, {7, 7}}, rotation = -90)));
      Modelica.Mechanics.Rotational.Sensors.PowerSensor powerGen annotation(
        Placement(visible = true, transformation(origin = {98, -74}, extent = {{10, 10}, {-10, -10}}, rotation = 180)));
      Modelica.Blocks.Interaction.Show.RealValue realValue1(significantDigits = 6) annotation(
        Placement(visible = true, transformation(origin = {117, -94}, extent = {{-17, -10}, {17, 10}}, rotation = 0)));
      Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heatAddedIntoEng annotation(
        Placement(visible = true, transformation(origin = {-66, 90}, extent = {{-6, 6}, {6, -6}}, rotation = -90)));
      Modelica.Blocks.Sources.RealExpression PR4q5(y = p4.p / p5.p) annotation(
        Placement(visible = true, transformation(origin = {-4, 36}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Sources.RealExpression Wc4(y = TrbByPump.port_b.m_flow * sqrt(T4.T / 288.15) / (p4.p / (101.325 * 1000))) annotation(
        Placement(visible = true, transformation(origin = {0, 22}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
      Modelica.Blocks.Math.Division calc_effThermal annotation(
        Placement(visible = true, transformation(origin = {112, -110}, extent = {{-6, -6}, {6, 6}}, rotation = 0)));
      Modelica.Blocks.Math.Gain calcWfuel(k = 1 / (43 * 10 ^ 6)) annotation(
        Placement(visible = true, transformation(origin = {-21, 120}, extent = {{-5, -5}, {5, 5}}, rotation = 0)));
      Modelica.Blocks.Math.Division calcFAR annotation(
        Placement(visible = true, transformation(origin = {1, 116}, extent = {{-7, -7}, {7, 7}}, rotation = 0)));
    equation
      arr_v[1] = 1.0/engineFluid.density_pTX(p = p1.p, T = T1.T, X = p1.port.Xi_outflow);
      arr_v[2] = 1.0/engineFluid.density_pTX(p = p3.p, T = T3.T, X = p3.port.Xi_outflow);
      arr_v[3] = 1.0/engineFluid.density_pTX(p = p4.p, T = T4.T, X = p4.port.Xi_outflow);
      arr_v[4] = 1.0/engineFluid.density_pTX(p = p5.p, T = T5.T, X = p5.port.Xi_outflow);
      arr_v[5] = arr_v[1];
      
      arr_p[1]= p1.p;
      arr_p[2]= p3.p;
      arr_p[3]= p4.p;
      arr_p[4]= p5.p;
      arr_p[5]= arr_p[1];
      //-----------
      
      connect(ramp_p1.y, boundary.p_in) annotation(
        Line(points = {{-279, 96}, {-270, 96}, {-270, 84}, {-262, 84}}, color = {0, 0, 127}));
      connect(ramp_T1.y, boundary.T_in) annotation(
        Line(points = {{-279, 66}, {-273, 66}, {-273, 80}, {-262, 80}}, color = {0, 0, 127}));
      connect(CmpByPump.port_b, p3.port) annotation(
        Line(points = {{-140, 76}, {-129, 76}}, color = {0, 127, 255}));
      connect(m_flow_1.port_b, CmpByPump.port_a) annotation(
        Line(points = {{-200, 76}, {-180, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(CmpByPump.shaft, pwrCmp.flange_b) annotation(
        Line(points = {{-160, 56}, {-160, -74}, {-134, -74}}, thickness = 1.5));
      connect(from_rpm1.y, speed1.w_ref) annotation(
        Line(points = {{179, -74}, {170, -74}}, color = {0, 0, 127}));
      connect(ramp_N.y, from_rpm1.u) annotation(
        Line(points = {{211, -74}, {201, -74}}, color = {0, 0, 127}));
      connect(realValue.numberPort, pwrCmp.power) annotation(
        Line(points = {{-131.45, -92}, {-123, -92}, {-123, -81}}, color = {0, 0, 127}));
      connect(realValue2.numberPort, m_flow_1.m_flow) annotation(
        Line(points = {{-209.75, 52}, {-205, 52}, {-205, 70.5}}, color = {0, 0, 127}));
      connect(realValue3.numberPort, p3.p) annotation(
        Line(points = {{-118.25, 34}, {-123, 34}, {-123, 69}}, color = {0, 0, 127}));
      connect(p3.port, T3.port) annotation(
        Line(points = {{-129, 76}, {-98, 76}}, color = {0, 127, 255}));
      connect(T3.T, realValue11.numberPort) annotation(
        Line(points = {{-102.2, 71}, {-109.2, 71}, {-109.2, 44}, {-104.2, 44}}, color = {0, 0, 127}));
      connect(boundary.ports[1], T1.port) annotation(
        Line(points = {{-240, 76}, {-235, 76}, {-235, 90}}, color = {0, 127, 255}));
      connect(boundary.ports[2], h1.port) annotation(
        Line(points = {{-240, 76}, {-215, 76}, {-215, 84}}, color = {0, 127, 255}));
      connect(CmpByPump.port_b, h3.port) annotation(
        Line(points = {{-140, 76}, {-107, 76}, {-107, 82}}, color = {0, 127, 255}));
      connect(TrbByPump.port_a, m_flow_5.port_a) annotation(
        Line(points = {{96, 76}, {142, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(p4.p, PRtrb.u1) annotation(
        Line(points = {{45, 60}, {45, 45}, {56, 45}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(TrbByPump.port_a, T5.port) annotation(
        Line(points = {{96, 76}, {132, 76}, {132, 68}}, color = {0, 127, 255}));
      connect(boundary_pT.ports[1], m_flow_5.port_b) annotation(
        Line(points = {{178, 76}, {152, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(TrbByPump.port_b, p4.port) annotation(
        Line(points = {{56, 76}, {41, 76}, {41, 64}}, color = {0, 127, 255}));
      connect(TrbByPump.port_a, p5.port) annotation(
        Line(points = {{96, 76}, {108, 76}, {108, 64}}, color = {0, 127, 255}));
      connect(gain.y, TrbByPump.m_flow_set) annotation(
        Line(points = {{86, 41}, {86, 59.6}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(p5.p, PRtrb.u2) annotation(
        Line(points = {{104, 60}, {104, 45}, {62, 45}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(TrbByPump.port_b, T4.port) annotation(
        Line(points = {{56, 76}, {16, 76}, {16, 68}}, color = {0, 127, 255}));
      connect(calc_m_flow_Trb.y, gain.u) annotation(
        Line(points = {{77, 18}, {86, 18}, {86, 27}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(Brn.ports[1], CmpByPump.port_b) annotation(
        Line(points = {{-46, 76}, {-140, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(Brn.ports[2], TrbByPump.port_b) annotation(
        Line(points = {{-46, 76}, {56, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(ramp_TbrnOut_tgt.y, feedback.u1) annotation(
        Line(points = {{-172, 148}, {-161, 148}}, color = {0, 0, 127}));
      connect(ctrlHeatPI.y, prescribedHeatFlow.Q_flow) annotation(
        Line(points = {{-110, 148}, {-86, 148}}, color = {0, 0, 127}));
      connect(feedback.y, ctrlHeatPI.u) annotation(
        Line(points = {{-144, 148}, {-133, 148}}, color = {0, 0, 127}));
      connect(temperatureSensor.T, feedback.u2) annotation(
        Line(points = {{-86, 174}, {-153, 174}, {-153, 156}}, color = {0, 0, 127}));
      connect(calc_Trb_trq.y, torque_Trb.tau) annotation(
        Line(points = {{59, -6}, {73, -6}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(torque_Trb.flange, w_Trb.flange) annotation(
        Line(points = {{74, -22}, {74, -24}, {60, -24}}));
      connect(pwrCmp.flange_a, powerGen.flange_a) annotation(
        Line(points = {{-122, -74}, {88, -74}}, thickness = 1.5));
      connect(powerGen.flange_b, speed1.flange) annotation(
        Line(points = {{108, -74}, {148, -74}}, thickness = 1.5));
      connect(temperatureSensor.port, Brn.heatPort) annotation(
        Line(points = {{-66, 174}, {-66, 56}}, color = {191, 0, 0}, thickness = 1));
      connect(realValue1.numberPort, powerGen.power) annotation(
        Line(points = {{97, -94}, {90, -94}, {90, -85}}, color = {0, 0, 127}));
      connect(prescribedHeatFlow.port, heatAddedIntoEng.port_a) annotation(
        Line(points = {{-66, 148}, {-66, 96}}, color = {191, 0, 0}, thickness = 1));
      connect(heatAddedIntoEng.port_b, Brn.heatPort) annotation(
        Line(points = {{-66, 84}, {-66, 56}}, color = {191, 0, 0}, thickness = 1));
      connect(torque_Trb.flange, pwrTrb.flange_a) annotation(
        Line(points = {{74, -22}, {74, -52}}, thickness = 1.5));
      connect(pwrTrb.flange_b, powerGen.flange_a) annotation(
        Line(points = {{74, -62}, {74, -74}, {88, -74}}, thickness = 1.5));
      connect(calc_effThermal.u1, powerGen.power) annotation(
        Line(points = {{105, -106}, {90, -106}, {90, -84}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(calc_effThermal.u2, heatAddedIntoEng.Q_flow) annotation(
        Line(points = {{105, -114}, {-22, -114}, {-22, 90}, {-60, 90}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(calcWfuel.y, calcFAR.u1) annotation(
        Line(points = {{-15.5, 120}, {-7, 120}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(ctrlHeatPI.y, calcWfuel.u) annotation(
        Line(points = {{-110, 148}, {-104, 148}, {-104, 120}, {-27, 120}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(m_flow_1.m_flow, calcFAR.u2) annotation(
        Line(points = {{-205, 70.5}, {-194, 70.5}, {-194, 112}, {-7, 112}}, color = {0, 0, 127}, pattern = LinePattern.Dash));
      connect(boundary.ports[3], m_flow_1.port_a) annotation(
        Line(points = {{-240, 76}, {-210, 76}}, color = {0, 127, 255}, thickness = 1));
      connect(boundary.ports[4], p1.port) annotation(
        Line(points = {{-240, 76}, {-232, 76}, {-232, 68}}, color = {0, 127, 255}));
      annotation(
        experiment(StartTime = 0, StopTime = 50, Tolerance = 1e-06, Interval = 0.1),
        __OpenModelica_simulationFlags(lv = "LOG_STATS", s = "dassl"),
        Diagram(coordinateSystem(extent = {{-300, -120}, {240, 220}}, initialScale = 0.1), graphics = {Rectangle(origin = {73, 39}, extent = {{-47, 73}, {47, -73}}), Text(origin = {71, 124}, extent = {{-33, 6}, {33, -6}}, textString = "Turbine"), Rectangle(origin = {189, -74}, extent = {{-49, 22}, {49, -22}}), Text(origin = {167, -32}, extent = {{-27, 6}, {27, -6}}, textString = "generator"), Text(origin = {206, -42}, extent = {{-30, 4}, {30, -4}}, textString = "Speed governed"), Rectangle(origin = {-126, 164}, extent = {{-74, 34}, {74, -34}}), Text(origin = {-163, 208}, extent = {{-39, 6}, {39, -6}}, textString = "Heat flow control"), Text(origin = {-122, 196}, extent = {{-70, 4}, {70, -4}}, textString = "target: gas temperature at outlet of burner")}),
        __OpenModelica_commandLineOptions = "--matchingAlgorithm=PFPlusExt --indexReductionMethod=dynamicStateSelection -d=initialization,NLSanalyticJacobian,nonewInst --maxMixedDeterminedIndex=10, --maxSizeLinearTearing=400, --maxSizeNonlinearTearing=600 ");
    end GasTurbineEngine_1sp_ByCtrldPump_ex01;
    
    
    ——————————————————————————-

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

     *OpenModelica ver 1.16.0 以降ではparameterウィンドウから設定出来るようになっている。
     OpenModelica の表示を、text viewに切り替える。そして、モデルソースコード内に、前項に示したソースコード中で黄色ハイライトで示されている記述を直接書き足す。これらの記述で、使用する物性モデル(本モデルでは水であること)を指定する。
     pumpingSystem_ex01の回でも述べたが、筆者はモデルの階層で一度「fluid1」というmediumを定義し、各コンポーネント内では = fluid1 と宣言している。これにより、参照した物性を変更する時に書き換える箇所を1か所で済ませる事が出来る。

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

     圧縮機に使用しているポンプコンポーネント「Pump」には、揚程vs.吐出体積流量と断熱効率の特性をfunctionで設定しなければならない。しかしMediaの宣言同様、OpenModelicaではGUI操作からは設定出来ないため、直接コードを書く。学習の為にひとまず動くモデルを作成するだけであれば、赤色ハイライト部をコピー&ペーストすればOK。
     設定内容について解説はここでは省略する.コンポーネント一覧と概要を解説したページに簡便な解説を記しているので意味を知りたい場合はそちらを参照されたい.
     今回は,揚程vs.吐出体積流量に1次関数特性のfunctionを,断熱効率に固定値を与える.
     本当は1次関数ではないのだが,圧縮機出口の体積流量とheadの関係が,圧力比-vs-修正流量に比べるとかなり線形に近い事,2次以上のカーブでは上手く計算が回るような設定を作る難易度が急に高くなる事から,本例題では1次関数で単純化する.
     ここで使う1次関数特性のfunctionは,x,yの点の配列を読込,回帰にて式の係数を算出してくれるもの.配列は,値を変えて計算を回し直し易いように,本モデルの頭であらかじめ宣言し,それをfunctionのredeclare時に呼び出す形を取っている.
     Turbineに使用しているポンプコンポーネント「ControlledPump」には断熱効率の特性をfunctionで設定しなければならない。本例題では,「Pump」と同様に,断熱効率を固定値で与える.
     
     Turbineの「ControlledPump」はチョークするような質量流量vs.圧力比特性をpump外部のRealExpressionコンポーネントで計算し,信号入力している.その質量流量算出に用いるカーブの,Turbineの大きさとチョーク特性(曲線の形)を決定付ける係数を,モデルの冒頭でparameterとして宣言し,簡単に値を変えて計算を回し直せるようにしている.上述の配列宣言の次の赤色ハイライト部がそれに当たる.

    簡易p-v線図を描くためのコード; 薄緑ハイライト部

     簡易p-v線図作成の為に,熱サイクルのpとvを格納する配列を用意し,計算モデルの計算結果をそれらに納める追加処理の方程式を記述する.
    import units= Modelica.SIunits;
    		
     -> 物理量のvariableをより短い文言で宣言できるように書いておく文.これにより,Modelica.SIunits.をunits.に省略できる.
    units.Pressure arr_p[5];
    units.SpecificVolume arr_v[5];
    		
     -> 圧力と比体積を配列で宣言.熱サイクル中の状態が4つなのに対して大きさ5で宣言するのは,最初の点を繰り返すことで環状のplotを作るため.
    arr_v[1] = 1.0/engineFluid.density_pTX(p = p1.p, T = T1.T, X = p1.port.Xi_outflow);
    arr_v[2] = 1.0/engineFluid.density_pTX(p = p3.p, T = T3.T, X = p3.port.Xi_outflow);
    arr_v[3] = 1.0/engineFluid.density_pTX(p = p4.p, T = T4.T, X = p4.port.Xi_outflow);
    arr_v[4] = 1.0/engineFluid.density_pTX(p = p5.p, T = T5.T, X = p5.port.Xi_outflow);
    arr_v[5] = arr_v[1];
    
    arr_p[1]= p1.p;
    arr_p[2]= p3.p;
    arr_p[3]= p4.p;
    arr_p[4]= p5.p;
    arr_p[5]= arr_p[1];
    		
     -> 圧力は単純に圧力センサのoutput connectorの値と繋げる.
     比体積は密度の逆数を計算する.密度はセンサで値を取得してないので,Mediaのメンバfunctionを使ってp, T, Xiから計算する.
     
     これで,計算完了後,array-parametric plotで,variableにarr_v, arr_p を選択すると(配列そのものを選択) p-v線図を表示出来る.(但し,isentropic curveは描けず,4状態を示す点が直線で結ばれた図となる.)

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

 それでは、観たいvariableの値や動きを評価してゆこう。

    Input

    1. 燃焼器出口目標温度
    2.  恐らくエンジンが自立ギリギリに近い500 [K] から,1000 [K]まで上昇させる.

    Output

    1. 燃焼器出口ガス温度
    2.  大きな遅れ,オーバーシュート無にinputした目標値に追随出来ている.

    3. ジェネレータパワー(エンジンの生成出力)
    4.  ほぼ燃焼器出口温度と同じ時間応答.燃焼器からジェネレータまでのエネルギの流れ道に時間遅れを生むような要素(質量・熱量溜め要素や熱慣性など)を居れていないので自然な動き.
       期待していた通り,出力上げ操作前はジェネレータのパワーは非常に小さく,圧縮機を駆動してエンジンが自立した状態を少し上回っている程度.出力上げ操作前後でジェネレータ出力は10倍程度変化している.

    5. ジェネレータ(赤),タービン(青),圧縮機(緑)のパワー
    6.  出力上げ操作に対する3つのパワー.機械回転軸でエネルギ保存が成り立ち,ジェネレータのパワー=タービンのパワー – 圧縮機のパワー,となる.
       タービンが生むパワーにほぼ追随してジェネレータのパワーが上昇する.一方で圧縮機のパワーは上昇どころか僅かだが減少している.
       これは,モデリング対象システムの解説にて記した,等回転を維持した時のエンジン出力上げに対する圧縮機作動点の挙動によるもの.等回転線の上を作動点が左側に動き,圧力比が上昇するが,吸込み流量が減る.そして吸込み流量が減る効果が少し勝り圧縮機駆動に要するパワーは減った.
       注意が必要なのは,圧縮機パワーが必ず減るとは限らない点.今回,圧縮機特性として設定した,等回転head-vs.-flow特性線の傾きが浅かったため,吸込み流量減効果が勝り,パワーが減った.この特性線の傾きがより急なものであれば圧力比上昇の効果が上回りパワーが増える事も有る(というか,大抵の圧縮機の等回転線は定格回転周辺でかなり急な傾きなのでその方が自然).ただその場合でも,タービンパワーの動きと違い,背反する2つの変化によりパワーの動きは小さなものとなる.

    7. 熱効率
    8.  熱力学で習う一般的な法則通り,加熱側温度(燃焼器出口)を上昇させるほど効率が上昇している.
       但し,実は複雑な式変形を進めると,ガスタービンのブレイトンサイクルの場合,実際には熱効率は燃焼器出口温度ではなく,圧縮機出口の圧力比上昇に依るもので有ることがわかる(詳細割愛).この例では燃焼器出口温度上げに伴って,圧縮機圧力比が上がるためこのような動きとなる事に注意されたい.もし,圧縮機圧力比を固定したまま燃焼器出口温度だけを上昇させると,動き方は同じにはならない(エンジンの運転状態を変えて実現することは出来ない変化のさせ方ではあるが).

    9. 燃焼器出口温度,排気温度
    10.  燃焼器出口と共に排気温度をplotしたもの.
       燃焼ガスが大気圧まで膨張しても排気はまだ非常に高い温度を有している事が解る.コンバインドサイクルや熱化学処理プラントとの複合システムはこの熱を活用したもの.

    11. 圧縮機昇圧,圧縮機通過質量流量(head-vs.-flow/P-Q)
    12.  今回のハイライト.P-Qとも呼ばれるもの.
      • 圧縮機昇圧(dp)

      • 圧縮機通過質量流量

      • dp-vs.-m_flow
      •  上の2つそれぞれからも解る通り,通過質量流量は減少して昇圧は上昇する.回転が拘束されていない場合(ジェットエンジンのような)に想像される動きと,質量流量の動きが逆になる.従って,当然dp-vs.-m_flowのplotは右肩下がりとなる.
         圧縮機パワーの所で述べたが,回転が拘束されている時,圧縮機の作動点は当然等回転線上しか動かない.そしてその等回転線は昇圧量上昇に対し通過質量流量が減るような線となっているので,出力を上げ動作に伴って圧縮機が昇圧を増すと流量は減らねばならない(流量が減るのと,昇圧が増えるのがどちらが因で果(鶏/卵)という事はない.陰的に繋がった物理現象なので辻褄があう所に落ち着く.).

    13. タービン入口修正流量
    14.  変化しない.
       これは終始タービンがチョーク状態となっているため.詳細は割愛してきたが,修正流量とはマッハ数を近似した変数であり,チョークしていると当然一定値を保つ(質量流量は減る点に注意).

    15. 簡易p-v線図
      •  配列を使って簡易にブレイトンサイクルのp-v線図を示す.上がOpenModelicaのarray-parametric1-plotで描いたもので,下は本当のブレイトンサイクルの形に見えるように等エントロピラインをフリーハンドで引いたもので飽くまでイメージ.概ね熱力学の専門書に記載されているような形となっている.
         左下が圧縮機入口の状態で,左上が圧縮機出口,右上が燃焼器出口,右下がタービン出口となる.
         下図の4つの状態を繋いだ線(曲線)で囲まれた面積が仕事(横軸が比体積なので単位質量あたりの仕事,比仕事)を示す.この記事で登場したオットーサイクルや,この記事で登場したディーゼルサイクルのようなピストン式機関とサイクルの形を見比べると,このブレイトンサイクルは右下に範囲が広い事が特徴であると読み取れる.これは膨張過程が長い(時間的な長さではない)事を意味する.出口の圧力で膨張のゴールが決まっており,吸気状態よりも遥かに低い比体積(密度)まで膨張・仕事取出しが出来ている.

          

最後に

 本例題は以上。

例モデルに関する情報

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

コメント

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