こんにちは(@t_kun_kamakiri)
本記事ではOpenFOAMを用いた熱流体解析の設定手順について解説を行います。
具体的には自然対流下でのマネキン周りの熱量を計算し、対流熱伝達と熱ふく射における影響度を調べることを目的とします。
今回はマネキン周りのメッシュ作成をsnappyHexMeshを用いて作成する方法を紹介します。
- OpenFOAMを用いて流体解析を勉強している人
- OpenFOAMで熱流体解析(ふく射込み)を試したい人
フォルダ構成は以下のようにしています。
1 2 3 4 5 |
kamakiri$ tree -L 1 . ├── cfMesh ├── model └── shm |
まずはsnappyHexMeshでのメッシュ作成用のフォルダに移動します。
1 |
cd shm |
OpenFOAM v2412(WSL Ubuntu 22.04)
モデルのコピー
まずはモデルを一式コピーします。
※モデルは前回記事で作成しているテストケースを使用します。
1 |
cp -r ../model/* . |
作業はshm
フォルダで行います。
FreeCADで外部領域のモデルを作成
FreeCADはこちらより最新版(2025/2/28時点 FreeCAD 1.0.0)をダウンロードします。
ダウンロードが終了したら早速モデルを作成していきます。
モデルの大きさは論文を参考に作成します。まずはFreeCADでBoxを作成します。
座標軸が論文と異なるので注意が必要です。
Boxの位置がおかしいのでPlacement
で、論文で示されている位置と同じになるようにだいたいの位置で合わせます。
OpenFOAMは境界条件の際に境界面に名前を付けておく必要があるため、以下のように面を分割して名前を付けます。
では外部領域の出力を行います。
作成した面を一括でstlとして出力するマクロは以下の記事に解説とプログラムがありますので、ご活用ください。
作成したのはFreeCAD 0.20.2でしたがFreeCAD 1.0.0内臓のPythonプログラムは無事動くようです。
👇こんな感じで分割した面を一括でまとめて出力できるので便利です。
出力した外部領域モデルとマネキンモデルを合わせてParaViewで確認しておきます。
サイズ感などは問題なさそうですね。
メッシュ作成
snappyHexMeshとsurfaceMeshExtractの設定用のファイルがないので適当なチュートリアルからコピーしてきます。
ついでにmeshQualityDictもコピーしています(snappyHexMeshで設定されているため)。
1 2 3 |
cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike/system/snappyHexMeshDict system/ cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike/system/surfaceMeshExtractDict system/ cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike/system/meshQualityDict system/ |
$FOAM_TUTORIALS=/usr/lib/openfoam/openfoam2412/tutorials/
snappyHexMeshで設定するモデルはconstant/triSurfaceフォルダに保存しておく必要があります。
1 2 |
mkdir constant/triSurface cp -r model/*.stl constant/triSurface/ |
blockMeshでベースメッシュ作成
snappyHexMeshを用いたメッシュ作成にはベースメッシュが必要です。
そのベースメッシュはblockMeshで行います。
snappyHexMeshは以下の図の流れでメッシュ作成を行っています。
blockMeshは外部モデル領域を覆うように少し大きめ(+0.02m)で設定します。
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 |
scale 1; vertices ( (0.88 -0.02 0.20) //0 (2.12 -0.02 0.20) //1 (2.12 2.68 0.20) //2 (0.88 2.68 0.20) //3 (0.88 -0.02 2.68) //4 (2.12 -0.02 2.68) //5 (2.12 2.68 2.68) //6 (0.88 2.68 2.68) //7 ); blocks ( hex (0 1 2 3 4 5 6 7) (13 24 33) simpleGrading (1 1 1) ); edges ( ); defaultPatch { type patch; } boundary (); mergePatchPairs ( ); |
以下のコマンドでメッシュ作成を行います。
1 |
blockMesh |
できたメッシュをParaViewで確認しておきます。
ベースメッシュとして問題がないか確認します。
surfaceMeshExtractで特徴線の作成
まずはsurfaceMeshExtractを用いて特徴線を作成します。
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 |
model.stl { // How to obtain raw features (extractFromFile || extractFromSurface) extractionMethod extractFromSurface; // Mark edges whose adjacent surface normals are at an angle less // than includedAngle as features // - 0 : selects no edges // - 180: selects all edges includedAngle 150; subsetFeatures { // Keep nonManifold edges (edges with >2 connected faces) nonManifoldEdges no; // Keep open edges (edges with 1 connected face) openEdges yes; } // Write options // Write features to obj format for postprocessing writeObj yes; } |
以下のコマンドを実行するとconstant/triSurface
フォルダにmodel.eMesh
が作成されます。
1 |
surfaceFeatureExtract |
vm_sitaf.eMesh
はsnappyHexMeshでの特徴線まわりのメッシュ再分割に使用します。
※.eMeshはParaViewでは読み込めないため.obj形式に変換するとParaViewで表示することができます。変換のコマンドは以下です。
1 |
surfaceFeatureConvert constant/triSurface/model.eMesh constant/triSurface/model.obj |
snappyHexMeshでメッシュ作成
続いてsnappyHexMeshの設定を行います。
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
/*--------------------------------*- C++ -*----------------------------------*\ | ========= | | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / O peration | Version: v2412 | | \\ / A nd | Website: www.openfoam.com | | \\/ M anipulation | | \*---------------------------------------------------------------------------*/ FoamFile { version 2.0; format ascii; class dictionary; object snappyHexMeshDict; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Which of the steps to run castellatedMesh true; snap true; addLayers true; // Geometry. Definition of all surfaces. All surfaces are of class // searchableSurface. // Surfaces are used // - to specify refinement for any mesh cell intersecting it // - to specify refinement for any mesh cell inside/outside/near // - to 'snap' the mesh boundary to the surface geometry { model.stl { type triSurfaceMesh; name model; regions { XMax { name XMax; } XMin { name XMin; } YMax { name YMax; } YMin { name YMin; } ZMax { name ZMax; } ZMin { name ZMin; } } } vm_sitaf.stl { type triSurfaceMesh; name vm_sitaf; /* unspecified-24 mouth-23 pelvis-12 hand-left-17 nose-right-9 shoulder-left-16 nose-left-18 shoulder-right-5 thigh-right-11 leg-right-13 arm-right-4 foot-right-14 arm-left-15 chest-8 neck-22 thigh-left-19 face-10 back-7 leg-left-20 hand-right-6 foot-left-21 */ regions { unspecified-24 { name unspecified-24; } mouth-23 { name mouth-23; } pelvis-12 { name pelvis-12; } hand-left-17 { name hand-left-17; } nose-right-9 { name nose-right-9; } shoulder-left-16 { name shoulder-left-16; } nose-left-18 { name nose-left-18; } shoulder-right-5 { name shoulder-right-5; } thigh-right-11 { name thigh-right-11; } leg-right-13 { name leg-right-13; } arm-right-4 { name arm-right-4; } foot-right-14 { name foot-right-14; } arm-left-15 { name arm-left-15; } chest-8 { name chest-8; } neck-22 { name neck-22; } thigh-left-19 { name thigh-left-19; } face-10 { name face-10; } back-7 { name back-7; } leg-left-20 { name leg-left-20; } hand-right-6 { name hand-right-6; } foot-left-21 { name foot-left-21; } } } // refinementBox // { // type box; // min (-1.0 -0.7 0.0); // max ( 8.0 0.7 2.5); // } } // Settings for the castellatedMesh generation. castellatedMeshControls { maxLocalCells 100000; maxGlobalCells 2000000; minRefinementCells 10; maxLoadUnbalance 0.10; nCellsBetweenLevels 3; features ( { file "model.eMesh"; level 2; } ); refinementSurfaces { model { level (0 0); regions { XMax { level (0 0); patchInfo { type wall; } } XMin { level (0 0); patchInfo { type wall; } } YMax { level (0 0); patchInfo { type wall; } } YMin { level (0 0); patchInfo { type wall; } } ZMax { level (0 0); patchInfo { type patch; } } ZMin { level (0 0); patchInfo { type patch; } } } } // "(.*-[0-9]+$|Ymin)" vm_sitaf { // Surface-wise min and max refinement level level (2 4); patchInfo { type wall; } // Optional specification of patch type (default is wall). No // constraint types (cyclic, symmetry) etc. are allowed. // regions // { // test // { // level (2 4); // patchInfo // { // type patch; // } // } } } resolveFeatureAngle 30; refinementRegions { // refinementBox // { // mode inside; // levels ((1E15 2)); // } } locationInMesh (1.5 1 1); allowFreeStandingZoneFaces true; } // Settings for the snapping. snapControls { nSmoothPatch 3; tolerance 2.0; nSolveIter 30; nRelaxIter 5; nFeatureSnapIter 10; implicitFeatureSnap false; explicitFeatureSnap true; multiRegionFeatureSnap false; } // Settings for the layer addition. addLayersControls { // Are the thickness parameters below relative to the undistorted // size of the refined cell outside layer (true) or absolute sizes (false). relativeSizes true; // Per final patch (so not geometry!) the layer information layers { ".*-[0-9]+$" { nSurfaceLayers 3; } } expansionRatio 1.2; finalLayerThickness 0.6; minThickness 0.3; nGrow 0; featureAngle 60; slipFeatureAngle 30; nRelaxIter 3; nSmoothSurfaceNormals 1; nSmoothNormals 3; nSmoothThickness 10; maxFaceThicknessRatio 0.5; maxThicknessToMedialRatio 0.3; minMedialAxisAngle 90; nBufferCellsNoExtrude 0; nLayerIter 50; } // Generic mesh quality settings. At any undoable phase these determine // where to undo. meshQualityControls { #include "meshQualityDict" // Advanced //- Number of error distribution iterations nSmoothScale 4; //- Amount to scale back displacement at error points errorReduction 0.75; } // Advanced // Write flags writeFlags ( scalarLevels layerSets layerFields // write volScalarField for layer coverage ); mergeTolerance 1e-6; // ************************************************************************* // |
注意すべき点はlocationInMesh (1.5 1 1);
がちゃんと作成したいメッシュ領域にあるかどうか確認してください。これはどの閉じた領域のメッシュを作成するかを指定するものです。
例えば、ParaViewで表示して間違いがないかを確認しています。
snappyHexMeshを実行します。
実行の際は-overwriteオプションを付けています。
1 |
snappyHexMesh -overwrite |
snappyHexMeshはメッシュを3段階に分けてメッシュ作成していますが、このオプションを付けない場合は途中経過も保存されていきます。途中経過は不要なときは、このオプションを付けておくと上書き保存でメッシュ作成されていきます。
では、ParaViewでメッシュ状態を確認してみましょう。
snappyHexMeshはメッシュ再分割(細分割)した部分の境界層がうまく入らないことがありますが、ひとまずメッシュ作成は完了とします。
まとめ
本記事ではOpenFOAMを用いた熱流体解析の準備としてマネキンモデルまわりのメッシュ作成を行いました。今回はOpenCFD版のsnappyHexMeshを使用していますが、次回紹介するcfMeshの方が境界層がきれいに入ったりします。
次回は、cfMeshを用いたメッシュ作成を行います。
計算力学技術者のための問題アプリ
計算力学技術者熱流体2級、1級対策アプリをリリースしました。
- 下記をクリックしてホームページでダウンロードできます。
- LINE公式に登録すると無料で問題の一部を閲覧できます。
※LINEの仕様で数式がずれていますが、アプリでは問題ありません。
- 計算力学技術者の熱流体2級問題アプリ作成
リリース後も試行錯誤をしながら改善に努め日々アップデートしています。
備忘録として作成の過程を綴っています。
OpenFOAMに関する技術書を販売中!
OpenFOAMを自宅で学べるシリーズを販売中です。
OpenFOAM初学者から中級者向けの技術書となっていますので、ぜひよろしくお願いいたします。
次回の技術書典18に向けて内容を考え中です。
乞うご期待!!
お勧めの参考書
本記事の内容について触れている書籍がこちらです。
CFD(流体解析)のガイドブックというタイトルだけあって、熱流体に関する内容は網羅的に書かれています。
乱流モデルの数式の展開が非常に丁寧なのはこちらの参考書です。
今まで読んだ本の中で途中式もしっかり書いてあって一番丁寧でした。
乱流モデルの話だけでなく、混相流(気液、固液)や粒子法、浅水方程式の話も乗っているので重宝しています。
乱流モデルはこちらもお勧めです。
前半は数値シミュレーションの離散化の話で、後半に乱流モデルの話が出てきます。
乱流モデルのざっくりした解説と流体全般の基礎知識にはこちらがちょうど良いでしょう。