Weitere ähnliche Inhalte Mehr von Fumiya Nozaki (11) Kürzlich hochgeladen (11) OpenFOAM の cyclic、cyclicAMI、cyclicACMI 条件について2. 2
はじめに
この資料では,
• cyclic
• cyclicAMI
• cyclicACMI
の3つの境界条件について取り扱います.
この資料を通して,ここでしっかり区別して使い分けできるようになりま
しょう!自分も含めて!
名前が似ていてとても紛らわしい (;^_^A
15. 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. 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. 17
“transform” のタイプ
“transform” のタイプは,次の5つから選択できます.
• rotational
これが, に対応しています.
• translational
これが, に対応しています.
• noOrdering
これが, に対応しています.
• unknown
• coincidentFullMatch
次のページからそれぞれの設定を見ていきます.
周期境界条件ー回転ー
周期境界条件ー並進ー
隣接する境界
調査中
調査中
18. 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. 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. 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. 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” の記
述例はこちら.
25. 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 となります.
27. 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. 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. 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. 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. 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” 境界条件を使用した計算が
うまく実行できない場合には,フェ
イスの対応が正しいかどうかこの方
法で確認できます.
ペアのフェイスの可視化
34. 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. 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. 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 からフェイスごとに
変換テンソルを計算.
各フェイスで計算した
変換テンソルが
一致している場合の処理