今野です。
> しかし,どうもsystem/controlDictのwriteIntervalで指定した時間刻み
> ではなく,毎時間ステップで出力してしまうようで,
> 0.000119904,0.00025673,0.0003475824・・・のようなフォルダがたくさん
> できてしまいます.
コード追加された R.write() は、その時点でのRを出力しますので、時間ステッ
プのループ内に置いた場合には、各時点で出力されてしまいます。
akiさんはRの宣言で、元々 IOobject::AUTO_WRITE と指定しており、
runTime.write() により、writeIntervalで指定した時間刻みで出力されるの
で、R.write() は不要ということになります。
さて、本題の
> の中のfvm::ddt(U) や,fvm::div(phi_, epsilon_),fvm::Sp(fvc::div(phi_),
> epsilon_)
> といった項を各時刻で A,B,Cといったファイルで出力したいのですが,kEpsilon.Cの
> ソースコードをどのように変更すれば良いかわかりません.
ですが、大渕さんの言われる
> それならば、ライブラリのソースを変更せずに、アプリケーションのソースを変更しましょう。
> ライブラリソースに手を加えるのは、サポートされていない境界条件やメッシュ移動など
> 本当に必要な時だけにしましょう。また、手を加えるとしても派生クラスを作る形にして
> 元のソースには手を加えないのが基本ルールです。
はごもっともで、本来そうすべきですが、どうやらpisoFoamとか単体のソルバ
だけで、各項をモニターしたいわけでもないようなので、今回はとりあえずデ
バッグ用ということで、kEpsilonのソースコードを直接いじる方法を説明しま
す。
*出力したい各項(ここではepsilonA,epsilonB,epsilonCとする)をnut同様に
kEpsilonのConstructorsでAUTO_WRITEで宣言します。初期値は各項の計算方法
により与えます(次元と初期値を陽に指定する方法でも良いです)。
例:
epsilonA_
(
IOobject
(
"epsilonA",
runTime_.timeName(),
mesh_,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
fvc::ddt(epsilon_)
),
*epsilonを解いた後で、各項を毎度計算します。
例:
epsilonA_=fvc::ddt(epsilon_);
ここで、epsilonの輸送方程式では fvm::ddt(epsilon_) 等と
fvm::が使われてますが、fvm::は陰解法用にMatrixを作成するので、
volScalarFieldのような陽に決まっている場を求めるには、fvc::に変える必
要があります。
*epsilonA_等の宣言をkEpsilon.Hで行っておく必要があります。
例:
volScalarField epsilonA_;
以下、kEpsilon.[C,H]へのパッチです。
行頭が+の行を+を除いて加えてください。
今野 雅 // IMANO Masashi
--- kEpsilon.C.orig 2010-03-06 14:32:52.000000000 +0900
+++ kEpsilon.C 2010-09-15 10:38:47.000000000 +0900
@@ -126,6 +126,42 @@
IOobject::AUTO_WRITE
),
autoCreateNut("nut", mesh_)
+ ),
+ epsilonA_
+ (
+ IOobject
+ (
+ "epsilonA",
+ runTime_.timeName(),
+ mesh_,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ fvc::ddt(epsilon_)
+ ),
+ epsilonB_
+ (
+ IOobject
+ (
+ "epsilonB",
+ runTime_.timeName(),
+ mesh_,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ fvc::div(phi_, epsilon_)
+ ),
+ epsilonC_
+ (
+ IOobject
+ (
+ "epsilonC",
+ runTime_.timeName(),
+ mesh_,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ fvc::Sp(fvc::div(phi_), epsilon_)
)
{
nut_ = Cmu_*sqr(k_)/(epsilon_ + epsilonSmall_);
@@ -239,6 +275,9 @@
solve(epsEqn);
bound(epsilon_, epsilon0_);
+ epsilonA_=fvc::ddt(epsilon_);
+ epsilonB_=fvc::div(phi_, epsilon_);
+ epsilonC_=fvc::Sp(fvc::div(phi_), epsilon_);
// Turbulent kinetic energy equation
tmp<fvScalarMatrix> kEqn
--- kEpsilon.H.orig 2010-03-06 14:32:52.000000000 +0900
+++ kEpsilon.H 2010-09-15 10:36:53.000000000 +0900
@@ -81,6 +81,9 @@
volScalarField k_;
volScalarField epsilon_;
volScalarField nut_;
+ volScalarField epsilonA_;
+ volScalarField epsilonB_;
+ volScalarField epsilonC_;
public:
返事が遅くなりました。
> 今野さん,
>
> 先日はソースコードの変更方法をお教えくださり,ありがとうございました.
> その後,先日お教え頂いた方法を参考にkEpsilonのソースコードを直接いじってみていますが,
> 一つだけまた疑問点が出てきましたので,質問させて頂きます.
ただ、ディスカッションボードでこのように回答者の指名のような形で書くと、
他の人からの回答が得られにくくなるので、できれば指名していないように書
いたほうが良いと思います。
> ですので,epsilonsum_は常に0になるべきだと思うのですが,実際に出力させてみると,
> その値が0にはなりません.特に,境界付近が0とはかけ離れた値になります.
壁境界付近の epsilon 輸送方程式 epsEqn の残差が0から大きく離れるのは、
壁に隣接する格子では壁関数による境界条件 (epsilonWallFunctions) を用いて、
以下のように epsilon を別途明示的に与えているからだと思います。
src/turbulenceModels/incompressible/RAS/derivedFvPatchFields/wallFunctions/epsilonWallFunctions/epsilonWallFunction/epsilonWallFunctionFvPatchScalarField.C:
void epsilonWallFunctionFvPatchScalarField::updateCoeffs()
:
// Set epsilon and G
forAll(nutw, faceI)
{
label faceCellI = patch().faceCells()[faceI];
scalar yPlus = Cmu25*y[faceI]*sqrt(k[faceCellI])/nuw[faceI];
epsilon[faceCellI] = Cmu75*pow(k[faceCellI], 1.5)/(kappa_*y[faceI]);
また、壁隣接格子以外で0にならないのは以下が原因だと思います。
*epsilon の輸送方程式を離散化した線型一次方程式は、CG法等の反復法で解か
れるが、残差が system/fvSolution の tolerance (絶対誤差の許容量)や
relTol (初期残差からの相対値の許容量) 以下になるように不完全に解かれ
るだけなので、そもそも完全には残差が0にはならない。
epsilon
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-05;
relTol 0.1;
}
*epsilonの輸送方程式を反復法で解いた後に、安定性のために、epsilonを
下限値である epsilon0 以上にする bouding が行なわれるので、それが行なわれた
格子や隣接格子では、残差が増える。
solve(epsEqn);
bound(epsilon_, epsilon0_);