|
[Sponsors] |
June 4, 2008, 16:58 |
Hi!
I hope that not only user
|
#1 |
Guest
Posts: n/a
|
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 |
|
June 4, 2008, 21:40 |
Hi Reimund
It seems that th
|
#2 |
Senior Member
|
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 |
|
June 5, 2008, 03:05 |
Well, You can duplicate a geom
|
#3 |
Senior Member
Hrvoje Jasak
Join Date: Mar 2009
Location: London, England
Posts: 1,907
Rep Power: 33 |
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
__________________
Hrvoje Jasak Providing commercial FOAM/OpenFOAM and CFD Consulting: http://wikki.co.uk |
|
June 5, 2008, 17:33 |
Thanks for your answers. I thi
|
#4 |
Guest
Posts: n/a
|
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"); } |
|
June 5, 2008, 18:09 |
Static variables (I believe) h
|
#5 |
Senior Member
Sandeep Menon
Join Date: Mar 2009
Location: Amherst, MA
Posts: 403
Rep Power: 25 |
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? |
|
June 5, 2008, 18:35 |
>Static variables (I believe)
|
#6 |
Guest
Posts: n/a
|
>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 |
|
June 5, 2008, 22:41 |
Hi Reimund
Return the refe
|
#7 |
Senior Member
|
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 |
|
June 5, 2008, 22:48 |
Can you rewrite it like this?
|
#8 |
Senior Member
Sandeep Menon
Join Date: Mar 2009
Location: Amherst, MA
Posts: 403
Rep Power: 25 |
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? |
|
June 7, 2008, 15:00 |
>Can you rewrite it like this?
|
#9 |
Guest
Posts: n/a
|
>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 |
|
June 9, 2008, 14:47 |
Hmm... Maybe this will work:
|
#10 |
Senior Member
Sandeep Menon
Join Date: Mar 2009
Location: Amherst, MA
Posts: 403
Rep Power: 25 |
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. |
|
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
How to convert from GeometricField to fvMatrix | waynezw0618 | OpenFOAM Running, Solving & CFD | 2 | January 8, 2021 17:35 |
Manipulation of cellvalue of a geometricField | ivan_cozza | OpenFOAM Running, Solving & CFD | 2 | September 25, 2008 14:58 |
Create GeometricField without IOobject | nadine | OpenFOAM Running, Solving & CFD | 3 | August 15, 2008 10:24 |
Accessing data of geometricField | bird | OpenFOAM Running, Solving & CFD | 1 | August 28, 2007 19:21 |
Duplicate mesh in FIELDVIEW | Jing | Siemens | 1 | August 4, 2003 04:08 |