CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM (https://www.cfd-online.com/Forums/openfoam/)
-   -   owner and neighbor (https://www.cfd-online.com/Forums/openfoam/95858-owner-neighbor.html)

vmsandip2011 January 5, 2012 08:19

owner and neighbor
 
can anybody suggest some links or resources which will give more information about the owner and neighbor file how the connectivity is defined etc.
I tried to read user guide but very less information is given there
thanks in advance .

ngj January 5, 2012 08:27

Hi Sandip

The owner/neighbour list are given for each and every face in the computational domain (the neighbour, however, is -1 for boundary faces).

So for face number 0, you could have that owner[0] = 10 and neighbour[0] = 114, which means that the owner cell has index 10, whereas the neighbour cell has index 114. I would recommend to loop over the neighbour list only for the internal faces, as I recall that it might actually not have the size of all of the faces, but only the size of the number of internal faces.

Kind regards,

Niels

anon_a January 5, 2012 11:08

You may also be interested in Hrvoje Jasak's Ph.D. dissertation, section 3.2
http://powerlab.fsb.hr/mwg-internal/...?id=4AI5YdtMgD
Even if it is not entirely what you want, it contains a lot of useful stuff and is a must read.

marupio January 5, 2012 12:35

Each internal face in a mesh has an "owner" and a "neighbour" cell. These are the two cells it borders. There's nothing special about this, and if you are talking only about geometry, we don't need to tell them apart... but since the algorithms need consistent directions for fluxes, we must distinguish them. A positive flux goes from "owner" to "neighbour".

If you are just looking at the text in the file, here's what it means:

The owner and neighbour files each contain a list of cell numbers. The position in that list is the face number. For example:

(
0 // this is face 0
0 // this is face 1
0 // this is face 2
1 // this is face 3
1 // this is face 4
... etc.

So, face 2's "owner" is cell 0, face 4's "owner" is cell 1, and so on.
Note that the owner file is longer than the neighbour file... that's because the owner file also lists boundary faces, whereas the neighbour file does not.

I think I got that right. Keep me honest...

vmsandip2011 January 7, 2012 11:56

owner and neighbor
 
Thanks for the information.
This means if i have 2 different files like follow :
owner
0
0
1
1
2
2
.
.
.
.
etc.

neighbor
1
20
2
21
3
.
.
.
.
etc.
It gives me information like
face 0 's owner is cell 0 and its neighbor is cell 1
face 1 's owner is cell 0 and its neighbor is cell 20
face 2 's owner is cell 1 and its neighbor is cell 2
So basically it will give me the connectivity information about the cells.
Please correct me if i am wrong.

with regards.

lakeat January 5, 2013 15:46

Does this mean in file "faces" the index order of the faces must be put in this way so that internal faces come first and then all the boundary faces that dont have neighboring cells? If not, how could it identify which face doesn't have any neighbour cell?

If what I am saying above is correct, I am wondering why not keep the "neighbour" array the same size as the "owner" array? And fill in "-1" in the "neighbour" array for all the faces that dont have an neighboring cell. By doing so, the index ordering of the faces in "faces" wont be a problem any more.

ngj January 5, 2013 16:51

Hi Daniel,

The easy answer to this question is that if you mix internal and boundary faces into a random ordering, then you would either have to have an additional ordering list to know, which faces are internal, or you would have to perform an additional "if" every time you want to loop over all internal faces (which is done a lot, so that would be prohibitively expensive).

In the way it is done you know for sure and without any risk of segmentation fault that the following can be performed (on the top of my head, so perhaps not fully correct)

Code:

const unallocLabelList & own( mesh.owner() );
const unallocLabelList & nei( mesh.neighbour() );

for( label i=0; i < mesh.nInternalFaces(); i++)
{
    // some operation of volfield[own[i]] and volfield[nei[i]]
}

and then you can afterwards safely treat the boundary faces in whatever way you want.

Kind regards,

Niels

deepsterblue January 5, 2013 21:59

If you had boundary faces scattered in the faces list, the boundary patches would have to maintain a list of indices... Right now, only a start index and patch size is sufficient. Not to mention the extra storage associated with unnecessary -1's for boundaries (the way it was in OF-1.3 and before).

lakeat January 6, 2013 16:12

haha, I see, thank you guys!

lakeat January 10, 2013 01:11

Owner index must be smaller than neighbour index, right?

fumiya January 10, 2013 05:00

You are absolutely correct, owner index < neighbour index.
Please see the following URL:
http://openfoamwiki.net/index.php/Write_OpenFOAM_meshes.

lakeat January 10, 2013 11:54

I saw a warning from here,
Quote:

In particular, the faces in the mesh will be reordered in the upper triangular order, i.e. the ordering of the faces depends on the ordering of the cells. Writing the files yourself will not guarantee that the ordering is optimised for OpenFOAM.
Anyone knows what is the trick in making "the ordering of the faces depends on the ordering of the cells"? As I am writing mesh generator myself, and the writing is so far so good until I found a error warning during the checkMesh complaining about the "upper triangular order".

Any ideas?

deepsterblue January 10, 2013 11:57

Take a look at the renumberMesh source code. It'll tell you how ordering needs to be done.

lakeat January 10, 2013 11:58

Oh, cool, after renumber the mesh, everything is fine!

JackW February 21, 2013 08:47

Hi,

So I have two quick questions if that's ok!

Is the cell index a free choice? i.e. the numbers that appear in the owner file (obviously they have to be consistent with each other). I mean that with the face/points information OF knows of the cells.

Also I have read the Mesh Description page and I am a little confused with this -1 talk, as I have never seen it before. If I omit them from my neighbours/owners files does OF know automatically that these omitted faces are on the boundary and how do I set my start face in this file - is it just that in the faces file I have to put these consecutively?

Thanks a lot,

Jack

deepsterblue February 21, 2013 08:58

Although cell indices can be a free choice in theory, it's hard to maintain them in arrays if there are gaps in the cell numbering order. It's probably a safer option to make sure they are numbered sequentially in a continuous way.

Starting with OF-1.4.1 (I think), there's no need to store -1's for boundaries, and even if it is written that way in the neighbour file, OF currently knows to ignore them for backward compatibility, and truncates the array at the number of internal faces.

JackW February 21, 2013 09:02

Thank you very much!

Jack

zhulianhua August 3, 2014 02:14

Hi, Niels,

I have a question for the the understanding of the implementation of boudary condition for the gaussGrad scheme. I think it has something to do with this post, so I post here.

The code below is form
https://github.com/OpenFOAM/OpenFOAM...ad/gaussGrad.C
We can see, the first forAll() expression loops over the owner list, so for the cell adjacent to the boundary, the facei is the boundary face, that means the neighbour[facei] is -1, but how can we index igGrad with -1?:confused:
Code:

GeometricField<GradType, fvPatchField, volMesh>& gGrad = tgGrad();

    const labelUList& owner = mesh.owner();
    const labelUList& neighbour = mesh.neighbour();
    const vectorField& Sf = mesh.Sf();

    Field<GradType>& igGrad = gGrad;
    const Field<Type>& issf = ssf;

    forAll(owner, facei)
    {
        GradType Sfssf = Sf[facei]*issf[facei];

        igGrad[owner[facei]] += Sfssf;
        igGrad[neighbour[facei]] -= Sfssf;
    }

    forAll(mesh.boundary(), patchi)
    {
        const labelUList& pFaceCells =
            mesh.boundary()[patchi].faceCells();

        const vectorField& pSf = mesh.Sf().boundaryField()[patchi];

        const fvsPatchField<Type>& pssf = ssf.boundaryField()[patchi];

        forAll(mesh.boundary()[patchi], facei)
        {
            igGrad[pFaceCells[facei]] += pSf[facei]*pssf[facei];
        }
    }


Bests,

Lianhua

Quote:

Originally Posted by ngj (Post 400242)
Hi Daniel,

The easy answer to this question is that if you mix internal and boundary faces into a random ordering, then you would either have to have an additional ordering list to know, which faces are internal, or you would have to perform an additional "if" every time you want to loop over all internal faces (which is done a lot, so that would be prohibitively expensive).

In the way it is done you know for sure and without any risk of segmentation fault that the following can be performed (on the top of my head, so perhaps not fully correct)

Code:

const unallocLabelList & own( mesh.owner() );
const unallocLabelList & nei( mesh.neighbour() );

for( label i=0; i < mesh.nInternalFaces(); i++)
{
    // some operation of volfield[own[i]] and volfield[nei[i]]
}

and then you can afterwards safely treat the boundary faces in whatever way you want.

Kind regards,

Niels


zhulianhua August 3, 2014 03:17

Quote:

Originally Posted by zhulianhua (Post 504196)
Hi, Niels,

I have a question for the the understanding of the implementation of boudary condition for the gaussGrad scheme. I think it has something to do with this post, so I post here.

The code below is form
https://github.com/OpenFOAM/OpenFOAM...ad/gaussGrad.C
We can see, the first forAll() expression loops over the owner list, so for the cell adjacent to the boundary, the facei is the boundary face, that means the neighbour[facei] is -1, but how can we index igGrad with -1?:confused:
Code:

GeometricField<GradType, fvPatchField, volMesh>& gGrad = tgGrad();

    const labelUList& owner = mesh.owner();
    const labelUList& neighbour = mesh.neighbour();
    const vectorField& Sf = mesh.Sf();

    Field<GradType>& igGrad = gGrad;
    const Field<Type>& issf = ssf;

    forAll(owner, facei)
    {
        GradType Sfssf = Sf[facei]*issf[facei];

        igGrad[owner[facei]] += Sfssf;
        igGrad[neighbour[facei]] -= Sfssf;
    }

    forAll(mesh.boundary(), patchi)
    {
        const labelUList& pFaceCells =
            mesh.boundary()[patchi].faceCells();

        const vectorField& pSf = mesh.Sf().boundaryField()[patchi];

        const fvsPatchField<Type>& pssf = ssf.boundaryField()[patchi];

        forAll(mesh.boundary()[patchi], facei)
        {
            igGrad[pFaceCells[facei]] += pSf[facei]*pssf[facei];
        }
    }


Bests,

Lianhua

I know why. After testing with a simple case, I found that the mesh.owner() and mesh.neighbour() return only the internal faces' owners and neighbours.

Lianhua


All times are GMT -4. The time now is 20:32.