Actual source code: dalocal.c

petsc-dev 2014-08-28
Report Typos and Errors
  2: /*
  3:   Code for manipulating distributed regular arrays in parallel.
  4: */

  6: #include <petsc-private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
  7: #include <petscbt.h>
  8: #include <petscsf.h>
  9: #include <petscds.h>
 10: #include <petscfe.h>

 12: /*
 13:    This allows the DMDA vectors to properly tell MATLAB their dimensions
 14: */
 15: #if defined(PETSC_HAVE_MATLAB_ENGINE)
 16: #include <engine.h>   /* MATLAB include file */
 17: #include <mex.h>      /* MATLAB include file */
 20: static PetscErrorCode  VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
 21: {
 23:   PetscInt       n,m;
 24:   Vec            vec = (Vec)obj;
 25:   PetscScalar    *array;
 26:   mxArray        *mat;
 27:   DM             da;

 30:   VecGetDM(vec, &da);
 31:   if (!da) SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
 32:   DMDAGetGhostCorners(da,0,0,0,&m,&n,0);

 34:   VecGetArray(vec,&array);
 35: #if !defined(PETSC_USE_COMPLEX)
 36:   mat = mxCreateDoubleMatrix(m,n,mxREAL);
 37: #else
 38:   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
 39: #endif
 40:   PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));
 41:   PetscObjectName(obj);
 42:   engPutVariable((Engine*)mengine,obj->name,mat);

 44:   VecRestoreArray(vec,&array);
 45:   return(0);
 46: }
 47: #endif


 52: PetscErrorCode  DMCreateLocalVector_DA(DM da,Vec *g)
 53: {
 55:   DM_DA          *dd = (DM_DA*)da->data;

 60:   if (da->defaultSection) {
 61:     DMCreateLocalVector_Section_Private(da,g);
 62:   } else {
 63:     VecCreate(PETSC_COMM_SELF,g);
 64:     VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);
 65:     VecSetBlockSize(*g,dd->w);
 66:     VecSetType(*g,da->vectype);
 67:     VecSetDM(*g, da);
 68: #if defined(PETSC_HAVE_MATLAB_ENGINE)
 69:     if (dd->w == 1  && dd->dim == 2) {
 70:       PetscObjectComposeFunction((PetscObject)*g,"PetscMatlabEnginePut_C",VecMatlabEnginePut_DA2d);
 71:     }
 72: #endif
 73:   }
 74:   return(0);
 75: }

 79: /*@
 80:   DMDAGetNumCells - Get the number of cells in the local piece of the DMDA. This includes ghost cells.

 82:   Input Parameter:
 83: . dm - The DM object

 85:   Output Parameters:
 86: + numCellsX - The number of local cells in the x-direction
 87: . numCellsY - The number of local cells in the y-direction
 88: . numCellsZ - The number of local cells in the z-direction
 89: - numCells - The number of local cells

 91:   Level: developer

 93: .seealso: DMDAGetCellPoint()
 94: @*/
 95: PetscErrorCode DMDAGetNumCells(DM dm, PetscInt *numCellsX, PetscInt *numCellsY, PetscInt *numCellsZ, PetscInt *numCells)
 96: {
 97:   DM_DA         *da  = (DM_DA*) dm->data;
 98:   const PetscInt dim = dm->dim;
 99:   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
100:   const PetscInt nC  = (mx)*(dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);

104:   if (numCellsX) {
106:     *numCellsX = mx;
107:   }
108:   if (numCellsY) {
110:     *numCellsY = my;
111:   }
112:   if (numCellsZ) {
114:     *numCellsZ = mz;
115:   }
116:   if (numCells) {
118:     *numCells = nC;
119:   }
120:   return(0);
121: }

125: /*@
126:   DMDAGetCellPoint - Get the DM point corresponding to the tuple (i, j, k) in the DMDA

128:   Input Parameters:
129: + dm - The DM object
130: - i,j,k - The global indices for the cell

132:   Output Parameters:
133: . point - The local DM point

135:   Level: developer

137: .seealso: DMDAGetNumCells()
138: @*/
139: PetscErrorCode DMDAGetCellPoint(DM dm, PetscInt i, PetscInt j, PetscInt k, PetscInt *point)
140: {
141:   const PetscInt dim = dm->dim;
142:   DMDALocalInfo  info;

148:   DMDAGetLocalInfo(dm, &info);
149:   if (dim > 0) {if ((i < info.gxs) || (i >= info.gxs+info.gxm)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "X index %d not in [%d, %d)", i, info.gxs, info.gxs+info.gxm);}
150:   if (dim > 1) {if ((i < info.gys) || (i >= info.gys+info.gym)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Y index %d not in [%d, %d)", i, info.gys, info.gys+info.gym);}
151:   if (dim > 2) {if ((i < info.gzs) || (i >= info.gzs+info.gzm)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Z index %d not in [%d, %d)", i, info.gzs, info.gzs+info.gzm);}
152:   *point = i + (dim > 1 ? (j + (dim > 2 ? k*info.gym : 0))*info.gxm : 0);
153:   return(0);
154: }

158: PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
159: {
160:   DM_DA          *da = (DM_DA*) dm->data;
161:   const PetscInt dim = dm->dim;
162:   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
163:   const PetscInt nVx = mx+1;
164:   const PetscInt nVy = dim > 1 ? (my+1) : 1;
165:   const PetscInt nVz = dim > 2 ? (mz+1) : 1;
166:   const PetscInt nV  = nVx*nVy*nVz;

169:   if (numVerticesX) {
171:     *numVerticesX = nVx;
172:   }
173:   if (numVerticesY) {
175:     *numVerticesY = nVy;
176:   }
177:   if (numVerticesZ) {
179:     *numVerticesZ = nVz;
180:   }
181:   if (numVertices) {
183:     *numVertices = nV;
184:   }
185:   return(0);
186: }

190: PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
191: {
192:   DM_DA          *da = (DM_DA*) dm->data;
193:   const PetscInt dim = dm->dim;
194:   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
195:   const PetscInt nxF = (dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
196:   const PetscInt nXF = (mx+1)*nxF;
197:   const PetscInt nyF = mx*(dim > 2 ? mz : 1);
198:   const PetscInt nYF = dim > 1 ? (my+1)*nyF : 0;
199:   const PetscInt nzF = mx*(dim > 1 ? my : 0);
200:   const PetscInt nZF = dim > 2 ? (mz+1)*nzF : 0;

203:   if (numXFacesX) {
205:     *numXFacesX = nxF;
206:   }
207:   if (numXFaces) {
209:     *numXFaces = nXF;
210:   }
211:   if (numYFacesY) {
213:     *numYFacesY = nyF;
214:   }
215:   if (numYFaces) {
217:     *numYFaces = nYF;
218:   }
219:   if (numZFacesZ) {
221:     *numZFacesZ = nzF;
222:   }
223:   if (numZFaces) {
225:     *numZFaces = nZF;
226:   }
227:   return(0);
228: }

232: PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PetscInt *pStart, PetscInt *pEnd)
233: {
234:   const PetscInt dim = dm->dim;
235:   PetscInt       nC, nV, nXF, nYF, nZF;

241:   DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);
242:   DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);
243:   DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);
244:   if (height == 0) {
245:     /* Cells */
246:     if (pStart) *pStart = 0;
247:     if (pEnd)   *pEnd   = nC;
248:   } else if (height == 1) {
249:     /* Faces */
250:     if (pStart) *pStart = nC+nV;
251:     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
252:   } else if (height == dim) {
253:     /* Vertices */
254:     if (pStart) *pStart = nC;
255:     if (pEnd)   *pEnd   = nC+nV;
256:   } else if (height < 0) {
257:     /* All points */
258:     if (pStart) *pStart = 0;
259:     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
260:   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of height %d in the DA", height);
261:   return(0);
262: }

266: PetscErrorCode DMDAGetDepthStratum(DM dm, PetscInt depth, PetscInt *pStart, PetscInt *pEnd)
267: {
268:   const PetscInt dim = dm->dim;
269:   PetscInt       nC, nV, nXF, nYF, nZF;

275:   DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);
276:   DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);
277:   DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);
278:   if (depth == dim) {
279:     /* Cells */
280:     if (pStart) *pStart = 0;
281:     if (pEnd)   *pEnd   = nC;
282:   } else if (depth == dim-1) {
283:     /* Faces */
284:     if (pStart) *pStart = nC+nV;
285:     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
286:   } else if (depth == 0) {
287:     /* Vertices */
288:     if (pStart) *pStart = nC;
289:     if (pEnd)   *pEnd   = nC+nV;
290:   } else if (depth < 0) {
291:     /* All points */
292:     if (pStart) *pStart = 0;
293:     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
294:   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of depth %d in the DA", depth);
295:   return(0);
296: }

300: PetscErrorCode DMDAGetConeSize(DM dm, PetscInt p, PetscInt *coneSize)
301: {
302:   const PetscInt dim = dm->dim;
303:   PetscInt       nC, nV, nXF, nYF, nZF;

307:   *coneSize = 0;
308:   DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);
309:   DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);
310:   DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);
311:   switch (dim) {
312:   case 2:
313:     if (p >= 0) {
314:       if (p < nC) {
315:         *coneSize = 4;
316:       } else if (p < nC+nV) {
317:         *coneSize = 0;
318:       } else if (p < nC+nV+nXF+nYF+nZF) {
319:         *coneSize = 2;
320:       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
321:     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
322:     break;
323:   case 3:
324:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
325:     break;
326:   }
327:   return(0);
328: }

332: PetscErrorCode DMDAGetCone(DM dm, PetscInt p, PetscInt *cone[])
333: {
334:   const PetscInt dim = dm->dim;
335:   PetscInt       nCx, nCy, nCz, nC, nVx, nVy, nVz, nV, nxF, nyF, nzF, nXF, nYF, nZF;

339:   if (!cone) {DMGetWorkArray(dm, 6, PETSC_INT, cone);}
340:   DMDAGetNumCells(dm, &nCx, &nCy, &nCz, &nC);
341:   DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);
342:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
343:   switch (dim) {
344:   case 2:
345:     if (p >= 0) {
346:       if (p < nC) {
347:         const PetscInt cy = p / nCx;
348:         const PetscInt cx = p % nCx;

350:         (*cone)[0] = cy*nxF + cx + nC+nV;
351:         (*cone)[1] = cx*nyF + cy + nyF + nC+nV+nXF;
352:         (*cone)[2] = cy*nxF + cx + nxF + nC+nV;
353:         (*cone)[3] = cx*nyF + cy + nC+nV+nXF;
354:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do cell cones");
355:       } else if (p < nC+nV) {
356:       } else if (p < nC+nV+nXF) {
357:         const PetscInt fy = (p - nC+nV) / nxF;
358:         const PetscInt fx = (p - nC+nV) % nxF;

360:         (*cone)[0] = fy*nVx + fx + nC;
361:         (*cone)[1] = fy*nVx + fx + 1 + nC;
362:       } else if (p < nC+nV+nXF+nYF) {
363:         const PetscInt fx = (p - nC+nV+nXF) / nyF;
364:         const PetscInt fy = (p - nC+nV+nXF) % nyF;

366:         (*cone)[0] = fy*nVx + fx + nC;
367:         (*cone)[1] = fy*nVx + fx + nVx + nC;
368:       } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d should be in [0, %d)", p, nC+nV+nXF+nYF+nZF);
369:     } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative point %d is invalid", p);
370:     break;
371:   case 3:
372:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Too lazy to do 3D");
373:     break;
374:   }
375:   return(0);
376: }

380: PetscErrorCode DMDARestoreCone(DM dm, PetscInt p, PetscInt *cone[])
381: {

385:   DMGetWorkArray(dm, 6, PETSC_INT, cone);
386:   return(0);
387: }

391: /*@C
392:   DMDACreateSection - Create a PetscSection inside the DMDA that describes data layout. This allows multiple fields with
393:   different numbers of dofs on vertices, cells, and faces in each direction.

395:   Input Parameters:
396: + dm- The DMDA
397: . numFields - The number of fields
398: . numComp - The number of components in each field
399: . numDof - The number of dofs per dimension for each field
400: . numFaceDof - The number of dofs per face for each field and direction, or NULL

402:   Level: developer

404:   Note:
405:   The default DMDA numbering is as follows:

407:     - Cells:    [0,             nC)
408:     - Vertices: [nC,            nC+nV)
409:     - X-Faces:  [nC+nV,         nC+nV+nXF)         normal is +- x-dir
410:     - Y-Faces:  [nC+nV+nXF,     nC+nV+nXF+nYF)     normal is +- y-dir
411:     - Z-Faces:  [nC+nV+nXF+nYF, nC+nV+nXF+nYF+nZF) normal is +- z-dir

413:   We interpret the default DMDA partition as a cell partition, and the data assignment as a cell assignment.
414: @*/
415: PetscErrorCode DMDACreateSection(DM dm, const PetscInt numComp[], const PetscInt numDof[], const PetscInt numFaceDof[], PetscSection *s)
416: {
417:   PetscSection      section;
418:   const PetscInt    dim = dm->dim;
419:   PetscInt          numFields, numVertexTotDof = 0, numCellTotDof = 0, numFaceTotDof[3] = {0, 0, 0};
420:   PetscBT           isLeaf;
421:   PetscSF           sf;
422:   PetscMPIInt       rank;
423:   const PetscMPIInt *neighbors;
424:   PetscInt          *localPoints;
425:   PetscSFNode       *remotePoints;
426:   PetscInt          nleaves = 0,  nleavesCheck = 0, nL = 0;
427:   PetscInt          nC, nVx, nVy, nVz, nV, nxF, nXF, nyF, nYF, nzF, nZF;
428:   PetscInt          pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart, zfEnd;
429:   PetscInt          f, v, c, xf, yf, zf, xn, yn, zn;
430:   PetscErrorCode    ierr;

435:   MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
436:   DMDAGetNumCells(dm, NULL, NULL, NULL, &nC);
437:   DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);
438:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
439:   DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);
440:   DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);
441:   DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);
442:   DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);
443:   xfStart = vEnd;  xfEnd = xfStart+nXF;
444:   yfStart = xfEnd; yfEnd = yfStart+nYF;
445:   zfStart = yfEnd; zfEnd = zfStart+nZF;
446:   if (zfEnd != fEnd) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid face end %d, should be %d", zfEnd, fEnd);
447:   /* Create local section */
448:   DMDAGetInfo(dm, 0,0,0,0,0,0,0, &numFields, 0,0,0,0,0);
449:   for (f = 0; f < numFields; ++f) {
450:     numVertexTotDof  += numDof[f*(dim+1)+0];
451:     numCellTotDof    += numDof[f*(dim+1)+dim];
452:     numFaceTotDof[0] += dim > 0 ? (numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]) : 0;
453:     numFaceTotDof[1] += dim > 1 ? (numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]) : 0;
454:     numFaceTotDof[2] += dim > 2 ? (numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]) : 0;
455:   }
456:   PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);
457:   if (numFields > 0) {
458:     PetscSectionSetNumFields(section, numFields);
459:     for (f = 0; f < numFields; ++f) {
460:       const char *name;

462:       DMDAGetFieldName(dm, f, &name);
463:       PetscSectionSetFieldName(section, f, name ? name : "Field");
464:       if (numComp) {
465:         PetscSectionSetFieldComponents(section, f, numComp[f]);
466:       }
467:     }
468:   }
469:   PetscSectionSetChart(section, pStart, pEnd);
470:   for (v = vStart; v < vEnd; ++v) {
471:     for (f = 0; f < numFields; ++f) {
472:       PetscSectionSetFieldDof(section, v, f, numDof[f*(dim+1)+0]);
473:     }
474:     PetscSectionSetDof(section, v, numVertexTotDof);
475:   }
476:   for (xf = xfStart; xf < xfEnd; ++xf) {
477:     for (f = 0; f < numFields; ++f) {
478:       PetscSectionSetFieldDof(section, xf, f, numFaceDof ? numFaceDof[f*dim+0] : numDof[f*(dim+1)+dim-1]);
479:     }
480:     PetscSectionSetDof(section, xf, numFaceTotDof[0]);
481:   }
482:   for (yf = yfStart; yf < yfEnd; ++yf) {
483:     for (f = 0; f < numFields; ++f) {
484:       PetscSectionSetFieldDof(section, yf, f, numFaceDof ? numFaceDof[f*dim+1] : numDof[f*(dim+1)+dim-1]);
485:     }
486:     PetscSectionSetDof(section, yf, numFaceTotDof[1]);
487:   }
488:   for (zf = zfStart; zf < zfEnd; ++zf) {
489:     for (f = 0; f < numFields; ++f) {
490:       PetscSectionSetFieldDof(section, zf, f, numFaceDof ? numFaceDof[f*dim+2] : numDof[f*(dim+1)+dim-1]);
491:     }
492:     PetscSectionSetDof(section, zf, numFaceTotDof[2]);
493:   }
494:   for (c = cStart; c < cEnd; ++c) {
495:     for (f = 0; f < numFields; ++f) {
496:       PetscSectionSetFieldDof(section, c, f, numDof[f*(dim+1)+dim]);
497:     }
498:     PetscSectionSetDof(section, c, numCellTotDof);
499:   }
500:   PetscSectionSetUp(section);
501:   /* Create mesh point SF */
502:   PetscBTCreate(pEnd-pStart, &isLeaf);
503:   DMDAGetNeighbors(dm, &neighbors);
504:   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
505:     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
506:       for (xn = 0; xn < 3; ++xn) {
507:         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
508:         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
509:         PetscInt       xv, yv, zv;

511:         if (neighbor >= 0 && neighbor < rank) {
512:           if (xp < 0) { /* left */
513:             if (yp < 0) { /* bottom */
514:               if (zp < 0) { /* back */
515:                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
516:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
517:               } else if (zp > 0) { /* front */
518:                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
519:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
520:               } else {
521:                 for (zv = 0; zv < nVz; ++zv) {
522:                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
523:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
524:                 }
525:               }
526:             } else if (yp > 0) { /* top */
527:               if (zp < 0) { /* back */
528:                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
529:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
530:               } else if (zp > 0) { /* front */
531:                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
532:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
533:               } else {
534:                 for (zv = 0; zv < nVz; ++zv) {
535:                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
536:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
537:                 }
538:               }
539:             } else {
540:               if (zp < 0) { /* back */
541:                 for (yv = 0; yv < nVy; ++yv) {
542:                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
543:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
544:                 }
545:               } else if (zp > 0) { /* front */
546:                 for (yv = 0; yv < nVy; ++yv) {
547:                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
548:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
549:                 }
550:               } else {
551:                 for (zv = 0; zv < nVz; ++zv) {
552:                   for (yv = 0; yv < nVy; ++yv) {
553:                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
554:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
555:                   }
556:                 }
557: #if 0
558:                 for (xf = 0; xf < nxF; ++xf) {
559:                   /* THIS IS WRONG */
560:                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
561:                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
562:                 }
563: #endif
564:               }
565:             }
566:           } else if (xp > 0) { /* right */
567:             if (yp < 0) { /* bottom */
568:               if (zp < 0) { /* back */
569:                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
570:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
571:               } else if (zp > 0) { /* front */
572:                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
573:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
574:               } else {
575:                 for (zv = 0; zv < nVz; ++zv) {
576:                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
577:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
578:                 }
579:               }
580:             } else if (yp > 0) { /* top */
581:               if (zp < 0) { /* back */
582:                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
583:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
584:               } else if (zp > 0) { /* front */
585:                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
586:                 if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
587:               } else {
588:                 for (zv = 0; zv < nVz; ++zv) {
589:                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
590:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
591:                 }
592:               }
593:             } else {
594:               if (zp < 0) { /* back */
595:                 for (yv = 0; yv < nVy; ++yv) {
596:                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
597:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
598:                 }
599:               } else if (zp > 0) { /* front */
600:                 for (yv = 0; yv < nVy; ++yv) {
601:                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
602:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
603:                 }
604:               } else {
605:                 for (zv = 0; zv < nVz; ++zv) {
606:                   for (yv = 0; yv < nVy; ++yv) {
607:                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
608:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
609:                   }
610:                 }
611: #if 0
612:                 for (xf = 0; xf < nxF; ++xf) {
613:                   /* THIS IS WRONG */
614:                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
615:                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
616:                 }
617: #endif
618:               }
619:             }
620:           } else {
621:             if (yp < 0) { /* bottom */
622:               if (zp < 0) { /* back */
623:                 for (xv = 0; xv < nVx; ++xv) {
624:                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
625:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
626:                 }
627:               } else if (zp > 0) { /* front */
628:                 for (xv = 0; xv < nVx; ++xv) {
629:                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
630:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
631:                 }
632:               } else {
633:                 for (zv = 0; zv < nVz; ++zv) {
634:                   for (xv = 0; xv < nVx; ++xv) {
635:                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
636:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
637:                   }
638:                 }
639: #if 0
640:                 for (yf = 0; yf < nyF; ++yf) {
641:                   /* THIS IS WRONG */
642:                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
643:                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
644:                 }
645: #endif
646:               }
647:             } else if (yp > 0) { /* top */
648:               if (zp < 0) { /* back */
649:                 for (xv = 0; xv < nVx; ++xv) {
650:                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
651:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
652:                 }
653:               } else if (zp > 0) { /* front */
654:                 for (xv = 0; xv < nVx; ++xv) {
655:                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
656:                   if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
657:                 }
658:               } else {
659:                 for (zv = 0; zv < nVz; ++zv) {
660:                   for (xv = 0; xv < nVx; ++xv) {
661:                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
662:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
663:                   }
664:                 }
665: #if 0
666:                 for (yf = 0; yf < nyF; ++yf) {
667:                   /* THIS IS WRONG */
668:                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
669:                   if (!PetscBTLookupSet(isLeaf, localVFace)) ++nleaves;
670:                 }
671: #endif
672:               }
673:             } else {
674:               if (zp < 0) { /* back */
675:                 for (yv = 0; yv < nVy; ++yv) {
676:                   for (xv = 0; xv < nVx; ++xv) {
677:                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
678:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
679:                   }
680:                 }
681: #if 0
682:                 for (zf = 0; zf < nzF; ++zf) {
683:                   /* THIS IS WRONG */
684:                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
685:                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
686:                 }
687: #endif
688:               } else if (zp > 0) { /* front */
689:                 for (yv = 0; yv < nVy; ++yv) {
690:                   for (xv = 0; xv < nVx; ++xv) {
691:                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
692:                     if (!PetscBTLookupSet(isLeaf, localVertex)) ++nleaves;
693:                   }
694:                 }
695: #if 0
696:                 for (zf = 0; zf < nzF; ++zf) {
697:                   /* THIS IS WRONG */
698:                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
699:                   if (!PetscBTLookupSet(isLeaf, localFace)) ++nleaves;
700:                 }
701: #endif
702:               } else {
703:                 /* Nothing is shared from the interior */
704:               }
705:             }
706:           }
707:         }
708:       }
709:     }
710:   }
711:   PetscBTMemzero(pEnd-pStart, isLeaf);
712:   PetscMalloc2(nleaves,&localPoints,nleaves,&remotePoints);
713:   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
714:     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
715:       for (xn = 0; xn < 3; ++xn) {
716:         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
717:         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
718:         PetscInt       xv, yv, zv;

720:         if (neighbor >= 0 && neighbor < rank) {
721:           if (xp < 0) { /* left */
722:             if (yp < 0) { /* bottom */
723:               if (zp < 0) { /* back */
724:                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC; /* left bottom back vertex */
725:                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

727:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
728:                   localPoints[nL]        = localVertex;
729:                   remotePoints[nL].rank  = neighbor;
730:                   remotePoints[nL].index = remoteVertex;
731:                   ++nL;
732:                 }
733:               } else if (zp > 0) { /* front */
734:                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* left bottom front vertex */
735:                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

737:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
738:                   localPoints[nL]        = localVertex;
739:                   remotePoints[nL].rank  = neighbor;
740:                   remotePoints[nL].index = remoteVertex;
741:                   ++nL;
742:                 }
743:               } else {
744:                 for (zv = 0; zv < nVz; ++zv) {
745:                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC; /* left bottom vertices */
746:                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

748:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
749:                     localPoints[nL]        = localVertex;
750:                     remotePoints[nL].rank  = neighbor;
751:                     remotePoints[nL].index = remoteVertex;
752:                     ++nL;
753:                   }
754:                 }
755:               }
756:             } else if (yp > 0) { /* top */
757:               if (zp < 0) { /* back */
758:                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC; /* left top back vertex */
759:                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

761:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
762:                   localPoints[nL]        = localVertex;
763:                   remotePoints[nL].rank  = neighbor;
764:                   remotePoints[nL].index = remoteVertex;
765:                   ++nL;
766:                 }
767:               } else if (zp > 0) { /* front */
768:                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* left top front vertex */
769:                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

771:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
772:                   localPoints[nL]        = localVertex;
773:                   remotePoints[nL].rank  = neighbor;
774:                   remotePoints[nL].index = remoteVertex;
775:                   ++nL;
776:                 }
777:               } else {
778:                 for (zv = 0; zv < nVz; ++zv) {
779:                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC; /* left top vertices */
780:                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

782:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
783:                     localPoints[nL]        = localVertex;
784:                     remotePoints[nL].rank  = neighbor;
785:                     remotePoints[nL].index = remoteVertex;
786:                     ++nL;
787:                   }
788:                 }
789:               }
790:             } else {
791:               if (zp < 0) { /* back */
792:                 for (yv = 0; yv < nVy; ++yv) {
793:                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC; /* left back vertices */
794:                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

796:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
797:                     localPoints[nL]        = localVertex;
798:                     remotePoints[nL].rank  = neighbor;
799:                     remotePoints[nL].index = remoteVertex;
800:                     ++nL;
801:                   }
802:                 }
803:               } else if (zp > 0) { /* front */
804:                 for (yv = 0; yv < nVy; ++yv) {
805:                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* left front vertices */
806:                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

808:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
809:                     localPoints[nL]        = localVertex;
810:                     remotePoints[nL].rank  = neighbor;
811:                     remotePoints[nL].index = remoteVertex;
812:                     ++nL;
813:                   }
814:                 }
815:               } else {
816:                 for (zv = 0; zv < nVz; ++zv) {
817:                   for (yv = 0; yv < nVy; ++yv) {
818:                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC; /* left vertices */
819:                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */

821:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
822:                       localPoints[nL]        = localVertex;
823:                       remotePoints[nL].rank  = neighbor;
824:                       remotePoints[nL].index = remoteVertex;
825:                       ++nL;
826:                     }
827:                   }
828:                 }
829: #if 0
830:                 for (xf = 0; xf < nxF; ++xf) {
831:                   /* THIS IS WRONG */
832:                   const PetscInt localFace  = 0 + nC+nV; /* left faces */
833:                   const PetscInt remoteFace = 0 + nC+nV;

835:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
836:                     localPoints[nL]        = localFace;
837:                     remotePoints[nL].rank  = neighbor;
838:                     remotePoints[nL].index = remoteFace;
839:                   }
840:                 }
841: #endif
842:               }
843:             }
844:           } else if (xp > 0) { /* right */
845:             if (yp < 0) { /* bottom */
846:               if (zp < 0) { /* back */
847:                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC; /* right bottom back vertex */
848:                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

850:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
851:                   localPoints[nL]        = localVertex;
852:                   remotePoints[nL].rank  = neighbor;
853:                   remotePoints[nL].index = remoteVertex;
854:                   ++nL;
855:                 }
856:               } else if (zp > 0) { /* front */
857:                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* right bottom front vertex */
858:                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

860:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
861:                   localPoints[nL]        = localVertex;
862:                   remotePoints[nL].rank  = neighbor;
863:                   remotePoints[nL].index = remoteVertex;
864:                   ++nL;
865:                 }
866:               } else {
867:                 nleavesCheck += nVz;
868:                 for (zv = 0; zv < nVz; ++zv) {
869:                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC; /* right bottom vertices */
870:                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

872:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
873:                     localPoints[nL]        = localVertex;
874:                     remotePoints[nL].rank  = neighbor;
875:                     remotePoints[nL].index = remoteVertex;
876:                     ++nL;
877:                   }
878:                 }
879:               }
880:             } else if (yp > 0) { /* top */
881:               if (zp < 0) { /* back */
882:                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top back vertex */
883:                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

885:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
886:                   localPoints[nL]        = localVertex;
887:                   remotePoints[nL].rank  = neighbor;
888:                   remotePoints[nL].index = remoteVertex;
889:                   ++nL;
890:                 }
891:               } else if (zp > 0) { /* front */
892:                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top front vertex */
893:                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

895:                 if (!PetscBTLookupSet(isLeaf, localVertex)) {
896:                   localPoints[nL]        = localVertex;
897:                   remotePoints[nL].rank  = neighbor;
898:                   remotePoints[nL].index = remoteVertex;
899:                   ++nL;
900:                 }
901:               } else {
902:                 for (zv = 0; zv < nVz; ++zv) {
903:                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* right top vertices */
904:                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

906:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
907:                     localPoints[nL]        = localVertex;
908:                     remotePoints[nL].rank  = neighbor;
909:                     remotePoints[nL].index = remoteVertex;
910:                     ++nL;
911:                   }
912:                 }
913:               }
914:             } else {
915:               if (zp < 0) { /* back */
916:                 for (yv = 0; yv < nVy; ++yv) {
917:                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC; /* right back vertices */
918:                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

920:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
921:                     localPoints[nL]        = localVertex;
922:                     remotePoints[nL].rank  = neighbor;
923:                     remotePoints[nL].index = remoteVertex;
924:                     ++nL;
925:                   }
926:                 }
927:               } else if (zp > 0) { /* front */
928:                 for (yv = 0; yv < nVy; ++yv) {
929:                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* right front vertices */
930:                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */

932:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
933:                     localPoints[nL]        = localVertex;
934:                     remotePoints[nL].rank  = neighbor;
935:                     remotePoints[nL].index = remoteVertex;
936:                     ++nL;
937:                   }
938:                 }
939:               } else {
940:                 for (zv = 0; zv < nVz; ++zv) {
941:                   for (yv = 0; yv < nVy; ++yv) {
942:                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC; /* right vertices */
943:                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + 0     + nC; /* TODO: Correct this for neighbor sizes */

945:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
946:                       localPoints[nL]        = localVertex;
947:                       remotePoints[nL].rank  = neighbor;
948:                       remotePoints[nL].index = remoteVertex;
949:                       ++nL;
950:                     }
951:                   }
952:                 }
953: #if 0
954:                 for (xf = 0; xf < nxF; ++xf) {
955:                   /* THIS IS WRONG */
956:                   const PetscInt localFace  = 0 + nC+nV; /* right faces */
957:                   const PetscInt remoteFace = 0 + nC+nV;

959:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
960:                     localPoints[nL]        = localFace;
961:                     remotePoints[nL].rank  = neighbor;
962:                     remotePoints[nL].index = remoteFace;
963:                     ++nL;
964:                   }
965:                 }
966: #endif
967:               }
968:             }
969:           } else {
970:             if (yp < 0) { /* bottom */
971:               if (zp < 0) { /* back */
972:                 for (xv = 0; xv < nVx; ++xv) {
973:                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC; /* bottom back vertices */
974:                   const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

976:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
977:                     localPoints[nL]        = localVertex;
978:                     remotePoints[nL].rank  = neighbor;
979:                     remotePoints[nL].index = remoteVertex;
980:                     ++nL;
981:                   }
982:                 }
983:               } else if (zp > 0) { /* front */
984:                 for (xv = 0; xv < nVx; ++xv) {
985:                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* bottom front vertices */
986:                   const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

988:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
989:                     localPoints[nL]        = localVertex;
990:                     remotePoints[nL].rank  = neighbor;
991:                     remotePoints[nL].index = remoteVertex;
992:                     ++nL;
993:                   }
994:                 }
995:               } else {
996:                 for (zv = 0; zv < nVz; ++zv) {
997:                   for (xv = 0; xv < nVx; ++xv) {
998:                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC; /* bottom vertices */
999:                     const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1001:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1002:                       localPoints[nL]        = localVertex;
1003:                       remotePoints[nL].rank  = neighbor;
1004:                       remotePoints[nL].index = remoteVertex;
1005:                       ++nL;
1006:                     }
1007:                   }
1008:                 }
1009: #if 0
1010:                 for (yf = 0; yf < nyF; ++yf) {
1011:                   /* THIS IS WRONG */
1012:                   const PetscInt localFace  = 0 + nC+nV; /* bottom faces */
1013:                   const PetscInt remoteFace = 0 + nC+nV;

1015:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1016:                     localPoints[nL]        = localFace;
1017:                     remotePoints[nL].rank  = neighbor;
1018:                     remotePoints[nL].index = remoteFace;
1019:                     ++nL;
1020:                   }
1021:                 }
1022: #endif
1023:               }
1024:             } else if (yp > 0) { /* top */
1025:               if (zp < 0) { /* back */
1026:                 for (xv = 0; xv < nVx; ++xv) {
1027:                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC; /* top back vertices */
1028:                   const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1030:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1031:                     localPoints[nL]        = localVertex;
1032:                     remotePoints[nL].rank  = neighbor;
1033:                     remotePoints[nL].index = remoteVertex;
1034:                     ++nL;
1035:                   }
1036:                 }
1037:               } else if (zp > 0) { /* front */
1038:                 for (xv = 0; xv < nVx; ++xv) {
1039:                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* top front vertices */
1040:                   const PetscInt remoteVertex = (      0*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1042:                   if (!PetscBTLookupSet(isLeaf, localVertex)) {
1043:                     localPoints[nL]        = localVertex;
1044:                     remotePoints[nL].rank  = neighbor;
1045:                     remotePoints[nL].index = remoteVertex;
1046:                     ++nL;
1047:                   }
1048:                 }
1049:               } else {
1050:                 for (zv = 0; zv < nVz; ++zv) {
1051:                   for (xv = 0; xv < nVx; ++xv) {
1052:                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC; /* top vertices */
1053:                     const PetscInt remoteVertex = (zv*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1055:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1056:                       localPoints[nL]        = localVertex;
1057:                       remotePoints[nL].rank  = neighbor;
1058:                       remotePoints[nL].index = remoteVertex;
1059:                       ++nL;
1060:                     }
1061:                   }
1062:                 }
1063: #if 0
1064:                 for (yf = 0; yf < nyF; ++yf) {
1065:                   /* THIS IS WRONG */
1066:                   const PetscInt localFace  = 0 + nC+nV; /* top faces */
1067:                   const PetscInt remoteFace = 0 + nC+nV;

1069:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1070:                     localPoints[nL]        = localFace;
1071:                     remotePoints[nL].rank  = neighbor;
1072:                     remotePoints[nL].index = remoteFace;
1073:                     ++nL;
1074:                   }
1075:                 }
1076: #endif
1077:               }
1078:             } else {
1079:               if (zp < 0) { /* back */
1080:                 for (yv = 0; yv < nVy; ++yv) {
1081:                   for (xv = 0; xv < nVx; ++xv) {
1082:                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC; /* back vertices */
1083:                     const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1085:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1086:                       localPoints[nL]        = localVertex;
1087:                       remotePoints[nL].rank  = neighbor;
1088:                       remotePoints[nL].index = remoteVertex;
1089:                       ++nL;
1090:                     }
1091:                   }
1092:                 }
1093: #if 0
1094:                 for (zf = 0; zf < nzF; ++zf) {
1095:                   /* THIS IS WRONG */
1096:                   const PetscInt localFace  = 0 + nC+nV; /* back faces */
1097:                   const PetscInt remoteFace = 0 + nC+nV;

1099:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1100:                     localPoints[nL]        = localFace;
1101:                     remotePoints[nL].rank  = neighbor;
1102:                     remotePoints[nL].index = remoteFace;
1103:                     ++nL;
1104:                   }
1105:                 }
1106: #endif
1107:               } else if (zp > 0) { /* front */
1108:                 for (yv = 0; yv < nVy; ++yv) {
1109:                   for (xv = 0; xv < nVx; ++xv) {
1110:                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* front vertices */
1111:                     const PetscInt remoteVertex = (      0*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */

1113:                     if (!PetscBTLookupSet(isLeaf, localVertex)) {
1114:                       localPoints[nL]        = localVertex;
1115:                       remotePoints[nL].rank  = neighbor;
1116:                       remotePoints[nL].index = remoteVertex;
1117:                       ++nL;
1118:                     }
1119:                   }
1120:                 }
1121: #if 0
1122:                 for (zf = 0; zf < nzF; ++zf) {
1123:                   /* THIS IS WRONG */
1124:                   const PetscInt localFace  = 0 + nC+nV; /* front faces */
1125:                   const PetscInt remoteFace = 0 + nC+nV;

1127:                   if (!PetscBTLookupSet(isLeaf, localFace)) {
1128:                     localPoints[nL]        = localFace;
1129:                     remotePoints[nL].rank  = neighbor;
1130:                     remotePoints[nL].index = remoteFace;
1131:                     ++nL;
1132:                   }
1133:                 }
1134: #endif
1135:               } else {
1136:                 /* Nothing is shared from the interior */
1137:               }
1138:             }
1139:           }
1140:         }
1141:       }
1142:     }
1143:   }
1144:   PetscBTDestroy(&isLeaf);
1145:   /* Remove duplication in leaf determination */
1146:   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);
1147:   PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf);
1148:   PetscSFSetGraph(sf, pEnd, nleaves, localPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);
1149:   DMSetPointSF(dm, sf);
1150:   PetscSFDestroy(&sf);
1151:   *s = section;
1152:   return(0);
1153: }

1157: PetscErrorCode DMDASetVertexCoordinates(DM dm, PetscReal xl, PetscReal xu, PetscReal yl, PetscReal yu, PetscReal zl, PetscReal zu)
1158: {
1159:   DM_DA         *da = (DM_DA *) dm->data;
1160:   Vec            coordinates;
1161:   PetscSection   section;
1162:   PetscScalar   *coords;
1163:   PetscReal      h[3];
1164:   PetscInt       dim, size, M, N, P, nVx, nVy, nVz, nV, vStart, vEnd, v, i, j, k;

1169:   DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0,0,0,0,0,0,0);
1170:   h[0] = (xu - xl)/M;
1171:   h[1] = (yu - yl)/N;
1172:   h[2] = (zu - zl)/P;
1173:   DMDAGetDepthStratum(dm, 0, &vStart, &vEnd);
1174:   DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);
1175:   PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);
1176:   PetscSectionSetNumFields(section, 1);
1177:   PetscSectionSetFieldComponents(section, 0, dim);
1178:   PetscSectionSetChart(section, vStart, vEnd);
1179:   for (v = vStart; v < vEnd; ++v) {
1180:     PetscSectionSetDof(section, v, dim);
1181:   }
1182:   PetscSectionSetUp(section);
1183:   PetscSectionGetStorageSize(section, &size);
1184:   VecCreateSeq(PETSC_COMM_SELF, size, &coordinates);
1185:   VecGetArray(coordinates, &coords);
1186:   for (k = 0; k < nVz; ++k) {
1187:     PetscInt ind[3], d, off;

1189:     ind[0] = 0;
1190:     ind[1] = 0;
1191:     ind[2] = k + da->zs;
1192:     for (j = 0; j < nVy; ++j) {
1193:       ind[1] = j + da->ys;
1194:       for (i = 0; i < nVx; ++i) {
1195:         const PetscInt vertex = (k*nVy + j)*nVx + i + vStart;

1197:         PetscSectionGetOffset(section, vertex, &off);
1198:         ind[0] = i + da->xs;
1199:         for (d = 0; d < dim; ++d) {
1200:           coords[off+d] = h[d]*ind[d];
1201:         }
1202:       }
1203:     }
1204:   }
1205:   VecRestoreArray(coordinates, &coords);
1206:   DMSetCoordinateSection(dm, PETSC_DETERMINE, section);
1207:   DMSetCoordinatesLocal(dm, coordinates);
1208:   PetscSectionDestroy(&section);
1209:   VecDestroy(&coordinates);
1210:   return(0);
1211: }

1215: PetscErrorCode DMDAProjectFunctionLocal(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
1216: {
1217:   PetscDS    prob;
1218:   PetscFE         fe;
1219:   PetscDualSpace  sp;
1220:   PetscQuadrature q;
1221:   PetscSection    section;
1222:   PetscScalar    *values;
1223:   PetscReal      *v0, *J, *detJ;
1224:   PetscInt        numFields, numComp, numPoints, dim, spDim, totDim, numValues, cStart, cEnd, f, c, v, d;
1225:   PetscErrorCode  ierr;

1228:   DMGetDS(dm, &prob);
1229:   PetscDSGetTotalDimension(prob, &totDim);
1230:   PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);
1231:   PetscFEGetQuadrature(fe, &q);
1232:   DMGetDefaultSection(dm, &section);
1233:   PetscSectionGetNumFields(section, &numFields);
1234:   DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);
1235:   DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);
1236:   DMDAVecGetClosure(dm, section, localX, cStart, &numValues, NULL);
1237:   if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section cell closure size %d != dual space dimension %d", numValues, totDim);
1238:   DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);
1239:   PetscQuadratureGetData(q, NULL, &numPoints, NULL, NULL);
1240:   PetscMalloc3(dim*numPoints,&v0,dim*dim*numPoints,&J,numPoints,&detJ);
1241:   for (c = cStart; c < cEnd; ++c) {
1242:     PetscCellGeometry geom;

1244:     DMDAComputeCellGeometryFEM(dm, c, q, v0, J, NULL, detJ);
1245:     geom.v0   = v0;
1246:     geom.J    = J;
1247:     geom.detJ = detJ;
1248:     for (f = 0, v = 0; f < numFields; ++f) {
1249:       void * const ctx = ctxs ? ctxs[f] : NULL;

1251:       PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);
1252:       PetscFEGetNumComponents(fe, &numComp);
1253:       PetscFEGetDualSpace(fe, &sp);
1254:       PetscDualSpaceGetDimension(sp, &spDim);
1255:       for (d = 0; d < spDim; ++d) {
1256:         PetscDualSpaceApply(sp, d, geom, numComp, funcs[f], ctx, &values[v]);
1257:         v += numComp;
1258:       }
1259:     }
1260:     DMDAVecSetClosure(dm, section, localX, c, values, mode);
1261:   }
1262:   DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);
1263:   PetscFree3(v0,J,detJ);
1264:   return(0);
1265: }

1269: /*@C
1270:   DMDAProjectFunction - This projects the given function into the function space provided.

1272:   Input Parameters:
1273: + dm      - The DM
1274: . funcs   - The coordinate functions to evaluate
1275: . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
1276: - mode    - The insertion mode for values

1278:   Output Parameter:
1279: . X - vector

1281:   Level: developer

1283: .seealso: DMDAComputeL2Diff()
1284: @*/
1285: PetscErrorCode DMDAProjectFunction(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
1286: {
1287:   Vec            localX;

1292:   DMGetLocalVector(dm, &localX);
1293:   DMDAProjectFunctionLocal(dm, funcs, ctxs, mode, localX);
1294:   DMLocalToGlobalBegin(dm, localX, mode, X);
1295:   DMLocalToGlobalEnd(dm, localX, mode, X);
1296:   DMRestoreLocalVector(dm, &localX);
1297:   return(0);
1298: }

1302: /*@C
1303:   DMDAComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.

1305:   Input Parameters:
1306: + dm    - The DM
1307: . funcs - The functions to evaluate for each field component
1308: . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
1309: - X     - The coefficient vector u_h

1311:   Output Parameter:
1312: . diff - The diff ||u - u_h||_2

1314:   Level: developer

1316: .seealso: DMDAProjectFunction(), DMDAComputeL2GradientDiff()
1317: @*/
1318: PetscErrorCode DMDAComputeL2Diff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
1319: {
1320:   const PetscInt  debug = 0;
1321:   PetscDS    prob;
1322:   PetscFE         fe;
1323:   PetscQuadrature quad;
1324:   PetscSection    section;
1325:   Vec             localX;
1326:   PetscScalar    *funcVal;
1327:   PetscReal      *coords, *v0, *J, *invJ, detJ;
1328:   PetscReal       localDiff = 0.0;
1329:   PetscInt        dim, numFields, Nc, cStart, cEnd, c, field, fieldOffset, comp;
1330:   PetscErrorCode  ierr;

1333:   DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);
1334:   DMGetDS(dm, &prob);
1335:   PetscDSGetTotalComponents(prob, &Nc);
1336:   PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);
1337:   PetscFEGetQuadrature(fe, &quad);
1338:   DMGetDefaultSection(dm, &section);
1339:   PetscSectionGetNumFields(section, &numFields);
1340:   DMGetLocalVector(dm, &localX);
1341:   DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);
1342:   DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);
1343:   /* There are no BC values in DAs right now: DMDAProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX); */
1344:   PetscMalloc5(Nc,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);
1345:   DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);
1346:   for (c = cStart; c < cEnd; ++c) {
1347:     PetscScalar *x = NULL;
1348:     PetscReal    elemDiff = 0.0;

1350:     DMDAComputeCellGeometryFEM(dm, c, quad, v0, J, invJ, &detJ);
1351:     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
1352:     DMDAVecGetClosure(dm, NULL, localX, c, NULL, &x);

1354:     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
1355:       void * const ctx = ctxs ? ctxs[field] : NULL;
1356:       const PetscReal *quadPoints, *quadWeights;
1357:       PetscReal       *basis;
1358:       PetscInt         numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f;

1360:       PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
1361:       PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);
1362:       PetscFEGetDimension(fe, &numBasisFuncs);
1363:       PetscFEGetNumComponents(fe, &numBasisComps);
1364:       PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);
1365:       if (debug) {
1366:         char title[1024];
1367:         PetscSNPrintf(title, 1023, "Solution for Field %d", field);
1368:         DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);
1369:       }
1370:       for (q = 0; q < numQuadPoints; ++q) {
1371:         for (d = 0; d < dim; d++) {
1372:           coords[d] = v0[d];
1373:           for (e = 0; e < dim; e++) {
1374:             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
1375:           }
1376:         }
1377:         (*funcs[field])(coords, funcVal, ctx);
1378:         for (fc = 0; fc < numBasisComps; ++fc) {
1379:           PetscScalar interpolant = 0.0;

1381:           for (f = 0; f < numBasisFuncs; ++f) {
1382:             const PetscInt fidx = f*numBasisComps+fc;
1383:             interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx];
1384:           }
1385:           if (debug) {PetscPrintf(PETSC_COMM_SELF, "    elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);}
1386:           elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ;
1387:         }
1388:       }
1389:       comp        += numBasisComps;
1390:       fieldOffset += numBasisFuncs*numBasisComps;
1391:     }
1392:     DMDAVecRestoreClosure(dm, NULL, localX, c, NULL, &x);
1393:     if (debug) {PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);}
1394:     localDiff += elemDiff;
1395:   }
1396:   PetscFree5(funcVal,coords,v0,J,invJ);
1397:   DMRestoreLocalVector(dm, &localX);
1398:   MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));
1399:   *diff = PetscSqrtReal(*diff);
1400:   return(0);
1401: }

1405: /*@C
1406:   DMDAComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.

1408:   Input Parameters:
1409: + dm    - The DM
1410: . funcs - The gradient functions to evaluate for each field component
1411: . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
1412: . X     - The coefficient vector u_h
1413: - n     - The vector to project along

1415:   Output Parameter:
1416: . diff - The diff ||(grad u - grad u_h) . n||_2

1418:   Level: developer

1420: .seealso: DMDAProjectFunction(), DMPlexComputeL2Diff()
1421: @*/
1422: PetscErrorCode DMDAComputeL2GradientDiff(DM dm, void (**funcs)(const PetscReal [], const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
1423: {
1424:   const PetscInt  debug = 0;
1425:   PetscDS    prob;
1426:   PetscFE         fe;
1427:   PetscQuadrature quad;
1428:   PetscSection    section;
1429:   Vec             localX;
1430:   PetscScalar    *funcVal, *interpolantVec;
1431:   PetscReal      *coords, *realSpaceDer, *v0, *J, *invJ, detJ;
1432:   PetscReal       localDiff = 0.0;
1433:   PetscInt        dim, numFields, Nc, cStart, cEnd, c, field, fieldOffset, comp;
1434:   PetscErrorCode  ierr;

1437:   DMDAGetInfo(dm, &dim,0,0,0,0,0,0,0,0,0,0,0,0);
1438:   DMGetDS(dm, &prob);
1439:   PetscDSGetTotalComponents(prob, &Nc);
1440:   PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);
1441:   PetscFEGetQuadrature(fe, &quad);
1442:   DMGetDefaultSection(dm, &section);
1443:   PetscSectionGetNumFields(section, &numFields);
1444:   DMGetLocalVector(dm, &localX);
1445:   DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);
1446:   DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);
1447:   /* There are no BC values in DAs right now: DMDAProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX); */
1448:   PetscMalloc7(Nc,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);
1449:   DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);
1450:   for (c = cStart; c < cEnd; ++c) {
1451:     PetscScalar *x = NULL;
1452:     PetscReal    elemDiff = 0.0;

1454:     DMDAComputeCellGeometryFEM(dm, c, quad, v0, J, invJ, &detJ);
1455:     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
1456:     DMDAVecGetClosure(dm, NULL, localX, c, NULL, &x);

1458:     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
1459:       void * const ctx = ctxs ? ctxs[field] : NULL;
1460:       const PetscReal *quadPoints, *quadWeights;
1461:       PetscReal       *basisDer;
1462:       PetscInt         Nq, Nb, Nc, q, d, e, fc, f, g;

1464:       PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
1465:       PetscQuadratureGetData(quad, NULL, &Nq, &quadPoints, &quadWeights);
1466:       PetscFEGetDimension(fe, &Nb);
1467:       PetscFEGetNumComponents(fe, &Nc);
1468:       PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);
1469:       if (debug) {
1470:         char title[1024];
1471:         PetscSNPrintf(title, 1023, "Solution for Field %d", field);
1472:         DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);
1473:       }
1474:       for (q = 0; q < Nq; ++q) {
1475:         for (d = 0; d < dim; d++) {
1476:           coords[d] = v0[d];
1477:           for (e = 0; e < dim; e++) {
1478:             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
1479:           }
1480:         }
1481:         (*funcs[field])(coords, n, funcVal, ctx);
1482:         for (fc = 0; fc < Nc; ++fc) {
1483:           PetscScalar interpolant = 0.0;

1485:           for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0;
1486:           for (f = 0; f < Nb; ++f) {
1487:             const PetscInt fidx = f*Nc+fc;

1489:             for (d = 0; d < dim; ++d) {
1490:               realSpaceDer[d] = 0.0;
1491:               for (g = 0; g < dim; ++g) {
1492:                 realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Nc+fidx)*dim+g];
1493:               }
1494:               interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d];
1495:             }
1496:           }
1497:           for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d];
1498:           if (debug) {PetscPrintf(PETSC_COMM_SELF, "    elem %d fieldDer %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);}
1499:           elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ;
1500:         }
1501:       }
1502:       comp        += Nc;
1503:       fieldOffset += Nb*Nc;
1504:     }
1505:     DMDAVecRestoreClosure(dm, NULL, localX, c, NULL, &x);
1506:     if (debug) {PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);}
1507:     localDiff += elemDiff;
1508:   }
1509:   PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);
1510:   DMRestoreLocalVector(dm, &localX);
1511:   MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));
1512:   *diff = PetscSqrtReal(*diff);
1513:   return(0);
1514: }

1516: /* ------------------------------------------------------------------- */

1520: /*@C
1521:      DMDAGetArray - Gets a work array for a DMDA

1523:     Input Parameter:
1524: +    da - information about my local patch
1525: -    ghosted - do you want arrays for the ghosted or nonghosted patch

1527:     Output Parameters:
1528: .    vptr - array data structured

1530:     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
1531:            to zero them.

1533:   Level: advanced

1535: .seealso: DMDARestoreArray()

1537: @*/
1538: PetscErrorCode  DMDAGetArray(DM da,PetscBool ghosted,void *vptr)
1539: {
1541:   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
1542:   char           *iarray_start;
1543:   void           **iptr = (void**)vptr;
1544:   DM_DA          *dd    = (DM_DA*)da->data;

1548:   if (ghosted) {
1549:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1550:       if (dd->arrayghostedin[i]) {
1551:         *iptr                 = dd->arrayghostedin[i];
1552:         iarray_start          = (char*)dd->startghostedin[i];
1553:         dd->arrayghostedin[i] = NULL;
1554:         dd->startghostedin[i] = NULL;

1556:         goto done;
1557:       }
1558:     }
1559:     xs = dd->Xs;
1560:     ys = dd->Ys;
1561:     zs = dd->Zs;
1562:     xm = dd->Xe-dd->Xs;
1563:     ym = dd->Ye-dd->Ys;
1564:     zm = dd->Ze-dd->Zs;
1565:   } else {
1566:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1567:       if (dd->arrayin[i]) {
1568:         *iptr          = dd->arrayin[i];
1569:         iarray_start   = (char*)dd->startin[i];
1570:         dd->arrayin[i] = NULL;
1571:         dd->startin[i] = NULL;

1573:         goto done;
1574:       }
1575:     }
1576:     xs = dd->xs;
1577:     ys = dd->ys;
1578:     zs = dd->zs;
1579:     xm = dd->xe-dd->xs;
1580:     ym = dd->ye-dd->ys;
1581:     zm = dd->ze-dd->zs;
1582:   }

1584:   switch (da->dim) {
1585:   case 1: {
1586:     void *ptr;

1588:     PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);

1590:     ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
1591:     *iptr = (void*)ptr;
1592:     break;
1593:   }
1594:   case 2: {
1595:     void **ptr;

1597:     PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);

1599:     ptr = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
1600:     for (j=ys; j<ys+ym; j++) ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
1601:     *iptr = (void*)ptr;
1602:     break;
1603:   }
1604:   case 3: {
1605:     void ***ptr,**bptr;

1607:     PetscMalloc((zm+1)*sizeof(void**)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);

1609:     ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
1610:     bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
1611:     for (i=zs; i<zs+zm; i++) ptr[i] = bptr + ((i-zs)*ym - ys);
1612:     for (i=zs; i<zs+zm; i++) {
1613:       for (j=ys; j<ys+ym; j++) {
1614:         ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
1615:       }
1616:     }
1617:     *iptr = (void*)ptr;
1618:     break;
1619:   }
1620:   default:
1621:     SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Dimension %D not supported",da->dim);
1622:   }

1624: done:
1625:   /* add arrays to the checked out list */
1626:   if (ghosted) {
1627:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1628:       if (!dd->arrayghostedout[i]) {
1629:         dd->arrayghostedout[i] = *iptr;
1630:         dd->startghostedout[i] = iarray_start;
1631:         break;
1632:       }
1633:     }
1634:   } else {
1635:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1636:       if (!dd->arrayout[i]) {
1637:         dd->arrayout[i] = *iptr;
1638:         dd->startout[i] = iarray_start;
1639:         break;
1640:       }
1641:     }
1642:   }
1643:   return(0);
1644: }

1648: /*@C
1649:      DMDARestoreArray - Restores an array of derivative types for a DMDA

1651:     Input Parameter:
1652: +    da - information about my local patch
1653: .    ghosted - do you want arrays for the ghosted or nonghosted patch
1654: -    vptr - array data structured to be passed to ad_FormFunctionLocal()

1656:      Level: advanced

1658: .seealso: DMDAGetArray()

1660: @*/
1661: PetscErrorCode  DMDARestoreArray(DM da,PetscBool ghosted,void *vptr)
1662: {
1663:   PetscInt i;
1664:   void     **iptr = (void**)vptr,*iarray_start = 0;
1665:   DM_DA    *dd    = (DM_DA*)da->data;

1669:   if (ghosted) {
1670:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1671:       if (dd->arrayghostedout[i] == *iptr) {
1672:         iarray_start           = dd->startghostedout[i];
1673:         dd->arrayghostedout[i] = NULL;
1674:         dd->startghostedout[i] = NULL;
1675:         break;
1676:       }
1677:     }
1678:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1679:       if (!dd->arrayghostedin[i]) {
1680:         dd->arrayghostedin[i] = *iptr;
1681:         dd->startghostedin[i] = iarray_start;
1682:         break;
1683:       }
1684:     }
1685:   } else {
1686:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1687:       if (dd->arrayout[i] == *iptr) {
1688:         iarray_start    = dd->startout[i];
1689:         dd->arrayout[i] = NULL;
1690:         dd->startout[i] = NULL;
1691:         break;
1692:       }
1693:     }
1694:     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
1695:       if (!dd->arrayin[i]) {
1696:         dd->arrayin[i] = *iptr;
1697:         dd->startin[i] = iarray_start;
1698:         break;
1699:       }
1700:     }
1701:   }
1702:   return(0);
1703: }