xref: /petsc/src/dm/impls/da/dalocal.c (revision b7a4d31f3bb8e2c344be29073528611f61e91ccc)
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>
9*b7a4d31fSMatthew G. Knepley #include <petscproblem.h>
109a800dd8SMatthew G. Knepley #include <petscfe.h>
1147c6ae99SBarry Smith 
1247c6ae99SBarry Smith /*
13e3c5b3baSBarry Smith    This allows the DMDA vectors to properly tell MATLAB their dimensions
1447c6ae99SBarry Smith */
1547c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
16c6db04a5SJed Brown #include <engine.h>   /* MATLAB include file */
17c6db04a5SJed Brown #include <mex.h>      /* MATLAB include file */
1847c6ae99SBarry Smith #undef __FUNCT__
1947c6ae99SBarry Smith #define __FUNCT__ "VecMatlabEnginePut_DA2d"
201e6b0712SBarry Smith static PetscErrorCode  VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
2147c6ae99SBarry Smith {
2247c6ae99SBarry Smith   PetscErrorCode ierr;
2347c6ae99SBarry Smith   PetscInt       n,m;
2447c6ae99SBarry Smith   Vec            vec = (Vec)obj;
2547c6ae99SBarry Smith   PetscScalar    *array;
2647c6ae99SBarry Smith   mxArray        *mat;
279a42bb27SBarry Smith   DM             da;
2847c6ae99SBarry Smith 
2947c6ae99SBarry Smith   PetscFunctionBegin;
30c688c046SMatthew G Knepley   ierr = VecGetDM(vec, &da);CHKERRQ(ierr);
31ce94432eSBarry Smith   if (!da) SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
32aa219208SBarry Smith   ierr = DMDAGetGhostCorners(da,0,0,0,&m,&n,0);CHKERRQ(ierr);
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
3547c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
3647c6ae99SBarry Smith   mat = mxCreateDoubleMatrix(m,n,mxREAL);
3747c6ae99SBarry Smith #else
3847c6ae99SBarry Smith   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
3947c6ae99SBarry Smith #endif
4047c6ae99SBarry Smith   ierr = PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));CHKERRQ(ierr);
4147c6ae99SBarry Smith   ierr = PetscObjectName(obj);CHKERRQ(ierr);
4247c6ae99SBarry Smith   engPutVariable((Engine*)mengine,obj->name,mat);
4347c6ae99SBarry Smith 
4447c6ae99SBarry Smith   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
4547c6ae99SBarry Smith   PetscFunctionReturn(0);
4647c6ae99SBarry Smith }
4747c6ae99SBarry Smith #endif
4847c6ae99SBarry Smith 
4947c6ae99SBarry Smith 
5047c6ae99SBarry Smith #undef __FUNCT__
51564755cdSBarry Smith #define __FUNCT__ "DMCreateLocalVector_DA"
527087cfbeSBarry Smith PetscErrorCode  DMCreateLocalVector_DA(DM da,Vec *g)
5347c6ae99SBarry Smith {
5447c6ae99SBarry Smith   PetscErrorCode ierr;
5547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
5647c6ae99SBarry Smith 
5747c6ae99SBarry Smith   PetscFunctionBegin;
5847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
5947c6ae99SBarry Smith   PetscValidPointer(g,2);
6011689aebSJed Brown   if (da->defaultSection) {
6111689aebSJed Brown     ierr = DMCreateLocalVector_Section_Private(da,g);CHKERRQ(ierr);
6211689aebSJed Brown   } else {
6347c6ae99SBarry Smith     ierr = VecCreate(PETSC_COMM_SELF,g);CHKERRQ(ierr);
6447c6ae99SBarry Smith     ierr = VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);CHKERRQ(ierr);
6547c6ae99SBarry Smith     ierr = VecSetBlockSize(*g,dd->w);CHKERRQ(ierr);
66401ddaa8SBarry Smith     ierr = VecSetType(*g,da->vectype);CHKERRQ(ierr);
67c688c046SMatthew G Knepley     ierr = VecSetDM(*g, da);CHKERRQ(ierr);
6847c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
6947c6ae99SBarry Smith     if (dd->w == 1  && dd->dim == 2) {
70bdf89e91SBarry Smith       ierr = PetscObjectComposeFunction((PetscObject)*g,"PetscMatlabEnginePut_C",VecMatlabEnginePut_DA2d);CHKERRQ(ierr);
7147c6ae99SBarry Smith     }
7247c6ae99SBarry Smith #endif
7311689aebSJed Brown   }
7447c6ae99SBarry Smith   PetscFunctionReturn(0);
7547c6ae99SBarry Smith }
7647c6ae99SBarry Smith 
77a66d4d66SMatthew G Knepley #undef __FUNCT__
7857459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumCells"
79939f6067SMatthew G. Knepley /*@
80939f6067SMatthew G. Knepley   DMDAGetNumCells - Get the number of cells in the local piece of the DMDA. This includes ghost cells.
81939f6067SMatthew G. Knepley 
82939f6067SMatthew G. Knepley   Input Parameter:
83939f6067SMatthew G. Knepley . dm - The DM object
84939f6067SMatthew G. Knepley 
85939f6067SMatthew G. Knepley   Output Parameters:
86939f6067SMatthew G. Knepley + numCellsX - The number of local cells in the x-direction
87939f6067SMatthew G. Knepley . numCellsY - The number of local cells in the y-direction
88939f6067SMatthew G. Knepley . numCellsZ - The number of local cells in the z-direction
89939f6067SMatthew G. Knepley - numCells - The number of local cells
90939f6067SMatthew G. Knepley 
91939f6067SMatthew G. Knepley   Level: developer
92939f6067SMatthew G. Knepley 
93939f6067SMatthew G. Knepley .seealso: DMDAGetCellPoint()
94939f6067SMatthew G. Knepley @*/
953582350cSMatthew G. Knepley PetscErrorCode DMDAGetNumCells(DM dm, PetscInt *numCellsX, PetscInt *numCellsY, PetscInt *numCellsZ, PetscInt *numCells)
9657459e9aSMatthew G Knepley {
9757459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA*) dm->data;
9857459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
9957459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
10057459e9aSMatthew G Knepley   const PetscInt nC  = (mx)*(dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
10157459e9aSMatthew G Knepley 
10257459e9aSMatthew G Knepley   PetscFunctionBegin;
103d6401b93SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1043582350cSMatthew G. Knepley   if (numCellsX) {
1053582350cSMatthew G. Knepley     PetscValidIntPointer(numCellsX,2);
1063582350cSMatthew G. Knepley     *numCellsX = mx;
1073582350cSMatthew G. Knepley   }
1083582350cSMatthew G. Knepley   if (numCellsY) {
1093582350cSMatthew G. Knepley     PetscValidIntPointer(numCellsX,3);
1103582350cSMatthew G. Knepley     *numCellsY = my;
1113582350cSMatthew G. Knepley   }
1123582350cSMatthew G. Knepley   if (numCellsZ) {
1133582350cSMatthew G. Knepley     PetscValidIntPointer(numCellsX,4);
1143582350cSMatthew G. Knepley     *numCellsZ = mz;
1153582350cSMatthew G. Knepley   }
11657459e9aSMatthew G Knepley   if (numCells) {
1173582350cSMatthew G. Knepley     PetscValidIntPointer(numCells,5);
11857459e9aSMatthew G Knepley     *numCells = nC;
11957459e9aSMatthew G Knepley   }
12057459e9aSMatthew G Knepley   PetscFunctionReturn(0);
12157459e9aSMatthew G Knepley }
12257459e9aSMatthew G Knepley 
12357459e9aSMatthew G Knepley #undef __FUNCT__
124d6401b93SMatthew G. Knepley #define __FUNCT__ "DMDAGetCellPoint"
125d6401b93SMatthew G. Knepley /*@
126d6401b93SMatthew G. Knepley   DMDAGetCellPoint - Get the DM point corresponding to the tuple (i, j, k) in the DMDA
127d6401b93SMatthew G. Knepley 
128d6401b93SMatthew G. Knepley   Input Parameters:
129d6401b93SMatthew G. Knepley + dm - The DM object
130d6401b93SMatthew G. Knepley - i,j,k - The global indices for the cell
131d6401b93SMatthew G. Knepley 
132d6401b93SMatthew G. Knepley   Output Parameters:
133d6401b93SMatthew G. Knepley . point - The local DM point
134d6401b93SMatthew G. Knepley 
135d6401b93SMatthew G. Knepley   Level: developer
136d6401b93SMatthew G. Knepley 
137d6401b93SMatthew G. Knepley .seealso: DMDAGetNumCells()
138d6401b93SMatthew G. Knepley @*/
139d6401b93SMatthew G. Knepley PetscErrorCode DMDAGetCellPoint(DM dm, PetscInt i, PetscInt j, PetscInt k, PetscInt *point)
140d6401b93SMatthew G. Knepley {
141d6401b93SMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
142d6401b93SMatthew G. Knepley   const PetscInt dim = da->dim;
143d6401b93SMatthew G. Knepley   DMDALocalInfo  info;
144d6401b93SMatthew G. Knepley   PetscErrorCode ierr;
145d6401b93SMatthew G. Knepley 
146d6401b93SMatthew G. Knepley   PetscFunctionBegin;
147d6401b93SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
148d6401b93SMatthew G. Knepley   PetscValidIntPointer(point,5);
149d6401b93SMatthew G. Knepley   ierr = DMDAGetLocalInfo(dm, &info);CHKERRQ(ierr);
150d6401b93SMatthew 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);}
151d6401b93SMatthew 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);}
152d6401b93SMatthew 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);}
153d6401b93SMatthew G. Knepley   *point = i + (dim > 1 ? (j + (dim > 2 ? k*info.gym : 0))*info.gxm : 0);
154d6401b93SMatthew G. Knepley   PetscFunctionReturn(0);
155d6401b93SMatthew G. Knepley }
156d6401b93SMatthew G. Knepley 
157d6401b93SMatthew G. Knepley #undef __FUNCT__
15857459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumVertices"
15957459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
16057459e9aSMatthew G Knepley {
16157459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
16257459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
16357459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
16457459e9aSMatthew G Knepley   const PetscInt nVx = mx+1;
16557459e9aSMatthew G Knepley   const PetscInt nVy = dim > 1 ? (my+1) : 1;
16657459e9aSMatthew G Knepley   const PetscInt nVz = dim > 2 ? (mz+1) : 1;
16757459e9aSMatthew G Knepley   const PetscInt nV  = nVx*nVy*nVz;
16857459e9aSMatthew G Knepley 
16957459e9aSMatthew G Knepley   PetscFunctionBegin;
17057459e9aSMatthew G Knepley   if (numVerticesX) {
17157459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesX,2);
17257459e9aSMatthew G Knepley     *numVerticesX = nVx;
17357459e9aSMatthew G Knepley   }
17457459e9aSMatthew G Knepley   if (numVerticesY) {
17557459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesY,3);
17657459e9aSMatthew G Knepley     *numVerticesY = nVy;
17757459e9aSMatthew G Knepley   }
17857459e9aSMatthew G Knepley   if (numVerticesZ) {
17957459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesZ,4);
18057459e9aSMatthew G Knepley     *numVerticesZ = nVz;
18157459e9aSMatthew G Knepley   }
18257459e9aSMatthew G Knepley   if (numVertices) {
18357459e9aSMatthew G Knepley     PetscValidIntPointer(numVertices,5);
18457459e9aSMatthew G Knepley     *numVertices = nV;
18557459e9aSMatthew G Knepley   }
18657459e9aSMatthew G Knepley   PetscFunctionReturn(0);
18757459e9aSMatthew G Knepley }
18857459e9aSMatthew G Knepley 
18957459e9aSMatthew G Knepley #undef __FUNCT__
19057459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumFaces"
19157459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
19257459e9aSMatthew G Knepley {
19357459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
19457459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
19557459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
19657459e9aSMatthew G Knepley   const PetscInt nxF = (dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
19757459e9aSMatthew G Knepley   const PetscInt nXF = (mx+1)*nxF;
19857459e9aSMatthew G Knepley   const PetscInt nyF = mx*(dim > 2 ? mz : 1);
19957459e9aSMatthew G Knepley   const PetscInt nYF = dim > 1 ? (my+1)*nyF : 0;
20057459e9aSMatthew G Knepley   const PetscInt nzF = mx*(dim > 1 ? my : 0);
20157459e9aSMatthew G Knepley   const PetscInt nZF = dim > 2 ? (mz+1)*nzF : 0;
20257459e9aSMatthew G Knepley 
20357459e9aSMatthew G Knepley   PetscFunctionBegin;
20457459e9aSMatthew G Knepley   if (numXFacesX) {
20557459e9aSMatthew G Knepley     PetscValidIntPointer(numXFacesX,2);
20657459e9aSMatthew G Knepley     *numXFacesX = nxF;
20757459e9aSMatthew G Knepley   }
20857459e9aSMatthew G Knepley   if (numXFaces) {
20957459e9aSMatthew G Knepley     PetscValidIntPointer(numXFaces,3);
21057459e9aSMatthew G Knepley     *numXFaces = nXF;
21157459e9aSMatthew G Knepley   }
21257459e9aSMatthew G Knepley   if (numYFacesY) {
21357459e9aSMatthew G Knepley     PetscValidIntPointer(numYFacesY,4);
21457459e9aSMatthew G Knepley     *numYFacesY = nyF;
21557459e9aSMatthew G Knepley   }
21657459e9aSMatthew G Knepley   if (numYFaces) {
21757459e9aSMatthew G Knepley     PetscValidIntPointer(numYFaces,5);
21857459e9aSMatthew G Knepley     *numYFaces = nYF;
21957459e9aSMatthew G Knepley   }
22057459e9aSMatthew G Knepley   if (numZFacesZ) {
22157459e9aSMatthew G Knepley     PetscValidIntPointer(numZFacesZ,6);
22257459e9aSMatthew G Knepley     *numZFacesZ = nzF;
22357459e9aSMatthew G Knepley   }
22457459e9aSMatthew G Knepley   if (numZFaces) {
22557459e9aSMatthew G Knepley     PetscValidIntPointer(numZFaces,7);
22657459e9aSMatthew G Knepley     *numZFaces = nZF;
22757459e9aSMatthew G Knepley   }
22857459e9aSMatthew G Knepley   PetscFunctionReturn(0);
22957459e9aSMatthew G Knepley }
23057459e9aSMatthew G Knepley 
23157459e9aSMatthew G Knepley #undef __FUNCT__
23257459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetHeightStratum"
23357459e9aSMatthew G Knepley PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PetscInt *pStart, PetscInt *pEnd)
23457459e9aSMatthew G Knepley {
23557459e9aSMatthew G Knepley   DM_DA          *da = (DM_DA*) dm->data;
23657459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
23757459e9aSMatthew G Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
23857459e9aSMatthew G Knepley   PetscErrorCode ierr;
23957459e9aSMatthew G Knepley 
24057459e9aSMatthew G Knepley   PetscFunctionBegin;
2418865f1eaSKarl Rupp   if (pStart) PetscValidIntPointer(pStart,3);
2428865f1eaSKarl Rupp   if (pEnd)   PetscValidIntPointer(pEnd,4);
2433582350cSMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
2440298fd71SBarry Smith   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
2450298fd71SBarry Smith   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
24657459e9aSMatthew G Knepley   if (height == 0) {
24757459e9aSMatthew G Knepley     /* Cells */
2488865f1eaSKarl Rupp     if (pStart) *pStart = 0;
2498865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC;
25057459e9aSMatthew G Knepley   } else if (height == 1) {
25157459e9aSMatthew G Knepley     /* Faces */
2528865f1eaSKarl Rupp     if (pStart) *pStart = nC+nV;
2538865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
25457459e9aSMatthew G Knepley   } else if (height == dim) {
25557459e9aSMatthew G Knepley     /* Vertices */
2568865f1eaSKarl Rupp     if (pStart) *pStart = nC;
2578865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV;
25857459e9aSMatthew G Knepley   } else if (height < 0) {
25957459e9aSMatthew G Knepley     /* All points */
2608865f1eaSKarl Rupp     if (pStart) *pStart = 0;
2618865f1eaSKarl Rupp     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
26282f516ccSBarry Smith   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of height %d in the DA", height);
26357459e9aSMatthew G Knepley   PetscFunctionReturn(0);
26457459e9aSMatthew G Knepley }
26557459e9aSMatthew G Knepley 
26657459e9aSMatthew G Knepley #undef __FUNCT__
2673385ff7eSMatthew G. Knepley #define __FUNCT__ "DMDAGetDepthStratum"
2683385ff7eSMatthew G. Knepley PetscErrorCode DMDAGetDepthStratum(DM dm, PetscInt depth, PetscInt *pStart, PetscInt *pEnd)
2693385ff7eSMatthew G. Knepley {
2703385ff7eSMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
2713385ff7eSMatthew G. Knepley   const PetscInt dim = da->dim;
2723385ff7eSMatthew G. Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
2733385ff7eSMatthew G. Knepley   PetscErrorCode ierr;
2743385ff7eSMatthew G. Knepley 
2753385ff7eSMatthew G. Knepley   PetscFunctionBegin;
2763385ff7eSMatthew G. Knepley   if (pStart) PetscValidIntPointer(pStart,3);
2773385ff7eSMatthew G. Knepley   if (pEnd)   PetscValidIntPointer(pEnd,4);
2783385ff7eSMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
2793385ff7eSMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
2803385ff7eSMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
2813385ff7eSMatthew G. Knepley   if (depth == dim) {
2823385ff7eSMatthew G. Knepley     /* Cells */
2833385ff7eSMatthew G. Knepley     if (pStart) *pStart = 0;
2843385ff7eSMatthew G. Knepley     if (pEnd)   *pEnd   = nC;
2853385ff7eSMatthew G. Knepley   } else if (depth == dim-1) {
2863385ff7eSMatthew G. Knepley     /* Faces */
2873385ff7eSMatthew G. Knepley     if (pStart) *pStart = nC+nV;
2883385ff7eSMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
2893385ff7eSMatthew G. Knepley   } else if (depth == 0) {
2903385ff7eSMatthew G. Knepley     /* Vertices */
2913385ff7eSMatthew G. Knepley     if (pStart) *pStart = nC;
2923385ff7eSMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV;
2933385ff7eSMatthew G. Knepley   } else if (depth < 0) {
2943385ff7eSMatthew G. Knepley     /* All points */
2953385ff7eSMatthew G. Knepley     if (pStart) *pStart = 0;
2963385ff7eSMatthew G. Knepley     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
2973385ff7eSMatthew G. Knepley   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of depth %d in the DA", depth);
2983385ff7eSMatthew G. Knepley   PetscFunctionReturn(0);
2993385ff7eSMatthew G. Knepley }
3003385ff7eSMatthew G. Knepley 
3013385ff7eSMatthew G. Knepley #undef __FUNCT__
3023385ff7eSMatthew G. Knepley #define __FUNCT__ "DMDAGetConeSize"
3033385ff7eSMatthew G. Knepley PetscErrorCode DMDAGetConeSize(DM dm, PetscInt p, PetscInt *coneSize)
3043385ff7eSMatthew G. Knepley {
3053385ff7eSMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
3063385ff7eSMatthew G. Knepley   const PetscInt dim = da->dim;
3073385ff7eSMatthew G. Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
3083385ff7eSMatthew G. Knepley   PetscErrorCode ierr;
3093385ff7eSMatthew G. Knepley 
3103385ff7eSMatthew G. Knepley   PetscFunctionBegin;
3113385ff7eSMatthew G. Knepley   *coneSize = 0;
3123385ff7eSMatthew G. Knepley   ierr = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
3133385ff7eSMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
3143385ff7eSMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
3153385ff7eSMatthew G. Knepley   switch (dim) {
3163385ff7eSMatthew G. Knepley   case 2:
3173385ff7eSMatthew G. Knepley     if (p >= 0) {
3183385ff7eSMatthew G. Knepley       if (p < nC) {
3193385ff7eSMatthew G. Knepley         *coneSize = 4;
3203385ff7eSMatthew G. Knepley       } else if (p < nC+nV) {
3213385ff7eSMatthew G. Knepley         *coneSize = 0;
3223385ff7eSMatthew G. Knepley       } else if (p < nC+nV+nXF+nYF+nZF) {
3233385ff7eSMatthew G. Knepley         *coneSize = 2;
3243385ff7eSMatthew G. Knepley       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
3253385ff7eSMatthew G. Knepley     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
3263385ff7eSMatthew G. Knepley     break;
3273385ff7eSMatthew G. Knepley   case 3:
3283385ff7eSMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
3293385ff7eSMatthew G. Knepley     break;
3303385ff7eSMatthew G. Knepley   }
3313385ff7eSMatthew G. Knepley   PetscFunctionReturn(0);
3323385ff7eSMatthew G. Knepley }
3333385ff7eSMatthew G. Knepley 
3343385ff7eSMatthew G. Knepley #undef __FUNCT__
3353385ff7eSMatthew G. Knepley #define __FUNCT__ "DMDAGetCone"
3363385ff7eSMatthew G. Knepley PetscErrorCode DMDAGetCone(DM dm, PetscInt p, PetscInt *cone[])
3373385ff7eSMatthew G. Knepley {
3383385ff7eSMatthew G. Knepley   DM_DA         *da  = (DM_DA*) dm->data;
3393385ff7eSMatthew G. Knepley   const PetscInt dim = da->dim;
3403385ff7eSMatthew G. Knepley   PetscInt       nCx, nCy, nCz, nC, nVx, nVy, nVz, nV, nxF, nyF, nzF, nXF, nYF, nZF;
3413385ff7eSMatthew G. Knepley   PetscErrorCode ierr;
3423385ff7eSMatthew G. Knepley 
3433385ff7eSMatthew G. Knepley   PetscFunctionBegin;
3443385ff7eSMatthew G. Knepley   if (!cone) {ierr = DMGetWorkArray(dm, 6, PETSC_INT, cone);CHKERRQ(ierr);}
3453385ff7eSMatthew G. Knepley   ierr = DMDAGetNumCells(dm, &nCx, &nCy, &nCz, &nC);CHKERRQ(ierr);
3463385ff7eSMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
3473385ff7eSMatthew G. Knepley   ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
3483385ff7eSMatthew G. Knepley   switch (dim) {
3493385ff7eSMatthew G. Knepley   case 2:
3503385ff7eSMatthew G. Knepley     if (p >= 0) {
3513385ff7eSMatthew G. Knepley       if (p < nC) {
3523385ff7eSMatthew G. Knepley         const PetscInt cy = p / nCx;
3533385ff7eSMatthew G. Knepley         const PetscInt cx = p % nCx;
3543385ff7eSMatthew G. Knepley 
3553385ff7eSMatthew G. Knepley         (*cone)[0] = cy*nxF + cx + nC+nV;
3563385ff7eSMatthew G. Knepley         (*cone)[1] = cx*nyF + cy + nyF + nC+nV+nXF;
3573385ff7eSMatthew G. Knepley         (*cone)[2] = cy*nxF + cx + nxF + nC+nV;
3583385ff7eSMatthew G. Knepley         (*cone)[3] = cx*nyF + cy + nC+nV+nXF;
3593385ff7eSMatthew G. Knepley         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do cell cones");
3603385ff7eSMatthew G. Knepley       } else if (p < nC+nV) {
3613385ff7eSMatthew G. Knepley       } else if (p < nC+nV+nXF) {
3623385ff7eSMatthew G. Knepley         const PetscInt fy = (p - nC+nV) / nxF;
3633385ff7eSMatthew G. Knepley         const PetscInt fx = (p - nC+nV) % nxF;
3643385ff7eSMatthew G. Knepley 
3653385ff7eSMatthew G. Knepley         (*cone)[0] = fy*nVx + fx + nC;
3663385ff7eSMatthew G. Knepley         (*cone)[1] = fy*nVx + fx + 1 + nC;
3673385ff7eSMatthew G. Knepley       } else if (p < nC+nV+nXF+nYF) {
3683385ff7eSMatthew G. Knepley         const PetscInt fx = (p - nC+nV+nXF) / nyF;
3693385ff7eSMatthew G. Knepley         const PetscInt fy = (p - nC+nV+nXF) % nyF;
3703385ff7eSMatthew G. Knepley 
3713385ff7eSMatthew G. Knepley         (*cone)[0] = fy*nVx + fx + nC;
3723385ff7eSMatthew G. Knepley         (*cone)[1] = fy*nVx + fx + nVx + nC;
3733385ff7eSMatthew G. Knepley       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
3743385ff7eSMatthew G. Knepley     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
3753385ff7eSMatthew G. Knepley     break;
3763385ff7eSMatthew G. Knepley   case 3:
3773385ff7eSMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
3783385ff7eSMatthew G. Knepley     break;
3793385ff7eSMatthew G. Knepley   }
3803385ff7eSMatthew G. Knepley   PetscFunctionReturn(0);
3813385ff7eSMatthew G. Knepley }
3823385ff7eSMatthew G. Knepley 
3833385ff7eSMatthew G. Knepley #undef __FUNCT__
3843385ff7eSMatthew G. Knepley #define __FUNCT__ "DMDARestoreCone"
3853385ff7eSMatthew G. Knepley PetscErrorCode DMDARestoreCone(DM dm, PetscInt p, PetscInt *cone[])
3863385ff7eSMatthew G. Knepley {
3873385ff7eSMatthew G. Knepley   PetscErrorCode ierr;
3883385ff7eSMatthew G. Knepley 
3893385ff7eSMatthew G. Knepley   PetscFunctionBegin;
3903385ff7eSMatthew G. Knepley   ierr = DMGetWorkArray(dm, 6, PETSC_INT, cone);CHKERRQ(ierr);
3913385ff7eSMatthew G. Knepley   PetscFunctionReturn(0);
3923385ff7eSMatthew G. Knepley }
3933385ff7eSMatthew G. Knepley 
3943385ff7eSMatthew G. Knepley #undef __FUNCT__
395a66d4d66SMatthew G Knepley #define __FUNCT__ "DMDACreateSection"
396a66d4d66SMatthew G Knepley /*@C
397a66d4d66SMatthew G Knepley   DMDACreateSection - Create a PetscSection inside the DMDA that describes data layout. This allows multiple fields with
398a66d4d66SMatthew G Knepley   different numbers of dofs on vertices, cells, and faces in each direction.
399a66d4d66SMatthew G Knepley 
400a66d4d66SMatthew G Knepley   Input Parameters:
401a66d4d66SMatthew G Knepley + dm- The DMDA
402a66d4d66SMatthew G Knepley . numFields - The number of fields
403affa55c7SMatthew G. Knepley . numComp - The number of components in each field
404affa55c7SMatthew G. Knepley . numDof - The number of dofs per dimension for each field
4050298fd71SBarry Smith . numFaceDof - The number of dofs per face for each field and direction, or NULL
406a66d4d66SMatthew G Knepley 
407a66d4d66SMatthew G Knepley   Level: developer
408a66d4d66SMatthew G Knepley 
409a66d4d66SMatthew G Knepley   Note:
410a66d4d66SMatthew G Knepley   The default DMDA numbering is as follows:
411a66d4d66SMatthew G Knepley 
412a66d4d66SMatthew G Knepley     - Cells:    [0,             nC)
413a66d4d66SMatthew G Knepley     - Vertices: [nC,            nC+nV)
41488ed4aceSMatthew G Knepley     - X-Faces:  [nC+nV,         nC+nV+nXF)         normal is +- x-dir
41588ed4aceSMatthew G Knepley     - Y-Faces:  [nC+nV+nXF,     nC+nV+nXF+nYF)     normal is +- y-dir
41688ed4aceSMatthew G Knepley     - Z-Faces:  [nC+nV+nXF+nYF, nC+nV+nXF+nYF+nZF) normal is +- z-dir
417a66d4d66SMatthew G Knepley 
418a66d4d66SMatthew G Knepley   We interpret the default DMDA partition as a cell partition, and the data assignment as a cell assignment.
419a66d4d66SMatthew G Knepley @*/
42044e1f9abSMatthew G. Knepley PetscErrorCode DMDACreateSection(DM dm, const PetscInt numComp[], const PetscInt numDof[], const PetscInt numFaceDof[], PetscSection *s)
421a66d4d66SMatthew G Knepley {
422a66d4d66SMatthew G Knepley   DM_DA            *da  = (DM_DA*) dm->data;
423a4b60ecfSMatthew G. Knepley   PetscSection      section;
42488ed4aceSMatthew G Knepley   const PetscInt    dim = da->dim;
42580800b1aSMatthew G Knepley   PetscInt          numFields, numVertexTotDof = 0, numCellTotDof = 0, numFaceTotDof[3] = {0, 0, 0};
426b2fff234SMatthew G. Knepley   PetscBT           isLeaf;
42788ed4aceSMatthew G Knepley   PetscSF           sf;
428feafbc5cSMatthew G Knepley   PetscMPIInt       rank;
42988ed4aceSMatthew G Knepley   const PetscMPIInt *neighbors;
43088ed4aceSMatthew G Knepley   PetscInt          *localPoints;
43188ed4aceSMatthew G Knepley   PetscSFNode       *remotePoints;
432f5eeb527SMatthew G Knepley   PetscInt          nleaves = 0,  nleavesCheck = 0, nL = 0;
43357459e9aSMatthew G Knepley   PetscInt          nC, nVx, nVy, nVz, nV, nxF, nXF, nyF, nYF, nzF, nZF;
43457459e9aSMatthew G Knepley   PetscInt          pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart, zfEnd;
43588ed4aceSMatthew G Knepley   PetscInt          f, v, c, xf, yf, zf, xn, yn, zn;
436a66d4d66SMatthew G Knepley   PetscErrorCode    ierr;
437a66d4d66SMatthew G Knepley 
438a66d4d66SMatthew G Knepley   PetscFunctionBegin;
439a66d4d66SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4403582350cSMatthew G. Knepley   PetscValidPointer(s, 4);
44182f516ccSBarry Smith   ierr    = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr);
4423582350cSMatthew G. Knepley   ierr    = DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);CHKERRQ(ierr);
44357459e9aSMatthew G Knepley   ierr    = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
44457459e9aSMatthew G Knepley   ierr    = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
44557459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);CHKERRQ(ierr);
44657459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);CHKERRQ(ierr);
44757459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);CHKERRQ(ierr);
44857459e9aSMatthew G Knepley   ierr    = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr);
44957459e9aSMatthew G Knepley   xfStart = vEnd;  xfEnd = xfStart+nXF;
45057459e9aSMatthew G Knepley   yfStart = xfEnd; yfEnd = yfStart+nYF;
45157459e9aSMatthew G Knepley   zfStart = yfEnd; zfEnd = zfStart+nZF;
45282f516ccSBarry Smith   if (zfEnd != fEnd) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid face end %d, should be %d", zfEnd, fEnd);
45388ed4aceSMatthew G Knepley   /* Create local section */
45480800b1aSMatthew G Knepley   ierr = DMDAGetInfo(dm, 0,0,0,0,0,0,0, &numFields, 0,0,0,0,0);CHKERRQ(ierr);
455a66d4d66SMatthew G Knepley   for (f = 0; f < numFields; ++f) {
456affa55c7SMatthew G. Knepley     numVertexTotDof  += numDof[f*(dim+1)+0];
457affa55c7SMatthew G. Knepley     numCellTotDof    += numDof[f*(dim+1)+dim];
458affa55c7SMatthew G. Knepley     numFaceTotDof[0] += dim > 0 ? (numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]) : 0;
459affa55c7SMatthew G. Knepley     numFaceTotDof[1] += dim > 1 ? (numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]) : 0;
460affa55c7SMatthew G. Knepley     numFaceTotDof[2] += dim > 2 ? (numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]) : 0;
461a66d4d66SMatthew G Knepley   }
462a4b60ecfSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
463affa55c7SMatthew G. Knepley   if (numFields > 0) {
464a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetNumFields(section, numFields);CHKERRQ(ierr);
465a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
46680800b1aSMatthew G Knepley       const char *name;
46780800b1aSMatthew G Knepley 
46880800b1aSMatthew G Knepley       ierr = DMDAGetFieldName(dm, f, &name);CHKERRQ(ierr);
469affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldName(section, f, name ? name : "Field");CHKERRQ(ierr);
47080800b1aSMatthew G Knepley       if (numComp) {
471a4b60ecfSMatthew G. Knepley         ierr = PetscSectionSetFieldComponents(section, f, numComp[f]);CHKERRQ(ierr);
472a66d4d66SMatthew G Knepley       }
473a66d4d66SMatthew G Knepley     }
474a66d4d66SMatthew G Knepley   }
475a4b60ecfSMatthew G. Knepley   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
476a66d4d66SMatthew G Knepley   for (v = vStart; v < vEnd; ++v) {
477a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
478affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, v, f, numDof[f*(dim+1)+0]);CHKERRQ(ierr);
479a66d4d66SMatthew G Knepley     }
480a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, v, numVertexTotDof);CHKERRQ(ierr);
481a66d4d66SMatthew G Knepley   }
482a66d4d66SMatthew G Knepley   for (xf = xfStart; xf < xfEnd; ++xf) {
483a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
484affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, xf, f, numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
485a66d4d66SMatthew G Knepley     }
486a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, xf, numFaceTotDof[0]);CHKERRQ(ierr);
487a66d4d66SMatthew G Knepley   }
488a66d4d66SMatthew G Knepley   for (yf = yfStart; yf < yfEnd; ++yf) {
489a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
490affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, yf, f, numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
491a66d4d66SMatthew G Knepley     }
492a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, yf, numFaceTotDof[1]);CHKERRQ(ierr);
493a66d4d66SMatthew G Knepley   }
494a66d4d66SMatthew G Knepley   for (zf = zfStart; zf < zfEnd; ++zf) {
495a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
496affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, zf, f, numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]);CHKERRQ(ierr);
497a66d4d66SMatthew G Knepley     }
498a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, zf, numFaceTotDof[2]);CHKERRQ(ierr);
499a66d4d66SMatthew G Knepley   }
500a66d4d66SMatthew G Knepley   for (c = cStart; c < cEnd; ++c) {
501a66d4d66SMatthew G Knepley     for (f = 0; f < numFields; ++f) {
502affa55c7SMatthew G. Knepley       ierr = PetscSectionSetFieldDof(section, c, f, numDof[f*(dim+1)+dim]);CHKERRQ(ierr);
503a66d4d66SMatthew G Knepley     }
504a4b60ecfSMatthew G. Knepley     ierr = PetscSectionSetDof(section, c, numCellTotDof);CHKERRQ(ierr);
505a66d4d66SMatthew G Knepley   }
506a4b60ecfSMatthew G. Knepley   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
50788ed4aceSMatthew G Knepley   /* Create mesh point SF */
508b2fff234SMatthew G. Knepley   ierr = PetscBTCreate(pEnd-pStart, &isLeaf);CHKERRQ(ierr);
50988ed4aceSMatthew G Knepley   ierr = DMDAGetNeighbors(dm, &neighbors);CHKERRQ(ierr);
51088ed4aceSMatthew G Knepley   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
51188ed4aceSMatthew G Knepley     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
51288ed4aceSMatthew G Knepley       for (xn = 0; xn < 3; ++xn) {
5137128ae9fSMatthew G Knepley         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
51488ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
515b2fff234SMatthew G. Knepley         PetscInt       xv, yv, zv;
51688ed4aceSMatthew G Knepley 
5173814d604SMatthew G Knepley         if (neighbor >= 0 && neighbor < rank) {
518b2fff234SMatthew G. Knepley           if (xp < 0) { /* left */
519b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
520b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
521b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
522b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
523b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
524b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
525b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
526b2fff234SMatthew G. Knepley               } else {
527b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
528b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
529b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
530b2fff234SMatthew G. Knepley                 }
531b2fff234SMatthew G. Knepley               }
532b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
533b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
534b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
535b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
536b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
537b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
538b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
539b2fff234SMatthew G. Knepley               } else {
540b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
541b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
542b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
543b2fff234SMatthew G. Knepley                 }
544b2fff234SMatthew G. Knepley               }
545b2fff234SMatthew G. Knepley             } else {
546b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
547b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
548b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
549b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
550b2fff234SMatthew G. Knepley                 }
551b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
552b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
553b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
554b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
555b2fff234SMatthew G. Knepley                 }
556b2fff234SMatthew G. Knepley               } else {
557b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
558b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
559b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
560b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
561b2fff234SMatthew G. Knepley                   }
562b2fff234SMatthew G. Knepley                 }
563b2fff234SMatthew G. Knepley #if 0
564b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
565b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
566b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
567b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
568b2fff234SMatthew G. Knepley                 }
569b2fff234SMatthew G. Knepley #endif
570b2fff234SMatthew G. Knepley               }
571b2fff234SMatthew G. Knepley             }
572b2fff234SMatthew G. Knepley           } else if (xp > 0) { /* right */
573b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
574b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
575b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
576b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
577b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
578b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
579b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
580b2fff234SMatthew G. Knepley               } else {
581b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
582b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
583b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
584b2fff234SMatthew G. Knepley                 }
585b2fff234SMatthew G. Knepley               }
586b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
587b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
588b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
589b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
590b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
591b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
592b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
593b2fff234SMatthew G. Knepley               } else {
594b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
595b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
596b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
597b2fff234SMatthew G. Knepley                 }
598b2fff234SMatthew G. Knepley               }
599b2fff234SMatthew G. Knepley             } else {
600b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
601b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
602b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
603b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
604b2fff234SMatthew G. Knepley                 }
605b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
606b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
607b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
608b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
609b2fff234SMatthew G. Knepley                 }
610b2fff234SMatthew G. Knepley               } else {
611b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
612b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
613b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
614b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
615b2fff234SMatthew G. Knepley                   }
616b2fff234SMatthew G. Knepley                 }
617b2fff234SMatthew G. Knepley #if 0
618b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
619b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
620b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
621b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
622b2fff234SMatthew G. Knepley                 }
623b2fff234SMatthew G. Knepley #endif
624b2fff234SMatthew G. Knepley               }
625b2fff234SMatthew G. Knepley             }
626b2fff234SMatthew G. Knepley           } else {
627b2fff234SMatthew G. Knepley             if (yp < 0) { /* bottom */
628b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
629b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
630b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
631b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
632b2fff234SMatthew G. Knepley                 }
633b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
634b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
635b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
636b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
637b2fff234SMatthew G. Knepley                 }
638b2fff234SMatthew G. Knepley               } else {
639b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
640b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
641b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
642b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
643b2fff234SMatthew G. Knepley                   }
644b2fff234SMatthew G. Knepley                 }
645b2fff234SMatthew G. Knepley #if 0
646b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
647b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
648b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
649b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
650b2fff234SMatthew G. Knepley                 }
651b2fff234SMatthew G. Knepley #endif
652b2fff234SMatthew G. Knepley               }
653b2fff234SMatthew G. Knepley             } else if (yp > 0) { /* top */
654b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
655b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
656b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
657b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
658b2fff234SMatthew G. Knepley                 }
659b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
660b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
661b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
662b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
663b2fff234SMatthew G. Knepley                 }
664b2fff234SMatthew G. Knepley               } else {
665b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
666b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
667b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
668b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
669b2fff234SMatthew G. Knepley                   }
670b2fff234SMatthew G. Knepley                 }
671b2fff234SMatthew G. Knepley #if 0
672b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
673b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
674b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
675b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
676b2fff234SMatthew G. Knepley                 }
677b2fff234SMatthew G. Knepley #endif
678b2fff234SMatthew G. Knepley               }
679b2fff234SMatthew G. Knepley             } else {
680b2fff234SMatthew G. Knepley               if (zp < 0) { /* back */
681b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
682b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
683b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
684b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
685b2fff234SMatthew G. Knepley                   }
686b2fff234SMatthew G. Knepley                 }
687b2fff234SMatthew G. Knepley #if 0
688b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
689b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
690b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
691b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
692b2fff234SMatthew G. Knepley                 }
693b2fff234SMatthew G. Knepley #endif
694b2fff234SMatthew G. Knepley               } else if (zp > 0) { /* front */
695b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
696b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
697b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
698b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
699b2fff234SMatthew G. Knepley                   }
700b2fff234SMatthew G. Knepley                 }
701b2fff234SMatthew G. Knepley #if 0
702b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
703b2fff234SMatthew G. Knepley                   /* THIS IS WRONG */
704b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
705b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
706b2fff234SMatthew G. Knepley                 }
707b2fff234SMatthew G. Knepley #endif
708b2fff234SMatthew G. Knepley               } else {
709b2fff234SMatthew G. Knepley                 /* Nothing is shared from the interior */
71088ed4aceSMatthew G Knepley               }
71188ed4aceSMatthew G Knepley             }
71288ed4aceSMatthew G Knepley           }
71388ed4aceSMatthew G Knepley         }
71488ed4aceSMatthew G Knepley       }
715b2fff234SMatthew G. Knepley     }
716b2fff234SMatthew G. Knepley   }
717b2fff234SMatthew G. Knepley   ierr = PetscBTMemzero(pEnd-pStart, isLeaf);CHKERRQ(ierr);
718dcca6d9dSJed Brown   ierr = PetscMalloc2(nleaves,&localPoints,nleaves,&remotePoints);CHKERRQ(ierr);
71988ed4aceSMatthew G Knepley   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
72088ed4aceSMatthew G Knepley     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
72188ed4aceSMatthew G Knepley       for (xn = 0; xn < 3; ++xn) {
7227128ae9fSMatthew G Knepley         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
72388ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
724f5eeb527SMatthew G Knepley         PetscInt       xv, yv, zv;
72588ed4aceSMatthew G Knepley 
7263814d604SMatthew G Knepley         if (neighbor >= 0 && neighbor < rank) {
72788ed4aceSMatthew G Knepley           if (xp < 0) { /* left */
72888ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
72988ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
730b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
731f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
732f5eeb527SMatthew G Knepley 
733b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
734f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
735f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
736f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
737f5eeb527SMatthew G Knepley                   ++nL;
738b2fff234SMatthew G. Knepley                 }
73988ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
740b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
741f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
742f5eeb527SMatthew G Knepley 
743b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
744f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
745f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
746f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
747f5eeb527SMatthew G Knepley                   ++nL;
748b2fff234SMatthew G. Knepley                 }
74988ed4aceSMatthew G Knepley               } else {
750b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
751b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
752f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
753f5eeb527SMatthew G Knepley 
754b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
755f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
756f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
757f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
758b2fff234SMatthew G. Knepley                     ++nL;
759b2fff234SMatthew G. Knepley                   }
760f5eeb527SMatthew G Knepley                 }
76188ed4aceSMatthew G Knepley               }
76288ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
76388ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
764b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
765f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
766f5eeb527SMatthew G Knepley 
767b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
768f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
769f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
770f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
771f5eeb527SMatthew G Knepley                   ++nL;
772b2fff234SMatthew G. Knepley                 }
77388ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
774b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
775f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
776f5eeb527SMatthew G Knepley 
777b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
778f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
779f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
780f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
781f5eeb527SMatthew G Knepley                   ++nL;
782b2fff234SMatthew G. Knepley                 }
78388ed4aceSMatthew G Knepley               } else {
784b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
785b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
786f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
787f5eeb527SMatthew G Knepley 
788b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
789f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
790f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
791f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
792b2fff234SMatthew G. Knepley                     ++nL;
793b2fff234SMatthew G. Knepley                   }
794f5eeb527SMatthew G Knepley                 }
79588ed4aceSMatthew G Knepley               }
79688ed4aceSMatthew G Knepley             } else {
79788ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
798b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
799b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
800f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
801f5eeb527SMatthew G Knepley 
802b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
803f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
804f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
805f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
806b2fff234SMatthew G. Knepley                     ++nL;
807b2fff234SMatthew G. Knepley                   }
808f5eeb527SMatthew G Knepley                 }
80988ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
810b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
811b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
812f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
813f5eeb527SMatthew G Knepley 
814b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
815f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
816f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
817f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
818b2fff234SMatthew G. Knepley                     ++nL;
819b2fff234SMatthew G. Knepley                   }
820f5eeb527SMatthew G Knepley                 }
82188ed4aceSMatthew G Knepley               } else {
822f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
823b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
824b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
825f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
826f5eeb527SMatthew G Knepley 
827b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
828f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
829f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
830f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
831b2fff234SMatthew G. Knepley                       ++nL;
832f5eeb527SMatthew G Knepley                     }
833f5eeb527SMatthew G Knepley                   }
834b2fff234SMatthew G. Knepley                 }
835b2fff234SMatthew G. Knepley #if 0
836b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
837f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
838b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
839f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
840f5eeb527SMatthew G Knepley 
841b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
842f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
843f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
844f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
845f5eeb527SMatthew G Knepley                   }
84688ed4aceSMatthew G Knepley                 }
847b2fff234SMatthew G. Knepley #endif
848b2fff234SMatthew G. Knepley               }
84988ed4aceSMatthew G Knepley             }
85088ed4aceSMatthew G Knepley           } else if (xp > 0) { /* right */
85188ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
85288ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
853b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
854f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
855f5eeb527SMatthew G Knepley 
856b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
857f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
858f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
859f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
860f5eeb527SMatthew G Knepley                   ++nL;
861b2fff234SMatthew G. Knepley                 }
86288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
863b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
864f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
865f5eeb527SMatthew G Knepley 
866b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
867f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
868f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
869f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
870f5eeb527SMatthew G Knepley                   ++nL;
871b2fff234SMatthew G. Knepley                 }
87288ed4aceSMatthew G Knepley               } else {
873b2fff234SMatthew G. Knepley                 nleavesCheck += nVz;
874b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
875b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
876f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
877f5eeb527SMatthew G Knepley 
878b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
879f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
880f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
881f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
882b2fff234SMatthew G. Knepley                     ++nL;
883b2fff234SMatthew G. Knepley                   }
884f5eeb527SMatthew G Knepley                 }
88588ed4aceSMatthew G Knepley               }
88688ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
88788ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
888b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
889f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
890f5eeb527SMatthew G Knepley 
891b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
892f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
893f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
894f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
895f5eeb527SMatthew G Knepley                   ++nL;
896b2fff234SMatthew G. Knepley                 }
89788ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
898b2fff234SMatthew G. Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
899f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
900f5eeb527SMatthew G Knepley 
901b2fff234SMatthew G. Knepley                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
902f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
903f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
904f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
905f5eeb527SMatthew G Knepley                   ++nL;
906b2fff234SMatthew G. Knepley                 }
90788ed4aceSMatthew G Knepley               } else {
908b2fff234SMatthew G. Knepley                 for (zv = 0; zv < nVz; ++zv) {
909b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
910f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
911f5eeb527SMatthew G Knepley 
912b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
913f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
914f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
915f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
916b2fff234SMatthew G. Knepley                     ++nL;
917b2fff234SMatthew G. Knepley                   }
918f5eeb527SMatthew G Knepley                 }
91988ed4aceSMatthew G Knepley               }
92088ed4aceSMatthew G Knepley             } else {
92188ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
922b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
923b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
924f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
925f5eeb527SMatthew G Knepley 
926b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
927f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
928f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
929f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
930b2fff234SMatthew G. Knepley                     ++nL;
931b2fff234SMatthew G. Knepley                   }
932f5eeb527SMatthew G Knepley                 }
93388ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
934b2fff234SMatthew G. Knepley                 for (yv = 0; yv < nVy; ++yv) {
935b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
936f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
937f5eeb527SMatthew G Knepley 
938b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
939f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
940f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
941f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
942b2fff234SMatthew G. Knepley                     ++nL;
943b2fff234SMatthew G. Knepley                   }
944f5eeb527SMatthew G Knepley                 }
94588ed4aceSMatthew G Knepley               } else {
946f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
947b2fff234SMatthew G. Knepley                   for (yv = 0; yv < nVy; ++yv) {
948b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
949f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + 0     + nC; /* TODO: Correct this for neighbor sizes */
950f5eeb527SMatthew G Knepley 
951b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
952f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
953f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
954f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
955b2fff234SMatthew G. Knepley                       ++nL;
956f5eeb527SMatthew G Knepley                     }
957f5eeb527SMatthew G Knepley                   }
958b2fff234SMatthew G. Knepley                 }
959b2fff234SMatthew G. Knepley #if 0
960b2fff234SMatthew G. Knepley                 for (xf = 0; xf < nxF; ++xf) {
961f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
962b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
963f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
964f5eeb527SMatthew G Knepley 
965b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
966f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
967f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
968f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
969b2fff234SMatthew G. Knepley                     ++nL;
970f5eeb527SMatthew G Knepley                   }
97188ed4aceSMatthew G Knepley                 }
972b2fff234SMatthew G. Knepley #endif
973b2fff234SMatthew G. Knepley               }
97488ed4aceSMatthew G Knepley             }
97588ed4aceSMatthew G Knepley           } else {
97688ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
97788ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
978b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
979b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
980f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
981f5eeb527SMatthew G Knepley 
982b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
983f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
984f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
985f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
986b2fff234SMatthew G. Knepley                     ++nL;
987b2fff234SMatthew G. Knepley                   }
988f5eeb527SMatthew G Knepley                 }
98988ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
990b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
991b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
992f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
993f5eeb527SMatthew G Knepley 
994b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
995f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
996f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
997f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
998b2fff234SMatthew G. Knepley                     ++nL;
999b2fff234SMatthew G. Knepley                   }
1000f5eeb527SMatthew G Knepley                 }
100188ed4aceSMatthew G Knepley               } else {
1002f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
1003b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1004b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
1005f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1006f5eeb527SMatthew G Knepley 
1007b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1008f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1009f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1010f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1011b2fff234SMatthew G. Knepley                       ++nL;
1012f5eeb527SMatthew G Knepley                     }
1013f5eeb527SMatthew G Knepley                   }
1014b2fff234SMatthew G. Knepley                 }
1015b2fff234SMatthew G. Knepley #if 0
1016b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
1017f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1018b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
1019f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1020f5eeb527SMatthew G Knepley 
1021b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1022f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1023f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1024f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1025b2fff234SMatthew G. Knepley                     ++nL;
1026f5eeb527SMatthew G Knepley                   }
102788ed4aceSMatthew G Knepley                 }
1028b2fff234SMatthew G. Knepley #endif
1029b2fff234SMatthew G. Knepley               }
103088ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
103188ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
1032b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
1033b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
1034f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1035f5eeb527SMatthew G Knepley 
1036b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1037f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
1038f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1039f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
1040b2fff234SMatthew G. Knepley                     ++nL;
1041b2fff234SMatthew G. Knepley                   }
1042f5eeb527SMatthew G Knepley                 }
104388ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
1044b2fff234SMatthew G. Knepley                 for (xv = 0; xv < nVx; ++xv) {
1045b2fff234SMatthew G. Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
1046f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1047f5eeb527SMatthew G Knepley 
1048b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1049f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
1050f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1051f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
1052b2fff234SMatthew G. Knepley                     ++nL;
1053b2fff234SMatthew G. Knepley                   }
1054f5eeb527SMatthew G Knepley                 }
105588ed4aceSMatthew G Knepley               } else {
1056f5eeb527SMatthew G Knepley                 for (zv = 0; zv < nVz; ++zv) {
1057b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1058b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
1059f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1060f5eeb527SMatthew G Knepley 
1061b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1062f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1063f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1064f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1065b2fff234SMatthew G. Knepley                       ++nL;
1066f5eeb527SMatthew G Knepley                     }
1067f5eeb527SMatthew G Knepley                   }
1068b2fff234SMatthew G. Knepley                 }
1069b2fff234SMatthew G. Knepley #if 0
1070b2fff234SMatthew G. Knepley                 for (yf = 0; yf < nyF; ++yf) {
1071f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1072b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
1073f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1074f5eeb527SMatthew G Knepley 
1075b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1076f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1077f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1078f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1079b2fff234SMatthew G. Knepley                     ++nL;
1080f5eeb527SMatthew G Knepley                   }
108188ed4aceSMatthew G Knepley                 }
1082b2fff234SMatthew G. Knepley #endif
1083b2fff234SMatthew G. Knepley               }
108488ed4aceSMatthew G Knepley             } else {
108588ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
1086f5eeb527SMatthew G Knepley                 for (yv = 0; yv < nVy; ++yv) {
1087b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1088b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
1089f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1090f5eeb527SMatthew G Knepley 
1091b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1092f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1093f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1094f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1095b2fff234SMatthew G. Knepley                       ++nL;
1096f5eeb527SMatthew G Knepley                     }
1097f5eeb527SMatthew G Knepley                   }
1098b2fff234SMatthew G. Knepley                 }
1099b2fff234SMatthew G. Knepley #if 0
1100b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
1101f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1102b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
1103f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1104f5eeb527SMatthew G Knepley 
1105b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1106f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1107f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1108f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1109b2fff234SMatthew G. Knepley                     ++nL;
1110f5eeb527SMatthew G Knepley                   }
1111b2fff234SMatthew G. Knepley                 }
1112b2fff234SMatthew G. Knepley #endif
111388ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
1114f5eeb527SMatthew G Knepley                 for (yv = 0; yv < nVy; ++yv) {
1115b2fff234SMatthew G. Knepley                   for (xv = 0; xv < nVx; ++xv) {
1116b2fff234SMatthew G. Knepley                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
1117f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (      0*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
1118f5eeb527SMatthew G Knepley 
1119b2fff234SMatthew G. Knepley                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1120f5eeb527SMatthew G Knepley                       localPoints[nL]        = localVertex;
1121f5eeb527SMatthew G Knepley                       remotePoints[nL].rank  = neighbor;
1122f5eeb527SMatthew G Knepley                       remotePoints[nL].index = remoteVertex;
1123b2fff234SMatthew G. Knepley                       ++nL;
1124f5eeb527SMatthew G Knepley                     }
1125f5eeb527SMatthew G Knepley                   }
1126b2fff234SMatthew G. Knepley                 }
1127b2fff234SMatthew G. Knepley #if 0
1128b2fff234SMatthew G. Knepley                 for (zf = 0; zf < nzF; ++zf) {
1129f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
1130b2fff234SMatthew G. Knepley                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
1131f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
1132f5eeb527SMatthew G Knepley 
1133b2fff234SMatthew G. Knepley                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1134f5eeb527SMatthew G Knepley                     localPoints[nL]        = localFace;
1135f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
1136f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteFace;
1137b2fff234SMatthew G. Knepley                     ++nL;
1138f5eeb527SMatthew G Knepley                   }
1139b2fff234SMatthew G. Knepley                 }
1140b2fff234SMatthew G. Knepley #endif
114188ed4aceSMatthew G Knepley               } else {
114288ed4aceSMatthew G Knepley                 /* Nothing is shared from the interior */
114388ed4aceSMatthew G Knepley               }
114488ed4aceSMatthew G Knepley             }
114588ed4aceSMatthew G Knepley           }
114688ed4aceSMatthew G Knepley         }
114788ed4aceSMatthew G Knepley       }
114888ed4aceSMatthew G Knepley     }
114988ed4aceSMatthew G Knepley   }
1150b2fff234SMatthew G. Knepley   ierr = PetscBTDestroy(&isLeaf);CHKERRQ(ierr);
1151b2fff234SMatthew G. Knepley   /* Remove duplication in leaf determination */
1152b2fff234SMatthew 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);
115382f516ccSBarry Smith   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf);CHKERRQ(ierr);
115488ed4aceSMatthew G Knepley   ierr = PetscSFSetGraph(sf, pEnd, nleaves, localPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
1155a4b60ecfSMatthew G. Knepley   ierr = DMSetPointSF(dm, sf);CHKERRQ(ierr);
115688ed4aceSMatthew G Knepley   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1157affa55c7SMatthew G. Knepley   *s = section;
1158affa55c7SMatthew G. Knepley   PetscFunctionReturn(0);
1159affa55c7SMatthew G. Knepley }
1160affa55c7SMatthew G. Knepley 
11613385ff7eSMatthew G. Knepley #undef __FUNCT__
11623385ff7eSMatthew G. Knepley #define __FUNCT__ "DMDASetVertexCoordinates"
11633385ff7eSMatthew G. Knepley PetscErrorCode DMDASetVertexCoordinates(DM dm, PetscReal xl, PetscReal xu, PetscReal yl, PetscReal yu, PetscReal zl, PetscReal zu)
11643385ff7eSMatthew G. Knepley {
11653385ff7eSMatthew G. Knepley   DM_DA         *da = (DM_DA *) dm->data;
11663385ff7eSMatthew G. Knepley   Vec            coordinates;
11673385ff7eSMatthew G. Knepley   PetscSection   section;
11683385ff7eSMatthew G. Knepley   PetscScalar   *coords;
11693385ff7eSMatthew G. Knepley   PetscReal      h[3];
11703385ff7eSMatthew G. Knepley   PetscInt       dim, size, M, N, P, nVx, nVy, nVz, nV, vStart, vEnd, v, i, j, k;
11713385ff7eSMatthew G. Knepley   PetscErrorCode ierr;
11723385ff7eSMatthew G. Knepley 
11733385ff7eSMatthew G. Knepley   PetscFunctionBegin;
11743385ff7eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11753385ff7eSMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
11763385ff7eSMatthew G. Knepley   h[0] = (xu - xl)/M;
11773385ff7eSMatthew G. Knepley   h[1] = (yu - yl)/N;
11783385ff7eSMatthew G. Knepley   h[2] = (zu - zl)/P;
11793385ff7eSMatthew G. Knepley   ierr = DMDAGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
11803385ff7eSMatthew G. Knepley   ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
11813385ff7eSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
11823385ff7eSMatthew G. Knepley   ierr = PetscSectionSetNumFields(section, 1);CHKERRQ(ierr);
11833385ff7eSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(section, 0, dim);CHKERRQ(ierr);
11843385ff7eSMatthew G. Knepley   ierr = PetscSectionSetChart(section, vStart, vEnd);CHKERRQ(ierr);
11853385ff7eSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
11863385ff7eSMatthew G. Knepley     ierr = PetscSectionSetDof(section, v, dim);CHKERRQ(ierr);
11873385ff7eSMatthew G. Knepley   }
11883385ff7eSMatthew G. Knepley   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
11893385ff7eSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
11903385ff7eSMatthew G. Knepley   ierr = VecCreateSeq(PETSC_COMM_SELF, size, &coordinates);CHKERRQ(ierr);
11913385ff7eSMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
11923385ff7eSMatthew G. Knepley   for (k = 0; k < nVz; ++k) {
1193e4d69e08SBarry Smith     PetscInt ind[3], d, off;
11943385ff7eSMatthew G. Knepley 
1195e4d69e08SBarry Smith     ind[0] = 0;
1196e4d69e08SBarry Smith     ind[1] = 0;
1197e4d69e08SBarry Smith     ind[2] = k + da->zs;
11983385ff7eSMatthew G. Knepley     for (j = 0; j < nVy; ++j) {
11993385ff7eSMatthew G. Knepley       ind[1] = j + da->ys;
12003385ff7eSMatthew G. Knepley       for (i = 0; i < nVx; ++i) {
12013385ff7eSMatthew G. Knepley         const PetscInt vertex = (k*nVy + j)*nVx + i + vStart;
12023385ff7eSMatthew G. Knepley 
12033385ff7eSMatthew G. Knepley         ierr = PetscSectionGetOffset(section, vertex, &off);CHKERRQ(ierr);
12043385ff7eSMatthew G. Knepley         ind[0] = i + da->xs;
12053385ff7eSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
12063385ff7eSMatthew G. Knepley           coords[off+d] = h[d]*ind[d];
12073385ff7eSMatthew G. Knepley         }
12083385ff7eSMatthew G. Knepley       }
12093385ff7eSMatthew G. Knepley     }
12103385ff7eSMatthew G. Knepley   }
12113385ff7eSMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
12123385ff7eSMatthew G. Knepley   ierr = DMSetCoordinateSection(dm, section);CHKERRQ(ierr);
12133385ff7eSMatthew G. Knepley   ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr);
1214a4b60ecfSMatthew G. Knepley   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
12153385ff7eSMatthew G. Knepley   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
12163385ff7eSMatthew G. Knepley   PetscFunctionReturn(0);
12173385ff7eSMatthew G. Knepley }
12189a800dd8SMatthew G. Knepley 
12199a800dd8SMatthew G. Knepley #undef __FUNCT__
12209a800dd8SMatthew G. Knepley #define __FUNCT__ "DMDAProjectFunctionLocal"
1221*b7a4d31fSMatthew G. Knepley PetscErrorCode DMDAProjectFunctionLocal(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
12229a800dd8SMatthew G. Knepley {
1223*b7a4d31fSMatthew G. Knepley   PetscProblem    prob;
1224*b7a4d31fSMatthew G. Knepley   PetscFE         fe;
1225*b7a4d31fSMatthew G. Knepley   PetscDualSpace  sp;
12269a800dd8SMatthew G. Knepley   PetscQuadrature q;
12279a800dd8SMatthew G. Knepley   PetscSection    section;
12289a800dd8SMatthew G. Knepley   PetscScalar    *values;
12299a800dd8SMatthew G. Knepley   PetscReal      *v0, *J, *detJ;
1230*b7a4d31fSMatthew G. Knepley   PetscInt        numFields, numComp, numPoints, dim, spDim, totDim, numValues, cStart, cEnd, f, c, v, d;
12319a800dd8SMatthew G. Knepley   PetscErrorCode  ierr;
12329a800dd8SMatthew G. Knepley 
12339a800dd8SMatthew G. Knepley   PetscFunctionBegin;
1234*b7a4d31fSMatthew G. Knepley   ierr = DMGetProblem(dm, &prob);CHKERRQ(ierr);
1235*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
1236*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr);
1237*b7a4d31fSMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
12389a800dd8SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
12399a800dd8SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
12409a800dd8SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
12419a800dd8SMatthew G. Knepley   ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
12429a800dd8SMatthew G. Knepley   ierr = DMDAVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr);
12439a800dd8SMatthew 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);
12449a800dd8SMatthew G. Knepley   ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr);
124521454ff5SMatthew G. Knepley   ierr = PetscQuadratureGetData(q, NULL, &numPoints, NULL, NULL);CHKERRQ(ierr);
124621454ff5SMatthew G. Knepley   ierr = PetscMalloc3(dim*numPoints,&v0,dim*dim*numPoints,&J,numPoints,&detJ);CHKERRQ(ierr);
12479a800dd8SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
12489a800dd8SMatthew G. Knepley     PetscCellGeometry geom;
12499a800dd8SMatthew G. Knepley 
125021454ff5SMatthew G. Knepley     ierr = DMDAComputeCellGeometry(dm, c, q, v0, J, NULL, detJ);CHKERRQ(ierr);
12519a800dd8SMatthew G. Knepley     geom.v0   = v0;
12529a800dd8SMatthew G. Knepley     geom.J    = J;
12539a800dd8SMatthew G. Knepley     geom.detJ = detJ;
12549a800dd8SMatthew G. Knepley     for (f = 0, v = 0; f < numFields; ++f) {
1255c110b1eeSGeoffrey Irving       void * const ctx = ctxs ? ctxs[f] : NULL;
1256*b7a4d31fSMatthew G. Knepley 
1257*b7a4d31fSMatthew G. Knepley       ierr = PetscProblemGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr);
1258*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr);
1259*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetDualSpace(fe, &sp);CHKERRQ(ierr);
1260*b7a4d31fSMatthew G. Knepley       ierr = PetscDualSpaceGetDimension(sp, &spDim);CHKERRQ(ierr);
12619a800dd8SMatthew G. Knepley       for (d = 0; d < spDim; ++d) {
1262*b7a4d31fSMatthew G. Knepley         ierr = PetscDualSpaceApply(sp, d, geom, numComp, funcs[f], ctx, &values[v]);CHKERRQ(ierr);
12639a800dd8SMatthew G. Knepley         v += numComp;
12649a800dd8SMatthew G. Knepley       }
12659a800dd8SMatthew G. Knepley     }
12669a800dd8SMatthew G. Knepley     ierr = DMDAVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr);
12679a800dd8SMatthew G. Knepley   }
12689a800dd8SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr);
12699a800dd8SMatthew G. Knepley   ierr = PetscFree3(v0,J,detJ);CHKERRQ(ierr);
12709a800dd8SMatthew G. Knepley   PetscFunctionReturn(0);
12719a800dd8SMatthew G. Knepley }
12729a800dd8SMatthew G. Knepley 
12739a800dd8SMatthew G. Knepley #undef __FUNCT__
12749a800dd8SMatthew G. Knepley #define __FUNCT__ "DMDAProjectFunction"
12759a800dd8SMatthew G. Knepley /*@C
12769a800dd8SMatthew G. Knepley   DMDAProjectFunction - This projects the given function into the function space provided.
12779a800dd8SMatthew G. Knepley 
12789a800dd8SMatthew G. Knepley   Input Parameters:
12799a800dd8SMatthew G. Knepley + dm      - The DM
12809a800dd8SMatthew G. Knepley . funcs   - The coordinate functions to evaluate
1281c110b1eeSGeoffrey Irving . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
12829a800dd8SMatthew G. Knepley - mode    - The insertion mode for values
12839a800dd8SMatthew G. Knepley 
12849a800dd8SMatthew G. Knepley   Output Parameter:
12859a800dd8SMatthew G. Knepley . X - vector
12869a800dd8SMatthew G. Knepley 
12879a800dd8SMatthew G. Knepley   Level: developer
12889a800dd8SMatthew G. Knepley 
12899a800dd8SMatthew G. Knepley .seealso: DMDAComputeL2Diff()
12909a800dd8SMatthew G. Knepley @*/
1291*b7a4d31fSMatthew G. Knepley PetscErrorCode DMDAProjectFunction(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
12929a800dd8SMatthew G. Knepley {
12939a800dd8SMatthew G. Knepley   Vec            localX;
12949a800dd8SMatthew G. Knepley   PetscErrorCode ierr;
12959a800dd8SMatthew G. Knepley 
12969a800dd8SMatthew G. Knepley   PetscFunctionBegin;
12979a800dd8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12989a800dd8SMatthew G. Knepley   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
1299*b7a4d31fSMatthew G. Knepley   ierr = DMDAProjectFunctionLocal(dm, funcs, ctxs, mode, localX);CHKERRQ(ierr);
13009a800dd8SMatthew G. Knepley   ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
13019a800dd8SMatthew G. Knepley   ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
13029a800dd8SMatthew G. Knepley   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
13039a800dd8SMatthew G. Knepley   PetscFunctionReturn(0);
13049a800dd8SMatthew G. Knepley }
13059a800dd8SMatthew G. Knepley 
13069a800dd8SMatthew G. Knepley #undef __FUNCT__
13079a800dd8SMatthew G. Knepley #define __FUNCT__ "DMDAComputeL2Diff"
13089a800dd8SMatthew G. Knepley /*@C
13099a800dd8SMatthew G. Knepley   DMDAComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
13109a800dd8SMatthew G. Knepley 
13119a800dd8SMatthew G. Knepley   Input Parameters:
13129a800dd8SMatthew G. Knepley + dm    - The DM
13139a800dd8SMatthew G. Knepley . funcs - The functions to evaluate for each field component
1314c110b1eeSGeoffrey Irving . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
13159a800dd8SMatthew G. Knepley - X     - The coefficient vector u_h
13169a800dd8SMatthew G. Knepley 
13179a800dd8SMatthew G. Knepley   Output Parameter:
13189a800dd8SMatthew G. Knepley . diff - The diff ||u - u_h||_2
13199a800dd8SMatthew G. Knepley 
13209a800dd8SMatthew G. Knepley   Level: developer
13219a800dd8SMatthew G. Knepley 
132223d86601SMatthew G. Knepley .seealso: DMDAProjectFunction(), DMDAComputeL2GradientDiff()
13239a800dd8SMatthew G. Knepley @*/
1324*b7a4d31fSMatthew G. Knepley PetscErrorCode DMDAComputeL2Diff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
13259a800dd8SMatthew G. Knepley {
13269a800dd8SMatthew G. Knepley   const PetscInt  debug = 0;
1327*b7a4d31fSMatthew G. Knepley   PetscProblem    prob;
1328*b7a4d31fSMatthew G. Knepley   PetscFE         fe;
13299a800dd8SMatthew G. Knepley   PetscQuadrature quad;
1330*b7a4d31fSMatthew G. Knepley   PetscSection    section;
13319a800dd8SMatthew G. Knepley   Vec             localX;
13329a800dd8SMatthew G. Knepley   PetscScalar    *funcVal;
13339a800dd8SMatthew G. Knepley   PetscReal      *coords, *v0, *J, *invJ, detJ;
13349a800dd8SMatthew G. Knepley   PetscReal       localDiff = 0.0;
1335*b7a4d31fSMatthew G. Knepley   PetscInt        dim, numFields, Nc, cStart, cEnd, c, field, fieldOffset, comp;
13369a800dd8SMatthew G. Knepley   PetscErrorCode  ierr;
13379a800dd8SMatthew G. Knepley 
13389a800dd8SMatthew G. Knepley   PetscFunctionBegin;
13399a800dd8SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
1340*b7a4d31fSMatthew G. Knepley   ierr = DMGetProblem(dm, &prob);CHKERRQ(ierr);
1341*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetTotalComponents(prob, &Nc);CHKERRQ(ierr);
1342*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr);
1343*b7a4d31fSMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
13449a800dd8SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
13459a800dd8SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
13469a800dd8SMatthew G. Knepley   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
13479a800dd8SMatthew G. Knepley   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
13489a800dd8SMatthew G. Knepley   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
13499a800dd8SMatthew G. Knepley   /* There are no BC values in DAs right now: ierr = DMDAProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */
1350*b7a4d31fSMatthew G. Knepley   ierr = PetscMalloc5(Nc,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
13519a800dd8SMatthew G. Knepley   ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
13529a800dd8SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
13539a800dd8SMatthew G. Knepley     PetscScalar *x = NULL;
13549a800dd8SMatthew G. Knepley     PetscReal    elemDiff = 0.0;
13559a800dd8SMatthew G. Knepley 
135621454ff5SMatthew G. Knepley     ierr = DMDAComputeCellGeometry(dm, c, quad, v0, J, invJ, &detJ);CHKERRQ(ierr);
13579a800dd8SMatthew G. Knepley     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
13589a800dd8SMatthew G. Knepley     ierr = DMDAVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
13599a800dd8SMatthew G. Knepley 
13609a800dd8SMatthew G. Knepley     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
1361c110b1eeSGeoffrey Irving       void * const ctx = ctxs ? ctxs[field] : NULL;
136221454ff5SMatthew G. Knepley       const PetscReal *quadPoints, *quadWeights;
13639a800dd8SMatthew G. Knepley       PetscReal       *basis;
136421454ff5SMatthew G. Knepley       PetscInt         numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f;
13659a800dd8SMatthew G. Knepley 
1366*b7a4d31fSMatthew G. Knepley       ierr = PetscProblemGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
136721454ff5SMatthew G. Knepley       ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr);
1368*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetDimension(fe, &numBasisFuncs);CHKERRQ(ierr);
1369*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetNumComponents(fe, &numBasisComps);CHKERRQ(ierr);
1370*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);CHKERRQ(ierr);
13719a800dd8SMatthew G. Knepley       if (debug) {
13729a800dd8SMatthew G. Knepley         char title[1024];
13739a800dd8SMatthew G. Knepley         ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr);
13749a800dd8SMatthew G. Knepley         ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr);
13759a800dd8SMatthew G. Knepley       }
13769a800dd8SMatthew G. Knepley       for (q = 0; q < numQuadPoints; ++q) {
13779a800dd8SMatthew G. Knepley         for (d = 0; d < dim; d++) {
13789a800dd8SMatthew G. Knepley           coords[d] = v0[d];
13799a800dd8SMatthew G. Knepley           for (e = 0; e < dim; e++) {
13809a800dd8SMatthew G. Knepley             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
13819a800dd8SMatthew G. Knepley           }
13829a800dd8SMatthew G. Knepley         }
1383c110b1eeSGeoffrey Irving         (*funcs[field])(coords, funcVal, ctx);
13849a800dd8SMatthew G. Knepley         for (fc = 0; fc < numBasisComps; ++fc) {
13859a800dd8SMatthew G. Knepley           PetscScalar interpolant = 0.0;
13869a800dd8SMatthew G. Knepley 
13879a800dd8SMatthew G. Knepley           for (f = 0; f < numBasisFuncs; ++f) {
13889a800dd8SMatthew G. Knepley             const PetscInt fidx = f*numBasisComps+fc;
13899a800dd8SMatthew G. Knepley             interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx];
13909a800dd8SMatthew G. Knepley           }
13919a800dd8SMatthew 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);}
13929a800dd8SMatthew G. Knepley           elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ;
13939a800dd8SMatthew G. Knepley         }
13949a800dd8SMatthew G. Knepley       }
13959a800dd8SMatthew G. Knepley       comp        += numBasisComps;
13969a800dd8SMatthew G. Knepley       fieldOffset += numBasisFuncs*numBasisComps;
13979a800dd8SMatthew G. Knepley     }
13989a800dd8SMatthew G. Knepley     ierr = DMDAVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
13999a800dd8SMatthew G. Knepley     if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);}
14009a800dd8SMatthew G. Knepley     localDiff += elemDiff;
14019a800dd8SMatthew G. Knepley   }
14029a800dd8SMatthew G. Knepley   ierr  = PetscFree5(funcVal,coords,v0,J,invJ);CHKERRQ(ierr);
14039a800dd8SMatthew G. Knepley   ierr  = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
14049a800dd8SMatthew G. Knepley   ierr  = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
14059a800dd8SMatthew G. Knepley   *diff = PetscSqrtReal(*diff);
1406a66d4d66SMatthew G Knepley   PetscFunctionReturn(0);
1407a66d4d66SMatthew G Knepley }
1408a66d4d66SMatthew G Knepley 
140923d86601SMatthew G. Knepley #undef __FUNCT__
141023d86601SMatthew G. Knepley #define __FUNCT__ "DMDAComputeL2GradientDiff"
141123d86601SMatthew G. Knepley /*@C
141223d86601SMatthew G. Knepley   DMDAComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
141323d86601SMatthew G. Knepley 
141423d86601SMatthew G. Knepley   Input Parameters:
141523d86601SMatthew G. Knepley + dm    - The DM
141623d86601SMatthew G. Knepley . funcs - The gradient functions to evaluate for each field component
141723d86601SMatthew G. Knepley . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
141823d86601SMatthew G. Knepley . X     - The coefficient vector u_h
141923d86601SMatthew G. Knepley - n     - The vector to project along
142023d86601SMatthew G. Knepley 
142123d86601SMatthew G. Knepley   Output Parameter:
142223d86601SMatthew G. Knepley . diff - The diff ||(grad u - grad u_h) . n||_2
142323d86601SMatthew G. Knepley 
142423d86601SMatthew G. Knepley   Level: developer
142523d86601SMatthew G. Knepley 
142623d86601SMatthew G. Knepley .seealso: DMDAProjectFunction(), DMPlexComputeL2Diff()
142723d86601SMatthew G. Knepley @*/
1428*b7a4d31fSMatthew G. Knepley PetscErrorCode DMDAComputeL2GradientDiff(DM dm, void (**funcs)(const PetscReal [], const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
142923d86601SMatthew G. Knepley {
143023d86601SMatthew G. Knepley   const PetscInt  debug = 0;
1431*b7a4d31fSMatthew G. Knepley   PetscProblem    prob;
1432*b7a4d31fSMatthew G. Knepley   PetscFE         fe;
143323d86601SMatthew G. Knepley   PetscQuadrature quad;
1434*b7a4d31fSMatthew G. Knepley   PetscSection    section;
143523d86601SMatthew G. Knepley   Vec             localX;
143623d86601SMatthew G. Knepley   PetscScalar    *funcVal, *interpolantVec;
143723d86601SMatthew G. Knepley   PetscReal      *coords, *realSpaceDer, *v0, *J, *invJ, detJ;
143823d86601SMatthew G. Knepley   PetscReal       localDiff = 0.0;
1439*b7a4d31fSMatthew G. Knepley   PetscInt        dim, numFields, Nc, cStart, cEnd, c, field, fieldOffset, comp;
144023d86601SMatthew G. Knepley   PetscErrorCode  ierr;
144123d86601SMatthew G. Knepley 
144223d86601SMatthew G. Knepley   PetscFunctionBegin;
144323d86601SMatthew G. Knepley   ierr = DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
1444*b7a4d31fSMatthew G. Knepley   ierr = DMGetProblem(dm, &prob);CHKERRQ(ierr);
1445*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetTotalComponents(prob, &Nc);CHKERRQ(ierr);
1446*b7a4d31fSMatthew G. Knepley   ierr = PetscProblemGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr);
1447*b7a4d31fSMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
144823d86601SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
144923d86601SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
145023d86601SMatthew G. Knepley   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
145123d86601SMatthew G. Knepley   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
145223d86601SMatthew G. Knepley   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
145323d86601SMatthew G. Knepley   /* There are no BC values in DAs right now: ierr = DMDAProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */
1454*b7a4d31fSMatthew G. Knepley   ierr = PetscMalloc7(Nc,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);CHKERRQ(ierr);
145523d86601SMatthew G. Knepley   ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
145623d86601SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
145723d86601SMatthew G. Knepley     PetscScalar *x = NULL;
145823d86601SMatthew G. Knepley     PetscReal    elemDiff = 0.0;
145923d86601SMatthew G. Knepley 
146023d86601SMatthew G. Knepley     ierr = DMDAComputeCellGeometry(dm, c, quad, v0, J, invJ, &detJ);CHKERRQ(ierr);
146123d86601SMatthew G. Knepley     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
146223d86601SMatthew G. Knepley     ierr = DMDAVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
146323d86601SMatthew G. Knepley 
146423d86601SMatthew G. Knepley     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
146523d86601SMatthew G. Knepley       void * const ctx = ctxs ? ctxs[field] : NULL;
146623d86601SMatthew G. Knepley       const PetscReal *quadPoints, *quadWeights;
146723d86601SMatthew G. Knepley       PetscReal       *basisDer;
146823d86601SMatthew G. Knepley       PetscInt         Nq, Nb, Nc, q, d, e, fc, f, g;
146923d86601SMatthew G. Knepley 
1470*b7a4d31fSMatthew G. Knepley       ierr = PetscProblemGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
147123d86601SMatthew G. Knepley       ierr = PetscQuadratureGetData(quad, NULL, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
1472*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
1473*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
1474*b7a4d31fSMatthew G. Knepley       ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr);
147523d86601SMatthew G. Knepley       if (debug) {
147623d86601SMatthew G. Knepley         char title[1024];
147723d86601SMatthew G. Knepley         ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr);
147823d86601SMatthew G. Knepley         ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr);
147923d86601SMatthew G. Knepley       }
148023d86601SMatthew G. Knepley       for (q = 0; q < Nq; ++q) {
148123d86601SMatthew G. Knepley         for (d = 0; d < dim; d++) {
148223d86601SMatthew G. Knepley           coords[d] = v0[d];
148323d86601SMatthew G. Knepley           for (e = 0; e < dim; e++) {
148423d86601SMatthew G. Knepley             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
148523d86601SMatthew G. Knepley           }
148623d86601SMatthew G. Knepley         }
148723d86601SMatthew G. Knepley         (*funcs[field])(coords, n, funcVal, ctx);
148823d86601SMatthew G. Knepley         for (fc = 0; fc < Nc; ++fc) {
148923d86601SMatthew G. Knepley           PetscScalar interpolant = 0.0;
149023d86601SMatthew G. Knepley 
149123d86601SMatthew G. Knepley           for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0;
149223d86601SMatthew G. Knepley           for (f = 0; f < Nb; ++f) {
149323d86601SMatthew G. Knepley             const PetscInt fidx = f*Nc+fc;
149423d86601SMatthew G. Knepley 
149523d86601SMatthew G. Knepley             for (d = 0; d < dim; ++d) {
149623d86601SMatthew G. Knepley               realSpaceDer[d] = 0.0;
149723d86601SMatthew G. Knepley               for (g = 0; g < dim; ++g) {
149823d86601SMatthew G. Knepley                 realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Nc+fidx)*dim+g];
149923d86601SMatthew G. Knepley               }
150023d86601SMatthew G. Knepley               interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d];
150123d86601SMatthew G. Knepley             }
150223d86601SMatthew G. Knepley           }
150323d86601SMatthew G. Knepley           for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d];
150423d86601SMatthew G. Knepley           if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "    elem %d fieldDer %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);}
150523d86601SMatthew G. Knepley           elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ;
150623d86601SMatthew G. Knepley         }
150723d86601SMatthew G. Knepley       }
150823d86601SMatthew G. Knepley       comp        += Nc;
150923d86601SMatthew G. Knepley       fieldOffset += Nb*Nc;
151023d86601SMatthew G. Knepley     }
151123d86601SMatthew G. Knepley     ierr = DMDAVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr);
151223d86601SMatthew G. Knepley     if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);}
151323d86601SMatthew G. Knepley     localDiff += elemDiff;
151423d86601SMatthew G. Knepley   }
151523d86601SMatthew G. Knepley   ierr  = PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);CHKERRQ(ierr);
151623d86601SMatthew G. Knepley   ierr  = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
151723d86601SMatthew G. Knepley   ierr  = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
151823d86601SMatthew G. Knepley   *diff = PetscSqrtReal(*diff);
151923d86601SMatthew G. Knepley   PetscFunctionReturn(0);
152023d86601SMatthew G. Knepley }
152123d86601SMatthew G. Knepley 
152247c6ae99SBarry Smith /* ------------------------------------------------------------------- */
152347c6ae99SBarry Smith 
152447c6ae99SBarry Smith #undef __FUNCT__
1525aa219208SBarry Smith #define __FUNCT__ "DMDAGetArray"
152647c6ae99SBarry Smith /*@C
1527aa219208SBarry Smith      DMDAGetArray - Gets a work array for a DMDA
152847c6ae99SBarry Smith 
152947c6ae99SBarry Smith     Input Parameter:
153047c6ae99SBarry Smith +    da - information about my local patch
153147c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch
153247c6ae99SBarry Smith 
153347c6ae99SBarry Smith     Output Parameters:
153447c6ae99SBarry Smith .    vptr - array data structured
153547c6ae99SBarry Smith 
153647c6ae99SBarry Smith     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
153747c6ae99SBarry Smith            to zero them.
153847c6ae99SBarry Smith 
153947c6ae99SBarry Smith   Level: advanced
154047c6ae99SBarry Smith 
1541bcaeba4dSBarry Smith .seealso: DMDARestoreArray()
154247c6ae99SBarry Smith 
154347c6ae99SBarry Smith @*/
15447087cfbeSBarry Smith PetscErrorCode  DMDAGetArray(DM da,PetscBool ghosted,void *vptr)
154547c6ae99SBarry Smith {
154647c6ae99SBarry Smith   PetscErrorCode ierr;
154747c6ae99SBarry Smith   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
154847c6ae99SBarry Smith   char           *iarray_start;
154947c6ae99SBarry Smith   void           **iptr = (void**)vptr;
155047c6ae99SBarry Smith   DM_DA          *dd    = (DM_DA*)da->data;
155147c6ae99SBarry Smith 
155247c6ae99SBarry Smith   PetscFunctionBegin;
155347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
155447c6ae99SBarry Smith   if (ghosted) {
1555aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
155647c6ae99SBarry Smith       if (dd->arrayghostedin[i]) {
155747c6ae99SBarry Smith         *iptr                 = dd->arrayghostedin[i];
155847c6ae99SBarry Smith         iarray_start          = (char*)dd->startghostedin[i];
15590298fd71SBarry Smith         dd->arrayghostedin[i] = NULL;
15600298fd71SBarry Smith         dd->startghostedin[i] = NULL;
156147c6ae99SBarry Smith 
156247c6ae99SBarry Smith         goto done;
156347c6ae99SBarry Smith       }
156447c6ae99SBarry Smith     }
156547c6ae99SBarry Smith     xs = dd->Xs;
156647c6ae99SBarry Smith     ys = dd->Ys;
156747c6ae99SBarry Smith     zs = dd->Zs;
156847c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
156947c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
157047c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
157147c6ae99SBarry Smith   } else {
1572aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
157347c6ae99SBarry Smith       if (dd->arrayin[i]) {
157447c6ae99SBarry Smith         *iptr          = dd->arrayin[i];
157547c6ae99SBarry Smith         iarray_start   = (char*)dd->startin[i];
15760298fd71SBarry Smith         dd->arrayin[i] = NULL;
15770298fd71SBarry Smith         dd->startin[i] = NULL;
157847c6ae99SBarry Smith 
157947c6ae99SBarry Smith         goto done;
158047c6ae99SBarry Smith       }
158147c6ae99SBarry Smith     }
158247c6ae99SBarry Smith     xs = dd->xs;
158347c6ae99SBarry Smith     ys = dd->ys;
158447c6ae99SBarry Smith     zs = dd->zs;
158547c6ae99SBarry Smith     xm = dd->xe-dd->xs;
158647c6ae99SBarry Smith     ym = dd->ye-dd->ys;
158747c6ae99SBarry Smith     zm = dd->ze-dd->zs;
158847c6ae99SBarry Smith   }
158947c6ae99SBarry Smith 
159047c6ae99SBarry Smith   switch (dd->dim) {
159147c6ae99SBarry Smith   case 1: {
159247c6ae99SBarry Smith     void *ptr;
159347c6ae99SBarry Smith 
1594901f1932SJed Brown     ierr = PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
159547c6ae99SBarry Smith 
159647c6ae99SBarry Smith     ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
159747c6ae99SBarry Smith     *iptr = (void*)ptr;
15988865f1eaSKarl Rupp     break;
15998865f1eaSKarl Rupp   }
160047c6ae99SBarry Smith   case 2: {
160147c6ae99SBarry Smith     void **ptr;
160247c6ae99SBarry Smith 
1603901f1932SJed Brown     ierr = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
160447c6ae99SBarry Smith 
160547c6ae99SBarry Smith     ptr = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
16068865f1eaSKarl Rupp     for (j=ys; j<ys+ym; j++) ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
160747c6ae99SBarry Smith     *iptr = (void*)ptr;
16088865f1eaSKarl Rupp     break;
16098865f1eaSKarl Rupp   }
161047c6ae99SBarry Smith   case 3: {
161147c6ae99SBarry Smith     void ***ptr,**bptr;
161247c6ae99SBarry Smith 
1613901f1932SJed Brown     ierr = PetscMalloc((zm+1)*sizeof(void**)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
161447c6ae99SBarry Smith 
161547c6ae99SBarry Smith     ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
161647c6ae99SBarry Smith     bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
16178865f1eaSKarl Rupp     for (i=zs; i<zs+zm; i++) ptr[i] = bptr + ((i-zs)*ym - ys);
161847c6ae99SBarry Smith     for (i=zs; i<zs+zm; i++) {
161947c6ae99SBarry Smith       for (j=ys; j<ys+ym; j++) {
162047c6ae99SBarry Smith         ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
162147c6ae99SBarry Smith       }
162247c6ae99SBarry Smith     }
162347c6ae99SBarry Smith     *iptr = (void*)ptr;
16248865f1eaSKarl Rupp     break;
16258865f1eaSKarl Rupp   }
162647c6ae99SBarry Smith   default:
1627ce94432eSBarry Smith     SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
162847c6ae99SBarry Smith   }
162947c6ae99SBarry Smith 
163047c6ae99SBarry Smith done:
163147c6ae99SBarry Smith   /* add arrays to the checked out list */
163247c6ae99SBarry Smith   if (ghosted) {
1633aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
163447c6ae99SBarry Smith       if (!dd->arrayghostedout[i]) {
163547c6ae99SBarry Smith         dd->arrayghostedout[i] = *iptr;
163647c6ae99SBarry Smith         dd->startghostedout[i] = iarray_start;
163747c6ae99SBarry Smith         break;
163847c6ae99SBarry Smith       }
163947c6ae99SBarry Smith     }
164047c6ae99SBarry Smith   } else {
1641aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
164247c6ae99SBarry Smith       if (!dd->arrayout[i]) {
164347c6ae99SBarry Smith         dd->arrayout[i] = *iptr;
164447c6ae99SBarry Smith         dd->startout[i] = iarray_start;
164547c6ae99SBarry Smith         break;
164647c6ae99SBarry Smith       }
164747c6ae99SBarry Smith     }
164847c6ae99SBarry Smith   }
164947c6ae99SBarry Smith   PetscFunctionReturn(0);
165047c6ae99SBarry Smith }
165147c6ae99SBarry Smith 
165247c6ae99SBarry Smith #undef __FUNCT__
1653aa219208SBarry Smith #define __FUNCT__ "DMDARestoreArray"
165447c6ae99SBarry Smith /*@C
1655aa219208SBarry Smith      DMDARestoreArray - Restores an array of derivative types for a DMDA
165647c6ae99SBarry Smith 
165747c6ae99SBarry Smith     Input Parameter:
165847c6ae99SBarry Smith +    da - information about my local patch
165947c6ae99SBarry Smith .    ghosted - do you want arrays for the ghosted or nonghosted patch
166047c6ae99SBarry Smith -    vptr - array data structured to be passed to ad_FormFunctionLocal()
166147c6ae99SBarry Smith 
166247c6ae99SBarry Smith      Level: advanced
166347c6ae99SBarry Smith 
1664bcaeba4dSBarry Smith .seealso: DMDAGetArray()
166547c6ae99SBarry Smith 
166647c6ae99SBarry Smith @*/
16677087cfbeSBarry Smith PetscErrorCode  DMDARestoreArray(DM da,PetscBool ghosted,void *vptr)
166847c6ae99SBarry Smith {
166947c6ae99SBarry Smith   PetscInt i;
167047c6ae99SBarry Smith   void     **iptr = (void**)vptr,*iarray_start = 0;
167147c6ae99SBarry Smith   DM_DA    *dd    = (DM_DA*)da->data;
167247c6ae99SBarry Smith 
167347c6ae99SBarry Smith   PetscFunctionBegin;
167447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
167547c6ae99SBarry Smith   if (ghosted) {
1676aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
167747c6ae99SBarry Smith       if (dd->arrayghostedout[i] == *iptr) {
167847c6ae99SBarry Smith         iarray_start           = dd->startghostedout[i];
16790298fd71SBarry Smith         dd->arrayghostedout[i] = NULL;
16800298fd71SBarry Smith         dd->startghostedout[i] = NULL;
168147c6ae99SBarry Smith         break;
168247c6ae99SBarry Smith       }
168347c6ae99SBarry Smith     }
1684aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
168547c6ae99SBarry Smith       if (!dd->arrayghostedin[i]) {
168647c6ae99SBarry Smith         dd->arrayghostedin[i] = *iptr;
168747c6ae99SBarry Smith         dd->startghostedin[i] = iarray_start;
168847c6ae99SBarry Smith         break;
168947c6ae99SBarry Smith       }
169047c6ae99SBarry Smith     }
169147c6ae99SBarry Smith   } else {
1692aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
169347c6ae99SBarry Smith       if (dd->arrayout[i] == *iptr) {
169447c6ae99SBarry Smith         iarray_start    = dd->startout[i];
16950298fd71SBarry Smith         dd->arrayout[i] = NULL;
16960298fd71SBarry Smith         dd->startout[i] = NULL;
169747c6ae99SBarry Smith         break;
169847c6ae99SBarry Smith       }
169947c6ae99SBarry Smith     }
1700aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
170147c6ae99SBarry Smith       if (!dd->arrayin[i]) {
170247c6ae99SBarry Smith         dd->arrayin[i] = *iptr;
170347c6ae99SBarry Smith         dd->startin[i] = iarray_start;
170447c6ae99SBarry Smith         break;
170547c6ae99SBarry Smith       }
170647c6ae99SBarry Smith     }
170747c6ae99SBarry Smith   }
170847c6ae99SBarry Smith   PetscFunctionReturn(0);
170947c6ae99SBarry Smith }
171047c6ae99SBarry Smith 
1711