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/)
-   -   Duplicate GeometricField (https://www.cfd-online.com/Forums/openfoam-solving/58832-duplicate-geometricfield.html)

reimund June 4, 2008 15:58

Hi! I hope that not only user
 
Hi!
I hope that not only users, but also developers are active in this list, because I have a rather technical question.

How can I duplicate a GeometricField?
I received some OpenFOAM solver code, which creates locally several volScalarFields, volVectorFields etc. I want to #include this code into another solver function without modifying it. After the #include the function has to return a list containing pointers to some of those fields.

However, because the local fields are discarded on function return, later use of the returned pointers causes a segmentation fault. How can I get out of this?
For example I have a local "volScalarField p". I tried to create a static copy q with "static volScalarField q(p);". When I return the pointer &q, this should be still valid, because the static variable is not discarded. But I still have a segmentation fault, maybe because the copy constructor q(p) only does a shallow copy?
I also tried many things with clone() and autoPtr<volscalarfield>, but none of them helped me to create a static volScalarField from p.

What is the correct approach?

Reimund

su_junwei June 4, 2008 20:40

Hi Reimund It seems that th
 
Hi Reimund

It seems that the assigment operator "=" in GeometricField is a copy assigment.
Returning the local variable of GeometericField type will cause a problem??

If several GeometericField objects need to be returned, use the class of "PtrList" passed as a argument.(That return PtrList directly will also cause a problem, for there is not a clone() function in GeometericField !!) or create a new class like "combustionMixture" located at
/src/thermophysicalModels/combustion/mixtureThermos/mixtures/combustionMixture/"

Help this helps

Su Junwei

hjasak June 5, 2008 02:05

Well, You can duplicate a geom
 
Well, You can duplicate a geometric field by calling a copy constructor, which is trivial:

volScalarField p2 = p;

What you need to worry about is a return type from your function - are you returning a reference to a temporary rather than a copy?

Hrv

reimund June 5, 2008 16:33

Thanks for your answers. I thi
 
Thanks for your answers. I think I am slowly understanding more about the problem. Below I post a small piece of code in the hope that you might try, what goes wrong, in case my explanations are not clear enough.

In the initialize() method the #included files represent the part that I wish not to change. The returned pointer to the field p is simplified for the list of field pointers to be returned.

As Hrvoje said, the copy constructor "static volScalarField p2=p;" does _in principle_ what I need, copying the local field into a static field to which a pointer can be returned.
BUT: I had to modify the declarations of the variables runTime and mesh into static declaration. These two are referenced in the field constructors, and apparently the static copy p2 can't be used, if the original runTime and mesh aren't valid anymore.

Is there any possiblity, how I can copy runTime and mesh into static variables _after_ the #includes, and plug these static copies into the static p2?

Reimund

This code I placed into the solvers/incompressible/icoFoam directory and compiled it like icoFoam.C:

#include "fvCFD.H"

volScalarField *initialize(int argc, char *argv[]){
#include "setRootCase.H"
#include "createTime.H" //here I had to change "Foam::Time runTime" to "static Foam::Time runTime"
#include "createMesh.H" //here I had to change "fvMesh mesh" to "static fvmesh mesh"
#include "createFields.H" //no changes needed

static volScalarField p2=p;
return &p;
}

int main(int argc, char *argv[])
{
volScalarField *p=initialize(argc,argv);
// test if p is valid:
Foam::mag(*p);
printf("If no exception has been reported, the pointer was valid.\n");
}

deepsterblue June 5, 2008 17:09

Static variables (I believe) h
 
Static variables (I believe) have a longer lifetime during the program run, and is generally a bad choice for your problem.
I'd suggest that you create a tmp<volscalarfield> within your function and return that. No messy pointers to deal with, and the object is destroyed automatically when it goes out of scope.
Am I right, Hrv?

reimund June 5, 2008 17:35

>Static variables (I believe)
 
>Static variables (I believe) have a longer lifetime during the program run, and is generally a bad
>choice for your problem.

Why? A longer lifetime than local variables is exactly what I need. My problem is, that the included code creates local fields. And I have to get those fields out of my initialize() function.

>I'd suggest that you create a tmp<volscalarfield> within your function and return that. No messy >pointers to deal with, and the object is destroyed automatically when it goes out of scope.

Destroyed out-of-scope opbjects is what I want to _avoid_!

Reimund

su_junwei June 5, 2008 21:41

Hi Reimund Return the refe
 
Hi Reimund

Return the reference of a local variable is not safe even if it is static, and please refer the book "effective c++ (item 23)" of scott Meyers.

try the code below

#include "fvCFD.H"

volScalarField initialize(int argc, char *argv[]){
#include "setRootCase.H"
#include "createTime.H" //here I had to change "Foam::Time runTime" to "static Foam::Time runTime"
#include "createMesh.H" //here I had to change "fvMesh mesh" to "static fvmesh mesh"
#include "createFields.H" //no changes needed

return p;
}

int main(int argc, char *argv[])
{
volScalarField p=initialize(argc,argv);
// test if p is valid:
Foam::mag(p);
printf("If no exception has been reported, the pointer was valid.\n");
}

OR


#include "fvCFD.H"

void initialize(int argc, char *argv[], volScalarField & p){
#include "setRootCase.H"
#include "createTime.H" //here I had to change "Foam::Time runTime" to "static Foam::Time runTime"
#include "createMesh.H" //here I had to change "fvMesh mesh" to "static fvmesh mesh"
#include "createFields.H" //no changes needed
}

int main(int argc, char *argv[])
{
// create volScalarField p;
.....

initialize(argc,argv,p);
// test if p is valid:
Foam::mag(p);
printf("If no exception has been reported, the pointer was valid.\n");
}

Su Junwei

deepsterblue June 5, 2008 21:48

Can you rewrite it like this?
 
Can you rewrite it like this?

tmp<volscalarfield> initialize(int argc, char *argv[]){
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
#include "createFields.H"

tmp<volscalarfield> p2 = new volScalarField(p);
return p2;
}

When you call initialize() in main, it should return a copy of 'p'. This still doesn't solve runTime and mesh going out of scope, though; and you're right - instantiating them as static is one way of doing it. Are you trying to do this to hide the #include statements in one convenient function?

reimund June 7, 2008 14:00

>Can you rewrite it like this?
 
>Can you rewrite it like this?
Sure, but it doesn't compile.

>tmp<volscalarfield> p2 = new volScalarField(p);
There is no tmp<volscalarfield> constructor from a volScalarField*.

If I remove the "new", I get the following output:

...
>Reading field U
>Reading/calculating face flux field phi
>terminate called after throwing an instance of 'std::length_error'
> what(): basic_string::_S_create
>Aborted (core dumped)

Because you repeat that I should use tmp<> to return the local field, could you please explain, how this would internally solve the task of converting the local field into an outside accessible field (assuming it worked)?

>Are you trying to do this to hide the #include statements in one convenient function?
Yes, it could be phrased like this.

Thank you! Reimund

deepsterblue June 9, 2008 13:47

Hmm... Maybe this will work:
 
Hmm... Maybe this will work:

tmp<volscalarfield> initialize(int argc, char *argv[]){
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
#include "createFields.H"

tmp<volscalarfield> p2(new volScalarField(p));
return p2;
}

You'd be able to return only a single field using this function, though. All other fields created in createFields.H still have only local scope.
Using the tmp<> approach is a good way to ensure proper garbage collection.


All times are GMT -4. The time now is 03:53.