OpenFOAM 编程笔记

编写代码过程中用到的,或者搜集的一些代码片段。

字典读取变量

在求解器中由于计算需要,要求通过字典文件输入某个值:首先创建字典,然后从这个字典读取数据。
创建一个字典或者使用已有字典:

  • 创建字典:
IOdictionary transportProperties//字典的变量名
(
IOobject
(
"transportProperties",//字典名字
runTime.constant(), //字典位于constant下
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
  • 使用已有字典:
const dictionary& subModelDict = parcels.subModelProperties();//这里要先获取已有的字典
vector position = subModelDict.subDict
(
"injectionModels"
).subDict("model1").lookup("position");
//子字典的用法可以参考这里

然后从这个字典读取数据:

  • 读取 OF 定义的类型,如 dimensionedScalar 等,直接使用lookup 函数:
word fuel(thermo.lookup("fuel"));
dimensionedScalar DT
(
transportProperties.lookup("DT")
);
scalarList Z_param_(flameManDict.lookup("Z_param"));
  • 但是读取标量例外,需要这样用:
scalar Sct = readScalar(transportProperties.lookup("Sct"));

另一个函数 lookupOrdefault 如何使用?
如下:

  • B_(dict.lookupOrDefault("B", 5.5))
  • deltaByR1Min_(coeffDict_.lookupOrDefault<scalar>("deltaByR1Min", 0.0))
  • active_(lookupOrDefault<Switch>("active", true))
  • Cg_(lookupOrDefault<scalar>("Cg", 2.0))

发现一个奇怪的地方:
case文件如下,可以看到D_NaCl需要两个word作为输入。

nu              [0 2 -1 0 0 0 0] 1e-05;
D_NaCl_111 What [0 2 -1 0 0 0 0] 0.01;
dimensionedScalar D_NaCl
(
transportProperties.lookup("D_NaCl_111")
);
Info<<"D_NaCl====="<<D_NaCl<<endl;
//output::::: D_NaCl=====What [0 2 -1 0 0 0 0] 0.01

dimensionedScalar的三个私有数据,分别对应上述输出的三个量。

template<class Type>
class dimensioned
{
// Private data

//- Variable name
word name_;

//- The dimension set
dimensionSet dimensions_;

//- The data value
Type value_;

那么lookup得到了这三个量,然后调用构造函数?

dimensioned(const word&, const dimensionSet&, const Type);

那么 nu 呢?为什么只有 dimension 和 value?

声明

dimensionedScalar nu0_;
volScalarField nu_;

定义

nu0_("nu", dimViscosity, viscosityProperties_),
nu_//nu_ 是用一个 dimensionedScalar 构造出来的。
(
IOobject
(
name,
U_.time().timeName(),
U_.db(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
U_.mesh(),
nu0_
)

读取数据

bool Foam::viscosityModels::Newtonian::read
(
const dictionary& viscosityProperties
)
{
viscosityModel::read(viscosityProperties);
viscosityProperties_.lookup("nu") >> nu0_;
nu_ = nu0_;
//volScalarField = dimensionedScalar 均匀场
return true;
}

那么这里的问题就变成了 nu0_D_NaCl 的区别了,再看一下他们 lookup 的具体函数:

viscosityProperties_.lookup("nu") >> nu0_;
//这里的 `lookup` 获取了 dimension value 两个值
//为什么两个值就够了?

dimensionedScalar D_NaCl
(
transportProperties.lookup("D_NaCl_111")
//这里 `lookup` 得到了 name dimension value 三个值
);

nu_ 输出是这样的:

turbulence.nu=====dimensions      [0 2 -1 0 0 0 0];

internalField uniform 1e-05;

boundaryField
{
movingWall
{
type calculated;
value uniform 1e-05;
}
fixedWalls
{
type calculated;
value uniform 1e-05;
}
frontAndBack
{
type empty;
}
}

所以说,体标量场没有name,只有dimension和值?值分为内部场值和边界值。

对某个量全场求和

使用 functionObject

functions
{
minMax
{
// Type of functionObject
type cellSource;
// Where to load it from (if not already in solver)
functionObjectLibs ("libfieldFunctionObjects.so");
// Function object enabled flag
enabled true;
// Log to output (default: false)
log false;
// Write information to file (default: true)
write true;
location no;
// Fields to be monitored - runTime modifiable
fields (dQ);
//fields (T);
writeControl timeStep;
writeInterval 2;
}
}

强行通过某个 const 接口修改变量:

volScalarField& mu_ = const_cast<volScalarField&>(this->thermo().mu()());

这样就可以修改热物理库中的 mu_ 了。

场的加减乘除操作符,同时包括内部场和边界场的操作。

哪些类有 lookupOrDefault 这个方法?已知的有:

dimensioned<Type>
dictionary中是一个模板函数

用法举例:

  • active_(lookupOrDefault<Switch>("active", true)) 这是在初始化列表中使用,当前类继承自 IOdictionary

  • Cg_(lookupOrDefault<scalar>("Cg", 2.0)) 这是在初始化列表中使用,当前类继承自 IOdictionary

  • const int nNonOrthCorr(dictionary.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0));

  • scalar maxDeltaT(Dict_.lookupOrDefault<scalar>("maxDeltaT", great));

  • B_(Dict_.lookupOrDefault("B", 5.5)) 这里为什么不需要提供模板? B_ 是个 scalar

  • deltaByR1Min_(Dict_.lookupOrDefault<scalar>("deltaByR1Min", 0.0))

  • dimensionedScalar Tmax;
    Tmax(Dict_.subDict("subName").lookup("Tmax")),
    这里需要字典里边给定它的值和量纲,格式如下:
    Tmax Tmax [0 0 0 1 0 0 0] 2800.0;
  • RASModel 的构造函数里边的这个 IOdictionary 是什么用法?这里的 RASModel 是继承自 IOdictionary 的,所以在构造函数的初始化列表里边,需要先初始化基类的成员,然后正是因为继承关系,所以可以直接使用 IOdictionary 里边的 lookup 等函数!

    RASModel::RASModel(...)
    :
    turbulenceModel(rho, U, phi, thermophysicalModel, turbulenceModelName),
    IOdictionary
    (
    IOobject
    (
    "RASProperties",
    U.time().constant(),
    U.db(),
    IOobject::MUST_READ_IF_MODIFIED,
    IOobject::NO_WRITE
    )
    ),
    turbulence_(lookup("turbulence")),
    printCoeffs_(lookupOrDefault<Switch>("printCoeffs", false)),
    coeffDict_(subOrEmptyDict(type + "Coeffs")),
    {}

字典的三种使用方法:

  • 创建字典文件
    CCMProperties
    (
    IOobject
    (
    "CCMProperties",
    this->mesh().time().constant(),
    this->mesh(),
    IOobject::MUST_READ,
    IOobject::NO_WRITE,
    false
    )
    ),
  • 创建某个文件中的字典中的子字典,无须创建,再使用一个 subDict ,如:
    dimensionedScalar Prandtl;
    Prandtl(CCMProperties.subDict("CCM").lookup("Prandtl")),

路径

db().time().rootPath() 当前算例的上级目录。
db().path() 当前运行目录,相当于在运行时执行 pwd 出现的结果。串行时为当前目录,并行时为每一个 processor*,不同的核对应各自的 processor*。
db().time().globalCaseName() 当前算例的文件夹的名字。
db().time().timeName() 是当前时间的字符串。

如果是 collated 模式,则没有 processor* 文件夹,只有 processors+核数这个文件夹,想要输出一个文件到这里,可以这么做:

std::ostringstream nProcs;
nProcs<<Pstream::nProcs();
fileName outputFile(db().time().rootPath()/db().time().globalCaseName()/"processors"+nProcs.str()/db().time().timeName()/+"vortons_"+patch().name());
Info<<"outputFile==="<<outputFile<<endl;
fileName outputFile2(db().time().rootPath()/db().time().globalCaseName()/"processors"+Foam::name(Pstream::nProcs())/db().time().timeName()/+"vortons_"+patch().name());
Info<<"outputFile2==="<<outputFile2<<endl;

上边的outputFile和outputFile2输出相同。

未解之谜

输运方程中的源项,我只需要内部场,边界场应该怎么处理呢?内部场给了矩阵的 source(),边界场应该没有参与计算。

文章作者: Yan Zhang
文章链接: https://openfoam.top/programmingNote/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 OpenFOAM 成长之路
您的肯定会给我更大动力~