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

tmp - stands for 'true macro pain'?

Register Blogs Members List Search Today's Posts Mark Forums Read

Like Tree2Likes
  • 2 Post By hjasak

Reply
 
LinkBack Thread Tools Display Modes
Old   January 19, 2010, 14:25
Default tmp - stands for 'true macro pain'?
  #1
Senior Member
 
David Gaden
Join Date: Apr 2009
Location: Winnipeg, Canada
Posts: 397
Rep Power: 12
marupio is on a distinguished road
I've never seen such a chopped-up macro-heavy series of classes before. Just trying to figure out DimensionedScalarField is a nightmare for me (and very humbling).

What is tmp?

It looks like a wrapper class for a field, which redirects its pointer on destruction, provided refCount says it's okay. Is this some sort of sneaky way of ensuring local objects survive function exits to prevent copying on return?

Does OpenFOAM get much more complicated than this? I'm not the most experienced programmer out there...

-Dave
marupio is offline   Reply With Quote

Old   January 20, 2010, 06:40
Default
  #2
Senior Member
 
Hrvoje Jasak
Join Date: Mar 2009
Location: London, England
Posts: 1,758
Rep Power: 21
hjasak will become famous soon enough
Yes - it does get much more complicated than this. But, you get used to it.

tmp is essential and extremely useful. This is a mechanism that avoids copying large chunks of data in memory when you do operations on them. Consider for example

scalarField a(1000000, 1.0);
scalarField b(1000000, 2.0);

scalarField c = a + b;

This calls operator+(const scalarField& a, const scalarField& b), and that needs a return type. If the return type is a scalarField, you will first create and then copy a field of length 1000000 floating point numbers - which hurts and takes time.

Therefore, you make a return type a tmp<scalarField>, where tmp holds a pointer to the actual array. Its (tmp's) constructor, copy constructor and destructor get called, but they do not involve allocation and copying of the real array of data - it just counts the number of references and manages storage.

Clear? Hope this helps...

Now to the real question: this is a piece of optimisation machinery in FOAM. Why do you need to know more (unless you are writing field and matrix operators)? It should all be transparent and automatic.

Good luck,

Hrv
__________________
Hrvoje Jasak
Providing commercial FOAM/OpenFOAM and CFD Consulting: http://wikki.co.uk
hjasak is offline   Reply With Quote

Old   January 20, 2010, 10:47
Default
  #3
Senior Member
 
David Gaden
Join Date: Apr 2009
Location: Winnipeg, Canada
Posts: 397
Rep Power: 12
marupio is on a distinguished road
I figured I was going too deep into the primitives. It's just sometimes I was seeing tmp<> and sometimes I wasn't. For instance, in icoFoam we see:

fvVectorMatrix UEqn

whereas in simpleFoam (UEqn.H) we see:

tmp<fvVectorMatrix> UEqn

... and two days later I have a macro headache. Am I right in thinking the tmp<> is unnecessary in simpleFoam? Otherwise, if it's supposed to work in the background, why should it appear at the top level (in a solver)?

At the moment, I don't intend to write any matrix functions for this project, just a solver with a complex biochemistry model (called ADM1).

begin aside
But the whole reason I'm using OpenFOAM for this project is because my long term goal is to write a new kind of fluid solver that models a fluid as a sort of half-continuum, half-particle cloud. So every fluid quantity has a fully-specified statistical distribution at every point. I imagine that will involve adding new primitive classes and operators (e.g. DimensionedScalarDistributionField).
end aside

-Dave

edit:

BTW You cite operator+ for scalarField: operator+(const scalarField& a, const scalarField& b)... this was the exact function I was looking for, but never found it. I used gcc's preprocessor to assemble the macros, and for DimensionedScalarField, the operator+'s it found are listed below. Note, it always involves a Field and a single scalar. I'm sure it exists... but I couldn't find it. This just goes to show: the deeper you go, the foggier it gets.

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const dimensioned<scalar>& dt1,
const DimensionedField<scalar, GeoMesh>& df2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const scalar& t1,
const DimensionedField<scalar, GeoMesh>& df2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const dimensioned<scalar>& dt1,
const tmp<DimensionedField<scalar, GeoMesh> >& tdf2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const scalar& t1,
const tmp<DimensionedField<scalar, GeoMesh> >& tdf2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const DimensionedField<scalar, GeoMesh>& df1,
const dimensioned<scalar>& dt2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const DimensionedField<scalar, GeoMesh>& df1,
const scalar& t2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const tmp<DimensionedField<scalar, GeoMesh> >& tdf1,
const dimensioned<scalar>& dt2
);

template<class GeoMesh>
tmp<DimensionedField<scalar, GeoMesh> > operator +
(
const tmp<DimensionedField<scalar, GeoMesh> >& tdf1,
const scalar& t2
);
marupio is offline   Reply With Quote

Old   January 20, 2010, 10:56
Default
  #4
Senior Member
 
Hrvoje Jasak
Join Date: Mar 2009
Location: London, England
Posts: 1,758
Rep Power: 21
hjasak will become famous soon enough
Well, put on your 1970-s hat (or a shirt with huge collars!) and let's talk about memory peaks. For simpleFoam, the memory peak is at the point of creation of the pressure equation, because, unlike PISO, I am allowed to delete the momentum matrix before the creation of the pressure matrix. Therefore, I make the momentum matrix a tmp and call UEqn.clear(); at an opportune place in the code and drop the peak memory requirement by one complete assymetric matrix!

Guess what clear() does: it will delete the pointer to the actual momentum matrix (before reaching the destructor) and free up a lot of memory to be re-used for the pressure matrix.

This is how FOAM beats eg Fluent and STAR in memory usage per cell, but in the 21st century (and especially when you are writing new discretisation capability) you don't care that much. In PISO-based solvers you don't have this option, since you will call UEqn.H() later on in the algorithm, and this requires access to momentum matrix coefficients. Therefore, there's no need for the tmp<matrix> gymnastics...

Clear?

Hrv
JBUNSW and franciscofelis like this.
__________________
Hrvoje Jasak
Providing commercial FOAM/OpenFOAM and CFD Consulting: http://wikki.co.uk
hjasak is offline   Reply With Quote

Old   January 21, 2010, 17:35
Smile
  #5
Senior Member
 
David Gaden
Join Date: Apr 2009
Location: Winnipeg, Canada
Posts: 397
Rep Power: 12
marupio is on a distinguished road
Got it. Thanks! I'm sure I'll be back...
marupio is offline   Reply With Quote

Old   September 22, 2010, 03:52
Default
  #6
New Member
 
Join Date: Sep 2009
Posts: 13
Rep Power: 7
cgoniva is on a distinguished road
Dear All!

I'm trying to write a code which is similar to the
inline tmp <volVectorField> spray::momentumSource()

Inside that function a tmp <volVectorField> is built from a new volVectorField

So I am wondering what is the scope of this tmp object and whether I need to do some clean up using delete at some point? I could not find such a thing inside the spray class.

Thx for your advise,
Cheers Chris
cgoniva is offline   Reply With Quote

Old   September 22, 2010, 04:31
Default
  #7
Assistant Moderator
 
Bernhard Gschaider
Join Date: Mar 2009
Posts: 3,912
Rep Power: 40
gschaider will become famous soon enoughgschaider will become famous soon enough
Quote:
Originally Posted by cgoniva View Post
Dear All!

I'm trying to write a code which is similar to the
inline tmp <volVectorField> spray::momentumSource()

Inside that function a tmp <volVectorField> is built from a new volVectorField

So I am wondering what is the scope of this tmp object and whether I need to do some clean up using delete at some point? I could not find such a thing inside the spray class.

Thx for your advise,
Cheers Chris
The whole point of tmp is that you don't have to care about deleting too much. Have you read: http://openfoamwiki.net/index.php/OpenFOAM_guide/tmp
I think it is explained quite nicely there

Bernhard
gschaider is offline   Reply With Quote

Old   September 22, 2010, 05:07
Default
  #8
New Member
 
Join Date: Sep 2009
Posts: 13
Rep Power: 7
cgoniva is on a distinguished road
Thx for your quick reply Bernhard!

I'll have a look at that link!

Cheers
Chris
cgoniva is offline   Reply With Quote

Old   June 4, 2015, 08:26
Default
  #9
Senior Member
 
Robert Sawko
Join Date: Mar 2009
Posts: 116
Rep Power: 13
AlmostSurelyRob will become famous soon enough
Sorry for necro-bumping this thread, but I would still like to ask for the clarification on tmp class. I understood the idea of returning a sort of smart pointer which will handle the memory allocation properly, but how is this related to mechanism of copy-elision* that already exists in C++?

I occasionally come across it when dealing with multiphase models as various interaction expressions return tmp.

* Copy-elision wikipedia:
http://en.wikipedia.org/wiki/Copy_elision
https://en.wikipedia.org/wiki/Return_value_optimization
AlmostSurelyRob is offline   Reply With Quote

Old   June 7, 2015, 23:01
Default
  #10
New Member
 
Albert Yiamakis
Join Date: Jun 2015
Posts: 2
Rep Power: 0
Kojirion is on a distinguished road
Quote:
Originally Posted by hjasak View Post
scalarField a(1000000, 1.0);
scalarField b(1000000, 2.0);

scalarField c = a + b;

This calls operator+(const scalarField& a, const scalarField& b), and that needs a return type. If the return type is a scalarField, you will first create and then copy a field of length 1000000 floating point numbers - which hurts and takes time.
I would expect that copy to be elided. RVO has been supported for a long time - apparently Scott Meyers recommended return by value in More Effective C++ back in 1996.
So while I do not dispute that tmp may have very good uses throughout OF code, this example - and the simllar reasoning answering 'Why is it needed?' in the guide is unconvincing.

Regarding early deletion, if the object is local it would be sufficient to create an arbitrary scope with a pair of braces; that makes it perfectly possible to destruct some locals in the middle of a function.

More interesting would be the problem of a+b+c and avoiding the temporary result of a+b, which expression templates would help with and tmp does not, as far as I can tell.
Kojirion is offline   Reply With Quote

Reply

Tags
macro, refcount, tmp

Thread Tools
Display Modes

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 On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Macro problem cfddummy CD-adapco 1 April 9, 2007 12:37


All times are GMT -4. The time now is 13:16.