xref: /petsc/src/dm/impls/da/dalocal.c (revision d6401b93c59c28d6e8d3fd3a212cb53b45f2ac32)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
347c6ae99SBarry Smith   Code for manipulating distributed regular arrays in parallel.
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
64035e84dSBarry Smith #include <petsc-private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
7b2fff234SMatthew G. Knepley #include <petscbt.h>
80c312b8eSJed Brown #include <petscsf.h>
937b16e26SMatthew G. Knepley #include <petscfe.h>
1047c6ae99SBarry Smith 
1147c6ae99SBarry Smith /*
12e3c5b3baSBarry Smith    This allows the DMDA vectors to properly tell MATLAB their dimensions
1347c6ae99SBarry Smith */
1447c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
15c6db04a5SJed Brown #include <engine.h>   /* MATLAB include file */
16c6db04a5SJed Brown #include <mex.h>      /* MATLAB include file */
1747c6ae99SBarry Smith #undef __FUNCT__
1847c6ae99SBarry Smith #define __FUNCT__ "VecMatlabEnginePut_DA2d"
191e6b0712SBarry Smith static PetscErrorCode  VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
2047c6ae99SBarry Smith {
2147c6ae99SBarry Smith   PetscErrorCode ierr;
2247c6ae99SBarry Smith   PetscInt       n,m;
2347c6ae99SBarry Smith   Vec            vec = (Vec)obj;
2447c6ae99SBarry Smith   PetscScalar    *array;
2547c6ae99SBarry Smith   mxArray        *mat;
269a42bb27SBarry Smith   DM             da;
2747c6ae99SBarry Smith 
2847c6ae99SBarry Smith   PetscFunctionBegin;
29c688c046SMatthew G Knepley   ierr = VecGetDM(vec, &da);CHKERRQ(ierr);
30ce94432eSBarry Smith   if (!da) SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
31aa219208SBarry Smith   ierr = DMDAGetGhostCorners(da,0,0,0,&m,&n,0);CHKERRQ(ierr);
3247c6ae99SBarry Smith 
3347c6ae99SBarry Smith   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
3447c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
3547c6ae99SBarry Smith   mat = mxCreateDoubleMatrix(m,n,mxREAL);
3647c6ae99SBarry Smith #else
3747c6ae99SBarry Smith   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
3847c6ae99SBarry Smith #endif
3947c6ae99SBarry Smith   ierr = PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));CHKERRQ(ierr);
4047c6ae99SBarry Smith   ierr = PetscObjectName(obj);CHKERRQ(ierr);
4147c6ae99SBarry Smith   engPutVariable((Engine*)mengine,obj->name,mat);
4247c6ae99SBarry Smith 
4347c6ae99SBarry Smith   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
4447c6ae99SBarry Smith   PetscFunctionReturn(0);
4547c6ae99SBarry Smith }
4647c6ae99SBarry Smith #endif
4747c6ae99SBarry Smith 
4847c6ae99SBarry Smith 
4947c6ae99SBarry Smith #undef __FUNCT__
50564755cdSBarry Smith #define __FUNCT__ "DMCreateLocalVector_DA"
517087cfbeSBarry Smith PetscErrorCode  DMCreateLocalVector_DA(DM da,Vec *g)
5247c6ae99SBarry Smith {
5347c6ae99SBarry Smith   PetscErrorCode ierr;
5447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
5547c6ae99SBarry Smith 
5647c6ae99SBarry Smith   PetscFunctionBegin;
5747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
5847c6ae99SBarry Smith   PetscValidPointer(g,2);
5911689aebSJed Brown   if (da->defaultSection) {
6011689aebSJed Brown     ierr = DMCreateLocalVector_Section_Private(da,g);CHKERRQ(ierr);
6111689aebSJed Brown   } else {
6247c6ae99SBarry Smith     ierr = VecCreate(PETSC_COMM_SELF,g);CHKERRQ(ierr);
6347c6ae99SBarry Smith     ierr = VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);CHKERRQ(ierr);
6447c6ae99SBarry Smith     ierr = VecSetBlockSize(*g,dd->w);CHKERRQ(ierr);
65401ddaa8SBarry Smith     ierr = VecSetType(*g,da->vectype);CHKERRQ(ierr);
66c688c046SMatthew G Knepley     ierr = VecSetDM(*g, da);CHKERRQ(ierr);
6747c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
6847c6ae99SBarry Smith     if (dd->w == 1  && dd->dim == 2) {
69bdf89e91SBarry Smith       ierr = PetscObjectComposeFunction((PetscObject)*g,"PetscMatlabEnginePut_C",VecMatlabEnginePut_DA2d);CHKERRQ(ierr);
7047c6ae99SBarry Smith     }
7147c6ae99SBarry Smith #endif
7211689aebSJed Brown   }
7347c6ae99SBarry Smith   PetscFunctionReturn(0);
7447c6ae99SBarry Smith }
7547c6ae99SBarry Smith 
76a66d4d66SMatthew G Knepley #undef __FUNCT__
7757459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumCells"
78939f6067SMatthew G. Knepley /*@
79939f6067SMatthew G. Knepley   DMDAGetNumCells - Get the number of cells in the local piece of the DMDA. This includes ghost cells.
80939f6067SMatthew G. Knepley 
81939f6067SMatthew G. Knepley   Input Parameter:
82939f6067SMatthew G. Knepley . dm - The DM object
83939f6067SMatthew G. Knepley 
84939f6067SMatthew G. Knepley   Output Parameters:
85939f6067SMatthew G. Knepley + numCellsX - The number of local cells in the x-direction
86939f6067SMatthew G. Knepley . numCellsY - The number of local cells in the y-direction
87939f6067SMatthew G. Knepley . numCellsZ - The number of local cells in the z-direction
88939f6067SMatthew G. Knepley - numCells - The number of local cells
89939f6067SMatthew G. Knepley 
90939f6067SMatthew G. Knepley   Level: developer
91939f6067SMatthew G. Knepley 
92939f6067SMatthew G. Knepley .seealso: DMDAGetCellPoint()
93939f6067SMatthew G. Knepley @*/
94e42e3c58SMatthew G. Knepley PetscErrorCode DMDAGetNumCells(DM dm, PetscInt *numCellsX, PetscInt *numCellsY, PetscInt *numCellsZ, PetscInt *numCells)
9557459e9aSMatthew G Knepley {
9657459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA*) dm->data;
9757459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
9857459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
9957459e9aSMatthew G Knepley   const PetscInt nC  = (mx)*(dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
10057459e9aSMatthew G Knepley 
10157459e9aSMatthew G Knepley   PetscFunctionBegin;
102*d6401b93SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
103e42e3c58SMatthew G. Knepley   if (numCellsX) {
104e42e3c58SMatthew G. Knepley     PetscValidIntPointer(numCellsX,2);
105e42e3c58SMatthew G. Knepley     *numCellsX = mx;
106e42e3c58SMatthew G. Knepley   }
107e42e3c58SMatthew G. Knepley   if (numCellsY) {
108e42e3c58SMatthew G. Knepley     PetscValidIntPointer(numCellsX,3);
109e42e3c58SMatthew G. Knepley     *numCellsY = my;
110e42e3c58SMatthew G. Knepley   }
111e42e3c58SMatthew G. Knepley   if (numCellsZ) {
112e42e3c58SMatthew G. Knepley     PetscValidIntPointer(numCellsX,4);
113e42e3c58SMatthew G. Knepley     *numCellsZ = mz;
114e42e3c58SMatthew G. Knepley   }
11557459e9aSMatthew G Knepley   if (numCells) {
116e42e3c58SMatthew G. Knepley     PetscValidIntPointer(numCells,5);
11757459e9aSMatthew G Knepley     *numCells = nC;
11857459e9aSMatthew G Knepley   }
11957459e9aSMatthew G Knepley   PetscFunctionReturn(0);
12057459e9aSMatthew G Knepley }
12157459e9aSMatthew G Knepley 
12257459e9aSMatthew G Knepley #undef __FUNCT__
123*d6401b93SMatthew G. Knepley #define __FUNCT__ "DMDAGetCellPoint"
124*d6401b93SMatthew G. Knepley /*@
125*d6401b93SMatthew G. Knepley   DMDAGetCellPoint - Get the DM point corresponding to the tuple (i, j, k) in the DMDA
126*d6401b93SMatthew G. Knepley 
127*d6401b93SMatthew G. Knepley   Input Parameters:
128*d6401b93SMatthew G. Knepley + dm - The DM object
129*d6401b93SMatthew G. Knepley - i,j,k - The global indices for the cell
130*d6401b93SMatthew G. Knepley 
131*d6401b93SMatthew G. Knepley   Output Parameters:
132*d6401b93SMatthew G. Knepley . point - The local DM point
133*d6401b93SMatthew G. Knepley 
134*d6401b93SMatthew G. Knepley   Level: developer
135*d6401b93SMatthew G. Knepley 
136*d6401b93SMatthew G. Knepley .seealso: DMDAGetNumCells()
137*d6401b93SMatthew G. Knepley @*/
138*d6401b93SMatthew G. Knepley PetscErrorCode DMDAGetCellPoint(DM dm, PetscInt i, PetscInt j, PetscInt k, PetscInt *point)
139*d6401b93SMatthew G. Knepley {
140*d6401b93SMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
141*d6401b93SMatthew G. Knepley   const PetscInt dim = da->dim;
142*d6401b93SMatthew G. Knepley   DMDALocalInfo  info;
143*d6401b93SMatthew G. Knepley   PetscErrorCode ierr;
144*d6401b93SMatthew G. Knepley 
145*d6401b93SMatthew G. Knepley   PetscFunctionBegin;
146*d6401b93SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
147*d6401b93SMatthew G. Knepley   PetscValidIntPointer(point,5);
148*d6401b93SMatthew G. Knepley   ierr = DMDAGetLocalInfo(dm, &info);CHKERRQ(ierr);
149*d6401b93SMatthew G. Knepley   if (dim > 0) {if ((i < info.gxs) || (i >= info.gxs+info.gxm)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "X index %d not in [%d, %d)", i, info.gxs, info.gxs+info.gxm);}
150*d6401b93SMatthew G. Knepley   if (dim > 1) {if ((i < info.gys) || (i >= info.gys+info.gym)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Y index %d not in [%d, %d)", i, info.gys, info.gys+info.gym);}
151*d6401b93SMatthew G. Knepley   if (dim > 2) {if ((i < info.gzs) || (i >= info.gzs+info.gzm)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Z index %d not in [%d, %d)", i, info.gzs, info.gzs+info.gzm);}
152*d6401b93SMatthew G. Knepley   *point = i + (dim > 1 ? (j + (dim > 2 ? k*info.gym : 0))*info.gxm : 0);
153*d6401b93SMatthew G. Knepley   PetscFunctionReturn(0);
154*d6401b93SMatthew G. Knepley }
155*d6401b93SMatthew G. Knepley 
156*d6401b93SMatthew G. Knepley #undef __FUNCT__
15757459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumVertices"
15857459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
15957459e9aSMatthew G Knepley {
16057459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
16157459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
16257459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
16357459e9aSMatthew G Knepley   const PetscInt nVx = mx+1;
16457459e9aSMatthew G Knepley   const PetscInt nVy = dim > 1 ? (my+1) : 1;
16557459e9aSMatthew G Knepley   const PetscInt nVz = dim > 2 ? (mz+1) : 1;
16657459e9aSMatthew G Knepley   const PetscInt nV  = nVx*nVy*nVz;
16757459e9aSMatthew G Knepley 
16857459e9aSMatthew G Knepley   PetscFunctionBegin;
16957459e9aSMatthew G Knepley   if (numVerticesX) {
17057459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesX,2);
17157459e9aSMatthew G Knepley     *numVerticesX = nVx;
17257459e9aSMatthew G Knepley   }
17357459e9aSMatthew G Knepley   if (numVerticesY) {
17457459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesY,3);
17557459e9aSMatthew G Knepley     *numVerticesY = nVy;
17657459e9aSMatthew G Knepley   }
17757459e9aSMatthew G Knepley   if (numVerticesZ) {
17857459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesZ,4);
17957459e9aSMatthew G Knepley     *numVerticesZ = nVz;
18057459e9aSMatthew G Knepley   }
18157459e9aSMatthew G Knepley   if (numVertices) {
18257459e9aSMatthew G Knepley     PetscValidIntPointer(numVertices,5);
18357459e9aSMatthew G Knepley     *numVertices = nV;
18457459e9aSMatthew G Knepley   }
18557459e9aSMatthew G Knepley   PetscFunctionReturn(0);
18657459e9aSMatthew G Knepley }
18757459e9aSMatthew G Knepley 
18857459e9aSMatthew G Knepley #undef __FUNCT__
18957459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumFaces"
19057459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
19157459e9aSMatthew G Knepley {
19257459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
19357459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
19457459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
19557459e9aSMatthew G Knepley   const PetscInt nxF = (dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
19657459e9aSMatthew G Knepley   const PetscInt nXF = (mx+1)*nxF;
19757459e9aSMatthew G Knepley   const PetscInt nyF = mx*(dim > 2 ? mz : 1);
19857459e9aSMatthew G Knepley   const PetscInt nYF = dim > 1 ? (my+1)*nyF : 0;
19957459e9aSMatthew G Knepley   const PetscInt nzF = mx*(dim > 1 ? my : 0);
20057459e9aSMatthew G Knepley   const PetscInt nZF = dim > 2 ? (mz+1)*nzF : 0;
20157459e9aSMatthew G Knepley 
20257459e9aSMatthew G Knepley   PetscFunctionBegin;
20357459e9aSMatthew G Knepley   if (numXFacesX) {
20457459e9aSMatthew G Knepley     PetscValidIntPointer(numXFacesX,2);
20557459e9aSMatthew G Knepley     *numXFacesX = nxF;
20657459e9aSMatthew G Knepley   }
20757459e9aSMatthew G Knepley   if (numXFaces) {
20857459e9aSMatthew G Knepley     PetscValidIntPointer(numXFaces,3);
20957459e9aSMatthew G Knepley     *numXFaces = nXF;
21057459e9aSMatthew G Knepley   }
21157459e9aSMatthew G Knepley   if (numYFacesY) {
21257459e9aSMatthew G Knepley     PetscValidIntPointer(numYFacesY,4);
21357459e9aSMatthew G Knepley     *numYFacesY = nyF;
21457459e9aSMatthew G Knepley   }
21557459e9aSMatthew G Knepley   if (numYFaces) {
21657459e9aSMatthew G Knepley     PetscValidIntPointer(numYFaces,5);
21757459e9aSMatthew G Knepley     *numYFaces = nYF;
21857459e9aSMatthew G Knepley   }
21957459e9aSMatthew G Knepley   if (numZFacesZ) {
22057459e9aSMatthew G Knepley     PetscValidIntPointer(numZFacesZ,6);
22157459e9aSMatthew G Knepley     *numZFacesZ = nzF;
22257459e9aSMatthew G Knepley   }
22357459e9aSMatthew G Knepley   if (numZFaces) {
22457459e9aSMatthew G Knepley     PetscValidIntPointer(numZFaces,7);
22557459e9aSMatthew G Knepley     *numZFaces = nZF;
22657459e9aSMatthew G Knepley   }
22757459e9aSMatthew G Knepley   PetscFunctionReturn(0);
22857459e9aSMatthew G Knepley }
22957459e9aSMatthew G Knepley 
23057459e9aSMatthew G Knepley #undef __FUNCT__
23157459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetHeightStratum"
23257459e9aSMatthew G Knepley PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PetscInt *pStart, PetscInt *pEnd)
23357459e9aSMatthew G Knepley {
23457459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
23557459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
23657459e9aSMatthew G Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
23757459e9aSMatthew G Knepley   PetscErrorCode ierr;
23857459e9aSMatthew G Knepley 
23957459e9aSMatthew G Knepley   PetscFunctionBegin;
2408865f1eaSKarl Rupp   if (pStart) PetscValidIntPointer(pStart,3);
2418865f1eaSKarl Rupp   if (pEnd)   PetscValidIntPointer(pEnd,4);
242e42e3c58SMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
2430298fd71SBarry Smith   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
2440298fd71SBarry Smith   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
24557459e9aSMatthew G Knepley   if (height == 0) {
24657459e9aSMatthew G Knepley     /* Cells */
2478865f1eaSKarl Rupp     if (pStart) *pStart = 0;
2488865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC;
24957459e9aSMatthew G Knepley   } else if (height == 1) {
25057459e9aSMatthew G Knepley     /* Faces */
2518865f1eaSKarl Rupp     if (pStart) *pStart = nC+nV;
2528865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
25357459e9aSMatthew G Knepley   } else if (height == dim) {
25457459e9aSMatthew G Knepley     /* Vertices */
2558865f1eaSKarl Rupp     if (pStart) *pStart = nC;
2568865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV;
25757459e9aSMatthew G Knepley   } else if (height < 0) {
25857459e9aSMatthew G Knepley     /* All points */
2598865f1eaSKarl Rupp     if (pStart) *pStart = 0;
2608865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
26182f516ccSBarry Smith   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of height %d in the DA", height);
26257459e9aSMatthew G Knepley   PetscFunctionReturn(0);
26357459e9aSMatthew G Knepley }
26457459e9aSMatthew G Knepley 
26557459e9aSMatthew G Knepley #undef __FUNCT__
266d0892670SMatthew G. Knepley #define __FUNCT__ "DMDAGetDepthStratum"
267d0892670SMatthew G. Knepley PetscErrorCode DMDAGetDepthStratum(DM dm, PetscInt depth, PetscInt *pStart, PetscInt *pEnd)
268d0892670SMatthew G. Knepley {
269d0892670SMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
270d0892670SMatthew G. Knepley   const PetscInt dim = da->dim;
271d0892670SMatthew G. Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
272d0892670SMatthew G. Knepley   PetscErrorCode ierr;
273d0892670SMatthew G. Knepley 
274d0892670SMatthew G. Knepley   PetscFunctionBegin;
275d0892670SMatthew G. Knepley   if (pStart) PetscValidIntPointer(pStart,3);
276d0892670SMatthew G. Knepley   if (pEnd)   PetscValidIntPointer(pEnd,4);
277d0892670SMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
278d0892670SMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
279d0892670SMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
280d0892670SMatthew G. Knepley   if (depth == dim) {
281d0892670SMatthew G. Knepley     /* Cells */
282d0892670SMatthew G. Knepley     if (pStart) *pStart = 0;
283d0892670SMatthew G. Knepley     if (pEnd)   *pEnd   = nC;
284d0892670SMatthew G. Knepley   } else if (depth == dim-1) {
285d0892670SMatthew G. Knepley     /* Faces */
286d0892670SMatthew G. Knepley     if (pStart) *pStart = nC+nV;
287d0892670SMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
288d0892670SMatthew G. Knepley   } else if (depth == 0) {
289d0892670SMatthew G. Knepley     /* Vertices */
290d0892670SMatthew G. Knepley     if (pStart) *pStart = nC;
291d0892670SMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV;
292d0892670SMatthew G. Knepley   } else if (depth < 0) {
293d0892670SMatthew G. Knepley     /* All points */
294d0892670SMatthew G. Knepley     if (pStart) *pStart = 0;
295d0892670SMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
296d0892670SMatthew G. Knepley   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of depth %d in the DA", depth);
297d0892670SMatthew G. Knepley   PetscFunctionReturn(0);
298d0892670SMatthew G. Knepley }
299d0892670SMatthew G. Knepley 
300d0892670SMatthew G. Knepley #undef __FUNCT__
301d0892670SMatthew G. Knepley #define __FUNCT__ "DMDAGetConeSize"
302d0892670SMatthew G. Knepley PetscErrorCode DMDAGetConeSize(DM dm, PetscInt p, PetscInt *coneSize)
303d0892670SMatthew G. Knepley {
304d0892670SMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
305d0892670SMatthew G. Knepley   const PetscInt dim = da->dim;
306d0892670SMatthew G. Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
307d0892670SMatthew G. Knepley   PetscErrorCode ierr;
308d0892670SMatthew G. Knepley 
309d0892670SMatthew G. Knepley   PetscFunctionBegin;
310d0892670SMatthew G. Knepley   *coneSize = 0;
311d0892670SMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
312d0892670SMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
313d0892670SMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
314d0892670SMatthew G. Knepley   switch (dim) {
315d0892670SMatthew G. Knepley   case 2:
316d0892670SMatthew G. Knepley     if (p >= 0) {
317d0892670SMatthew G. Knepley       if (p < nC) {
318d0892670SMatthew G. Knepley         *coneSize = 4;
319d0892670SMatthew G. Knepley       } else if (p < nC+nV) {
320d0892670SMatthew G. Knepley         *coneSize = 0;
321d0892670SMatthew G. Knepley       } else if (p < nC+nV+nXF+nYF+nZF) {
322d0892670SMatthew G. Knepley         *coneSize = 2;
323d0892670SMatthew G. Knepley       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
324d0892670SMatthew G. Knepley     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
325d0892670SMatthew G. Knepley     break;
326d0892670SMatthew G. Knepley   case 3:
327d0892670SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
328d0892670SMatthew G. Knepley     break;
329d0892670SMatthew G. Knepley   }
330d0892670SMatthew G. Knepley   PetscFunctionReturn(0);
331d0892670SMatthew G. Knepley }
332d0892670SMatthew G. Knepley 
333d0892670SMatthew G. Knepley #undef __FUNCT__
334d0892670SMatthew G. Knepley #define __FUNCT__ "DMDAGetCone"
335d0892670SMatthew G. Knepley PetscErrorCode DMDAGetCone(DM dm, PetscInt p, PetscInt *cone[])
336d0892670SMatthew G. Knepley {
337d0892670SMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
338d0892670SMatthew G. Knepley   const PetscInt dim = da->dim;
339d0892670SMatthew G. Knepley   PetscInt       nCx, nCy, nCz, nC, nVx, nVy, nVz, nV, nxF, nyF, nzF, nXF, nYF, nZF;
340d0892670SMatthew G. Knepley   PetscErrorCode ierr;
341d0892670SMatthew G. Knepley 
342d0892670SMatthew G. Knepley   PetscFunctionBegin;
343d0892670SMatthew G. Knepley   if (!cone) {ierr = DMGetWorkArray(dm, 6, PETSC_INT, cone);CHKERRQ(ierr);}
344d0892670SMatthew G. Knepley   ierr = DMDAGetNumCells(dm, &nCx, &nCy, &nCz, &nC);CHKERRQ(ierr);
345d0892670SMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
346d0892670SMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
347d0892670SMatthew G. Knepley   switch (dim) {
348d0892670SMatthew G. Knepley   case 2:
349d0892670SMatthew G. Knepley     if (p >= 0) {
350d0892670SMatthew G. Knepley       if (p < nC) {
351d0892670SMatthew G. Knepley         const PetscInt cy = p / nCx;
352d0892670SMatthew G. Knepley         const PetscInt cx = p % nCx;
353d0892670SMatthew G. Knepley 
354d0892670SMatthew G. Knepley         (*cone)[0] = cy*nxF + cx + nC+nV;
355d0892670SMatthew G. Knepley         (*cone)[1] = cx*nyF + cy + nyF + nC+nV+nXF;
356d0892670SMatthew G. Knepley         (*cone)[2] = cy*nxF + cx + nxF + nC+nV;
357d0892670SMatthew G. Knepley         (*cone)[3] = cx*nyF + cy + nC+nV+nXF;
358d0892670SMatthew G. Knepley         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do cell cones");
359d0892670SMatthew G. Knepley       } else if (p < nC+nV) {
360d0892670SMatthew G. Knepley       } else if (p < nC+nV+nXF) {
361d0892670SMatthew G. Knepley         const PetscInt fy = (p - nC+nV) / nxF;
362d0892670SMatthew G. Knepley         const PetscInt fx = (p - nC+nV) % nxF;
363d0892670SMatthew G. Knepley 
364d0892670SMatthew G. Knepley         (*cone)[0] = fy*nVx + fx + nC;
365d0892670SMatthew G. Knepley         (*cone)[1] = fy*nVx + fx + 1 + nC;
366d0892670SMatthew G. Knepley       } else if (p < nC+nV+nXF+nYF) {
367d0892670SMatthew G. Knepley         const PetscInt fx = (p - nC+nV+nXF) / nyF;
368d0892670SMatthew G. Knepley         const PetscInt fy = (p - nC+nV+nXF) % nyF;
369d0892670SMatthew G. Knepley 
370d0892670SMatthew G. Knepley         (*cone)[0] = fy*nVx + fx + nC;
371d0892670SMatthew G. Knepley         (*cone)[1] = fy*nVx + fx + nVx + nC;
372d0892670SMatthew G. Knepley       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
373d0892670SMatthew G. Knepley     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
374d0892670SMatthew G. Knepley     break;
375d0892670SMatthew G. Knepley   case 3:
376d0892670SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
377d0892670SMatthew G. Knepley     break;
378d0892670SMatthew G. Knepley   }
379d0892670SMatthew G. Knepley   PetscFunctionReturn(0);
380d0892670SMatthew G. Knepley }
381d0892670SMatthew G. Knepley 
382d0892670SMatthew G. Knepley #undef __FUNCT__
383d0892670SMatthew G. Knepley #define __FUNCT__ "DMDARestoreCone"
384d0892670SMatthew G. Knepley PetscErrorCode DMDARestoreCone(DM dm, PetscInt p, PetscInt *cone[])
385d0892670SMatthew G. Knepley {
386d0892670SMatthew G. Knepley   PetscErrorCode ierr;
387d0892670SMatthew G. Knepley 
388d0892670SMatthew G. Knepley   PetscFunctionBegin;
389d0892670SMatthew G. Knepley   ierr = DMGetWorkArray(dm, 6, PETSC_INT, cone);CHKERRQ(ierr);
390d0892670SMatthew G. Knepley   PetscFunctionReturn(0);
391d0892670SMatthew G. Knepley }
392d0892670SMatthew G. Knepley 
393d0892670SMatthew G. Knepley #undef __FUNCT__
394a66d4d66SMatthew G Knepley #define __FUNCT__ "DMDACreateSection"
395a66d4d66SMatthew G Knepley /*@C
396a66d4d66SMatthew G Knepley   DMDACreateSection - Create a PetscSection inside the DMDA that describes data layout. This allows multiple fields with
397a66d4d66SMatthew G Knepley   different numbers of dofs on vertices, cells, and faces in each direction.
398a66d4d66SMatthew G Knepley 
399a66d4d66SMatthew G Knepley   Input Parameters:
400a66d4d66SMatthew G Knepley + dm- The DMDA
401a66d4d66SMatthew G Knepley . numFields - The number of fields
402a4294c51SMatthew G. Knepley . numComp - The number of components in each field
403a4294c51SMatthew G. Knepley . numDof - The number of dofs per dimension for each field
4040298fd71SBarry Smith . numFaceDof - The number of dofs per face for each field and direction, or NULL
405a66d4d66SMatthew G Knepley 
406a66d4d66SMatthew G Knepley   Level: developer
407a66d4d66SMatthew G Knepley 
408a66d4d66SMatthew G Knepley   Note:
409a66d4d66SMatthew G Knepley   The default DMDA numbering is as follows:
410a66d4d66SMatthew G Knepley 
411a66d4d66SMatthew G Knepley     - Cells:    [0,             nC)
412a66d4d66SMatthew G Knepley     - Vertices: [nC,            nC+nV)
41388ed4aceSMatthew G Knepley     - X-Faces:  [nC+nV,         nC+nV+nXF)         normal is +- x-dir
41488ed4aceSMatthew G Knepley     - Y-Faces:  [nC+nV+nXF,     nC+nV+nXF+nYF)     normal is +- y-dir
41588ed4aceSMatthew G Knepley     - Z-Faces:  [nC+nV+nXF+nYF, nC+nV+nXF+nYF+nZF) normal is +- z-dir
416a66d4d66SMatthew G Knepley 
417a66d4d66SMatthew G Knepley   We interpret the default DMDA partition as a cell partition, and the data assignment as a cell assignment.
418a66d4d66SMatthew G Knepley @*/
419a4294c51SMatthew G. Knepley PetscErrorCode DMDACreateSection(DM dm, PetscInt numComp[], PetscInt numDof[], PetscInt numFaceDof[], PetscSection *s)
420a66d4d66SMatthew G Knepley {
421a66d4d66SMatthew G Knepley   DM_DA            *da  = (DM_DA*) dm->data;
422a4b60ecfSMatthew G. Knepley   PetscSection      section;
42388ed4aceSMatthew G Knepley   const PetscInt    dim = da->dim;
42480800b1aSMatthew G Knepley   PetscInt          numFields, numVertexTotDof = 0, numCellTotDof = 0, numFaceTotDof[3] = {0, 0, 0};
425b2fff234SMatthew G. Knepley   PetscBT           isLeaf;
42688ed4aceSMatthew G Knepley   PetscSF           sf;
427feafbc5cSMatthew G Knepley   PetscMPIInt       rank;
42888ed4aceSMatthew G Knepley   const PetscMPIInt *neighbors;
42988ed4aceSMatthew G Knepley   PetscInt          *localPoints;
43088ed4aceSMatthew G Knepley   PetscSFNode       *remotePoints;
431f5eeb527SMatthew G Knepley   PetscInt          nleaves = 0,  nleavesCheck = 0, nL = 0;
43257459e9aSMatthew G Knepley   PetscInt          nC, nVx, nVy, nVz, nV, nxF, nXF, nyF, nYF, nzF, nZF;
43357459e9aSMatthew G Knepley   PetscInt          pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart, zfEnd;
43488ed4aceSMatthew G Knepley   PetscInt          f, v, c, xf, yf, zf, xn, yn, zn;
435a66d4d66SMatthew G Knepley   PetscErrorCode    ierr;
436a66d4d66SMatthew G Knepley 
437a66d4d66SMatthew G Knepley   PetscFunctionBegin;
438a66d4d66SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
439e42e3c58SMatthew G. Knepley   PetscValidPointer(s, 4);
44082f516ccSBarry Smith   ierr    = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr);
441e42e3c58SMatthew G. Knepley   ierr    = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
44257459e9aSMatthew G Knepley   ierr    = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
44357459e9aSMatthew G Knepley   ierr    = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
44457459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);CHKERRQ(ierr);
44557459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);CHKERRQ(ierr);
44657459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);CHKERRQ(ierr);
44757459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr);
44857459e9aSMatthew G Knepley   xfStart = vEnd;  xfEnd = xfStart+nXF;
44957459e9aSMatthew G Knepley   yfStart = xfEnd; yfEnd = yfStart+nYF;
45057459e9aSMatthew G Knepley   zfStart = yfEnd; zfEnd = zfStart+nZF;
45182f516ccSBarry Smith   if (zfEnd != fEnd) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid face end %d, should be %d", zfEnd, fEnd);
45288ed4aceSMatthew G Knepley   /* Create local section */
45380800b1aSMatthew G Knepley   ierr = DMDAGetInfo(dm, 0,0,0,0,0,0,0, &numFields, 0,0,0,0,0);CHKERRQ(ierr);
454a66d4d66SMatthew G Knepley   for (f = 0; f < numFields; ++f) {
455a4294c51SMatthew G. Knepley     numVertexTotDof  += numDof[f*(dim+1)+0];
456a4294c51SMatthew G. Knepley     numCellTotDof    += numDof[f*(dim+1)+dim];
457a4294c51SMatthew G. Knepley     numFaceTotDof[0] += dim > 0 ? (numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]) : 0;
458a4294c51SMatthew G. Knepley     numFaceTotDof[1] += dim > 1 ? (numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]) : 0;
459a4294c51SMatthew G. Knepley     numFaceTotDof[2] += dim > 2 ? (numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]) : 0;
460a66d4d66SMatthew G Knepley   }
461a4b60ecfSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
462a4294c51SMatthew G. Knepley   if (numFields > 0) {
463a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetNumFields(section, numFields);CHKERRQ(ierr);
464a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
46580800b1aSMatthew G Knepley       const char *name;
46680800b1aSMatthew G Knepley 
46780800b1aSMatthew G Knepley       ierr = DMDAGetFieldName(dm, f, &name);CHKERRQ(ierr);
468a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldName(section, f, name ? name : "Field");CHKERRQ(ierr);
46980800b1aSMatthew G Knepley       if (numComp) {
470a4b60ecfSMatthew G. Knepley         ierr = PetscSectionSetFieldComponents(section, f, numComp[f]);CHKERRQ(ierr);
471a66d4d66SMatthew G Knepley       }
472a66d4d66SMatthew G Knepley     }
473a66d4d66SMatthew G Knepley   }
474a4b60ecfSMatthew G. Knepley   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
475a66d4d66SMatthew G Knepley   for (v = vStart; v < vEnd; ++v) {
476a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
477a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, v, f, numDof[f*(dim+1)+0]);CHKERRQ(ierr);
478a66d4d66SMatthew G Knepley     }
479a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, v, numVertexTotDof);CHKERRQ(ierr);
480a66d4d66SMatthew G Knepley   }
481a66d4d66SMatthew G Knepley   for (xf = xfStart; xf < xfEnd; ++xf) {
482a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
483a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, xf, f, numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
484a66d4d66SMatthew G Knepley     }
485a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, xf, numFaceTotDof[0]);CHKERRQ(ierr);
486a66d4d66SMatthew G Knepley   }
487a66d4d66SMatthew G Knepley   for (yf = yfStart; yf < yfEnd; ++yf) {
488a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
489a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, yf, f, numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
490a66d4d66SMatthew G Knepley     }
491a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, yf, numFaceTotDof[1]);CHKERRQ(ierr);
492a66d4d66SMatthew G Knepley   }
493a66d4d66SMatthew G Knepley   for (zf = zfStart; zf < zfEnd; ++zf) {
494a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
495a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, zf, f, numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
496a66d4d66SMatthew G Knepley     }
497a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, zf, numFaceTotDof[2]);CHKERRQ(ierr);
498a66d4d66SMatthew G Knepley   }
499a66d4d66SMatthew G Knepley   for (c = cStart; c < cEnd; ++c) {
500a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
501a4294c51SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, c, f, numDof[f*(dim+1)+dim]);CHKERRQ(ierr);
502a66d4d66SMatthew G Knepley     }
503a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, c, numCellTotDof);CHKERRQ(ierr);
504a66d4d66SMatthew G Knepley   }
505a4b60ecfSMatthew G. Knepley   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
50688ed4aceSMatthew G Knepley   /* Create mesh point SF */
507b2fff234SMatthew G. Knepley   ierr = PetscBTCreate(pEnd-pStart, &isLeaf);CHKERRQ(ierr);
50888ed4aceSMatthew G Knepley   ierr = DMDAGetNeighbors(dm, &neighbors);CHKERRQ(ierr);
50988ed4aceSMatthew G Knepley   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
51088ed4aceSMatthew G Knepley     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
51188ed4aceSMatthew G Knepley       for (xn = 0; xn < 3; ++xn) {
5127128ae9fSMatthew G Knepley         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
51388ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
514b2fff234SMatthew G. Knepley         PetscInt       xv, yv, zv;
51588ed4aceSMatthew G Knepley 
5163814d604SMatthew G Knepley         if (neighbor >= 0 && neighbor < rank) {
517b2fff234SMatthew G. Knepley           if (xp < 0) { /* left */
518b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
519b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
520b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
521b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
522b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
523b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
524b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
525b2fff234SMatthew G. Knepley               } else {
526b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
527b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
528b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
529b2fff234SMatthew G. Knepley                 }
530b2fff234SMatthew G. Knepley               }
531b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
532b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
533b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
534b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
535b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
536b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
537b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
538b2fff234SMatthew G. Knepley               } else {
539b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
540b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
541b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
542b2fff234SMatthew G. Knepley                 }
543b2fff234SMatthew G. Knepley               }
544b2fff234SMatthew G. Knepley             } else {
545b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
546b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
547b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
548b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
549b2fff234SMatthew G. Knepley                 }
550b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
551b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
552b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
553b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
554b2fff234SMatthew G. Knepley                 }
555b2fff234SMatthew G. Knepley               } else {
556b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
557b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
558b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
559b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
560b2fff234SMatthew G. Knepley                   }
561b2fff234SMatthew G. Knepley                 }
562b2fff234SMatthew G. Knepley #if 0
563b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
564b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
565b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
566b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
567b2fff234SMatthew G. Knepley                 }
568b2fff234SMatthew G. Knepley #endif
569b2fff234SMatthew G. Knepley               }
570b2fff234SMatthew G. Knepley             }
571b2fff234SMatthew G. Knepley           } else if (xp > 0) { /* right */
572b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
573b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
574b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
575b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
576b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
577b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
578b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
579b2fff234SMatthew G. Knepley               } else {
580b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
581b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
582b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
583b2fff234SMatthew G. Knepley                 }
584b2fff234SMatthew G. Knepley               }
585b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
586b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
587b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
588b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
589b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
590b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
591b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
592b2fff234SMatthew G. Knepley               } else {
593b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
594b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
595b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
596b2fff234SMatthew G. Knepley                 }
597b2fff234SMatthew G. Knepley               }
598b2fff234SMatthew G. Knepley             } else {
599b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
600b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
601b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
602b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
603b2fff234SMatthew G. Knepley                 }
604b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
605b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
606b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
607b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
608b2fff234SMatthew G. Knepley                 }
609b2fff234SMatthew G. Knepley               } else {
610b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
611b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
612b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
613b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
614b2fff234SMatthew G. Knepley                   }
615b2fff234SMatthew G. Knepley                 }
616b2fff234SMatthew G. Knepley #if 0
617b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
618b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
619b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
620b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
621b2fff234SMatthew G. Knepley                 }
622b2fff234SMatthew G. Knepley #endif
623b2fff234SMatthew G. Knepley               }
624b2fff234SMatthew G. Knepley             }
625b2fff234SMatthew G. Knepley           } else {
626b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
627b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
628b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
629b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
630b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
631b2fff234SMatthew G. Knepley                 }
632b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
633b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
634b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
635b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
636b2fff234SMatthew G. Knepley                 }
637b2fff234SMatthew G. Knepley               } else {
638b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
639b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
640b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
641b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
642b2fff234SMatthew G. Knepley                   }
643b2fff234SMatthew G. Knepley                 }
644b2fff234SMatthew G. Knepley #if 0
645b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
646b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
647b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
648b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
649b2fff234SMatthew G. Knepley                 }
650b2fff234SMatthew G. Knepley #endif
651b2fff234SMatthew G. Knepley               }
652b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
653b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
654b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
655b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
656b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
657b2fff234SMatthew G. Knepley                 }
658b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
659b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
660b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
661b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
662b2fff234SMatthew G. Knepley                 }
663b2fff234SMatthew G. Knepley               } else {
664b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
665b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
666b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
667b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
668b2fff234SMatthew G. Knepley                   }
669b2fff234SMatthew G. Knepley                 }
670b2fff234SMatthew G. Knepley #if 0
671b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
672b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
673b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
674b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
675b2fff234SMatthew G. Knepley                 }
676b2fff234SMatthew G. Knepley #endif
677b2fff234SMatthew G. Knepley               }
678b2fff234SMatthew G. Knepley             } else {
679b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
680b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
681b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
682b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
683b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
684b2fff234SMatthew G. Knepley                   }
685b2fff234SMatthew G. Knepley                 }
686b2fff234SMatthew G. Knepley #if 0
687b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
688b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
689b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
690b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
691b2fff234SMatthew G. Knepley                 }
692b2fff234SMatthew G. Knepley #endif
693b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
694b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
695b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
696b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
697b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
698b2fff234SMatthew G. Knepley                   }
699b2fff234SMatthew G. Knepley                 }
700b2fff234SMatthew G. Knepley #if 0
701b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
702b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
703b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
704b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
705b2fff234SMatthew G. Knepley                 }
706b2fff234SMatthew G. Knepley #endif
707b2fff234SMatthew G. Knepley               } else {
708b2fff234SMatthew G. Knepley                 /* Nothing is shared from the interior */
70988ed4aceSMatthew G Knepley               }
71088ed4aceSMatthew G Knepley             }
71188ed4aceSMatthew G Knepley           }
71288ed4aceSMatthew G Knepley         }
71388ed4aceSMatthew G Knepley       }
714b2fff234SMatthew G. Knepley     }
715b2fff234SMatthew G. Knepley   }
716b2fff234SMatthew G. Knepley   ierr = PetscBTMemzero(pEnd-pStart, isLeaf);CHKERRQ(ierr);
71788ed4aceSMatthew G Knepley   ierr = PetscMalloc2(nleaves,PetscInt,&localPoints,nleaves,PetscSFNode,&remotePoints);CHKERRQ(ierr);
71888ed4aceSMatthew G Knepley   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
71988ed4aceSMatthew G Knepley     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
72088ed4aceSMatthew G Knepley       for (xn = 0; xn < 3; ++xn) {
7217128ae9fSMatthew G Knepley         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
72288ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
723f5eeb527SMatthew G Knepley         PetscInt       xv, yv, zv;
72488ed4aceSMatthew G Knepley 
7253814d604SMatthew G Knepley         if (neighbor >= 0 && neighbor < rank) {
72688ed4aceSMatthew G Knepley           if (xp < 0) { /* left */
72788ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
72888ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
729b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
730f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
731f5eeb527SMatthew G Knepley 
732b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
733f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
734f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
735f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
736f5eeb527SMatthew G Knepley                   ++nL;
737b2fff234SMatthew G. Knepley                 }
73888ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
739b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
740f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
741f5eeb527SMatthew G Knepley 
742b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
743f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
744f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
745f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
746f5eeb527SMatthew G Knepley                   ++nL;
747b2fff234SMatthew G. Knepley                 }
74888ed4aceSMatthew G Knepley               } else {
749b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
750b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
751f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
752f5eeb527SMatthew G Knepley 
753b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
754f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
755f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
756f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
757b2fff234SMatthew G. Knepley                     ++nL;
758b2fff234SMatthew G. Knepley                   }
759f5eeb527SMatthew G Knepley                 }
76088ed4aceSMatthew G Knepley               }
76188ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
76288ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
763b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
764f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
765f5eeb527SMatthew G Knepley 
766b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
767f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
768f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
769f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
770f5eeb527SMatthew G Knepley                   ++nL;
771b2fff234SMatthew G. Knepley                 }
77288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
773b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
774f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
775f5eeb527SMatthew G Knepley 
776b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
777f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
778f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
779f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
780f5eeb527SMatthew G Knepley                   ++nL;
781b2fff234SMatthew G. Knepley                 }
78288ed4aceSMatthew G Knepley               } else {
783b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
784b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
785f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
786f5eeb527SMatthew G Knepley 
787b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
788f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
789f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
790f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
791b2fff234SMatthew G. Knepley                     ++nL;
792b2fff234SMatthew G. Knepley                   }
793f5eeb527SMatthew G Knepley                 }
79488ed4aceSMatthew G Knepley               }
79588ed4aceSMatthew G Knepley             } else {
79688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
797b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
798b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
799f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
800f5eeb527SMatthew G Knepley 
801b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
802f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
803f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
804f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
805b2fff234SMatthew G. Knepley                     ++nL;
806b2fff234SMatthew G. Knepley                   }
807f5eeb527SMatthew G Knepley                 }
80888ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
809b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
810b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
811f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
812f5eeb527SMatthew G Knepley 
813b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
814f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
815f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
816f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
817b2fff234SMatthew G. Knepley                     ++nL;
818b2fff234SMatthew G. Knepley                   }
819f5eeb527SMatthew G Knepley                 }
82088ed4aceSMatthew G Knepley               } else {
821f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
822b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
823b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
824f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
825f5eeb527SMatthew G Knepley 
826b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
827f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
828f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
829f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
830b2fff234SMatthew G. Knepley                       ++nL;
831f5eeb527SMatthew G Knepley                     }
832f5eeb527SMatthew G Knepley                   }
833b2fff234SMatthew G. Knepley                 }
834b2fff234SMatthew G. Knepley #if 0
835b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
836f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
837b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
838f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
839f5eeb527SMatthew G Knepley 
840b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
841f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
842f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
843f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
844f5eeb527SMatthew G Knepley                   }
84588ed4aceSMatthew G Knepley                 }
846b2fff234SMatthew G. Knepley #endif
847b2fff234SMatthew G. Knepley               }
84888ed4aceSMatthew G Knepley             }
84988ed4aceSMatthew G Knepley           } else if (xp > 0) { /* right */
85088ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
85188ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
852b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
853f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
854f5eeb527SMatthew G Knepley 
855b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
856f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
857f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
858f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
859f5eeb527SMatthew G Knepley                   ++nL;
860b2fff234SMatthew G. Knepley                 }
86188ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
862b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
863f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
864f5eeb527SMatthew G Knepley 
865b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
866f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
867f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
868f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
869f5eeb527SMatthew G Knepley                   ++nL;
870b2fff234SMatthew G. Knepley                 }
87188ed4aceSMatthew G Knepley               } else {
872b2fff234SMatthew G. Knepley                 nleavesCheck += nVz;
873b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
874b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
875f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
876f5eeb527SMatthew G Knepley 
877b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
878f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
879f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
880f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
881b2fff234SMatthew G. Knepley                     ++nL;
882b2fff234SMatthew G. Knepley                   }
883f5eeb527SMatthew G Knepley                 }
88488ed4aceSMatthew G Knepley               }
88588ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
88688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
887b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
888f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
889f5eeb527SMatthew G Knepley 
890b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
891f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
892f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
893f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
894f5eeb527SMatthew G Knepley                   ++nL;
895b2fff234SMatthew G. Knepley                 }
89688ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
897b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
898f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
899f5eeb527SMatthew G Knepley 
900b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
901f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
902f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
903f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
904f5eeb527SMatthew G Knepley                   ++nL;
905b2fff234SMatthew G. Knepley                 }
90688ed4aceSMatthew G Knepley               } else {
907b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
908b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
909f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
910f5eeb527SMatthew G Knepley 
911b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
912f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
913f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
914f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
915b2fff234SMatthew G. Knepley                     ++nL;
916b2fff234SMatthew G. Knepley                   }
917f5eeb527SMatthew G Knepley                 }
91888ed4aceSMatthew G Knepley               }
91988ed4aceSMatthew G Knepley             } else {
92088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
921b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
922b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
923f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
924f5eeb527SMatthew G Knepley 
925b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
926f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
927f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
928f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
929b2fff234SMatthew G. Knepley                     ++nL;
930b2fff234SMatthew G. Knepley                   }
931f5eeb527SMatthew G Knepley                 }
93288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
933b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
934b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
935f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
936f5eeb527SMatthew G Knepley 
937b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
938f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
939f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
940f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
941b2fff234SMatthew G. Knepley                     ++nL;
942b2fff234SMatthew G. Knepley                   }
943f5eeb527SMatthew G Knepley                 }
94488ed4aceSMatthew G Knepley               } else {
945f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
946b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
947b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
948f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + 0     + nC; /* TODO: Correct this for neighbor sizes */
949f5eeb527SMatthew G Knepley 
950b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
951f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
952f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
953f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
954b2fff234SMatthew G. Knepley                       ++nL;
955f5eeb527SMatthew G Knepley                     }
956f5eeb527SMatthew G Knepley                   }
957b2fff234SMatthew G. Knepley                 }
958b2fff234SMatthew G. Knepley #if 0
959b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
960f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
961b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
962f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
963f5eeb527SMatthew G Knepley 
964b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
965f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
966f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
967f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
968b2fff234SMatthew G. Knepley                     ++nL;
969f5eeb527SMatthew G Knepley                   }
97088ed4aceSMatthew G Knepley                 }
971b2fff234SMatthew G. Knepley #endif
972b2fff234SMatthew G. Knepley               }
97388ed4aceSMatthew G Knepley             }
97488ed4aceSMatthew G Knepley           } else {
97588ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
97688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
977b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
978b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
979f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
980f5eeb527SMatthew G Knepley 
981b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
982f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
983f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
984f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
985b2fff234SMatthew G. Knepley                     ++nL;
986b2fff234SMatthew G. Knepley                   }
987f5eeb527SMatthew G Knepley                 }
98888ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
989b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
990b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
991f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
992f5eeb527SMatthew G Knepley 
993b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
994f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
995f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
996f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
997b2fff234SMatthew G. Knepley                     ++nL;
998b2fff234SMatthew G. Knepley                   }
999f5eeb527SMatthew G Knepley                 }
100088ed4aceSMatthew G Knepley               } else {
1001f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
1002b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1003b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
1004f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1005f5eeb527SMatthew G Knepley 
1006b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1007f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1008f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1009f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1010b2fff234SMatthew G. Knepley                       ++nL;
1011f5eeb527SMatthew G Knepley                     }
1012f5eeb527SMatthew G Knepley                   }
1013b2fff234SMatthew G. Knepley                 }
1014b2fff234SMatthew G. Knepley #if 0
1015b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
1016f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1017b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
1018f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1019f5eeb527SMatthew G Knepley 
1020b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1021f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1022f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1023f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1024b2fff234SMatthew G. Knepley                     ++nL;
1025f5eeb527SMatthew G Knepley                   }
102688ed4aceSMatthew G Knepley                 }
1027b2fff234SMatthew G. Knepley #endif
1028b2fff234SMatthew G. Knepley               }
102988ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
103088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
1031b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
1032b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
1033f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1034f5eeb527SMatthew G Knepley 
1035b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1036f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
1037f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1038f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
1039b2fff234SMatthew G. Knepley                     ++nL;
1040b2fff234SMatthew G. Knepley                   }
1041f5eeb527SMatthew G Knepley                 }
104288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
1043b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
1044b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
1045f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1046f5eeb527SMatthew G Knepley 
1047b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1048f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
1049f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1050f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
1051b2fff234SMatthew G. Knepley                     ++nL;
1052b2fff234SMatthew G. Knepley                   }
1053f5eeb527SMatthew G Knepley                 }
105488ed4aceSMatthew G Knepley               } else {
1055f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
1056b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1057b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
1058f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1059f5eeb527SMatthew G Knepley 
1060b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1061f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1062f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1063f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1064b2fff234SMatthew G. Knepley                       ++nL;
1065f5eeb527SMatthew G Knepley                     }
1066f5eeb527SMatthew G Knepley                   }
1067b2fff234SMatthew G. Knepley                 }
1068b2fff234SMatthew G. Knepley #if 0
1069b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
1070f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1071b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
1072f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1073f5eeb527SMatthew G Knepley 
1074b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1075f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1076f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1077f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1078b2fff234SMatthew G. Knepley                     ++nL;
1079f5eeb527SMatthew G Knepley                   }
108088ed4aceSMatthew G Knepley                 }
1081b2fff234SMatthew G. Knepley #endif
1082b2fff234SMatthew G. Knepley               }
108388ed4aceSMatthew G Knepley             } else {
108488ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
1085f5eeb527SMatthew G Knepley                 for (yv = 0; yv < nVy; ++yv) {
1086b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1087b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
1088f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1089f5eeb527SMatthew G Knepley 
1090b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1091f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1092f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1093f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1094b2fff234SMatthew G. Knepley                       ++nL;
1095f5eeb527SMatthew G Knepley                     }
1096f5eeb527SMatthew G Knepley                   }
1097b2fff234SMatthew G. Knepley                 }
1098b2fff234SMatthew G. Knepley #if 0
1099b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
1100f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1101b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
1102f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1103f5eeb527SMatthew G Knepley 
1104b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1105f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1106f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1107f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1108b2fff234SMatthew G. Knepley                     ++nL;
1109f5eeb527SMatthew G Knepley                   }
1110b2fff234SMatthew G. Knepley                 }
1111b2fff234SMatthew G. Knepley #endif
111288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
1113f5eeb527SMatthew G Knepley                 for (yv = 0; yv < nVy; ++yv) {
1114b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1115b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
1116f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (      0*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1117f5eeb527SMatthew G Knepley 
1118b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1119f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1120f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1121f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1122b2fff234SMatthew G. Knepley                       ++nL;
1123f5eeb527SMatthew G Knepley                     }
1124f5eeb527SMatthew G Knepley                   }
1125b2fff234SMatthew G. Knepley                 }
1126b2fff234SMatthew G. Knepley #if 0
1127b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
1128f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1129b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
1130f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1131f5eeb527SMatthew G Knepley 
1132b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1133f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1134f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1135f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1136b2fff234SMatthew G. Knepley                     ++nL;
1137f5eeb527SMatthew G Knepley                   }
1138b2fff234SMatthew G. Knepley                 }
1139b2fff234SMatthew G. Knepley #endif
114088ed4aceSMatthew G Knepley               } else {
114188ed4aceSMatthew G Knepley                 /* Nothing is shared from the interior */
114288ed4aceSMatthew G Knepley               }
114388ed4aceSMatthew G Knepley             }
114488ed4aceSMatthew G Knepley           }
114588ed4aceSMatthew G Knepley         }
114688ed4aceSMatthew G Knepley       }
114788ed4aceSMatthew G Knepley     }
114888ed4aceSMatthew G Knepley   }
1149b2fff234SMatthew G. Knepley   ierr = PetscBTDestroy(&isLeaf);CHKERRQ(ierr);
1150b2fff234SMatthew G. Knepley   /* Remove duplication in leaf determination */
1151b2fff234SMatthew G. Knepley   if (nleaves != nL) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "The number of leaves %d did not match the number of remote leaves %d", nleaves, nleavesCheck);
115282f516ccSBarry Smith   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf);CHKERRQ(ierr);
115388ed4aceSMatthew G Knepley   ierr = PetscSFSetGraph(sf, pEnd, nleaves, localPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
1154a4b60ecfSMatthew G. Knepley   ierr = DMSetPointSF(dm, sf);CHKERRQ(ierr);
115588ed4aceSMatthew G Knepley   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1156a4294c51SMatthew G. Knepley   *s = section;
1157a4294c51SMatthew G. Knepley   PetscFunctionReturn(0);
1158a4294c51SMatthew G. Knepley }
1159a4294c51SMatthew G. Knepley 
1160d0892670SMatthew G. Knepley #undef __FUNCT__
1161d0892670SMatthew G. Knepley #define __FUNCT__ "DMDASetVertexCoordinates"
1162d0892670SMatthew G. Knepley PetscErrorCode DMDASetVertexCoordinates(DM dm, PetscReal xl, PetscReal xu, PetscReal yl, PetscReal yu, PetscReal zl, PetscReal zu)
1163d0892670SMatthew G. Knepley {
1164d0892670SMatthew G. Knepley   DM_DA         *da = (DM_DA *) dm->data;
1165d0892670SMatthew G. Knepley   Vec            coordinates;
1166d0892670SMatthew G. Knepley   PetscSection   section;
1167d0892670SMatthew G. Knepley   PetscScalar   *coords;
1168d0892670SMatthew G. Knepley   PetscReal      h[3];
1169d0892670SMatthew G. Knepley   PetscInt       dim, size, M, N, P, nVx, nVy, nVz, nV, vStart, vEnd, v, i, j, k;
1170d0892670SMatthew G. Knepley   PetscErrorCode ierr;
1171d0892670SMatthew G. Knepley 
1172d0892670SMatthew G. Knepley   PetscFunctionBegin;
1173d0892670SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1174d0892670SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
1175d0892670SMatthew G. Knepley   h[0] = (xu - xl)/M;
1176d0892670SMatthew G. Knepley   h[1] = (yu - yl)/N;
1177d0892670SMatthew G. Knepley   h[2] = (zu - zl)/P;
1178d0892670SMatthew G. Knepley   ierr = DMDAGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1179d0892670SMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
1180d0892670SMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
1181d0892670SMatthew G. Knepley   ierr = PetscSectionSetNumFields(section, 1);CHKERRQ(ierr);
1182d0892670SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(section, 0, dim);CHKERRQ(ierr);
1183d0892670SMatthew G. Knepley   ierr = PetscSectionSetChart(section, vStart, vEnd);CHKERRQ(ierr);
1184d0892670SMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
1185d0892670SMatthew G. Knepley     ierr = PetscSectionSetDof(section, v, dim);CHKERRQ(ierr);
1186d0892670SMatthew G. Knepley   }
1187d0892670SMatthew G. Knepley   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
1188d0892670SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
1189d0892670SMatthew G. Knepley   ierr = VecCreateSeq(PETSC_COMM_SELF, size, &coordinates);CHKERRQ(ierr);
1190d0892670SMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
1191d0892670SMatthew G. Knepley   for (k = 0; k < nVz; ++k) {
1192d0892670SMatthew G. Knepley     PetscInt ind[3] = {0, 0, k + da->zs}, d, off;
1193d0892670SMatthew G. Knepley 
1194d0892670SMatthew G. Knepley     for (j = 0; j < nVy; ++j) {
1195d0892670SMatthew G. Knepley       ind[1] = j + da->ys;
1196d0892670SMatthew G. Knepley       for (i = 0; i < nVx; ++i) {
1197d0892670SMatthew G. Knepley         const PetscInt vertex = (k*nVy + j)*nVx + i + vStart;
1198d0892670SMatthew G. Knepley 
1199d0892670SMatthew G. Knepley         ierr = PetscSectionGetOffset(section, vertex, &off);CHKERRQ(ierr);
1200d0892670SMatthew G. Knepley         ind[0] = i + da->xs;
1201d0892670SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
1202d0892670SMatthew G. Knepley           coords[off+d] = h[d]*ind[d];
1203d0892670SMatthew G. Knepley         }
1204d0892670SMatthew G. Knepley       }
1205d0892670SMatthew G. Knepley     }
1206d0892670SMatthew G. Knepley   }
1207d0892670SMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
1208d0892670SMatthew G. Knepley   ierr = DMSetCoordinateSection(dm, section);CHKERRQ(ierr);
1209d0892670SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr);
1210a4b60ecfSMatthew G. Knepley   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
1211d0892670SMatthew G. Knepley   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
1212d0892670SMatthew G. Knepley   PetscFunctionReturn(0);
1213d0892670SMatthew G. Knepley }
121437b16e26SMatthew G. Knepley 
121537b16e26SMatthew G. Knepley #undef __FUNCT__
121637b16e26SMatthew G. Knepley #define __FUNCT__ "DMDAProjectFunctionLocal"
121737b16e26SMatthew G. Knepley PetscErrorCode DMDAProjectFunctionLocal(DM dm, PetscFE fe[], void (**funcs)(const PetscReal [], PetscScalar *), InsertMode mode, Vec localX)
121837b16e26SMatthew G. Knepley {
121937b16e26SMatthew G. Knepley   PetscDualSpace *sp;
122037b16e26SMatthew G. Knepley   PetscQuadrature q;
122137b16e26SMatthew G. Knepley   PetscSection    section;
122237b16e26SMatthew G. Knepley   PetscScalar    *values;
122337b16e26SMatthew G. Knepley   PetscReal      *v0, *J, *detJ;
122437b16e26SMatthew G. Knepley   PetscInt        numFields, numComp, dim, spDim, totDim = 0, numValues, cStart, cEnd, f, c, v, d;
122537b16e26SMatthew G. Knepley   PetscErrorCode  ierr;
122637b16e26SMatthew G. Knepley 
122737b16e26SMatthew G. Knepley   PetscFunctionBegin;
122837b16e26SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
122937b16e26SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe[0], &q);CHKERRQ(ierr);
123037b16e26SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
123137b16e26SMatthew G. Knepley   ierr = PetscMalloc(numFields * sizeof(PetscDualSpace), &sp);CHKERRQ(ierr);
123237b16e26SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
123337b16e26SMatthew G. Knepley     ierr = PetscFEGetDualSpace(fe[f], &sp[f]);CHKERRQ(ierr);
123437b16e26SMatthew G. Knepley     ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr);
123537b16e26SMatthew G. Knepley     ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr);
123637b16e26SMatthew G. Knepley     totDim += spDim*numComp;
123737b16e26SMatthew G. Knepley   }
123837b16e26SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
123937b16e26SMatthew G. Knepley   ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
124037b16e26SMatthew G. Knepley   ierr = DMDAVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr);
124137b16e26SMatthew G. Knepley   if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section cell closure size %d != dual space dimension %d", numValues, totDim);
124237b16e26SMatthew G. Knepley   ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr);
124337b16e26SMatthew G. Knepley   ierr = PetscMalloc3(dim*q.numPoints,PetscReal,&v0,dim*dim*q.numPoints,PetscReal,&J,q.numPoints,PetscReal,&detJ);CHKERRQ(ierr);
124437b16e26SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
124537b16e26SMatthew G. Knepley     PetscCellGeometry geom;
124637b16e26SMatthew G. Knepley 
124737b16e26SMatthew G. Knepley     ierr = DMDAComputeCellGeometry(dm, c, &q, v0, J, NULL, detJ);CHKERRQ(ierr);
124837b16e26SMatthew G. Knepley     geom.v0   = v0;
124937b16e26SMatthew G. Knepley     geom.J    = J;
125037b16e26SMatthew G. Knepley     geom.detJ = detJ;
125137b16e26SMatthew G. Knepley     for (f = 0, v = 0; f < numFields; ++f) {
125237b16e26SMatthew G. Knepley       ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr);
125337b16e26SMatthew G. Knepley       ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr);
125437b16e26SMatthew G. Knepley       for (d = 0; d < spDim; ++d) {
125537b16e26SMatthew G. Knepley         ierr = PetscDualSpaceApply(sp[f], d, geom, numComp, funcs[f], &values[v]);CHKERRQ(ierr);
125637b16e26SMatthew G. Knepley         v += numComp;
125737b16e26SMatthew G. Knepley       }
125837b16e26SMatthew G. Knepley     }
125937b16e26SMatthew G. Knepley     ierr = DMDAVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr);
126037b16e26SMatthew G. Knepley   }
126137b16e26SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr);
126237b16e26SMatthew G. Knepley   ierr = PetscFree3(v0,J,detJ);CHKERRQ(ierr);
126337b16e26SMatthew G. Knepley   ierr = PetscFree(sp);CHKERRQ(ierr);
126437b16e26SMatthew G. Knepley   PetscFunctionReturn(0);
126537b16e26SMatthew G. Knepley }
126637b16e26SMatthew G. Knepley 
126737b16e26SMatthew G. Knepley #undef __FUNCT__
126837b16e26SMatthew G. Knepley #define __FUNCT__ "DMDAProjectFunction"
126937b16e26SMatthew G. Knepley /*@C
127037b16e26SMatthew G. Knepley   DMDAProjectFunction - This projects the given function into the function space provided.
127137b16e26SMatthew G. Knepley 
127237b16e26SMatthew G. Knepley   Input Parameters:
127337b16e26SMatthew G. Knepley + dm      - The DM
127437b16e26SMatthew G. Knepley . fe      - The PetscFE associated with the field
127537b16e26SMatthew G. Knepley . funcs   - The coordinate functions to evaluate
127637b16e26SMatthew G. Knepley - mode    - The insertion mode for values
127737b16e26SMatthew G. Knepley 
127837b16e26SMatthew G. Knepley   Output Parameter:
127937b16e26SMatthew G. Knepley . X - vector
128037b16e26SMatthew G. Knepley 
128137b16e26SMatthew G. Knepley   Level: developer
128237b16e26SMatthew G. Knepley 
128337b16e26SMatthew G. Knepley .seealso: DMDAComputeL2Diff()
128437b16e26SMatthew G. Knepley @*/
128537b16e26SMatthew G. Knepley PetscErrorCode DMDAProjectFunction(DM dm, PetscFE fe[], void (**funcs)(const PetscReal [], PetscScalar *), InsertMode mode, Vec X)
128637b16e26SMatthew G. Knepley {
128737b16e26SMatthew G. Knepley   Vec            localX;
128837b16e26SMatthew G. Knepley   PetscErrorCode ierr;
128937b16e26SMatthew G. Knepley 
129037b16e26SMatthew G. Knepley   PetscFunctionBegin;
129137b16e26SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
129237b16e26SMatthew G. Knepley   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
129337b16e26SMatthew G. Knepley   ierr = DMDAProjectFunctionLocal(dm, fe, funcs, mode, localX);CHKERRQ(ierr);
129437b16e26SMatthew G. Knepley   ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
129537b16e26SMatthew G. Knepley   ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
129637b16e26SMatthew G. Knepley   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
129737b16e26SMatthew G. Knepley   PetscFunctionReturn(0);
129837b16e26SMatthew G. Knepley }
129937b16e26SMatthew G. Knepley 
130037b16e26SMatthew G. Knepley #undef __FUNCT__
130137b16e26SMatthew G. Knepley #define __FUNCT__ "DMDAComputeL2Diff"
130237b16e26SMatthew G. Knepley /*@C
130337b16e26SMatthew G. Knepley   DMDAComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
130437b16e26SMatthew G. Knepley 
130537b16e26SMatthew G. Knepley   Input Parameters:
130637b16e26SMatthew G. Knepley + dm    - The DM
130737b16e26SMatthew G. Knepley . fe    - The PetscFE object for each field
130837b16e26SMatthew G. Knepley . funcs - The functions to evaluate for each field component
130937b16e26SMatthew G. Knepley - X     - The coefficient vector u_h
131037b16e26SMatthew G. Knepley 
131137b16e26SMatthew G. Knepley   Output Parameter:
131237b16e26SMatthew G. Knepley . diff - The diff ||u - u_h||_2
131337b16e26SMatthew G. Knepley 
131437b16e26SMatthew G. Knepley   Level: developer
131537b16e26SMatthew G. Knepley 
131637b16e26SMatthew G. Knepley .seealso: DMDAProjectFunction()
131737b16e26SMatthew G. Knepley @*/
131837b16e26SMatthew G. Knepley PetscErrorCode DMDAComputeL2Diff(DM dm, PetscFE fe[], void (**funcs)(const PetscReal [], PetscScalar *), Vec X, PetscReal *diff)
131937b16e26SMatthew G. Knepley {
132037b16e26SMatthew G. Knepley   const PetscInt  debug = 0;
132137b16e26SMatthew G. Knepley   PetscSection    section;
132237b16e26SMatthew G. Knepley   PetscQuadrature quad;
132337b16e26SMatthew G. Knepley   Vec             localX;
132437b16e26SMatthew G. Knepley   PetscScalar    *funcVal;
132537b16e26SMatthew G. Knepley   PetscReal      *coords, *v0, *J, *invJ, detJ;
132637b16e26SMatthew G. Knepley   PetscReal       localDiff = 0.0;
132737b16e26SMatthew G. Knepley   PetscInt        dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp;
132837b16e26SMatthew G. Knepley   PetscErrorCode  ierr;
132937b16e26SMatthew G. Knepley 
133037b16e26SMatthew G. Knepley   PetscFunctionBegin;
133137b16e26SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
133237b16e26SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
133337b16e26SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
133437b16e26SMatthew G. Knepley   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
133537b16e26SMatthew G. Knepley   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
133637b16e26SMatthew G. Knepley   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
133737b16e26SMatthew G. Knepley   for (field = 0; field < numFields; ++field) {
133837b16e26SMatthew G. Knepley     PetscInt Nc;
133937b16e26SMatthew G. Knepley 
134037b16e26SMatthew G. Knepley     ierr = PetscFEGetNumComponents(fe[field], &Nc);CHKERRQ(ierr);
134137b16e26SMatthew G. Knepley     numComponents += Nc;
134237b16e26SMatthew G. Knepley   }
134337b16e26SMatthew G. Knepley   /* There are no BC values in DAs right now: ierr = DMDAProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */
134437b16e26SMatthew G. Knepley   ierr = PetscMalloc5(numComponents,PetscScalar,&funcVal,dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr);
134537b16e26SMatthew G. Knepley   ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
134637b16e26SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe[0], &quad);CHKERRQ(ierr);
134737b16e26SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1348df66330eSJed Brown     const PetscScalar *x = NULL;
134937b16e26SMatthew G. Knepley     PetscReal    elemDiff = 0.0;
135037b16e26SMatthew G. Knepley 
135137b16e26SMatthew G. Knepley     ierr = DMDAComputeCellGeometry(dm, c, &quad, v0, J, invJ, &detJ);CHKERRQ(ierr);
135237b16e26SMatthew G. Knepley     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
135337b16e26SMatthew G. Knepley     ierr = DMDAVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
135437b16e26SMatthew G. Knepley 
135537b16e26SMatthew G. Knepley     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
135637b16e26SMatthew G. Knepley       const PetscInt   numQuadPoints = quad.numPoints;
135737b16e26SMatthew G. Knepley       const PetscReal *quadPoints    = quad.points;
135837b16e26SMatthew G. Knepley       const PetscReal *quadWeights   = quad.weights;
135937b16e26SMatthew G. Knepley       PetscReal       *basis;
136037b16e26SMatthew G. Knepley       PetscInt         numBasisFuncs, numBasisComps, q, d, e, fc, f;
136137b16e26SMatthew G. Knepley 
136237b16e26SMatthew G. Knepley       ierr = PetscFEGetDimension(fe[field], &numBasisFuncs);CHKERRQ(ierr);
136337b16e26SMatthew G. Knepley       ierr = PetscFEGetNumComponents(fe[field], &numBasisComps);CHKERRQ(ierr);
136437b16e26SMatthew G. Knepley       ierr = PetscFEGetDefaultTabulation(fe[field], &basis, NULL, NULL);CHKERRQ(ierr);
136537b16e26SMatthew G. Knepley       if (debug) {
136637b16e26SMatthew G. Knepley         char title[1024];
136737b16e26SMatthew G. Knepley         ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr);
136837b16e26SMatthew G. Knepley         ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr);
136937b16e26SMatthew G. Knepley       }
137037b16e26SMatthew G. Knepley       for (q = 0; q < numQuadPoints; ++q) {
137137b16e26SMatthew G. Knepley         for (d = 0; d < dim; d++) {
137237b16e26SMatthew G. Knepley           coords[d] = v0[d];
137337b16e26SMatthew G. Knepley           for (e = 0; e < dim; e++) {
137437b16e26SMatthew G. Knepley             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
137537b16e26SMatthew G. Knepley           }
137637b16e26SMatthew G. Knepley         }
137737b16e26SMatthew G. Knepley         (*funcs[field])(coords, funcVal);
137837b16e26SMatthew G. Knepley         for (fc = 0; fc < numBasisComps; ++fc) {
137937b16e26SMatthew G. Knepley           PetscScalar interpolant = 0.0;
138037b16e26SMatthew G. Knepley 
138137b16e26SMatthew G. Knepley           for (f = 0; f < numBasisFuncs; ++f) {
138237b16e26SMatthew G. Knepley             const PetscInt fidx = f*numBasisComps+fc;
138337b16e26SMatthew G. Knepley             interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx];
138437b16e26SMatthew G. Knepley           }
138537b16e26SMatthew G. Knepley           if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "    elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);}
138637b16e26SMatthew G. Knepley           elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ;
138737b16e26SMatthew G. Knepley         }
138837b16e26SMatthew G. Knepley       }
138937b16e26SMatthew G. Knepley       comp        += numBasisComps;
139037b16e26SMatthew G. Knepley       fieldOffset += numBasisFuncs*numBasisComps;
139137b16e26SMatthew G. Knepley     }
139237b16e26SMatthew G. Knepley     ierr = DMDAVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
139337b16e26SMatthew G. Knepley     if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);}
139437b16e26SMatthew G. Knepley     localDiff += elemDiff;
139537b16e26SMatthew G. Knepley   }
139637b16e26SMatthew G. Knepley   ierr  = PetscFree5(funcVal,coords,v0,J,invJ);CHKERRQ(ierr);
139737b16e26SMatthew G. Knepley   ierr  = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
139837b16e26SMatthew G. Knepley   ierr  = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
139937b16e26SMatthew G. Knepley   *diff = PetscSqrtReal(*diff);
1400a66d4d66SMatthew G Knepley   PetscFunctionReturn(0);
1401a66d4d66SMatthew G Knepley }
1402a66d4d66SMatthew G Knepley 
140347c6ae99SBarry Smith /* ------------------------------------------------------------------- */
140447c6ae99SBarry Smith 
140547c6ae99SBarry Smith #undef __FUNCT__
1406aa219208SBarry Smith #define __FUNCT__ "DMDAGetArray"
140747c6ae99SBarry Smith /*@C
1408aa219208SBarry Smith      DMDAGetArray - Gets a work array for a DMDA
140947c6ae99SBarry Smith 
141047c6ae99SBarry Smith     Input Parameter:
141147c6ae99SBarry Smith +    da - information about my local patch
141247c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch
141347c6ae99SBarry Smith 
141447c6ae99SBarry Smith     Output Parameters:
141547c6ae99SBarry Smith .    vptr - array data structured
141647c6ae99SBarry Smith 
141747c6ae99SBarry Smith     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
141847c6ae99SBarry Smith            to zero them.
141947c6ae99SBarry Smith 
142047c6ae99SBarry Smith   Level: advanced
142147c6ae99SBarry Smith 
1422bcaeba4dSBarry Smith .seealso: DMDARestoreArray()
142347c6ae99SBarry Smith 
142447c6ae99SBarry Smith @*/
14257087cfbeSBarry Smith PetscErrorCode  DMDAGetArray(DM da,PetscBool ghosted,void *vptr)
142647c6ae99SBarry Smith {
142747c6ae99SBarry Smith   PetscErrorCode ierr;
142847c6ae99SBarry Smith   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
142947c6ae99SBarry Smith   char           *iarray_start;
143047c6ae99SBarry Smith   void           **iptr = (void**)vptr;
143147c6ae99SBarry Smith   DM_DA          *dd    = (DM_DA*)da->data;
143247c6ae99SBarry Smith 
143347c6ae99SBarry Smith   PetscFunctionBegin;
143447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
143547c6ae99SBarry Smith   if (ghosted) {
1436aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
143747c6ae99SBarry Smith       if (dd->arrayghostedin[i]) {
143847c6ae99SBarry Smith         *iptr                 = dd->arrayghostedin[i];
143947c6ae99SBarry Smith         iarray_start          = (char*)dd->startghostedin[i];
14400298fd71SBarry Smith         dd->arrayghostedin[i] = NULL;
14410298fd71SBarry Smith         dd->startghostedin[i] = NULL;
144247c6ae99SBarry Smith 
144347c6ae99SBarry Smith         goto done;
144447c6ae99SBarry Smith       }
144547c6ae99SBarry Smith     }
144647c6ae99SBarry Smith     xs = dd->Xs;
144747c6ae99SBarry Smith     ys = dd->Ys;
144847c6ae99SBarry Smith     zs = dd->Zs;
144947c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
145047c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
145147c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
145247c6ae99SBarry Smith   } else {
1453aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
145447c6ae99SBarry Smith       if (dd->arrayin[i]) {
145547c6ae99SBarry Smith         *iptr          = dd->arrayin[i];
145647c6ae99SBarry Smith         iarray_start   = (char*)dd->startin[i];
14570298fd71SBarry Smith         dd->arrayin[i] = NULL;
14580298fd71SBarry Smith         dd->startin[i] = NULL;
145947c6ae99SBarry Smith 
146047c6ae99SBarry Smith         goto done;
146147c6ae99SBarry Smith       }
146247c6ae99SBarry Smith     }
146347c6ae99SBarry Smith     xs = dd->xs;
146447c6ae99SBarry Smith     ys = dd->ys;
146547c6ae99SBarry Smith     zs = dd->zs;
146647c6ae99SBarry Smith     xm = dd->xe-dd->xs;
146747c6ae99SBarry Smith     ym = dd->ye-dd->ys;
146847c6ae99SBarry Smith     zm = dd->ze-dd->zs;
146947c6ae99SBarry Smith   }
147047c6ae99SBarry Smith 
147147c6ae99SBarry Smith   switch (dd->dim) {
147247c6ae99SBarry Smith   case 1: {
147347c6ae99SBarry Smith     void *ptr;
147447c6ae99SBarry Smith 
147547c6ae99SBarry Smith     ierr = PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
147647c6ae99SBarry Smith 
147747c6ae99SBarry Smith     ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
147847c6ae99SBarry Smith     *iptr = (void*)ptr;
14798865f1eaSKarl Rupp     break;
14808865f1eaSKarl Rupp   }
148147c6ae99SBarry Smith   case 2: {
148247c6ae99SBarry Smith     void **ptr;
148347c6ae99SBarry Smith 
148447c6ae99SBarry Smith     ierr = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
148547c6ae99SBarry Smith 
148647c6ae99SBarry Smith     ptr = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
14878865f1eaSKarl Rupp     for (j=ys; j<ys+ym; j++) ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
148847c6ae99SBarry Smith     *iptr = (void*)ptr;
14898865f1eaSKarl Rupp     break;
14908865f1eaSKarl Rupp   }
149147c6ae99SBarry Smith   case 3: {
149247c6ae99SBarry Smith     void ***ptr,**bptr;
149347c6ae99SBarry Smith 
149447c6ae99SBarry Smith     ierr = PetscMalloc((zm+1)*sizeof(void**)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
149547c6ae99SBarry Smith 
149647c6ae99SBarry Smith     ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
149747c6ae99SBarry Smith     bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
14988865f1eaSKarl Rupp     for (i=zs; i<zs+zm; i++) ptr[i] = bptr + ((i-zs)*ym - ys);
149947c6ae99SBarry Smith     for (i=zs; i<zs+zm; i++) {
150047c6ae99SBarry Smith       for (j=ys; j<ys+ym; j++) {
150147c6ae99SBarry Smith         ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
150247c6ae99SBarry Smith       }
150347c6ae99SBarry Smith     }
150447c6ae99SBarry Smith     *iptr = (void*)ptr;
15058865f1eaSKarl Rupp     break;
15068865f1eaSKarl Rupp   }
150747c6ae99SBarry Smith   default:
1508ce94432eSBarry Smith     SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
150947c6ae99SBarry Smith   }
151047c6ae99SBarry Smith 
151147c6ae99SBarry Smith done:
151247c6ae99SBarry Smith   /* add arrays to the checked out list */
151347c6ae99SBarry Smith   if (ghosted) {
1514aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
151547c6ae99SBarry Smith       if (!dd->arrayghostedout[i]) {
151647c6ae99SBarry Smith         dd->arrayghostedout[i] = *iptr;
151747c6ae99SBarry Smith         dd->startghostedout[i] = iarray_start;
151847c6ae99SBarry Smith         break;
151947c6ae99SBarry Smith       }
152047c6ae99SBarry Smith     }
152147c6ae99SBarry Smith   } else {
1522aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
152347c6ae99SBarry Smith       if (!dd->arrayout[i]) {
152447c6ae99SBarry Smith         dd->arrayout[i] = *iptr;
152547c6ae99SBarry Smith         dd->startout[i] = iarray_start;
152647c6ae99SBarry Smith         break;
152747c6ae99SBarry Smith       }
152847c6ae99SBarry Smith     }
152947c6ae99SBarry Smith   }
153047c6ae99SBarry Smith   PetscFunctionReturn(0);
153147c6ae99SBarry Smith }
153247c6ae99SBarry Smith 
153347c6ae99SBarry Smith #undef __FUNCT__
1534aa219208SBarry Smith #define __FUNCT__ "DMDARestoreArray"
153547c6ae99SBarry Smith /*@C
1536aa219208SBarry Smith      DMDARestoreArray - Restores an array of derivative types for a DMDA
153747c6ae99SBarry Smith 
153847c6ae99SBarry Smith     Input Parameter:
153947c6ae99SBarry Smith +    da - information about my local patch
154047c6ae99SBarry Smith .    ghosted - do you want arrays for the ghosted or nonghosted patch
154147c6ae99SBarry Smith -    vptr - array data structured to be passed to ad_FormFunctionLocal()
154247c6ae99SBarry Smith 
154347c6ae99SBarry Smith      Level: advanced
154447c6ae99SBarry Smith 
1545bcaeba4dSBarry Smith .seealso: DMDAGetArray()
154647c6ae99SBarry Smith 
154747c6ae99SBarry Smith @*/
15487087cfbeSBarry Smith PetscErrorCode  DMDARestoreArray(DM da,PetscBool ghosted,void *vptr)
154947c6ae99SBarry Smith {
155047c6ae99SBarry Smith   PetscInt i;
155147c6ae99SBarry Smith   void     **iptr = (void**)vptr,*iarray_start = 0;
155247c6ae99SBarry Smith   DM_DA    *dd    = (DM_DA*)da->data;
155347c6ae99SBarry Smith 
155447c6ae99SBarry Smith   PetscFunctionBegin;
155547c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
155647c6ae99SBarry Smith   if (ghosted) {
1557aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
155847c6ae99SBarry Smith       if (dd->arrayghostedout[i] == *iptr) {
155947c6ae99SBarry Smith         iarray_start           = dd->startghostedout[i];
15600298fd71SBarry Smith         dd->arrayghostedout[i] = NULL;
15610298fd71SBarry Smith         dd->startghostedout[i] = NULL;
156247c6ae99SBarry Smith         break;
156347c6ae99SBarry Smith       }
156447c6ae99SBarry Smith     }
1565aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
156647c6ae99SBarry Smith       if (!dd->arrayghostedin[i]) {
156747c6ae99SBarry Smith         dd->arrayghostedin[i] = *iptr;
156847c6ae99SBarry Smith         dd->startghostedin[i] = iarray_start;
156947c6ae99SBarry Smith         break;
157047c6ae99SBarry Smith       }
157147c6ae99SBarry Smith     }
157247c6ae99SBarry Smith   } else {
1573aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
157447c6ae99SBarry Smith       if (dd->arrayout[i] == *iptr) {
157547c6ae99SBarry Smith         iarray_start    = dd->startout[i];
15760298fd71SBarry Smith         dd->arrayout[i] = NULL;
15770298fd71SBarry Smith         dd->startout[i] = NULL;
157847c6ae99SBarry Smith         break;
157947c6ae99SBarry Smith       }
158047c6ae99SBarry Smith     }
1581aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
158247c6ae99SBarry Smith       if (!dd->arrayin[i]) {
158347c6ae99SBarry Smith         dd->arrayin[i] = *iptr;
158447c6ae99SBarry Smith         dd->startin[i] = iarray_start;
158547c6ae99SBarry Smith         break;
158647c6ae99SBarry Smith       }
158747c6ae99SBarry Smith     }
158847c6ae99SBarry Smith   }
158947c6ae99SBarry Smith   PetscFunctionReturn(0);
159047c6ae99SBarry Smith }
159147c6ae99SBarry Smith 
1592