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

Register object inside functionObject without static pointer

Register Blogs Community New Posts Updated Threads Search

Like Tree4Likes
  • 2 Post By olesen
  • 1 Post By olesen
  • 1 Post By olesen

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   February 10, 2021, 07:41
Default Register object inside functionObject without static pointer
  #1
Member
 
Tom Lauriks
Join Date: Apr 2020
Posts: 34
Rep Power: 6
Tom Lauriks is on a distinguished road
I'm trying to store an object to the register inside a function object. A closely related post which provided me with a working solution is: https://www.cfd-online.com/Forums/openfoam-programming-development/99207-create-registered-object-runtime-using-functionobject.html


Following the comments in this thread, I wrote:
Code:
   if (!obr_.foundObject<volScalarField>("k"))//Check if k is registered variable
    {
        static autoPtr<volScalarField> kField;//If not, initialize pointer to what will be registered as k 
        if(!kField.valid())//Check if the pointer is set
        {
        kField.set//set sets pointer to what is given
        (
         new volScalarField
         (
            IOobject
            (
               "k",
               obr_.time().timeName(),
               obr_,
               IOobject::NO_READ,
               IOobject::NO_WRITE
            ),
            model.k()
         )
        );
        Info << "function object TKEsgs: pField was not set" << 
        nl << endl;  
        }
        volScalarField& k = kField();//Create reference to the pointer

        k.checkIn();//Add k to the register
        Info <<  "function object TKEsgs: using checkIn" << 
            nl << endl;  
         if (obr_.foundObject<volScalarField>("k"))
        {
            Info <<  "function object TKEsgs: k successfully stored" << 
            nl << endl; 
        }
    }
However, I think that maybe using the static characteristic for the pointer, might not be very elegant c++ coding.

The code above can either be inserted in the constructor of my function object (the body of the function) or e.g. in the execute function and it will work. However, when I try to insert similar code used in fieldAverage at said locations, the object is not stored to the register, or I cannot find it afterwards. Said code is:
Code:
    if (!obr_.foundObject<volScalarField>("k"))
    {
        obr_.store
        (
            new volScalarField 
            (
                IOobject
                (
                    "k",
                    obr_.time().timeName(),
                    obr_,
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                model.k()
            )
        ); 
        Info << type() << " " << name() << " storing k to register" << 
            nl << endl;  
         if (obr_.foundObject<volScalarField>("k"))
        {
            Info << type() << " " << name() << " k successfully stored" << 
            nl << endl; 
        }
    }
In the log file, I do not get the "k successfully stored" message.

In fieldAverage, similar code stores the mean fields to the register, which evidently works. However, I cannot spot what is different to what I'm trying with the code above. The code of fieldAverage is present in the fieldAverageTemplates.C file, and is ultimately called from the initialize function, it seems to me. With the code being:
Code:
    if (obr_.foundObject<Type>(meanFieldName))
    {}
       else
    {
        const Type& baseField = obr_.lookupObject<Type>(fieldName);

        // Store on registry
        obr_.store
        (
            new Type
            (
                IOobject
                (
                    meanFieldName,
                    obr_.time().timeName(obr_.time().startTime().value()),
                    obr_,
                    restartOnOutput_
                  ? IOobject::NO_READ
                  : IOobject::READ_IF_PRESENT,
                    IOobject::NO_WRITE
                ),
                1*baseField
            )
        );
    }
}

Can anyone explain me why this is working in fieldAverage and not in my function object?
Tom Lauriks is offline   Reply With Quote

Old   April 12, 2023, 11:23
Default
  #2
Senior Member
 
Domenico Lahaye
Join Date: Dec 2013
Posts: 736
Blog Entries: 1
Rep Power: 17
dlahaye is on a distinguished road
Any solution to this issue? Thx!
dlahaye is offline   Reply With Quote

Old   April 13, 2023, 03:49
Default
  #3
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by Tom Lauriks View Post
I'm trying to store an object to the register inside a function object. A closely related post which provided me with a working solution is: https://www.cfd-online.com/Forums/openfoam-programming-development/99207-create-registered-object-runtime-using-functionobject.html


Following the comments in this thread, I wrote:
Code:
   if (!obr_.foundObject<volScalarField>("k"))//Check if k is registered variable
    {
        static autoPtr<volScalarField> kField;//If not, initialize pointer to what will be registered as k 
        if(!kField.valid())//Check if the pointer is set
        {
        kField.set//set sets pointer to what is given
        (
         new volScalarField
         (
            IOobject
            (
               "k",
               obr_.time().timeName(),
               obr_,
               IOobject::NO_READ,
               IOobject::NO_WRITE
            ),
            model.k()
         )
        );
        Info << "function object TKEsgs: pField was not set" << 
        nl << endl;  
        }
        volScalarField& k = kField();//Create reference to the pointer

        k.checkIn();//Add k to the register
        Info <<  "function object TKEsgs: using checkIn" << 
            nl << endl;  
         if (obr_.foundObject<volScalarField>("k"))
        {
            Info <<  "function object TKEsgs: k successfully stored" << 
            nl << endl; 
        }
    }
However, I think that maybe using the static characteristic for the pointer, might not be very elegant c++ coding.

The code above can either be inserted in the constructor of my function object (the body of the function) or e.g. in the execute function and it will work. However, when I try to insert similar code used in fieldAverage at said locations, the object is not stored to the register, or I cannot find it afterwards. Said code is:
Code:
    if (!obr_.foundObject<volScalarField>("k"))
    {
        obr_.store
        (
            new volScalarField 
            (
                IOobject
                (
                    "k",
                    obr_.time().timeName(),
                    obr_,
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                model.k()
            )
        ); 
        Info << type() << " " << name() << " storing k to register" << 
            nl << endl;  
         if (obr_.foundObject<volScalarField>("k"))
        {
            Info << type() << " " << name() << " k successfully stored" << 
            nl << endl; 
        }
    }
In the log file, I do not get the "k successfully stored" message.

In fieldAverage, similar code stores the mean fields to the register, which evidently works. However, I cannot spot what is different to what I'm trying with the code above. The code of fieldAverage is present in the fieldAverageTemplates.C file, and is ultimately called from the initialize function, it seems to me. With the code being:
Code:
    if (obr_.foundObject<Type>(meanFieldName))
    {}
       else
    {
        const Type& baseField = obr_.lookupObject<Type>(fieldName);

        // Store on registry
        obr_.store
        (
            new Type
            (
                IOobject
                (
                    meanFieldName,
                    obr_.time().timeName(obr_.time().startTime().value()),
                    obr_,
                    restartOnOutput_
                  ? IOobject::NO_READ
                  : IOobject::READ_IF_PRESENT,
                    IOobject::NO_WRITE
                ),
                1*baseField
            )
        );
    }
}
Can anyone explain me why this is working in fieldAverage and not in my function object?



In fieldAverage (which is the correct approach), the existing field is retrieved from the registry if it exists. If it does not exist, a new field (notice the raw pointer) is created and passed to the registry for storage. This means that the field (as a pointer) is now contained and managed by the registry. The lifetime of the local pointer then doesn't matter, there is no need to have a 'delete' or worry about memory leaks since the objectRegistry now manages it a bit like a smart pointer. When the registry is cleared, or goes out of scope it will trigger the deletion of that pointer.
olesen is offline   Reply With Quote

Old   April 13, 2023, 04:14
Default
  #4
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Now added information in https://develop.openfoam.com/Develop...terns/registry
snak and dlahaye like this.
olesen is offline   Reply With Quote

Old   April 16, 2023, 12:55
Default
  #5
Senior Member
 
Domenico Lahaye
Join Date: Dec 2013
Posts: 736
Blog Entries: 1
Rep Power: 17
dlahaye is on a distinguished road
Does it make sense to replace in https://develop.openfoam.com/Develop...terns/registry

Code:
    fieldPtr = new volScalarField
    (
        IOobject
        (
            resultName_,
            mesh.time().timeName(),
            mesh.thisDb(),
            IOobject::NO_READ,
            IOobject::NO_WRITE
            // implicit:  IOobject::REGISTER
        ),
        mesh,
        dimensionedScalar(dimless, Zero)
        // implicit:  calculatedType()
    );
by

Code:
    fieldPtr = new volScalarField
    (
        IOobject
        (
            resultName_,
            mesh().time().timeName(),
            mesh().thisDb(),
            IOobject::NO_READ,
            IOobject::NO_WRITE
            // implicit:  IOobject::REGISTER
        ),
        mesh(),
        dimensionedScalar(dimless, Zero)
        // implicit:  calculatedType()
    );
(replaced mesh by mesh() at 3 instances) to help out those struggling in the same way I am struggling with this?

Thanks for this wonderful post!
dlahaye is offline   Reply With Quote

Old   April 18, 2023, 10:24
Default
  #6
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Context is everything here. You might have a mesh reference available directly as a 'mesh' variable, or as a private/protected 'mesh_' variable, or a 'mesh()' method.
Having 'mesh()' would be even more confusing, when some has mesh' as a variable.
olesen is offline   Reply With Quote

Old   April 18, 2023, 12:59
Default
  #7
Senior Member
 
Domenico Lahaye
Join Date: Dec 2013
Posts: 736
Blog Entries: 1
Rep Power: 17
dlahaye is on a distinguished road
Aha, Thx.

In case that an example illustrating the post is seen to be beneficial, here is one

Code:
functions
{

    // here autoPtr is used to avoid that Tsclaled goes out of scope as soon as the function is left;
    // for an example, see e.g. https://www.cfd-online.com/Forums/openfoam-programming-development/99207-create-registered-object-runtime-using-functionobject.html
    // how to share this data among functionObjects: using object registry (currently checkin() fails) or using shared pointer

    // scales the temperature with a constant and stores scaled value in the object registry
    scalingNut
    {
        type    coded;
        libs    ("libutilityFunctionObjects.so");
        name    scalingNut;

        codeOptions // this seems mandatory: without it, code fails to compile 
        #{
            -I$(LIB_SRC)/meshTools/lnInclude \
            -I$(LIB_SRC)/OpenFOAM/lnInclude
        #};

        codeExecute 
        #{
        #};

        codeWrite // "to avoid No critical "code" prefixed keywords found."
        #{
           Info<<" Scaling the kinematic viscosity at time "<<endl;
           Info<<" t = " << mesh().time().timeName() <<" with scaling factor "<< endl;
        #};

        codeWrite
        #{
          //..Defines scaling constant as a fixed scalar
          const scalar sigmat = .5;

          //..Defines const pointer to existing T-field
          const volScalarField& nut = mesh().lookupObject<volScalarField>("nut");

          //..Check whether nutscaled is a registered variable..
          if (!mesh().foundObject<volScalarField>("nutscaled"))
          {
            //..If not, initialize auto pointer to what will be registered as nutscaled
            static autoPtr<volScalarField> nutscaledField;

            //..Check whether the auto pointer is set
            if(!nutscaledField.valid())
            {
                //..If not, set auto pointer
                nutscaledField.set
                (
                    new volScalarField
                    (
                        IOobject
                        (
                            "nutscaled",
                            mesh().time().timeName(),
                            mesh().thisDb(),
                            IOobject::NO_READ,
                            IOobject::AUTO_WRITE
                        ),
                        mesh(),
                        dimensionedScalar("nut",nut.dimensions(), 0.0)
                    )
                );
                Info<<"  [fct-obj-scalingnut]:: nutscaledField was auto-ptr not set" << endl;
            }

            volScalarField& nutscaled = nutscaledField();//..Create reference to the pointer

            forAll(nut,cellI){
              nutscaled[cellI] = nut[cellI]/sigmat;
            }

            Info<<"  [fct-obj-scalingnut]:: checkIn of nutscaled" << endl;
            nutscaled.checkIn(); //..Add nutscaled to the registry

          }

          if (mesh().foundObject<volScalarField>("nutscaled"))
          {
            Info<<"  [fct-obj-scalingnut]:: nutscaled successfully stored in object registry" << endl;
          }

        #};

     }

    lookupScalednut
    {
        type    coded;
        libs    ("libutilityFunctionObjects.so");
        name    lookupScalednut;

        codeOptions // this seems mandatory: without it, code fails to compile
        #{
          -I$(LIB_SRC)/meshTools/lnInclude \
          -I$(LIB_SRC)/OpenFOAM/lnInclude
        #};

        codeExecute
        #{
        #};

        codeWrite // "to avoid No critical "code" prefixed keywords found."
        #{
          const volScalarField& nut = mesh().lookupObject<volScalarField>("nut");
          const volScalarField& nutscaled = mesh().lookupObject<volScalarField>("nutscaled");
          Info<<" Looking up the scaled temperature at time "<<endl;
          Info<<" t = " << mesh().time().timeName() << endl;
          Info<<" with magnitude = " << gSumMag(nut) << endl;
          Info<<" with magnitude = " << gSumMag(nutscaled) << endl;
        #};

    }

    mixtureFraction
    {
        type            scalarTransport;
        libs            ("libsolverFunctionObjects.so");

        // Name of scalar field to transport, default = 's'
        field           mf;

        // Name of flux field, default = 'phi'
        phi             phi;

        // Name of density field for compressible cases, default = 'rho'
        rho             rho;

        // Set the scalar to zero on start/re-start
        resetOnStartUp  no;

        // Name of field to use when looking up schemes from fvSchemes
        // default = <field>
        schemesField    Yi;

        // Diffusivity

        // Fixed value diffusivity
        D               0.001;

        // Name of field to use as diffusivity, default = 'none'
        nut             nutScaled;

        // Run-time selectable sources
        // fvOptions
        //{
        //...
        //}
    }

}
dlahaye is offline   Reply With Quote

Old   April 18, 2023, 14:30
Default
  #8
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Okay, but this seems even more confusing to me, or at least needs some more comments about why you are trying to store a field locally (in the autoPtr), and register it with the objectRegistry. The only advantage I can see (versus just storing it on the objectRegistry directly) is if you expect your functionObject to be removed during the run time if the user edits the controlDict and you don't want the nut field to hang around any longer than needed. Otherwise, it is quite a few more lines of code.
dlahaye likes this.
olesen is offline   Reply With Quote

Old   April 18, 2023, 14:32
Default
  #9
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Since you are modifying the internal field directly for whatever reason, you will also need to have correctBoundaryConditions() - otherwise the calculated patch values will be inconsistent and retain their initial 0.0 value.
dlahaye likes this.
olesen is offline   Reply With Quote

Old   April 19, 2023, 03:26
Default
  #10
Senior Member
 
Domenico Lahaye
Join Date: Dec 2013
Posts: 736
Blog Entries: 1
Rep Power: 17
dlahaye is on a distinguished road
Dear Mark,

Many thanks.

The scope is to perform scalar transport with a scaled variant of nut. What your seeing are first attempts. These attempts are blurred by partial understanding on by behalf. I will look into the matter and get here.

Cheers, Domenico.
dlahaye is offline   Reply With Quote

Old   April 19, 2023, 05:12
Default
  #11
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,695
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Not an issue, but gSumMag() is redundant on GeometricField (eg, volScalarField). Can just write sumMag() if you want.
olesen is offline   Reply With Quote

Old   April 19, 2023, 11:54
Default
  #12
Senior Member
 
Domenico Lahaye
Join Date: Dec 2013
Posts: 736
Blog Entries: 1
Rep Power: 17
dlahaye is on a distinguished road
Quote:
Originally Posted by olesen View Post
<cut> why you are trying to store a field locally (in the autoPtr), and register it with the objectRegistry. <cut>
The reason is that "the object is destroyed when it goes out of scope and the during that the destructor calls checkOut" as pointer out by Bernard Gschaider in Item 6 of Create registered object at runtime using a functionObject.

Thx, D.
dlahaye is offline   Reply With Quote

Reply

Tags
function object, functionobject, object, register, registry


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


Similar Threads
Thread Thread Starter Forum Replies Last Post
GGI: rotating object completely within a static object Tobb OpenFOAM 2 October 15, 2010 06:29
register a new object sprayRASModel yejungong OpenFOAM Running, Solving & CFD 0 May 22, 2009 04:04
Compilation error OF1.5-dev on Suse10.3 darenyang OpenFOAM Installation 0 April 29, 2009 04:55
[blockMesh] BlockMeshmergePatchPairs hjasak OpenFOAM Meshing & Mesh Conversion 11 August 15, 2008 07:36
OpenFOAM141dev linking error on IBM AIX 52 matthias OpenFOAM Installation 24 April 28, 2008 15:49


All times are GMT -4. The time now is 09:54.