CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (http://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Newbie Question on PtrList usage (http://www.cfd-online.com/Forums/openfoam-programming-development/123777-newbie-question-ptrlist-usage.html)

chyczewski September 20, 2013 13:56

Newbie Question on PtrList usage
 
I recently received the following information from another post:

If N, you need
PtrList<volScalarField> ks(N);
PtrList<volScalarField> thetas(N);
You will access them as ks[i] and thetas[i].
If NxM, make a PtrList<PtrList<volScalarField> > bigOne(N);
forAll (bigOne, i)
{
bigOne.set(i, new PtrList<volScalarField>(M));
}
and then fill the lot. You will access them as bigOne[i][j];

I am able to create the arrays via PtrList as described above but I am not able to access them. If I try

ks[1]=1.0;

I get a fatal error: hanging pointer, cannot dereference at runtime.

If I try

ks.set(1,1.0);


I get a number of compilation errors. Any suggestions?

mlaurita September 24, 2013 15:03

What are you trying to do with the line ks[1]=1.0? I'm not an expert on PtrLists, but I believe that ks[1] is a pointer to a volScalarField, so you can't just assign a value to it.

For example, if you were trying to set a value in a particular grid cell for the field pointed to by ks[1] you would need to do something like:

ks[1]->internalField()[cellI] = 1.0 (because ks[1] is a pointer you need the '->' instead of the '.' to call a member function)

or maybe...

*ks[1][cellI] = 1.0 (I'm not 100% sure about this one, but the thinking is that you would have to dereference the pointer to access the volScalarField, and then assign a value to the desired cell)

Hope this helps a little.

MJL

chyczewski September 25, 2013 08:13

Matt,

Thanks for posting a reply. It helped but didn't get me there yet. I tried your suggestions and they unfortunately led to compiler errors:

invalid type argument of unary '*' (have 'double')
*ks[1][1] = 1.0;
^
base operand of '->' has non-pointer type 'Foam::GeometricField<double, Foam::fvPatchField, Foam::volMesh>'
ks[1]->internalField()[1] = 1.0;
^

The second error suggests that PrtList doesn't return a pointer. If I

PtrList<volScalarField> ks(10);

then ks.size() returns 0 and ks.empty() returns true. I was expecting the size to be equal to 10 times the number of cells. If I first

ks.setSize(mesh.C().size());

then ks.size() returns #cells and ks.empty() returns false.

But I was expecting ks.size() to return #cells*10. I am at a bit of a loss. Any other suggestions?

mlaurita September 25, 2013 09:19

My mistake... a look at PtrList.H reveals that the operator [] returns a reference to the list element, not a pointer, so I think you could do something like:

ks[1].internalField[cellI] = 1

or just

ks[1][cellI] = 1

to set/access the value of volScalarField #1 in cell #cellI

I'm not sure why PtrList<volScalarField> ks(10) is returning a size of 0. It should return 10, because ks is a list of pointers to 10 volScalarFields. You shouldn't expect it to be 10*nCells. Each one of the elements of the PtrList is a volScalarField of size nCells (e.g. ks[0].size() should return nCells, because ks[0] is a reference to the first volScalarField pointed to by ks; likewise ks[1].size(), ks[2].size(), etc, would all give you nCells).

Don't forget that you would need to assign each pointer in the list to actually point to something (i.e. an existing volScalarField) before you can set/access any field values.

Makes sense?

MJL

GPesch September 28, 2013 11:27

Quote:

Originally Posted by chyczewski (Post 453531)
Matt,

Thanks for posting a reply. It helped but didn't get me there yet. I tried your suggestions and they unfortunately led to compiler errors:

invalid type argument of unary '*' (have 'double')
*ks[1][1] = 1.0;
^
base operand of '->' has non-pointer type 'Foam::GeometricField<double, Foam::fvPatchField, Foam::volMesh>'
ks[1]->internalField()[1] = 1.0;
^

The second error suggests that PrtList doesn't return a pointer. If I

PtrList<volScalarField> ks(10);

then ks.size() returns 0 and ks.empty() returns true. I was expecting the size to be equal to 10 times the number of cells. If I first

ks.setSize(mesh.C().size());

then ks.size() returns #cells and ks.empty() returns false.

But I was expecting ks.size() to return #cells*10. I am at a bit of a loss. Any other suggestions?

ks.size() won't return the amount #cells*10 if you initialize it by ks(10), because it then has only 10 elements. If each of the 10 elements is a volScalarField, each of the 10 elements has a size of #cells. But, the function ks.size() is not interested in the size of each of its elements, but is only interested in the amount of elements ks has, which is still 10...

I guess(!) the problem is that you have to actually initialize the volScalarFields in your PtrList by iterating through it.

E.g.:

Code:

for (int n=1; n==10, n++)
{
    ks.set(n, volScalarField(....));
}

You then need to use a valid constructor for volScalarField(...)...

Does it make sense?

//Edit:

To give you an example of a code I recently produced and which is working for me:

Code:

    forAll(moleculeTypeIds_, tI)
    {
        adsorbedParcels_.set
        (
            tI,
            volScalarField
            (
                IOobject
                (
                    "adsorbedParcels_" + moleculeTypeIds_[tI],
                    this->owner().mesh().time().timeName(),
                    this->owner().mesh(),
                    IOobject::READ_IF_PRESENT,
                    IOobject::AUTO_WRITE
                ),
                this->owner().mesh(),
                dimensionedScalar("zero",  dimensionSet(0, 0, 0, 0, 0), 0.0)
            )
        );
    }

With "adsorbedParcels_" being a PtrList<volScalarField> with the same size as "moleculeTypeIds_"...

chyczewski October 1, 2013 10:46

Thanks Matt and GPesch! What you are saying makes sense and the code is behaving as you suggest it would. For example, here is my code to generate a 2D array of volScalarField's :

Code:

PtrList<PtrList<volScalarField> > wasd(imax);
forAll (wasd,n)
{
  wasd.set(n, new PtrList<volScalarField>(jmax));
}
forAll (wasd, n)
{
  forAll (wasd[n], m)
  {
      wasd[n].set(m, new volScalarField
                        (
                        IOobject
                        (
                        "amn",
                        runTime.timeName(),
                        mesh,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                    mesh,
                    dimensionedScalar("amn", dimensionSet(0,4,1,0,0,0,0),0.0)
                    ));
  }
}

So I now have wasd[imax][jmax][ncells], which is what I wanted. But I am wondering if my volScalarField parameters are the most appropriate. For example, how does OpenFOAM use "amn"? Thanks again.

GPesch October 1, 2013 16:39

Actually "amn" is the name of the dimensioned scalar - I do not know what OpenFOAM does with it. I have never experienced, that it matters what name you set for the dimensioned scalar.

Although I am quite interested in the answer to your question: What influence has the name of the dimensionedScalar?


All times are GMT -4. The time now is 02:11.