simpleFoamで管内流れを計算する際に、入り口と出口の圧力差で境界条件を設定したい場合、通常の静圧を規定する方法だと、うまくいかない場合がある。一方、rasCavitatingFoamでは、静圧でなく全圧(totalPressure)を規定して計算しており、これだとちゃんと計算できていたという経験があったので、これが使えないかと考えたが、simpleFoamでのパラメタファイルの書式がわからない。OF-1.4.1に戻って、FoamXで設定できないかとやってみたが選択メニューに出てこない。
そこであれこれ試行錯誤した方法の記録を残すとともに、FoamXについて考えさせられた点について記しておくことにした。
題材は、simpleFoamのチュートリアルケースpitzDaily を用いた。
デフォルトで速度型(U=10)の入り口条件になっていたところを、まずは、rasCavitatingFoam で使っているパラメタセットを、そのまま(但し、圧力の値だけは変更)の形で動かしてみる。
U
inlet
{
type zeroGradient;
}
p
inlet
{
type totalPressure;
U U;
phi phiv;
rho rho;
psi none;
gamma 1;
p0 uniform 50;
}
【エラーメッセージ抜粋】
request for surfaceScalarField phiv from objectRegistry region0 failed
available objects of type surfaceScalarField are
3
(
weightingFactors
differenceFactors_
phi
)
phiv が駄目で、以下の3つの中から選べ。。。となっている。phiは計算しているはずなので、それを使うこととして、
inlet
{
type totalPressure;
U U;
phi phi;
rho rho;
psi none;
gamma 1;
p0 uniform 40;
}
【エラーメッセージ抜粋】
request for volScalarField rho from objectRegistry region0 failed
available objects of type volScalarField are
6
(
k
p
((Cmu*sqr(k))|(epsilon+epsilonSmall))
pPrevIter
epsilon
nu
)
今度は、rho が駄目と言ってきた。simpleFoamは非圧縮流れなので、rhoは定義されていない。ここはあえて入れるとしたら1という値だが、valueの選択はないようなので困った。しかし、ふと rho の下のパラメタを見れば、
psi none;
というのがあって、おっとこの手があったか。。。で、あとはすんなりでした。
あと、p0の値は、40でなくて、
p=U**2/2 を考えれば50にしてもよさそうなものだが、出口の動圧分(流速)を考えると、50では大きすぎる。あとは微調整といったところでしょうか。
ちなみにOF-1.4.1でもこの方法は、コマンドラインでの実行なら使用可能。但し、FoamX上では使えない。どういうことかというと、simpleFoamのFoamX用configファイルにはtotalPressureの選択可能リストは用意されていないということであり、仮に手作業でファイルの中味を書き換えておいても、FoamX上ではErrorにならないまでも無視されて、所望の計算はしてくれない。
結局、このあたりにもFoamXの限界というか、ほころびがあちこちにあって、FoamXをこれ以上続けることを諦めたんでしょうね。。。
問題は、我々ユーザーにとって、チュートリアルケースにない設定をしたいと考えた時に、上述のような試行錯誤でやる以外の方法はないか?ということですが、、、結局、ソースコードを見るしかない、ということでしょうか。。。
この場合、
/src/finiteVolume/fields/fvPatchFields/derived/totalPressure/totalPressureFvPatchScalarField.C ってのがあって、その中味を見ると。。。
totalPressureFvPatchScalarField::totalPressureFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar , volMesh>& iF,
const dictionary& dict
)
:
fixedValueFvPatchScalarField(p, iF),
UName_(dict.lookup("U")),
phiName_(dict.lookup("phi")),
rhoName_(dict.lookup("rho")),
psiName_(dict.lookup("psi")),
gamma_(readScalar(dict.lookup("gamma"))),
p0_("p0", dict, p.size())
{
if (dict.found("value"))
{
fvPatchField</scalar><scalar>::operator=
(
scalarField("value", dict, p.size())
);
}
else
{
fvPatchField</scalar><scalar>::operator=(p0_);
}
}
(途中省略)
else if (rhoName_ == "none")
{
const fvPatchField</scalar><scalar>& psip =
patch().lookupPatchField<volscalarfield , scalar>(psiName_);
if (gamma_ > 1.0)
{
scalar gM1ByG = (gamma_ – 1.0)/gamma_;
operator==
(
p0_
/pow
(
(1.0 + 0.5*psip*gM1ByG*(1.0 – pos(phip))*magSqr(Up)),
1.0/gM1ByG
)
);
}
else
{
operator==(p0_/(1.0 + 0.5*psip*(1.0 – pos(phip))*magSqr(Up)));
}
}
else if (psiName_ == "none")
{
と、まぁ。。。何となく理解はできるんですがね。ここへたどり着くまでの苦労を考えると、試行錯誤の方がよほど手っ取り早い?
</volscalarfield></scalar>