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/)
-   -   Storing Boundary Condition Values for Later Use (https://www.cfd-online.com/Forums/openfoam-programming-development/93583-storing-boundary-condition-values-later-use.html)

Fransje October 19, 2011 16:10

Storing Boundary Condition Values for Later Use
 
Dear Foamers,

I would like to be able to store time-averaged patch values I extract from a boundary condition I'm programming. More specifically I'm trying to store a vectorField. The problem is that at every (sub)-iteration step the boundary condition I'm working on is instantiated and destroyed again, making it impossible to store it in the boundary condition itself.

I thought of a few things:
  1. I could store it in a file, but reading from and writing to disk every sub-iteration step would be prohibitively expensive, so that is not an option.
  2. I tried hacking my way into the IOobject registry, by using a IOList<vector>, but it is deleted as soon as my boundary condition is uninstantiated.. So that doesn't work either.
  3. I tried putting the same IOList<vector> in the solver, which doesn't work either, because when the solver start I don't know what the size of my vectorField would be, and I can't modify the IOList object once it is created..
So this leaves me out of ideas...
Would anybody know how to solve this? Maybe by finding a way workaround allowing me to modify the IOList?

Looking forward to your suggestions

Francois.

marupio October 19, 2011 22:08

Can you access it during a sub iteration, when it is still alive, and store a copy at the top level? Then you could use your registry hack to retrieve a const copy from within the boundary condition the next time to create a fresh copy.

I can't think of much else - the algorithm you describe is difficult to guess at.

deepsterblue October 19, 2011 22:20

So you want a vectorField stored for each time-step? Are you looking to store this list of vectorFields to a file eventually (i.e., when the run is completed presumably)?

You can always resize a field using the setSize() member function, so it is possible to modify it after construction.

tomislav_maric October 20, 2011 04:41

Quote:

Originally Posted by Fransje (Post 328625)
Dear Foamers,

The problem is that at every (sub)-iteration step the boundary condition I'm working on is instantiated and destroyed again, making it impossible to store it in the boundary condition itself.

Why would you define and destroy a boundary condition, and even more on every sub-iteration? The purpose of the BC is to influence the computation of the matrix coefficients, you may have a boundary condition which requires some kind of sub-cycle, but at the end, it will just do that. Do you mean you are initializing and deleting a FvPatchField object (or derived one)?

What is the overall algorithm that you need? I don't mean what you have implemented so far, but, your actual goal?

Fransje October 20, 2011 11:02

Dear All,

Thank you for your replies!
I will reply to them in anti-chronological order.

  1. Dear Tomislav, Sorry for being unclear. Yes, I'm using a derived -FvPatchField, so it is being re-instantiated at every sub-iteration.
    The overal algorithm I need for my PatchField I already implemented. I'm working on a sort of recycled-inflow. But for the time being, as I didn't manage to store time-averaged mean-velocity data, I can only look at planner-averages. Eventually I would like to be able to also include time-averaging for increased accuracy.
  2. Dear Sandeep, Yes, in fact, the easiest for me would be to store a vectorField which I can lookup and modify at each timestep. And eventually, yes, I will print it to a file. But the printing out is not the issue, the use of OFstream is very straightforward.
  3. Dear David, Yes, I can access the IOobject I create during a sub-iteration, when it's still alive. Unfortunately, once my I exit my boundary condition, it gets kicked out of the registry.. :-(
    I doubt the setSize() option would work on my third solution (i.e., where the IOobject is created in the solver), because the object returned from the registry database is constant. Something like:
    Quote:

    const IOList<vector>& myVec = mesh.thisDb().lookupObject< IOList<vector> >("myVectorList");
I hope this clarified slightly the explanation of the issue I was having.. :o

Looking forward to your replies,
Kind regards,

Francois.

tomislav_maric October 20, 2011 11:35

Well, if the IOobject is dying when going out of scope, why not wrap it into a tmp<IOobject>? This way, it won't die after going out of scope... either this or autoPtr..

I think I get what you mean to do now (hopefully), thanks for clarifying! :)

Tomislav

marupio October 20, 2011 17:21

Yes, you could try using tmp. See here: http://openfoamwiki.net/index.php/OpenFOAM_guide/tmp

Here's what I mean.

In createFields.H:
- Create a vectorField with a size of 0.
- Initialize your IOList<vector> hack as well, size = 0.

In your custom boundary condition:
- lookup your IOList
-- if size = 0, initialize your temporary vectorField with all vectors at your initial guess (zero?).
-- if size != 0, initialize your temporary vectorField by copying the vectors from IOList.

In you solver body, sub-iteration loop, when the custom boundary condition exists:
- Access the boundary field in question.
- setSize your IOList, and copy the field values into it.

Fransje October 21, 2011 09:15

Dear Tomislav, dear David,

Although I was aware of the existence of tmp<> objects I thought they were only used to return large objects from functions. I will re-dive in the wiki and try to implement my vectorFields following your guidelines. I'll keep you updated on my progress!

Thank you for your help,
Kind regards,

Francois.

marupio October 21, 2011 10:47

tmp<> will only work if another object is holding a reference to it outside of your boundary condition.

Fransje December 9, 2011 12:00

Store in Object registry
 
Anyways, just in case somebody might be interested in how I solve this problem, here is my workaround:
  1. Look in the database if my variable exisits.
  2. This leads to two options:
    1. No, it doesn't exist. => read the variable from a file, create an IOobject from it and store it in the database. Then use it.
    2. Yes, it exists. => Great. Just look it up and use it.
  3. After use, it has to be updated in the databse. However, you can only retrieve const object from the database, so in theory you cannot change the objects in the database directy. But a workaround can be found using a const_cast<>() function.
The check, reading and checking in of the new variable in the registry is done with this code gem:
Code:

List<vector> avgMeanReturned( my_var_size, vector::zero );

if( !mesh.thisDb().foundObject< IOList< vector > >( "avgMean" ) )
{
    if( Pstream::master() )
    { 
        avgMeanReturned = readMeanFromFile();
    } 
    reduce( avgMeanReturned , sumOp< List< vector > >() );

    mesh.thisDb().store
    ( 
        new IOList< vector >
        (
            IOobject
            (
                "avgMean",
                mesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            ),
            avgMeanReturned
        )
    );
}
else
{
    const IOList< vector >& dbVecLst
        = mesh.thisDb().lookupObject< IOList< vector > >(  "avgMean"  );
    avgMeanReturned = dbVecLst;
}

return avgMeanReturned;

And the update with const_cast<>() can be done using:
Code:

// using the new variable avgMeanUpdated

const IOList< vector >& dbVecLst
    = mesh.thisDb().lookupObject< IOList< vector > >( "avgMean" );
const_cast< IOList< vector >& >( dbVecLst ) = avgMeanUpdated;

Hope this might be of help to somebody someday.

Kind regards,

Francois.


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