こんにちは(@t_kun_kamakiri)
本記事ではOpenFOAMのメッシュ生成ユーティリティであるblockMeshを使って円柱のメッシュを6面体で生成したいと思います。
最終的には以下のようになります。
【使用環境】
OpenFOAM-v2012(WSL2)
チュートリアルをコピーする
以下のコマンドでチュートリアルをコピーします。
1 |
cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/pitzDaily Cylinder_blockMesh |
ちなみに「$FOAM_TUTORIALS」は環境変数が割り当てられており、以下のコマンドで確認することができます。
1 |
echo $FOAM_TUTORIALS |
環境変数「FOAM_TUTORIALS = /opt/OpenFOAM/OpenFOAM-v2012/tutorials」であることが確認できます。
blockMeshを編集
コピーしたフォルダに移動してメッシュを作ります。
1 |
cd Cylinder_blockMesh |
ファイル構成を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
. ├── 0 │ ├── U │ ├── epsilon │ ├── k │ ├── nuTilda │ ├── nut │ ├── omega │ └── p ├── constant │ ├── transportProperties │ └── turbulenceProperties └── system ├── blockMeshDict ├── controlDict ├── fvSchemes ├── fvSolution └── streamlines |
メッシュ生成用のファイルであるblockMeshの設定は「system/blockMeshDict」で行います。blockMeshDictを以下のように編集します。
長さ12000mm、半径10mmの円柱にしています。
作成のイメージはこんな感じ。
system/blockMeshDict
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 |
/*--------------------------------*- C++ -*----------------------------------*\ | ========= | | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / O peration | Version: v2012 | | \\ / A nd | Website: www.openfoam.com | | \\/ M anipulation | | \*---------------------------------------------------------------------------*/ FoamFile { version 2.0; format ascii; class dictionary; object blockMeshDict; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // scale 0.001; // Divisions in x/y/z directions. Can be unequal. nx 15; ny 15; nz 100; // radius r 10; pi 3.1415926; theta0 0.0; theta45 45.0; theta90 90.0; theta135 135.0; theta180 180.0; theta225 225.0; theta270 270.0; theta315 315.0; ratio 2.5; ratioMid 0.75; Xin1 #calc "$r/$ratio * cos($theta45 * $pi /180)"; Yin1 #calc "$r/$ratio * sin($theta45 * $pi /180)"; Xin2 #calc "$r/$ratio * cos($theta135 * $pi /180)"; Yin2 #calc "$r/$ratio * sin($theta135 * $pi /180)"; Xin3 #calc "$r/$ratio * cos($theta225 * $pi /180)"; Yin3 #calc "$r/$ratio * sin($theta225 * $pi /180)"; Xin4 #calc "$r/$ratio * cos($theta315 * $pi /180)"; Yin4 #calc "$r/$ratio * sin($theta315 * $pi /180)"; Xout1 #calc "$r * cos($theta45 * $pi /180)"; Yout1 #calc "$r * sin($theta45 * $pi /180)"; Xout2 #calc "$r * cos($theta135 * $pi /180)"; Yout2 #calc "$r * sin($theta135 * $pi /180)"; Xout3 #calc "$r * cos($theta225 * $pi /180)"; Yout3 #calc "$r * sin($theta225 * $pi /180)"; Xout4 #calc "$r * cos($theta315 * $pi /180)"; Yout4 #calc "$r * sin($theta315 * $pi /180)"; InYmin #calc "$r/$ratio*$ratioMid * sin($theta270 * $pi /180)"; InXmax #calc "$r/$ratio*$ratioMid * cos($theta0 * $pi /180)"; InYmax #calc "$r/$ratio*$ratioMid * sin($theta90 * $pi /180)"; InXmin #calc "$r/$ratio*$ratioMid * cos($theta180 * $pi /180)"; OutYmin #calc "$r * sin($theta270 * $pi /180)"; OutXmax #calc "$r * cos($theta0 * $pi /180)"; OutYmax #calc "$r * sin($theta90 * $pi /180)"; OutXmin #calc "$r * cos($theta180 * $pi /180)"; Zmin 0.0; Zmax 1200; geometry { } vertices ( //circle radius in ($Xin3 $Yin3 $Zmin) //0 ($Xin4 $Yin4 $Zmin) //1 ($Xin1 $Yin1 $Zmin) //2 ($Xin2 $Yin2 $Zmin) //3 //circle radius out ($Xout3 $Yout3 $Zmin) //4 ($Xout4 $Yout4 $Zmin) //5 ($Xout1 $Yout1 $Zmin) //6 ($Xout2 $Yout2 $Zmin) //7 //circle radius in ($Xin3 $Yin3 $Zmax) //8 ($Xin4 $Yin4 $Zmax) //9 ($Xin1 $Yin1 $Zmax) //10 ($Xin2 $Yin2 $Zmax) //11 //circle radius out ($Xout3 $Yout3 $Zmax) //12 ($Xout4 $Yout4 $Zmax) //13 ($Xout1 $Yout1 $Zmax) //14 ($Xout2 $Yout2 $Zmax) //15 ); blocks ( hex (0 1 2 3 8 9 10 11) ($nx $ny $nz) grading (1 1 1) //center(block0) hex (1 0 4 5 9 8 12 13) ($nx $ny $nz) grading (1 1 1) //Ymin(block1) hex (2 1 5 6 10 9 13 14) ($nx $ny $nz) grading (1 1 1) //Xmax(block2) hex (3 2 6 7 11 10 14 15) ($nx $ny $nz) grading (1 1 1) //Ymax(block3) hex (0 3 7 4 8 11 15 12) ($nx $ny $nz) grading (1 1 1) // Xmin(block4) ); edges ( //circle radius out arc 4 5 (0 $OutYmin $Zmin) arc 5 6 ($OutXmax 0 $Zmin) arc 6 7 (0 $OutYmax $Zmin) arc 7 4 ($OutXmin 0 $Zmin) arc 12 13 (0 $OutYmin $Zmax) arc 13 14 ($OutXmax 0 $Zmax) arc 14 15 (0 $OutYmax $Zmax) arc 15 12 ($OutXmin 0 $Zmax) //circle radius in arc 0 1 (0 $InYmin $Zmin) arc 1 2 ($InXmax 0 $Zmin) arc 2 3 (0 $InYmax $Zmin) arc 3 0 ($InXmin 0 $Zmin) arc 8 9 (0 $InYmin $Zmax) arc 9 10 ($InXmax 0 $Zmax) arc 10 11 (0 $InYmax $Zmax) arc 11 8 ($InXmin 0 $Zmax) ); faces ( ); boundary ( walls { type wall; faces ( (5 13 14 6) (6 14 15 7) (7 15 12 4) (4 12 13 5) ); } inlet { type patch; faces ( (0 1 2 3) (0 4 5 1) (1 5 6 2) (2 6 7 3) (7 4 0 3) ); } outlet { type patch; faces ( (8 9 10 11) (8 12 13 9) (9 13 14 10) (10 14 15 11) (11 15 12 8) ); } ); // ************************************************************************* // |
設定が終わったらblockMeshを実行しましょう。
1 |
blockMesh |
blockMeshDictには変数設定をしているため、コンパイルが必要になりメッシュ生成に少々時間がかかります。ただし、変数の値を変えると再度コンパイルされますが、変数部分以外を変更したとしても再度コンパイルすることはないので時間はかかりません。
※追記
2023年現在はblockMeshも進化しているようです。
ParaViewで確認
OpenFOAMでは拡張子「.foam」という空ファイルを読み込むだけで結果を確認できます。
1 |
touch post.foam |
ParaViewを起動してメッシュを確認しましょう。
断面を切っても全てのメッシュが6面台であることがわかります。
メッシュ品質も確認しておきましょう。
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 |
Mesh stats points: 116756 faces: 341625 internal faces: 333375 cells: 112500 faces per cell: 6 boundary patches: 3 point zones: 0 face zones: 0 cell zones: 0 Overall number of cells of each type: hexahedra: 112500 prisms: 0 wedges: 0 pyramids: 0 tet wedges: 0 tetrahedra: 0 polyhedra: 0 Checking topology... Boundary definition OK. Cell to face addressing OK. Point usage OK. Upper triangular ordering OK. Face vertices OK. Number of regions: 1 (OK). Checking patch topology for multiply connected surfaces... Patch Faces Points Surface topology walls 6000 6060 ok (non-closed singly connected) inlet 1125 1156 ok (non-closed singly connected) outlet 1125 1156 ok (non-closed singly connected) Checking faceZone topology for multiply connected surfaces... No faceZones found. Checking basic cellZone addressing... No cellZones found. Checking geometry... Overall domain bounding box (-0.0099863 -0.0099863 0) (0.0099863 0.0099863 0.5) Mesh has 3 geometric (non-empty/wedge) directions (1 1 1) Mesh has 3 solution (non-empty) directions (1 1 1) Boundary openness (1.47567e-15 -1.58517e-16 -6.94208e-18) OK. Max cell openness = 2.52357e-16 OK. Max aspect ratio = 24.2143 OK. Minimum face area = 1.35967e-07. Maximum face area = 5.2336e-06. Face area magnitudes OK. Min volume = 6.79837e-10. Max volume = 2.38592e-09. Total volume = 0.000156793. Cell volumes OK. Mesh non-orthogonality Max: 29.347 average: 5.99634 Non-orthogonality check OK. Face pyramids OK. Max skewness = 0.55946 OK. Coupled point location match (average 0) OK. Mesh OK. End |
以下の部分は最低確認するようにしましょう。
- Max aspect ratio:アスペクト比(縦横の比率)→境界層で大きくなりやすいので大きすぎる場合は確認
- non-orthogonality:直交性→70°以上であれば修正
- Max skewness:歪度→4以上だと修正
メッシュ品質の基準は以下のファイルにも記載がありますで確認してみましょう。
1 |
$WM_PROJECT_DIR/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/ |
コマンドでファイルを探す場合は、
1 |
find $FOAM_SRC -name "primitiveMeshCheck*" |
以下のように出力されます。
1 2 3 4 5 6 7 |
/opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/lnInclude/primitiveMeshCheckEdgeLength.C /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/lnInclude/primitiveMeshCheckPointNearness.C /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/lnInclude/primitiveMeshCheck.C /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheckEdgeLength.C /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheckPointNearness.C /opt/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C |
primitiveMeshCheck.Cの中身を確認しましょう。
1 |
vi $FOAM_SRC/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C |
該当箇所は「/primitiveMesh」と打って「n(下へ)」「shift + n(上へ)」で探すことができます。
viを終了するには
ESCボタンを押して「:q」か「:q!」で終了することができます。
1 2 3 4 5 |
Foam::scalar Foam::primitiveMesh::closedThreshold_ = 1.0e-6; Foam::scalar Foam::primitiveMesh::aspectThreshold_ = 1000; Foam::scalar Foam::primitiveMesh::nonOrthThreshold_ = 70; // deg Foam::scalar Foam::primitiveMesh::skewThreshold_ = 4; Foam::scalar Foam::primitiveMesh::planarCosAngle_ = 1.0e-6; |
シミュレーションを行う場合、低品質なセルや面によって生じる数値誤差を低減できる数値スキームを選択します。
おすすめ参考図書
☟こちらは、OpenFOAMの日本語書籍が無い中唯一わかりやすい参考書だと思います。
☟こちらもOpenFOMの古いバージョンでの和訳になります。さすがにこちらはバージョンに対する日本語でのケアはしていないので、OpenFOAMに慣れている方は購入しても良いかと思います。僕は「日本語でまとまっている内容」なので少し重宝しています。
☟以下に、もっと初心者向けの同人誌を紹介しておきます。
初心者は「ってか、まずどうやってOpenFOAMをインストールするの?」というところからつまずきがちです。
そんな時は、以下の書籍をおすすめします。
インストール方法とチュートリアルで流体解析を体験・・・ちょっと高度な解析まで解説があります。著者曰くOpenFOAMのバージョンの追跡を行いながら、書籍をアップデートするようなので安心ですね。