ファイルから境界の値を読み込む
0/Uと0/Tの全文を載せときます。
- 0/UのinletにOpenModelicaで計算した質量流moutを設定
- 0/TのinletにOpenModelicaで計算したToutを設定
0/U
|
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 |
#include "<case>/constant/inletTempFile"; dimensions [0 1 -1 0 0 0 0]; internalField uniform (0 0 0); boundaryField { floor { type noSlip; } ceiling { type noSlip; } fixedWalls { type noSlip; } inlet { // type fixedValue; // value uniform (0 0 -1.0); type codedFixedValue; name pythonSyncFixedValue; value uniform (0 0 $mout); code #{ // pythonSyncファイルをobjectRegistryへ登録(初回のみ) if(!db().foundObject<IOdictionary>("boundarySyncFile")) { autoPtr<IOdictionary> pythonSyncPtr ( new IOdictionary ( IOobject ( "boundarySyncFile", db().time().constant(), db(), IOobject::MUST_READ, IOobject::NO_WRITE ) ) ); db().store<IOdictionary>(pythonSyncPtr); } // objectRegistry上のpythonSyncを呼び出す IOdictionary& pythonSync = db().lookupObjectRef<IOdictionary>("boundarySyncFile"); // 内容の更新 pythonSync.regIOobject::read(); // pythonSyncファイルからUColdSyncの値を取得 const scalar& moutSync= pythonSync.get<scalar>("mout"); // fixedValueの値を渡す operator==(vector(0, moutSync, 0)); #}; // 元の設定 // { // type coupledFlowRateInletVelocity; // mFlowInit 1e-8; // massFlowRate mdotin; // uniform (0 0 0); // } outlet { type pressureInletOutletVelocity; value uniform (0 0 0); } } |
今気づいたけど本当は質量流moutを設定したいのに、上記の記述だと流速の設定になってしまっている?気がします(見直して後日修正します)
0/T
|
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 85 86 87 88 89 |
#include "<case>/constant/inletTempFile"; dimensions [0 0 0 1 0 0 0]; internalField uniform 293; boundaryField { ceiling { type externalWallHeatFluxTemperature; value uniform 293; kappaMethod fluidThermo; mode coefficient; h 10; Ta 273; // its cold its winter } floor { type externalWallHeatFluxTemperature; value uniform 293; kappaMethod fluidThermo; mode coefficient; h 10; Ta 293; // neighboor appartment } fixedWalls { type externalWallHeatFluxTemperature; value uniform 293; kappaMethod fluidThermo; mode coefficient; h 10; Ta 273; // its cold its winter } inlet { // type fixedValue; // value uniform 303.15; //流入温度(30deg.) type codedFixedValue; name pythonSyncFixedValue; value uniform $Tout; code #{ // pythonSyncファイルをobjectRegistryへ登録(初回のみ) if(!db().foundObject<IOdictionary>("boundarySyncFile")) { autoPtr<IOdictionary> pythonSyncPtr ( new IOdictionary ( IOobject ( "boundarySyncFile", db().time().constant(), db(), IOobject::MUST_READ, IOobject::NO_WRITE ) ) ); db().store<IOdictionary>(pythonSyncPtr); } // objectRegistry上のpythonSyncを呼び出す IOdictionary& pythonSync = db().lookupObjectRef<IOdictionary>("boundarySyncFile"); // 内容の更新 pythonSync.regIOobject::read(); // pythonSyncファイルからUColdSyncの値を取得 const scalar& ToutSync = pythonSync.get<scalar>("Tout"); // fixedValueの値を渡す operator==(ToutSync); #}; } // { // type coupledUniformExternalValue; // inputName Tin; // value uniform 350; // initValue 293; // } outlet { type zeroGradient; } } |
consant/boundarySyncFileファイルに記述されたmoutとToutを計算毎に読み込む記述が書かれています。
あまり重要ではないですが初期条件は#include "<case>/constant/inletTempFile";として別ファイルにしています。
constant/inletTempFile
|
1 2 3 4 5 6 7 8 9 10 11 12 |
FoamFile { version 2.0; format ascii; class dictionary; location constant; object inletTempFile; } mout 0; Tout 293.15 Time 0.0; |
output.dat
output.datはupdateMOS_and_Run.pyの中に書かれたOpenModelicaの結果ファイルです。以下のように書き出されます。
output.dat
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Time mout Tout heatFlowSensor.Q_flow TSensor ramp.y 0.00012 5.74507 293.164 244893 293 298 0.000264002 5.74515 293.181 244878 293 298 0.000436804 5.74525 293.201 244860 293 298 0.000644169 5.74537 293.225 244838 293 298 0.000893009 5.74551 293.254 244811 293 298 0.00119161 5.74568 293.289 244779 293 298 0.00154994 5.74589 293.331 244741 293 298 0.00197993 5.74614 293.381 244696 293 298 0.0024959 5.74643 293.441 244641 293 298 0.00311506 5.74679 293.514 244575 293 298 0.00385804 5.74722 293.6 244497 293 298 0.0047496 5.74773 293.704 244402 293 298 0.00581941 5.74834 293.829 244288 293 298 ...(省略)... |
output.datの出力はupdateMOS_and_Run.pyからimportしているsync_to_table.pyに書かれています。
sync_to_table.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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# /mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom/sync_to_table.py from pathlib import Path from typing import Dict, List, Tuple def _strip_semicolon(s: str) -> str: return s[:-1] if s.endswith(";") else s def parse_boundary_sync(sync_path: Path) -> Dict[str, float]: """ constant/boundarySyncFile を読み込み、{key: value} を返す。 FoamFile ブロックを無視し、 'Key Value;' 形式に対応。 """ vals: Dict[str, float] = {} in_foam_block = False with sync_path.open(encoding="utf-8") as f: for raw in f: line = raw.strip() if not line: continue if line.startswith("FoamFile"): in_foam_block = True continue if in_foam_block: if "}" in line: in_foam_block = False continue line = _strip_semicolon(line) parts = line.split() if len(parts) < 2: continue key, val_str = parts[0], parts[1] try: val: float | str = float(val_str) except ValueError: val = val_str vals[key] = val return vals def _fmt(v): if isinstance(v, (float, int)): return f"{v:g}" return "" if v is None else str(v) def _read_existing_header(path: Path, sep: str) -> List[str] | None: if not path.exists() or path.stat().st_size == 0: return None with path.open("r", encoding="utf-8") as f: first = f.readline().rstrip("\n") return first.split(sep) def _append_missing_columns_in_file(path: Path, sep: str, existing: List[str], target: List[str]) -> None: """ 既存ヘッダ existing に対し、target にあるが existing に無い列を末尾追加。 既存データ行には空欄を付加して列数を合わせる。 """ missing = [c for c in target if c not in existing] if not missing: return new_header = existing + missing # 全行を読み込み with path.open("r", encoding="utf-8") as f: lines = f.readlines() # 先頭行を新ヘッダへ lines[0] = sep.join(new_header) + "\n" # データ行を末尾に空欄を追加 for i in range(1, len(lines)): lines[i] = lines[i].rstrip("\n") + (sep + sep.join([""] * len(missing)) if missing else "") + "\n" with path.open("w", encoding="utf-8") as f: f.writelines(lines) def _ensure_header(out_path: Path, headers: List[str], sep: str) -> List[str]: """ output.dat のヘッダ整合性を保証: - ファイルが無ければ headers を書く - あれば既存ヘッダを読み、不足列を末尾に追加して既存行を補完 - 返り値: 実際のヘッダ(既存+不足列) """ existing = _read_existing_header(out_path, sep) if existing is None: out_path.write_text(sep.join(headers) + "\n", encoding="utf-8") return headers # 既存に不足があれば追加 _append_missing_columns_in_file(out_path, sep, existing, headers) return _read_existing_header(out_path, sep) or headers def append_output_row( base_dir: Path, vals: Dict[str, float], headers: List[str] | None = None, out_name: str = "output.dat", sep: str = "\t", ) -> Tuple[Path, str]: """ vals を out_name に追記。列は headers の順序で出力。 既存ファイルがあれば自動的に不足列を追加し整合させる。 """ if headers is None: headers = ["Time", "mout", "Tout", "pipe.Q_flow"] out_path = base_dir / out_name actual_headers = _ensure_header(out_path, headers, sep) row_vals = [_fmt(vals.get(h, None)) for h in actual_headers] row = sep.join(row_vals) with out_path.open("a", encoding="utf-8") as g: g.write(row + "\n") return out_path, row # ===== 使用例 ===== if __name__ == "__main__": base = Path("/mnt/d/work/openfoam/20251017_OpenCAE2025/heatedRoom") sync_file = base / "constant/boundarySyncFile" vals = parse_boundary_sync(sync_file) # ここで列が増えても OK(自動で不足列を追加し、既存行は空欄で補完) out_path, row = append_output_row( base, vals, headers=["Time","mout","Tout","pipe.Q_flow","TSensor","TTarget"], sep="\t" ) print(f"[INFO] Appended to {out_path}: {row}") |
難しいことはAIに書いてもらうなどしてサポートしてもらえればOK。
注意
- HVACSystem002.mosによる冒頭の2行をコメントアウト外して./runMos.shを実行しておく必要があります。
|
1 2 3 4 5 6 |
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"); ...(省略)... |
コンパイルは./runMos.sh HVACSystem002.mosで行います。
一度OpenModelicaのHVACSystem001.moをコンパイルする必要があるからです。
毎回コンパイルする必要はなく、1度だけで構わないため、計算毎に既にコンパイル済の実行ファイルを使うためコメントアウトしていました。
- constant/boundarySyncFileがないとエラーになる。
初期で0/U, 0/Tがこのファイルを読むため、ファイルがなかったり何も記述されていない場合はエラーになります。
計算毎に更新するため計算を止めたりするとタイミングがわるいと空ファイルになることがあるため、必ず以下のようにヘッダーも含めて書いておく必要があります。
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; |



