CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Accessing specie data in OF2.2 (https://www.cfd-online.com/Forums/openfoam-programming-development/117010-accessing-specie-data-of2-2-a.html)

hanness April 30, 2013 10:00

Accessing specie data in OF2.2
 
Hi,

I want to write a new boundary condition for which I have to access specie data (specific gas constant). I added #include "specie.H" at the top of the myBC.C and tried to get the data with specie::R() but obviously that does not work. During compilation I get the following:

error: cannot call member function āFoam::scalar Foam::specie::R() constā without object

Can anybody tell me how it can be done?

Thanks a lot
Hannes

wyldckat May 1, 2013 15:44

Greetings Hannes,

I've finished just now writing a post on how to calculate entropy, which requires direct access to the full thermodynamic model that was chosen in the file "constant/thermophysicalProperties". It's this thread: Entropy calculation in OpenFoam - specifically the post #11. You better read the whole post very carefully, because it can get a bit confusing!

Now, in case you're wondering how exactly you're going to access the "R()" method from the species in question, you'll see the following code in "entropy.C":
Code:

S[celli] =
      thermo.cellMixture(celli).S(thermo.p()[celli], thermo.T()[celli]);

Change it to:
Code:

Rfield[celli] = thermo.cellMixture(celli).R();
Where "Rfield" is the field you can create if you want to.

For the patches, you can change:
Code:

pS[facei] =
      thermo.patchFaceMixture(patchi, facei).S(pp[facei], pT[facei]);

to:
Code:

pRfield[facei] =
      thermo.patchFaceMixture(patchi, facei).R();

Where "pRfield" is the patch field for the "Rfield".

And there you have it! If you have questions about this, please ask it here on your thread, so that things don't get very confusing on the other thread...

Best regards,
Bruno

hanness May 2, 2013 03:27

Hi Bruno,

this seems to be a powerful tool. However, to me it seems a little bit too complex as in my simulation there is only one fluid (namely air) and thus the specific gas constant does not change and could be calculated by use of the molar mass which is given in the thermophysicalProperties file. As far as I understand this is done in the specieI.H which is called from specie.H. So, is there really no easy way to access those constants?

Best regards
Hannes

wyldckat May 2, 2013 07:56

Hi Hannes,

This was an interesting exercise :D

OK, so here are the steps that need to be taken:
  1. You need to include the header file "specie.H", possibly in your ".C" file:
    Code:

    #include "specie.H"
  2. Since we're including this file, edit the file "Make/options" and add the following line to the "EXE_INC" entry:
    Code:

        -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
    In my case, it looks like this:
    Code:

    EXE_INC = \
        -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
        -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
        -I$(LIB_SRC)/finiteVolume/lnInclude

    edit: forgot to give the "EXE_LIBS" part:
    Code:

    EXE_LIBS = \
        -lmeshTools \
        -lfluidThermophysicalModels \
        -lspecie \
        -lfiniteVolume \
        -lgenericPatchFields

  3. Now, this part depends on how things are working up to the point where you need to calculate "R". We need to get access to the "thermophysicalProperties" dictionary somehow and there are two possibilities:
    1. If the dictionary is already in memory, we can access it with:
      Code:

      const dictionary& thermoProps =
              mesh.lookupObject<basicThermo>("thermophysicalProperties");

      Where "mesh" can also be "mesh_", in case you're coding inside a boundary condition.
      • Note: this might require that you also include the "basicThermo.H" header file:
        Code:

        #include "basicThermo.H"
        Along with the respective inclusion of the path shown above for ".../basic/lnInclude" in the "Make/options" file.
    2. If the dictionary isn't loaded into memory, you'll need to load it locally with the following code:
      Code:

          IOdictionary thermoProps
          (
              IOobject
              (
                  "thermophysicalProperties",
                  mesh.time().constant(),
                  mesh,
                  IOobject::MUST_READ_IF_MODIFIED,
                  IOobject::NO_WRITE
              )
          );

  4. Now that we have access to the dictionary, we need to create an instance of the class "specie" with the right dictionary part, like this:
    Code:

    specie theSpecie(thermoProps.subDict("mixture"));
  5. Now you can use "theSpecie" as you need, such as:
    Code:

    theSpecie.R()
And there you have it, another less contrived way of getting specie data! :D

Best regards,
Bruno

hanness May 2, 2013 09:54

Hi Bruno,

thanks a lot - that's exactly what I've been looking for.
I had to load the dictionary according to your description 3.2 and additionally I had to locally define the mesh:
Code:

const fvMesh& mesh_ = patch().boundaryMesh().mesh();
and now it works!

Best regards,
Hannes

hanness May 6, 2013 03:44

Hi,

unfortunately I still got a small problem with the code.
The boundary condition works perfectly, but whenever "libmyBCs.so" is loaded (whether for blockMesh or decomposePar etc.) I get a warning:
Code:

Create time
--> FOAM Warning :
    From function dlOpen(const fileName&, const bool)
    in file POSIX.C at line 1179
    dlopen error : /home/hs/OpenFOAM/hs-2.2.0/platforms/linux64GccDPOpt/lib/libmyBCs.so: undefined symbol: _ZN4Foam6specie2RRE
--> FOAM Warning :
    From function dlLibraryTable::open(const fileName&, const bool)
    in file db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C at line 99
    could not load "libmyBCs.so"

As I said, running the solver is not a problem - everything is there.
The problem occurs as soon as the call to
Code:

theSpecie.R()
appears in the
Code:

operator==...
in updateCoeffs. Defining a new scalar and giving it the value of theSpecie.R() is no problem either. Am I missing something in the Make/options or so?

Thanks a lot
Hannes

wyldckat May 6, 2013 17:01

Hi Hannes,

I've edited my previous post. I had forgotten to mention the dependency on "libspecie.so", which is added in "Make/options":
Code:

EXE_LIBS = \
[...]
    -lspecie \
[...]

See the previous post for the complete content of the one I used.

Best regards,
Bruno

hanness May 7, 2013 09:59

Hi Bruno,

unfortunately it still does not work. I tried the reference to lspecie before but since the boundary condition does what it is supposed to without putting anything in the Make/options I'm not quite sure what happens.
Currently the files looks like that:
Code:

EXE_INC = \
    -I$(LIB_SRC)/finiteVolume/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude
EXE_LIBS = \
    -lmeshTools \
    -lfluidThermophysicalModels \
    -lspecie \
    -lfiniteVolume \
    -lgenericPatchFields \
    -L$(FOAM_USER_LIBBIN) \
    -lmyBCs

but that is more or less trial and error. For the sake of completeness, my Make/files looks like that:
Code:

totalPressureRGHFvPatchScalarField.C
LIB = $(FOAM_USER_LIBBIN)/libmyBCs

Do you have any idea? I'm really appreciating your help - thanks a lot!

Hannes

ngj May 7, 2013 10:37

Hi Hannes,

You said that it goes wrong, when you are trying to use

Code:

operator==<something with theSpecies.R()>
but it works, if you call

Code:

scalar R = theSpecies.R();
operator==<the same something with R>

is that correctly understood? And the problem first occurs, when you execute the program and not during compilation?

Well, I would like you to put the following in the command line, before you are running your program:

Code:

export FOAM_ABORT=1
In this way you are getting a lot more information on the reason for the crash, why you/we can do better diagnostics.

Kind regards

Niels

wyldckat May 7, 2013 16:42

Greetings to all!

@Hannes: There is something very strange going on... Niels is probably right, but I still suspect something very strange is going on ;) Here's why:
Quote:

Originally Posted by hanness (Post 425849)
Code:

EXE_INC = \
    -I$(LIB_SRC)/finiteVolume/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude
EXE_LIBS = \
    -lmeshTools \
    -lfluidThermophysicalModels \
    -lspecie \
    -lfiniteVolume \
    -lgenericPatchFields \
    -L$(FOAM_USER_LIBBIN) \
    -lmyBCs


This code above is located inside a file named "Make/options". Problem is that from what I'm seeing, it looks like this file is part of a custom solver, not part of the library "libmyBCs.so". I say this because if this file is part of "myBCs" folder, then it is self-referencing; in other words, it depends on itself! And in theory, it would load itself infinitely, if it weren't for the load-only-once strategy that usually library loaders usually follow...

So, just for the sake of making sure that something strange doesn't happen later on, edit the file "myBCs/Make/options" to look something like this:
Code:

EXE_INC = \
    -I$(LIB_SRC)/finiteVolume/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude

EXE_LIBS = \
    -lmeshTools \
    -lfluidThermophysicalModels \
    -lspecie \
    -lfiniteVolume \
    -lgenericPatchFields

Best regards,
Bruno

hanness May 8, 2013 02:41

Hi,

@Bruno:
I found the reference to itself in some of the other posts so that's why I tried it, but basically I don't know what I have to include in the Make/options EXE_LIBS part. The behaviour is the same whether I include nothing or whether I include the libraries as supposed in your posts.

@Niels:
Probably I've been a little bit unclear so far. It compiles without error (code below) and when using the boundary condition the behaviour is as wanted - no problems with the solver, no error (and no warning!) during solver run. I only get the warning when any of the additional tools is used (blockMesh, mapFields, wallHeatFlux, yPlusRAS, ...) which does not affect the results - it is just annoying because I don't understand the reason for it. That's why I don't get any additional output when setting FOAM_ABORT=1

Concerning your second question, this
Quote:

Code:

scalar R = theSpecies.R();
operator==<the same something with R>


is unfortunately not a solution. I hoped that it would work but apparently not the value of the scalar is given to R but the pointer to theSpecies.R(). What works is to call theSpecies.R but not use it in the operator - but that is sort of meaningless because then I don't need it at all.
Code:

scalar R = theSpecies.R();
operator==<something with 287.0>

Is it possible to give the value of theSpecie.R() to some other scalar instead of the pointer?

So as mentioned above here my compiler output:
Code:

hs@Computer:~/OpenFOAM/hs-2.2.0/src/finiteVolume/fields/fvPatchFields/derived/totalPressureRGH> wmake libso
wmakeLnInclude: linking include files to ./lnInclude
SOURCE=totalPressureRGHFvPatchScalarField.C ;  g++ -m64 -Dlinux64 -DWM_DP -Wall -Wextra -Wno-unused-parameter -Wold-style-cast -Wnon-virtual-dtor -O3  -DNoRepository -ftemplate-depth-100 -I/opt/OpenFOAM-2.2.0/src/finiteVolume/lnInclude -I/opt/OpenFOAM-2.2.0/src/thermophysicalModels/basic/lnInclude -I/opt/OpenFOAM-2.2.0/src/thermophysicalModels/specie/lnInclude -IlnInclude -I. -I/opt/OpenFOAM-2.2.0/src/OpenFOAM/lnInclude -I/opt/OpenFOAM-2.2.0/src/OSspecific/POSIX/lnInclude  -fPIC -c $SOURCE -o Make/linux64GccDPOpt/totalPressureRGHFvPatchScalarField.o
'/home/hs/OpenFOAM/hs-2.2.0/platforms/linux64GccDPOpt/lib/libmyBCs.so' is up to date.

What really surprises me is that apparently everything is working fine (compilation and solver run) and the warning only appears when toole are used which do not really need the boundary condition.

Best regards
Hannes

ngj May 8, 2013 03:09

Good morning,

Quote:

I hoped that it would work but apparently not the value of the scalar is given to R but the pointer to theSpecies.R().
This is a bit weird. I have been looking in the source code and it is clear as day. Are you allowed to post the entire boundary condition here on the Forum, so we can have a look in the correct context? This would make it easier.

With respect to the warning, when you use blockMesh, you should not be bothered with that. My understanding of this warning is: Since blockMesh is not compiled with thermo* libraries, then it does not know how to handle the linking to these libraries are thereby your libmyBCs.so.

Kind regards

Niels

hanness May 8, 2013 11:14

1 Attachment(s)
Hi Niels,

I attached the entire BC. Basically it's the same as totalPressure but reduced to a single case with a given pressure profile for p_rgh.

Thanks
Hannes

ngj May 8, 2013 11:47

Hi Hannes,

I have had a look on the code, and there is only one detail, which bothers me. But first a question: "Are the thermophysicalProperties defined in the solver as well?".

If yes:
By construction of the thermoProps you add a second dictionary with the same name to the object registry, however, one of these will be deleted when going out of scope. This might give rise to some nasty problems.
Therefore, I suggest that you do the following instead, and see if this helps:

Code:

// Reference to the sub-dictionary called mixture
const dictionary & subDictThermo = mesh_.thisDb().lookupObject<dictionary>("thermophysicalProperties").subDict("mixture");

// Construct your species
specie theSpecie( subDictThermo );

You might already have tried this, but what happens, when you put the following in the code and execute it:
Code:

const scalar RM = theSpecie.R();

Info << "Reading RM: " << tab << RM << tab << theSpecie.R() << endl;

It should give the same output, but one never knows...

Furthermore, a small note on the readability of the source code, then the underscore ("_") after the variable name is by convention reserved to variables, which belong to the class itself. A variable defined inside a scope in one of the methods in the class should be without underscore. Thus in this case:

Code:

const scalar RM_ = theSpecie.R(); // Wrong / unconventional
const scalar RM  = theSpecie.R(); // Conventional / correct

Kind regards

Niels

hanness May 9, 2013 10:07

Hi Niels,

thanks again for your input. I changed the code according to your suggestions and I'm sort of surprised that it compiles and runs because your approach seems to be very similar to the one suggested by Bruno in his second post in this thread:
Quote:

Code:

const dictionary& thermoProps =
        mesh.lookupObject<basicThermo>("thermophysicalProperties");


This code did not work so I went for Brunos second suggestion and constructed the dictionary.

Now referring directly to the subdictionary works, however, the behaviour remains the same - the boundary condition compiles and runs, but the warnings are still there. I think I'll just live with those (ugly) warnings.

Concerning your suggestion to write out the values of RM and theSpecie.R() - they are indeed the same.

Best regards,
Hannes

ngj May 9, 2013 10:22

Congrats:) It is nice to hear that you sorted it out.

Happy Foaming,

Niels

P.S. Yes, forget about the warnings; they are merely warnings.

Elinka September 23, 2020 09:11

Greetings to all!
I'm trying to calculate the strainrate function inside my transport model located in the specie/transport folder and need to call the velocity field.
Could you be so kind to give me some tips how to call the volVectorField U from the specie folder (if it's possible in OpenFOAM)? Maybe I can do it somehow using objectRegistry function?
Kind regards,
Elina


All times are GMT -4. The time now is 22:29.