snappyHexMesh によるメッシュの作成

2019年1月26日

はじめに

snappyHexMesh によるメッシュの作成について。

使用バージョン

OpenFOAM 6

ファイル

形状

snappyHexMesh によるメッシュの作成

snappyHexMesh は、OpenFOAM の標準ユーティリティに含まれるもので、構造格子状のメッシュを形状に適合させることでメッシュを構成する。STL などの形状ファイルから、ほぼ六面体セルによるメッシュを半自動的に作成することができる。

ベースとなるメッシュは blockMesh で作成する。snappyHexMesh の設定は system/snappyHexMeshDict で行うが、かなり大規模な設定ファイルになるので、チュートリアルケースからコピーしたものを修正したほうがよい (たとえば、simpleFoam の motorBike のケースに含まれる)。

STL などの形状ファイルは constant/triSurface に入れておく。形状ファイルとしては、STL ファイルのほか OBJ ファイルや VTK ファイルも使える。

snappyHexMesh のしくみ

snappyHexMesh はつぎのような手順でメッシュを作成する。実際は 3 次元だが、説明のため 2 次元の図で示す。

  1. STL などのサーフェイスを用意する。
  2. blockMesh でベースとなるメッシュを作成する。ここまで手動。
  3. ここからは snappyHexMesh 内の動き。境界近傍を六面体で細分化する。一部分だけ実施したのが以下の図。
    これをサーフェイス全体に対して行う。
  4. 領域外になる部分のセルを取り除く。ここまでを "castellate" (お城のようにする、スーパーマリオに出てくるみたいな) と呼ぶ。
  5. 領域外に飛び出た部分をサーフェイスに合わせる ("snap")。
  6. 必要があれば境界層メッシュを挿入する。

準備

ここではミキシングエルボーモデルの例を示しながら、snappyHexMesh によるメッシュの作成について説明する。

チュートリアルケースの motorBike ディレクトリをコピーする。

$ cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike mixing_elbow

このケースには今回必要な設定ファイルが含まれている。

形状ファイルを配置する。

$ mv mixing_elbow.stl mixing_elbow/constant/triSurface

ベースとなるメッシュを作成するために、ParaView (paraFoam ではない) で形状ファイルを読み込み、"Object Inspector" の "Information" タブにある "Bounds" でモデルの範囲を調べておく。あるいは、範囲を調べるだけならユーティリティの surfaceCheck を用いてもよい。

$ surfaceCheck mixing_elbow.stl

Reading surface from "mixing_elbow.stl" ...

Statistics:
Triangles    : 6522
Vertices     : 3263
Bounding Box : (0 -0.005 -0.00914214) (0.05 0.005 0.045)

設定とメッシュの作成

blockMesh

blockMesh でモデル全体を囲む大きさの直方体を作る。モデルの範囲よりも少し広めにする。

system/blockMeshDict

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}

convertToMeters 1;

minx -0.001;
maxx  0.051;
miny -0.006;
maxy  0.006;
minz -0.010;
maxz  0.046;

nx 50;
ny 10;
nz 55;

vertices
(
    ($minx $miny $minz)
    ($maxx $miny $minz)
    ($maxx $maxy $minz)
    ($minx $maxy $minz)
    ($minx $miny $maxz)
    ($maxx $miny $maxz)
    ($maxx $maxy $maxz)
    ($minx $maxy $maxz)
);

blocks
(
    hex (0 1 2 3 4 5 6 7) ($nx $ny $nz) simpleGrading (1 1 1)
);

edges
(
);

boundary
(
    minX
    {
        type patch;
        faces
        (
            (0 4 7 3)
        );
    }
    maxX
    {
        type patch;
        faces
        (
            (2 6 5 1)
        );
    }
    minY
    {
        type wall;
        faces
        (
            (1 5 4 0)
        );
    }
    maxY
    {
        type wall;
        faces
        (
            (3 7 6 2)
        );
    }
    minZ
    {
        type wall;
        faces
        (
            (0 3 2 1)
        );
    }
    maxZ
    {
        type wall;
        faces
        (
            (4 5 6 7)
        );
    }
);

この blockMeshDict では、汎用性のために設定の一部がキーワードの参照を用いて書かれている。"minx"、"maxx" などが設定変更用のキーワードで、"$minx"、"$maxx" などとして参照されている。"minx"、"maxx"、…、"maxz" でモデルを囲む直方体の範囲を設定する。

snappyHexMesh のメッシュサイズは blockMesh のメッシュサイズによって決まるので、ここで十分な分割数を設定する必要がある。上の blockMeshDict では "nx"、"ny"、"nz" が分割数に当たり、ここでは 50 x 10 x 55 分割としている。これらの値を大きくすれば、より細かいメッシュが得られる。モデルを囲むメッシュは必ずしも直方体にする必要はなく、できるだけモデル形状に近いメッシュを作っておいたほうがきれいなメッシュを作りやすい。

準備が整ったら、blockMesh を実行する。

$ cd mixing_elbow
$ blockMesh

特徴線

snappyHexMesh において特徴線 (feature) を利用することがある。特徴線は、メッシュを形状に合わせるために使われるもので、surfaceFeatures で作成する。設定は system/surfaceFeaturesDict で行う。

system/surfaceFeaturesDict

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      surfaceFeaturesDict;
}

surfaces ("mixing_elbow.stl");

includedAngle       150;

subsetFeatures
{
    nonManifoldEdges       no;

    openEdges       yes;
}

includedAngle は特徴線を抽出する角度である。面と面が作る角度が includedAngle 以下であれば、その辺を特徴線とする。

つぎのように実行する。

$ surfaceFeatures

snappyHexMesh

snappyHexMesh の設定は system/snappyHexMeshDict で行う。

スイッチ

castellatedMesh true;
snap            true;
addLayers       true;

snappyHexMesh によるメッシュの作成には 3 つのステップがある。

  1. ブロックメッシュから形状と重なった部分だけを取り出す。
  2. メッシュを形状に合わせる (snap)。
  3. 境界層メッシュを追加する。
上記はそれぞれのスイッチである。スイッチを切り替えて手動で 1 ステップずつ実行することもできる。

形状の指定

形状ファイルの指定は geometry で行う。

geometry
{
    mixing_elbow
    {
        type triSurfaceMesh;
        file "mixing_elbow.stl";
    }
};

ブロック状メッシュの作成

ブロック状メッシュ作成の設定を castellatedMeshControls で行う。

castellatedMeshControls
{
    maxLocalCells 100000;

    maxGlobalCells 2000000;

    minRefinementCells 0;

    maxLoadUnbalance 0.10;

    nCellsBetweenLevels 1;

    features
    (
        {
            file "mixing_elbow.eMesh";
            level 0;
        }
    );

    refinementSurfaces
    {
        mixing_elbow
      {
            level (0 0);
        }
    }

    resolveFeatureAngle 30;

    refinementRegions
    {
    }

    locationInMesh (0.001 0 0);

    allowFreeStandingZoneFaces true;
}

セルの数は maxGlobalCells で制限される。

features は、surfaceFeatureExtract で作成した特徴線を指定する (次のスナップに影響する)。特徴線の部分における細分化を指定できる。たとえば、つぎのように設定する。

    features
    (
        {
            file "mixing_elbow.eMesh";
            level 1;
        }
    );

この設定では、特徴線の部分を 1 段階細分化する。また、level の代わりに、つぎのように levels を使うこともできる。

            levels ((0.001 2) (0.002 1));

境界から距離 0.001 の範囲は 2 段階、距離 0.002 の範囲は 1 段階の細分化を行うようにしている。

refinementSurfaces は境界メッシュの細分化を制御する。たとえば、つぎのように設定すると、1 段階から 2 段階の間で境界メッシュを細分化する。

    refinementSurfaces
    {
        mixing_elbow
        {
            level (1 2);
        }
    }

この設定自体は形状の指定でもあるので、境界メッシュの細分化が必要なくても必ず設定する。ここでは以下のように境界タイプの設定もできる。

    refinementSurfaces
    {
        mixing_elbow
        {
            level (0 0);

            patchInfo
            {
                type wall;
            }

            regions
            {
                "(in1|in2|out)"
                {
                    level (0 0);

                    patchInfo
                    {
                        type patch;
                    }
                }
            }
        }
    }

patchInfo でデフォルトの設定をして、regions で個別の設定をしている。細分化も個別に指定できる。

locationInMesh ではメッシュ内部の座標を指定する。たとえば、配管の中の座標を指定すれば配管の内部流れのメッシュが作られ、配管の外の座標を指定すれば配管の外部流れのメッシュが作られる。

スナップ

メッシュを形状に合わせるスナップ (snap) の設定を行う。

snapControls
{
    nSmoothPatch 3;

    tolerance 2.0;

    nSolveIter 30;

    nRelaxIter 5;

    nFeatureSnapIter 10;

    implicitFeatureSnap false;

    explicitFeatureSnap true;

    multiRegionFeatureSnap false;
}

nSmoothPatch はパッチのスムージングの設定で、やりすぎると角が丸くなる。

explicitFeatureSnap を有効にすると、castellatedMeshControls の features で指定した特徴線にメッシュを合わせる。implicitFeatureSnap を有効にすると、特徴線を使わずにメッシュを形状に合わせる。 併せて nFeatureSnapIter を設定する必要がある。

境界層メッシュの追加

境界層メッシュの追加の設定を行う。

addLayersControls
{
    relativeSizes true;

    layers
    {
        mixing_elbow_side
        {
            nSurfaceLayers 3;
        }
    }

    expansionRatio 1.1;

    finalLayerThickness 0.3;

    minThickness 0.1;

    nGrow 0;

    //featureAngle 60;
    featureAngle 360;

    slipFeatureAngle 30;

    nRelaxIter 3;

    nSmoothSurfaceNormals 1;

    nSmoothNormals 3;

    nSmoothThickness 10;

    maxFaceThicknessRatio 0.5;

    maxThicknessToMedialRatio 0.3;

    minMedianAxisAngle 90;

    nBufferCellsNoExtrude 0;

    nLayerIter 50;
}

layers で境界層メッシュを追加する境界と層の数を指定する。境界の名前は、形状の名前が "mixing_elbow" で STL の境界名が "side" であれば、"mixing_elbow_side" となる。

expansionRatio で層の拡大率を指定する。featureAngle は境界層メッシュを入れない面の接続角度である。ここでは急な角度をもつ管の結合部でも境界層メッシュが入るように大きな値を設定している。

メッシュ品質

メッシュ品質を設定する。

meshQualityControls
{
    #include "meshQualityDict"

    maxConcave 10;
    minTetQuality 1e-30;
}

system/meshQualityDict がインクルードされている。この中身は以下のとおりである。

system/meshQualityDict

#includeEtc "caseDicts/mesh/generation/meshQualityDict"

//- minFaceWeight (0 -> 0.5)
minFaceWeight 0.02;

さらにシステムの $FOAM_ETC/caseDicts/mesh/generation/meshQualityDict が読み込まれている。

$FOAM_ETC/caseDicts/mesh/generation/meshQualityDict

maxNonOrtho 65;

maxBoundarySkewness 20;
maxInternalSkewness 4;

maxConcave 80;

minVol 1e-13;

minTetQuality 1e-15;

minArea -1;

minTwist 0.02;

minDeterminant 0.001;

minFaceWeight 0.05;

minVolRatio 0.01;

minTriangleTwist -1;

nSmoothScale   4;

errorReduction 0.75;

//minVolCollapseRatio 0.1;

ここでは maxConcave を調整している (設定を上書きしている)。minTetQuality を -1e30 に設定したほうがきれいなメッシュができることがある。

実行

設定を終えたら、snappyHexMesh を実行する。

$ snappyHexMesh

snappyHexMesh を実行すると、実行ステップごとに時刻ディレクトリができる。できたメッシュをチェックして、問題なければ、0 以外の時刻ディレクトリを削除してから、改めて上書きで snappyHexMesh を実行する。

$ snappyHexMesh -overwrite

メッシュの初期化

もし完全にまっさらな状態から (blockMesh から) やりなおしたい場合は、foamCleanPolyMesh でメッシュ情報を削除する。

$ foamCleanPolyMesh

ステップごとの実行

ブロック状メッシュの作成、スナップ、境界層メッシュの追加の各ステップは別々に実行できるため、各ステップで設定を変えて実行することができる。たとえば、境界層メッシュの追加だけ設定を変えたい場合、つぎのようなスクリプトを実行すればよい。

createMesh

#!/bin/sh
foamCleanPolyMesh
blockMesh
cp system/snappyHexMeshDict.1 system/snappyHexMeshDict
snappyHexMesh -overwrite
cp system/snappyHexMeshDict.2 system/snappyHexMeshDict
snappyHexMesh -overwrite

"system/snappyHexMeshDict.1" では castellatedMesh と snap を有効にし、"system/snappyHexMeshDict.2" では addLayers のみを有効にしている。ここでは、"snappyHexMeshDict.1" では meshQualityControls の maxConcave を 10、minTetQuality を 1e-30 にし、"snappyHexMeshDict.2" では maxConcave を 80、minTetQuality を -1e30 としている。こうすることで、下部のノズル表面がなめらかになり、境界層もきれいに入る。また、メッシュに不自然な穴が発生することも抑えている。

完成したメッシュを下図に示す。

メッシュのチェック

メッシュができたら、計算に不都合な品質の悪いメッシュができていないか checkMesh でチェックする。

$ checkMesh

エラーメッセージが出なければよい。

checkMesh の実行には 0 ディレクトリが必要だが、ここでの作業で使用した元のケース motorBike には 0 がなく、代わりに 0.org が置かれているので、まず 0.org を 0 としてコピーする必要がある。

メッシュの細分化

castellatedMeshControls の refinementRegions で細分化領域を指定できる。細分化領域は geometry でつぎのように定義する。

geometry
{
    mixing_elbow.stl
    {
        type triSurfaceMesh;
        name mixing_elbow;
    }

    box
    {
        type searchableBox;
        min (0.04 -0.006 -0.01);
        max (0.05  0.006  0.01);
    }

    cylinder
    {
        type searchableCylinder;
        point1 (0.044 0 -0.01);
        point2 (0.044 0  0.01);
        radius 0.003;
    }

    sphere
    {
        type searchableSphere;
        centre (0.044 0 0);
        radius 0.01;
    }
};

形状ファイルも細分化領域に指定できる。

細分化の設定は次のようにする。

    refinementRegions
    {
        mixing_elbow
        {
            mode distance;
            levels ((0.001 2) (0.002 1));
        }

        box
        {
            mode inside;
            levels ((1E15 2));
        }
    }

mode には "distance"、"inside"、"outside" が指定できる。"distance" は距離で細分化レベルを指定する。"levels" は features のものと同様である。"inside", "outside" は領域内部あるいは外部の細分化レベルを指定する。"levels" は features のものと同様であるが、項目は 1 つだけ指定する。また、レベルの指定だけが使われ、距離の指定は無視される。

並列実行

snappyHexMesh は並列実行が可能である。ソルバーと異なり、メッシュを統合するのに reconstructPar ではなく reconstructParMesh を使う。領域分割のために、system/decomposePar をつぎのように設定する。

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      decomposeParDict;
}

numberOfSubdomains 4;

method          hierarchical;
//method          simple;

simpleCoeffs
{
    n               (2 2 1);
    delta           0.001;
}

hierarchicalCoeffs
{
    n               (2 2 1);
    delta           0.001;
    order           xyz;
}

実行はつぎのようにする。

$ decomposePar
$ mpirun -np 4 snappyHexMesh -parallel
$ reconstructParMesh -latestTime -mergeTol 1e-6

上書きで実行する場合は以下のようにする。

$ mpirun -np 4 snappyHexMesh -overwrite -parallel
$ reconstructParMesh -constant -mergeTol 1e-6

古い