xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 66e92ce5b5fa7f7e4d7588634eff3e1bd33e3262)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h>
3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h>
4e8f14785SLisandro Dalcin 
5a7748839SVaclav Hapla const char * const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", 0};
6a7748839SVaclav Hapla 
7e8f14785SLisandro Dalcin /* HashIJKL */
8e8f14785SLisandro Dalcin 
9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h>
10e8f14785SLisandro Dalcin 
11e8f14785SLisandro Dalcin typedef struct _PetscHashIJKLKey { PetscInt i, j, k, l; } PetscHashIJKLKey;
12e8f14785SLisandro Dalcin 
13e8f14785SLisandro Dalcin #define PetscHashIJKLKeyHash(key) \
14e8f14785SLisandro Dalcin   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i),PetscHashInt((key).j)), \
15e8f14785SLisandro Dalcin                    PetscHashCombine(PetscHashInt((key).k),PetscHashInt((key).l)))
16e8f14785SLisandro Dalcin 
17e8f14785SLisandro Dalcin #define PetscHashIJKLKeyEqual(k1,k2) \
18e8f14785SLisandro Dalcin   (((k1).i==(k2).i) ? ((k1).j==(k2).j) ? ((k1).k==(k2).k) ? ((k1).l==(k2).l) : 0 : 0 : 0)
19e8f14785SLisandro Dalcin 
20e8f14785SLisandro Dalcin PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1)
21e8f14785SLisandro Dalcin 
223be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1};
233be36e83SMatthew G. Knepley 
243be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey;
253be36e83SMatthew G. Knepley 
263be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \
273be36e83SMatthew G. Knepley   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \
283be36e83SMatthew G. Knepley                    PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index),PetscHashInt((key).l.rank + (key).l.index)))
293be36e83SMatthew G. Knepley 
303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1,k2) \
313be36e83SMatthew G. Knepley   (((k1).i.rank==(k2).i.rank) ? ((k1).i.index==(k2).i.index) ? ((k1).j.rank==(k2).j.rank) ? ((k1).j.index==(k2).j.index) ? ((k1).k.rank==(k2).k.rank) ? ((k1).k.index==(k2).k.index) ? ((k1).l.rank==(k2).l.rank) ? ((k1).l.index==(k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0)
323be36e83SMatthew G. Knepley 
333be36e83SMatthew G. Knepley PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode)
343be36e83SMatthew G. Knepley 
353be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
363be36e83SMatthew G. Knepley {
373be36e83SMatthew G. Knepley   PetscInt i;
383be36e83SMatthew G. Knepley 
393be36e83SMatthew G. Knepley   PetscFunctionBegin;
403be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
413be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
423be36e83SMatthew G. Knepley     PetscInt    j;
433be36e83SMatthew G. Knepley 
443be36e83SMatthew G. Knepley     for (j = i-1; j >= 0; --j) {
453be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
463be36e83SMatthew G. Knepley       A[j+1] = A[j];
473be36e83SMatthew G. Knepley     }
483be36e83SMatthew G. Knepley     A[j+1] = x;
493be36e83SMatthew G. Knepley   }
503be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
513be36e83SMatthew G. Knepley }
529f074e33SMatthew G Knepley 
539f074e33SMatthew G Knepley /*
549a5b13a2SMatthew G Knepley   DMPlexGetFaces_Internal - Gets groups of vertices that correspond to faces for the given cell
55cd921712SStefano Zampini   This assumes that the mesh is not interpolated from the depth of point p to the vertices
569f074e33SMatthew G Knepley */
57ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetFaces_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[])
589f074e33SMatthew G Knepley {
599f074e33SMatthew G Knepley   const PetscInt *cone = NULL;
60ba2698f1SMatthew G. Knepley   DMPolytopeType  ct;
619f074e33SMatthew G Knepley   PetscErrorCode  ierr;
629f074e33SMatthew G Knepley 
639f074e33SMatthew G Knepley   PetscFunctionBegin;
649f074e33SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
669f074e33SMatthew G Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
67ba2698f1SMatthew G. Knepley   ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, numFaces, faceSize, faces);CHKERRQ(ierr);
68439ece16SMatthew G. Knepley   PetscFunctionReturn(0);
69439ece16SMatthew G. Knepley }
70439ece16SMatthew G. Knepley 
71439ece16SMatthew G. Knepley /*
72439ece16SMatthew G. Knepley   DMPlexRestoreFaces_Internal - Restores the array
73439ece16SMatthew G. Knepley */
74ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaces_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[])
75439ece16SMatthew G. Knepley {
76439ece16SMatthew G. Knepley   PetscErrorCode  ierr;
77439ece16SMatthew G. Knepley 
78439ece16SMatthew G. Knepley   PetscFunctionBegin;
79cd921712SStefano Zampini   if (faces) { ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr); }
80439ece16SMatthew G. Knepley   PetscFunctionReturn(0);
81439ece16SMatthew G. Knepley }
82439ece16SMatthew G. Knepley 
83439ece16SMatthew G. Knepley /*
84439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
85439ece16SMatthew G. Knepley */
86ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[])
87439ece16SMatthew G. Knepley {
88439ece16SMatthew G. Knepley   PetscInt       *facesTmp;
89439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
90439ece16SMatthew G. Knepley   PetscErrorCode  ierr;
91439ece16SMatthew G. Knepley 
92439ece16SMatthew G. Knepley   PetscFunctionBegin;
93439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
95439ece16SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
9669291d52SBarry Smith   if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);}
97ba2698f1SMatthew G. Knepley   switch (ct) {
98ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
99ba2698f1SMatthew G. Knepley       if (numFaces) *numFaces = 0;
100ba2698f1SMatthew G. Knepley       if (faceSize) *faceSize = 0;
101ba2698f1SMatthew G. Knepley       break;
102ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
103c49d9212SMatthew G. Knepley       if (faces) {
104c49d9212SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
105c49d9212SMatthew G. Knepley         *faces = facesTmp;
106c49d9212SMatthew G. Knepley       }
107c49d9212SMatthew G. Knepley       if (numFaces) *numFaces = 2;
108c49d9212SMatthew G. Knepley       if (faceSize) *faceSize = 1;
109c49d9212SMatthew G. Knepley       break;
110ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
1119a5b13a2SMatthew G Knepley       if (faces) {
1129a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1139a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1149a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[0];
1159a5b13a2SMatthew G Knepley         *faces = facesTmp;
1169a5b13a2SMatthew G Knepley       }
1179a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 3;
1189a5b13a2SMatthew G Knepley       if (faceSize) *faceSize = 2;
1199f074e33SMatthew G Knepley       break;
120ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1219a5b13a2SMatthew G Knepley       /* Vertices follow right hand rule */
1229a5b13a2SMatthew G Knepley       if (faces) {
1239a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1249a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1259a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[3];
1269a5b13a2SMatthew G Knepley         facesTmp[6] = cone[3]; facesTmp[7] = cone[0];
1279a5b13a2SMatthew G Knepley         *faces = facesTmp;
1289a5b13a2SMatthew G Knepley       }
1299a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 4;
1309a5b13a2SMatthew G Knepley       if (faceSize) *faceSize = 2;
1319f074e33SMatthew G Knepley       break;
132ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1332e1b13c2SMatthew G. Knepley       /* Vertices of first face follow right hand rule and normal points away from last vertex */
1349a5b13a2SMatthew G Knepley       if (faces) {
1352e1b13c2SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];
1362e1b13c2SMatthew G. Knepley         facesTmp[3] = cone[0]; facesTmp[4]  = cone[3]; facesTmp[5]  = cone[1];
1372e1b13c2SMatthew G. Knepley         facesTmp[6] = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[3];
1382e1b13c2SMatthew G. Knepley         facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3];
1399a5b13a2SMatthew G Knepley         *faces = facesTmp;
1409a5b13a2SMatthew G Knepley       }
1419a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 4;
1429a5b13a2SMatthew G Knepley       if (faceSize) *faceSize = 3;
1439a5b13a2SMatthew G Knepley       break;
144ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
145e368ef20SMatthew G. Knepley       /*  7--------6
146e368ef20SMatthew G. Knepley          /|       /|
147e368ef20SMatthew G. Knepley         / |      / |
148e368ef20SMatthew G. Knepley        4--------5  |
149e368ef20SMatthew G. Knepley        |  |     |  |
150e368ef20SMatthew G. Knepley        |  |     |  |
151e368ef20SMatthew G. Knepley        |  1--------2
152e368ef20SMatthew G. Knepley        | /      | /
153e368ef20SMatthew G. Knepley        |/       |/
154e368ef20SMatthew G. Knepley        0--------3
155e368ef20SMatthew G. Knepley        */
1569a5b13a2SMatthew G Knepley       if (faces) {
15751cfd6a4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
15851cfd6a4SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
15951cfd6a4SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */
16051cfd6a4SMatthew G. Knepley         facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */
16151cfd6a4SMatthew G. Knepley         facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */
16251cfd6a4SMatthew G. Knepley         facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */
1639a5b13a2SMatthew G Knepley         *faces = facesTmp;
1649a5b13a2SMatthew G Knepley       }
1659a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 6;
1669a5b13a2SMatthew G Knepley       if (faceSize) *faceSize = 4;
1679f074e33SMatthew G Knepley       break;
168ba2698f1SMatthew G. Knepley     default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
1699f074e33SMatthew G Knepley   }
1709f074e33SMatthew G Knepley   PetscFunctionReturn(0);
1719f074e33SMatthew G Knepley }
1729f074e33SMatthew G Knepley 
17399836e0eSStefano Zampini /*
17499836e0eSStefano Zampini   DMPlexGetRawFacesHybrid_Internal - Gets groups of vertices that correspond to faces for the given cone using hybrid ordering (prisms)
17599836e0eSStefano Zampini */
176ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexGetRawFacesHybrid_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[])
17799836e0eSStefano Zampini {
17899836e0eSStefano Zampini   PetscInt       *facesTmp;
17999836e0eSStefano Zampini   PetscInt        maxConeSize, maxSupportSize;
18099836e0eSStefano Zampini   PetscErrorCode  ierr;
18199836e0eSStefano Zampini 
18299836e0eSStefano Zampini   PetscFunctionBegin;
18399836e0eSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
184ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
18599836e0eSStefano Zampini   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
18699836e0eSStefano Zampini   if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);}
187ba2698f1SMatthew G. Knepley   switch (ct) {
188ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
18999836e0eSStefano Zampini       if (faces) {
19099836e0eSStefano Zampini         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
19199836e0eSStefano Zampini         *faces = facesTmp;
19299836e0eSStefano Zampini       }
19399836e0eSStefano Zampini       if (numFaces)     *numFaces = 2;
19499836e0eSStefano Zampini       if (numFacesNotH) *numFacesNotH = 2;
19599836e0eSStefano Zampini       if (faceSize)     *faceSize = 1;
19699836e0eSStefano Zampini       break;
197ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
198ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
19999836e0eSStefano Zampini       if (faces) {
20099836e0eSStefano Zampini         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
20199836e0eSStefano Zampini         facesTmp[2] = cone[2]; facesTmp[3] = cone[3];
20299836e0eSStefano Zampini         facesTmp[4] = cone[0]; facesTmp[5] = cone[2];
20399836e0eSStefano Zampini         facesTmp[6] = cone[1]; facesTmp[7] = cone[3];
20499836e0eSStefano Zampini         *faces = facesTmp;
20599836e0eSStefano Zampini       }
20699836e0eSStefano Zampini       if (numFaces)     *numFaces = 4;
20799836e0eSStefano Zampini       if (numFacesNotH) *numFacesNotH = 2;
20899836e0eSStefano Zampini       if (faceSize)     *faceSize = 2;
20999836e0eSStefano Zampini       break;
210ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
211ba2698f1SMatthew G. Knepley       if (faces) {
212ba2698f1SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[2]; facesTmp[2]  = cone[1]; facesTmp[3]  = -1;      /* Bottom */
213ba2698f1SMatthew G. Knepley         facesTmp[4]  = cone[3]; facesTmp[5]  = cone[4]; facesTmp[6]  = cone[5]; facesTmp[7]  = -1;      /* Top */
214ba2698f1SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[3]; /* Back left */
215ba2698f1SMatthew G. Knepley         facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[4]; /* Back right */
216ba2698f1SMatthew G. Knepley         facesTmp[16] = cone[2]; facesTmp[17] = cone[0]; facesTmp[18] = cone[3]; facesTmp[19] = cone[5]; /* Front */
217ba2698f1SMatthew G. Knepley         *faces = facesTmp;
21899836e0eSStefano Zampini       }
219ba2698f1SMatthew G. Knepley       if (numFaces)     *numFaces = 5;
220ba2698f1SMatthew G. Knepley       if (numFacesNotH) *numFacesNotH = 2;
221ba2698f1SMatthew G. Knepley       if (faceSize)     *faceSize = -4;
22299836e0eSStefano Zampini       break;
223ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
22499836e0eSStefano Zampini       if (faces) {
22599836e0eSStefano Zampini         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = -1;      /* Bottom */
22699836e0eSStefano Zampini         facesTmp[4]  = cone[3]; facesTmp[5]  = cone[4]; facesTmp[6]  = cone[5]; facesTmp[7]  = -1;      /* Top */
22799836e0eSStefano Zampini         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[1]; facesTmp[10] = cone[3]; facesTmp[11] = cone[4]; /* Back left */
22899836e0eSStefano Zampini         facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[4]; facesTmp[15] = cone[5]; /* Back right */
22999836e0eSStefano Zampini         facesTmp[16] = cone[2]; facesTmp[17] = cone[0]; facesTmp[18] = cone[5]; facesTmp[19] = cone[3]; /* Front */
23099836e0eSStefano Zampini         *faces = facesTmp;
23199836e0eSStefano Zampini       }
23299836e0eSStefano Zampini       if (numFaces)     *numFaces = 5;
23399836e0eSStefano Zampini       if (numFacesNotH) *numFacesNotH = 2;
23499836e0eSStefano Zampini       if (faceSize)     *faceSize = -4;
23599836e0eSStefano Zampini       break;
236ba2698f1SMatthew G. Knepley     default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
23799836e0eSStefano Zampini   }
23899836e0eSStefano Zampini   PetscFunctionReturn(0);
23999836e0eSStefano Zampini }
24099836e0eSStefano Zampini 
241ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexRestoreRawFacesHybrid_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[])
24299836e0eSStefano Zampini {
24399836e0eSStefano Zampini   PetscErrorCode  ierr;
24499836e0eSStefano Zampini 
24599836e0eSStefano Zampini   PetscFunctionBegin;
24699836e0eSStefano Zampini   if (faces) { ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr); }
24799836e0eSStefano Zampini   PetscFunctionReturn(0);
24899836e0eSStefano Zampini }
24999836e0eSStefano Zampini 
250ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexGetFacesHybrid_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[])
25199836e0eSStefano Zampini {
25299836e0eSStefano Zampini   const PetscInt *cone = NULL;
253ba2698f1SMatthew G. Knepley   DMPolytopeType  ct;
25499836e0eSStefano Zampini   PetscErrorCode  ierr;
25599836e0eSStefano Zampini 
25699836e0eSStefano Zampini   PetscFunctionBegin;
25799836e0eSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
258ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
25999836e0eSStefano Zampini   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
260ba2698f1SMatthew G. Knepley   ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, numFaces, numFacesNotH, faceSize, faces);CHKERRQ(ierr);
26199836e0eSStefano Zampini   PetscFunctionReturn(0);
26299836e0eSStefano Zampini }
26399836e0eSStefano Zampini 
2649a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
2659a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
2669f074e33SMatthew G Knepley {
267d4efc6f1SMatthew G. Knepley   DMLabel        subpointMap;
2689a5b13a2SMatthew G Knepley   PetscHashIJKL  faceTable;
2699a5b13a2SMatthew G Knepley   PetscInt      *pStart, *pEnd;
2709a5b13a2SMatthew G Knepley   PetscInt       cellDim, depth, faceDepth = cellDepth, numPoints = 0, faceSizeAll = 0, face, c, d;
271e9fa77a1SMatthew G. Knepley   PetscInt       coneSizeH = 0, faceSizeAllH = 0, faceSizeAllT = 0, numCellFacesH = 0, faceT = 0, faceH, pMax = -1, dim, outerloop;
27299836e0eSStefano Zampini   PetscInt       cMax, fMax, eMax, vMax;
2739f074e33SMatthew G Knepley   PetscErrorCode ierr;
2749f074e33SMatthew G Knepley 
2759f074e33SMatthew G Knepley   PetscFunctionBegin;
276c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &cellDim);CHKERRQ(ierr);
277d4efc6f1SMatthew G. Knepley   /* HACK: I need a better way to determine face dimension, or an alternative to GetFaces() */
278d4efc6f1SMatthew G. Knepley   ierr = DMPlexGetSubpointMap(dm, &subpointMap);CHKERRQ(ierr);
279d4efc6f1SMatthew G. Knepley   if (subpointMap) ++cellDim;
2809a5b13a2SMatthew G Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
2819a5b13a2SMatthew G Knepley   ++depth;
2829a5b13a2SMatthew G Knepley   ++cellDepth;
2839a5b13a2SMatthew G Knepley   cellDim -= depth - cellDepth;
284dcca6d9dSJed Brown   ierr = PetscMalloc2(depth+1,&pStart,depth+1,&pEnd);CHKERRQ(ierr);
2859a5b13a2SMatthew G Knepley   for (d = depth-1; d >= faceDepth; --d) {
2869a5b13a2SMatthew G Knepley     ierr = DMPlexGetDepthStratum(dm, d, &pStart[d+1], &pEnd[d+1]);CHKERRQ(ierr);
2879f074e33SMatthew G Knepley   }
2889a5b13a2SMatthew G Knepley   ierr = DMPlexGetDepthStratum(dm, -1, NULL, &pStart[faceDepth]);CHKERRQ(ierr);
2899a5b13a2SMatthew G Knepley   pEnd[faceDepth] = pStart[faceDepth];
2909a5b13a2SMatthew G Knepley   for (d = faceDepth-1; d >= 0; --d) {
2919a5b13a2SMatthew G Knepley     ierr = DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);CHKERRQ(ierr);
2929f074e33SMatthew G Knepley   }
29399836e0eSStefano Zampini   cMax = fMax = eMax = vMax = PETSC_DETERMINE;
29499836e0eSStefano Zampini   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
29599836e0eSStefano Zampini   if (cellDim == dim) {
29699836e0eSStefano Zampini     ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
29799836e0eSStefano Zampini     pMax = cMax;
29899836e0eSStefano Zampini   } else if (cellDim == dim -1) {
29999836e0eSStefano Zampini     ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);CHKERRQ(ierr);
30099836e0eSStefano Zampini     pMax = fMax;
30199836e0eSStefano Zampini   }
30299836e0eSStefano Zampini   pMax = pMax < 0 ? pEnd[cellDepth] : pMax;
30399836e0eSStefano Zampini   if (pMax < pEnd[cellDepth]) {
30499836e0eSStefano Zampini     const PetscInt *cellFaces, *cone;
305ba2698f1SMatthew G. Knepley     DMPolytopeType  ct;
30699836e0eSStefano Zampini     PetscInt        numCellFacesT, faceSize, cf;
3079f074e33SMatthew G Knepley 
308e9fa77a1SMatthew G. Knepley     /* First get normal cell face size (we now allow hybrid cells to meet normal cells on either hybrid or normal faces */
309ba2698f1SMatthew G. Knepley     if (pStart[cellDepth] < pMax) {ierr = DMPlexGetFaces_Internal(dm, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr);}
310e9fa77a1SMatthew G. Knepley 
311ba2698f1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, pMax, &ct);CHKERRQ(ierr);
31299836e0eSStefano Zampini     ierr = DMPlexGetConeSize(dm, pMax, &coneSizeH);CHKERRQ(ierr);
31399836e0eSStefano Zampini     ierr = DMPlexGetCone(dm, pMax, &cone);CHKERRQ(ierr);
314ba2698f1SMatthew G. Knepley     ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr);
31599836e0eSStefano Zampini     if (faceSize < 0) {
31699836e0eSStefano Zampini       PetscInt *sizes, minv, maxv;
31799836e0eSStefano Zampini 
31899836e0eSStefano Zampini       /* count vertices of hybrid and non-hybrid faces */
31999836e0eSStefano Zampini       ierr = PetscCalloc1(numCellFacesH, &sizes);CHKERRQ(ierr);
32099836e0eSStefano Zampini       for (cf = 0; cf < numCellFacesT; ++cf) { /* These are the non-hybrid faces */
32199836e0eSStefano Zampini         const PetscInt *cellFace = &cellFaces[-cf*faceSize];
32299836e0eSStefano Zampini         PetscInt       f;
32399836e0eSStefano Zampini 
32499836e0eSStefano Zampini         for (f = 0; f < -faceSize; ++f) sizes[cf] += (cellFace[f] >= 0 ? 1 : 0);
32599836e0eSStefano Zampini       }
32699836e0eSStefano Zampini       ierr = PetscSortInt(numCellFacesT, sizes);CHKERRQ(ierr);
32799836e0eSStefano Zampini       minv = sizes[0];
32899836e0eSStefano Zampini       maxv = sizes[PetscMax(numCellFacesT-1, 0)];
32999836e0eSStefano Zampini       if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for non-hybrid face %D != %D", minv, maxv);
330e9fa77a1SMatthew G. Knepley       faceSizeAllT = minv;
331580bdb30SBarry Smith       ierr = PetscArrayzero(sizes, numCellFacesH);CHKERRQ(ierr);
33299836e0eSStefano Zampini       for (cf = numCellFacesT; cf < numCellFacesH; ++cf) { /* These are the hybrid faces */
33399836e0eSStefano Zampini         const PetscInt *cellFace = &cellFaces[-cf*faceSize];
33499836e0eSStefano Zampini         PetscInt       f;
33599836e0eSStefano Zampini 
33699836e0eSStefano Zampini         for (f = 0; f < -faceSize; ++f) sizes[cf-numCellFacesT] += (cellFace[f] >= 0 ? 1 : 0);
33799836e0eSStefano Zampini       }
33899836e0eSStefano Zampini       ierr = PetscSortInt(numCellFacesH - numCellFacesT, sizes);CHKERRQ(ierr);
33999836e0eSStefano Zampini       minv = sizes[0];
34099836e0eSStefano Zampini       maxv = sizes[PetscMax(numCellFacesH - numCellFacesT-1, 0)];
34199836e0eSStefano Zampini       ierr = PetscFree(sizes);CHKERRQ(ierr);
34299836e0eSStefano Zampini       if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for hybrid face %D != %D", minv, maxv);
34399836e0eSStefano Zampini       faceSizeAllH = minv;
3445ebdaad1SMatthew G. Knepley       if (!faceSizeAll) faceSizeAll = faceSizeAllT;
34599836e0eSStefano Zampini     } else { /* the size of the faces in hybrid cells is the same */
346e9fa77a1SMatthew G. Knepley       faceSizeAll = faceSizeAllH = faceSizeAllT = faceSize;
34799836e0eSStefano Zampini     }
348ba2698f1SMatthew G. Knepley     ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr);
34999836e0eSStefano Zampini   } else if (pEnd[cellDepth] > pStart[cellDepth]) {
350ba2698f1SMatthew G. Knepley     ierr = DMPlexGetFaces_Internal(dm, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr);
351a1bcd873SMatthew G. Knepley     faceSizeAllH = faceSizeAllT = faceSizeAll;
35299836e0eSStefano Zampini   }
35399836e0eSStefano Zampini   if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll);
35499836e0eSStefano Zampini 
355b135d7daSStefano Zampini   /* With hybrid grids, we first iterate on hybrid cells and start numbering the non-hybrid faces
35699836e0eSStefano Zampini      Then, faces for non-hybrid cells are numbered.
35799836e0eSStefano Zampini      This is to guarantee consistent orientations (all 0) of all the points in the cone of the hybrid cells */
35899836e0eSStefano Zampini   ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr);
35999836e0eSStefano Zampini   for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) {
36099836e0eSStefano Zampini     PetscInt start, end;
36199836e0eSStefano Zampini 
36299836e0eSStefano Zampini     start = outerloop == 0 ? pMax : pStart[cellDepth];
36399836e0eSStefano Zampini     end = outerloop == 0 ? pEnd[cellDepth] : pMax;
36499836e0eSStefano Zampini     for (c = start; c < end; ++c) {
36599836e0eSStefano Zampini       const PetscInt *cellFaces;
366e9fa77a1SMatthew G. Knepley       PetscInt        numCellFaces, faceSize, faceSizeInc, faceSizeCheck, cf;
36799836e0eSStefano Zampini 
36899836e0eSStefano Zampini       if (c < pMax) {
369ba2698f1SMatthew G. Knepley         ierr = DMPlexGetFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
3709a5b13a2SMatthew G Knepley         if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll);
371e9fa77a1SMatthew G. Knepley         faceSizeCheck = faceSizeAll;
37299836e0eSStefano Zampini       } else { /* Hybrid cell */
37399836e0eSStefano Zampini         const PetscInt *cone;
374ba2698f1SMatthew G. Knepley         DMPolytopeType  ct;
37599836e0eSStefano Zampini         PetscInt        numCellFacesN, coneSize;
37699836e0eSStefano Zampini 
377ba2698f1SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
37899836e0eSStefano Zampini         ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
37999836e0eSStefano Zampini         if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH);
38099836e0eSStefano Zampini         ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
381ba2698f1SMatthew G. Knepley         ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
38299836e0eSStefano Zampini         if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c);
38399836e0eSStefano Zampini         faceSize = PetscMax(faceSize, -faceSize);
38499836e0eSStefano Zampini         if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize);
38599836e0eSStefano Zampini         numCellFaces = numCellFacesN; /* process only non-hybrid faces */
386e9fa77a1SMatthew G. Knepley         faceSizeCheck = faceSizeAllT;
38799836e0eSStefano Zampini       }
38899836e0eSStefano Zampini       faceSizeInc = faceSize;
3899f074e33SMatthew G Knepley       for (cf = 0; cf < numCellFaces; ++cf) {
39099836e0eSStefano Zampini         const PetscInt   *cellFace = &cellFaces[cf*faceSizeInc];
39199836e0eSStefano Zampini         PetscInt          faceSizeH = faceSize;
3929a5b13a2SMatthew G Knepley         PetscHashIJKLKey  key;
393e8f14785SLisandro Dalcin         PetscHashIter     iter;
394e8f14785SLisandro Dalcin         PetscBool         missing;
3959f074e33SMatthew G Knepley 
39699836e0eSStefano Zampini         if (faceSizeInc == 2) {
3979a5b13a2SMatthew G Knepley           key.i = PetscMin(cellFace[0], cellFace[1]);
3989a5b13a2SMatthew G Knepley           key.j = PetscMax(cellFace[0], cellFace[1]);
39999836e0eSStefano Zampini           key.k = PETSC_MAX_INT;
40099836e0eSStefano Zampini           key.l = PETSC_MAX_INT;
4019a5b13a2SMatthew G Knepley         } else {
40299836e0eSStefano Zampini           key.i = cellFace[0];
40399836e0eSStefano Zampini           key.j = cellFace[1];
40499836e0eSStefano Zampini           key.k = cellFace[2];
40599836e0eSStefano Zampini           key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT;
406302440fdSBarry Smith           ierr  = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
4079f074e33SMatthew G Knepley         }
40899836e0eSStefano Zampini         /* this check is redundant for non-hybrid meshes */
409e9fa77a1SMatthew G. Knepley         if (faceSizeH != faceSizeCheck) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeCheck);
410e8f14785SLisandro Dalcin         ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
411e9fa77a1SMatthew G. Knepley         if (missing) {
412e9fa77a1SMatthew G. Knepley           ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr);
413e9fa77a1SMatthew G. Knepley           if (c >= pMax) ++faceT;
414e9fa77a1SMatthew G. Knepley         }
4159a5b13a2SMatthew G Knepley       }
41699836e0eSStefano Zampini       if (c < pMax) {
417ba2698f1SMatthew G. Knepley         ierr = DMPlexRestoreFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
41899836e0eSStefano Zampini       } else {
419ba2698f1SMatthew G. Knepley         ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, DM_POLYTOPE_UNKNOWN, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr);
42099836e0eSStefano Zampini       }
42199836e0eSStefano Zampini     }
42299836e0eSStefano Zampini   }
42399836e0eSStefano Zampini   pEnd[faceDepth] = face;
42499836e0eSStefano Zampini 
42599836e0eSStefano Zampini   /* Second pass for hybrid meshes: number hybrid faces */
42699836e0eSStefano Zampini   for (c = pMax; c < pEnd[cellDepth]; ++c) {
42799836e0eSStefano Zampini     const PetscInt *cellFaces, *cone;
428ba2698f1SMatthew G. Knepley     DMPolytopeType  ct;
429ba2698f1SMatthew G. Knepley     PetscInt        numCellFaces, numCellFacesN, faceSize, cf;
43099836e0eSStefano Zampini 
431ba2698f1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
43299836e0eSStefano Zampini     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
433ba2698f1SMatthew G. Knepley     ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
43499836e0eSStefano Zampini     if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH);
43599836e0eSStefano Zampini     faceSize = PetscMax(faceSize, -faceSize);
43699836e0eSStefano Zampini     for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */
43799836e0eSStefano Zampini       const PetscInt   *cellFace = &cellFaces[cf*faceSize];
43899836e0eSStefano Zampini       PetscHashIJKLKey  key;
43999836e0eSStefano Zampini       PetscHashIter     iter;
44099836e0eSStefano Zampini       PetscBool         missing;
44199836e0eSStefano Zampini       PetscInt          faceSizeH = faceSize;
44299836e0eSStefano Zampini 
44399836e0eSStefano Zampini       if (faceSize == 2) {
44499836e0eSStefano Zampini         key.i = PetscMin(cellFace[0], cellFace[1]);
44599836e0eSStefano Zampini         key.j = PetscMax(cellFace[0], cellFace[1]);
44699836e0eSStefano Zampini         key.k = PETSC_MAX_INT;
44799836e0eSStefano Zampini         key.l = PETSC_MAX_INT;
44899836e0eSStefano Zampini       } else {
44999836e0eSStefano Zampini         key.i = cellFace[0];
45099836e0eSStefano Zampini         key.j = cellFace[1];
45199836e0eSStefano Zampini         key.k = cellFace[2];
45299836e0eSStefano Zampini         key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT;
45399836e0eSStefano Zampini         ierr  = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
45499836e0eSStefano Zampini       }
45599836e0eSStefano Zampini       if (faceSizeH != faceSizeAllH) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for hybrid face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeAllH);
45699836e0eSStefano Zampini       ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
45799836e0eSStefano Zampini       if (missing) {ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr);}
45899836e0eSStefano Zampini     }
459ba2698f1SMatthew G. Knepley     ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
46099836e0eSStefano Zampini   }
46199836e0eSStefano Zampini   faceH = face - pEnd[faceDepth];
46299836e0eSStefano Zampini   if (faceH) {
46399836e0eSStefano Zampini     if (fMax == PETSC_DETERMINE) fMax = pEnd[faceDepth];
46499836e0eSStefano Zampini     else if (eMax == PETSC_DETERMINE) eMax = pEnd[faceDepth];
46599836e0eSStefano Zampini     else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of unassigned hybrid facets %D for cellDim %D and dimension %D", faceH, cellDim, dim);
4669a5b13a2SMatthew G Knepley   }
4679a5b13a2SMatthew G Knepley   pEnd[faceDepth] = face;
4689a5b13a2SMatthew G Knepley   ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr);
4699a5b13a2SMatthew G Knepley   /* Count new points */
4709a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
4719a5b13a2SMatthew G Knepley     numPoints += pEnd[d]-pStart[d];
4729a5b13a2SMatthew G Knepley   }
4739a5b13a2SMatthew G Knepley   ierr = DMPlexSetChart(idm, 0, numPoints);CHKERRQ(ierr);
4749a5b13a2SMatthew G Knepley   /* Set cone sizes */
4759a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
4769a5b13a2SMatthew G Knepley     PetscInt coneSize, p;
4779f074e33SMatthew G Knepley 
4789a5b13a2SMatthew G Knepley     if (d == faceDepth) {
479e9fa77a1SMatthew G. Knepley       /* Now we have two cases: */
480e9fa77a1SMatthew G. Knepley       if (faceSizeAll == faceSizeAllT) {
4819a5b13a2SMatthew G Knepley         /* I see no way to do this if we admit faces of different shapes */
48299836e0eSStefano Zampini         for (p = pStart[d]; p < pEnd[d]-faceH; ++p) {
4839a5b13a2SMatthew G Knepley           ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr);
4849a5b13a2SMatthew G Knepley         }
48599836e0eSStefano Zampini         for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) {
48699836e0eSStefano Zampini           ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr);
48799836e0eSStefano Zampini         }
488e9fa77a1SMatthew G. Knepley       } else if (faceSizeAll == faceSizeAllH) {
489e9fa77a1SMatthew G. Knepley         for (p = pStart[d]; p < pStart[d]+faceT; ++p) {
490e9fa77a1SMatthew G. Knepley           ierr = DMPlexSetConeSize(idm, p, faceSizeAllT);CHKERRQ(ierr);
491e9fa77a1SMatthew G. Knepley         }
492e9fa77a1SMatthew G. Knepley         for (p = pStart[d]+faceT; p < pEnd[d]-faceH; ++p) {
493e9fa77a1SMatthew G. Knepley           ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr);
494e9fa77a1SMatthew G. Knepley         }
495e9fa77a1SMatthew G. Knepley         for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) {
496e9fa77a1SMatthew G. Knepley           ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr);
497e9fa77a1SMatthew G. Knepley         }
498e9fa77a1SMatthew G. Knepley       } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent faces sizes N: %D T: %D H: %D", faceSizeAll, faceSizeAllT, faceSizeAllH);
499a014044eSMatthew G Knepley     } else if (d == cellDepth) {
500a014044eSMatthew G Knepley       for (p = pStart[d]; p < pEnd[d]; ++p) {
501a014044eSMatthew G Knepley         /* Number of cell faces may be different from number of cell vertices*/
50299836e0eSStefano Zampini         if (p < pMax) {
503ba2698f1SMatthew G. Knepley           ierr = DMPlexGetFaces_Internal(dm, p, &coneSize, NULL, NULL);CHKERRQ(ierr);
50499836e0eSStefano Zampini         } else {
505ba2698f1SMatthew G. Knepley           ierr = DMPlexGetFacesHybrid_Internal(dm, p, &coneSize, NULL, NULL, NULL);CHKERRQ(ierr);
50699836e0eSStefano Zampini         }
507a014044eSMatthew G Knepley         ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr);
508a014044eSMatthew G Knepley       }
5099a5b13a2SMatthew G Knepley     } else {
5109a5b13a2SMatthew G Knepley       for (p = pStart[d]; p < pEnd[d]; ++p) {
5119a5b13a2SMatthew G Knepley         ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
5129a5b13a2SMatthew G Knepley         ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr);
5139f074e33SMatthew G Knepley       }
5149f074e33SMatthew G Knepley     }
5159f074e33SMatthew G Knepley   }
5169f074e33SMatthew G Knepley   ierr = DMSetUp(idm);CHKERRQ(ierr);
5179f074e33SMatthew G Knepley   /* Get face cones from subsets of cell vertices */
51899836e0eSStefano Zampini   if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll);
5199a5b13a2SMatthew G Knepley   ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr);
5209a5b13a2SMatthew G Knepley   for (d = depth; d > cellDepth; --d) {
5219a5b13a2SMatthew G Knepley     const PetscInt *cone;
5229a5b13a2SMatthew G Knepley     PetscInt        p;
5239a5b13a2SMatthew G Knepley 
5249a5b13a2SMatthew G Knepley     for (p = pStart[d]; p < pEnd[d]; ++p) {
5259a5b13a2SMatthew G Knepley       ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
5269a5b13a2SMatthew G Knepley       ierr = DMPlexSetCone(idm, p, cone);CHKERRQ(ierr);
5279a5b13a2SMatthew G Knepley       ierr = DMPlexGetConeOrientation(dm, p, &cone);CHKERRQ(ierr);
5289a5b13a2SMatthew G Knepley       ierr = DMPlexSetConeOrientation(idm, p, cone);CHKERRQ(ierr);
5299f074e33SMatthew G Knepley     }
5309a5b13a2SMatthew G Knepley   }
53199836e0eSStefano Zampini   for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) {
53299836e0eSStefano Zampini     PetscInt start, end;
5339f074e33SMatthew G Knepley 
53499836e0eSStefano Zampini     start = outerloop == 0 ? pMax : pStart[cellDepth];
53599836e0eSStefano Zampini     end = outerloop == 0 ? pEnd[cellDepth] : pMax;
53699836e0eSStefano Zampini     for (c = start; c < end; ++c) {
53799836e0eSStefano Zampini       const PetscInt *cellFaces;
53899836e0eSStefano Zampini       PetscInt        numCellFaces, faceSize, faceSizeInc, cf;
53999836e0eSStefano Zampini 
54099836e0eSStefano Zampini       if (c < pMax) {
541ba2698f1SMatthew G. Knepley         ierr = DMPlexGetFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
5429a5b13a2SMatthew G Knepley         if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll);
54399836e0eSStefano Zampini       } else {
54499836e0eSStefano Zampini         const PetscInt *cone;
545ba2698f1SMatthew G. Knepley         DMPolytopeType  ct;
54699836e0eSStefano Zampini         PetscInt        numCellFacesN, coneSize;
54799836e0eSStefano Zampini 
548ba2698f1SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
54999836e0eSStefano Zampini         ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
55099836e0eSStefano Zampini         if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH);
55199836e0eSStefano Zampini         ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
552ba2698f1SMatthew G. Knepley         ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
55399836e0eSStefano Zampini         if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c);
55499836e0eSStefano Zampini         faceSize = PetscMax(faceSize, -faceSize);
55599836e0eSStefano Zampini         if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize);
55699836e0eSStefano Zampini         numCellFaces = numCellFacesN; /* process only non-hybrid faces */
55799836e0eSStefano Zampini       }
55899836e0eSStefano Zampini       faceSizeInc = faceSize;
5599f074e33SMatthew G Knepley       for (cf = 0; cf < numCellFaces; ++cf) {
56099836e0eSStefano Zampini         const PetscInt  *cellFace = &cellFaces[cf*faceSizeInc];
5619a5b13a2SMatthew G Knepley         PetscHashIJKLKey key;
562e8f14785SLisandro Dalcin         PetscHashIter    iter;
563e8f14785SLisandro Dalcin         PetscBool        missing;
5649f074e33SMatthew G Knepley 
56599836e0eSStefano Zampini         if (faceSizeInc == 2) {
5669a5b13a2SMatthew G Knepley           key.i = PetscMin(cellFace[0], cellFace[1]);
5679a5b13a2SMatthew G Knepley           key.j = PetscMax(cellFace[0], cellFace[1]);
56899836e0eSStefano Zampini           key.k = PETSC_MAX_INT;
56999836e0eSStefano Zampini           key.l = PETSC_MAX_INT;
5709a5b13a2SMatthew G Knepley         } else {
571e8f14785SLisandro Dalcin           key.i = cellFace[0];
572e8f14785SLisandro Dalcin           key.j = cellFace[1];
573e8f14785SLisandro Dalcin           key.k = cellFace[2];
57499836e0eSStefano Zampini           key.l = faceSizeInc > 3 ? (cellFace[3] < 0 ? faceSize = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT;
57599836e0eSStefano Zampini           ierr  = PetscSortInt(faceSizeInc, (PetscInt *) &key);CHKERRQ(ierr);
5769f074e33SMatthew G Knepley         }
577e8f14785SLisandro Dalcin         ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
578735a0255SMatthew G. Knepley         if (missing) {
5799a5b13a2SMatthew G Knepley           ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr);
580e8f14785SLisandro Dalcin           ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr);
581735a0255SMatthew G. Knepley           ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr);
5829a5b13a2SMatthew G Knepley         } else {
5839a5b13a2SMatthew G Knepley           const PetscInt *cone;
584735a0255SMatthew G. Knepley           PetscInt        coneSize, ornt, i, j, f;
5859f074e33SMatthew G Knepley 
586e8f14785SLisandro Dalcin           ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr);
5879a5b13a2SMatthew G Knepley           ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr);
5882e1b13c2SMatthew G. Knepley           /* Orient face: Do not allow reverse orientation at the first vertex */
5899f074e33SMatthew G Knepley           ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr);
5909f074e33SMatthew G Knepley           ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
5919a5b13a2SMatthew G Knepley           if (coneSize != faceSize) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize);
5929a5b13a2SMatthew G Knepley           /* - First find the initial vertex */
5939a5b13a2SMatthew G Knepley           for (i = 0; i < faceSize; ++i) if (cellFace[0] == cone[i]) break;
5949a5b13a2SMatthew G Knepley           /* - Try forward comparison */
5959a5b13a2SMatthew G Knepley           for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+j)%faceSize]) break;
5969a5b13a2SMatthew G Knepley           if (j == faceSize) {
5979a5b13a2SMatthew G Knepley             if ((faceSize == 2) && (i == 1)) ornt = -2;
5989a5b13a2SMatthew G Knepley             else                             ornt = i;
5999a5b13a2SMatthew G Knepley           } else {
6009a5b13a2SMatthew G Knepley             /* - Try backward comparison */
6019a5b13a2SMatthew G Knepley             for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+faceSize-j)%faceSize]) break;
6022e1b13c2SMatthew G. Knepley             if (j == faceSize) {
6032e1b13c2SMatthew G. Knepley               if (i == 0) ornt = -faceSize;
604dc1a705cSMatthew G. Knepley               else        ornt = -i;
605e9fa77a1SMatthew G. Knepley             } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c);
6069a5b13a2SMatthew G Knepley           }
6079a5b13a2SMatthew G Knepley           ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr);
6089f074e33SMatthew G Knepley         }
6099f074e33SMatthew G Knepley       }
61099836e0eSStefano Zampini       if (c < pMax) {
611ba2698f1SMatthew G. Knepley         ierr = DMPlexRestoreFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
61299836e0eSStefano Zampini       } else {
613ba2698f1SMatthew G. Knepley         ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, DM_POLYTOPE_UNKNOWN, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr);
6149f074e33SMatthew G Knepley       }
61599836e0eSStefano Zampini     }
61699836e0eSStefano Zampini   }
61799836e0eSStefano Zampini   /* Second pass for hybrid meshes: orient hybrid faces */
61899836e0eSStefano Zampini   for (c = pMax; c < pEnd[cellDepth]; ++c) {
61999836e0eSStefano Zampini     const PetscInt *cellFaces, *cone;
620ba2698f1SMatthew G. Knepley     DMPolytopeType  ct;
621ba2698f1SMatthew G. Knepley     PetscInt        numCellFaces, numCellFacesN, faceSize, coneSize, cf;
62299836e0eSStefano Zampini 
623ba2698f1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
62499836e0eSStefano Zampini     ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
62599836e0eSStefano Zampini     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
626ba2698f1SMatthew G. Knepley     ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
62799836e0eSStefano Zampini     if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH);
62899836e0eSStefano Zampini     faceSize = PetscMax(faceSize, -faceSize);
62999836e0eSStefano Zampini     for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */
63099836e0eSStefano Zampini       const PetscInt   *cellFace = &cellFaces[cf*faceSize];
63199836e0eSStefano Zampini       PetscHashIJKLKey key;
63299836e0eSStefano Zampini       PetscHashIter    iter;
63399836e0eSStefano Zampini       PetscBool        missing;
63499836e0eSStefano Zampini       PetscInt         faceSizeH = faceSize;
63599836e0eSStefano Zampini 
63699836e0eSStefano Zampini       if (faceSize == 2) {
63799836e0eSStefano Zampini         key.i = PetscMin(cellFace[0], cellFace[1]);
63899836e0eSStefano Zampini         key.j = PetscMax(cellFace[0], cellFace[1]);
63999836e0eSStefano Zampini         key.k = PETSC_MAX_INT;
64099836e0eSStefano Zampini         key.l = PETSC_MAX_INT;
64199836e0eSStefano Zampini       } else {
64299836e0eSStefano Zampini         key.i = cellFace[0];
64399836e0eSStefano Zampini         key.j = cellFace[1];
64499836e0eSStefano Zampini         key.k = cellFace[2];
64599836e0eSStefano Zampini         key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT;
64699836e0eSStefano Zampini         ierr  = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
64799836e0eSStefano Zampini       }
64899836e0eSStefano Zampini       if (faceSizeH != faceSizeAllH) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for hybrid face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeAllH);
64999836e0eSStefano Zampini       ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
65099836e0eSStefano Zampini       if (missing) {
65199836e0eSStefano Zampini         ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr);
65299836e0eSStefano Zampini         ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr);
65399836e0eSStefano Zampini         ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr);
65499836e0eSStefano Zampini       } else {
655e9fa77a1SMatthew G. Knepley         PetscInt        fv[4] = {0, 1, 2, 3};
65699836e0eSStefano Zampini         const PetscInt *cone;
65799836e0eSStefano Zampini         PetscInt        coneSize, ornt, i, j, f;
658a74221b0SStefano Zampini         PetscBool       q2h = PETSC_FALSE;
65999836e0eSStefano Zampini 
66099836e0eSStefano Zampini         ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr);
66199836e0eSStefano Zampini         ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr);
66299836e0eSStefano Zampini         /* Orient face: Do not allow reverse orientation at the first vertex */
66399836e0eSStefano Zampini         ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr);
66499836e0eSStefano Zampini         ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
66599836e0eSStefano Zampini         if (coneSize != faceSizeH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSizeH);
666e9fa77a1SMatthew G. Knepley         /* Hybrid faces are stored as tensor products of edges, so to compare them to normal faces, we have to flip */
667a74221b0SStefano Zampini         if (faceSize == 4 && c >= pMax && faceSizeAll != faceSizeAllT && f < pEnd[faceDepth] - faceH) {q2h = PETSC_TRUE; fv[2] = 3; fv[3] = 2;}
66899836e0eSStefano Zampini         /* - First find the initial vertex */
669e9fa77a1SMatthew G. Knepley         for (i = 0; i < faceSizeH; ++i) if (cellFace[fv[0]] == cone[i]) break;
670a74221b0SStefano Zampini         if (q2h) { /* Matt's case: hybrid faces meeting with non-hybrid faces. This is a case that is not (and will not be) supported in general by the refinements */
67199836e0eSStefano Zampini           /* - Try forward comparison */
672e9fa77a1SMatthew G. Knepley           for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+j)%faceSizeH]) break;
67399836e0eSStefano Zampini           if (j == faceSizeH) {
67499836e0eSStefano Zampini             if ((faceSizeH == 2) && (i == 1)) ornt = -2;
67599836e0eSStefano Zampini             else                              ornt = i;
67699836e0eSStefano Zampini           } else {
67799836e0eSStefano Zampini             /* - Try backward comparison */
678e9fa77a1SMatthew G. Knepley             for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+faceSizeH-j)%faceSizeH]) break;
67999836e0eSStefano Zampini             if (j == faceSizeH) {
68099836e0eSStefano Zampini               if (i == 0) ornt = -faceSizeH;
68199836e0eSStefano Zampini               else        ornt = -i;
682e9fa77a1SMatthew G. Knepley             } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c);
68399836e0eSStefano Zampini           }
684a74221b0SStefano Zampini         } else {
685a74221b0SStefano Zampini           /* when matching hybrid faces in 3D, only few cases are possible.
686a74221b0SStefano Zampini              Face traversal however can no longer follow the usual convention, this seems a serious issue to me */
687a74221b0SStefano Zampini           PetscInt tquad_map[4][4] = { {PETSC_MIN_INT,            0,PETSC_MIN_INT,PETSC_MIN_INT},
688a74221b0SStefano Zampini                                        {           -1,PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT},
689a74221b0SStefano Zampini                                        {PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT,            1},
690a74221b0SStefano Zampini                                        {PETSC_MIN_INT,PETSC_MIN_INT,           -2,PETSC_MIN_INT} };
691a74221b0SStefano Zampini           PetscInt i2;
692a74221b0SStefano Zampini 
693a74221b0SStefano Zampini           /* find the second vertex */
694a74221b0SStefano Zampini           for (i2 = 0; i2 < faceSizeH; ++i2) if (cellFace[fv[1]] == cone[i2]) break;
695a74221b0SStefano Zampini           switch (faceSizeH) {
696a74221b0SStefano Zampini           case 2:
697a74221b0SStefano Zampini             ornt = i ? -2 : 0;
698a74221b0SStefano Zampini             break;
699a74221b0SStefano Zampini           case 4:
700a74221b0SStefano Zampini             ornt = tquad_map[i][i2];
701a74221b0SStefano Zampini             break;
702a74221b0SStefano Zampini           default:
703a74221b0SStefano Zampini             SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled face size %D for face %D in cell %D", faceSizeH, f, c);
704a74221b0SStefano Zampini 
705a74221b0SStefano Zampini           }
706a74221b0SStefano Zampini         }
70799836e0eSStefano Zampini         ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr);
70899836e0eSStefano Zampini       }
70999836e0eSStefano Zampini     }
710ba2698f1SMatthew G. Knepley     ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr);
71199836e0eSStefano Zampini   }
71299836e0eSStefano Zampini   if (face != pEnd[faceDepth]) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-pStart[faceDepth], pEnd[faceDepth]-pStart[faceDepth]);
713c907b753SJed Brown   ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr);
7149a5b13a2SMatthew G Knepley   ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr);
7156551a8c7SMatthew G. Knepley   ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr);
71699836e0eSStefano Zampini   ierr = DMPlexSetHybridBounds(idm, cMax, fMax, eMax, vMax);CHKERRQ(ierr);
7179a5b13a2SMatthew G Knepley   ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr);
7189a5b13a2SMatthew G Knepley   ierr = DMPlexStratify(idm);CHKERRQ(ierr);
7199f074e33SMatthew G Knepley   PetscFunctionReturn(0);
7209f074e33SMatthew G Knepley }
7219f074e33SMatthew G Knepley 
722f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
723f80536cbSVaclav Hapla {
724f80536cbSVaclav Hapla   PetscInt            nleaves;
725f80536cbSVaclav Hapla   PetscInt            nranks;
726a0d42dbcSVaclav Hapla   const PetscMPIInt  *ranks=NULL;
727a0d42dbcSVaclav Hapla   const PetscInt     *roffset=NULL, *rmine=NULL, *rremote=NULL;
728f80536cbSVaclav Hapla   PetscInt            n, o, r;
729f80536cbSVaclav Hapla   PetscErrorCode      ierr;
730f80536cbSVaclav Hapla 
731f80536cbSVaclav Hapla   PetscFunctionBegin;
732dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr);
733f80536cbSVaclav Hapla   nleaves = roffset[nranks];
734f80536cbSVaclav Hapla   ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr);
735f80536cbSVaclav Hapla   for (r=0; r<nranks; r++) {
736f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
737f80536cbSVaclav Hapla        - to unify order with the other side */
738f80536cbSVaclav Hapla     o = roffset[r];
739f80536cbSVaclav Hapla     n = roffset[r+1] - o;
740580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr);
741580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr);
742f80536cbSVaclav Hapla     ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr);
743f80536cbSVaclav Hapla   }
744f80536cbSVaclav Hapla   PetscFunctionReturn(0);
745f80536cbSVaclav Hapla }
746f80536cbSVaclav Hapla 
74727d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
7482e745bdaSMatthew G. Knepley {
74927d0e99aSVaclav Hapla   /* Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */
75027d0e99aSVaclav Hapla   PetscInt          masterCone[2];
751cae7fe92SVaclav Hapla   PetscInt          (*roots)[2], (*leaves)[2];
7528a650c75SVaclav Hapla   PetscMPIInt       (*rootsRanks)[2], (*leavesRanks)[2];
75327d0e99aSVaclav Hapla 
75427d0e99aSVaclav Hapla   PetscSF           sf=NULL;
755a0d42dbcSVaclav Hapla   const PetscInt    *locals=NULL;
756a0d42dbcSVaclav Hapla   const PetscSFNode *remotes=NULL;
7578a650c75SVaclav Hapla   PetscInt           nroots, nleaves, p, c;
758f80536cbSVaclav Hapla   PetscInt           nranks, n, o, r;
759a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks=NULL;
760a0d42dbcSVaclav Hapla   const PetscInt    *roffset=NULL;
761a0d42dbcSVaclav Hapla   PetscInt          *rmine1=NULL, *rremote1=NULL; /* rmine and rremote copies simultaneously sorted by rank and rremote */
762a0d42dbcSVaclav Hapla   const PetscInt    *cone=NULL;
763adeface4SVaclav Hapla   PetscInt           coneSize, ind0;
7642e745bdaSMatthew G. Knepley   MPI_Comm           comm;
76527d0e99aSVaclav Hapla   PetscMPIInt        rank,size;
7662e745bdaSMatthew G. Knepley   PetscInt           debug = 0;
7672e745bdaSMatthew G. Knepley   PetscErrorCode     ierr;
7682e745bdaSMatthew G. Knepley 
7692e745bdaSMatthew G. Knepley   PetscFunctionBegin;
770df6a9fadSVaclav Hapla   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
7712e745bdaSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr);
7723ede9f65SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
773f80536cbSVaclav Hapla   ierr = PetscSFSetUp(sf);CHKERRQ(ierr);
774dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr);
775dc21a0bfSVaclav Hapla   ierr = DMViewFromOptions(dm, NULL, "-before_fix_dm_view");CHKERRQ(ierr);
77627d0e99aSVaclav Hapla #if defined(PETSC_USE_DEBUG)
777dc21a0bfSVaclav Hapla   ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);
778dc21a0bfSVaclav Hapla #endif
779f80536cbSVaclav Hapla   ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr);
7808a650c75SVaclav Hapla   ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr);
7812e745bdaSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
7822e745bdaSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
78327d0e99aSVaclav Hapla   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
7849e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
7859e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
7869e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
78727d0e99aSVaclav Hapla     if (coneSize < 2) {
78827d0e99aSVaclav Hapla       for (c = 0; c < 2; c++) {
78927d0e99aSVaclav Hapla         roots[p][c] = -1;
79027d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
79127d0e99aSVaclav Hapla       }
79227d0e99aSVaclav Hapla       continue;
79327d0e99aSVaclav Hapla     }
7942e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
7958a650c75SVaclav Hapla     for (c = 0; c < 2; c++) {
7968a650c75SVaclav Hapla       ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr);
7978a650c75SVaclav Hapla       if (ind0 < 0) {
7988a650c75SVaclav Hapla         roots[p][c] = cone[c];
7998a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
800c8148b97SVaclav Hapla       } else {
8018a650c75SVaclav Hapla         roots[p][c] = remotes[ind0].index;
8028a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
8038a650c75SVaclav Hapla       }
8042e745bdaSMatthew G. Knepley     }
8052e745bdaSMatthew G. Knepley   }
8069e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
8078ccb905dSVaclav Hapla     for (c = 0; c < 2; c++) {
8088ccb905dSVaclav Hapla       leaves[p][c] = -2;
8098ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8108ccb905dSVaclav Hapla     }
811c8148b97SVaclav Hapla   }
8122e745bdaSMatthew G. Knepley   ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr);
8138a650c75SVaclav Hapla   ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr);
8142e745bdaSMatthew G. Knepley   ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr);
8158a650c75SVaclav Hapla   ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr);
816c8148b97SVaclav Hapla   if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
81727d0e99aSVaclav Hapla   if (debug && rank == 0) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);}
8189e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
8199e24d8a0SVaclav Hapla     if (leaves[p][0] < 0) continue;
8209e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8219e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
82227d0e99aSVaclav Hapla     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  %4D: cone=[%4D %4D] roots=[(%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D)]", rank, p, cone[0], cone[1], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1]);CHKERRQ(ierr);}
82382f5c0aeSVaclav Hapla     if ((leaves[p][0] != roots[p][0]) || (leaves[p][1] != roots[p][1]) || (leavesRanks[p][0] != rootsRanks[p][0]) || (leavesRanks[p][1] != rootsRanks[p][1])) {
82427d0e99aSVaclav Hapla       /* Translate these two leaves to my cone points; masterCone means desired order p's cone points */
825f80536cbSVaclav Hapla       for (c = 0; c < 2; c++) {
82627d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
82727d0e99aSVaclav Hapla           /* A local leave is just taken as it is */
82827d0e99aSVaclav Hapla           masterCone[c] = leaves[p][c];
82927d0e99aSVaclav Hapla           continue;
83027d0e99aSVaclav Hapla         }
831f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
832f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
833f80536cbSVaclav Hapla         ierr = PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr);
83427d0e99aSVaclav Hapla         if (PetscUnlikely(r < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): leave rank not found among remote ranks",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]);
83527d0e99aSVaclav Hapla         if (PetscUnlikely(ranks[r] < 0 || ranks[r] >= size)) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense",p,c,size,r,ranks[r]);
836f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
837f80536cbSVaclav Hapla         o = roffset[r];
838f80536cbSVaclav Hapla         n = roffset[r+1] - o;
839f80536cbSVaclav Hapla         ierr = PetscFindInt(leaves[p][c], n, &rremote1[o], &ind0);CHKERRQ(ierr);
84027d0e99aSVaclav Hapla         if (PetscUnlikely(ind0 < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): corresponding remote point not found - it seems there is missing connection in point SF!",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]);
841f80536cbSVaclav Hapla         /* Get the corresponding local point */
842f80536cbSVaclav Hapla         masterCone[c] = rmine1[o+ind0];CHKERRQ(ierr);
843f80536cbSVaclav Hapla       }
84427d0e99aSVaclav Hapla       if (debug) {ierr = PetscSynchronizedPrintf(comm, " masterCone=[%4D %4D]\n", masterCone[0], masterCone[1]);CHKERRQ(ierr);}
84527d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
846f80536cbSVaclav Hapla       /* Vaclav's note: Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */
847f80536cbSVaclav Hapla       ierr = DMPlexOrientCell(dm, p, 2, masterCone);CHKERRQ(ierr);
84827d0e99aSVaclav Hapla     } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);}
84923aaf07bSVaclav Hapla   }
85027d0e99aSVaclav Hapla   if (debug) {
85127d0e99aSVaclav Hapla     ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
85227d0e99aSVaclav Hapla     ierr = MPI_Barrier(comm);CHKERRQ(ierr);
8532e745bdaSMatthew G. Knepley   }
854adeface4SVaclav Hapla   ierr = DMViewFromOptions(dm, NULL, "-after_fix_dm_view");CHKERRQ(ierr);
8558a650c75SVaclav Hapla   ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr);
8567c7bb832SVaclav Hapla   ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr);
8572e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
8582e745bdaSMatthew G. Knepley }
8592e745bdaSMatthew G. Knepley 
8602e72742cSMatthew G. Knepley static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
8617bffde78SMichael Lange {
8622e72742cSMatthew G. Knepley   PetscInt       idx;
8632e72742cSMatthew G. Knepley   PetscMPIInt    rank;
8642e72742cSMatthew G. Knepley   PetscBool      flg;
8657bffde78SMichael Lange   PetscErrorCode ierr;
8667bffde78SMichael Lange 
8677bffde78SMichael Lange   PetscFunctionBegin;
8682e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
8692e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
8702e72742cSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
8712e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
8722e72742cSMatthew G. Knepley   for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx]);CHKERRQ(ierr);}
8732e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
8742e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
8752e72742cSMatthew G. Knepley }
8762e72742cSMatthew G. Knepley 
8772e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
8782e72742cSMatthew G. Knepley {
8792e72742cSMatthew G. Knepley   PetscInt       idx;
8802e72742cSMatthew G. Knepley   PetscMPIInt    rank;
8812e72742cSMatthew G. Knepley   PetscBool      flg;
8822e72742cSMatthew G. Knepley   PetscErrorCode ierr;
8832e72742cSMatthew G. Knepley 
8842e72742cSMatthew G. Knepley   PetscFunctionBegin;
8852e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
8862e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
8872e72742cSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
8882e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
8892e72742cSMatthew G. Knepley   if (idxname) {
8902e72742cSMatthew G. Knepley     for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index);CHKERRQ(ierr);}
8912e72742cSMatthew G. Knepley   } else {
8922e72742cSMatthew G. Knepley     for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index);CHKERRQ(ierr);}
8932e72742cSMatthew G. Knepley   }
8942e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
8952e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
8962e72742cSMatthew G. Knepley }
8972e72742cSMatthew G. Knepley 
8983be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint)
8992e72742cSMatthew G. Knepley {
9003be36e83SMatthew G. Knepley   PetscSF         sf;
9013be36e83SMatthew G. Knepley   const PetscInt *locals;
9023be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9032e72742cSMatthew G. Knepley   PetscErrorCode  ierr;
9042e72742cSMatthew G. Knepley 
9052e72742cSMatthew G. Knepley   PetscFunctionBegin;
9063be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
9073be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
9083be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr);
9092e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9102e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9112e72742cSMatthew G. Knepley   } else {
9122e72742cSMatthew G. Knepley     PetscHashIJKey key;
9133be36e83SMatthew G. Knepley     PetscInt       l;
9142e72742cSMatthew G. Knepley 
9152e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9162e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9173be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr);
9183be36e83SMatthew G. Knepley     if (l >= 0) {
9193be36e83SMatthew G. Knepley       *localPoint = locals[l];
9202e72742cSMatthew G. Knepley     } else PetscFunctionReturn(1);
9212e72742cSMatthew G. Knepley   }
9222e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
9232e72742cSMatthew G. Knepley }
9242e72742cSMatthew G. Knepley 
9253be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint)
9263be36e83SMatthew G. Knepley {
9273be36e83SMatthew G. Knepley   PetscSF            sf;
9283be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9293be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9303be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9313be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9323be36e83SMatthew G. Knepley   PetscErrorCode     ierr;
9333be36e83SMatthew G. Knepley 
9343be36e83SMatthew G. Knepley   PetscFunctionBegin;
9353be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
9363be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
9373be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr);
9383be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9393be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
9403be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
9413be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9423be36e83SMatthew G. Knepley   ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr);
9433be36e83SMatthew G. Knepley   if (l < 0) PetscFunctionReturn(1);
9443be36e83SMatthew G. Knepley   *remotePoint = remotes[l];
9453be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9463be36e83SMatthew G. Knepley   owned:
9473be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9483be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
9493be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9503be36e83SMatthew G. Knepley }
9513be36e83SMatthew G. Knepley 
9523be36e83SMatthew G. Knepley 
9533be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
9543be36e83SMatthew G. Knepley {
9553be36e83SMatthew G. Knepley   PetscSF         sf;
9563be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9573be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9583be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
9593be36e83SMatthew G. Knepley 
9603be36e83SMatthew G. Knepley   PetscFunctionBegin;
9613be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9623be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
9633be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr);
9643be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
9653be36e83SMatthew G. Knepley   ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr);
9663be36e83SMatthew G. Knepley   if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);}
9673be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
9683be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
9693be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
9703be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9713be36e83SMatthew G. Knepley }
9723be36e83SMatthew G. Knepley 
9733be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
9743be36e83SMatthew G. Knepley {
9753be36e83SMatthew G. Knepley   const PetscInt *cone;
9763be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9773be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
9783be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
9793be36e83SMatthew G. Knepley 
9803be36e83SMatthew G. Knepley   PetscFunctionBegin;
9813be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
9823be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
9833be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9843be36e83SMatthew G. Knepley     PetscBool pointShared;
9853be36e83SMatthew G. Knepley 
9863be36e83SMatthew G. Knepley     ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr);
9873be36e83SMatthew G. Knepley     cShared = (PetscBool) (cShared && pointShared);
9883be36e83SMatthew G. Knepley   }
9893be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
9903be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9913be36e83SMatthew G. Knepley }
9923be36e83SMatthew G. Knepley 
9933be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
9943be36e83SMatthew G. Knepley {
9953be36e83SMatthew G. Knepley   const PetscInt *cone;
9963be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9973be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
9983be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
9993be36e83SMatthew G. Knepley 
10003be36e83SMatthew G. Knepley   PetscFunctionBegin;
10013be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
10023be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
10033be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10043be36e83SMatthew G. Knepley     PetscSFNode rcp;
10053be36e83SMatthew G. Knepley 
10063be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp);
10073be36e83SMatthew G. Knepley     if (ierr) {
10083be36e83SMatthew G. Knepley       cmin = missing;
10093be36e83SMatthew G. Knepley     } else {
10103be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10113be36e83SMatthew G. Knepley     }
10123be36e83SMatthew G. Knepley   }
10133be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10143be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
10153be36e83SMatthew G. Knepley }
10163be36e83SMatthew G. Knepley 
10173be36e83SMatthew G. Knepley /*
10183be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10193be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10203be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10213be36e83SMatthew G. Knepley */
10223be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
10233be36e83SMatthew G. Knepley {
10243be36e83SMatthew G. Knepley   MPI_Comm        comm;
10253be36e83SMatthew G. Knepley   const PetscInt *support;
10263be36e83SMatthew G. Knepley   PetscInt        supportSize, s, off = 0, idx = 0;
10273be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10283be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
10293be36e83SMatthew G. Knepley 
10303be36e83SMatthew G. Knepley   PetscFunctionBegin;
10313be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
10323be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
10333be36e83SMatthew G. Knepley   ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
10343be36e83SMatthew G. Knepley   ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
10353be36e83SMatthew G. Knepley   if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);}
10363be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10373be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10383be36e83SMatthew G. Knepley     const PetscInt *cone;
10393be36e83SMatthew G. Knepley     PetscSFNode     cpmin={-1,-1}, rp={-1,-1};
10403be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10413be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10423be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10433be36e83SMatthew G. Knepley 
10443be36e83SMatthew G. Knepley     /* Only add point once */
10453be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Support face %D\n", rank, face);CHKERRQ(ierr);}
10463be36e83SMatthew G. Knepley     key.i = p;
10473be36e83SMatthew G. Knepley     key.j = face;
10483be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr);
10493be36e83SMatthew G. Knepley     if (f >= 0) continue;
10503be36e83SMatthew G. Knepley     ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr);
10513be36e83SMatthew G. Knepley     ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr);
10523be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr);
10533be36e83SMatthew G. Knepley     if (debug) {
10543be36e83SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d]      Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr);
10553be36e83SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d]      Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index);CHKERRQ(ierr);
10563be36e83SMatthew G. Knepley     }
10573be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
10583be36e83SMatthew G. Knepley       ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
10593be36e83SMatthew G. Knepley       if (candidates) {
10603be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %D at idx %D\n[%d]     ", rank, face, idx, rank);CHKERRQ(ierr);}
10613be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
10623be36e83SMatthew G. Knepley         ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr);
10633be36e83SMatthew G. Knepley         candidates[off+idx].rank    = -1;
10643be36e83SMatthew G. Knepley         candidates[off+idx++].index = coneSize-1;
10653be36e83SMatthew G. Knepley         candidates[off+idx].rank    = rank;
10663be36e83SMatthew G. Knepley         candidates[off+idx++].index = face;
10673be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
10683be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
10693be36e83SMatthew G. Knepley 
10703be36e83SMatthew G. Knepley           if (cp == p) continue;
10713be36e83SMatthew G. Knepley           ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr);
10723be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);}
10733be36e83SMatthew G. Knepley           ++idx;
10743be36e83SMatthew G. Knepley         }
10753be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);}
10763be36e83SMatthew G. Knepley       } else {
10773be36e83SMatthew G. Knepley         /* Add cone size to section */
10783be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);}
10793be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
10803be36e83SMatthew G. Knepley         ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
10813be36e83SMatthew G. Knepley         ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr);
10823be36e83SMatthew G. Knepley       }
10833be36e83SMatthew G. Knepley     }
10843be36e83SMatthew G. Knepley   }
10853be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
10863be36e83SMatthew G. Knepley }
10873be36e83SMatthew G. Knepley 
10882e72742cSMatthew G. Knepley /*@
10892e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
10902e72742cSMatthew G. Knepley 
1091d083f849SBarry Smith   Collective on dm
10922e72742cSMatthew G. Knepley 
10932e72742cSMatthew G. Knepley   Input Parameters:
10942e72742cSMatthew G. Knepley + dm      - The interpolated DM
10952e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
10962e72742cSMatthew G. Knepley 
10972e72742cSMatthew G. Knepley   Output Parameter:
10982e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
10992e72742cSMatthew G. Knepley 
1100f0cfc026SVaclav Hapla   Level: developer
11012e72742cSMatthew G. Knepley 
11022e72742cSMatthew G. Knepley    Note: All debugging for this process can be turned on with the options: -dm_interp_pre_view -petscsf_interp_pre_view -petscsection_interp_candidate_view -petscsection_interp_candidate_remote_view -petscsection_interp_claim_view -petscsf_interp_pre_view -dmplex_interp_debug
11032e72742cSMatthew G. Knepley 
11042e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate()
11052e72742cSMatthew G. Knepley @*/
1106e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
11072e72742cSMatthew G. Knepley {
11083be36e83SMatthew G. Knepley   MPI_Comm           comm;
11093be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11103be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11113be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11123be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11132e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11142e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11153be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11163be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11173be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1118f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11192e72742cSMatthew G. Knepley   PetscErrorCode     ierr;
11202e72742cSMatthew G. Knepley 
11212e72742cSMatthew G. Knepley   PetscFunctionBegin;
1122f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11233be36e83SMatthew G. Knepley   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3);
1124f0cfc026SVaclav Hapla   ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr);
1125f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
11263be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11273be36e83SMatthew G. Knepley   ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr);
11283be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
11293be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
11303be36e83SMatthew G. Knepley   ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr);
11313be36e83SMatthew G. Knepley   if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11323be36e83SMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr);
11332e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr);
11342e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr);
113525afeb17SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
11363be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11373be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr);
11383be36e83SMatthew G. Knepley   if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11393be36e83SMatthew G. Knepley   ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr);
11403be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11413be36e83SMatthew G. Knepley     PetscHashIJKey key;
11422e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11432e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11443be36e83SMatthew G. Knepley     ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr);
11457bffde78SMichael Lange   }
114666aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11472e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr);
11482e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr);
11493be36e83SMatthew G. Knepley   ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr);
11503be36e83SMatthew G. Knepley   /*
11513be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11523be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11533be36e83SMatthew G. Knepley   \begin{itemize}
11543be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11553be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11563be36e83SMatthew G. Knepley   \end{itemize}
11573be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
11583be36e83SMatthew G. Knepley   \item At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared \label{alg:rootStep} and choose the root face
11593be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
11603be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
11613be36e83SMatthew G. Knepley   */
11623be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
11633be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
11643be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
11653be36e83SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr);
11663be36e83SMatthew G. Knepley   ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr);
11677bffde78SMichael Lange   {
11683be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
11692e72742cSMatthew G. Knepley 
11703be36e83SMatthew G. Knepley     ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr);
11713be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11723be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11732e72742cSMatthew G. Knepley 
11743be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
11753be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr);
11762e72742cSMatthew G. Knepley     }
11773be36e83SMatthew G. Knepley     ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr);
11787bffde78SMichael Lange     ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr);
11797bffde78SMichael Lange     ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr);
11807bffde78SMichael Lange     ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr);
11813be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11823be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11832e72742cSMatthew G. Knepley 
11843be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
11853be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr);
11862e72742cSMatthew G. Knepley     }
11873be36e83SMatthew G. Knepley     ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr);
11883be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
11897bffde78SMichael Lange   }
11903be36e83SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr);
11912e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr);
11923be36e83SMatthew G. Knepley   ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr);
11933be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
11942e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
11957bffde78SMichael Lange   {
11967bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
11977bffde78SMichael Lange     PetscInt *remoteOffsets;
11982e72742cSMatthew G. Knepley 
11997bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
12007bffde78SMichael Lange     ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr);
12013be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr);
12023be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr);
12033be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr);
12043be36e83SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr);
12057bffde78SMichael Lange     ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr);
12067bffde78SMichael Lange     ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr);
12077bffde78SMichael Lange     ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr);
12087bffde78SMichael Lange     ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr);
12097bffde78SMichael Lange     ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr);
12107bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
12112e72742cSMatthew G. Knepley 
12123be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr);
12133be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr);
12143be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr);
12157bffde78SMichael Lange   }
12163be36e83SMatthew G. Knepley   /* Step 3: At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared and choose the root face */
12177bffde78SMichael Lange   {
12183be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
12193be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12203be36e83SMatthew G. Knepley 
12213be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr);
12222e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12233be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12242e72742cSMatthew G. Knepley       PetscInt deg;
12253be36e83SMatthew G. Knepley 
12262e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12272e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12282e72742cSMatthew G. Knepley 
12293be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr);
12303be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr);
12313be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12322e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12333be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
12343be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
12353be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx+1];
12363be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
12373be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12383be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
12392e72742cSMatthew G. Knepley           const PetscInt        *join  = NULL;
12403be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
12413be36e83SMatthew G. Knepley           PetscHashIter          iter;
12423be36e83SMatthew G. Knepley           PetscBool              missing;
12432e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12442e72742cSMatthew G. Knepley 
1245*66e92ce5SVaclav Hapla           if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking face (%D, %D) at (%D, %D, %D) with cone size %D\n", rank, rface.rank, rface.index, r, idx, d, Np);CHKERRQ(ierr);}
1246*66e92ce5SVaclav Hapla           if (Np > 4) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%D, %D) at (%D, %D, %D) with %D cone points", rface.rank, rface.index, r, idx, d, Np);
12473be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12483be36e83SMatthew G. Knepley           fcp0.index = r;
12493be36e83SMatthew G. Knepley           d += Np;
12503be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12513be36e83SMatthew G. Knepley           key.i = fcp0;
12523be36e83SMatthew G. Knepley           key.j = fcone[0];
12533be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12543be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12553be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
12563be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
12573be36e83SMatthew G. Knepley           if (missing) {
12583be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
12593be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
12603be36e83SMatthew G. Knepley           } else {
12613be36e83SMatthew G. Knepley             PetscSFNode oface;
12623be36e83SMatthew G. Knepley 
12633be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
12643be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
12653be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
12663be36e83SMatthew G. Knepley               ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
12673be36e83SMatthew G. Knepley             }
12683be36e83SMatthew G. Knepley           }
12693be36e83SMatthew G. Knepley           /* Check for local face */
12702e72742cSMatthew G. Knepley           points[0] = r;
12713be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
12723be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]);
12733be36e83SMatthew G. Knepley             if (ierr) break; /* We got a point not in our overlap */
12743be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);}
12757bffde78SMichael Lange           }
12762e72742cSMatthew G. Knepley           if (ierr) continue;
12773be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
12787bffde78SMichael Lange           if (joinSize == 1) {
12793be36e83SMatthew G. Knepley             PetscSFNode lface;
12803be36e83SMatthew G. Knepley             PetscSFNode oface;
12813be36e83SMatthew G. Knepley 
12823be36e83SMatthew G. Knepley             /* Always replace with local face */
12833be36e83SMatthew G. Knepley             lface.rank  = rank;
12843be36e83SMatthew G. Knepley             lface.index = join[0];
12853be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
12863be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank);CHKERRQ(ierr);}
12873be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr);
12887bffde78SMichael Lange           }
12893be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
12903be36e83SMatthew G. Knepley         }
12913be36e83SMatthew G. Knepley       }
12923be36e83SMatthew G. Knepley       /* Put back faces for this root */
12933be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
12943be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
12953be36e83SMatthew G. Knepley 
12963be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr);
12973be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr);
12983be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12993be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13003be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
13013be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
13023be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
13033be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13043be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
13053be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
13063be36e83SMatthew G. Knepley           PetscHashIter          iter;
13073be36e83SMatthew G. Knepley           PetscBool              missing;
13083be36e83SMatthew G. Knepley 
13093be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);}
13103be36e83SMatthew G. Knepley           if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np);
13113be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13123be36e83SMatthew G. Knepley           fcp0.index = r;
13133be36e83SMatthew G. Knepley           d += Np;
13143be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13153be36e83SMatthew G. Knepley           key.i = fcp0;
13163be36e83SMatthew G. Knepley           key.j = fcone[0];
13173be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13183be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13193be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
13203be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]    key (%D, %D) (%D, %D) (%D, %D) (%D, %D)\n", rank, key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index);CHKERRQ(ierr);}
13213be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
13223be36e83SMatthew G. Knepley           if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an assoicated face", r, idx2);
13233be36e83SMatthew G. Knepley           else        {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);}
13247bffde78SMichael Lange         }
13257bffde78SMichael Lange       }
13267bffde78SMichael Lange     }
13272e72742cSMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);}
13283be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr);
13297bffde78SMichael Lange   }
13303be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13317bffde78SMichael Lange   {
13327bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13337bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13342e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13353be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13362e72742cSMatthew G. Knepley 
13373be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13387bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
13393be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr);
13403be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr);
13413be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr);
13422e72742cSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr);
13432e72742cSMatthew G. Knepley     ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr);
13443be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13457bffde78SMichael Lange     ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr);
13467bffde78SMichael Lange     ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr);
13477bffde78SMichael Lange     ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr);
13487bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
13493be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr);
13502e72742cSMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr);
13513be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr);
13523be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
13533be36e83SMatthew G. Knepley     /* TODO I should not have to do a join here since I already put the face and its cone in the candidate section */
1354e8f14785SLisandro Dalcin     ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr);
13553be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
13563be36e83SMatthew G. Knepley       PetscInt dof, off, d;
13572e72742cSMatthew G. Knepley 
13583be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %D\n", rank, r);CHKERRQ(ierr);}
13593be36e83SMatthew G. Knepley       ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr);
13603be36e83SMatthew G. Knepley       ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr);
13612e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
13623be36e83SMatthew G. Knepley         if (claims[off+d].rank >= 0) {
13633be36e83SMatthew G. Knepley           const PetscInt  faceInd = off+d;
13643be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off+d].index;
13652e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
13662e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
13672e72742cSMatthew G. Knepley 
13683be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index);CHKERRQ(ierr);}
13693be36e83SMatthew G. Knepley           points[0] = r;
13703be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[0]);CHKERRQ(ierr);}
13713be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
13723be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr);
13733be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[c+1]);CHKERRQ(ierr);}
13742e72742cSMatthew G. Knepley           }
13753be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
13762e72742cSMatthew G. Knepley           if (joinSize == 1) {
13773be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
13783be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);}
13793be36e83SMatthew G. Knepley             } else {
13803be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Found local face %D\n", rank, join[0]);CHKERRQ(ierr);}
13812e72742cSMatthew G. Knepley               ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr);
13822e72742cSMatthew G. Knepley             }
13833be36e83SMatthew G. Knepley           } else {
13843be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank);CHKERRQ(ierr);}
13853be36e83SMatthew G. Knepley           }
13863be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
13873be36e83SMatthew G. Knepley         } else {
13883be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    No claim for point %D\n", rank, r);CHKERRQ(ierr);}
13893be36e83SMatthew G. Knepley           d += claims[off+d].index+1;
13907bffde78SMichael Lange         }
13917bffde78SMichael Lange       }
13923be36e83SMatthew G. Knepley     }
13933be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
13943be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
13953be36e83SMatthew G. Knepley     ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr);
13967bffde78SMichael Lange     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
13973be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr);
13983be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr);
13993be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14003be36e83SMatthew G. Knepley       localPointsNew[l] = localPoints[l];
14013be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14023be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14037bffde78SMichael Lange     }
14043be36e83SMatthew G. Knepley     p = Nl;
1405e8f14785SLisandro Dalcin     ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr);
14063be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14073be36e83SMatthew G. Knepley     ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr);
14083be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14093be36e83SMatthew G. Knepley       PetscInt off;
14103be36e83SMatthew G. Knepley       ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr);
14113be36e83SMatthew G. Knepley       if (claims[off].rank < 0 || claims[off].index < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index);
14123be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14137bffde78SMichael Lange     }
14143be36e83SMatthew G. Knepley     ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr);
14153be36e83SMatthew G. Knepley     ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
14163be36e83SMatthew G. Knepley     ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr);
14177bffde78SMichael Lange     ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr);
14183be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr);
14197bffde78SMichael Lange     ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr);
1420e8f14785SLisandro Dalcin     ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr);
14217bffde78SMichael Lange   }
14223be36e83SMatthew G. Knepley   ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr);
14237bffde78SMichael Lange   ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr);
14243be36e83SMatthew G. Knepley   ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr);
14257bffde78SMichael Lange   ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr);
14267bffde78SMichael Lange   ierr = PetscFree(candidates);CHKERRQ(ierr);
14277bffde78SMichael Lange   ierr = PetscFree(candidatesRemote);CHKERRQ(ierr);
14287bffde78SMichael Lange   ierr = PetscFree(claims);CHKERRQ(ierr);
142925afeb17SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
14307bffde78SMichael Lange   PetscFunctionReturn(0);
14317bffde78SMichael Lange }
14327bffde78SMichael Lange 
1433248eb259SVaclav Hapla /*@
143480330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
143580330477SMatthew G. Knepley 
1436d083f849SBarry Smith   Collective on dm
143780330477SMatthew G. Knepley 
1438e56d480eSMatthew G. Knepley   Input Parameters:
1439e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
144010a67516SMatthew G. Knepley - dmInt - The interpolated DM
144180330477SMatthew G. Knepley 
144280330477SMatthew G. Knepley   Output Parameter:
14434e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
144480330477SMatthew G. Knepley 
144580330477SMatthew G. Knepley   Level: intermediate
144680330477SMatthew G. Knepley 
144795452b02SPatrick Sanan   Notes:
144895452b02SPatrick Sanan     It does not copy over the coordinates.
144943eeeb2dSStefano Zampini 
14509ade3219SVaclav Hapla   Developer Notes:
14519ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
14529ade3219SVaclav Hapla 
145343eeeb2dSStefano Zampini .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates()
145480330477SMatthew G. Knepley @*/
14559f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
14569f074e33SMatthew G Knepley {
1457a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
14589a5b13a2SMatthew G Knepley   DM             idm, odm = dm;
14597bffde78SMichael Lange   PetscSF        sfPoint;
14602e1b13c2SMatthew G. Knepley   PetscInt       depth, dim, d;
146110a67516SMatthew G. Knepley   const char    *name;
1462b325530aSVaclav Hapla   PetscBool      flg=PETSC_TRUE;
14639f074e33SMatthew G Knepley   PetscErrorCode ierr;
14649f074e33SMatthew G Knepley 
14659f074e33SMatthew G Knepley   PetscFunctionBegin;
146610a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
146710a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
1468a72f3261SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
14692e1b13c2SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1470c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1471827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1472827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1473827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
147476b791aaSMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
147576b791aaSMatthew G. Knepley     idm  = dm;
1476b21b8912SMatthew G. Knepley   } else {
14779a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
14789a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
147910a67516SMatthew G. Knepley       ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr);
14809a5b13a2SMatthew G Knepley       ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr);
1481c73cfb54SMatthew G. Knepley       ierr = DMSetDimension(idm, dim);CHKERRQ(ierr);
14827bffde78SMichael Lange       if (depth > 0) {
14837bffde78SMichael Lange         ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr);
14847bffde78SMichael Lange         ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr);
148594488200SVaclav Hapla         {
14863be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
148794488200SVaclav Hapla           PetscInt nroots;
148894488200SVaclav Hapla           ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
148994488200SVaclav Hapla           if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);}
149094488200SVaclav Hapla         }
14917bffde78SMichael Lange       }
14929a5b13a2SMatthew G Knepley       if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);}
14939a5b13a2SMatthew G Knepley       odm = idm;
14949f074e33SMatthew G Knepley     }
149510a67516SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm,  &name);CHKERRQ(ierr);
149610a67516SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) idm,  name);CHKERRQ(ierr);
149710a67516SMatthew G. Knepley     ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr);
14985d80c0bfSVaclav Hapla     ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr);
1499b325530aSVaclav Hapla     ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr);
150027d0e99aSVaclav Hapla     if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);}
150184699f70SSatish Balay   }
150243eeeb2dSStefano Zampini   {
150343eeeb2dSStefano Zampini     PetscBool            isper;
150443eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
150543eeeb2dSStefano Zampini     const DMBoundaryType *bd;
150643eeeb2dSStefano Zampini 
150743eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
150843eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr);
150943eeeb2dSStefano Zampini   }
1510827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1511827c4036SVaclav Hapla   {
1512d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) idm->data;
1513827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1514827c4036SVaclav Hapla   }
15159a5b13a2SMatthew G Knepley   *dmInt = idm;
1516a72f3261SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
15179f074e33SMatthew G Knepley   PetscFunctionReturn(0);
15189f074e33SMatthew G Knepley }
151907b0a1fcSMatthew G Knepley 
152080330477SMatthew G. Knepley /*@
152180330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
152280330477SMatthew G. Knepley 
1523d083f849SBarry Smith   Collective on dmA
152480330477SMatthew G. Knepley 
152580330477SMatthew G. Knepley   Input Parameter:
152680330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
152780330477SMatthew G. Knepley 
152880330477SMatthew G. Knepley   Output Parameter:
152980330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
153080330477SMatthew G. Knepley 
153180330477SMatthew G. Knepley   Level: intermediate
153280330477SMatthew G. Knepley 
153380330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
153480330477SMatthew G. Knepley 
153565f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
153680330477SMatthew G. Knepley @*/
153707b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
153807b0a1fcSMatthew G Knepley {
153907b0a1fcSMatthew G Knepley   Vec            coordinatesA, coordinatesB;
154043eeeb2dSStefano Zampini   VecType        vtype;
154107b0a1fcSMatthew G Knepley   PetscSection   coordSectionA, coordSectionB;
154207b0a1fcSMatthew G Knepley   PetscScalar   *coordsA, *coordsB;
15430bedd6beSMatthew G. Knepley   PetscInt       spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
154490a8aa44SJed Brown   PetscInt       cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
154543eeeb2dSStefano Zampini   PetscBool      lc = PETSC_FALSE;
154607b0a1fcSMatthew G Knepley   PetscErrorCode ierr;
154707b0a1fcSMatthew G Knepley 
154807b0a1fcSMatthew G Knepley   PetscFunctionBegin;
154943eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
155043eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
155176b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
155290a8aa44SJed Brown   ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr);
155390a8aa44SJed Brown   ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr);
155407b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr);
155507b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr);
155607b0a1fcSMatthew G Knepley   if ((vEndA-vStartA) != (vEndB-vStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB);
155743eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr);
155843eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr);
155969d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr);
156069d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr);
1561972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
15620bedd6beSMatthew G. Knepley   ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr);
15630bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
15640bedd6beSMatthew G. Knepley   if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf);
1565df26b574SMatthew G. Knepley   if (!coordSectionB) {
1566df26b574SMatthew G. Knepley     PetscInt dim;
1567df26b574SMatthew G. Knepley 
1568df26b574SMatthew G. Knepley     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr);
1569df26b574SMatthew G. Knepley     ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr);
1570df26b574SMatthew G. Knepley     ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr);
1571df26b574SMatthew G. Knepley     ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr);
1572df26b574SMatthew G. Knepley   }
157307b0a1fcSMatthew G Knepley   ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr);
157407b0a1fcSMatthew G Knepley   ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr);
157507b0a1fcSMatthew G Knepley   ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr);
157643eeeb2dSStefano Zampini   ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr);
157743eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
1578367003a6SStefano Zampini     if ((cEndA-cStartA) != (cEndB-cStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB);
157943eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
158043eeeb2dSStefano Zampini     cE = vEndB;
158143eeeb2dSStefano Zampini     lc = PETSC_TRUE;
158243eeeb2dSStefano Zampini   } else {
158343eeeb2dSStefano Zampini     cS = vStartB;
158443eeeb2dSStefano Zampini     cE = vEndB;
158543eeeb2dSStefano Zampini   }
158643eeeb2dSStefano Zampini   ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr);
158707b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
158807b0a1fcSMatthew G Knepley     ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr);
158907b0a1fcSMatthew G Knepley     ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr);
159007b0a1fcSMatthew G Knepley   }
159143eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
159243eeeb2dSStefano Zampini     PetscInt c;
159343eeeb2dSStefano Zampini 
159443eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
159543eeeb2dSStefano Zampini       PetscInt dof;
159643eeeb2dSStefano Zampini 
159743eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
159843eeeb2dSStefano Zampini       ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr);
159943eeeb2dSStefano Zampini       ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr);
160043eeeb2dSStefano Zampini     }
160143eeeb2dSStefano Zampini   }
160207b0a1fcSMatthew G Knepley   ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr);
160307b0a1fcSMatthew G Knepley   ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr);
160407b0a1fcSMatthew G Knepley   ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr);
16058b9ced59SLisandro Dalcin   ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr);
160607b0a1fcSMatthew G Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr);
160707b0a1fcSMatthew G Knepley   ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr);
160843eeeb2dSStefano Zampini   ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr);
160943eeeb2dSStefano Zampini   ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr);
161043eeeb2dSStefano Zampini   ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr);
161143eeeb2dSStefano Zampini   ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr);
161207b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr);
161307b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr);
161407b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB-vStartB; ++v) {
161543eeeb2dSStefano Zampini     PetscInt offA, offB;
161643eeeb2dSStefano Zampini 
161743eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr);
161843eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr);
161907b0a1fcSMatthew G Knepley     for (d = 0; d < spaceDim; ++d) {
162043eeeb2dSStefano Zampini       coordsB[offB+d] = coordsA[offA+d];
162143eeeb2dSStefano Zampini     }
162243eeeb2dSStefano Zampini   }
162343eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
162443eeeb2dSStefano Zampini     PetscInt c;
162543eeeb2dSStefano Zampini 
162643eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
162743eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
162843eeeb2dSStefano Zampini 
162943eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr);
163043eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr);
163143eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
1632580bdb30SBarry Smith       ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr);
163307b0a1fcSMatthew G Knepley     }
163407b0a1fcSMatthew G Knepley   }
163507b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr);
163607b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr);
163707b0a1fcSMatthew G Knepley   ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr);
163807b0a1fcSMatthew G Knepley   ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr);
163907b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
164007b0a1fcSMatthew G Knepley }
16415c386225SMatthew G. Knepley 
16424e3744c5SMatthew G. Knepley /*@
16434e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16444e3744c5SMatthew G. Knepley 
1645d083f849SBarry Smith   Collective on dm
16464e3744c5SMatthew G. Knepley 
16474e3744c5SMatthew G. Knepley   Input Parameter:
16484e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
16494e3744c5SMatthew G. Knepley 
16504e3744c5SMatthew G. Knepley   Output Parameter:
16514e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
16524e3744c5SMatthew G. Knepley 
16534e3744c5SMatthew G. Knepley   Level: intermediate
16544e3744c5SMatthew G. Knepley 
165595452b02SPatrick Sanan   Notes:
165695452b02SPatrick Sanan     It does not copy over the coordinates.
165743eeeb2dSStefano Zampini 
16589ade3219SVaclav Hapla   Developer Notes:
16599ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
16609ade3219SVaclav Hapla 
166143eeeb2dSStefano Zampini .seealso: DMPlexInterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates()
16624e3744c5SMatthew G. Knepley @*/
16634e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
16644e3744c5SMatthew G. Knepley {
1665827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
16664e3744c5SMatthew G. Knepley   DM             udm;
1667c9f63434SStefano Zampini   PetscInt       dim, vStart, vEnd, cStart, cEnd, cMax, c, maxConeSize = 0, *cone;
16684e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
16694e3744c5SMatthew G. Knepley 
16704e3744c5SMatthew G. Knepley   PetscFunctionBegin;
167143eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
167243eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
1673c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1674827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1675827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1676827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1677827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
16784e3744c5SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
1679595d4abbSMatthew G. Knepley     *dmUnint = dm;
1680595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
16814e3744c5SMatthew G. Knepley   }
1682595d4abbSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1683595d4abbSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1684c9f63434SStefano Zampini   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
16854e3744c5SMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr);
16864e3744c5SMatthew G. Knepley   ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr);
1687c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(udm, dim);CHKERRQ(ierr);
16884e3744c5SMatthew G. Knepley   ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr);
16894e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1690595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
16914e3744c5SMatthew G. Knepley 
16924e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
16934e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
16944e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
16954e3744c5SMatthew G. Knepley 
16964e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
16974e3744c5SMatthew G. Knepley     }
16984e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
16994e3744c5SMatthew G. Knepley     ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr);
1700595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17014e3744c5SMatthew G. Knepley   }
17024e3744c5SMatthew G. Knepley   ierr = DMSetUp(udm);CHKERRQ(ierr);
1703785e854fSJed Brown   ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr);
17044e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1705595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17064e3744c5SMatthew G. Knepley 
17074e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
17084e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
17094e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17104e3744c5SMatthew G. Knepley 
17114e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17124e3744c5SMatthew G. Knepley     }
17134e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
17144e3744c5SMatthew G. Knepley     ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr);
17154e3744c5SMatthew G. Knepley   }
17164e3744c5SMatthew G. Knepley   ierr = PetscFree(cone);CHKERRQ(ierr);
1717c9f63434SStefano Zampini   ierr = DMPlexSetHybridBounds(udm, cMax, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
17184e3744c5SMatthew G. Knepley   ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr);
17194e3744c5SMatthew G. Knepley   ierr = DMPlexStratify(udm);CHKERRQ(ierr);
17205c7de58aSMatthew G. Knepley   /* Reduce SF */
17215c7de58aSMatthew G. Knepley   {
17225c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17235c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17245c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17255c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17265c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
17275c7de58aSMatthew G. Knepley     PetscInt           vEnd, numRoots, numLeaves, l;
17285c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17295c7de58aSMatthew G. Knepley     PetscErrorCode     ierr;
17305c7de58aSMatthew G. Knepley 
17315c7de58aSMatthew G. Knepley     /* Get original SF information */
17325c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
17335c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr);
17345c7de58aSMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr);
17355c7de58aSMatthew G. Knepley     ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
17365c7de58aSMatthew G. Knepley     /* Allocate space for cells and vertices */
17375c7de58aSMatthew G. Knepley     for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++;
17385c7de58aSMatthew G. Knepley     /* Fill in leaves */
17395c7de58aSMatthew G. Knepley     if (vEnd >= 0) {
17405c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr);
17415c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr);
17425c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
17435c7de58aSMatthew G. Knepley         if (localPoints[l] < vEnd) {
17445c7de58aSMatthew G. Knepley           localPointsUn[n]        = localPoints[l];
17455c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17465c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17475c7de58aSMatthew G. Knepley           ++n;
17485c7de58aSMatthew G. Knepley         }
17495c7de58aSMatthew G. Knepley       }
17505c7de58aSMatthew G. Knepley       if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn);
17515c7de58aSMatthew G. Knepley       ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr);
17525c7de58aSMatthew G. Knepley     }
17535c7de58aSMatthew G. Knepley   }
175443eeeb2dSStefano Zampini   {
175543eeeb2dSStefano Zampini     PetscBool            isper;
175643eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
175743eeeb2dSStefano Zampini     const DMBoundaryType *bd;
175843eeeb2dSStefano Zampini 
175943eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
176043eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr);
176143eeeb2dSStefano Zampini   }
1762827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1763827c4036SVaclav Hapla   {
1764d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) udm->data;
1765827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1766827c4036SVaclav Hapla   }
17674e3744c5SMatthew G. Knepley   *dmUnint = udm;
17684e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
17694e3744c5SMatthew G. Knepley }
1770a7748839SVaclav Hapla 
1771a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1772a7748839SVaclav Hapla {
1773a7748839SVaclav Hapla   PetscInt       coneSize, depth, dim, h, p, pStart, pEnd;
1774a7748839SVaclav Hapla   MPI_Comm       comm;
1775a7748839SVaclav Hapla   PetscErrorCode ierr;
1776a7748839SVaclav Hapla 
1777a7748839SVaclav Hapla   PetscFunctionBegin;
1778a7748839SVaclav Hapla   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1779a7748839SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1780a7748839SVaclav Hapla   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1781a7748839SVaclav Hapla 
1782a7748839SVaclav Hapla   if (depth == dim) {
1783a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1784a7748839SVaclav Hapla     if (!dim) goto finish;
1785a7748839SVaclav Hapla 
1786a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
1787a7748839SVaclav Hapla     ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr);
1788a7748839SVaclav Hapla     for (p=pStart; p<pEnd; p++) {
1789a7748839SVaclav Hapla       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1790a7748839SVaclav Hapla       if (coneSize) {
1791a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1792a7748839SVaclav Hapla         goto finish;
1793a7748839SVaclav Hapla       }
1794a7748839SVaclav Hapla     }
1795a7748839SVaclav Hapla 
1796a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1797a7748839SVaclav Hapla     for (h=0; h<dim; h++) {
1798a7748839SVaclav Hapla       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
1799a7748839SVaclav Hapla       for (p=pStart; p<pEnd; p++) {
1800a7748839SVaclav Hapla         ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1801a7748839SVaclav Hapla         if (!coneSize) {
1802a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1803a7748839SVaclav Hapla           goto finish;
1804a7748839SVaclav Hapla         }
1805a7748839SVaclav Hapla       }
1806a7748839SVaclav Hapla     }
1807a7748839SVaclav Hapla   } else if (depth == 1) {
1808a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1809a7748839SVaclav Hapla   } else {
1810a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1811a7748839SVaclav Hapla   }
1812a7748839SVaclav Hapla finish:
1813a7748839SVaclav Hapla   PetscFunctionReturn(0);
1814a7748839SVaclav Hapla }
1815a7748839SVaclav Hapla 
1816a7748839SVaclav Hapla /*@
18179ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1818a7748839SVaclav Hapla 
1819a7748839SVaclav Hapla   Not Collective
1820a7748839SVaclav Hapla 
1821a7748839SVaclav Hapla   Input Parameter:
1822a7748839SVaclav Hapla . dm      - The DM object
1823a7748839SVaclav Hapla 
1824a7748839SVaclav Hapla   Output Parameter:
1825a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1826a7748839SVaclav Hapla 
1827a7748839SVaclav Hapla   Level: intermediate
1828a7748839SVaclav Hapla 
1829a7748839SVaclav Hapla   Notes:
18309ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
18319ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1832a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
18339ade3219SVaclav Hapla 
1834a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1835a7748839SVaclav Hapla 
18369ade3219SVaclav Hapla   Developer Notes:
18379ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
18389ade3219SVaclav Hapla 
18399ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
18409ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
18419ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
18429ade3219SVaclav Hapla 
18439ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
18449ade3219SVaclav Hapla 
18459ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
18469ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
18479ade3219SVaclav Hapla 
1848a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective()
1849a7748839SVaclav Hapla @*/
1850a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1851a7748839SVaclav Hapla {
1852a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1853a7748839SVaclav Hapla   PetscErrorCode  ierr;
1854a7748839SVaclav Hapla 
1855a7748839SVaclav Hapla   PetscFunctionBegin;
1856a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1857a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1858a7748839SVaclav Hapla   if (plex->interpolated < 0) {
1859a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr);
1860a7748839SVaclav Hapla   } else {
1861a7748839SVaclav Hapla #if defined (PETSC_USE_DEBUG)
1862a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1863a7748839SVaclav Hapla 
1864a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr);
18657fc06600SVaclav Hapla     if (flg != plex->interpolated) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1866a7748839SVaclav Hapla #endif
1867a7748839SVaclav Hapla   }
1868a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1869a7748839SVaclav Hapla   PetscFunctionReturn(0);
1870a7748839SVaclav Hapla }
1871a7748839SVaclav Hapla 
1872a7748839SVaclav Hapla /*@
18739ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1874a7748839SVaclav Hapla 
18752666ff3cSVaclav Hapla   Collective
1876a7748839SVaclav Hapla 
1877a7748839SVaclav Hapla   Input Parameter:
1878a7748839SVaclav Hapla . dm      - The DM object
1879a7748839SVaclav Hapla 
1880a7748839SVaclav Hapla   Output Parameter:
1881a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1882a7748839SVaclav Hapla 
1883a7748839SVaclav Hapla   Level: intermediate
1884a7748839SVaclav Hapla 
1885a7748839SVaclav Hapla   Notes:
18869ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
18879ade3219SVaclav Hapla 
18889ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
18899ade3219SVaclav Hapla 
18909ade3219SVaclav Hapla   Developer Notes:
18919ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
18929ade3219SVaclav Hapla 
18939ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
18949ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
18959ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
18969ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
18979ade3219SVaclav Hapla 
18989ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1899a7748839SVaclav Hapla 
1900a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated()
1901a7748839SVaclav Hapla @*/
1902a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1903a7748839SVaclav Hapla {
1904a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1905a7748839SVaclav Hapla   PetscBool       debug=PETSC_FALSE;
1906a7748839SVaclav Hapla   PetscErrorCode  ierr;
1907a7748839SVaclav Hapla 
1908a7748839SVaclav Hapla   PetscFunctionBegin;
1909a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1910a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1911a7748839SVaclav Hapla   ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr);
1912a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1913a7748839SVaclav Hapla     DMPlexInterpolatedFlag  min, max;
1914a7748839SVaclav Hapla     MPI_Comm                comm;
1915a7748839SVaclav Hapla 
1916a7748839SVaclav Hapla     ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1917a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr);
1918a7748839SVaclav Hapla     ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr);
1919a7748839SVaclav Hapla     ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr);
1920a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1921a7748839SVaclav Hapla     if (debug) {
1922a7748839SVaclav Hapla       PetscMPIInt rank;
1923a7748839SVaclav Hapla 
1924a7748839SVaclav Hapla       ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1925a7748839SVaclav Hapla       ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr);
1926a7748839SVaclav Hapla       ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr);
1927a7748839SVaclav Hapla     }
1928a7748839SVaclav Hapla   }
1929a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1930a7748839SVaclav Hapla   PetscFunctionReturn(0);
1931a7748839SVaclav Hapla }
1932