CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (http://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Read properties per component from an input file dictionary (http://www.cfd-online.com/Forums/openfoam-programming-development/85049-read-properties-per-component-input-file-dictionary.html)

Cyp February 16, 2011 06:21

Read properties per component from an input file dictionary
 
Hi!

For my application (multicomponent mixture) I would like to read some properties (such as molecular diffusion, dispersion tensor, partionning coefficient...) from an input file.

For example, this file will have the following form:

Code:

O2
(
    H      H  [0 0 0 0 0 0] 1.3;
    D      D  [0 2 -1 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5)
)

N2
(
    H      H  [0 0 0 0 0 0] 5.3;
    D      D  [0 2 -1 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5)
)

CH4
(
    H      H  [0 0 0 0 0 0] 1.1;
    D      D  [0 2 -1 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5)
)

I can't see how can I do this. I would really appreciate any help.

Best regards,
Cyp

MartinB February 16, 2011 10:35

Hi Cyp,

if you can change your data format to
Code:

/*--------------------------------*- C++ -*----------------------------------*\
| =========                |                                                |
| \\      /  F ield        | OpenFOAM: The Open Source CFD Toolbox          |
|  \\    /  O peration    | Version:  1.6                                  |
|  \\  /    A nd          | Web:      www.OpenFOAM.org                      |
|    \\/    M anipulation  |                                                |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version    2.0;
    format      ascii;
    class      dictionary;
    location    "constant";
    object      values;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

species
(
  O2
  N2
  CH4
);

O2
{
    H      H  [0 0 0 0 0 0 0] 1.3;
    D      D  [0 2 -1 0 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5);
}

N2
{
    H      H  [0 0 0 0 0 0 0] 5.3;
    D      D  [0 2 -1 0 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5);
}

CH4
{
    H      H  [0 0 0 0 0 0 0] 1.1;
    D      D  [0 2 -1 0 0 0 0] 1e-5;
    DD  DD [0 2 -1 0 0 0 0] (1.e-5 0 0 0 1.4e-5 0 0 0 1.e-5);
};

with the file named "values", located in "constant", then this ugly piece of code can read the data:

Code:

    IOdictionary speciesDict
    (
        IOobject
        (
            "values",    // dictionary name
            runTime.constant(),    // dict is found in "constant"
            mesh,                  // registry for the dict
            IOobject::MUST_READ,    // must exist, otherwise failure
            IOobject::NO_WRITE      // dict is only read by the solver
        )
    );
    wordList speciesNamesCyp
    (
        speciesDict.lookup("species")
    );
    forAll(speciesNamesCyp, s)
    {
        word currentSpecie = speciesNamesCyp[s];
        Info<< "Doing stuff for specie: " << currentSpecie << endl;

        const dictionary& subDict = speciesDict.subDict(currentSpecie);
        dimensionedScalar H_("H", dimensionSet(0,0,0,0,0,0,0), scalar(0.0));
        dimensionedScalar D_("D", dimensionSet(0,2,-1,0,0,0,0), scalar(0.0));
        dimensionedTensor DD_("DD", dimensionSet(0,2,-1,0,0,0,0), tensor(0.0));
        H_ = subDict.lookup("H");
        D_ = subDict.lookup("D");
        DD_ = subDict.lookup("DD");
        Info<< "H = " << H_ << endl;
        Info<< "D = " << D_ << endl;
        Info<< "DD = " << DD_ << endl;
    }

May I ask: are you using the multiComponentMixture class, or just the basicMultiComponentMixture class?

Martin

olesen February 17, 2011 04:22

Martin provides a good solution. If you drop the extra "species" entry you can simply retrieve the species names from the dictionary .toc() method.

Code:

    const wordList specieNames(speciesDict.toc());
 
    forAll(specieNames, i)
    {
        const word& specieName = specieNames[i];
        ...
    }


Cyp February 17, 2011 08:35

Hello Martin and Mark!

Thank you very much for your quick answer!


Martin> Once again you help me much!! For the moment I just use basicMultiComponentMixture class. What are the differences with the multiComponentMixture class ??


I have another question: how can I store DD_, H_, D_ in a list and call DD[i], H[i], D[i] in my solver ?


Best regards,
Cyp

olesen February 21, 2011 04:24

Quote:

Originally Posted by Cyp (Post 295698)
...
I have another question: how can I store DD_, H_, D_ in a list and call DD, H, D in my solver ?

Without actually knowing what you want, this might be a solution (as untested pseudo-code):

Code:

    const wordList specieNames(speciesDict.toc());
 
    List<dimensionedScalar> Hval(specieNames.size());
    List<dimensionedScalar> Dval(specieNames.size());
    List<dimensionedScalar> DDval(specieNames.size());
 
    forAll(specieNames, i)
    {
        const word& specieName = specieNames[i];
        const dictionary& subDict = speciesDict.subDict(specieName);
 
        Hval[i] = dimensionedScalar(subDict.lookup("H"));
        Dval[i] = dimensionedScalar(subDict.lookup("D"));
        DDval[i] = dimensionedScalar(subDict.lookup("DD"));
    }

Try it and see if it does what you need.

Cyp February 21, 2011 05:21

Hello,

What I want is to defined some transport properties (H, D) for each component. Your solution seems to be close to what I am looking for. However, I get a compiling error. Indeed
Code:

List<dimensionedScalar> Hval(specieNames.size());
doesn't compile. So I tried PtrList<> instead of List<>. It succeeded in compiling but failed when I run the program with the following error message:
Code:

--> FOAM FATAL ERROR:
hanging pointer, cannot dereference

    From function PtrList::operator[]
    in file /gemp/csoulain/OpenFOAM/OpenFOAM-1.7.0/src/OpenFOAM/lnInclude/PtrListI.H at line 122.

FOAM aborting

#0  Foam::error::printStack(Foam::Ostream&) in "/gemp/csoulain/OpenFOAM/OpenFOAM-1.7.0/lib/linux64GccDPOpt/libOpenFOAM.so"
#1  Foam::error::abort() in "/gemp/csoulain/OpenFOAM/OpenFOAM-1.7.0/lib/linux64GccDPOpt/libOpenFOAM.so"
#2  main in "/gemp/csoulain/OpenFOAM/csoulain-1.7.0/applications/bin/linux64GccDPOpt/impesMultiComponentFoam"
#3  __libc_start_main in "/lib64/libc.so.6"
#4  _start at /usr/src/packages/BUILD/glibc-2.10.1/csu/../sysdeps/x86_64/elf/start.S:116
Abandon

Do I have any idea ? I think I need to specify a constructor with "List<dimensionedScalar> Hval(specieNames.size());" but I don't know which one..

Regards,
Cyp

olesen February 21, 2011 05:52

Quote:

Originally Posted by Cyp (Post 296209)
However, I get a compiling error. Indeed
Code:

List<dimensionedScalar> Hval(specieNames.size());
doesn't compile.

Sorry, as I wrote, it was 'untested' code. But you are right - it cannot compile since dimensionedType doesn't have a null constructor. I'd suggest you file an RFE for that. I can't offhand expect any side-effects for adding a null constructor.

Quote:

Originally Posted by Cyp (Post 296209)
So I tried PtrList<> instead of List<>.

If you use PtrList, you definitely need the .set() method for assignment.
This is also untested, but should work without a segfault I think.

Code:

    const wordList specieNames(speciesDict.toc());
 
    PtrList<dimensionedScalar> Hval(specieNames.size());
    PtrList<dimensionedScalar> Dval(specieNames.size());
    PtrList<dimensionedScalar> DDval(specieNames.size());
 
    forAll(specieNames, i)
    {
        const word& specieName = specieNames[i];
        const dictionary& subDict = speciesDict.subDict(specieName);
 
        Hval.set
        (
            i,
            new dimensionedScalar(subDict.lookup("H"))
        );
        Dval.set
        (
            i,
            new dimensionedScalar(subDict.lookup("D"))
        );
        DDval.set
        (
            i,
            new dimensionedScalar(subDict.lookup("DD"))
        );
    }


Cyp February 21, 2011 06:47

It perfectly works !! Thank you very much!!

rudolf.hellmuth September 10, 2012 09:50

Thanks for the solutions!

I was wondering how to get information from a list of subdictionaries like that:

Code:

speciesList
(
    A
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }

    B
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }
       
);

Any idea how to do that?
I tried:
Code:

    IOdictionary solutionProperties
    (
      IOobject
      (
        "solutionProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ_IF_MODIFIED,
        IOobject::NO_WRITE
      )
    );
    List<dictionary> speciesList(solutionProperties.lookup("speciesList"));

which returned this error:
Code:

--> FOAM FATAL IO ERROR:
attempt to read beyond EOF


blaise August 14, 2013 08:36

List of subdictionaries
 
Hi Rudolf,

did you find the solution to your problem with the list of subdirectories? If so, could you share it here? I have exactly the same problem.

Thanks,

Pascal.

mkraposhin August 14, 2013 13:10

Quote:

Originally Posted by rudolf.hellmuth (Post 381061)
Thanks for the solutions!

I was wondering how to get information from a list of subdictionaries like that:

Code:

speciesList
(
    A
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }

    B
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }
       
);

Any idea how to do that?
I tried:
Code:

    IOdictionary solutionProperties
    (
      IOobject
      (
        "solutionProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ_IF_MODIFIED,
        IOobject::NO_WRITE
      )
    );
    List<dictionary> speciesList(solutionProperties.lookup("speciesList"));

which returned this error:
Code:

--> FOAM FATAL IO ERROR:
attempt to read beyond EOF


You can go by alternate way:
1) Use dictionary '{' instead of list '(':
Code:

speciesList
{
    A
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }

    B
    {
        diffusionModel  constant;
        D          D          [0 2 -1 0 0 0 0] 0.00005;
        molarMass  molarMass  [1 0 0 0 -1 0 0] 2;
    }
       
};

2) Loop over all sub-dictionaries in this dictionary:
Code:

    IOdictionary solutionProperties
    (
      IOobject
      (
        "solutionProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ_IF_MODIFIED,
        IOobject::NO_WRITE
      )
    );
    speciesDict = solutionProperites.subDict("speciesList");
    wordList speciesDictToc = speciesDict.toc();
    forAll (speciesDictToc, iToc)
    {
      const dictionary& specDict =
                                  speciesDict.subDict(speciesDictToc[iToc]);
      // read and manipulate with data
    }


mkraposhin August 14, 2013 13:29

Another good example for your problem is OF file: functionObjectList.C

Example how to read list of dictionaries you can find here:
src/postProcessing/functionObjects/field/fieldAverage/fieldAverage/fieldAverage.C
src/postProcessing/functionObjects/field/fieldAverage/fieldAverageItem/fieldAverageItem.C

blaise August 16, 2013 05:52

Solution: Reading list of subdictionaries
 
Hello Matvej,

thanks for your reply! After quite a struggle (as a beginner in OF programming) I found this solution to read a list of subdictionaries, which I post here for the benefit of other fellow strugglers ;-):

(Sorry, I do not know how to insert code properly)

Assuming a properties dictionary file containing this:

Props
(
firstEntry
{
prop1 (1 0 0);
prop2 (6.12 5.0 -5.78);
prop3 3.5;
}

secondEntry
{
prop1 (1 0 0);
prop2 (5.12 0.0 -5.78);
prop3 2.3;
}
);

(This is a list of dictionaries on the top level of the dictionary file).

In the main function I use this code:

#include "IOdictionary.H"
#include "dictionaryEntry.H"

const word dictName("myDictFile");

IOobject myDictIO
(
dictName,
runTime.system(),
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
);

IOdictionary myDict(myDictIO);

const entry* entryPtr_ = myDict.lookupEntryPtr
(
"Props",
false,
false
);

// The PtrList contains pointers to the entries of the list. Each element of this list is of type <entry> (surprise, surprise), and this entry is a dictionary.
PtrList<entry> propDictsList(entryPtr_->stream());
// propDict is the dictionary to hold the respective list element, i.e. the actual subdictionary
dictionary propDict;
forAll(propDictsList, dictI)
{
const word& propDictName(propDictsList[dictI].keyword()); // gives "firstEntry", "secondEntry"
Info << "PropDictionary: " << propDictName << nl;
// Here we get access to the respective dictionary
propDict = propDictsList[dictI].dict();
// Now we can use the dictionary lookup as usual
propDict.lookup("prop1") >> prop1_;
Info << "prop1: " << prop1_ << nl;
}

That did the trick for me.

Thanks a lot again for your input, it set me on the right track!

Best regards,

Pascal.

mkraposhin August 19, 2013 17:00

1 Attachment(s)
The more elegant way is to use List<> template API:

1) Create class for each specie with overloaded operations for I/O:
Code:

#ifndef MY_SPECIE_MODEL_H
#define MY_SPECIE_MODEL_H

#include "dictionaryEntry.H"

namespace Foam
{

// Forward declaration of classes
class Istream;
class Ostream;

// Forward declaration of friend functions and operators
class specieModel;
Istream& operator>>(Istream&, specieModel&);
Ostream& operator<<(Ostream&, const specieModel&);


class specieModel
{

    private:
   
        //-
        word name_;
   
        //-
        word diffusionModel_;

        //-
        dimensionedScalar D_;

        //-
        dimensionedScalar molarMass_;

    public:
   
        /// Constructors
   
        //-
        specieModel()
        :
            name_(word::null),
            diffusionModel_(word::null),
            D_(dimensionedScalar("D", dimensionSet(0,2,-1,0,0,0,0), 0.0)),
            molarMass_(dimensionedScalar("molarMass", dimensionSet(1,0,0,0,-1,0,0), 1.0))
        {
        };

        specieModel(const specieModel& sm)
        :
            name_(sm.name_),
            diffusionModel_(sm.diffusionModel_),
            D_(sm.D_),
            molarMass_(sm.molarMass_)
        {
        };

        //-
        specieModel(Istream& is)
        :
            name_(word::null),
            diffusionModel_(word::null),
            D_(dimensionedScalar("D", dimensionSet(0,2,-1,0,0,0,0), 0.0)),
            molarMass_(dimensionedScalar("molarMass", dimensionSet(1,0,0,0,-1,0,0), 1.0))
        {
            const dictionaryEntry entry(dictionary::null, is);

            name_ = entry.keyword();
            entry.lookup("diffusionModel") >> diffusionModel_;
            entry.lookup("D") >> D_;
            entry.lookup("molarMass") >> molarMass_;
        };

        /// Access functions

        //-
        const word& name() const
        {
            return name_;
        }

        //-
        const word& diffusionModel() const
        {
            return diffusionModel_;
        };

        //-
        const dimensionedScalar& D() const
        {
            return D_;
        }

        const dimensionedScalar& molarMass() const
        {
            return molarMass_;
        }

        /// Operators
      friend bool operator==
      (
          const specieModel& a,
          const specieModel& b
      )
      {
          return
              (a.name_ == b.name_)
            && (a.D_.value() == b.D_.value())
            && (a.diffusionModel_ == b.diffusionModel_)
            && (a.molarMass_.value() == b.molarMass_.value());
      }

      friend bool operator!=
      (
            const specieModel& a,
            const specieModel& b
      )
      {
              return !(a == b);
      }


        /// Friend operators

        friend Istream& operator>>(Istream&, specieModel&);
        friend Ostream& operator<<(Ostream&, const specieModel&);
};

// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //

Istream& operator>>(Istream& is, specieModel& sm)
{
    const dictionaryEntry entry(dictionary::null, is);

    sm.name_ = entry.keyword();
    entry.lookup("diffusionModel") >> sm.diffusionModel_;
    entry.lookup("D") >> sm.D_;
    entry.lookup("molarMass") >> sm.molarMass_;
   
    return is;
}

Ostream& operator<<(Ostream& os, const specieModel& sm)
{
    os  << sm.name_ << nl << token::BEGIN_BLOCK << nl;
    os  << "diffusionModel " << sm.diffusionModel_ << token::END_STATEMENT << nl;
    os  << sm.D_ << token::END_STATEMENT << nl;
    os  << sm.molarMass_ << token::END_STATEMENT << nl;
    os  << token::END_BLOCK << nl;
   
    return os;
}

}//end of namespace Foam

#endif

//END-OF-FILE

2) Include this file at youApp.C
Code:

\*---------------------------------------------------------------------------*/

#include "fvCFD.H"
#include "specieModel.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

3) Read properties
Code:

IOdictionary solutionProperties
(
    IOobject
        (
            "solutionProperties",
            runTime.constant(),
            mesh,
            IOobject::MUST_READ_IF_MODIFIED,
            IOobject::NO_WRITE
        )
);

List<specieModel> speciesList (0);

solutionProperties.lookup("speciesList") >> speciesList;

Info << "solutionProperties: " << endl << speciesList << endl;

Source code for application located at the tarball

blaise August 22, 2013 05:43

Hi Matvej,

thanks a lot for your input, it gave me a lot to learn and think about. Unfortunately this solution seems to lack one certain capability, and I apologize for being not specific enough about my requirements. I need to read not only a list of dictionaries, but all sorts of entries from the dictionary file. Something like:

---------- solutionProperties file ----------------------
speciesList
(
A
{
diffusionModel constant;
D D [0 2 -1 0 0 0 0] 0.00005;
molarMass molarMass [1 0 0 0 -1 0 0] 2;
}

B
{
diffusionModel constant;
D D [0 2 -1 0 0 0 0] 0.00005;
molarMass molarMass [1 0 0 0 -1 0 0] 2;
}

);

testscalar 2.345;

testlist ( 0.2 0.3 0.4 0.5 );

testword raw;

----------------------------------------------------------

It is meant to be similar to the "sample" utility, which I wanted to modify to my needs in the first place. As a bloody beginner in OF C++ programming I found it too complicated to understand how to intercept the sampleAndWrite functionality of "sample" to access the data and do some own manipulation with (and I can go also without the fancy output formats and only need the "cloud" type of sample points, etc.). So I decided to go for a fresh start, but I still need the capability to read this kind of dictionary file.

As far as I understand your code by now, the very core of all the magic is in the Istream operator>> part of the specieModel.H file. This function takes the stream of bytes read from the solutionProperties dictionary and the specieModel object instance generated by the call

List<specieModel> speciesList(0);
solutionProperties.lookup("speciesList") >> speciesList;

in readSolutionProps.H.
Correct?

So, how must things be modified to be able to read arbitrary variables from a dictionary file into the specieModel object? I can't figure it out. :-(

Again I apologize for not being complete about the scope of my initial problem. I was not able to see the consequences...

Just another question: The constructor specieModel(Istream& is) never gets called. Why do we have it here anyway?

Best regards,

Pascal.

blaise August 29, 2013 06:59

Any idea?

Cheers,

Pascal.

mkraposhin August 29, 2013 13:47

Quote:

Originally Posted by blaise (Post 447393)
Hi Matvej,

thanks a lot for your input, it gave me a lot to learn and think about. Unfortunately this solution seems to lack one certain capability, and I apologize for being not specific enough about my requirements. I need to read not only a list of dictionaries, but all sorts of entries from the dictionary file. Something like:

Sorry for the late reply.
Now i see, that i must to clarify some parts of the source code.

1) code
Code:

  solutionProperties.lookup("speciesList") >> speciesList;
Reads only array "speciesList" from the dictionary "solutionProperties", which is stored in the object solutionProperties of class IOdictionary.

So, if you want to get access to another entries of solutionProperties, you can use standard OpenFOAM dictionary API (see on the OpenFOAM sourceforge website)
For example:
Code:

List<word> = solutionProperties.toc();
will give to you a complete list of keywords (variables, named lists and named subdictionaries) in your dictionary.

Now you can use dictionary::lookup, ::read or other functions to get values.

2) In my example, using operator '>>', OpenFOAM takes everything, that is located in the list 'speciesList' of dictionary between '(' and ')' and passes it to the speciesList object. speciesList object (array) starts to create new array entries for each sequence '{' '}'. To create new entry it uses constructor p, li { white-space: pre-wrap; } specieModel(Istream& is) to create new instance of specieModel from input stream Istream

So, if you want to create parser for another list, like:
Code:


newList
(
 ....
 entryJ
 {
    var1 var2;
   
    sublist1 (1 2 3);
   
    subSubDict
    {
        subSubDictValue  -1;
    }
 }
 ....
);

you have to create your new own class (say newClass), which knows how to read data between
{ and }. In this class you must implement all neccesary member functions and operators:
--- newClass::newClass() - default constructor, used by List<newClass> to create empty entries
--- newClass::newClass(const newClass&) - copy constructor, used to create copy of the newClass
--- newClass::newClass(Istream& is) - input stream constructor, used to create a new instance of the newClass from the input stream

--- bool operator == (...), bool operator != (...) - operators, that are used to check whether to objects of the class newClass are equivalent or not

--- Static operators >> and << are used to re-direct newClass data to/from text(or binary) stream

Of course, i will propose to you to read more about C++ (Bjarn Straustrup?)

P.S.
Please, separate your posts by short questions, because it is not easy to me to answer all questions simultaneously (sometime i'm using google translator :)

blaise August 30, 2013 05:34

Hi Matvej,

thanks again for your clarifications. I have been trying hard to learn some more C++ and OF stuff.

There might be a slight misunderstanding, though: What I want to do is not to read more variables from
another LIST in the dictionary file, but like in most dictionary files, read variables from the top level in the
dictionary file AND ALSO read a list of subdictionaries from this file.

As I wrote in my previous posting, the structure of the dictionary file is:

Code:

// ******** Attention! This is the very beginning
// of the dictionary _FILE_ ********************
// Simple variables
test_scalar 2.345;
test_list ( 0.2 0.3 0.4 0.5 );
test_word raw;

// List
listOfSubDictionaries
(
    A
    {
        diffusionModel constant;
        D D [0 2 -1 0 0 0 0] 0.00005;
        molarMass molarMass [1 0 0 0 -1 0 0] 2;
    }

    B
    {
        diffusionModel constant;
        D D [0 2 -1 0 0 0 0] 0.00005;
        molarMass molarMass [1 0 0 0 -1 0 0] 2;
    }
);
// *************** End of dictionary file **********

### Question 1:
How can I read the simple variables (e.g. test_word) from the above dictionary _file_ into an _existing_ instance
of class newClass using the >>operator? Something like:

Code:

// *************** Class definition ***************
class newClass
{
    private:
   
        word test_word_;
        List<dictionary> listOfSubDictionaries_;

    public:

        newClass()
        {
        };

        const word& test_word() const
        {
            return test_word_;
        };

        const List<dictionary>& listOfSubDictionaries const
        {
            return listOfSubDictionaries_;
        };

        friend Istream& operator>>(Istream&, newClass&);
};
// ***************** IOStream Operators *****************

Istream& operator>>(Istream& is, newClass& nc)
{
    const dictionaryEntry entry(dictionary::null, is);

    entry.lookup("test_word") >> nc.test_word_;
    entry.lookup("listOfSubDictionaries") >> nc.listOfSubDictionaries_;
    return is;
}

Then in main function:
Code:

int main(int argc, char *argv[])
{
    newClass myNewClass();
    myDict.lookup("test_word") >> myNewClass;
    myDict.lookup("listOfSubdictionaries") >> myNewClass;

    return 0;
}

This does not work: Error:

--> FOAM FATAL IO ERROR:
wrong token type - expected word or string, found on line XXX the punctuation token '('

Why???

This probably will need different implementations of the static >> operator, but I do not know how to do this. So:

### Question 2:
How can I implement an additional >>operator in a way that it accepts "normal" variables as well as lists of subdictionaries, so that I can do the stuff above.

The problem seems to be that I cannot do someting like:

Code:

word& operator>>(word& w, newClass& nc)
{
    nc.test_word_ = w;
    return w;
}

### Question 3:
The >>operator always seems to expect a stream, am I right?


Maybe my conceptual understanding of this is completely wrong. Could you once more comment on the stuff above?

I know how to get the variables into the object by initializing everything in a constructor, no problem with this. But I would like to use your approach.

Thanks a lot!

Cheers,

Pascal.

mkraposhin September 1, 2013 14:07

Quote:

Originally Posted by blaise (Post 448868)
Hi Matvej,

There might be a slight misunderstanding, though: What I want to do is not to read more variables from
another LIST in the dictionary file, but like in most dictionary files, read variables from the top level in the
dictionary file AND ALSO read a list of subdictionaries from this file.

Hi, Blaise!
Of course, it's a misunderstood! What i tried to deliver to you - is a way to read ANY dictionary. The main problem - is a translation from russian to english.

PART 1.

Let's start from the beginning. Suggest, you have a dictionary file "solutionPropeties". Suggest, that this file is situated in "constant". Now you can read this file with:
Code:

IOdictionary solutionProperties
 (
    IOobject
        (
            "solutionProperties",
            runTime.constant(),
            mesh,
            IOobject::MUST_READ_IF_MODIFIED,
            IOobject::NO_WRITE
          )
 );

Now, object solutionProperites of class IOdictionary contains all data from file "solutionProperties". This object will try to read data again, whether it will be modified by the user

Object solutionProperties (class IOdictionary, which is sub-class of dictionary) contains data about next "atomic" data:
- variables ("some_var some_value;");
- lists ( ( 0 1 2 3 ) );
- subdictionaries ( sub_dict_name{ ... } );

1) You can read variables from solutionProperties with the code:
Code:

dimensionedScalar a (solutionProperties.lookup("a"));
 //or
 scalar b;
 solutionProperties.lookup("b") >> b;

In the first case, class 'dimensionedScalar' (object 'a' is of this class) knows how to read data from string;
In the second case, you are looking in solutionProperties for the variable 'b' and, if it found, it's value is transmitted to variable 'b' of type scalar. It means, that, operator '>>' knows how to convert string data to scalar type. If IOdictionary doesn't know how to convert from steam to your type, it will give an error message to you (like in your example).

2) Suggest, you want to read a list of OpenFOAM variables from dict. Then, you can do something like this:
Code:

List<scalar> myList (solutionProperties.lookup("myList"));
 //or by
 List<scalar> myList1 (0); //list of scalars with zero size
 solutionProperties.lookup("myList1") >> myList1;

In the first example, class List<scalar> knows how to convert from the stream to the list of scalars. In the second example, operator '>>' knows how to convert from the stream to the list of scalars List<scalar>

3) Suggest, you want to read sub-dictionary
Code:

dictionary subDict = solutionProperties.lookup("subDict");
This means, that solutionProperties object (which is of the class IOdictionary) should look for sub-dictionary "subDict" and then, it must return new dictionary reference to the object subDict

Please, tell if something is not clear below this line (Part 1)

PART 2.

Now, suggest, that you want to read a list of your own type. Like 'specieModel'. OpenFOAM don't know how to read data of such type. It means, that you need to write your own class (see my code example in previous posts).
When you are writing
Code:

solutionProperties.lookup("speciesList") >> speciesList;
Then OpenFOAM starts to initialize List<specieModel> with new elements, each new element is created using specieModel (Istream& is). OpenFOAM knows, that everything between '(' and ')' is an element. But OpenFOAM don't know actual type of this element. Your implementation of the class specieModel and consequent operators brings this knowledge to OpenFOAM.

So, List<specieModel> knows how to read the list of specieModel from the specified stream (solutionProperties.lookup("speciesList"))

Please, tell if something is not clear below this line (Part 2)

Part 3.

Let us suggest, that you want to read a whole dictionary using one operator in the new class object. Then, you must:

1) You must implement this class
2) You must implement read constructor for this class myClass (Istream& is)
3) You must implement operator '>>' to read from the stream data to the data of the object of class myClass

Blaise, if my explanations are still seems dark to you, then we can do the following
1) Suggest you own class data structure
2) I will write wrapper for your class, then i can make explanations from step to step

I hope, this helped to you

blaise September 2, 2013 05:57

1 Attachment(s)
Hi Matvej,

I really appreciate your effort to handle the english translation problems!!!

Part I is perfectly clear. My problem is this:

Quote:

Then OpenFOAM starts to initialize List<specieModel> with new elements, each new element is created using specieModel (Istream& is). OpenFOAM knows, that everything between '(' and ')' is an element. But OpenFOAM don't know actual type of this element. Your implementation of the class specieModel and consequent operators brings this knowledge to OpenFOAM.
I do not know how to implement the necessary things (operators and class parts) to let OpenFOAM know about the data type in the list between the "(" and ")".

So I set up the basic stuff of my future application and appended the files. This application does not do anything useful yet, beside printing out the values read from the dictionary. At least, it should do this, but at the moment it gives an error saying it cannot find the keyword "sym" in the list of dictionaries, which is exactly what my problem is:
"sym" is a keyword contained in the base level of the dictionary. I cannot get the data from this base level of the dictionary file into my object along with the data from the dictionaries in the list of subdictionaries (here it is called "flakeProps") IN ONE SINGLE CALL to >>operator. As you mention above, I have to implement this in my class to let OpenFOAM know about, but how?

It would be great if you could alter the code I append here and comment in the code what you are doing to achieve this goal.

Thank you very much again for your effort!

Best regards,

Pascal.


All times are GMT -4. The time now is 01:14.