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/)
-   -   Accessing all cells that are next to a wall (https://www.cfd-online.com/Forums/openfoam-programming-development/74824-accessing-all-cells-next-wall.html)

dohnie April 9, 2010 07:52

Accessing all cells that are next to a wall
 
Hi,
I am stuck on a combustion model. I have implemented a source term (a volScalarField). I need to recalculate the source term in every timestep but force it to be zero in all cells that are next to a wall.
Can anybody help me how to get the information which cells are next to a wall?

olesen April 11, 2010 11:44

Quote:

Originally Posted by dohnie (Post 253932)
Hi,
I am stuck on a combustion model. I have implemented a source term (a volScalarField). I need to recalculate the source term in every timestep but force it to be zero in all cells that are next to a wall.
Can anybody help me how to get the information which cells are next to a wall?

Just loop over the boundary patches and select the wall patches.
Then loop over those faces - the face owner() is the cell ID that you are looking for.

deepsterblue April 11, 2010 12:18

Alternatively, you can specify:

mesh.boundaryMesh()[patchI].faceCells();

to obtain a list of cells adjacent to patchI.

holger_marschall April 11, 2010 13:03

Hi Florian,

I have implemented this, for switching off some force coefficients near to walls. Simply use (as already described):

Code:

const fvPatchList& patches = mesh.boundary();

    forAll(patches, patchi)
    {
        const fvPatch& curPatch = patches[patchi];
        if (isType<wallFvPatch>(curPatch))
        {
            forAll(curPatch, facei)
            {
                label faceCelli = curPatch.faceCells()[facei];
                //your stuff
            }
        }
    }

If needed you could add a word (or wordList) holding only the patch(es) under consideration and check for the right patch name in the if-statement. This could be accomplished most conveniently via dictionary lookup, in case you want to change the corresoponding patch names in a flexible way.

Hope that helps :)

best,

dohnie April 12, 2010 05:44

Thanks!
 
Thanks to all of you, that really helped!

Based on Holger's suggestion I make a list of all cells at the beginning of a run

Code:

const fvPatchList& patches = mesh.boundary();
labelList wallList;
wallList.clear();

    forAll(patches, patchi)
    {
        const fvPatch& curPatch = patches[patchi];
        if (isType<wallFvPatch>(curPatch))
        {
            forAll(curPatch, facei)
            {
                label faceCelli = curPatch.faceCells()[facei];
                wallList.resize(wallList.size()+1);
                wallList[wallList.size()-1]=faceCelli;
            }
        }
    }

(You have to include wallFvPatch.H to make this work)

I'm not much of a C++ crack, but I suppose that the adding of elements to wallList could be done in a nicer way (append() only works for appending lists, not elements to a list).

Then I can refer to this list in every time step to set the source term to zero:

Code:

forAll(wallList,i)  omegaC[wallList[i]] = 0.0;

olesen April 12, 2010 07:42

Just to add a little kibitzing ...
Your approach is OK, but it might be faster and more efficient to use a DynamicList of labels instead. This gives you an append() method and should be faster since it avoids too many small resizing operations.

For example,
Code:

const fvPatchList& patches = mesh.boundary();
DynamicList<label> dynWallList;

forAll(patches, patchI)
{
    const fvPatch& p = patches[patchI];
    if (isType<wallFvPatch>(p))
    {
        forAll(p, pFaceI)
        {
            dynWallList.append(p.faceCells()[pFaceI]);
        }
    }
}

// make invariant labelList, reusing allocated memory
const labelList wallList(dynWallList.xfer());

With either approach, you will get double entries for cells that have two wall faces (which shouldn't be an issue in your case).

Another alternative would be to first note which cells are addressed and then build the label list afterwards.
For example,

Code:

const fvPatchList& patches = mesh.boundary();
PackedBoolList isWallCell(mesh.nCells());

// stage 1: find the cells that are near a wall
forAll(patches, patchI)
{
    const fvPatch& p = patches[patchI];
    if (isType<wallFvPatch>(p))
    {
        forAll(p, pFaceI)
        {
            isWallCell.set(p.faceCells()[pFaceI]);
        }
    }
}

// stage 2: build labelList from list of bools
labelList wallList(isWallCell.count());
label nWallCells = 0;
forAll(isWallCell, celli)
{
    if (isWallCell.get(celli))
    {
        wallList[nWallCells++] = celli;
    }
}

// paranoid
wallList.setSize(nWallCells);

A third way would be similar to the first one, but slightly more efficient again.

Code:

const fvPatchList& patches = mesh.boundary();
 label nWallCells = 0;

// stage 1: get the max number of wall cells (including doubled entries)
forAll(patches, patchI)
{
    const fvPatch& p = patches[patchI];
    if (isType<wallFvPatch>(p))
    {
        nWallCells += p.size();
    }
}

// stage 2: build labelList

labelList wallList(nWallCells);
nWallCells = 0;
 
 forAll(patches, patchI)
 {
    const fvPatch& p = patches[patchI];
    if (isType<wallFvPatch>(p))
    {
        forAll(p, faceI)
        {
            wallList[nWallCells++] = p.faceCells()[faceI];
        }
    }
 }

// safety
wallList.setSize(nWallCells);

You could use similar trick with the xfer() method if you wanted your list to be invariant.

holger_marschall April 12, 2010 11:38

Quote:

Originally Posted by olesen (Post 254287)
Just to add a little kibitzing ...

why kibitzing...? These are nice adds. Thanks a lot, Mark.

best,

olesen April 13, 2010 08:21

Quote:

Originally Posted by holger_marschall (Post 254338)
why kibitzing...? These are nice adds. Thanks a lot, Mark.

Actually, for even better efficiency and more flexibility, it is probably better to avoid the faceCells() method and also to avoid storing any extra lists.

Initially it may appear somewhat less convenient to use the face owners directly, but you only need to add in the patch start as an offset.

Here is what I think would be a useful, and more general implementation:

Code:

#ifndef setWallCells_H
#define setWallCells_H

#include "wallFvPatch.H"

template<class Type>
void setWallCells
(
    GeometricField<Type, fvPatchField, volMesh>& field,
    const Type& value
)
{
    // the patches and the face owners
    const fvPatchList& patches = field.mesh().boundary();
    const labelList& own = field.mesh().owner();

    forAll(patches, patchI)
    {
        const fvPatch& p = patches[patchI];

        // only do walls
        if (isType<wallFvPatch>(p))
        {
            const polyPatch& pp = p.patch();
            forAll(pp, patchFaceI)
            {
                field[own[pp.start() + patchFaceI]] = value;
            }
        }
    }
}

#endif

Within the code you could then simply use it like this:
Code:

const scalar omegaWallValue = SMALL;

setWallCells(omegaC, omegaWallValue);

// should work with other volFields too:
setWallCells(U, vector::zero);


nikwin May 19, 2010 13:19

Hello,

Holger, you're writing that it's possible to change patch name in a convenient way via dictionary lookup. Could you please give an example since I can't get it? I would need it both for vol<type>fields and for the fvMesh.

Thanks
/NW

holger_marschall May 19, 2010 16:46

Quote:

Originally Posted by nikwin (Post 259496)
Holger, you're writing that it's possible to change patch name in a convenient way via dictionary lookup. Could you please give an example since I can't get it? I would need it both for vol<type>fields and for the fvMesh.
/NW

Hi Niklas,

no, not to change. I was talking just about reading them in.
This simply might be accomplished by a word or wordlist (for multiple patches) and an dictionary lookup:

For example: Provide this in a dictionary (say in arbitraryNameDict)
Code:

wallPatches (wallName1 wallName2);
and some appropriate lines in createFields.H, for instance:
Code:

IOdictionary arbitraryNameDict
(
    IOobject
    (
        "arbitraryNameDict",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ,
        IOobject::NO_WRITE
    )
);

wordList wallPatchNames
(
    arbitraryNameDict.lookup("wallPatches")
);

which makes the wallPatches declared in the dictionary file available in your top-level code.

Hope that helps.

best regards,

nikwin May 24, 2010 09:14

Ok, Thanks anyway! I realized however that it's possible via fvMeshSubset to write faces into a user supplied patch which solves my problem.

All the Best
/NW

gwierink June 14, 2010 12:38

Dear all,

Neat stuff, thanks for that! :D I would like to do a routine over only internal cells. Is there a function to retrieve the internal cells only? Thank you in advance!


All times are GMT -4. The time now is 13:18.