Upload
fumiya-nozaki
View
4.792
Download
45
Embed Size (px)
Citation preview
Fumiya Nozaki
最終更新日: 2014年7月13日
Cyclic & Arbitrary Mesh Interface (AMI)
OpenFOAM v2.3.0
日本語版
Keywords: • OpenFOAM • cyclic • cyclicAMI • cyclicACMI
2
はじめに
この資料では,
• cyclic • cyclicAMI • cyclicACMI の3つの境界条件について取り扱います.
この資料を通して,ここでしっかり区別して使い分けできるようになりましょう!自分も含めて!
名前が似ていてとても紛らわしい (;^_^A
3
目次
Chapter 1. 概要 Chapter 2. 3つの境界条件に共通な内容 Chapter 3. cyclic 境界条件 Chapter 4. cyclicAMI 境界条件 Chapter 5. cyclicACMI 境界条件
4
Chapter 1
3つの境界条件の 共通点 と 相違点 を理解しましょう.
5
共通点
3つの境界条件で共通している点
2つの境界を関係づける境界条件である
PatchA
PatchD
PatchB
PatchC
例えば, と とを関係づけるという場合,
具体的にはどんな関係があるか見てみましょう.
PatchA PatchB
6
1つめの関係-周期境界条件-
空間的な周期性から生じる関係 ⇒ 周期境界条件
PatchA
PatchD
PatchB
PatchC
例えば左図の場合,空間的な周期性から,
と PatchA PatchB
上では,同じ流れ場になると考えられます
この関係は,
『周期境界条件』 と呼ばれる境界条件です.
7
1つめの関係-周期境界条件-
平行移動で重なる
回転移動で重なる
空間的な周期性には次の2種類があります.
8
2つめの関係-隣接する境界-
空間的に隣接しているという関係
PatchA
PatchB
例えば,
• 青色の領域が回転領域で • ピンク色の領域が静止領域
という場合があります.
インペラとボリュートの間の境界が1つの具体例です.
9
相違点
cyclicACMI
Yes No
cyclicAMI cyclic
ペアの境界が同一形状
ペアの境界のサーフェスメッシュが 回転 or 並進で一致
Yes No
3つの境界条件で異なる点
ペアとなる2つの境界の形状,サーフェスメッシュの関係によって 使用できる境界条件が異なります.
• フェイスの数や • 格子点の位置関係が 一致しているかどうか.
10
cyclic
言葉だけだとイメージしにくいので,チュートリアルを見てみましょう. のチュートリアル:incompressible/SRFSimpleFoam/mixer cyclic
cyclic_half1
cyclic_half0
• 境界の形状 • フェイス数 • 格子点の相対的な位置関係
がペアの境界で一致しています.
ペアの境界
11
cyclicAMI
AMI2
AMI1
境界の形状は一致していますが,
• フェイス数 • 格子点の相対的な位置関係
がペアの境界で異なっています.
次は, のチュートリアル:incompressible/pimpleDyMFoam/propeller cyclicAMI
回転領域の境界
静止領域の境界
ペアの境界
12
cyclicACMI
最後に, のチュートリアル:incompressible/pimpleDyMFoam/oscillatingInletACMI2D cyclicACMI
ACMI1_couple
ACMI2_couple
ACMI2_blockage
ACMI1_blockage ペアの境界
AMI1
AMI2
ペアの境界の形状(大きさ) が異なっています.
13
まとめ
これまでの内容を整理してみましょう.
cyclic,cyclicAMI,cyclicACMI はどれも ペアとなる2つの境界を関係づける境界条件です.
この関係には次の3種類があります:
• 周期境界条件ー回転ー • 周期境界条件ー並進ー • 隣接する境界
この3つでは,ペアとなる2つの境界の形状,サーフェスメッシュの関係によって使用できる境界条件が異なります: • 形状もサーフェスメッシュも同一の場合: cyclic • 形状は同一だが,サーフェスメッシュが異なる場合: cyclicAMI • 形状自体異なる場合: cyclicACMI
14
Chapter 2
3つの境界条件に共通な内容を学んでいきましょう.
15
2つの境界のペアの指定
cyclic_half0 //ペアの一方の境界名
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 101720;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half1;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
cyclic_half1 //もう一方の境界名
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 103320;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half0;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
3つの境界条件はどれも,2つの境界のペアに対して設定されます.
3つの境界条件のどれを使用するかは,“type” の項目で指定します.
“neighbourPatch” の項目で,ペアを構成するもう一方の境界を名前で指定します.
左の設定では,2つの境界 • cyclic_half0 • cyclic_half1 をペアとして,このペアに ”cyclic” 条件を設定しています.
16
ペアの境界の関係性の指定
ペアの境界の関係性を “transform” の項目で指定します.
詳細は次のページ.
cyclic_half0 //ペアの一方の境界名
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 101720;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half1;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
cyclic_half1 //もう一方の境界名
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 103320;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half0;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
17
“transform” のタイプ
“transform” のタイプは,次の5つから選択できます. • rotational
これが, に対応しています.
• translational
これが, に対応しています. • noOrdering
これが, に対応しています. • unknown • coincidentFullMatch
次のページからそれぞれの設定を見ていきます.
周期境界条件ー回転ー
周期境界条件ー並進ー
隣接する境界
調査中
調査中
18
rotational タイプ
cyclic_half0
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 101720;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half1;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
cyclic_half1
{
type cyclic;
inGroups 1(cyclic);
nFaces 1600;
startFace 103320;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half0;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
}
回転移動で一致する周期性には, “rotational” を使用します.
この場合,回転軸の設定が必要です. • “rotationAxis”:回転軸の方向ベクトル • “rotationCentre”:回転軸が通る点 • “rotationCentre” については,回転軸上の
点であれば,どの点の座標を指定しても計算結果に影響ありません.
チュートリアル • incompressible/SRFSimpleFoam/mixer
boundary ファイル
cyclic_half1 cyclic_half0
19
TOP
{
type cyclic;
inGroups 1(cyclic);
nFaces 240;
startFace 81570;
matchTolerance 0.0001;
transform translational;
neighbourPatch BTM;
separationVector(0 -0.16192 0);
}
BTM
{
type cyclic;
inGroups 1(cyclic);
nFaces 240;
startFace 81810;
matchTolerance 0.0001;
transform translational;
neighbourPatch TOP;
separationVector (0 0.16192 0);
}
boundary ファイル 並進移動で一致する周期性には, “translational” タイプを使用します.
この場合,周期境界条件を設定する境界ペア間で,それぞれから見たもう一方の相対的な位置をベクトルで指定します. • “separationVector”:もう一方の境界への
位置ベクトル
TOP
BTM
0.16192 m
translational タイプ
20
noOrdering タイプ
AMI1
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 18496;
startFace 1602395;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch AMI2;
}
AMI2
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 18720;
startFace 1620891;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch AMI1;
}
隣接する境界には, “noOrdering” タイプを使用します.
このタイプでは,特に追加で設定が必要な項目はありません.
AMI2
AMI1
21
メッシュの生成
blockMesh でメッシュを生成する場合
cyclic_half0
{
type cyclic;
neighbourPatch cyclic_half1;
transform rotational;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
faces
(
(0 9 21 12)
(10 0 12 22)
);
}
cyclic_half1
{
type cyclic;
neighbourPatch cyclic_half0;
transform rotational;
rotationAxis (0 0 1);
rotationCentre (0 0 0);
faces
(
(3 15 20 8)
(11 23 15 3)
);
}
blockMeshDict に 設定を記述
snappyHexMesh でメッシュを生成する場合やサードパーティーのツールで生成したメッシュを変換して使用する場合 “createPatch” ユーティリティーを使用して,境界を定義します. 設定ファイル “createPatchDict” の記述例はこちら.
22
周期的な形状の可視化
ParaView を使用して,1区画分の計算結果を周期的に表示するには,”Transform” フィルターを使用します.
設定
• “Translate”:並進コピーを生成 各方向への移動量を指定
• “Rotate”:回転コピーを生成 回転角度を度 [deg] 単位で指定 例)Z軸周りに反時計方向に45[deg]回転 Rotate 0 0 45
• “Scale”:拡大/縮小コピーを生成
23
まとめ
rotational translational
noOrdering
“transform” のタイプの使い分け
24
Chapter 3
cyclic 境界条件に関してもう少し詳しく見ていきます.
25
owner と neighbour
cyclic_half0
{
type cyclic;
inGroups 1(cyclic);
nFaces 1728;
startFace 350208;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half1;
rotationAxis (1 0 0);
rotationCentre (0 0 0);
}
cyclic_half1
{
type cyclic;
inGroups 1(cyclic);
nFaces 1728;
startFace 351936;
matchTolerance 0.0001;
transform rotational;
neighbourPatch cyclic_half0;
rotationAxis (1 0 0);
rotationCentre (0 0 0);
}
ペアを構成する2つの境界の内,”boundary” ファイルで最初に定義されている方をペアの “owner”,後に定義されている方を “neighbour” と定義しています.
virtual bool owner() const
{
return index() < neighbPatchID();
}
virtual bool neighbour() const
{
return !owner();
}
cyclicPolyPatch.H
例えば,右のような “boundary” の設定の場合,最初に定義されている cyclic_half0 が owner となり,後に定義されている cyclic_half1 が neighbour となります.
26
曲面での使用
cyclic_half1 cyclic_half0
cyclic 境界条件は,ペアとなる境界が曲面の場合でも問題なく使用可能です.
27
”matchTolerance” パラメータの役割
cyclicPolyPatch.C
if (areaDiff > matchTolerance())
{
FatalErrorIn
(
"cyclicPolyPatch::calcTransforms()“ ) << "face " << facei
<< " area does not match neighbour by “ << 100*areaDiff
<< "% -- possible face ordering problem." << endl
(省略)
<< "If you are certain your matching is correct“
<< " you can increase the 'matchTolerance' setting“
<< " in the patch dictionary in the boundary file.“
<< endl
<< "Rerun with cyclic debug flag set“
<< " for more information." << exit(FatalError)
}
“areaDiff” と “matchTolerance” の大小を比較し, “areaDiff” の方が大きい場合には計算を終了します.
“areaDiff” については 次のページへ.
28
scalar areaDiff = mag(magSf - nbrMagSf)/avSf;
cyclicPolyPatch.C
cyclic に指定された2つの境界
同じラベルのフェイス同士で面積を比較
half0 half1
まとめると,
• cyclic に指定された2つの境界間で対応する(つまり境界上のラベルが同一の)フェイスの面積を比較し,その差がある閾値よりも大きい場合には,そのメッシュでは cyclic 条件の使用が適切ではないとソルバーが判断します.
• その閾値の大きさをコントロールするのが ”matchTolerance” であり,大きな値に設定するほど,条件は緩和されますが,計算結果の妥当性のチェックが必要です.
ここで, • magSf:境界 half0 の facei 番目のフェイスの面積 • nbrMagSf:ペアの境界 half1 の facei 番目のフェイスの面積 • avSf:2つのフェイスの平均面積 ((magSf + nbrMagSf)/2)
”matchTolerance” パラメータの役割
29
cubic 0;
cubicUpwindFit 0;
curve 0;
cyclic 0;
cyclicLduInterface 0;
cyclicLduInterfaceField 0;
cylinderToCell 0;
cylindrical 0;
decompositionMethod 0;
391行目
“cyclic” 変数の値を 0 から 1 に変更します.
“cyclic” クラスで定義されている ”debug” 変数の値を ”true” に変更することで より多くの情報を出力できるようになります.
$WM_PROJECT_DIR/etc ディレクトリ
ペアのフェイスの可視化
ケースディレクトリにある “system/controlDict” ファイルに 以下を追記します.
DebugSwitches
{
cyclic 1;
}
方法1 方法2 ファイルを直接編集
30
if (debug && owner())
{
fileName casePath(boundaryMesh().mesh().time().path());
{
fileName nm0(casePath/name()+"_faces.obj");
Pout<< "cyclicPolyPatch::calcTransforms : Writing " << name()
<< " faces to OBJ file " << nm0 << endl;
writeOBJ(nm0, half0, half0.points());
}
const cyclicPolyPatch& half1 = neighbPatch();
{
fileName nm1(casePath/half1.name()+"_faces.obj");
Pout<< "cyclicPolyPatch::calcTransforms : Writing " << half1.name()
<< " faces to OBJ file " << nm1 << endl;
writeOBJ(nm1, half1, half1.points());
}
前ページの設定により“true”になります.
“cyclic” 境界条件を使用しているケースで “blockMesh” や ソルバーを実行すると 次の3つの “obj” ファイルが作成されます.
• cyclic_half0_faces.obj
• cyclic_half1_faces.obj
• cyclic_half0_to_cyclic_half1.obj
ペアのフェイスの可視化
cyclicPolyPatch.C
31
obj ファイルはそのままでは ParaView で可視化できないので,”objToVTK” ユーティリティーを使用して VTK 形式に変換します.
変換する obj ファイル名
objToVTK cyclic_half0_to_cyclic_half1.obj cyclic_half0_to_cyclic_half1.vtk
変換後の出力ファイル名
“cyclic_half0_to_cyclic_half1” ファイルは,”cyclic” 境界に指定された境界のペアとなるフェイスの中心点間を結んだ線分データです.
“cyclic” 境界条件を使用した計算がうまく実行できない場合には,フェイスの対応が正しいかどうかこの方法で確認できます.
ペアのフェイスの可視化
32
変換テンソルの計算
例えば,回転で一致する周期性の場合,対応するフェイスの向きが異なるので,ベクトル量やテンソル量については,ペアとなる patch の向きを考慮した変換操作が行われます.
その変換操作を行うのが次の2つのテンソルで,ペアとなる境界それぞれで定義されています. • forwardT() • reverseT()
cyclic_half1 cyclic_half0
回転軸
cyclic_half0 上のフェイス
cyclic_half1 上のフェイス
変換操作
33
変換テンソルの計算|rotational の場合
neighbour owner
変換テンソルによる変換の向きを図示すると
forwardT()
reverseT()
owner 境界の
owner 境界の
forwardT()
neighbour 境界の
reverseT()
neighbour 境界の
34
変換テンソルの計算|rotational の場合
// Extended tensor from two local coordinate systems calculated
// using normal and rotation axis
const tensor E0
(
rotationAxis_,
(n0 ^ rotationAxis_),
n0
);
const tensor E1
(
rotationAxis_,
(-n1 ^ rotationAxis_),
-n1
);
const tensor revT(E1.T() & E0);
const_cast<tensorField&>(forwardT()) = tensorField(1, revT.T());
const_cast<tensorField&>(reverseT()) = tensorField(1, revT);
const_cast<vectorField&>(separation()).setSize(0);
const_cast<boolList&>(collocated()) = boolList(1, false);
cyclicPolyPatch.C
rotationAxis (入力値) n0,n1 (計算値)を使って 変換テンソルを計算します.
35
変換テンソルの計算|rotational の場合
Foam::vector Foam::cyclicPolyPatch::findFaceMaxRadius
(
const pointField& faceCentres
) const
{
// Determine a face furthest away from the axis
const vectorField n((faceCentres - rotationCentre_) ^ rotationAxis_);
const scalarField magRadSqr(magSqr(n));
label faceI = findMax(magRadSqr);
if (debug)
{
Info<< "findFaceMaxRadius(const pointField&) : patch: " << name() << nl
<< " rotFace = " << faceI << nl
<< " point = " << faceCentres[faceI] << nl
<< " distance = " << Foam::sqrt(magRadSqr[faceI])
<< endl;
}
return n[faceI];
}
cyclicPolyPatch.C
n0,n1 の計算
36
変換テンソルの計算|unknown の場合
forAll(forwardT_, facei)
{
forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]);
reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]);
}
if (debug)
{
Pout<< " sum(mag(forwardT_ - forwardT_[0])):"
<< sum(mag(forwardT_ - forwardT_[0]))
<< endl;
}
if (sum(mag(forwardT_ - forwardT_[0])) < error)
{
forwardT_.setSize(1);
reverseT_.setSize(1);
collocated_.setSize(1);
if (debug)
{
Pout<< " difference in rotation less than"
<< " local tolerance "
<< error << ". Assuming uniform rotation." << endl;
}
}
coupledPolyPatch.C
ユーザーの入力値は使わず, nr,nf からフェイスごとに 変換テンソルを計算.
各フェイスで計算した 変換テンソルが 一致している場合の処理
37
Chapter 4
cyclicAMI 境界条件に関してもう少し詳しく見ていきます.
38
Chapter 5
cyclicACMI 境界条件に関してもう少し詳しく見ていきます.
39
まずは
この資料を更新するまでは, この境界条件を使用したチュートリアルの紹介資料をご覧ください.
40
Thank You!