マルチリージョンソルバで特定の面の条件を変える方法
こんにちは(@t_kun_kamakiri)
前回の記事では以下の解析を行い総括熱伝達率(U値)をOpenFOAMを使って算出してみました。

今回の記事では特定の面だけを名前を変える方法を紹介します。具体的には、固体領域の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にしています。
計算の設定の前回の記事で詳しく書いていますのでご参考ください。



まとめ
マルチリージョンソルバで既にメッシュ作成と領域分割を終えてから面の一部の名前を変更する方法を紹介しました。
これは「メッシュは作り終わっているのに、特定の面だけ境界条件を変えたい」ときに役立ちます。特に、元の patch に複数の面がまとめられていて、その一部だけを分けたい場合に便利です。
方法は、topoSet と createPatch を使って、既存の patch の一部だけを切り出し、新しい名前の面として再定義し、さらに changeDictionary でその新しい面にだけ別の境界条件を与えます。
この方法を使えば、マルチリージョンでは、blockMesh や外部メッシャーで作った面を後から柔軟に分割し、流体・固体の各領域ごとに適切な境界条件を入れ直せるので、とても有効です。領域間 interface を壊さずに、外壁の一部だけ条件変更したいときに役立ちますので、お困りの際はご活用ください。

























