前編はこちらです。
fvSolution
solvers
{
"p.*|pa.*"
{
solver PCG;
preconditioner DIC;
tolerance 1e-9;
relTol 0.01;
};
"m|ma"
{
solver PCG;
preconditioner DIC;
tolerance 1e-9;
relTol 0.01;
};
"U.*|Ua.*|nuTilda.*|nuaTilda.*|yWall|da"
{
solver PBiCGStab;
preconditioner DILU;
tolerance 1e-9;
relTol 0.1;
}
}
relaxationFactors
{
fields
{
"p.*" 0.3;
"pa.*" 0.3;
}
equations
{
"U.*" 0.7;
"Ua.*" 0.7;
"nuTilda.*" 0.7;
"nuaTilda.*" 0.7;
"yWall.*" 0.5;
"da.*" 0.7;
}
}
solvers と relaxationFactors に「pa」「Ua」「ma」のような adjoint 系の値を追加する。
一般的には、「”p.*|pa.*”」のようにして primal 変数とそれに対応する adjoint 変数は同じ線形ソルバーを用いて解く。
「multi-point runs」を行っているときは、ワイルドカードが使える。
緩和係数である relaxationFactors の設定では、 primal 変数と adjoint 変数で逆の値を使う設定がよく用いられる。
例えば、(p 0.3; U 0.7;) に対して、 (pa 0.7; Ua 0.3;) にするというようなものだ。
また、 adjoint 乱流変数に対する緩和係数 は 0.1 程度の小さい値に設定した方が良い場合がしばしばある。
da の 緩和係数は 0.5 程度が用いられ、 ma には緩和係数は必要ない。
fvSchemes
gradSchemes
{
gradUATC cellLimited Gauss linear 1;
gradUaATC cellLimited Gauss linear 1;
}
gradSchemes は ATC 項に含まれる勾配項を解くのに使う。
cellLimited スキームは工業的な問題を解く場合に使い、より単純な問題を解くときには limited ではないスキームを使うことができる。
divSchemes
{
div(-phi,Ua) bounded Gauss linearUpwind gradUaConv;
div(-phi,nuaTilda) bounded Gauss linearUpwind gradNuaTildaConv;
div(-yPhi,da) Gauss linearUpwind gradDaConv;
}
divSchemes は、 adjoint 方程式の平均流や乱流の移流項を解くのに使われる。
div(-phi, adjointField) と指定する。
発散しやすい問題では、 Gauss upwind のような一次元のスキームを用いると良い。
laplacianSchemes
{
default Gauss linear corrected;
}
laplacianSchemes で defalut として与えるスキームは、ラプラス演算子を含むグリッド変位の離散化だけでなく、拡散項の離散化にも使える。
primal ソルバーでも adjoint ソルバーでも useSolverNameForFields を true にしているときには、fvSchemes、特に divSchemes で場の名前が適当なものになっているかどうかに注意する必要がある。
また、 primal ソルバーの設定で average を true にした場合、離散化スキームを設定するときに div(-phi, Ua) の代わりに div(-phiMean, Ua) としなくてはならない。
adjointRASProperties
「constant」フォルダの中にある「adjointRASProperties」で使用する adjoint 乱流モデルを定義できる。
adjointRASModel adjointSpalartAllmaras;
- adjointRASModel : adjointLaminar もしくは adjointSpalartAllmaras から選択する。「凍結乱流」とみなして簡易化する場合には、adjointLaminar を使い、Spalart Allmaras 乱流もでるを用いて adjoint 方程式を解く場合には adjointSpalartAllmaras を使う。その際、境界条件、ソルバー、緩和係数、離散化スキームの設定に「nuaTilda」を追加する必要がある。
adjointTurbulence on;
- adjointTurbulence : 乱流モデルを解く際に adjoint 法を使うかどうか。使わないときは off にする。
adjointSpalartAllmarasCoeffs
{
nSmooth 0;
zeroATCPatchTypes (wall);
maskType faceCells;
}
- adjointSpalartAllmarasCoeffs : adjointRASModel を adjointSpalartAllmaras にしたときのみ必要。ATC モデルの設定と同じく、発散しやすい項を滑らかにする設定を行う。
Adjoint 境界条件
「0」のような開始時間の名前のフォルダの中にある各変数名のファイルには境界条件を記入する必要がある。
基本的には primal ソルバーの変数で用いられる境界条件をここでも使えば良いが、それ以外に設定する項目があるものを以下に記載する。
また、 slip、symmetry、symmetryPlane、cyclic のような特殊な境界条件を用いる場合には primal 場と同じものを対応する adjoint 場の境界条件に設定しなくてはいけない。
Ua
adjoint 速度の境界条件の設定。
- adjointInletVelocity : U に
fixedValue
が、 p にzeroGradient
が設定されている inlet - adjointOutletVelocity : U に
zeroGradient
が、 p にfixedValue
が設定されている outlet - adjointOutletVelocityFlux : U に
zeroGradient
が、 p にfixedValue
が設定されている outlet でなおかつ outlet 部分で逆流が観測される場合 - adjointWallVelocity : U に
fixedValue
が、 p にzeroGradient
が設定されている壁境界。高レイノルズ数の乱流モデルを解く nut にnutUSpaldingWallFunction
が設定されているときには自動的に適用される。 - adjointWallVelocityLowRe : 低レイノルズ数もしくは層流を解くときの U に
fixedValue
が、 p にzeroGradient
が設定されている壁境界 - adjointFarFieldVelocity : inletOutlet もしくは
freestream
が U に設定されている遠方境界
pa
adjoint 圧力の境界条件の設定。
- zeroGradient : U に
fixedValue
が、 p にzeroGradient
が設定されている inlet もしくは壁境界 - adjointOutletPressure : U に
zeroGradient
が、 p にfixedValue
が設定されている outlet - adjointFarFieldPressure : outletInlet が p に設定されている遠方境界
nuaTilda
adjoint 乱流モデルの境界条件の設定。
- adjointInletNuaTilda : nuTilda に
fixedValue
が設定されている inlet - adjointOutletNuaTilda : nuTilda に
zeroGradient
が設定されている outlet - adjointOutletNuaTildaFlux : nuTilda に
zeroGradient
が設定されている outlet でなおかつ outlet 部分で逆流が観測される場合 - fixedValue : 壁境界
- adjointFarFieldNuaTilda : inletOutlet もしくは freestream が nuTilda に設定されている遠方境界
ma
adjoint グリッド変位の境界条件の設定。
もし足りない項目がある場合には自動生成される。
- fixedValue uniform 0 : 指定のないものすべて
da
adjoint 距離の境界条件の設定。
もし足りない項目がある場合には自動生成される。
- fixedValue uniform 0 : inlet / outlet
- zeroGradient : 壁境界
Applications
solvers
adjointOptimisationFoam
現在は simgleRun モードしか使えないが、そのうち自動的な形状最適化もできるようになるらしい。
adjoint 方程式も解けるということを除いては、 simpleFoam とほぼ同じ計算をしている。
optimistionDict で nIter が指定されているときには、 controlDict の entTime は無視され、 nIter だけ反復して計算を終了させる。
active が true になっている すべての primal ソルバーは adjoint ソルバーに続いて計算を行い、最終的に computeSensitivities が true になっている adjoint ソルバーが感度係数を計算する。
residualControl で設定した残差に収まるか、 nIter 反復に達するまで計算は繰り返される。
終了時には、controlDict で設定した writeInterval に応じて primal ソルバーと adjoint ソルバーが結果を書き出す。
primal ソルバーの計算中、 adjoint ソルバーに定められている目的関数の値が計算され、「optimisation/objective/timeName/objectiveName+Instant+adjointSolverName」に書き出される。
utilities
computeSensitivities
計算中に感度を計算していなかった場合、ポスト処理の段階で、computeSensitivities を用いて計算することができる。
2020/12/13 -
[…] https://www.shirokurohitsuji.studio/2020/08/02/adjointoptimisationfoam-usermanual/ […]