CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Running, Solving & CFD (https://www.cfd-online.com/Forums/openfoam-solving/)
-   -   Understanding tmp%2360T classes (https://www.cfd-online.com/Forums/openfoam-solving/58069-understanding-tmp-2360t-classes.html)

nadine July 4, 2008 17:35

Hi! I would like to ask if yo
 
Hi!
I would like to ask if you can recommend a good explanation how the tmp<t> classes are supposed to be used.
As long as I copy parts of the source code from existing solvers, I have been more or less able to get rid of the bugs that I produced when trying to work with tmp<>. But I definitely don't understand what is going on in the temporaries, so that I receive lots of segfaults when I can't get along with copying code.

Am I right that each tmp<> can be only used in a single calculation and then the temporary is invalidated? What is the reasoning behind this implementation? And can I find some guidelines how to use temporaries successfully?

Thank you
Nadine

deepsterblue July 5, 2008 14:21

A tmp<> object is used in the
 
A tmp<> object is used in the safe and automatic allocation/deallocation of temporary objects (like Fields, volFields, etc). Each tmp<> object has a reference count which gets incremented at allocation and decremented when the destructor is called. When the refCount is zero and the destructor is called (usually in situations when the object is going out of scope), the pointer to the object is deleted.

tmp objects can be used any number of times, as long as it stays in scope. Hope this helps.

nadine July 5, 2008 16:00

"Each tmp<> object has a refer
 
"Each tmp<> object has a reference count which gets incremented at allocation and decremented when the destructor is called."

How would this work?

If I allocate a tmp(A), there is one single reference to A, if I allocate another tmp(A), the count has to be incremented. But if I allocate a tmp(B), the refcount has to be one again.
Does the tmp<> template have a static list of all classes and objects which it has allocated?

Or do you mean that tmp is a replacement for the boost smart pointers (www.boost.org/doc/libs/release/libs/smart_ptr)?

Thank you
Nadine

mbeaudoin July 6, 2008 03:47

"Each tmp<> object has a refer
 
"Each tmp<> object has a reference count which gets incremented at allocation and decremented when the destructor is called."

The reference counter is not a global variable.

tmp(A) and tmp(B) are both distinct and separate objects, with both their internal refcount.

Martin

nadine July 24, 2008 05:13

Hi! After a few weeks I'm c
 
Hi!

After a few weeks I'm coming back to my question about how to use tmp<t> template classes. I show a small piece of code which doesn't behave as I expect. Can you point out, what I'm getting wrong?

Here is the file test.C:
>>>>>>>>>>>>>>>>>>>>>>>>
#include "fvCFD.H"

#include <iostream>
using namespace std;

class A{
int cnt;
public:
A(){cout<<"A::A()\n"; cnt=0;}
~A(){cout<<"A::~A()\n";}
bool okToDelete(){return true;}
void peek(){cout<<"A::peek() cnt="<<cnt<<"\n";}
int operator--(){cnt--; cout<<"A::op--() returns "<<cnt<<"\n"; return cnt;}
int operator++(){cnt++; cout<<"A::op++() returns "<<cnt<<"\n"; return cnt;}
};

int main(int argc, char *argv[])
{
//A *a=new A(); //this line instead of the next one causes a "double free or corruption"
A a;

tmp<a > t1(a);
t1().peek();
tmp<a > t2=t1;
t2().peek();
}
<<<<<<<<<<<<<<<<<<<<<

You can use this simple Makefile to build the executable "test" by running "make test" (assuming a linux OS):
>>>>>>>>>>>>>>>>>>>>>
CPPFLAGS=-DDP -DNoRepository \
-I$(FOAM_SRC)/OpenFOAM/lnInclude \
-I$(FOAM_SRC)/finiteVolume/lnInclude \
-I$(FOAM_APP)/solvers/incompressible/icoFoam
LDFLAGS=-L $(FOAM_LIB)/linuxGccDPOpt
LDLIBS=-lOpenFOAM
<<<<<<<<<<<<<<<<<<<<<

The output from running "./test" is:
>>>>>>>>>>>>>>>>>>>>>
A::A()
A::peek() cnt=0
A::peek() cnt=0
A::~A()
<<<<<<<<<<<<<<<<<<<<<

Apparently the operators ++ and -- of class A are never executed, although my understanding is that they should be used by tmp<a > to do the reference counting?

More importantly, if I replace the line "A a;" in the code above with "A *a=new A();" I get the following output with a core dump:
>>>>>>>>>>>>>>>>>>>>>
A::A()
A::peek() cnt=0
A::op++() returns 1
A::peek() cnt=1
A::~A()
A::~A()
*** glibc detected *** ./test: double free or corruption (fasttop): 0x08094120 ***
....
Aborted (core dumped)
<<<<<<<<<<<<<<<<<<<<<

Here the reference count actually is increased, but nevertheless the pointer "A *a" seems to be freed twice.
What do I need to change to make the example finish without an error? Do I have to test the reference count myself in okToDelete()? I also tried to initialze cnt=1 or even cnt=2 in the constructor A::A(), but it doesn't help.


Thank you
Nadine

mgomez July 24, 2008 06:30

Hello Nadine Have a look at
 
Hello Nadine

Have a look at $FOAM_SRC/OpenFOAM/fields/tmp/refCount.H for the details of the implementation. You need to inherit your class A from refCount, then you can forget about doing any counting yourself.

As to your first question, your local variable "A a;" is allocated on the stack, not on the heap. Therefore the tmp class doesn't have to keep track of the reference count.

As to your second question, yes, okToDelete is the place to check whether the count has become zero. Only then okToDelete can return True.

Again, check how it is done in refCount.H, and it will be straightforward to code your own refcountable class.

HTH
Miguel

nadine July 24, 2008 09:06

Thank you Miguel! You helped m
 
Thank you Miguel! You helped me make a big step ahead.

I thought okToDelete() was some extra option to prevent references from being destroyed although their counter is zero, like a "Do you really want to quit?" dialog. But your explanations and a look into refCount.H and tmpI.H made it clear.

Thank you
Nadine

maka November 18, 2008 14:23

Can any one explain the differ
 
Can any one explain the difference between:

{
tmp<scalarfield> xTmp = ...;
scalarField x = ...;

{
tmp<scalarfield> xTmp = ...;
scalarField x = ...;
}
}

in terms of when the memory is free from the variables.

Thanks,
Maka.

maka January 22, 2009 06:52

to reproduce the error: - V1.
 
to reproduce the error:
- V1.3
- bug correction in here is implemented.
- add to the beginning of the definition of LES models correct(const tmp<voltensorfield>& gradU)

Info <<"1" << average(mag(gradU)) << endl;
Info <<"2" << average(mag(gradU)) << endl;
Info <<"3" << average(mag(gradU)) << endl;

if the variable gradU is used more than once or twice within the scope of the function definition (inside correct function) it gives:
FOAM FATAL ERROR : temporary deallocated

From function const T& tmp<t>::operator()() const
in file ../maka/OpenFOAM/OpenFOAM-1.3/src/OpenFOAM/lnInclude/tmpI.H at line 190.

Thanks.

olesen January 22, 2009 07:08

Maka, 1. I don't think you
 
Maka,

1. I don't think you should expect any bugfixes for version 1.3, version 1.5.x is current.

2. The code you showed (using a tmp value several times) should always result in a fatal error.
You sent mag() a tmp, so of course it freed it!

hjasak January 22, 2009 07:17

Unfortunately, two errors (apa
 
Unfortunately, two errors (apart from Mark not knowing what he's talking about):

First const tmp<voltensorfield>& gradU is wrong: it is a reference to a temporary, which gets deleted. This should read
const voltensorfield& gradU

Second,

tmp<voltensorfield> gradU = fvc::grad(U);
Info <<"1" << average(mag(gradU)) << endl;
Info <<"2" << average(mag(gradU)) << endl;
Info <<"3" << average(mag(gradU)) << endl;



does not work. I do not have a strong opinion if it should - it violates the rules of using a tmp, so I'm not bothered if it fails.

The correct and working code reads:

volTensorField gradU = fvc::grad(U);
Info <<"1" << average(mag(gradU)) << endl;
Info <<"2" << average(mag(gradU)) << endl;
Info <<"3" << average(mag(gradU)) << endl;


I will change the LES models over here.

Hrv

maka January 22, 2009 07:58

It seems to be a bug since the
 
It seems to be a bug since the following is the declaration of correct() member function that is used in most LES models in the standard release 1.4.1 (I did not check later versions):
void Smagorinsky::correct(const tmp<voltensorfield>& gradU).

If you could explain what are the rules of using tmp and what do we gain from using tmp. I will be very grateful. Thanks.

hjasak January 22, 2009 07:59

If you need a quick fix do gra
 
If you need a quick fix do gradU()} in function calls.

maka January 22, 2009 08:02

I used to do that all the time
 
I used to do that all the time but I do not understand what I'm doing that is why I would be thankful if you could explain:
(1) what are the rules of using tmp?
(2) what do we gain from using tmp?
Thanks.

dmoroian January 22, 2009 09:25

Hello developers, It would be
 
Hello developers,
It would be very nice if you take a bit of your time and put some guide lines "why, when, how" to use temporary objects.
I've searched the forum and there are many places (~100) where this subject is approached but it still lacks the above basics.

Dragos


All times are GMT -4. The time now is 18:35.