こんにちは(@t_kun_kamakiri)

前回の記事では以下の解析を行い総括熱伝達率(U値)をOpenFOAMを使って算出してみました。

OpenFOAMで総括熱伝達率(U値)を計算する方法。chtMultiRegionFoam対応 こんにちは(@t_kun_kamakiri) OpenFOAMの熱流体固体連成による総括熱伝達率(U値)を計算で求めたい...

今回の記事では特定の面だけを名前を変える方法を紹介します。具体的には、固体領域の3つの面が「s2_maxX」となっている場合に、一番右端だけを「maxX_perp」という名前にする場合を考えます。

最終的にはこうなります。

面の一部の名前を変更するとその面だけ違う境界条件にすることができます。
その場合には有効は方法だと思いますので、お困りの際はこちらの記事をご参考ください。

作業フォルダを作成

適当にフォルダを作成し、そちらを作業フォルダとします。

mkdir ana003_changeSpecificFaceCondition

メッシュ作成

system/blockMeshDict

scale   1;

vertices
(
    (0    0   0)    //0
    (0.1  0   0)    //1
    (0.11 0   0)    //2
    (0.21 0   0)    //3
    (0.22 0   0)    //4
    (0.22 0.3 0)    //5
    (0.21 0.3 0)    //6
    (0.11 0.3 0)    //7
    (0.1  0.3 0)    //8
    (0    0.3 0)    //9
    (0    0   0.01) //10
    (0.1  0   0.01) //11
    (0.11 0   0.01) //12
    (0.21 0   0.01) //13
    (0.22 0   0.01)    //14
    (0.22 0.3 0.01)    //15
    (0.21 0.3 0.01)    //16
    (0.11 0.3 0.01)    //17
    (0.1  0.3 0.01)    //18
    (0    0.3 0.01)    //19
);

blocks
(
    hex (0 1 8 9 10 11 18 19)  fluid_1 (20 60 1) simpleGrading (1 1 1)
    hex (1 2 7 8 11 12 17 18)  solid_1 (10 60 1) simpleGrading (1 1 1)
    hex (2 3 6 7 12 13 16 17)  fluid_2 (20 60 1) simpleGrading (1 1 1)
    hex (3 4 5 6 13 14 15 16) solid_2 (10 60 1) simpleGrading (1 1 1)
);

edges
(
);

boundary
(
    f1_minX
    {
        type wall;
        faces
        (
            (0 9 19 10)
        );
    }
    f1_minY
    {
        type wall;
        faces
        (
            (1 0 10 11)
        );
    }
    s1_minY
    {
        type wall;
        faces
        (
            (2 1 11 12 )
        );
    }
    f2_minY
    {
        type wall;
        faces
        (
            (3 2 12 13)
        );
    }
    // s2_minY
    // {
    //     type wall;
    //     faces
    //     (
    //         (4 3 13 14)
    //     );
    // }
    // s2_maxY
    // {
    //     type wall;
    //     faces
    //     (
    //         (6 5 15 16)
    //     );
    // }
    s2_maxX
    {
        type wall;
        faces
        (
            (4 5 15 14)
            (6 5 15 16)
            (4 3 13 14)
        );
    }
    f2_maxY
    {
        type wall;
        faces
        (
            (7 6 16 17)
        );
    }
    s1_maxY
    {
        type wall;
        faces
        (
            (8 7 17 18)
        );
    }
    f1_maxY
    {
        type wall;
        faces
        (
            (9 8 18 19)
        );
    }
);

mergePatchPairs
(
);

領域を分割

メッシュを作成しただけでは領域分割は行えていないので、以下のコマンドで領域を分割します。

splitMeshRegions -cellZones -overwrite

ParaViewで確認すると領域分割できていることがわかります。
領域間の共通の面は「領域1_to _領域2」のように名前が自動で付けられます。

今は意図的のblockMeshで以下のように3面で「s2_maxX」となるようにしました。

ここから一番右端の面だけを名前を変える方法を紹介します。
blockMeshくらいでしたらblockMeshDictを編集して、もう一度メッシュを作り直せば良い話ですが、別のメッシャーを使って既に時間をかけてメッシュを作ってしまった場合に、はじめからメッシュを作り替えたりするのは面倒です。

というわけでその場合に本記事の方法が有効というわけです。

FaceSetを作成する

以下のコマンドでコピー

cp -r  $FOAM_TUTORIALS/incompressible/pisoFoam/RAS/cavity/system/topoSetDict system/solid_2

$FOAM_TUTORIALS = /usr/lib/openfoam/openfoam2506/tutorials/

まずはFaceZoneを使って特定の面を抽出します。

system/solid_2/topoSetDict

actions
(
    // (1) まず s2_maxX パッチ上の面を全部 faceSet に入れる
    {
        name    maxX_target;
        type    faceSet;
        action  new;
        source  patchToFace;
        sourceInfo
        {
            patch s2_maxX;
        }
    }

    // (2) その中から「法線が x 軸方向(±x)」の面だけに絞る
    {
        name    maxX_target;
        type    faceSet;
        action  subset;
        source  normalToFace;
        sourceInfo
        {
            normal      (1 0 0);   // x 方向
            cos         0.996;     // ≒ 5°以内にする例。必要に応じて調整
            bothSides   true;      // +x と -x 両方許可(片側だけなら false)
        }
    }

    // (3) さらに「x が最大付近」の面だけに絞る
    //     x_max を自分で確認してから ε を決めてください
    {
        name    maxX_target;
        type    faceSet;
        action  subset;
        source  boxToFace;
        sourceInfo
        {
            // 例:x_max ≒ 0.200, ±0.0005 だけ許容
            box (0.1995 -1e10 -1e10) (100 1e10 1e10);
        }
    }
);
  • 1つ目のブロック
    s2_maxX パッチにある面を全部集めています。
  • 2つ目のブロック
    その中から、法線が x 方向に近い面だけに絞っています。
  • 3つ目のブロック
    さらにその中から、x 座標が最大付近にある面だけに絞っています。

今回の場合はX方向に垂直な面は1つしかないので、2つ目のブロックまでで十分ですが念のためさらに領域を絞るためのブロック3を設けています。

実行方法は以下のコマンドです。

topoSet -region solid_2

実行すると以下のファイルが作成されています。

constant/solid_2/polyMesh/sets/maxX_target

60
(
1130
1131
1132
1133
1134
1135
1136
1137
...(省略)...

ここの数値が0になっている場合は、FaceSetの作成に失敗しているのでtopoSetDictにミスがないか確認してください。

※ParaViewで確認するにはtopoSetでFaceSetからさらにFaceZoneを作成する必要があります。

面に名前を付けなおす

cp -r $FOAM_TUTORIALS/incompressible/pimpleFoam/RAS/ellipsekkLOmega/system/createPatchDict system/solid_2

system/solid_2/createPatchDict

pointSync false;

patches
(
    {
        name        maxX1_highY;        // 新しく作るパッチ名
        patchInfo
        {
            type wall;                 // 必要な種類に変更
        }

        constructFrom   set;
        set             maxX1_part;    // 上で作った faceSet

        // 元のパッチ名(splitType によって扱いが変わる)
        // 同じ maxX1 内の一部だけを切り出すので、ここを指定
        patches         ( maxX1 );
    }
);

createPatch -overwrite -region solid_2

確認してほしいのは以下の箇所です。

constant/solid_2/boundary

4
(
    s2_maxX
    {
        type            wall;
        inGroups        1(wall);
        nFaces          20;
        startFace       1130;
    }
    defaultFaces
    {
        type            empty;
        inGroups        1(empty);
        nFaces          1200;
        startFace       1150;
    }
    solid_2_to_fluid_2
    {
        type            mappedWall;
        inGroups        2(wall mappedPatch);
        nFaces          60;
        startFace       2350;
        sampleMode      nearestPatchFace;
        sampleRegion    fluid_2;
        samplePatch     fluid_2_to_solid_2;
    }
    maxX_perp
    {
        type            wall;
        inGroups        1(wall);
        nFaces          60;
        startFace       2410;
    }
)

このように「maxX_perp」が新たに作られ、nFacesが0でなければOKです。

ParaViewで確認しても一番右端の面だけ「maxX_perp」に変わっています。

changeDictionaryDictによる境界条件の設定

system/solid_2/changeDictionaryDict

T
{
    internalField   uniform 293.15;

    boundaryField
    {
        ".*"
        {
            type    fixedValue;
            value   uniform 293.15;
        }

        defaultFaces
        {
            type            empty;
        }

        ".*_to_.*"
        {
            type            compressible::turbulentTemperatureRadCoupledMixed;
            value           uniform 293.15;
            Tnbr            T;
            kappaMethod     fluidThermo;
            qrNbr           none;
            qr              none;//qr;
            thermalInertia  true;
            kappa           none;
        }
        
        maxX_perp
        {
            type    fixedValue;
            value   uniform 293.15;
        }
    }
}

p
{
    internalField   uniform 100000;

    boundaryField
    {
        ".*"
        {
            type            calculated;
            value           uniform 100000;
        }
        defaultFaces
        {
            type            empty;
        }
        maxX_perp
        {
            type            calculated;
            value           uniform 100000;
        }
    }
}

面倒ですが温度と圧力に「maxX_perp」の条件を追加します。

以下のコマンドを実行して境界条件に反映させます。

for region in $(foamListRegions); do changeDictionary -region "$region"; done

スクリプトで書くと以下となります。

#!/bin/bash

for region in $(foamListRegions)
do
    echo "=== changeDictionary for region: $region ==="
    changeDictionary -region "$region"
done

実行すると以下のようになります。

0/solid_2/T

dimensions      [ 0 0 0 1 0 0 0 ];

internalField   uniform 293.15;

boundaryField
{
    s2_maxX
    {
        type            fixedValue;
        value           uniform 293.15;
    }
    defaultFaces
    {
        type            empty;
    }
    solid_2_to_fluid_2
    {
        type            compressible::turbulentTemperatureRadCoupledMixed;
        value           uniform 293.15;
        Tnbr            T;
        kappaMethod     fluidThermo;
        qrNbr           none;
        qr              none;
        thermalInertia  true;
        kappa           none;
    }
    maxX_perp
    {
        type            fixedValue;
        value           uniform 300;
    }
}

0/solid_2/p

dimensions      [ 1 -1 -2 0 0 0 0 ];

internalField   uniform 100000;

boundaryField
{
    s2_maxX
    {
        type            calculated;
        value           uniform 100000;
    }
    defaultFaces
    {
        type            empty;
    }
    solid_2_to_fluid_2
    {
        type            calculated;
        value           uniform 100000;
    }
    maxX_perp
    {
        type            calculated;
        value           uniform 100000;
    }
}

計算実行

2次元計算でメッシュ数も多くないので並列計算させずにいきます。

chtMultiRegionFoam > log.chtMultiRegionFoam &

今回最大クーラン数を流体側も固体側も10にしています。

計算の設定の前回の記事で詳しく書いていますのでご参考ください。

OpenFOAMで総括熱伝達率(U値)を計算する方法。chtMultiRegionFoam対応 こんにちは(@t_kun_kamakiri) OpenFOAMの熱流体固体連成による総括熱伝達率(U値)を計算で求めたい...

まとめ

マルチリージョンソルバで既にメッシュ作成と領域分割を終えてから面の一部の名前を変更する方法を紹介しました。

これは「メッシュは作り終わっているのに、特定の面だけ境界条件を変えたい」ときに役立ちます。特に、元の patch に複数の面がまとめられていて、その一部だけを分けたい場合に便利です。

方法は、topoSet と createPatch を使って、既存の patch の一部だけを切り出し、新しい名前の面として再定義し、さらに changeDictionary でその新しい面にだけ別の境界条件を与えます。

この方法を使えば、マルチリージョンでは、blockMesh や外部メッシャーで作った面を後から柔軟に分割し、流体・固体の各領域ごとに適切な境界条件を入れ直せるので、とても有効です。領域間 interface を壊さずに、外壁の一部だけ条件変更したいときに役立ちますので、お困りの際はご活用ください。