Understanding the source code for an OpenFOAM solver (CFD)

In summary: VOF interface.In summary, the argList::addNote function adds a comment to the end of an argList object.
  • #1
JD_PM
1,131
158
TL;DR Summary
I am going through the C++ code for interPhaseChangeFoam, which is a solver in OpenFOAM and I got some questions
I am trying to understand the following code (it starts from line 59) and there are pieces I do not understand.

Code:
argList::addNote
 (
        "Solver for two incompressible, isothermal immiscible fluids with"
         " phase-change.\n"
         "Uses VOF (volume of fluid) phase-fraction based interface capturing."
     );

What does argList::addNote do, just add a comment?

Code:
 Info<< "\nStarting time loop\n" << endl

My guess is that the above sets the time of the while loop coming next but not sure.

Code:
++runTime; 
Info<< "Time = " << runTime.timeName() << nl << endl;

Regarding the first line, I do not know what ++ does. The structure of the second line is the same than the previous question I asked.

Code:
Info<< "End\n" << endl

It seems that it finishes what Info<< "\nStarting time loop\n" << endl started but not sure.Your time is appreciated.

Thank you :smile:
 
Technology news on Phys.org
  • #2
The ++ operator just adds one to the runTime objects value.

The info object refers to a printable output log so the info << prints a text msg with a newline character ie \n character. It appears to work like the more common cout object.
 
  • Like
Likes JD_PM and sysprog
  • #3
JD_PM said:
What does argList::addNote do, just add a comment?
It looks to me like addNote is just a member of the argList class, that consists of the string inside the braces.
jedishrfu said:
The info object refers to a printable output log so the info << prints a text msg with a newline character ie \n character. It appears to work like the more common cout object.
Info<< "Time = " << runTime.timeName() << nl << endl; doesn't really print anything. Instead, the << operator (stream insertion operator) inserts the string shown above into the stream named Info. Presumably Info previously has been opened as an output stream, likely for logging purposes as you said. Anything written to this stream likely ends up in a file, rather than being displayed on the console, the usual output device for the cout stream.
 
  • Like
Likes JD_PM and sysprog
  • #5
jedishrfu said:
The ++ operator just adds one to the runTime objects value.

This would be true if runTime were a scalar, however given the context:

JD_PM said:
Code:
++runTime;
Info<< "Time = " << runTime.timeName() << nl << endl;

It seems that runTime is an instance of a class so a more complete answer is "the ++ operator does whatever is implemented in the class's operator++() function. Normally this would be an action which increments a value by 1".

I would guess that runTime is in fact an instance of OpenFoam's Time class, and Time::operator++() does quite a lot of things, including calling setTime(value() + deltaT_, timeIndex_ + 1); which I guess adds deltaT_ to the time value and increments timeIndex by 1.
 
  • Like
Likes JD_PM
  • #6
JD_PM said:
Regarding the first line, I do not know what ++ does.

bigfooted said:
Before diving into openfoam, you have to know C++.
@JD_PM, if you're uncertain about what the ++ operator does in general, then I completely agree with the reply by @bigfooted. I don't know your programming skills, so possibly your question is more about the specific context of the statement ++runTime;.
 
  • Like
Likes JD_PM
  • #7
To add to the confusion: ++a means increment a before you use a, a++ means use a and then increment a.
My favourite c expression (an exercise in compact statements) is:
This code is explicit, but you must read carefully:
while (dest++=src++);
 
  • Like
Likes JD_PM
  • #8
First off, let me thank you all for the helpful replies.

bigfooted said:
Before diving into openfoam, you have to know C++. Here are some basic tutorial websites:

https://www.cplusplus.com/doc/tutorial/
https://www.w3schools.com/cpp/cpp_intro.asp

I know the basics of python but I am new to C++, so I indeed need to learn the basics. I chose to follow
the first of the tutorials above (I covered Introduction and basics of C++).

jedishrfu said:
The ++ operator just adds one to the runTime objects value.
Svein said:
To add to the confusion: ++a means increment a before you use a, a++ means use a and then increment a.

OK, now the basics of the increment operator ++ are clear to me (after studying Increment and decrement (++, --) on the tutorial). Actually, as @Svein mentioned, ++ operator can be used both as a prefix and as a suffix.

pbuk said:
Given the context, it seems that runTime is an instance of a class so a more complete answer is "the ++ operator does whatever is implemented in the class's operator++() function. Normally this would be an action which increments a value by 1".

I would guess that runTime is in fact an instance of OpenFoam's Time class, and Time::operator++() does quite a lot of things, including calling setTime(value() + deltaT_, timeIndex_ + 1); which I guess adds deltaT_ to the time value and increments timeIndex by 1.

That's a helpful insight. Please notice you're looking at the OpenFOAM foundation branch C++ source code, and I shared a solver from ESI-OpenCFD branch and they do not necessarily have the same code for the same solver (look at #6 here). So let us stick to ESI-OpenCFD branch C++ source code.

Code:
  Info << "\nStarting time loop\n" << endl;
while (runTime.run())
          {
               #include "readTimeControls.H"
               #include "CourantNo.H"
               #include "setDeltaT.H"
   
               ++runTime;
   
               Info<< "Time = " << runTime.timeName() << nl << endl;
               // stuff
            }

I think what the above code does (let's not dive into what the directives read by the preprocessor do) is first send the string "\nStarting time loop\n" into the file Info and second, ++runTime adds a unity to runTime.timeName() while runTime.run() is running. So once the while loop is done, I would expect to find in the Info file "Time = X", where X is the total running program time (here's the definition of runTime variable). Do you all agree?

Btw, what does nl do?

JD_PM said:
Code:
Info<< "End\n" << endl

After checking the tutorial, the above makes sense :)

Now I am trying to understand what the code piece 101-111 does. I will go further later, just posting already in case you guys want to add insight :biggrin:
 
  • #9
JD_PM said:
and second, ++runTime adds a unity to runTime.timeName() while runTime.run() is running.
No, there are several misconceptions here. ++runTime increments runTime, which appears to be an instance of some class. Incrementing a variable does not necessarily mean that 1 is added, particularly if the variable is a pointer of some kind. I looked at the code in the link you provided in post #1, but not deeply enough to find a definition for this variable. The expression runTime.timeName() is a call to a function named timeName(), so it doesn't make sense to say that you are incrementing this function.

"while runTime.run() is running." -- The while loop executes if runTime.run() returns any nonzero value.
JD_PM said:
Btw, what does nl do?
No idea without seeing how it's defined. If I had to hazard a guess, though, it might be shorthand for new line; i.e., the same character as '\n'. My guess is based on the code below that you showed in post #1.

Info<< "End\n" << endl
This mixes up two different idioms for inserting a new line character at the end of a string: '\n' and endl. '\n' is the symbol for a new line, used mostly in C code. endl is used in C++.
 
Last edited:
  • Like
Likes jedishrfu and JD_PM
  • #10
Let me add I now understand what :: means (it's the scope resolution operator)

Mark44 said:
It looks to me like addNote is just a member of the argList class, that consists of the string inside the braces.

An analogous example is std::cout (where cout is just a member of the std class).
Mark44 said:
No, there are several misconceptions here. ++runTime increments runTime, which appears to be an instance of some class. I looked at the code in the link you provided in post #1, but not deeply enough to find a definition for this variable.

I tried to look for more info about the variable (here and here) and it seems to be related to the function runTimePtr(), which I am reading further to see what it does.
Mark44 said:
No idea without seeing how it's defined. If I had to hazard a guess, though, it might be shorthand for new line; i.e., the same character as '\n'. My guess is based on the code below that you showed in post #1.

Mmm. I think it is a n1 function; if I find out more I'll share.

Mark44 said:
This mixes up two different idioms for inserting a new line character at the end of a string: '\n' and endl. '\n' is the symbol for a new line, used mostly in C code. endl is used in C++.

Then should not be written either Info<< "End\n" ; or Info<< "End" << endl;?
 
  • #11
Mark44 said:
I looked at the code in the link you provided in post #1, but not deeply enough to find a definition for this variable.

See
pbuk said:
I would guess that runTime is in fact an instance of OpenFoam's Time class, and Time::operator++() does quite a lot of things, including calling setTime(value() + deltaT_, timeIndex_ + 1); which I guess adds deltaT_ to the time value and increments timeIndex by 1.
 
  • #12
JD_PM said:
Then should not be written either Info<< "End\n" ; or Info<< "End" << endl;?

They presumably wanted a blank line after the message. Note that <stream> << "\n" (which is the same as <stream> << nl) is not the same as <stream> << endl; the latter flushes the stream after sending an EOL character. Depending on how the stream class is implemented this may be significant - in this case as the stream appears to be a log it may prefix the message with 'Info:' (as opposed to 'Debug' or 'Error' etc.) and a timestamp and write it to a file, which you obviously only want to do once for each message.
 
Last edited:
  • Informative
Likes JD_PM
  • #13
JD_PM said:
An analogous example is std::cout (where cout is just a member of the std class).
Technically, std is a namespace, not a class.
JD_PM said:
Mmm. I think it is a n1 function; if I find out more I'll share.
No. As alluded to by @pbuk earlier, it's almost certainly shorthand for newline. In the code you provided, there is a tool tip link that says this is a constexpr of type char that is defined in Ostream.H at line 404.
pbuk said:
See
(referring to the definition of runTime) -- I saw your earlier post, but forgot that I had seen it. Doh!
 
Last edited:
  • Like
Likes JD_PM and pbuk
  • #14
JD_PM said:
Now I am trying to understand what the code piece 101-111 does. I will go further later, just posting already in case you guys want to add insight :biggrin:

Let me write the piece of code explicitly

Code:
// --- Pressure-velocity PIMPLE corrector loop
         while (pimple.loop())
         {
             #include "alphaControls.H"
  
             surfaceScalarField rhoPhi
             (
                 IOobject
                 (
                     "rhoPhi",
                     runTime.timeName(),
                     mesh
                 ),
                 mesh,
                 dimensionedScalar(dimMass/dimTime, Zero)
             );
  
             mixture->correct();
  
             #include "alphaEqnSubCycle.H"
             interface.correct();
  
             #include "UEqn.H"

This is what I learned so far about it. Please feel free do comment/correct :)

1) What's surfaceScalarField? It's not a function (because it doesn't have its structure: a type, a name and a pair of parentheses). It is a namespace and rhoPhi is just the variable declared in it.

rhoPhi, as a local variable, is defined here.

The best I could find about what it does is the following "A surfaceScalarField is defined on the faces of the mesh [...] Face ordering is defined by the faces file in polyMesh. For each of the faces, you can get the owner/neigbour cell info by asking the mesh. In surfaceScalarFields, the internal faces belong to the internalField() and patch fields are done in the usual way. Note the limitations on the patch field types: you cannot have, say, a zeroGradient patch field on the surfaceScalarField [...]." (for more see this link, specially #3).

2) What's IOobject? It's a class OK. More precisely, it's a class member function (i.e. a function that has its definition within the class definition like any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object). This function contains within the parenthesis: "rhoPhi" which is a string, a call to timeName() function and the variable mesh.

What does it mean in the given context? I still didn't figure it out.

3) What's mesh? It's a variable and I understand its general purpose.

4) What's dimensionedScalar? It seems to be a function. This function contains within the parenthesis: dimMass, dimTime and Zero, all variables.

What does it mean in the given context? I still didn't figure it out.
 
  • #15
The following are my best guesses, based on my read of the documentation (which is pretty poor IMO):
JD_PM said:
1) What's surfaceScalarField? It's not a function (because it doesn't have its structure: a type, a name and a pair of parentheses). It is a namespace and rhoPhi is just the variable declared in it.
Best guess is that surfaceScalarField is a class, and rhoPhi is an instance of that class. The parenthesized block initializes that instance with an IOobject, a mesh, and a dimensionedScalar.
I've spent quite a bit of time trying to find things in the documentation you linked to, but was unable to find a definition for surfaceScalarField. Finding things is very difficult, which is why I consider these docs to be very poor. A better choice for finding out information would be to look at the header files, such as alphacontrols.H and the other two listed in the sample.
JD_PM said:
rhoPhi, as a local variable, is defined here.
No, that isn't a definition of rhoPhi, despite what the documentation says. It's a variable that is assigned a value: namely
rhoPhi = rhoEqn.flux()
A definition would include the type of this variable.
JD_PM said:
2) What's IOobject? It's a class OK. More precisely, it's a class member function (i.e. a function that has its definition within the class definition like any other variable.
IOobject is a class, and IOobject(...) is one of six constructors, some of which are copy constructors. The constructors and a destructor are documented here: https://www.openfoam.com/documentat...object.html#a7cb85f8a9438cd905612df50f89a3dae
JD_PM said:
What does it mean in the given context? I still didn't figure it out.
In the code example you provided, it looks to me like "rhoPhi" is a name for the IOobject instance, runTime.timeName() is a filename (my guess), and mesh is a reference to a polyMesh. The constructors and a destructor are documented here: https://www.openfoam.com/documentat...object.html#a7cb85f8a9438cd905612df50f89a3dae
 
  • Love
Likes JD_PM

FAQ: Understanding the source code for an OpenFOAM solver (CFD)

What is OpenFOAM and why is it used for CFD simulations?

OpenFOAM is an open-source computational fluid dynamics (CFD) software package that allows for the simulation of fluid flow and other related phenomena. It is used for CFD simulations because it is highly customizable and offers a wide range of solvers and physical models, making it suitable for various applications in engineering, science, and research.

How do I access the source code for an OpenFOAM solver?

The source code for all OpenFOAM solvers can be found on the official OpenFOAM website, as well as on various online repositories such as GitHub. You can also access the source code directly through the OpenFOAM software, as it is open-source and freely available to users.

What programming language is used for writing OpenFOAM solvers?

The majority of OpenFOAM solvers are written in C++, a high-level programming language that is known for its efficiency and versatility in handling complex mathematical operations. However, some solvers may also use other languages such as Fortran or Python for specific functions.

Can I modify the source code for an OpenFOAM solver?

Yes, the source code for OpenFOAM solvers is open-source, which means that it can be freely modified and redistributed. However, it is important to note that any modifications made to the source code may affect the accuracy and reliability of the simulations, so it is recommended to have a thorough understanding of the code before making any changes.

How can I improve my understanding of the source code for an OpenFOAM solver?

There are several resources available for learning about the source code of OpenFOAM solvers, including documentation, tutorials, and online forums. It is also helpful to have a strong background in C++ programming and numerical methods, as well as prior experience with CFD simulations.

Similar threads

Back
Top