updateMOS_and_Run.py
updateMOS_and_Run.pyの全文を載せときます。
updateMOS_and_Run.py
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
import re import subprocess from pathlib import Path # === ここから別ファイルを import して利用 === from sync_to_table import parse_boundary_sync, append_output_row # ===== パス設定 ===== base = Path("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom") input_file = base / "constant/outletWeightAreaTempFile" mos_file = base / "HVACSystem002.mos" sync_file = base / "constant/boundarySyncFile" # ===== outletWeightAreaTempFile の読み込み ===== text = input_file.read_text(encoding="utf-8") def get_value(key): """Tout,293.094; のような行から値を取り出す""" m = re.search(rf"{key},([0-9eE\.\-]+);", text) return float(m.group(1)) if m else None Tout = get_value("Tout") Tprobe = get_value("Tprobe") TimeVal = get_value("Time") print(f"[INFO] Read from {input_file.name}: Tout={Tout}, Tprobe={Tprobe}, Time={TimeVal}") # ===== MOSファイルを自動生成 ===== mos_content = f""" //loadModel(Modelica); //loadFile("{base}/HVACSystem001.mo"); buildModel(HVACSystem001, startTime=0, stopTime=300, numberOfIntervals=1000, tolerance=1e-6, method="dassl", outputFormat="mat", fileNamePrefix="HVACSystem"); system("/tmp/OpenModelica/HVACSystem -override Tinlet={Tout},TSensor={Tprobe} -r={base}/HVACSystemResult.mat"); t := {TimeVal}; tout_val := val(Tout, t, fileName="{base}/HVACSystemResult.mat"); mout_val := val(mout, t, fileName="{base}/HVACSystemResult.mat"); heatFlowSensor_Q_flow_val := val(heatFlowSensor.Q_flow, t, fileName="{base}/HVACSystemResult.mat"); TSensor_val := val(TSensor, t, fileName="{base}/HVACSystemResult.mat"); TTarget_val := val(ramp.y, t, fileName="{base}/HVACSystemResult.mat"); // ===== OpenFOAM形式のヘッダを書き出す ===== writeFile("{sync_file}", "FoamFile\\n" +"{{\\n" +" version 2.0;\\n" +" format ascii;\\n" +" class dictionary;\\n" +" location constant;\\n" +" object boundarySyncFile;\\n" +"}}\\n" ); // ===== データ行を書き出す ===== writeFile("{sync_file}", "Time\\t" + String(t) + ";\\n", append=true); writeFile("{sync_file}", "mout\\t" + String(mout_val) + ";\\n", append=true); writeFile("{sync_file}", "Tout\\t" + String(tout_val) + ";\\n", append=true); writeFile("{sync_file}", "heatFlowSensor.Q_flow\\t" + String(heatFlowSensor_Q_flow_val) + ";\\n", append=true); writeFile("{sync_file}", "TSensor\\t" + String(TSensor_val) + ";\\n", append=true); writeFile("{sync_file}", "ramp.y\\t" + String(TTarget_val) + ";\\n", append=true); """ mos_file.write_text(mos_content, encoding="utf-8") print(f"[INFO] Wrote updated {mos_file.name}") # ===== runMos.sh 経由で実行 ===== cmd = ["./runMos.sh", str(mos_file.name)] print(f"[INFO] Running: {' '.join(cmd)} in {base}") subprocess.run(cmd, cwd=base) # ===== 処理完了後にロック削除 ===== lock = base / "constant/updateMOS.lock" if lock.exists(): lock.unlink() print("OK [INFO] Lock file removed, OpenFOAM can continue.") else: print("[INFO] No lock file found.") # ===== boundarySyncFile を読み込み output.dat に追記 ===== vals = parse_boundary_sync(sync_file) out_path, row = append_output_row(base, vals, headers=["Time","mout","Tout","heatFlowSensor.Q_flow","TSensor", "ramp.y"], sep="\t") print(f"[INFO] Appended to {out_path}: {row}") |
ここで行っているのは以下です。
- HVACSystem002.mosというOpenModelicaをスクリプト実行するためのファイルを作成
- 最後にrunMos.shによりHVACSystem002.mosを実行
- constant/updateMOS.lockが削除し、Python実行が終了したことをOpenFOAMに知らせる
- output.datにOpenModelicaで得られた結果を出力する
HVACSystem002.mos
mosファイルの全文を載せておきます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//loadModel(Modelica); //loadFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystem001.mo"); buildModel(HVACSystem001, startTime=0, stopTime=300, numberOfIntervals=1000, tolerance=1e-6, method="dassl", outputFormat="mat", fileNamePrefix="HVACSystem"); system("/tmp/OpenModelica/HVACSystem -override Tinlet=293.0,TSensor=310.0 -r=/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); t := 300.0; tout_val := val(Tout, t, fileName="/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); mout_val := val(mout, t, fileName="/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); heatFlowSensor_Q_flow_val := val(heatFlowSensor.Q_flow, t, fileName="/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); TSensor_val := val(TSensor, t, fileName="/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); TTarget_val := val(ramp.y, t, fileName="/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat"); // ===== OpenFOAM形式のヘッダを書き出す ===== writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "FoamFile\n" +"{\n" +" version 2.0;\n" +" format ascii;\n" +" class dictionary;\n" +" location constant;\n" +" object boundarySyncFile;\n" +"}\n" ); // ===== データ行を書き出す ===== writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "Time\t" + String(t) + ";\n", append=true); writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "mout\t" + String(mout_val) + ";\n", append=true); writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "Tout\t" + String(tout_val) + ";\n", append=true); writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "heatFlowSensor.Q_flow\t" + String(heatFlowSensor_Q_flow_val) + ";\n", append=true); writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "TSensor\t" + String(TSensor_val) + ";\n", append=true); writeFile("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/constant/boundarySyncFile", "ramp.y\t" + String(TTarget_val) + ";\n", append=true); |
やっていることをまとめると以下です。
- Modelica標準ライブラリを読み込む
loadModel(Modelica); - 指定されたモデルファイルを読み込む
/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystem001.mo - モデルをビルド(コンパイル)
モデル名:HVACSystem001
解析条件:
- 開始時刻:0
- 終了時刻:300
- ステップ数:1000
- 許容誤差:1e-6
- 数値積分法:dassl
- 出力形式:.mat
- 出力プレフィックス:HVACSystem - システムコマンドでシミュレーションを実行(ここで値を更新している)
パラメータ上書き
-Tinlet=293.0
-TSensor=310.0
結果出力:
/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/HVACSystemResult.mat - 指定時刻
t=300.0における変数値を読み取る
-Tout(出口温度)
-mout(質量流量)
-heatFlowSensor.Q_flow(熱流量)
-TSensor(センサー温度)
-ramp.y(ターゲット温度) - OpenFOAM形式のヘッダを
constant/boundarySyncFileに書き出す
FoamFileブロックとして、
- バージョン、フォーマット、クラス、場所、オブジェクト名を定義。 - 取得したデータ行を追記モードで出力
各行に以下の項目を書き出す
-Time(時刻)
-mout(質量流量)
-Tout(出口温度)
-heatFlowSensor.Q_flow(熱流量)
-TSensor(センサー温度)
-ramp.y(ターゲット温度)
OpenModelicaではOpenFOAMで計算したTSensorがOpenModelicaでしているターゲット温度波形(ramp.y:下図一番左オレンジ線)になるようにPID制御を行っています。
この記述をupdateMOS_and_Run.py内で行っているというのが重要なところで、TinletとTSensorはOpenFOAMでの結果で得られた値になります。
つまり、OpenFOAMにとってのoutletの温度$\overline{T} = \frac{\sum_i \rho v_iA_i C_p T_i}{\sum_i \rho v_iA_i C_p }= \frac{\sum_i \rho Q_i C_p T_i}{\sum_i \rho Q_i C_p }$はOpenModelicaではTinletとしてインプットされているということです。
constant/boundarySyncFileに結果を出力します。
constant/boundarySyncFile
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
FoamFile { version 2.0; format ascii; class dictionary; location constant; object boundarySyncFile; } Time 300; mout 11.49; Tout 313.033; heatFlowSensor.Q_flow 231793; TSensor 310; ramp.y 328; |
今度はOpenFOAMがこのファイルを読み込み境界名inletに与えれることになります。
runMos.sh
そしてrunMos.shによりHVACSystem002.mosを実行されるとOpenModelicaの計算が進みます。
runMos.sh
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#!/bin/bash # 使用方法: ./run_OM.sh Tank002.mos # ./run_OM.sh HVACSystem001.mos MOSFILE=$1 # 引数チェック if [ -z "$MOSFILE" ]; then echo "使用方法: $0 <mosファイル名>" exit 1 fi # 現在のディレクトリを基準に対象ファイルを指定 CURRENT_PATH=$(pwd) TARGET_PATH="$CURRENT_PATH/$MOSFILE" # 出力先ディレクトリ WORK_DIR="/tmp/OpenModelica" # フォルダがなければ作成 mkdir -p "$WORK_DIR" # ディレクトリ移動と実行 cd "$WORK_DIR" || { echo "ディレクトリ移動に失敗しました"; exit 1; } omc "$TARGET_PATH" |




