【OpenFOAM用のC++勉強(4)】速度場と圧力場の取得
こんにちは。
OpenFOAM用のC++の勉強のメモを自分のために残しています。
OpenFOAM v2112
前回はメッシュのセルや面、境界に対しての情報を取得するというのをしました。
今回はセルが持つ速度や圧力の情報を取得します。
前回の記事で書いたコードを長くなってきたので必要な部分に絞って書きます。
mainOF.C
#include "argList.H"
#include "fvMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
Info << "================== Create mesh ==================" << endl;
argList args(argc, argv);
#include "createTime.H"
// mesh
fvMesh mesh
(
IOobject
(
fvMesh::defaultRegion,
runTime.timeName(),
runTime,
IOobject::MUST_READ
)
);
Info << "============= volScalarField p ===============" << endl;
// volScalarField typedef=> GeometricField => DimensionedField => Field
// https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1DimensionedField.html
word t_ = "0.5";
volScalarField p
(
IOobject
(
"p",
// runTime.timeName(), // word
t_,
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info << t_ << endl;
vector P_pos(0, 0, 0);
Info << "get p value at P_pos = " << P_pos << endl;
// mesh is fvMesh class.
// fvMesh => polyMesh
/*
Foam::label Foam::polyMesh::findCell
(
const point& p,
const cellDecomposition decompMode
)
*/
label cellPNo = mesh.findCell(P_pos);
const labelList& cellFaces = mesh.cells()[cellPNo]; // face no. list of cell
vector cellCentor = mesh.C()[cellPNo]; // centor cord. of cell fvMesh => polyMesh => primitiveMesh
scalar cellVolume = mesh.V()[cellPNo]; // volume of cell
Info << "cellNo1 = " << cellPNo << endl;
Info << "cellFaces = " << cellFaces << endl;
Info << "cellCentor = " << cellCentor << endl;
Info << "cellVolume = " << cellVolume << endl;
Info << "p" << P_pos << " = " << p[cellPNo] << endl;
Info << "p" << P_pos << " = " << p.ref()[cellPNo] << endl; //https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1GeometricField.html#a77a3ea1ce7e2adc04d27301292b095ae
const dimensionedScalar& p1 = p.internalField()[cellPNo]; // Return a const-reference to the dimensioned internal field.
const scalar& p2 = p.primitiveField()[cellPNo]; // don't have dimension
Info << "p1 = " << p1 << endl;
Info << "p2 = " << p2 << endl;
Info<< "End\n" << endl;
return 0;
}
Make/files
meshOF.C
EXE = $(FOAM_USER_APPBIN)/mesh005
Make/options
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lfiniteVolume
以下のコマンドでコンパイル。
wmake 2>&1 | tee log
※チュートリアルは以下からコピーしてくる。
cp -r /opt/OpenFOAM/OpenFOAM-v2012/tutorials/incompressible/icoFoam/cavity/cavity mycavity
以下のコマンドでmycavityのケースファイルに移動します。
cd mycavity
そしてblockMeshを実行しておきます。
blockMesh
これはメッシュ情報には以下のファイルが必要だからです。
constant/polyMesh/boundary
constant/polyMesh/faces
constant/polyMesh/neighbour
constant/polyMesh/owner
constant/polyMesh/points
そして流速Uや圧力pの情報を取得するには計算を実行しておく必要があります。
icoFoam
では、mycavityの中で以下のmesh005を実行してます。
実行結果は長いのでlog.mesh005に掃き出します。
mesh005 > log.meesh005
log.mesh005
================== Create mesh ==================
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : _7bdb509494-20201222 OPENFOAM=2012
Arch : "LSB;label=32;scalar=64"
Exec : mesh005
Date : Dec 06 2022
Time : 21:09:37
Host : DESKTOP-CT961AV
PID : 2259
I/O : uncollated
Case : /mnt/d/openfoam/20221011_wolf_benchmark/OpenFOAM_Training/OF9/101programming/myWork/mesh005/mycavity
nProcs : 1
trapFpe: Floating point exception trapping enabled (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster (fileModificationSkew 5, maxFileModificationPolls 20)
allowSystemOperations : Allowing user-supplied system call operations
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time
============= volScalarField p ===============
0.5
get p value at P_pos = (0 0 0)
cellNo1 = 0
cellFaces = 6(0 1 780 820 840 1240)
cellCentor = (0.0025 0.0025 0.005)
cellVolume = 2.5e-07
p(0 0 0) = 4.29931e-06
p(0 0 0) = 4.29931e-06
p1 = 4.29931e-06 [0 0 0 0 0 0 0] 4.29931e-06
p2 = 4.29931e-06
End
プログラムの引数情報を渡す
argList のオブジェクトは、mesh005の実行ファイルの実行時に引数を付けて実行した情報をargc, argvを渡して作成するものです。
argList を持つヘッダーファイルは、プログラムの冒頭でインクルードしています。
#include "argList.H"
argListクラスのインスタンス化を行っています。
変数名はargsとしていますが、これはcreateTime.Hで必要なのでそのような名前にしています。
次にメッシュ情報のための記述をしています。
// mesh
fvMesh mesh
(
IOobject
(
fvMesh::defaultRegion,
runTime.timeName(),
runTime,
IOobject::MUST_READ
)
);
メッシュ情報の取得は前回の記事で解説した内容ですね。
ちなみにrunTime.timeName()はwordクラスで文字列を意味しています。
はじめはrunTime.timeName()は0なので初期のメッシュを取得しているという意味です。
これはcreateTime.H内のrunTime関数の返りがFoam::Timeなのでそれを追っていくとtimeName()関数があるので、返ってくる型を確認すればわかります。runTime.timeName()は、wordとなっているので文字列が返ってきます。
圧力場の取得
runTime.timeName()がどの時刻を取得するか(どのファイルを取得するか)を意味するので、word t_ = "0.5";として0.5のファイルから圧力を取得するようにします。
runTime.timeName()をコメントアウトしてword型(文字列)で定義したt_をIOobjectの引数にしました。
word t_ = "0.5";
volScalarField p
(
IOobject
(
"p",
// runTime.timeName(), // word
t_,
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
圧力の取得はまず、座標を指定します。
それにはvector型を使って定義をすれば良いです。
vector P_pos(0, 0, 0);
Info << "get p value at P_pos = " << P_pos << endl;
出力結果は以下のようになっています。
get p value at P_pos = (0 0 0)
座標を指定して、近傍のセルNo.を取得します。
セルNo.は整数なのでOpenFOAM用の整数型であるlabel型で定義します。
label cellPNo = mesh.findCell(P_pos);
ちなみに、findCell()はfvMeshが継承しているpolyMeshのメンバ関数です。
セルNo.が取得できれば圧力はp[セルNo.]とすることで取得できます。
「座標に対応したセルNo.→セルNo.に対応した圧力」という流れですね。
ついでにセル中心の座標や体積も取得しておきます。
const labelList& cellFaces = mesh.cells()[cellPNo]; // face no. list of cell
vector cellCentor = mesh.C()[cellPNo]; // centor cord. of cell fvMesh => polyMesh => primitiveMesh
scalar cellVolume = mesh.V()[cellPNo]; // volume of cell
Info << "cellNo1 = " << cellPNo << endl;
Info << "cellFaces = " << cellFaces << endl;
Info << "cellCentor = " << cellCentor << endl;
Info << "cellVolume = " << cellVolume << endl;
圧力は次元を持った型であるvolScalarFieldです。
volScalarFieldはGemmetricFieldを定義しなおしたものなのでGemmetricFieldクラスのメンバ関数を扱うことができます。
以下のようにp[cellPNo]や p.ref()[cellPNo]とすると値を取得できます。
Info << "p" << P_pos << " = " << p[cellPNo] << endl;
Info << "p" << P_pos << " = " << p.ref()[cellPNo] << endl; //https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1GeometricField.html#a77a3ea1ce7e2adc04d27301292b095ae
またセルでの圧力を取得したい場合は以下のようにします。
const dimensionedScalar& p1 = p.internalField()[cellPNo]; // Return a const-reference to the dimensioned internal field.
const scalar& p2 = p.primitiveField()[cellPNo]; // don't have dimension
Info << "p1 = " << p1 << endl;
Info << "p2 = " << p2 << endl;
internalField()とprimitiveField()はGemmetricFieldが持つメンバ関数で違いは以下のようになります。
internalField():次元を持つ。constなので値を変えれない。
primitiveField():値のみ参照する。値を変更できる。
出力結果は以下のようになります。
p1 = 4.29931e-06 [0 0 0 0 0 0 0] 4.29931e-06
p2 = 4.29931e-06
p1は次元を持っていることがわかります。
でも圧力のdimensionは[0 2 -2 0 0 0 0]のはずなのにおかしいな(*_*;
後で調べるとしてひとまず置いておこう・・・
流速Uの値も出力
圧力の取得方法とほぼ同じです。
流速はベクトルなのでvolVectorField型として定義しておく必要があります。
volVectorFieldもGemmetricFieldなので、GemmetricFieldが持つメンバ関数を使うことができます。
取得する座標は vector U_pos(0.05, 0.05, 0);としておきました。
#include "argList.H"
#include "fvMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
Info << "================== Create mesh ==================" << endl;
argList args(argc, argv);
#include "createTime.H"
// mesh
fvMesh mesh
(
IOobject
(
fvMesh::defaultRegion,
runTime.timeName(),
runTime,
IOobject::MUST_READ
)
);
Info << "runTime.timeName() = " << runTime.timeName() << endl;
Info << "============= volScalarField p ===============" << endl;
// volScalarField typedef=> GeometricField => DimensionedField => Field
// https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1DimensionedField.html
word t_ = "0.5";
volScalarField p
(
IOobject
(
"p",
// runTime.timeName(), // word
t_,
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info << t_ << endl;
vector P_pos(0.05, 0.05, 0);
Info << "get p value at P_pos = " << P_pos << endl;
// mesh is fvMesh class.
// fvMesh => polyMesh
/*
Foam::label Foam::polyMesh::findCell
(
const point& p,
const cellDecomposition decompMode
)
*/
label cellPNo = mesh.findCell(P_pos);
const labelList& cellFaces = mesh.cells()[cellPNo]; // face no. list of cell
vector cellCentor = mesh.C()[cellPNo]; // centor cord. of cell fvMesh => polyMesh => primitiveMesh
scalar cellVolume = mesh.V()[cellPNo]; // volume of cell
Info << "cellNo1 = " << cellPNo << endl;
Info << "cellFaces = " << cellFaces << endl;
Info << "cellCentor = " << cellCentor << endl;
Info << "cellVolume = " << cellVolume << endl;
Info << "p" << P_pos << " = " << p[cellPNo] << endl;
Info << "p" << P_pos << " = " << p.ref()[cellPNo] << endl; //https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1GeometricField.html#a77a3ea1ce7e2adc04d27301292b095ae
const dimensionedScalar& p1 = p.internalField()[cellPNo]; // Return a const-reference to the dimensioned internal field.
const scalar& p2 = p.primitiveField()[cellPNo]; // don't have dimension
Info << "p1 = " << p1 << endl;
Info << "p2 = " << p2 << endl;
Info << "============= volVectorField U ===============" << endl;
volVectorField U
(
IOobject
(
"U",
// runTime.timeName(), // word
t_,
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
vector U_pos(0.05, 0.05, 0);
Info << "get U value at U_pos = " << U_pos << endl;
label cellUNo = mesh.findCell(U_pos);
Info << "U" << U_pos << " = " << U[cellUNo] << endl;
Info << "U" << U_pos << " = " << U.ref()[cellUNo] << endl;
return 0;
}
出力結果は以下のようになります。
================== Create mesh ==================
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : _7bdb509494-20201222 OPENFOAM=2012
Arch : "LSB;label=32;scalar=64"
Exec : mesh005
Date : Dec 06 2022
Time : 22:05:37
Host : DESKTOP-CT961AV
PID : 3076
I/O : uncollated
Case : /mnt/d/openfoam/20221011_wolf_benchmark/OpenFOAM_Training/OF9/101programming/myWork/mesh005/mycavity
nProcs : 1
trapFpe: Floating point exception trapping enabled (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster (fileModificationSkew 5, maxFileModificationPolls 20)
allowSystemOperations : Allowing user-supplied system call operations
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time
runTime.timeName() = 0
============= volScalarField p ===============
0.5
get p value at P_pos = (0.05 0.05 0)
cellNo1 = 189
cellFaces = 6(369 370 1029 1429 331 367)
cellCentor = (0.0475 0.0475 0.005)
cellVolume = 2.5e-07
p(0.05 0.05 0) = -0.00133453
p(0.05 0.05 0) = -0.00133453
p1 = -0.00133453 [0 0 0 0 0 0 0] -0.00133453
p2 = -0.00133453
============= volVectorField U ===============
get U value at U_pos = (0.05 0.05 0)
U(0.05 0.05 0) = (-0.196068 0.0263898 0)
U(0.05 0.05 0) = (-0.196068 0.0263898 0)
以上のように座標からセルNo.を取得すれば、セルNo.からpやUの値を取得することができます。
ちなみにOpenFOAMのコードの中で出てくるforAllはC++の文法というわけではなく、OpenFOAMが独自で定義したforループです。
#define forAll(list, i) \
for (Foam::label i=0; i<(list).size(); ++i)
と定義しています。
まだまだわかっていない部分が多いですが、引き続き勉強します。
参考にしているOpenFOAMの辞書です。
Foundation版をベースにしていますがわからないことはこちらで調べています。
引き続きC++の勉強を続けます。
Twitter➡@t_kun_kamakiri
ブログ➡宇宙に入ったカマキリ(物理ブログ)