CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Foam::DynamicList<Type>.append( new Type ); (https://www.cfd-online.com/Forums/openfoam-programming-development/229290-foam-dynamiclist-type-append-new-type.html)

Gerry Kan August 3, 2020 10:15

Foam::DynamicList<Type>.append( new Type );
 
Howdy Foamers:

I have a C++ question. I think I know the answer empirically, but I don't know if my conception is correct.

I have created a DynamicList of some data type (let's call it "Type"). Its starts off with zero elements and I would like to append new terms in it. Currently I would have to declare a new instance in a dummy variable of this "Type" and append this into the list:

Code:

Foam::DynamicList<Type> myList(0);
Type dummy;
myList.append ( dummy );

From reading the code, I believe append() member function makes a copy of dummy into myList. So by that argument I should be able to declare the instance directly in the DynamicList without going through an intermediate variable, like this:

Code:

Foam::DynamicList<Type> myList(0);
myList.append ( new Type );

Okay, I know the new operator will give you a pointer to Type, instead of Type itself. Is there something that will achieve this, or through some kind of temp variable that can be used?

Thanks in advance, Gerry.

deepsterblue August 3, 2020 15:54

Unfortunately, what you're looking for isn't possible with the way DynamicList is currently written. You're effectively looking for functionality identical to "emplace_back" with std::vector. My suggestion would be to ask the "powers that be" to put this functionality in. It isn't hard - just requires a new member function with variadic template arguments which uses std::forward to pass constructor arguments to the element you're trying to construct in-place.

The alternative is to use a DynamicList with an std::auto_ptr<Type> template argument (or, equivalently, std::shared_ptr / std::unique_ptr since auto_ptr was deprecated). But unless the cost of you copy constructor is large, you should question whether this entire effort is worth it, and maybe you should simply live with the temporary.

Gerry Kan August 4, 2020 03:23

Dear Sandeep:

Thanks for your clarification. My dummy variable is local, and the function in question is only called at initialization. So there is not a lot of overhead (for now). I can live with an extra line of code.

The autoPtr thing sounds like something I should explore for some other things I am considering, and I should in the mean time dig a little deeper into it.

Sincerely yours, Gerry.

Gerry Kan August 4, 2020 05:04

At the risk of hijacking my own thread ...

Howdy Foamers:

Does anyone know where volScalarField is defined? I see GeometricField, which is similar, but no volScalarField.

I am asking because I am trying to create a DynamicList<volScalarField>.

Code:

DynamicList<volScalarField> myList(0);
volScalarField dummy (
        IOobject ( "dummy",
                      runTime().timeName(),
                      mesh,
                      IOobject::NO_READ, IOobject::NO_WRITE ),
        mesh,
        dimensionedScalar ( "dummy", dimensionSet(0,0,0,0,0,0,0), 0.0 ) );
myList.append ( dummy );

The .C file containing this code did not report compiling errors, but I got a compile error in the List.C:

Code:

lnInclude/List.C:294:21: error: no matching function for call to ‘Foam::GeometricField<double, Foam::fvPatchField, Foam::volMesh>::GeometricField()’
  294 |            T* nv = new T[label(newSize)];
      |                    ^~~~~~~~~~~~~~~~~~~~~
...
/worknb/users/ech/DEV/OpenFOAM/OpenFOAM-7/src/OpenFOAM/lnInclude/GeometricField.C:697:1: note: candidate: ‘Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField(const Foam::IOobject&, const Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh> >&, const wordList&, const wordList&) [with Type = double; PatchField = Foam::fvPatchField; GeoMesh = Foam::volMesh; Foam::wordList = Foam::List<Foam::word>]’
  697 | Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
      | ^~~~
/worknb/users/ech/DEV/OpenFOAM/OpenFOAM-7/src/OpenFOAM/lnInclude/GeometricField.C:697:1: note:  candidate expects 4 arguments, 0 provided

I have an inkling that "volScalarField" is some kind of macro. As a workaround, I save only the internal field data in the DynamicList and only upload this to a "temp" volScalarField if necessary. Like this:

Code:


// initialization

DynamicList<Field<scalar>> myList(0);
Field<scalar> dummy(100);    // size of 100 is placeholder for this example
myList.append(dummy);

// time loop

volScalarField dummyVolScalarField (
        IOobject ( "dummy",
                      runTime().timeName(),
                      mesh,
                      IOobject::NO_READ, IOobject::NO_WRITE ),
        mesh,
        dimensionedScalar ( "dummy", dimensionSet(0,0,0,0,0,0,0), 0.0 ) );

forAll ( dummyVolScalarField.internalField(), iCell )
        dummyVolScalarField.ref()[iCell] = dummy[iCell];

This seems to compile and work properly.

Sandeep, this is where I would like to ask for your opinion. Would there be any benefit of making dummyVolScalarField into an autoPtr. Ultimately it would more efficient if I could just reference dummyVolScalarField.ref() to dummy directly. Would this be possible?

Thanks in advance, Gerry.


All times are GMT -4. The time now is 08:47.