CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM (http://www.cfd-online.com/Forums/openfoam/)
-   -   Access particle data from functionObject (http://www.cfd-online.com/Forums/openfoam/75528-access-particle-data-functionobject.html)

CedricVH April 28, 2010 05:55

Access particle data from functionObject
 
Is there a way to access particle data from a functionObject? The standard way of accessing a field or a mesh in a functionObject is with this code:

Code:

const volVectorField& velocity = obr_.lookupObject<volVectorField>("U");
const fvMesh& mesh=refCast<const fvMesh>(obr_);

However, this system does not work for clouds (thermoClouds or kinematicClouds) as this code:

Code:

const passiveParticleCloud myCloud = obr_.lookupObject<passiveParticleCloud>("kinematicCloud1");
gives me this error:

Code:

/home/cedric/OpenFOAM/OpenFOAM-1.6.x/src/lagrangian/basic/lnInclude/passiveParticleCloud.H: In member function ‘virtual void Foam::patchParticleFunctionObject::write()’:
/home/cedric/OpenFOAM/OpenFOAM-1.6.x/src/lagrangian/basic/lnInclude/passiveParticleCloud.H:58: fout: ‘Foam::passiveParticleCloud::passiveParticleCloud(const Foam::passiveParticleCloud&)’ is private

Using kinematicCloud or basicKinematicCloud instead of passiveParticleCloud does also not work. In the post processing tool particleTracks, passiveParticleCloud is used so I think this is a good programming practice.

Is there a public access function for lagrangian data?

CedricVH April 28, 2010 10:08

The reason why is does not work is due to following code in passiveParticleCloud.H

Code:

//- Disallow default bitwise copy construct
passiveParticleCloud(const passiveParticleCloud&);

//- Disallow default bitwise assignment
void operator=(const passiveParticleCloud&);

This code is also in kinematicCloud.H. When adding an & to get a reference:

Code:

const passiveParticleCloud& myCloud = obr_.lookupObject<passiveParticleCloud>("kinematicCloud1");
Then it compiles but gives a runtime error.

panda60 April 28, 2010 10:25

Dear Cedric,

Could you give me some idea how to make my own functionObject ?
Because nobody can help me.


my purpose is to extract a plane data of internal domain in every time step, and save to disk.
I noticed "surfaces functionObject" can do the similar thing, so I want to modify surfaces functionObject.
I found it belongs to sampling,So I copy src/sampling directory to another position.
I changed the libsampling.so to libmysampling.so
in sampling\sampledSurface\sampledSurfaces, I found 2 places had name "surfaces",

*.H file:
public:
//- Runtime type information
TypeName("surfaces");

*.C file:
PtrList<sampledSurface> newList
(
dict.lookup("surfaces"),
sampledSurface::iNew(mesh_)
);

I changed these "surfaces" to "mysurfaces", and compiled, no problem.
but when I used, had the following mistake,

Starting time loop
--> FOAM Warning :
From function dlLibraryTable::open(const dictionary& dict, const word& libsEntry, const TablePtr tablePtr)
in file lnInclude/dlLibraryTableTemplates.C at line 68
library "libmysampling.so" did not introduce any new entries

Unknown function type mysurfaces
Valid functions are :
5
(
surfaces
fieldAverage
fieldMinMax
sets
probes
)

From function functionObject::New(const word& name, const Time&, const dictionary&)
in file db/functionObjects/functionObject/functionObject.C at line 89.
FOAM exiting

It seems that my modified name haven't been registed in functionObject.
Could you give me some help ?

I just want to copy the original sampling functionObject ,and modify "surfaces" functionObject to "mysurfaces" functionObject .

Thanks.

CedricVH April 29, 2010 04:00

It is not nice to hijack someones thread.

I don't even understand your problem. You don't have to make a new functionObject as the surfaces functionObject can do everything that you want. Just put this in your controlDict:

Code:

functions
{
    type surfaces;
    functionObjectLibs ("libsampling.so");
    surfaceFormat raw;
    interpolationScheme cellPointFace;

    fields
    (
        p    // define the fields you want to monitor
        U
    );

    surfaces
    (
        newPlane
        {
            type plane;
            basepoint (0 0 0);    // coordinates of basepoint of the plane
            normalVector (0 1 0);    // coordinates of the normal vector of the plane
        }
    );
}

If you want to monitor on a patch, just replace the newPlane{...} subdict with:

Code:

existingPatch
{
    type patch;
    patchName wall;    // name of an existing patch
    triangulate false;
}

Can we please get back to my thread?

josp April 29, 2010 06:45

Code:

const passiveParticleCloud& myCloud = obr_.lookupObject<passiveParticleCloud>("kinematicCloud1");
Quote:

Then it compiles but gives a runtime error.
Can you post the output of this runtime error? Also, is the object you are trying to access a basicKinematicCloud?
Why convert it to a passiveParticleCloud at all?

if you are using uncoupledKinematicParcelFoam then a functionObject having this code will access the cloud...

Code:

const  kinematicCloud& abstractBase = obr_.lookupObject<kinematicCloud> ("kinematicCloud");
passiveParticleCloud * pointer = (passiveParticleCloud*) &abstractBase;
Info <<"testing access from functionObject" << endl;
pointer -> info();
Info <<"done testing.." << endl;

This involves casting away constness.. I don't know if there are any other way to access the cloud.

Regards

/Johan

CedricVH April 29, 2010 07:11

The object is indeed a basicKinematicCloud, but the functionObject should work for any type of Cloud. The runtime error I get is:

Code:

--> FOAM FATAL ERROR:

    lookup of kinematicCloud1 from objectRegistry region0 successful
    but it is not a Cloud<passiveParticle>, it is a Cloud<basicKinematicParcel>

    From function objectRegistry::lookupObject<Type>(const word&) const
    in file /home/cedric/OpenFOAM/OpenFOAM-1.6.x/src/OpenFOAM/lnInclude/objectRegistryTemplates.C at line 121.

FOAM aborting

#0  Foam::error::printStack(Foam::Ostream&) in "/home/cedric/OpenFOAM/OpenFOAM-1.6.x/lib/linux64GccDPOpt/libOpenFOAM.so"
#1  Foam::error::abort() in "/home/cedric/OpenFOAM/OpenFOAM-1.6.x/lib/linux64GccDPOpt/libOpenFOAM.so"
#2  Foam::Ostream& Foam::operator<< <Foam::error>(Foam::Ostream&, Foam::errorManip<Foam::error>) in "/home/cedric/OpenFOAM/cedric-1.6.x/applications/bin/linux64GccDPOpt/pimpleLagrangianFoam"
#3  Foam::passiveParticleCloud const& Foam::objectRegistry::lookupObject<Foam::passiveParticleCloud>(Foam::word const&) const in "/home/cedric/OpenFOAM/cedric-1.6.x/lib/linux64GccDPOpt/libsimpleFunctionObjects.so"
#4  Foam::patchParticleFunctionObject::write() in "/home/cedric/OpenFOAM/cedric-1.6.x/lib/linux64GccDPOpt/libsimpleFunctionObjects.so"
#5  Foam::simpleFunctionObject::execute() in "/home/cedric/OpenFOAM/cedric-1.6.x/lib/linux64GccDPOpt/libsimpleFunctionObjects.so"
#6  Foam::functionObjectList::execute() in "/home/cedric/OpenFOAM/OpenFOAM-1.6.x/lib/linux64GccDPOpt/libOpenFOAM.so"
#7  Foam::Time::operator++() in "/home/cedric/OpenFOAM/OpenFOAM-1.6.x/lib/linux64GccDPOpt/libOpenFOAM.so"
#8  main in "/home/cedric/OpenFOAM/cedric-1.6.x/applications/bin/linux64GccDPOpt/pimpleLagrangianFoam"
#9  __libc_start_main in "/lib/libc.so.6"
#10  _start at /build/buildd/eglibc-2.10.1/csu/../sysdeps/x86_64/elf/start.S:116

kinematicCloud1 is indeed of type basicKinematicCloud and not of type Cloud<passiveParticle> so this runtime error is maybe normal. However, when changing my code to:

Code:

const basicKinematicCloud& myCloud = obr_.lookupObject<basicKinematicCloud>("kinematicCloud1");

or to

const kinematicCloud& myCloud = obr_.lookupObject<kinematicCloud>("kinematicCloud1");

or to

const Cloud& myCloud = obr_.lookupObject<Cloud>("kinematicCloud1");

I get a compile error again:

Code:

patch/patchParticleFunctionObject/patchParticleFunctionObject.C: In member function ‘virtual void Foam::patchParticleFunctionObject::write()’:
patch/patchParticleFunctionObject/patchParticleFunctionObject.C:78: fout: expected initializer before ‘&’ token

When I change my code to

Code:

const passiveParticleCloud& myCloud = obr_.lookupObject<basicKinematicCloud>("kinematicCloud1");
It gives me this compile error:

Code:

patch/patchParticleFunctionObject/patchParticleFunctionObject.C: In member function ‘virtual void Foam::patchParticleFunctionObject::write()’:
patch/patchParticleFunctionObject/patchParticleFunctionObject.C:78: fout: ‘basicKinematicCloud’ was not declared in this scope
patch/patchParticleFunctionObject/patchParticleFunctionObject.C:78: fout: no matching function for call to ‘Foam::objectRegistry::lookupObject(Foam::word&) const’

In the make options file, the libraries

Code:

EXE_INC = \
    ...
    -I$(LIB_SRC)/lagrangian/basic/lnInclude \
    -I$(LIB_SRC)/lagrangian/intermediate/lnInclude

LIB_LIBS = \
    ...
    -llagrangian \
    -llagrangianIntermediate

are included. I want to make this functionObject generic for all sorts of Clouds, so it would be nice if I don't have to specify the type of cloud at compile time. Has anyone an idea?

josp April 29, 2010 07:22

Code:

patch/patchParticleFunctionObject/patchParticleFunctionObject.C: In member function ‘virtual void Foam::patchParticleFunctionObject::write()’:
patch/patchParticleFunctionObject/patchParticleFunctionObject.C:78: fout: ‘basicKinematicCloud’ was not declared in this scope
patch/patchParticleFunctionObject/patchParticleFunctionObject.C:78: fout: no matching function for call to ‘Foam::objectRegistry::lookupObject(Foam::word&) const’

did you add #include "basicKinematicCloud.H" ?

But I doubt that will help for what you are trying to do.

Sorry, I have no more ideas now except for the casting example in my previous post.

/Johan

CedricVH April 29, 2010 08:23

Thank you for your effort! Indeed, I forgot to include kinematicParticle.H. Now I can read in a kinematicCloud with:

Code:

const kinematicCloud& myCloud = obr_.lookupObject<kinematicCloud>("kinematicCloud1");
However, I still have to find out how to iterate trough it (the function forAllConstIter(cloudType, cloudName, iter) does not work on kinematicCloud, but this system works with passiveParticleCloud).

For a more general approach, I can read in all sorts of Clouds with the code:

Code:

const passiveParticleCloud myCloud(mesh, "kinematicCloud1");
However, in this way, I can only read clouds that have been written to disk (timestep/lagrangian) and not the clouds stored in the memory. This system works and does not complain about incompatible types.

josp April 29, 2010 10:33

I think these are two completely different things. If you construct a passiveParticleCloud from file it just reads the few basic things that is required to represent the all types of clouds and particles, ignoring the rest.

I don't think you can arbitrarily convert different cloud types just by casting. Sure, if one is the base-class of the other it should work (polymorphism). Also remember that most things uses templates. For instance you can access

Code:

basicKinematicCloud * q;
q->size(); //ok
q->Foam::Cloud<basicKinematicParcel>::size(); //ok

size() was introduced in basic/Cloud so it can be accessed from both the sub and super classes.

rho() is introduced in the kinematicCloud to return the volScalarField rho. It can be called from q directly but not when using q as its sub-class:

Code:

q->rho(); //ok
q->Foam::Cloud<basicKinematicParcel >::rho(); //Will not compile since rho() not defined in Cloud<particleType>.

Here is an example of the danger of casting away constness:
Code:

const  kinematicCloud& a = obr_.lookupObject<kinematicCloud> ("kinematicCloud");
basicKinematicCloud * q = (basicKinematicCloud*) &a;
passiveParticleCloud * w = (passiveParticleCloud*) &a;

Info << q->size() << endl; // gives correct number, in my case 100
Info << w->size() << endl; // compiles, runs and returns garbage!, in my case 1351820000

To iterate, again I have no general solution but this works:
Code:

const  kinematicCloud& a = obr_.lookupObject<kinematicCloud> ("kinematicCloud");
basicKinematicCloud * q = (basicKinematicCloud*) &a;
forAllIter(basicKinematicCloud, *q, pIter)
{
Info << pIter().position() << endl;
}

This will output the position of all the particles:
(0.0283602845304 0.0234627817678 0.0360479880876)
(-0.0332881768715 0.00226135358128 0.0628545323643)
(-0.0187156570622 -0.0364530494542 0.0683987321281)
(-0.0204049351688 -0.0250428155967 0.05823746172)
(0.0287147114221 -0.0221560052747 0.0358643420419)

/Johan

CedricVH April 30, 2010 03:54

I understand your explaination and your suggestion works. Thank you very much!

kel85uk July 21, 2011 12:03

Changing particle properties
 
1 Attachment(s)
Hi Johan and Cedric,

I have a query about the method that you're using to loop over the parcels, can I use it to modify the properties of the parcels? Also I have some issues with this snippet:

Code:

const  kinematicCloud& a = obr_.lookupObject<kinematicCloud> ("kinematicCloud");
basicKinematicCloud * q = (basicKinematicCloud*) &a;
forAllIter(basicKinematicCloud, *q, pIter)
{
  Info << pIter().position() << endl;
}

The compiler gives an error stating that a is not initialized.

Any idea why the problem arises?

Attached is the source of the main solver.

Thank you.

Regards,
Kelvin


All times are GMT -4. The time now is 04:56.