本文演示在OpenFOAM中自定义库的基本过程。
有时候为了数据封装的需要,可以将特殊的代码先编译成库,然后在其他的代码中对库加以调用。本案例演示此过程。
1 文件准备
这里将库文件、功能文件以及测试文件分开。所有的文件都放置在run文件夹下。
使用下面的命令创建文件结构。
run
mkdir demo7 && cd demo7
mkdir customLibrary && cd customLibrary
mkdir Make
touch customLibrary.H customLibrary.C
touch Make/files Make/options
cd ..
foamNewApp demo7
创建完毕后的文件结构如下所示。
2 库的定义与编译
-
修改 customLibrary/Make/files
文件
customLibrary.C
LIB = $(FOAM_USER_LIBBIN)/libcustomLibrary
注意这里不再是之前案例的EXE
了,而是换成了LIB
。
-
修改 customLibrary/Make/options
文件
EXE_INC =
-I$(LIB_SRC)/finiteVolume/lnInclude
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS =
-lfiniteVolume
-lmeshTools
-
修改头文件 customLibrary/customLibrary.H
#include "fvCFD.H"
// 在头文件中声明函数
scalar computeR(const fvMesh &mesh,volScalarField & r, dimensionedVector x0);
void computeU(const fvMesh & mesh, volVectorField &U, word pname="p");
头文件中只是声明了两个函数。
-
修改源文件 customLibrary/customLibrary.C
#include "customLibrary.H"
// 这两个函数之前的案例中使用过,就不重复介绍了
scalar computeR(const fvMesh &mesh,volScalarField &r, dimensionedVector x0)
{
r = mag(mesh.C()-x0);
return returnReduce(max(r).value(),maxOp());
}
void computeU(const fvMesh &mesh, volVectorField &U,word pName)
{
const volScalarField &pField = mesh.lookupObject(pName);
U = fvc::grad(pField)*dimensionedScalar("tmp",dimTime,1.0);
}
所有文件修改完毕后,进入customLibrary
路径下,执行命令wmake
进行编译。
可以看到在$FOAM_USER_LIBBIN
路径下生成了一个名为libcustomLibrary.so
的动态库文件。
3 功能程序定义
进入demo7
目录下。利用命令touch createFields.H
创建文件,此时demo7文件夹中的文件结构如下:
-
修改 files
文件
demo7.C
EXE = demo7
-
修改 options
文件,注意编译为库的话指定的是EXE_LIBS
,还要注意包含头文件
EXE_INC =
-I$(LIB_SRC)/finiteVolume/lnInclude
-I$(LIB_SRC)/meshTools/lnInclude
-I../customLibrary
EXE_LIBS =
-lfiniteVolume
-lmeshTools
-L$(FOAM_USER_LIBBIN) -lcustomLibrary
注意库文件的加载,先加载路径后加载库名称,把库名称前面的lib去掉。
-
编写 createFields.H
头文件
// createFields.H中包含了各种参数及物理场的读入
Info << "读取tranportProperties文件n" << endl;
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
dimensionedScalar nu
(
"nu",
dimViscosity,
transportProperties
);
Info << "读取p文件"<< endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info << "读取U文件" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
-
编写源代码 demo7.C
#include "fvCFD.H"
// 注意文件路径
#include "../customLibrary/customLibrary.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
// 添加两个头文件,一个创建fvMesh对象,另一个读取数据
#include "createMesh.H"
#include "createFields.H"
// 定义一个向量x0,其量纲为dimLength
const dimensionedVector originVector("x0", dimLength, vector(0.05, 0.05, 0.005));
scalar f(1.0);
// 定义一个标量场r,给了一个初始值r0
volScalarField r(
IOobject(
"r",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE),
mesh,
dimensionedScalar("r0", dimLength, 0.0));
// 利用自定义库中的computeR函数
const scalar rFaceCell = computeR(mesh, r, originVector);
Info << "Starting time loopn" << endl;
while (runTime.loop())
{
Info << "Time = " << runTime.timeName() << nl << endl;
// 利用网格距离进行压力计算,没什么特别的意义,只是随便计算
// 场变量计算的时候需要注意量纲
p = Foam::sin(2. * constant::mathematical::pi * f * runTime.time().value()) /
(r / rFaceCell + dimensionedScalar("small", dimLength, 1e-12)) *
dimensionedScalar("tmp", dimensionSet(0, 3, -2, 0, 0), 1.0);
p.correctBoundaryConditions();
// 利用自定义库中的computeU函数计算速度
computeU(mesh, U);
runTime.write();
}
// * * * * * * * * * * * * * * * * * * * //
Info << nl;
runTime.printExecutionTime(Info);
Info << "Endn" << endl;
return 0;
}
代码编写完毕后,可以使用wmake
进行编译。
4 测试案例
利用cavity案例作为测试案例。将cavity案例拷贝到run/demo7
文件夹下。
cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity .
注意demo7文件夹下的子文件夹组织形式,如下图所示。
当前目录为run/demo7
,利用下面的命令进入cavity目录,生成网格并调用上面编译成功的程序。
cd cavity
blockMesh
../demo7/demo7
修改system/controlDict
文件中endTime
关键字的值为2
,设置deltaT
为0.1
。
执行结果如下图所示。
压力场如下图所示。
(本文结束)
本篇文章来源于微信公众号: CFD之道
评论前必须登录!
注册