CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > Software User Forums > OpenFOAM > OpenFOAM Programming & Development

Read properties per component from an input file dictionary

Register Blogs Community New Posts Updated Threads Search

Like Tree27Likes

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   February 16, 2011, 06:21
Default Read properties per component from an input file dictionary
  #1
Cyp
Senior Member
 
Cyprien
Join Date: Feb 2010
Location: Stanford University
Posts: 299
Rep Power: 18
Cyp is on a distinguished road
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
Cyp is offline   Reply With Quote

Old   February 16, 2011, 10:35
Default
  #2
Senior Member
 
Martin
Join Date: Oct 2009
Location: Aachen, Germany
Posts: 255
Rep Power: 22
MartinB will become famous soon enough
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
MartinB is offline   Reply With Quote

Old   February 17, 2011, 04:22
Default
  #3
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,715
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
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];
        ...
    }
olesen is offline   Reply With Quote

Old   February 17, 2011, 08:35
Default
  #4
Cyp
Senior Member
 
Cyprien
Join Date: Feb 2010
Location: Stanford University
Posts: 299
Rep Power: 18
Cyp is on a distinguished road
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
Cyp is offline   Reply With Quote

Old   February 21, 2011, 04:24
Default
  #5
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,715
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by Cyp View Post
...
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.

Last edited by olesen; February 21, 2011 at 05:44.
olesen is offline   Reply With Quote

Old   February 21, 2011, 05:21
Default
  #6
Cyp
Senior Member
 
Cyprien
Join Date: Feb 2010
Location: Stanford University
Posts: 299
Rep Power: 18
Cyp is on a distinguished road
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
Cyp is offline   Reply With Quote

Old   February 21, 2011, 05:52
Default
  #7
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,715
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by Cyp View Post
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 View Post
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"))
        );
    }
matthi, Milad06, wenxu and 1 others like this.
olesen is offline   Reply With Quote

Old   February 21, 2011, 06:47
Default
  #8
Cyp
Senior Member
 
Cyprien
Join Date: Feb 2010
Location: Stanford University
Posts: 299
Rep Power: 18
Cyp is on a distinguished road
It perfectly works !! Thank you very much!!
Cyp is offline   Reply With Quote

Old   September 10, 2012, 10:50
Default
  #9
Member
 
Rudolf Hellmuth
Join Date: Sep 2012
Location: Dundee, Scotland
Posts: 40
Rep Power: 14
rudolf.hellmuth is on a distinguished road
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
rudolf.hellmuth is offline   Reply With Quote

Old   August 14, 2013, 09:36
Default List of subdictionaries
  #10
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
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.
blaise is offline   Reply With Quote

Old   August 14, 2013, 14:10
Default
  #11
Senior Member
 
mkraposhin's Avatar
 
Matvey Kraposhin
Join Date: Mar 2009
Location: Moscow, Russian Federation
Posts: 355
Rep Power: 21
mkraposhin is on a distinguished road
Quote:
Originally Posted by rudolf.hellmuth View Post
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 is offline   Reply With Quote

Old   August 14, 2013, 14:29
Default
  #12
Senior Member
 
mkraposhin's Avatar
 
Matvey Kraposhin
Join Date: Mar 2009
Location: Moscow, Russian Federation
Posts: 355
Rep Power: 21
mkraposhin is on a distinguished road
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
mkraposhin is offline   Reply With Quote

Old   August 16, 2013, 06:52
Default Solution: Reading list of subdictionaries
  #13
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
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.
blaise is offline   Reply With Quote

Old   August 19, 2013, 18:00
Default
  #14
Senior Member
 
mkraposhin's Avatar
 
Matvey Kraposhin
Join Date: Mar 2009
Location: Moscow, Russian Federation
Posts: 355
Rep Power: 21
mkraposhin is on a distinguished road
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
Attached Files
File Type: gz myIcoFoam.tar.gz (4.2 KB, 80 views)
blaise and tom_flint2012 like this.
mkraposhin is offline   Reply With Quote

Old   August 22, 2013, 06:43
Default
  #15
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
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 is offline   Reply With Quote

Old   August 29, 2013, 07:59
Default
  #16
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
Any idea?

Cheers,

Pascal.
blaise is offline   Reply With Quote

Old   August 29, 2013, 14:47
Default
  #17
Senior Member
 
mkraposhin's Avatar
 
Matvey Kraposhin
Join Date: Mar 2009
Location: Moscow, Russian Federation
Posts: 355
Rep Power: 21
mkraposhin is on a distinguished road
Quote:
Originally Posted by blaise View Post
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
sonGoku likes this.
mkraposhin is offline   Reply With Quote

Old   August 30, 2013, 06:34
Default
  #18
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
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.
blaise is offline   Reply With Quote

Old   September 1, 2013, 15:07
Default
  #19
Senior Member
 
mkraposhin's Avatar
 
Matvey Kraposhin
Join Date: Mar 2009
Location: Moscow, Russian Federation
Posts: 355
Rep Power: 21
mkraposhin is on a distinguished road
Quote:
Originally Posted by blaise View Post
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
ngj, daire6, huyidao and 2 others like this.
mkraposhin is offline   Reply With Quote

Old   September 2, 2013, 06:57
Default
  #20
Member
 
P.A.
Join Date: Mar 2009
Location: Germany
Posts: 83
Rep Power: 17
blaise is on a distinguished road
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.
Attached Files
File Type: gz flake.tar.gz (2.8 KB, 21 views)

Last edited by blaise; September 2, 2013 at 10:22.
blaise is offline   Reply With Quote

Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
1.7.x Environment Variables on Linux 10.04 rasma OpenFOAM Installation 9 July 30, 2010 05:43
Installation of OpenFOAM-1.6 on Ubuntu 9.10 marval OpenFOAM Installation 2 March 17, 2010 09:33
[OpenFOAM] ParaView 33 canbt open OpenFoam file hariya03 ParaView 7 September 25, 2008 18:33
DxFoam reader update hjasak OpenFOAM Post-Processing 69 April 24, 2008 02:24
Results saving in CFD hawk Main CFD Forum 16 July 21, 2005 21:51


All times are GMT -4. The time now is 12:20.