About how to use dictionary in openFOAM

This is used to understand a little bit about how to use dictionary functions in OpenFOAM. We won’t dig into the code too much here. I come up with writing this when I read binary.C.

In binary.C

In the constructor of binary.C:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Foam::radiationModels::absorptionEmissionModels::binary::binary
(
const dictionary& dict,
const fvMesh& mesh
)
:
absorptionEmissionModel(dict, mesh),
coeffsDict_(dict.optionalSubDict(typeName + "Coeffs")),
model1_
(
absorptionEmissionModel::New(coeffsDict_.subDict("model1"), mesh)
),
model2_
(
absorptionEmissionModel::New(coeffsDict_.subDict("model2"), mesh)
)
{
//**************************************************************
//Lines below are what I add to help us understand how the dunctions work
cout << "In Binary.C ~~~~~~~~~~~~" << typeName <<'\n';
Info << "In Binary.C ~~~~~~~~~~~~"
<<dict.optionalSubDict(typeName + "Coeffs").subDict("model1") <<'\n';
Info << "In Binary.C ~~~~~~~~~~~~"
<<dict.optionalSubDict(typeName + "Coeffs").subDict("model2") <<'\n';
const word modelType(dict.optionalSubDict(typeName + "Coeffs").subDict("model1").subDict("constantCoeffs").lookup("boyao"));
cout << "zhangzixin" << modelType << '\n';
//*************************************************************
}

Besides talking about the use of the dictionary class functions, here, I also want to share some idea about the Macro called TypeName(). It is defined in typeInfo.H:

1
2
3
4
//- Declare a ClassName() with extra virtual type info
#define TypeName(TypeNameString) \
ClassName(TypeNameString); \
virtual const word& type() const { return typeName; }

You can also easily find out that ClassName is another Macro which is defined in className.H. In className.H:

1
2
3
#define ClassName(TypeNameString)                                              \
ClassNameNoDebug(TypeNameString); \
static int debug

and

1
2
3
#define ClassNameNoDebug(TypeNameString)                                       \
static const char* typeName_() { return TypeNameString; } \
static const ::Foam::word typeName

Then we know how typeName is defined. Let’s go back to our initial aim to see how to use dictionary’s functions. There are 2 functions that we have used here, which are optionalSubDict() and subDict(). Firstly, we found that in optionalSubDict(typeName + "Coeffs") we use a + operator. This + operator can combine 2 words object, which is the same as defined in original C++ string class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Foam::dictionary& Foam::dictionary::optionalSubDict
(
const word& keyword
) const
{
const entry* entryPtr = lookupEntryPtr(keyword, false, true);

if (entryPtr)
{
return entryPtr->dict();
}
else
{
return *this;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
{
const entry* entryPtr = lookupEntryPtr(keyword, false, true);

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

It can be seen that, if entryPtr is not a null pointer, both optionalSubDict and subDict will return entryPtr->dict(). So, they have no big difference if the pointer is not a null pointer. To illustrate how the subDict works, I list part of the radiationProperties file here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
absorptionEmissionModel binary;

binaryCoeffs
{
model1
{
absorptionEmissionModel constant;
constantCoeffs
{
absorptivity 0.5;
emissivity 0.5;
E 0;
boyao zixin;
boyao1 gouzi;
}
}
model2
{
absorptionEmissionModel cloud;
cloudCoeffs
{
cloudNames
(
coalCloud1
limestoneCloud1
);
}
}
}

If dict.optionalSubDict(typeName + "Coeffs") (typeName is binary here, typeName + "Coeffs" is equivalent to binaryCoeffs) is called, we will go into the block:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
binaryCoeffs
{
model1
{
absorptionEmissionModel constant;
constantCoeffs
{
absorptivity 0.5;
emissivity 0.5;
E 0;
boyao zixin;
boyao1 gouzi;
}
}
model2
{
absorptionEmissionModel cloud;
cloudCoeffs
{
cloudNames
(
coalCloud1
limestoneCloud1
);
}
}
}

And if we call optionalSubDict(typeName + "Coeffs").subDict("model1"), we will go to block:

1
2
3
4
5
6
7
8
9
10
11
12
model1
{
absorptionEmissionModel constant;
constantCoeffs
{
absorptivity 0.5;
emissivity 0.5;
E 0;
boyao zixin;
boyao1 gouzi;
}
}

So, now you know how we go through the radiationProperties file. Finally, if you want to look up for a certain “model” on a certain line with a “mark” behind. You can use the lookup function. For example I add two lines at the bottom of the constantCoeffs block. If I call:

1
const word modelType(dict.optionalSubDict(typeName + "Coeffs").subDict("model1").subDict("constantCoeffs").lookup("boyao"));

modelType will be assigned with a string of zixin.