OpenFOAM 中的字典

无摘要

常见用法

创建 IOdictionary

IOdictionary transportProperties//字典的变量名
(
IOobject
(
"transportProperties",//字典名字
runTime.constant(), //字典位于constant下
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);

创建字典并不是创建文件!
如果想自定义路径呢?可以把 runTime.constant() 改成 "./Properties"。这样的话,我们就需要在当前算例目录下新建一个文件夹 Properties,文件夹里需要有一个文件 transportProperties。该文件还必须包含文件头(header):

FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object thermophysicalProperties;
}

里边的信息可以随意,比如 location 仍然写 constant 也没关系。

使用已有 IOdictionary

const dictionary& subModelDict = parcels.subModelProperties();//这里获取已有的字典
vector position = subModelDict.subDict("injectionModels").subDict("model1").lookup("position");
//subDict 是子字典

这里的 parcels.subModelProperties()SprayCloudProperties 中的 subModels

const wordList fuelList(thermo.subDict("liquids").keys());

这里的 thermothermophysicalProperties

通过字典读取变量

word fuel(dict.lookup("fuel"));
dimensionedScalar DT(dict.lookup("DT"));
scalarList Z_param(dict.lookup("Z_param"));
scalar Sct = readScalar(dict.lookup("Sct"));
label int_a=readLabel(dict.lookup("int_a"));
Switch flagg(dict.lookup("flagg"));

另外还可以给定默认值,即 lookupOrdefault 函数:

word fuel2(dict.lookupOrDefault("fuel2",fuel));
dimensionedScalar DT2(dict.lookupOrDefault("DT2",DT));
scalarList Z_param2(dict.lookupOrDefault("Z_param2",Z_param));
scalar Sct2 = dict.lookupOrDefault("Sct2", 9.);
label int_a2(dict.lookupOrDefault("int_a2", 25));
Switch flagg2(dict.lookupOrDefault("flagg2",false));

//或者:
word fuel3(dict.lookupOrDefault<word>("fuel3",fuel));
dimensionedScalar DT3(dict.lookupOrDefault<dimensionedScalar>("DT3",DT));
scalarList Z_param3(dict.lookupOrDefault<scalarList>("Z_param3",Z_param));
scalar Sct3 = dict.lookupOrDefault<scalar>("Sct3", 9.);
Switch flagg3(dict.lookupOrDefault<Switch>("flagg3",false));
label int_a3(dict.lookupOrDefault<label>("int_a3", 35));

算例文件:

fuel ZY.3;// word 中允许有 点 ?
DT DT [0 2 -1 0 0 0 0] 1e-05;
//Z_param (0 0.2 1); //OK
//Z_param 3(0 0.2 1); //OK too
Z_param 101{0}; //OK too
Sct 10.2;
flagg true; //expected 'true/false', 'on/off'

Sct2 10.8;

如果重复给定,那么最后边的那个会起作用。

给定一个全是 0 的多维数组:

zeroList
21
{
308
{
101{0}
}
}
;

看一下这两个函数的代码,发现 lookup 返回的是 ITstream,而 lookupOrDefault 返回的是它的模板类型。
疑问:

  • 为什么需要 readScalar 才能使用 lookup 读取标量?可能是因为 ITstream 无法隐式的转换成 scalar
  • 为什么 lookupOrDefault 不给定模板也可以呢?因为它的第二个参数的类型就是模板的类型啊。
ITstream& lookup(const word&,bool recursive=false,bool patternMatch=true) const;

Foam::ITstream& Foam::dictionary::lookup
(
const word& keyword,
bool recursive,
bool patternMatch
) const
{
return lookupEntry(keyword, recursive, patternMatch).stream();
}

const Foam::entry& Foam::dictionary::lookupEntry
(
const word& keyword,
bool recursive,
bool patternMatch
) const
{
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);

if (entryPtr == nullptr)
{
FatalIOErrorInFunction
(
*this
) << "keyword " << keyword << " is undefined in dictionary "
<< name()
<< exit(FatalIOError);
}

return *entryPtr;
}


template<class T>T lookupOrDefault(const word&,const T&,bool recursive=false,bool patternMatch=true) const;

template<class T>
T Foam::dictionary::lookupOrDefault
(
const word& keyword,
const T& deflt,
bool recursive,
bool patternMatch
) const
{
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);

if (entryPtr)
{
return pTraits<T>(entryPtr->stream());
}
else
{
if (writeOptionalEntries)
{
IOInfoInFunction(*this)
<< "Optional entry '" << keyword << "' is not present,"
<< " returning the default value '" << deflt << "'"
<< endl;
}

return deflt;
}
}


const Foam::entry* Foam::dictionary::lookupEntryPtr
(
const word& keyword,
bool recursive,
bool patternMatch
) const
{
HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);

if (iter == hashedEntries_.end())
{
if (patternMatch && patternEntries_.size())
{
DLList<entry*>::const_iterator wcLink =
patternEntries_.begin();
DLList<autoPtr<regExp>>::const_iterator reLink =
patternRegexps_.begin();

// Find in patterns using regular expressions only
if (findInPatterns(patternMatch, keyword, wcLink, reLink))
{
return wcLink();
}
}

if (recursive && &parent_ != &dictionary::null)
{
return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
}
else
{
return nullptr;
}
}

return iter();
}

代码解析

一些函数探秘

算例里的文件片段:

RanzMarshallCoeffs
{
BirdCorrection true;
}

代码:

const dictionary& subModelDict = parcels.subModelProperties().subDict("RanzMarshallCoeffs");
Info<<"RanzMarshallCoeffs.toc()==="<<subModelDict.toc()<<endl;
Info<<"RanzMarshallCoeffs.keys()==="<<subModelDict.keys()<<endl;

输出:

RanzMarshallCoeffs.toc()===1(BirdCorrection)
RanzMarshallCoeffs.keys()===1(BirdCorrection)

算例里的文件片段:

liquids
{
C7H16
{
defaultCoeffs yes;
}
IC8H18
{
defaultCoeffs yes;
}
}

代码:

const wordList fuelList(thermo.subDict("liquids").keys());
const wordList fuelCoeff1(thermo.subDict("liquids").subDict("C7H16").keys());
Info<<"fuelList==="<<fuelList<<endl;
Info<<"fuelCoeff1==="<<fuelCoeff1<<endl;

输出:

fuelList===
2
(
C7H16
IC8H18
)

fuelCoeff1===1(defaultCoeffs)

算例里的文件片段:

Cd   constant 0.88;

其实这里的 Cd 是读取给一个 TimeFunction1<scalar> 的类型。
这里我们强行读取后边的标量:

scalar Cd_ = 0.;
token firstToken(modelDict.lookup("Cd")[1]);
//这里 lookup 得到一个list,我们取[1],即后边的 0.88
if (firstToken.isScalar())
{
Cd_ = firstToken.scalarToken();
}

其实“更”正确的用法是:

TimeFunction1<scalar> Cd2_(mesh.time(),"Cd");
Cd2_.reset(modelDict);
Info<<"Cd2_==="<<Cd2_.value(0.)<<endl;
scalar Cd_ = Cd2_.value(0.);

算例里的文件片段:

37 liquids
38 {
39 C7H16
40 {
41 defaultCoeffs yes;
42 }
43 IC8H18
44 {
45 defaultCoeffs yes;
46 }
47 }

代码:

Info<<"thermo.subDict(liquids).subDict(C7H16).parent()==="<<thermo.subDict("liquids").subDict("C7H16").parent()<<endl;
Info<<"thermo.subDict(liquids).topDict()==="<<thermo.subDict("liquids").topDict()<<endl;
Info<<"thermo.subDict(liquids).startLineNumber()==="<<thermo.subDict("liquids").startLineNumber()<<endl;
Info<<"thermo.subDict(liquids).endLineNumber()==="<<thermo.subDict("liquids").endLineNumber()<<endl;
Info<<"thermo.subDict(liquids).tokens()==="<<thermo.subDict("liquids").tokens()<<endl;
Info<<"thermo.subDict(liquids).toc()==="<<thermo.subDict("liquids").toc()<<endl;

输出:
parent 返回的是上一级字典。
topDict 返回的是最顶层的字典。

thermo.subDict(liquids).startLineNumber()===41
thermo.subDict(liquids).endLineNumber()===45
thermo.subDict(liquids).tokens()===
12
(
C7H16
{
defaultCoeffs
yes
;
}
IC8H18
{
defaultCoeffs
yes
;
}
)

thermo.subDict(liquids).toc()===
2
(
C7H16
IC8H18
)

tokens 就是这个字典中的所有元素,这里有 12 个元素,包括字符串和标点符号。
tockeys 一样的?他们的定义如下:

Foam::wordList Foam::dictionary::toc() const
{
wordList keys(size());

label nKeys = 0;
forAllConstIter(IDLList<entry>, *this, iter)
{
keys[nKeys++] = iter().keyword();
}

return keys;
}

Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns=false) const
{
List<keyType> keys(size());

label nKeys = 0;
forAllConstIter(IDLList<entry>, *this, iter)
{
if (iter().keyword().isPattern() ? patterns : !patterns)
{
keys[nKeys++] = iter().keyword();
}
}
keys.setSize(nKeys);

return keys;
}
文章作者: Yan Zhang
文章链接: https://openfoam.top/dictionary/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 OpenFOAM 成长之路
微信打赏给博主更多动力吧~