ModelicaのBuildingsライブラリのThermalZones.Detailed.MixedAirで室温/熱負荷計算を学ぶ_その1

概要

OpenModelicaとJModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。
前回までは換気回路網計算を見ていたが、今回は熱回路網計算によって自然室温計算をしているモデルBuildings.ThermalZones.Detailed.Examples.MixedAirFreeResponseを見ていく。本当はBuildings.ThermalZones.Detailed.Validation.BESTEST.Cases6xx.Case600FFの方を見たかったのだけれどどうも計算が途中で止まるのでまずはこちらをみていくことにする。理解が深まったらなにか原因がわかるかもしれない。OpenModelicaでは実行できなかったのでコードを読むのはOpenModelica、実行するのはJModelicaとした。
使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-JModelica3.4 →Modelica標準ライブラリ3.2.2
-Buildings 5.1.0

Buildings.ThermalZonesについて

ThermalZonesは建物の年間熱負荷計算とか室温変動の非定常計算などをするためのパッケージなのだと思う。室温の計算のためにBuildings.FluidやBuildings.HeatTransferなどのモデルを組み合わせてモデルを作ってくれているようだ。下の表のようにまずは大きく二つに分かれていてDetailedが詳細計算で、ReducedOrderの方はVerein Deutscher Ingenieureというドイツ技術者協会の規格のVDI 6007にある室と建物の過渡的な熱応答の計算方法を実装しているらしい。

名称 説明
Detailed 室モデルのパッケージ
ReducedOrder VDI 6007に基づく簡易化したモデル

どちらも気になるのだがDetailedの方をみることにする。Detailedに含まれるパッケージは下の表の通り。

名称 説明
UsersGuide ユーザーガイド
CFD CFDにより室内空気を計算するモデル
MixedAir 完全混合空気による室のモデル
Constructions 室モデルで使われる壁体構成のためのモデル
FLEXLAB FLEXLAB(多分LBNLの実験施設)をモデル化するために使うモデル
Types 型定義のパッケージ
Examples モデルの使用方法とテストモデルを示すモデル群
Validation 検証モデル群
BaseClasses Buildings.ThermalZones.Detailedのための基底クラスのパッケージ

メインとなるモデルはCFDとMixedAirの二つで、CFDの方は室内の温度などの分布をFast Fluid Dynamics (FFD) のプログラムで計算してModelicaと連成しているらしくBuildings.ThermalZones.Detailed.Examples.FFD.UsersGuideあたりを読みながら使うのだと思う。面白そうだが 計算時間とか精度とかどんなものなのだろう。いずれ使ってみたい。
今回はMixedAirの方を使った検証モデルについて見ていくことにする。このモデルは室内空気が完全混合しているものとして一つの代表点で室温をあらわしている。よくある熱回路網計算である。ちなみにConstructionsはMixedAirの実装に使われているモデルで、FLEXLABはMixedAirを使ってLBNLの実験施設のFLEXLABのセルを再現しているものだと思われる。

MixedAirの方にはコンピュータプログラムによる建物のエネルギー性能評価の試験方法のアメリカの規格(ANSI/ASHRAE Standard 140-2007)に含まれるBESTESTによる方法に従って検証をしたファイルがある。この規格の最新版は2017なので最新の規格に対応できているかまではわからない。ASHRAEはいくつかの規格を公開しているものの140は公開していない。買うと110ドルするのでどこかで見れないものだろうか。いくつかファイルがあるのだが、Case600FFが単室の自然室温の計算をしているもので、これに空調を加えたものがCase600、そしてCase600を継承して多くのファイルが派生している。Cases6xx系統は軽量な(熱容量の小さい)壁体のモデルでCases9xx系統が重い(熱容量の大きい)壁体のモデルになっている。これにも取り組みたいのだが、まずはExamplesにあるもう少しシンプルなモデルMixedAirFreeResponseをみることにする。

MixedAirFreeResponseの構成

最初にモデル全体の構成を確認する。
- 室のモデル(MixedAir)roo
- 気象データweaDat
- 土壌温度TSoi
- 間仕切conOutを介した隣室温度TBou
- 室内の発熱multiplex3_1とそれにつないだ固定値の3種の発熱
- 窓のブラインド等の開閉制御信号replicatorとそれにつないだ固定値
これらを用いて二日間分の単室の室温を計算している。
f:id:kinonotofu:20181030224508p:plain
図において線でつながっていないアイコンがあるがこれはrecord(変数のまとまり)である。

今回パラメータとして定義しているのは室を構成する素材の数と、recordによる素材の構成の定義である。
- 窓の数 parameter Integer nConExtWin = 1;
- 土壌に接する壁の数 parameter Integer nConBou = 1;
- 隣室に接する壁の数 parameter Integer nSurBou = 1;
の3つをパラメータとしており外壁の数もparameter Integer nConExt = 2;としてよいはずだがこれはなぜかrooの方で定義されている。土壌や隣室は勝手にそう呼んでいるだけで、nConBouは室rooの中でConBouで指定した壁面に接する温度、nSurBouは室rooの空気に直接接する温度をつなぐ面の数のことである。

素材の構成はライブラリに登録されたものをそのまま使うことも、素材を指定して厚みを与えて自分で構成を作ることもできる。素材の物性値を変更したい場合は自分で素材のrecordを作ってやる必要がある。
外壁parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Insulation100Concrete200 matLayExt;
間仕切壁parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Brick120 matLayPar;
屋根(上が外側として指定のはず)

  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matLayRoo(
        material={
          HeatTransfer.Data.Solids.InsulationBoard(x=0.2),
          HeatTransfer.Data.Solids.Concrete(x=0.2)},
        final nLay=2);

床(上が外側として指定のはず)

  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matLayFlo(
        material={
          HeatTransfer.Data.Solids.Concrete(x=0.2),
          HeatTransfer.Data.Solids.InsulationBoard(x=0.15),
          HeatTransfer.Data.Solids.Concrete(x=0.05)},
        final nLay=3);

窓の素材

  parameter Buildings.HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false);

以上が素材のrecordで、当然これらもアイコンをダブルクリックして変数に値を入力できる。
屋根のmatLayRooの場合以下のような感じになる。両面の長波放射率と日射吸収率はデフォルト値がはいっている。外気側のroughnessは何に使う値かわからない。対流熱伝達率でもかわるのだろうか。
f:id:kinonotofu:20181030225114p:plain

モデルの頭でpackage MediumA = Buildings.Media.Airとしてrooの中で再宣言するのはいつもと同じである。

気象データweaDat

気象データはconnect(weaDat.weaBus, roo.weaBus)としてweaBusをつなぎこんでいる。ファイルを適当に指定して、湿球温度の計算は切っておく。

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"),
      computeWetBulbTemperature=false)

間仕切conOutと隣室温度TBou

surf_surBouという室rooの空気に直接接続するheatportの配列に多層壁のモデルの配列をconnect(roo.surf_surBou, conOut.port_a)としてつないでいる。多層壁の反対側は15℃固定とした隣室側表面温度TBouにconnect(TBou.port,conOut.port_b)としてつないでいる。多層壁モデルはstateAtSurfaceをtrueにすると表温度を計算するので、今回のように片側の温度を固定している場合はFalseにしてやる必要がある。Aに壁の面積、layersに壁体構成のrecordを入力する。port_aがrecordで上側に定義したものとつながるようになっている。

  Buildings.HeatTransfer.Sources.FixedTemperature TBou[nSurBou](each T=288.15);
  Buildings.HeatTransfer.Conduction.MultiLayer conOut[nSurBou](
    each A=6*4,
    each layers=matLayPar,
    each steadyStateInitial=true,
    each stateAtSurface_a=true,
    each stateAtSurface_b=false);

土壌温度TSoi

室rooの壁体conBouに接続するsurf_conBouというheatportの配列に10℃の固定温度TSoiをconnect(TSoi.port, roo.surf_conBou)として与えている。

  Buildings.HeatTransfer.Sources.FixedTemperature TSoi[nConBou](each T = 283.15)

室内の発熱multiplex3_1

室内の発熱として放射、対流、潜熱流の順番の3つのheatportの配列qGai_flowにmultiplex3_1から発熱をconnect(multiplex3_1.y, roo.qGai_flow)として与えている。放射だけならheaPorRad、対流だけならheaPorAirというheatportがそれぞれ単独で存在するようだ。潜熱流としてMixedAirに内部発熱を定義したいときは要素3つの配列にしてやる必要があるのだと思う。
Modelica.Blocks.Routing.Multiplex3は3つのinputを順にならべた配列にして1つのoutputにするモデルである。inputが配列でも問題ないが今回は単独の数値3つをまとめているのでoutputは要素3つの配列である。値はすべて0なので実質発熱はない。

  Modelica.Blocks.Routing.Multiplex3 multiplex3_1;
  Modelica.Blocks.Sources.Constant qRadGai_flow(k=0);
  Modelica.Blocks.Sources.Constant qConGai_flow(k=0);
  Modelica.Blocks.Sources.Constant qLatGai_flow(k=0);
  connect(qRadGai_flow.y, multiplex3_1.u1[1]);
  connect(qConGai_flow.y, multiplex3_1.u2[1]);
  connect(qLatGai_flow.y, multiplex3_1.u3[1]);

窓のブラインド等の開閉制御信号replicator

uShaという窓のブラインド等の開閉制御信号を入力する配列にReplicatorで作成した配列をconnect(roo.uSha, replicator.y)としてつないでいる。Replicatorはinputの値がnout個並ぶ配列を出力するモデルであり、複数の窓に一括で同じ制御をしたいときなどに便利だと思う。今回は定数で0をconnect(uSha.y, replicator.u) としてつなげて複製しているので日射遮蔽はないものとしていると思われる。

  Modelica.Blocks.Sources.Constant uSha(k=0)
  Modelica.Blocks.Routing.Replicator replicator(nout=max(1,nConExtWin))

これとは別にuWinという窓の状態(電気のオンオフで透過率が変わるなど?)を表すReal型の入力ポート(たぶん日射をカットする割合を入力する)がある。uShaもuWinも0~1の値を入力することになる。窓周りは詳しく調べておきたいところだがとりあえずこんなものがあるのか程度で留めておく。

壁や窓を含む室モデルroo

このモデルが今回の本題である。設定は以下のようになっている。

  Buildings.ThermalZones.Detailed.MixedAir roo(
    redeclare package Medium = MediumA,
    AFlo=6*4,
    hRoo=2.7,
    nConExt=2,
    datConExt(layers={matLayRoo, matLayExt},
           A={6*4, 6*3},
           til={Buildings.Types.Tilt.Ceiling, Buildings.Types.Tilt.Wall},
           azi={Buildings.Types.Azimuth.S, Buildings.Types.Azimuth.W}),
    nConExtWin=nConExtWin,
    datConExtWin(
              layers={matLayExt},
              each A=4*3,
              glaSys={glaSys},
              each hWin=2,
              each wWin=4,
              ove(wR={0},wL={0}, gap={0.1}, dep={1}),
              each fFra=0.1,
              each til=Buildings.Types.Tilt.Wall,
              azi={Buildings.Types.Azimuth.S}),
    nConPar=1,
    datConPar(layers={matLayPar}, each A=10,
           each til=Buildings.Types.Tilt.Wall),
    nConBou=1,
    datConBou(layers={matLayFlo}, each A=6*4,
           each til=Buildings.Types.Tilt.Floor,
           each stateAtSurface_a = false),
    nSurBou=1,
    surBou(each A=6*3,
           each absIR=0.9,
           each absSol=0.9,
           each til=Buildings.Types.Tilt.Wall),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=273.15+22,
    lat=0.73268921998722) "Room model"

床面積、天井高さ、各構成要素の数とその設定などが入力されている。各構成要素の数の入力にパラメーターの変数を使っていないところがあるがミスだろうか。ConExtが外壁で気象データとつながる壁体、ConExtwinが窓、ConParが室内壁(壁の両面がこの室に面している)、ConBouが土壌、SurBouが今回の間仕切壁となっている。それぞれの要素を表にすると以下のような使い分けになっている。この名称の頭にnをつけて要素数、datをつけてそれぞれの設定を記述している。

名称 用途 境界条件を与えるポート
ConExt 外壁 weabus
ConExtwin weabus
ConPar 室内の壁の蓄熱とか放射の効果を見たいとき なし(両面とも室内空気に面する)
ConBou 境界の温度を気象データ以外から与えたいとき surf_conBou
SurBou 壁のモデルをMixedAir以外でつくりたいとき surf_surBou

surBouは壁体がモデルの外でモデル化されるので素材の指定はないのだが、これの指定の変数名はdatSurBouでなくsurBouであることには注意が必要かも知れない。長波放射率(室内の壁同士の放射熱交換用)absIR=0.9と日射吸収率absSol=0.9(窓から入ってきた日射の計算用)を設定している。
Buildingsライブラリで使っている定数として自然換気で風向を指定するときにAzimuthについては確認した。今回は壁体の角度tilに使っている角度の定数Buildings.Types.Tiltを確認する。こちらも単位はラジアンで角度の定数が入っていて、壁面の方向が0[rad]が上向き(水平屋根面など)となっている。

  constant Modelica.SIunits.Angle Ceiling = 0 ;
  constant Modelica.SIunits.Angle Floor =   Modelica.Constants.pi;
  constant Modelica.SIunits.Angle Wall =    Modelica.Constants.pi/2;

窓の設定は袖壁が設定できるようになっている。hWinが窓高さ、wWinが窓の幅、ove(窓の右端から庇の右端の距離,窓の左端から庇の左端の距離, 窓の上面から庇まで距離,庇の深さ)が庇の設定で、このあたりのパラメータは窓のガラス部分のサイズを基準に入力するはずである。右というのが外側から窓に向かって右側であるらしい。またfFraは窓面全体面積にたいするサッシ面積の割合となっている。ちなみに袖壁はsidFin(窓の上面より上に出る長さ,窓の側面からの距離, 袖壁の深さ)袖壁は窓の最下端以下の部分からはじまり、窓の両側に対象的に配置される。

初期温度は室の空気だけでなくここで定義した壁体すべてにも適用される。緯度は気象データのものと一致している必要があるようなので太陽位置などを計算するのだろう。太陽位置は日射量を直達成分と拡散成分に分解したときと壁面の角度に応じて計算するときで一致していなければならない。
今回は使用していないが、MixedAirにはportsとC_flowはfluidportとCO2などの物質の濃度のポートがある。このポートとAirflowのモデルをつかって換気計算も同時に行うことができる。(計算負荷がどの程度になるかは不明)

OMEdit上での設定も確認してみる。
f:id:kinonotofu:20181030230621p:plain
dummyConとdummyGlaSysというダミーのパラメータをインスタンスにあたえるための設定があるが使いどころがよく分からない。
linearizeRadiationは放射計算を温度の4乗で行うと計算負荷が高くなるので放射伝達率などで近似的に線形で計算する設定だと思われる。
hIntFixedは室内側対流熱伝達率でhExtFixedは外気側対流熱伝達率である。ただしデフォルトではこの値は使われておらず、下のintConModとextConModでFixedを選択することでこの値を使用することになると思われる。

f:id:kinonotofu:20181030230838p:plain
steadyStateWindowは窓を定常計算モデルとするかの設定である。窓は熱容量が小さいので定常計算(熱容量なし)とするのはよくあるが、デフォルトでは熱容量を考慮しておりしかもこれがシミュレーションの高速化に寄与するらしい。
mSenFacの室の家具などの熱容量の設定がここにあるが、今回は特別見込まず空気の熱容量のみになっている。

f:id:kinonotofu:20181030231218p:plain
ホモトピー法を使用するかどうかの設定。

f:id:kinonotofu:20181030231339p:plain
ここは実験的に時間のサンプリングの処理により計算の高速化を図ろうとする設定らしいが将来的になくなるかもしれないらしい。

f:id:kinonotofu:20181030231716p:plain
圧力と温度の初期値の設定。

計算の実行

OpenModelicaで実行しようとすると以下のエラーがでる。
f:id:kinonotofu:20181030232145p:plain [3]~[5]はこのファイルを開いたときの警告、[1]と[2]は実行時のエラーである。壁体の配列のあたりでなにかよくないことが起こっているのかもしれない。窓のペアガラスの中空層の空気の部分もファイルを開いたときにエラーとなっている。

とりあえずJModelicaで実行してみる。今回は前回JModelicaを使ったときよりバージョンがあがって2.4を使っている。ファイルが見つからないという警告がでなくなった。少し初期値がみつからないと警告してくるがとりあえず計算はできた。

室温roo.air.vol.Tと外気温度roo.weaBus.DryBul、屋根roo.conEXT[1]と間仕切りconOutの表面温度は以下の通り。計算開始時にがくっと温度が変化している。屋根表面の温度が外気より下がるのは夜間放射の影響と思われる。昼間は日射の影響により屋根や間仕切りの室内側表面温度に比べて室温が上昇している。家具の熱容量は考慮していないがRCの壁を使っているので室温変動はこんなものなのだろうか。
f:id:kinonotofu:20181030235331p:plain

まとめ

とりあえずMixedAirの使い方が分かった。あいかわらず計算結果から知りたい値を探し出すのがたいへんである。伝熱の各要素などの理解を深めたい気もするが、次回はとりあえずBESTESTの計算をどうにかうまくできないかと思う。計算が止まる原因の解決が難しそうなら多数室の計算とか空調時の熱負荷の算出に挑戦してもよいかもしれない。

先日LBNLがModelicaやFMI関係のスタッフを募集していた。

BuildingsライブラリやOpen Building Control, Spawn of EnergyPlus それからIBPSA librariesにも関わる事をするようだ。Modelica関係の開発がさらに活発化するかもしれない。

OpenModelicaのBuildingsライブラリで換気回路網計算を学ぶ_その3

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。
前回Buildings.Airflow.Multizoneパッケージで風力換気の計算をしてみた。今回はその続きで気象データを読み込んで風向と風速が時間変化するときの換気量をみていきたい。

使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-Buildings 5.1.0

作成するモデルの概要

前回作った風力換気の単室モデルに適当なスケジュールで発熱を与えて気象データを読み取って自然室温のようなものを計算する。外壁の熱貫流は無視しているので自然室温ではない。

べき乗則モデルの作成

前回と同様にBuildings.Airflow.Multizone.Examples.OneRoomのモデルをベースにするのでコピーしてくる。今回は外気側のボリュームを外部風向に合わせて風圧係数を計算できるBuildings.Fluid.Sources.Outside_CpLowRiseにしたいのだが、そのまま使うのも味気ないのでべき乗則で風速を補正して使うようにしてみる。気象データで得られる風速の計測高さと風圧係数を求めたときの風速の高さ(軒や屋根の高さ)は必ずしも一致しないので、気象データの風速をべき乗則などで補正してやる必要がある。気圧も高さが変わると補正が必要だと思うけれど、そもそも今は定数として標準大気圧を使っているので特に補正はしない。
今回使う気象データ(USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos)は風速計高さを調べても不明だったので30mを6mに換算してみる。energyplusの気象データ風速計の高さをどこで見るのかご存知の方がいれば教えて頂けるとありがたい。TMY3のマニュアルをみたりしたけれどよくわからず観測所の情報も緯度経度と高度はわかっても風速計高さにたどりつけなかった。アメダスの場合は気象庁の地域気象観測所一覧から確認できる。拡張アメダス標準気象データは風速計の高さを補正している場合があるので補正時と異なるべき指数を使いたい場合は注意が必要である。それから、元の風速計の高さが低くい場合は周辺の建物の影響を受けていたり、十分な高さの気象官署からデータを取るにしても検討地点から距離が離れすぎててたりと悩ましいことが少なくないのだけれどそこは割り切るしかないかもしれない。(よい検討方法が実はすでにあるかもしれないけれど。)

まずは前回のように修正したいモデルOutside_CpLowRiseをコピーしてくる。
変数として気象データの風速計高さhWea、風圧算出用の風速高さhCor、補正用のべき指数nCor、風圧算出用の風速vCorを加えてべき乗則で風速を補正して使用するように書き換える。元のモデルでは気象データから読み込む風速はvWinという変数に入れられている。

model Outside_CpLowRise "Boundary that takes weather data as an input and computes wind pressure for low-rise buildings"
  extends Buildings.Fluid.Sources.BaseClasses.Outside;
  parameter Modelica.SIunits.Height hWea "height in weathedata";  //追加部分
  parameter Modelica.SIunits.Height hCor "height for Wind pressure coefficient";  //追加部分
  parameter Real nCor "coefficient for power low";  //追加部分
  Modelica.SIunits.Velocity vCor "Wind velocity at hCor";  //追加部分
(略)
equation
  alpha = winDir - surOut;
  CpAct = Buildings.Airflow.Multizone.BaseClasses.windPressureLowRise(Cp0 = Cp0, incAng = alpha, G = G);
  vCor = vWin * ( ( hCor / hWea ) ^ nCor ); //追加部分
//  pWin = 0.5 * CpAct * medium.d * vWin * vWin;  //修正前コメントアウト
  pWin = 0.5 * CpAct * medium.d * vCor * vCor;  //修正後
  pTot = pWea + pWin; 
(略)
end Outside_CpLowRise;

今回はこのような変更にしたけれど、connect(weaBus.winSpe, vWin);の部分を消して、別途べき乗則用のモデルを用意して補正した風速をvWinにつないでもよいかもしれない。

できたら左のライブラリブラウザからドラッグ&ドロップしてきてoutNとoutSという名前をつけてやる。右クリックで横反転してやると見やすい。ここでは北壁を上の窓につなぐようにした。 ダブルクリックするとちゃんと設定にhWea、hCor、nCorが追加されているので30、6、0.28としてやる。べき指数は地表面の状態で変わる指数で、今回は平屋建物が立ち並ぶ郊外を想定して0.28にした。
f:id:kinonotofu:20181007185513p:plain

風圧係数の関数について

風圧係数についてはOutside_CpLowRiseに組み込んである関数を使って算出するのだが。この関数はBuildings.Airflow.Multizone.BaseClasses.windPressureLowRiseにある関数で、BaseClassesと同じ場所にあるがfunctionである。 これを使わない場合の風圧係数は何らかの設計資料から似た形のものを引用したり、CFDから風圧係数を計算したり、場合によっては風洞実験をするなどの方法で風向別のデータを得ることができる。その場合は別途風向から風圧係数を算出するモデルを作るか、風向から風圧係数を事前に求めておいて時系列データとして読み込んでBuildings.Fluid.Sources.Outside_Cpに入力することになる。
今回使う気象データはチュートリアルのSpaceCooolingと同じものでは北風が0°で時計回りに東風が90°で南風が180°西風が270°となっており10°刻みで風向が定義されている。日本だと16風向で22.5°刻みのことが多いので不思議な感じがする。無風時はデータが空になっているらしいが今回はそのようなデータはなかった。ちなみに一般に風向の定義として南風は南から北へ向かって吹く風である。逆と間違えないようにしたい。

WindPressureLowRiseの関数はSwami and Chandra (1987) の論文によるものだ。 Cp0は風向が壁に正対するとき(南向きの壁に南風が吹いたとき)の風圧係数で一般的な低層の建物では0.6が推奨らしい。 sは(対象の壁の幅/対象の壁に隣接する壁の幅)である。隣接する壁の幅とは対象の壁に正対したときの建物の奥行き方向の長さになる。ここでは幅18m奥行き22mの建物と考えて0.81と入力してみる。 aziは壁の向きで南が0°、西が90°になっている。角度の単位はdegreeかradianか選べる他、東西南北についてはBuildings.Types.Azimuth.Nなどで指定してやることができる。これは次のように定義されているので単位はradianである。

within Buildings.Types;
package Azimuth "List of possible constant values for surface azimuth"
   constant Modelica.SIunits.Angle E = -Modelica.Constants.pi/2
   constant Modelica.SIunits.Angle N = Modelica.Constants.pi
   constant Modelica.SIunits.Angle S = 0
   constant Modelica.SIunits.Angle W = +Modelica.Constants.pi/2
end Azimuth;

これでパラメータの設定ができた。nportは流体の入出力ポートでこれを1にしておく。CO2とか粉塵とかの計算はしないのでuse_C_inはfalseにする。それから、テキストビューで媒体の指定を追加してやる。
f:id:kinonotofu:20181007192941p:plain

OneRoomTest.Outside_CpLowRise outN(redeclare package Medium = Medium,azi(displayUnit = "rad") = Buildings.Types.Azimuth.N,hCor = 6, hWea = 30, nCor = 0.28, nPorts = 1, s = 0.81)

気象データと発熱スケジュールの読み込み

気象データはBuildings.BoundaryConditions.WeatherData.ReaderTMY3を使う。湿球温度は特にいらないのでcomputeWetBulbTemperatureをfalseにし、filNamはライブラリにはじめからついているUSA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mosを使う。他のパラメータはデフォルトのままで大気圧はパラメーター固定値で他はファイルから、天空温度も使わないのでそのままにしている。

さらに換気による排熱の効果も見たいと思ったので室の内部発熱スケジュールを組み込んでみたいと思う。これはModelica標準ライブラリを使う。発熱スケジュールデータをModelica.Blocks.Sources.CombiTimeTable から読み込み、Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlowを経由してheatportとしてvolEasにつなぎこんでやる。PrescribedHeatFlowはデフォルトの設定のままでよいがインプットをそのまま出力するだけなのでalphaが0であることを確認する。
CombiTimeTableによる時系列データの入力は3種類あり、直接記述、ファイル読み込み、cのソースに書き込みができるようだがcのソースに書き込みの使い方がいまいちよくわからなかった。ファイルの読み込みはASCIIファイルのフォーマット以外にMATLABのフォーマットを使うことができるらしい。OMEdit上の設定は次のとおり。
f:id:kinonotofu:20181007195525p:plain
tableOnFileをfalseにしたときはtableのところに直接テーブルを記述する。[0,0;1,2;2,0;3,2]のように各時刻のデータをカンマで区切り、時刻が変わるときにはセミコロンで区切る。毎時刻の一番初めのデータは時刻(秒)になるようにして時刻は単調増加(減少しない事)にしないといけない。基本的にテーブルに無い時刻のデータは線形補間で計算される。不連続に値を変動させたい場合は[0,0;1,0;1,2;2,0;3,2]などのようにすると1秒のところで不連続になる。この時刻では計算が2回行われるのだと思う。
tableOnFileをtrueにした場合はfileNameが”NoName”だとcのソースに書き込みになるらしい。"C:\OpenModelica1.12.0-64bit\lib\omlibrary\Modelica 3.2.2\Resources\Data\Tables"とかにあるusertab.cやらusertab.hやらにサンプルらしきものがある。
そしてファイル名を指定してやるとファイルの読み込みになる。同じところにtest.txtというサンプルファイルがある。読み込みファイルの形式としては
* 1行目に#1と記載する。(データ形式のバージョンを示す) * double tab0(2,2)のようにデータ型(floatかdouble)、テーブル名(ここではtab0)、データの数(行数、列数)を示す。 * テーブルのデータをスペース、タブ、カンマ、セミコロンのいずれかで区切って記載していく。一列目には単位を秒として時刻を記述する。改行コードは特にその行のデータの終わりを意味しないので複数行に同じ時刻のデータを記載できる。 * 一つのファイルに複数のテーブルを記載できる。tableNameで読み込むテーブルを選択する。

今回はファイルを読み込んで使用するのでtableOnFileをtrueにし、tableはそのまま、tableNameは"heat"にして(ダブルクオーテーションを忘れないように)、fileNameは"C:/Users/Simulation/OModelica/heat.txt"とheat.txtを作成して指定する。verboseReadは読み込みのメッセージの出力設定なのでfalseでよいと思う。作成したファイルは次のとおり。9時から18時まで100Wの発熱を与えるようにする。時間が秒の単位になっていないがそれは別に設定する。テーブルが大きい場合はExcelでつくってcsvなどで書き出してやるとよいと思う。

#1
double heat(4,2)
0,0
9,100
18,0
24,0 

設定の続きにもどる。columnsは読み込む列の番号を指定するのだと思うけれど使い方があまりよくわからなかった。今回はたぶん2列のデータなのでデフォルトで特に問題なかった。
smoothnessはテーブルに記載の無い時刻でのデータの補間の方法を指定する。デフォルトはLinearSegmentsで線形補間だがConstantSegmentsだとその前の時刻の値を保持することになるのでこれを指定する。
extrapolationはテーブルの時刻の外側のデータの取り扱いでデフォルトはLastTwoPointsで線形外挿だがPeriodicとして周期的にテーブルを使用する。これで1日分のスケジュールを毎日繰り返すようになる。 offsetは時刻以外のすべてのデータに加える値で0のままに、startTimeはすべての時刻に加える値で0のままにする。
timeScaleはすべての時刻に掛ける値でこれを3600にする。こうすることでスケジュールデータの時刻の単位を秒に変換できる。これで設定ができた。
f:id:kinonotofu:20181007212920p:plain

時系列の換気量の計算

設定したファイルをつなげてやる。weaBusなどはインスタンスの名前がついていないことがあるので注意。
f:id:kinonotofu:20181007213524p:plain
今回追加した部分の接続は以下の通り。

  connect(colOutTop.port_b, outN.ports[1]);
  connect(colOutBot.port_a, outS.ports[1]);
  connect(weaDat.weaBus, outN.weaBus);
  connect(weaDat.weaBus, outS.weaBus);
  connect(combiTimeTable1.y[1], prescribedHeatFlow1.Q_flow);
  connect(prescribedHeatFlow1.port, volEas.heatPort);

計算を開始する。年間計算として終了時刻を31532400s、計算は間隔3600sにしてみる。年間計算したけれどそこまで計算時間が気にはならなかった。そして年間計算したけれど結局集計や詳細にデータを見るのがたいへんなので部分だけ取り出して計算ができてそうだというのを確認するだけになった。
室温の変化は以下の通りで昼間発熱して温度があがって夜間に換気で外気近くまで温度が下がる様子が計算できた。ただ熱容量や壁の伝熱がないと100Wでこんなに室温があがるものなのかと驚いた。(容積は2.5×5×5m3)
f:id:kinonotofu:20181007223237p:plain

計算開始後の換気量(上)と風速(下)の関係は以下の通りで風速の大きいところでしっかり換気量が増えているのがわかる。風向毎に風圧係数がかわったり浮力(温度差)の影響があったりするので必ずしもこんなにきれいに相関は出ないのが普通かもしれないけど今回はきれいにでた。
f:id:kinonotofu:20181007225954p:plain
csvで出力すると発熱開始と終了のたびにデータが3つでていた。データの集計の際に面倒なことになるので何かよい方法は無いものかなぁと思った。

おわりに

とりあえず時系列の換気計算ができた。理解が間違っている部分があれば指摘していただけるとありがたい。
風圧係数については8月に建築研究所建築物の自然換気設計のための風圧係数データベースを公開した。まだ読めていないのだけれど、単なるデータベースではなく風圧係数についての知識や考察がたっぷり書いてあるようなのでとても勉強になると思う。このデータベースは32風向分用意されており、日本で得られる気象データは16風向なのでそのまま使える。ただし、今回使った気象データは10°刻みの36風向の気象データになっていたので、このデータベースを使うなら風圧係数を補間してやる必要がでてくる。(線形補間してよいのかは分からないのだけれど、分からなければとりあえず線形補間するのだろう)

次回は自然室温や熱負荷を計算するためのパッケージと思われるBuildings.ThermalZonesについて少し見ていきたいと思う。チュートリアルのSpaceCoolingでは定常計算の壁体熱貫流と換気負荷を見込んだ単純な室だったが、壁体を非定常熱伝導にしたり、窓を取り付けたり、室内の放射伝熱などの計算をしたりなど、より詳細な室の取り扱いができるといいなぁと思う(Buildings.HeatTransferに関連モデルがあるようだけれど室のサンプルはThermalZonesのはず)。次回見るサンプル(Buildings.ThermalZones.Detailed.Validation.BESTEST.Cases6xx.Case600FF)もOpenModelicaではエラーが出るようなのでJModelicaと併用していくと思う。

OpenModelicaでBuildingsライブラリで換気回路網計算を学ぶ_その2

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。
その1ではBuildings.Airflow.Multizoneパッケージを見てExamples.OneRoomにある温度差換気の計算を確認した。風力換気のモデルが見つからなかったので今回は自分で作って使ってみた(実は風力換気用のモデルがあったのでそれも使ってみた)。

使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-Buildings 5.1.0

作成するモデルの概要

その1で扱ったOneRoomにおいて風が風速2.0[m/s]で吹くものとし、高いほうの窓の風圧係数が-0.2であるとする。低いほうの窓は特に変更しないので風圧係数0.0ということになる。さらに、手計算と比較して検算をしやすくするため、室温と外気温を同じ値にして浮力駆動の換気が起こらないようにする。その他の条件はOneRoomと同じである。

既存モデルの改変

Buildings.Airflow.Multizone.Examples.OneRoomのモデルをベースにするため、モデルを複製する。ファイル→Modelicaクラス新規作成からOneRoomTestというPackageを作り、そこにBuildings.Airflow.Multizone.Examples.OneRoomを複製する。
また、風圧力を考慮したモデルをつくるためにBuildings.Airflow.Multizone.MediumColumnをMediumColumnWithWindという名前で複製しておく。場所はOneRoomTestにする。 このあたりの操作はOpenModelicaでSpaceCoolingを使うときにしたものと同じである。

ファイルを複製したらMediumColumnWithWindに風圧係数と風速を受け取るコネクタを追加し、風圧力を計算する項を追加する。
まず、OMEditのアイコンビューかダイアグラムビューでModelica.Blocks.Interfaces.RealInputをドラッグ&ドロップして名前をvとCpにする。ライブラリブラウザでRealInputで検索をかけてやると見つけやすい。さらにアイコンビュー上でテキストを追加してvとCpとする。既存のテキストを右クリックして複製すると色やサイズなどの設定が楽である。
f:id:kinonotofu:20180908165137p:plain

そして、風圧力を考慮するように以下のように記述する。ここではport_a側(位置が高い方、Top側)に風圧力がかかるようにした。hの最小値は0のままにしているので、このモデルでは高さが低い側に風圧力をかけることはできないことに注意する。

model MediumColumnWithWind "Vertical shaft with no friction and no storage of heat and mass"
(略)
equation 
(略)
  dp = port_a.p - port_b.p;//ここはそのまま
//  dp = -h*rho*Modelica.Constants.g_n
  dp = -h*rho*Modelica.Constants.g_n+Cp*0.5*rho*v^2;//ここは書き換え
(省略)
end MediumColumnWithWind;

このモデルで風圧力を求めるために使っている風圧係数とは風の動圧(速度圧)が建物壁面で静圧に変わる割合のことである。風が吹いているときの壁面の圧力を屋根面平均高さとか軒の高さの動圧で割って算出している。そして風速が大きくなればその動圧に比例して壁面圧力も大きくなるということにしている。風速が変わっても流れ場の性状は風圧係数を求めたときとだいたい同じということを仮定しているのだと思うが、この仮定が有効な風速の条件とかは勉強不足でわからない。レイノルズ数が大きく違ってくるとよくないような気はするがどうなんだろう。

モデルのテスト

風圧力を考慮したモデルができたのでOneRoomで使用するように書き換える。colOutTopのBuildings.Airflow.Multizone.MediumColumnをMediumColumnWithWindに書き換えてやる。ダイヤグラムビューでみると風速と風圧係数をつなぎこむところが使いにくいので右クリックで横反転をしてやる。風圧係数と風速は固定値で与えるのでModelica.Blocks.Sources.Constantをドラッグ&ドロップしてそれぞれCp、とvという名前にする。kにそれぞれ-0.2、2.0を与え、コネクタをつないでやる。
f:id:kinonotofu:20180908183251p:plain

さらに、今は風圧力だけの換気を計算するようにしたいので、浮力が発生しないようにvolOutのInitializationタブのT_startを273.15+20にしてvolEasと同じ値にする。これでモデルを全角文字を含まないパスに保存して、実行する。
f:id:kinonotofu:20180908183316p:plain

手計算だと流量係数0.65、面積0.01m2の開口部を直列合成したときの有効開口面積は0.00459619[m]、密度を1.19684[kg/m3]として圧力差0.478736[Pa]で風量は0.00410554[m3/s]になる。計算結果が0.0041059[m3/s]でだいたい計算はできていそうである。

動圧込みの外気モデル

実はBuildings.Fluid.Sources.Outside_CpBuildings.Fluid.Sources.Outside_CpLowRiseでは気象データで得られる大気圧に風速と風圧係数から算出した動圧を加えた圧力を使っている。Outside_Cpは風圧係数を定数かコネクタから入力でき、Outside_CpLowRiseはwindPressureLowRiseで風圧係数を計算する。ただし、大気圧と風速の入力はweaBusからなのでReaderTMY3からデータを入力する必要がある。そういうことでこれを使って計算してみることにした。
上の開口部はOutside_CpでCpを-0.2にして下の開口部はOutsideを使うようにした。どちらもredeclare package Medium = Mediumをテキストビューで追加し、接続はnPortsを1にしてport[1]にcolOutTopやcolOutBotにつないだ。
気象データの方はReaderTMY3でpAtmを1.01325[bar]、TDryBulを20[degC]、winSpeを2.0[m/s]としてそれぞれParameterから入力とした。filNamは指定しないと計算できなかったので適当に"C:/OpenModelica1.12.0-64bit/lib/omlibrary/Buildings 5.1.0/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"を指定した。それから接続するときダイアグラムビューで接続するとconnect(weaBus, weaBus)などとなってしまったのでconnect(weaDat.weaBus, out.weaBus)やconnect(weaDat.weaBus, outcp.weaBus) に修正する必要があった。モデルと計算結果は以下のとおり。
f:id:kinonotofu:20180908200730p:plain
f:id:kinonotofu:20180908201013p:plain
風量は0.00406035[m3/s]でだいたい同じ値である。こちらをはじめから使えばよかったのだけれど気づかなかった。サンプルファイルもBuildings.Fluid.Sources.Examples.Outside_Cpにありだいたい同じようなことをやっている。

おわりに

とりあえず風力換気の計算ができた。次はもう少しだけ実践的に気象データを使って時刻変動する換気量を計算したい。

OpenModelicaでSpaceCooingを動かす

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。チュートリアルSpaceCoolingはStstem2、System3がOpenModelicaではエラーが発生して動かなかったのだが、動くように修正する方法をfinbackさんに教えていただいたので紹介する。finbackさんにはお世話になりっぱなしで本当にありがとうございます。

使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-Buildings 5.0.1

SpaceCoolingと関連モデルの複製とパスの修正

まずは修正したモデル一式を格納するパッケージを作成する。ファイル→Modelicaクラス新規作成を選択しSpaceCoolingTestという名前のPackageを作成する。
f:id:kinonotofu:20180831072244p:plain

SpaceCoolingをパッケージまるごとSpaceCoolingTestパッケージの中に複製する。Buildings.Examples.Tutorial.SpaceCoolingを右クリックして複製を選択。パスをSpaceCoolingTestにしてOKを押す。
f:id:kinonotofu:20180831070526p:plain
f:id:kinonotofu:20180831072430p:plain

さらにBuildings.Fluid.HeatExchangers.WetCoilCounterFlowとBuildings.Fluid.HeatExchangers.DryCoilCounterFlowを同様にして複製する。WetCoilCounterFlowはDryCoilCounterFlowを継承しており、DryCoilCounterFlowがOpenModelicaで問題となっているモデルということになる。複製が終わると以下のようになる。
f:id:kinonotofu:20180831072606p:plain

そしてパスを修正していく。
SpaceCoolingTestの冒頭でimport文によりBuildings.Boundaryconditionsを読み込むようにする。

package SpaceCoolingTest
  import Buildings.BoundryConditions;
  package SpaceCooling "Package with example for how to build a model for space cooling"
(略)

SpaceCoolingのSystem2とSystem3でそれぞれ複製した方のWetCoilCounterFlowを読み込むようにcooCoiの定義部分でBuildings.Fluid.HeatExchangers.WetCoilCounterFlowとなっている部分のBuildings.Fluid.HeatExchangers.を削除してWetCoilCounterFlowに修正する。コメントアウトした部分が元の記述。

(略)
//元はBuildings.Fluid.HeatExchangers.WetCoilCounterFlow cooCoi(略);
  WetCoilCounterFlow cooCoi(redeclare package Medium1 = MediumW, redeclare package Medium2 = MediumA, m1_flow_nominal = mW_flow_nominal, m2_flow_nominal = mA_flow_nominal, dp1_nominal = 6000, dp2_nominal = 200, UA_nominal = -QCoiC_flow_nominal / Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(T_a1 = THeaRecLvg, T_b1 = TASup_nominal, T_a2 = TWSup_nominal, T_b2 = TWRet_nominal), show_T = true, energyDynamics = Modelica.Fluid.Types.Dynamics.FixedInitial) "Cooling coil" annotation(
    Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 180, origin = {-30, -26})));
(略)

DryCoilCounterFlowの冒頭にimport文を追加してBuildings.Fluid.HeatExchangers.BaseClassesを読み込む。

model DryCoilCounterFlow "Counterflow coil with discretization along the flow paths and without humidity condensation"
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface(show_T = false);
  extends Buildings.Fluid.Interfaces.FourPortFlowResistanceParameters(final computeFlowResistance1 = false, final computeFlowResistance2 = false, from_dp1 = false, from_dp2 = false);
  import Buildings.Fluid.HeatExchangers.BaseClasses;
(略)

モデルの修正

DryCoilCounterFlowにおいて、replaceable BaseClasses.HexElementSensible ele[nEle] constrainedby BaseClasses.PartialHexElement(略)となっている部分を修正する。replaceable文ではクラスを交換することはあってもインスタンスを交換することはあまりないとのこと。また、constrainedbyでクラスを限定するような部分でカッコ内の引数をredeclareするのも一般的ではないのではないかとのこと。MElementというreplaceableなモデルをつくり、これでele[nEle]インスタンスを作成する。コメントアウトした部分が元の記述。

(略)
//  replaceable BaseClasses.HexElementSensible ele[nEle] constrainedby BaseClasses.PartialHexElement();
replaceable model MElement = BaseClasses.HexElementSensible constrainedby BaseClasses.PartialHexElement;
MElement ele[nEle](redeclare each package Medium1 = Medium1, redeclare each package Medium2 = Medium2, each allowFlowReversal1 = allowFlowReversal1, each allowFlowReversal2 = allowFlowReversal2, each tau1 = tau1 / nEle, each m1_flow_nominal = m1_flow_nominal, each tau2 = tau2, each m2_flow_nominal = m2_flow_nominal, each tau_m = tau_m / nEle, each UA_nominal = UA_nominal / nEle, each energyDynamics = energyDynamics, initialize_p1 = {i == 1 and not Medium1.singleState for i in 1:nEle}, initialize_p2 = {i == 1 and not Medium2.singleState for i in 1:nEle}, each deltaM1 = deltaM1, each deltaM2 = deltaM2, each from_dp1 = from_dp1, each from_dp2 = from_dp2, dp1_nominal = {if i == 1 then dp1_nominal else 0 for i in 1:nEle}, dp2_nominal = {if i == nEle then dp2_nominal else 0 for i in 1:nEle}) "Heat exchanger element" annotation(
     Placement(transformation(extent = {{0, 0}, {20, 20}})));
(略)

WetCoilCounterFlowでele[nEle]はredeclareされているので対応するように修正。こちらもインスタンスを再宣言するのではなくクラス(model)を再宣言するようにする。コメントアウトした部分が元の記述。

(略)
//extends Buildings.Fluid.HeatExchangers.DryCoilCounterFlow(redeclare replaceable package Medium2 = Modelica.Media.Interfaces.PartialCondensingGases, redeclare final Buildings.Fluid.HeatExchangers.BaseClasses.HexElementLatent ele[nEle]);
extends Buildings.Fluid.HeatExchangers.DryCoilCounterFlow(redeclare replaceable package Medium2 = Modelica.Media.Interfaces.PartialCondensingGases, redeclare final model MElement=Buildings.Fluid.HeatExchangers.BaseClasses.HexElementLatent);
(略)

計算実行

修正が終わったファイル一式を保存して実行する。たぶんファイルパスに日本語とか全角文字が含まれていると対応できない。
計算ができなくておかしいと思っていたが、WetCoilCounterFlowを右クリックしての順番をDryCoilCounterFlowの下に変えてやると計算できた。当然といえば当然だが継承元を先に記述しないといけないのだろう。
f:id:kinonotofu:20180831083102p:plain

System2の室温は以下のとおり。
f:id:kinonotofu:20180831081118p:plain

System3の室温は以下のとおり。
f:id:kinonotofu:20180831081530p:plain

おわりに

無事にOpenMoelicaで動作させることができた。多分同じような修正(インスタンスをreplaceable、redeclareしているような部分を書き直す)で他にも現在OpenModelicaで動いていない部分が動くようになったりするのではないかと思う。この修正でDymolaで困ることがなければプルリクやイシューで頼めば直してもらえるはず。
修正方法を教えて頂いたfinbackさんには本当に感謝します。

OpenModelicaでBuildingsライブラリで換気回路網計算を学ぶ_その1

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。
今回はBuildings.Airflow.Multizoneパッケージを見ていく。Buildings.Airflowパッケージでは異なる部屋間や部屋と外部環境との間の空気の流れを計算するためのモデルがあるのだが、直下にはMultizoneパッケージのみがぶら下がっていてそこに各要素のモデルがある。ダクトのネットワークはBuildings.Fluidを見ろと書いてあるのだが多分FixedResistancesとかMoversあたりを使うのだと思う。
このパッケージでできる換気回路網計算はCFDとは異なり、空間をそれぞれ1つの点で表現し、空間同士を開口による流れの抵抗のネットワークとしてつないでいくものだ。年間の自然換気量の変化の影響を見たいときなどCFDで非定常計算をするのはあまり実用的ではないのでこちらを使ったりする。定常計算でもこちらの方がざっくり設定できるし1ケースの計算時間もたぶん早いので都合がよいことも多い。

使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-Buildings 5.1.0

Buildings.Airflow.Multizoneの構成

名称 説明
UsersGuide ユーザーガイド
DoorDiscretizedOpen 高さに沿って離散化したドアモデル
DoorDiscretizedOperable 高さに沿って離散化したドアモデル
EffectiveAirLeakageArea 有効漏気面のモデル
MediumColumn 摩擦がなく熱と質量の蓄積がない垂直軸のモデル
MediumColumnDynamic 摩擦はないが熱と質量の蓄積がある垂直軸のモデル
Orifice オリフィス(単純開口)のモデル
ZonalFlow_ACS 1秒あたりの換気量の入力によるゾーン流のモデル
ZonalFlow_m_flow 1秒あたりの換気量の入力によるゾーン流のモデル
Types 型の定義のパッケージ
Examples モデルの使用法やテストモデルなどのパッケージ
Validation バリデーション用のモデルのパッケージ
BaseClasses Buildings.Airflow.Multizoneの基底クラスのパッケージ

ユーザーガイドと型定義やサンプルや検証や基底クラスなどのパッケージがあるが実際に使用するモデルは8個である。正直ユーザーガイドには大したことは書いていないのでExamplesを見ながらなんとなく組み上げていくのだと思う。
Typesパッケージで定義されているものは1つだけでdensitySelectionというMediumColumnモデルの密度の設定パラメータとなる列挙型の変数があるのみである。

type densitySelection = enumeration(
  fromTop   "Density from top port",
  fromBottom   "Density from bottom port",
  actual   "Actual density based on flow direction")
  "Enumeration to select density in medium column";

Examplesパッケージは結構たくさん例がある。

名称 説明
CO2TransportStep 浮力駆動によるCO2輸送モデル
ChimneyShaftNoVolume シャフトの定常状態モデルでの煙突効果を示すモデル
himneyShaftWithVolume シャフトの動的モデルによる煙突効果を示すモデル
ClosedDoors 3つの閉じたドアのモデル
NaturalVentilation 密度差による流れの逆転のテストモデル
OneEffectiveAirLeakageArea 有効漏気面を持つモデル
OneOpenDoor 1つの開いたドアと1つの閉じたドアのモデル
OneRoom マルチゾーン空気交換モデルの検証のための1つの室のモデル
Orifice オリフィスのモデル
ReverseBuoyancy 4つの室と逆流する浮力駆動型空気循環モデル
ReverseBuoyancy3Zones 3つの室と逆流する浮力駆動の空気循環モデル
ZonalFlow 2つの室で所定の空気交換を行うモデル

ValidationパッケージはThreeRoomsContamモデル一つだけである。Michael WetterのMultizone Airflow Model in Modelicaに詳細な内容が書いてあるようだ。

Buildings.Airflow.Multizone.Examples.OneRoom

とりあえずサンプルとして一室モデルを見ていく。
f:id:kinonotofu:20180807233745p:plain
室volEasと外気volOutを、上下の開口部oriOutTopとoriOutBotでつないで温度差換気を行っているモデルである。室と開口部の間はcolEasInTop、colEasInBot、colOutTop、colOutBotという高さ方向の距離を示すモデルでつないでいる。

  connect(colEasInTop.port_a, oriOutTop.port_a);
  connect(colEasInTop.port_b, volEas.ports[1]);
  connect(colEasInBot.port_a, volEas.ports[2]);
  connect(colEasInBot.port_b, oriOutBot.port_a);
  connect(oriOutBot.port_b, colOutBot.port_b);
  connect(colOutBot.port_a, volOut.ports[1]);
  connect(colOutTop.port_b, volOut.ports[2]);
  connect(colOutTop.port_a, oriOutTop.port_b);

空気の流れの計算なので媒体としてBuildings.Media.Airを使用している。

  package Medium = Buildings.Media.Air;

空間のモデルの設定

室volEasの設定はSpaceCoolingで見たときと比べて、熱容量の係数を使っていない(家具などの熱容量を考慮しない)、massDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitialを指定する、m_flow_nominal=0.001が0に近い小さな値になっているなどの違いがある。
以下に設定を示す。

  Buildings.Fluid.MixingVolumes.MixingVolume volEas(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=273.15+20,
    V=2.5*5*5,
    nPorts=2,
    m_flow_nominal=0.001,
    massDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial);

外気volOutはモデルとしては室と同じものを使用している。
体積を非常に大きくとっているのは室との換気で温度が変動しないようにするためだろうか。また、外気側では圧力を指定している。外気を圧力の基準とするような意味合いだと思うがMedium.p_defaultで大気圧を与えている。こちらのmassDynamicsはFixedInitialになっている。これで圧力固定になるのだろうか。

  Buildings.Fluid.MixingVolumes.MixingVolume volOut(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=273.15 + 10,
    V=1E12,
    p_start=Medium.p_default,
    nPorts=2,
    m_flow_nominal=0.001,
    massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial);

開口部のモデルの設定

上下の開口部oriOutTopとoriOutBotをまとめて示す。

  Buildings.Airflow.Multizone.Orifice oriOutTop(
    redeclare package Medium = Medium,
    A=0.01,
    m=0.5);
  Buildings.Airflow.Multizone.Orifice oriOutBot(
    redeclare package Medium = Medium,
    A=0.01,
    m=0.5);

OMEdit上の設定画面は以下のとおり。
f:id:kinonotofu:20180807234101p:plain
オリフィスの流量係数は0.65がデフォルトになっており今回はデフォルト値をつかっている。ForceErrorControlOnFlowAはよくわからないが流量を見たいときはtrueにしておくらしい。Aが開口面積、mは0.5が乱流時で1が層流時を示すらしい。useDefaultPropertiesはfalseにすると実際の密度と粘性係数を使用し、trueだとデフォルト値を使用するようになっている。dp_turbulentは層流と乱流が一致するときの差圧?だが0.1を推奨しているらしい。lWetはレイノルズ数の計算に使用するパラメーターなので水力直径だろう。密度の扱いは計算の安定性に関わるので設定があるのはわかるけれど、粘性係数は気にしたことがなかった。乱流層流の切替も気にしたことがなかったけど確かに流量が変わりそうな気はする。 
以下の残りの2つのタブは流れに関係する設定でよくあるやつだった。
f:id:kinonotofu:20180807234116p:plain
f:id:kinonotofu:20180807234126p:plain

高さ方向の距離を示すモデルの設定

Buildings.Airflow.Multizone.MediumColumnは開口部の高さ位置を指定するためのモデルなのだと思う。浮力換気のための高低差による圧力の変動を計算しているのだと思う。設定を以下に示す。

  Buildings.Airflow.Multizone.MediumColumn colOutTop(
    redeclare package Medium = Medium,
    h=1.5,
    densitySelection=Buildings.Airflow.Multizone.Types.densitySelection.fromBottom);
  Buildings.Airflow.Multizone.MediumColumn colOutBot(
    redeclare package Medium = Medium,
    h=1.5,
    densitySelection=Buildings.Airflow.Multizone.Types.densitySelection.fromTop);
  Buildings.Airflow.Multizone.MediumColumn colEasInTop(
    redeclare package Medium = Medium,
    h=1.5,
    densitySelection=Buildings.Airflow.Multizone.Types.densitySelection.fromBottom);
  Buildings.Airflow.Multizone.MediumColumn colEasInBot(
    redeclare package Medium = Medium,
    h=1.5,
    densitySelection=Buildings.Airflow.Multizone.Types.densitySelection.fromTop);

OMEdit上の設定画面は以下のとおり。
f:id:kinonotofu:20180808000457p:plain
f:id:kinonotofu:20180808000649p:plain
hが高さ方向の距離を示し、Topにつないだほうが上、Bottomにつないだほうが下という位置関係になるようだ。ここでの室の圧力の基準位置がどこだかわからないが、基準位置を床にして上に0.5と3.5などのように床面と開口面高さ方向中央位置で指定したほうがよさそうな気がする。このあたりは自分で整合性をとっておけばたぶん問題はないとは思う。
densitySelectionではモデルのどちら側の密度を使用するかを指定している。TopとBottomの間にはρghだけ圧力差があるのだが、このときのρをどちら側からとってくるかを選んでいるのだろう。actualという選択肢もあるのでそのときは風上側の密度を使用するのだと思う。

計算実行

温度差換気(浮力駆動の換気)で気にすることはだいたい以下のとおり。
* 外気はどの高さでも同じ温度、室内もどの高さでも同じ温度(完全混合の仮定)
* 温度(=室)によって密度ρが変わる。
* 高さにより「密度ρ × 重力加速度g × 高さh」だけ圧力が変わる。
* 温度(=密度)が異なる二つの空間の間の圧力差は高さによって変わる。
* 圧力差によって流れが発生。「開口面の高さでの圧力差により流れを計算」するので同じ室の間でも開口部ごとに流れの方向がかわることができる。

計算結果は以下の通り。とりあえず1秒だけ計算している。
f:id:kinonotofu:20180808002843p:plain
自分で計算をしてみると0.0065[m3/s]だったのでだいたいよさそうである。
1時間分計算してみると室温が下がっている様子がわかる。
f:id:kinonotofu:20180808003437p:plain
圧力は以下のとおり。外気の圧力が一定なのが確認できた。室の圧力が外気を上回ったり下回ったり変動しているように見えるがレンジの設定が細か過ぎるだけでほぼ外気と同じ圧力となっている。ちなみにcsvでデータ出力すると1.01325[bar]で一定値となってでてくる。桁落ちされるのは困るのでどうにかしたいが大気圧との差分をどこかで計算すれば場当たり的には対処できそうな気はする。しかしなんでグラフ上で見える値をそのまま書き出せないのだろう。ちなみに単位が[bar]なのは[Pa]に直すのを忘れていただけでグラフ上もcsvも[Pa]にできる。

f:id:kinonotofu:20180808011533p:plain

おわりに

なんとなく雰囲気は分かったような気がするけれど、まだあまり仕組みはよく分かっていない。Fluidportをつないであげれば開口部では圧力から流量と計算し、室のほうで流量の収支をとるように圧力を補正してくれているのだろうか。開口への風圧の与え方もわからないのだけれど、別のFluidポートをつなぎこんで圧力だけあたえるとかはできなさそうな気がするのでMediumColumnに手を加えて風圧力を組み込むしかないのかもしれない。あと一応ちゃんと論文を読んだほうがよさそうである。

OpenModelica(とJModelica)でBuildingsライブラリを学ぶ_その9

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。
前回SpaceCoolingのSystem2をやったので今回はSystem3をやる。
使用バージョン
-OpenModelica1.12.0 →Modelica標準ライブラリ3.2.2
-JModelica2.2 →Modelica標準ライブラリ3.2
-Buildings 5.0.1

System3の概要とSystem2からの変更点

f:id:kinonotofu:20180804205959p:plain
System2では気象データファイル読み取り用のモデルweaDatを使用していたものの、使用時は定数を設定して一定の外気温を出力しているだけだった。今回はその部分をちゃんと気象データファイルを読み込んで外気温を出力するように変更する。また、一定の外気温度の場合は定常状態となりオープンループ制御でも一定の室温に収束していたが、外気温が変動するとそうもいかなくなるので閉ループ制御を追加する。
それからvolのenergyDynamicsがFixedInitialからSteadyStateInitialにかわっていた。このタイミングで変更した理由はよくわからない。 閉ループ制御のために新しく追加したモデルはオンオフコントローラーcon、設定温度TRooSetPoi、室温センサーsenTemRooであり、ポンプ流量mWat_flowはSystem2とは別のモデルを使用している。これらはModelica標準ライブラリを使って実装している。Modelica標準ライブラリでuがインプット、yがアウトプットになっているのは何かの略なのだろうけど何なんだろう。追加したモデルのコネクタの設定を以下に示す。

  connect(TRooSetPoi.y, con.reference);
  connect(vol.heatPort, senTemRoo.port);
  connect(senTemRoo.T, con.u);
  connect(con.y, mWat_flow.u);
  connect(mWat_flow.y, souWat.m_flow_in);

senTemRooはvolから温度をもらってconに渡している。conは別のポートにもTRooSetPoiから温度をもらっている。conからオンオフの制御信号をmWat_flowに送り、mWat_flowが信号を流量にしてsouWatに渡している。

気象データ読取モデルweaDat

前回はこのモデルをつかいながらも外気温は定数を出力していたが今回は.mosファイルからデータを読み取って出力する。そのため、TDryBulSouをBuildings.BoundaryConditions.Types.DataSource.ParameterからBuildings.BoundaryConditions.Types.DataSource.Fileへ変更している。TDryBul=TOut_nominalが残っているのは初期値として使うからだろうか。設定しなくてもよいかもしれない。

  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    pAtmSou=Buildings.BoundaryConditions.Types.DataSource.Parameter,
    TDryBul=TOut_nominal,
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"),
    TDryBulSou=Buildings.BoundaryConditions.Types.DataSource.File)

オンオフコントローラーcon

ややこしいが熱コンダクタンス用のモデルのインスタンスはtheConという名前でこれとは別物である。 TRooSetPoiから設定温度をreferenceに、senTemRooから計測温度をuに受け取り、mWat_flowへyを受け渡している。帯域幅は1[K]に設定している。

  Modelica.Blocks.Logical.OnOffController con(bandwidth=1)
    "Controller for coil water flow rate";

Modelica.Blocks.Logical.OnOffControllerの実装は以下の通り。

  block OnOffController
    Blocks.Interfaces.RealInput reference
    Blocks.Interfaces.RealInput u
    Blocks.Interfaces.BooleanOutput y
    parameter Real bandwidth(start=0.1)
    parameter Boolean pre_y_start=false
  initial equation
    pre(y) = pre_y_start;
  equation
    y = pre(y) and (u < reference + bandwidth/2) or (u < reference - bandwidth/2);
  end OnOffController;

pre(y)で1時刻前のyの値を参照している。yが論理演算になっているが設定温度-0.5×帯域幅より低い場合はtrue、設定温度+0.5×帯域幅より高い場合がfalseであることに注意。bandwidthの範囲の温度のときはpre(y)と同じになる。
f:id:kinonotofu:20180805195753p:plain

設定温度TRooSetPoi

TRooSetPoiは定数を出力するだけのモデルである。conが設定値をコネクタからもらってくる仕様になっているため追加されている。

  Modelica.Blocks.Sources.Constant TRooSetPoi(k=TRooSet)

f:id:kinonotofu:20180805195858p:plain

室温センサーsenTemRoo

volから温度をもらってconへ出力している。特に設定はない。

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTemRoo

conの入力がReal型の数値であり、volからのコネクタがHeatPortかFluidportなので、HeatPortから温度をもらってReal型の数値として出力している。 Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensorの実装は以下の通り。

  model TemperatureSensor
    Modelica.Blocks.Interfaces.RealOutput T(unit="K");
    Interfaces.HeatPort_a port;
  equation
    T = port.T;
    port.Q_flow = 0;
  end TemperatureSensor;

f:id:kinonotofu:20180805195828p:plain

ポンプ流量mWat_flow

mWat_flowのモデルをModelica.Blocks.Sources.ConstantからModelica.Blocks.Math.BooleanToRealに置き換える。ポンプsouWatの入力はBoolean型のオンオフ信号を使えないのでオンオフ信号を流量に変換するために使っている。OnOffControllerは暖房向けのオンオフになっており、冷却時の設定としてtrueで0、falseでmW_flow_nominalを出力している。

  Modelica.Blocks.Math.BooleanToReal mWat_flow(realTrue=0, realFalse=
        mW_flow_nominal) 

Modelica.Blocks.Math.BooleanToRealの実装は以下の通り。

  block BooleanToReal "Convert Boolean to Real signal"
    parameter Real realTrue=1.0;
    parameter Real realFalse=0.0";
    Blocks.Interfaces.RealOutput y;
  equation
    y = if u then realTrue else realFalse;
  end BooleanToReal;

f:id:kinonotofu:20180805195714p:plain

計算実行

やっぱりOpenModelicaでは実行できないので前回と同じくJModelicaで実行してみる。
計算は15552000[s]から15638400[s]まで9732個のデータが出力されており一日分の計算になっているものの時間間隔が均等ではなかった。そういうものなのだろうか。
* 室温と外気温
f:id:kinonotofu:20180805202706p:plain

外気温が変動しているが、室温はオンオフ制御でだいたい設定温度±0.5[K]くらいになっている。グラフの形もまぁチュートリアルのドキュメントにあるものと同じ形状にはなっている。ちなみにweaDatのTDryBulSouは常に1を、TDryBulは常に305.5を出力しており、実際に外気温を確認できるのはTDryBul_in_internalである。TDryBulはあくまで一定値の出力用、TDryBulSouは設定値Buildings.BoundaryConditions.Types.DataSource.Fileを示す数値が出力されているだけのようだった。

  • ポンプの水の発停
    f:id:kinonotofu:20180805203056p:plain
    ポンプの流量も一応確認。

  • コイル水側の出入口温度
    f:id:kinonotofu:20180805203915p:plain
    水の出入口温度はポンプが停止して流量がなくなってもコイルを通過する空気温度になっているようである。流量が0だから計算できないとかにはなっていないらしい。

おわりに

コネクタの型をあわせるためにモデルを追加するのはもう少しシンプルにできないものかなぁと思ったけどモデルを入れ子にしてもう少しまとまりをつくるとすっきりするのだろうか。今回追加した4つのモデルをまとめて一つのモデルとして扱ってもいいような気がする。とりあえずBuildingsライブラリのExamples/Tutorial/SpaceCoolingはひとまずこれで終わり。このチュートリアルの中でもいろいろ疑問を放置したままになっていることが多いのでそのあたりは少しずつ整理してつぶしていきたいと思った。ライブラリの.moファイルのannotationにそれぞれ書いてあるドキュメントの日本語訳作業ものんびりはじめた。

github.com

さすがに全部を訳し切るのはできない気がするけれど使用するモデルの整理のついでくらいに思って部分的にでもやろうと思う。なによりもう一個の方がまだ終わってないので図とかそろえてさっさと形を整えてあげないといけないのだけれど。。。
とりあえずブログでは次回からはAirflowのExampleでも見ながら建物の換気回路網計算をしたいと思う。

OpenModelica(とJModelica)でBuildingsライブラリを学ぶ_その8

概要

OpenModelicaでLBNLのBuildingsライブラリを使う。初心者なのでいろいろ教えて頂けるとありがたい。 SpaceCoolingのSystem2をやる。前回でモデルの設定は全部見たので今回は計算をまわしたい。
使用バージョン
-OpenModelica1.12.0
-JModelica2.2 → Modelica標準ライブラリ3.2?
-Buildings 5.0.1

JModelicaを使う

System2の計算を実行しようとOpenModelicaで実行したところコンパイルエラーが発生した。
f:id:kinonotofu:20180725222614p:plain
もともとBuildingsライブラリの動作検証はDymolaという商用ソフトとJModelicaというOSSソフトでしか行っていないのだった。そういうわけでJModelicaを使うことにした。Windows環境でのインストールは公式サイトからバイナリインストーラをダウンロードしてきて実行すればたぶん悩むことは無いと思う。
JModelicaはOMEditのようなGUIでモデルを設定するツールがないようだ。OMEditでモデルを作成して実行はJModelicaというのもありかもしれないし、ちょっとしたものならVSCode(Modelica用の拡張機能がある)などテキストエディタで書くのもよいかもしれない。
次に書くJModelicaの使い方はfinbackさんに教えて頂きました。ありがとうございます。

  • Buildingsライブライリを適当な作業場所へ置いてBuildingsライブライリのフォルダの名前をバージョン名抜きのBuildingsという名称にする。
  • JModelicaのIPythonを実行し、cdでBuildingsフォルダを置いた場所へ移動する。
  • 以下のコードを入力してSystem2のモデルをfmuファイルにコンパイルする。
from pymodelica import compile_fmu
fmufile = compile_fmu('Buildings.Examples.Tutorial.SpaceCooling.System2','Buildings')

f:id:kinonotofu:20180725230258p:plain
* これダメじゃないかと思うようなすごい勢いで「ファイルが見つかりません」を訴えかけてきてエラーを出しながらもBuildings_Examples_Tutorial_SpaceCooling_System2.fmuファイルが生成される。気にせず以下のコードを入力して生成されたfmuファイルを実行する。

from pyfmi import load_fmu
model = load_fmu('Buildings_Examples_Tutorial_SpaceCooling_System2.fmu')
model.simulate()
  • Buildings_Examples_Tutorial_SpaceCooling_System2_result.mat が出力されるのでJModelicaのplot-GUIで読み込む。

このmatファイルをOMEditで読み込むと温度は絶対温度でのみ見ることができる。System1ではOpenModelicaで実行して結果を読み込むと温度を摂氏と絶対温度と切り替え表示ができていたのでJModelicaで実行したときの仕様だと考えられる。

System2のおさらい

f:id:kinonotofu:20180606201749p:plain
System2の簡単なおさらいは以下の通り。
* 熱容量を持った室に発熱1000Wと熱貫流を熱流としてコネクタから与えている。
* さらに流体を与えるコネクタから冷気を給気して冷やしている。
* 室の熱貫流はテキストデータから読み取った外気温度から計算。
* 室にコイルで冷却した外気を給気。この外気温度もおなじテキストデータから読み取っている。
* 外気はファンの位置で質量流量固定。
* 室の排気は冷却コイルに入る前の外気と顕熱交換。
* コイルの冷水側は温度固定、流量固定

パラメータと各モデルの設定を以下の表に示す。

変数名 説明
V 室容積[m3] 6*10*3
eps 熱交換器の熱交換効率[-] 0.8
TASup_nominal 室の給気温度の公称値[K] 273.15+18
TRooSet 室の設定室温[K] 273.15+24
TOut_nominal 外気の設計温度[K] 273.15+30
THeaRecLvg 給気側の熱交換器出口温度[K]
=給気側のコイル入口温度[K]
TOut_nominal
-eps*(TOut_nominal-TRooSet)
QRooInt_flow 室の発熱[W] 1000
QRooC_flow_nominal 室の冷却負荷の公称値[W] -QRooInt_flow
-10E3/30*(TOut_nominal-TRooSet)
mA_flow_nominal 空気の質量流量の公称値[kg/s]
温度変化後を考慮して1.3倍?
1.3*QRooC_flow_nominal/1006
/(TASup_nominal-TRooSet)
dTFan ファンによる想定温度上昇[K] 2
QCoiC_flow_nominal 熱交換器と潜熱負荷を考慮にいれたコイルの冷却負荷[W] 4*(QRooC_flow_nominal
+mA_flow_nominal*(TASup_nominal
-THeaRecLvg-dTFan)*1006)
TWSup_nominal 水の往き温度?[K] 273.15+16
TWRet_nominal 水の還り温度?[K] 273.15+12
mW_flow_nominal 水の質量流量の公称値[kg/s] QCoiC_flow_nominal/(TWRet_nominal-TWSup_nominal)/4200
インスタンス 用途 設定
vol redeclare package Medium = MediumA
m_flow_nominal=mA_flow_nominal
V=V
nPorts=2
energyDynamics=
Modelica.Fluid.Types.Dynamics.FixedInitial
mSenFac=3
theCon 室の壁体の熱コンダクタンス G=10000/30
TOut 外気温 なし
preHea 室の発熱ソース Q_flow=QRooInt_flow
fan 給気ファン redeclare package Medium=MediumA
m_flow_nominal=mA_flow_nominal
energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
hex 熱交換器 redeclare package Medium1=MediumA
redeclare package Medium2=MediumA
m1_flow_nominal=mA_flow_nominal
m2_flow_nominal=mA_flow_nominal
dp1_nominal=200
dp2_nominal=200
eps=eps
cooCoi 冷却コイル redeclare package Medium1=
MediumW
redeclare package Medium2=MediumA
m1_flow_nominal=mW_flow_nominal
m2_flow_nominal=mA_flow_nominal
dp1_nominal=6000
dp2_nominal=200
UA_nominal=-QCoiC_flow_nominal
/Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
T_a1=THeaRecLvg,T_b1=TASup_nominal
,T_a2=TWSup_nominal,T_b2=TWRet_nominal)
show_T=true
energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
out 外気 nPorts=2
redeclare package Medium=MediumA
souWat 冷水ポンプ
(流量ソース)
nPorts=1
redeclare package Medium=MediumW
use_m_flow_in=true
T=TWSup_nominal
sinWat 冷水の排出先 nPorts=1
redeclare package Medium=MediumW
weaDat 気象データ pAtmSou=Buildings.BoundaryConditions.Types.DataSource.Parameter
TDryBulSou=Buildings.BoundaryConditions.Types.DataSource.Parameter
TDryBul=TOut_nominal
filNam=
Modelica.Utilities.Files.loadResource(
"modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos")
weaBus 気象データ用バス なし
mAir_flow 給気風量 k=mA_flow_nominal
mWat_flow 冷水流量 k=mW_flow_nominal
senTemHXOut 給気側熱交換器出口温度 redeclare package Medium=MediumA
m_flow_nominal=mA_flow_nominal
senTemSupAir 給気側コイル出口温度 redeclare package Medium=MediumA
m_flow_nominal=mA_flow_nominal

TWSup_nominalとTWRet_nominalはおそらく名前が逆である。
パラメータは直接数値を指定したものと数式で入力したデータがある。だいたい次のような流れでパラメータを数式で指定している。考え方を残しておくという意味で良いと思うし、パラメータは計算の途中で変更できない仕様なのでたぶんモデルを呼び出すたびに計算して遅くなるとかもないはず。
* 設定室温から室の負荷を求める。
* 室の負荷と給気温度から空気の風量を求める。
* 空気の風量とコイルの空気側の入口出口温度差からコイルの処理負荷を求める。
* コイルの処理負荷と水の入口出口温度差から水の流量を求める。

ここで空気の風量を1.3倍している理由がちょっとわかっていない。

System2の実行

ここで注目すべきは開ループ制御により室温vol.Tが設計温度273.15+24=297.15[K]になっているかである。ついでに熱交換器からの排気の影響が気になっていたので給気側外気条件の温度out.Tが273.15+30=303.15[K]になっているかを見る。 f:id:kinonotofu:20180725225019p:plain
外気のほうは排気の影響はなさそうだが、室温が少し低くなっている。風量1.3倍がよくないのではないかと思ったが公式のドキュメントでも室温が低くなっていて計算結果自体はだいたいあっていそうではある。念のために風量を1.3倍→1.0倍として計算してみた。CoocoiでShou_TをTrueにしていたのでそこの温度も表示してみる。Fluidportからは標準では温度がでないためこの設定により温度出力用のportができていた。
f:id:kinonotofu:20180725233030p:plain
JModelicaの結果表示からテキストデータでの書き出しがよく分からないのでOMEditのほうでCSVデータを書き出して計算終了時点の温度を見てみる。

名称 変数名 設計温度 計算温度
室温 vol.T 24℃ 23.758℃
空気側コイル出口温度 a1.T 16℃ 18℃
空気側コイル入口温度 a2.T 25.2℃ 25.038℃
水側コイル出口温度 b1.T 16℃ 17.818℃
水側コイル入口温度 b2.T 12℃ 16.648℃

風量を直すと室温はそれらしい値になった。ただ給気温度となるコイル出口温度が低いしコイルの水側にいたっては固定値のはずのコイル入口温度が全然違う。System2で想定される計算結果といえるのが風量1.3倍にしていたもののグラフしかなくて、それはまぁだいたいそれっぽくなってはいたけれど、どうにも不安になる結果である。まぁ細かい検証とかはまた別の機会にやりたいと思う。

おわりに

今回は結果を見るときにそんな変数あったっけっていうものまで並んでいたので表示したい変数を探すのが少し手間でした。なにかよい方法はないかなぁと。それから、慣れもあると思うけれどプレとかポストの処理はOpenModelicaがやっぱりやりやすくて、Buildingsライブラリを使うにしてもJModelicaと併用か、OpenModelicaで計算できるようにしたいなぁと思いました。JModelicaの計算もこれで大丈夫なのか不安なところもあるし、新たな課題が見つかったような感じです。
OpenModelicaで計算できなかったときはとても困ったけれどfinbackさんの助けによりなんとか計算ができました。本当に感謝しています。まだまだ知らない事だらけだけれどSystem2を通してまた少し理解が進みました。次はSystem3をやります。