xref: /petsc/src/dm/impls/da/dalocal.c (revision bdf89e91df64bd49f4414ba801fb07e6338da027)
1 
2 /*
3   Code for manipulating distributed regular arrays in parallel.
4 */
5 
6 #include <petsc-private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
7 
8 /*
9    This allows the DMDA vectors to properly tell MATLAB their dimensions
10 */
11 #if defined(PETSC_HAVE_MATLAB_ENGINE)
12 #include <engine.h>   /* MATLAB include file */
13 #include <mex.h>      /* MATLAB include file */
14 #undef __FUNCT__
15 #define __FUNCT__ "VecMatlabEnginePut_DA2d"
16 static PetscErrorCode  VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
17 {
18   PetscErrorCode ierr;
19   PetscInt       n,m;
20   Vec            vec = (Vec)obj;
21   PetscScalar    *array;
22   mxArray        *mat;
23   DM             da;
24 
25   PetscFunctionBegin;
26   ierr = VecGetDM(vec, &da);CHKERRQ(ierr);
27   if (!da) SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
28   ierr = DMDAGetGhostCorners(da,0,0,0,&m,&n,0);CHKERRQ(ierr);
29 
30   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
31 #if !defined(PETSC_USE_COMPLEX)
32   mat = mxCreateDoubleMatrix(m,n,mxREAL);
33 #else
34   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
35 #endif
36   ierr = PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));CHKERRQ(ierr);
37   ierr = PetscObjectName(obj);CHKERRQ(ierr);
38   engPutVariable((Engine*)mengine,obj->name,mat);
39 
40   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
41   PetscFunctionReturn(0);
42 }
43 #endif
44 
45 
46 #undef __FUNCT__
47 #define __FUNCT__ "DMCreateLocalVector_DA"
48 PetscErrorCode  DMCreateLocalVector_DA(DM da,Vec *g)
49 {
50   PetscErrorCode ierr;
51   DM_DA          *dd = (DM_DA*)da->data;
52 
53   PetscFunctionBegin;
54   PetscValidHeaderSpecific(da,DM_CLASSID,1);
55   PetscValidPointer(g,2);
56   if (da->defaultSection) {
57     ierr = DMCreateLocalVector_Section_Private(da,g);CHKERRQ(ierr);
58   } else {
59     ierr = VecCreate(PETSC_COMM_SELF,g);CHKERRQ(ierr);
60     ierr = VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);CHKERRQ(ierr);
61     ierr = VecSetBlockSize(*g,dd->w);CHKERRQ(ierr);
62     ierr = VecSetType(*g,da->vectype);CHKERRQ(ierr);
63     ierr = VecSetDM(*g, da);CHKERRQ(ierr);
64 #if defined(PETSC_HAVE_MATLAB_ENGINE)
65     if (dd->w == 1  && dd->dim == 2) {
66       ierr = PetscObjectComposeFunction((PetscObject)*g,"PetscMatlabEnginePut_C",VecMatlabEnginePut_DA2d);CHKERRQ(ierr);
67     }
68 #endif
69   }
70   PetscFunctionReturn(0);
71 }
72 
73 #undef __FUNCT__
74 #define __FUNCT__ "DMDAGetNumCells"
75 PetscErrorCode DMDAGetNumCells(DM dm, PetscInt *numCells)
76 {
77   DM_DA          *da = (DM_DA*) dm->data;
78   const PetscInt dim = da->dim;
79   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
80   const PetscInt nC  = (mx)*(dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
81 
82   PetscFunctionBegin;
83   if (numCells) {
84     PetscValidIntPointer(numCells,2);
85     *numCells = nC;
86   }
87   PetscFunctionReturn(0);
88 }
89 
90 #undef __FUNCT__
91 #define __FUNCT__ "DMDAGetNumVertices"
92 PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
93 {
94   DM_DA          *da = (DM_DA*) dm->data;
95   const PetscInt dim = da->dim;
96   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
97   const PetscInt nVx = mx+1;
98   const PetscInt nVy = dim > 1 ? (my+1) : 1;
99   const PetscInt nVz = dim > 2 ? (mz+1) : 1;
100   const PetscInt nV  = nVx*nVy*nVz;
101 
102   PetscFunctionBegin;
103   if (numVerticesX) {
104     PetscValidIntPointer(numVerticesX,2);
105     *numVerticesX = nVx;
106   }
107   if (numVerticesY) {
108     PetscValidIntPointer(numVerticesY,3);
109     *numVerticesY = nVy;
110   }
111   if (numVerticesZ) {
112     PetscValidIntPointer(numVerticesZ,4);
113     *numVerticesZ = nVz;
114   }
115   if (numVertices) {
116     PetscValidIntPointer(numVertices,5);
117     *numVertices = nV;
118   }
119   PetscFunctionReturn(0);
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "DMDAGetNumFaces"
124 PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
125 {
126   DM_DA          *da = (DM_DA*) dm->data;
127   const PetscInt dim = da->dim;
128   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
129   const PetscInt nxF = (dim > 1 ? (my)*(dim > 2 ? (mz) : 1) : 1);
130   const PetscInt nXF = (mx+1)*nxF;
131   const PetscInt nyF = mx*(dim > 2 ? mz : 1);
132   const PetscInt nYF = dim > 1 ? (my+1)*nyF : 0;
133   const PetscInt nzF = mx*(dim > 1 ? my : 0);
134   const PetscInt nZF = dim > 2 ? (mz+1)*nzF : 0;
135 
136   PetscFunctionBegin;
137   if (numXFacesX) {
138     PetscValidIntPointer(numXFacesX,2);
139     *numXFacesX = nxF;
140   }
141   if (numXFaces) {
142     PetscValidIntPointer(numXFaces,3);
143     *numXFaces = nXF;
144   }
145   if (numYFacesY) {
146     PetscValidIntPointer(numYFacesY,4);
147     *numYFacesY = nyF;
148   }
149   if (numYFaces) {
150     PetscValidIntPointer(numYFaces,5);
151     *numYFaces = nYF;
152   }
153   if (numZFacesZ) {
154     PetscValidIntPointer(numZFacesZ,6);
155     *numZFacesZ = nzF;
156   }
157   if (numZFaces) {
158     PetscValidIntPointer(numZFaces,7);
159     *numZFaces = nZF;
160   }
161   PetscFunctionReturn(0);
162 }
163 
164 #undef __FUNCT__
165 #define __FUNCT__ "DMDAGetHeightStratum"
166 PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PetscInt *pStart, PetscInt *pEnd)
167 {
168   DM_DA          *da = (DM_DA*) dm->data;
169   const PetscInt dim = da->dim;
170   PetscInt       nC, nV, nXF, nYF, nZF;
171   PetscErrorCode ierr;
172 
173   PetscFunctionBegin;
174   if (pStart) PetscValidIntPointer(pStart,3);
175   if (pEnd)   PetscValidIntPointer(pEnd,4);
176   ierr = DMDAGetNumCells(dm, &nC);CHKERRQ(ierr);
177   ierr = DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV);CHKERRQ(ierr);
178   ierr = DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF);CHKERRQ(ierr);
179   if (height == 0) {
180     /* Cells */
181     if (pStart) *pStart = 0;
182     if (pEnd)   *pEnd   = nC;
183   } else if (height == 1) {
184     /* Faces */
185     if (pStart) *pStart = nC+nV;
186     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
187   } else if (height == dim) {
188     /* Vertices */
189     if (pStart) *pStart = nC;
190     if (pEnd)   *pEnd   = nC+nV;
191   } else if (height < 0) {
192     /* All points */
193     if (pStart) *pStart = 0;
194     if (pEnd)   *pEnd   = nC+nV+nXF+nYF+nZF;
195   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of height %d in the DA", height);
196   PetscFunctionReturn(0);
197 }
198 
199 #undef __FUNCT__
200 #define __FUNCT__ "DMDACreateSection"
201 /*@C
202   DMDACreateSection - Create a PetscSection inside the DMDA that describes data layout. This allows multiple fields with
203   different numbers of dofs on vertices, cells, and faces in each direction.
204 
205   Input Parameters:
206 + dm- The DMDA
207 . numFields - The number of fields
208 . numComp - The number of components in each field, or NULL for 1
209 . numVertexDof - The number of dofs per vertex for each field, or NULL
210 . numFaceDof - The number of dofs per face for each field and direction, or NULL
211 - numCellDof - The number of dofs per cell for each field, or NULL
212 
213   Level: developer
214 
215   Note:
216   The default DMDA numbering is as follows:
217 
218     - Cells:    [0,             nC)
219     - Vertices: [nC,            nC+nV)
220     - X-Faces:  [nC+nV,         nC+nV+nXF)         normal is +- x-dir
221     - Y-Faces:  [nC+nV+nXF,     nC+nV+nXF+nYF)     normal is +- y-dir
222     - Z-Faces:  [nC+nV+nXF+nYF, nC+nV+nXF+nYF+nZF) normal is +- z-dir
223 
224   We interpret the default DMDA partition as a cell partition, and the data assignment as a cell assignment.
225 @*/
226 PetscErrorCode DMDACreateSection(DM dm, PetscInt numComp[], PetscInt numVertexDof[], PetscInt numFaceDof[], PetscInt numCellDof[])
227 {
228   DM_DA             *da = (DM_DA*) dm->data;
229   const PetscInt    dim = da->dim;
230   PetscInt          numFields, numVertexTotDof = 0, numCellTotDof = 0, numFaceTotDof[3] = {0, 0, 0};
231   PetscSF           sf;
232   PetscMPIInt       rank;
233   const PetscMPIInt *neighbors;
234   PetscInt          *localPoints;
235   PetscSFNode       *remotePoints;
236   PetscInt          nleaves = 0,  nleavesCheck = 0, nL = 0;
237   PetscInt          nC, nVx, nVy, nVz, nV, nxF, nXF, nyF, nYF, nzF, nZF;
238   PetscInt          pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart, zfEnd;
239   PetscInt          f, v, c, xf, yf, zf, xn, yn, zn;
240   PetscErrorCode    ierr;
241 
242   PetscFunctionBegin;
243   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
244   ierr    = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr);
245   ierr    = DMDAGetNumCells(dm, &nC);CHKERRQ(ierr);
246   ierr    = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
247   ierr    = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
248   ierr    = DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);CHKERRQ(ierr);
249   ierr    = DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);CHKERRQ(ierr);
250   ierr    = DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);CHKERRQ(ierr);
251   ierr    = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr);
252   xfStart = vEnd;  xfEnd = xfStart+nXF;
253   yfStart = xfEnd; yfEnd = yfStart+nYF;
254   zfStart = yfEnd; zfEnd = zfStart+nZF;
255   if (zfEnd != fEnd) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid face end %d, should be %d", zfEnd, fEnd);
256   /* Create local section */
257   ierr = DMDAGetInfo(dm, 0,0,0,0,0,0,0, &numFields, 0,0,0,0,0);CHKERRQ(ierr);
258   for (f = 0; f < numFields; ++f) {
259     if (numVertexDof) numVertexTotDof  += numVertexDof[f];
260     if (numCellDof)   numCellTotDof    += numCellDof[f];
261     if (numFaceDof) {
262       numFaceTotDof[0] += numFaceDof[f*dim+0];
263       numFaceTotDof[1] += dim > 1 ? numFaceDof[f*dim+1] : 0;
264       numFaceTotDof[2] += dim > 2 ? numFaceDof[f*dim+2] : 0;
265     }
266   }
267   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &dm->defaultSection);CHKERRQ(ierr);
268   if (numFields > 1) {
269     ierr = PetscSectionSetNumFields(dm->defaultSection, numFields);CHKERRQ(ierr);
270     for (f = 0; f < numFields; ++f) {
271       const char *name;
272 
273       ierr = DMDAGetFieldName(dm, f, &name);CHKERRQ(ierr);
274       ierr = PetscSectionSetFieldName(dm->defaultSection, f, name);CHKERRQ(ierr);
275       if (numComp) {
276         ierr = PetscSectionSetFieldComponents(dm->defaultSection, f, numComp[f]);CHKERRQ(ierr);
277       }
278     }
279   } else {
280     numFields = 0;
281   }
282   ierr = PetscSectionSetChart(dm->defaultSection, pStart, pEnd);CHKERRQ(ierr);
283   if (numVertexDof) {
284     for (v = vStart; v < vEnd; ++v) {
285       for (f = 0; f < numFields; ++f) {
286         ierr = PetscSectionSetFieldDof(dm->defaultSection, v, f, numVertexDof[f]);CHKERRQ(ierr);
287       }
288       ierr = PetscSectionSetDof(dm->defaultSection, v, numVertexTotDof);CHKERRQ(ierr);
289     }
290   }
291   if (numFaceDof) {
292     for (xf = xfStart; xf < xfEnd; ++xf) {
293       for (f = 0; f < numFields; ++f) {
294         ierr = PetscSectionSetFieldDof(dm->defaultSection, xf, f, numFaceDof[f*dim+0]);CHKERRQ(ierr);
295       }
296       ierr = PetscSectionSetDof(dm->defaultSection, xf, numFaceTotDof[0]);CHKERRQ(ierr);
297     }
298     for (yf = yfStart; yf < yfEnd; ++yf) {
299       for (f = 0; f < numFields; ++f) {
300         ierr = PetscSectionSetFieldDof(dm->defaultSection, yf, f, numFaceDof[f*dim+1]);CHKERRQ(ierr);
301       }
302       ierr = PetscSectionSetDof(dm->defaultSection, yf, numFaceTotDof[1]);CHKERRQ(ierr);
303     }
304     for (zf = zfStart; zf < zfEnd; ++zf) {
305       for (f = 0; f < numFields; ++f) {
306         ierr = PetscSectionSetFieldDof(dm->defaultSection, zf, f, numFaceDof[f*dim+2]);CHKERRQ(ierr);
307       }
308       ierr = PetscSectionSetDof(dm->defaultSection, zf, numFaceTotDof[2]);CHKERRQ(ierr);
309     }
310   }
311   if (numCellDof) {
312     for (c = cStart; c < cEnd; ++c) {
313       for (f = 0; f < numFields; ++f) {
314         ierr = PetscSectionSetFieldDof(dm->defaultSection, c, f, numCellDof[f]);CHKERRQ(ierr);
315       }
316       ierr = PetscSectionSetDof(dm->defaultSection, c, numCellTotDof);CHKERRQ(ierr);
317     }
318   }
319   ierr = PetscSectionSetUp(dm->defaultSection);CHKERRQ(ierr);
320   /* Create mesh point SF */
321   ierr = DMDAGetNeighbors(dm, &neighbors);CHKERRQ(ierr);
322   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
323     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
324       for (xn = 0; xn < 3; ++xn) {
325         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
326         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
327 
328         if (neighbor >= 0 && neighbor < rank) {
329           nleaves += (!xp ? nVx : 1) * (!yp ? nVy : 1) * (!zp ? nVz : 1); /* vertices */
330           if (xp && !yp && !zp) {
331             nleaves += nxF; /* x faces */
332           } else if (yp && !zp && !xp) {
333             nleaves += nyF; /* y faces */
334           } else if (zp && !xp && !yp) {
335             nleaves += nzF; /* z faces */
336           }
337         }
338       }
339     }
340   }
341   ierr = PetscMalloc2(nleaves,PetscInt,&localPoints,nleaves,PetscSFNode,&remotePoints);CHKERRQ(ierr);
342   for (zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
343     for (yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
344       for (xn = 0; xn < 3; ++xn) {
345         const PetscInt xp       = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
346         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
347         PetscInt       xv, yv, zv;
348 
349         if (neighbor >= 0 && neighbor < rank) {
350           if (xp < 0) { /* left */
351             if (yp < 0) { /* bottom */
352               if (zp < 0) { /* back */
353                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC;
354                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
355                 nleavesCheck += 1; /* left bottom back vertex */
356 
357                 localPoints[nL]        = localVertex;
358                 remotePoints[nL].rank  = neighbor;
359                 remotePoints[nL].index = remoteVertex;
360                 ++nL;
361               } else if (zp > 0) { /* front */
362                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC;
363                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
364                 nleavesCheck += 1; /* left bottom front vertex */
365 
366                 localPoints[nL]        = localVertex;
367                 remotePoints[nL].rank  = neighbor;
368                 remotePoints[nL].index = remoteVertex;
369                 ++nL;
370               } else {
371                 nleavesCheck += nVz; /* left bottom vertices */
372                 for (zv = 0; zv < nVz; ++zv, ++nL) {
373                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC;
374                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
375 
376                   localPoints[nL]        = localVertex;
377                   remotePoints[nL].rank  = neighbor;
378                   remotePoints[nL].index = remoteVertex;
379                 }
380               }
381             } else if (yp > 0) { /* top */
382               if (zp < 0) { /* back */
383                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC;
384                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
385                 nleavesCheck += 1; /* left top back vertex */
386 
387                 localPoints[nL]        = localVertex;
388                 remotePoints[nL].rank  = neighbor;
389                 remotePoints[nL].index = remoteVertex;
390                 ++nL;
391               } else if (zp > 0) { /* front */
392                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC;
393                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
394                 nleavesCheck += 1; /* left top front vertex */
395 
396                 localPoints[nL]        = localVertex;
397                 remotePoints[nL].rank  = neighbor;
398                 remotePoints[nL].index = remoteVertex;
399                 ++nL;
400               } else {
401                 nleavesCheck += nVz; /* left top vertices */
402                 for (zv = 0; zv < nVz; ++zv, ++nL) {
403                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC;
404                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
405 
406                   localPoints[nL]        = localVertex;
407                   remotePoints[nL].rank  = neighbor;
408                   remotePoints[nL].index = remoteVertex;
409                 }
410               }
411             } else {
412               if (zp < 0) { /* back */
413                 nleavesCheck += nVy; /* left back vertices */
414                 for (yv = 0; yv < nVy; ++yv, ++nL) {
415                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC;
416                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
417 
418                   localPoints[nL]        = localVertex;
419                   remotePoints[nL].rank  = neighbor;
420                   remotePoints[nL].index = remoteVertex;
421                 }
422               } else if (zp > 0) { /* front */
423                 nleavesCheck += nVy; /* left front vertices */
424                 for (yv = 0; yv < nVy; ++yv, ++nL) {
425                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC;
426                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
427 
428                   localPoints[nL]        = localVertex;
429                   remotePoints[nL].rank  = neighbor;
430                   remotePoints[nL].index = remoteVertex;
431                 }
432               } else {
433                 nleavesCheck += nVy*nVz; /* left vertices */
434                 for (zv = 0; zv < nVz; ++zv) {
435                   for (yv = 0; yv < nVy; ++yv, ++nL) {
436                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC;
437                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
438 
439                     localPoints[nL]        = localVertex;
440                     remotePoints[nL].rank  = neighbor;
441                     remotePoints[nL].index = remoteVertex;
442                   }
443                 }
444                 nleavesCheck += nxF;     /* left faces */
445                 for (xf = 0; xf < nxF; ++xf, ++nL) {
446                   /* THIS IS WRONG */
447                   const PetscInt localFace  = 0 + nC+nV;
448                   const PetscInt remoteFace = 0 + nC+nV;
449 
450                   localPoints[nL]        = localFace;
451                   remotePoints[nL].rank  = neighbor;
452                   remotePoints[nL].index = remoteFace;
453                 }
454               }
455             }
456           } else if (xp > 0) { /* right */
457             if (yp < 0) { /* bottom */
458               if (zp < 0) { /* back */
459                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC;
460                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
461                 nleavesCheck += 1; /* right bottom back vertex */
462 
463                 localPoints[nL]        = localVertex;
464                 remotePoints[nL].rank  = neighbor;
465                 remotePoints[nL].index = remoteVertex;
466                 ++nL;
467               } else if (zp > 0) { /* front */
468                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC;
469                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
470                 nleavesCheck += 1; /* right bottom front vertex */
471 
472                 localPoints[nL]        = localVertex;
473                 remotePoints[nL].rank  = neighbor;
474                 remotePoints[nL].index = remoteVertex;
475                 ++nL;
476               } else {
477                 nleavesCheck += nVz; /* right bottom vertices */
478                 for (zv = 0; zv < nVz; ++zv, ++nL) {
479                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC;
480                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
481 
482                   localPoints[nL]        = localVertex;
483                   remotePoints[nL].rank  = neighbor;
484                   remotePoints[nL].index = remoteVertex;
485                 }
486               }
487             } else if (yp > 0) { /* top */
488               if (zp < 0) { /* back */
489                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC;
490                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
491                 nleavesCheck += 1; /* right top back vertex */
492 
493                 localPoints[nL]        = localVertex;
494                 remotePoints[nL].rank  = neighbor;
495                 remotePoints[nL].index = remoteVertex;
496                 ++nL;
497               } else if (zp > 0) { /* front */
498                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC;
499                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
500                 nleavesCheck += 1; /* right top front vertex */
501 
502                 localPoints[nL]        = localVertex;
503                 remotePoints[nL].rank  = neighbor;
504                 remotePoints[nL].index = remoteVertex;
505                 ++nL;
506               } else {
507                 nleavesCheck += nVz; /* right top vertices */
508                 for (zv = 0; zv < nVz; ++zv, ++nL) {
509                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC;
510                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
511 
512                   localPoints[nL]        = localVertex;
513                   remotePoints[nL].rank  = neighbor;
514                   remotePoints[nL].index = remoteVertex;
515                 }
516               }
517             } else {
518               if (zp < 0) { /* back */
519                 nleavesCheck += nVy; /* right back vertices */
520                 for (yv = 0; yv < nVy; ++yv, ++nL) {
521                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC;
522                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
523 
524                   localPoints[nL]        = localVertex;
525                   remotePoints[nL].rank  = neighbor;
526                   remotePoints[nL].index = remoteVertex;
527                 }
528               } else if (zp > 0) { /* front */
529                 nleavesCheck += nVy; /* right front vertices */
530                 for (yv = 0; yv < nVy; ++yv, ++nL) {
531                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC;
532                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
533 
534                   localPoints[nL]        = localVertex;
535                   remotePoints[nL].rank  = neighbor;
536                   remotePoints[nL].index = remoteVertex;
537                 }
538               } else {
539                 nleavesCheck += nVy*nVz; /* right vertices */
540                 for (zv = 0; zv < nVz; ++zv) {
541                   for (yv = 0; yv < nVy; ++yv, ++nL) {
542                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC;
543                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + 0     + nC; /* TODO: Correct this for neighbor sizes */
544 
545                     localPoints[nL]        = localVertex;
546                     remotePoints[nL].rank  = neighbor;
547                     remotePoints[nL].index = remoteVertex;
548                   }
549                 }
550                 nleavesCheck += nxF;     /* right faces */
551                 for (xf = 0; xf < nxF; ++xf, ++nL) {
552                   /* THIS IS WRONG */
553                   const PetscInt localFace  = 0 + nC+nV;
554                   const PetscInt remoteFace = 0 + nC+nV;
555 
556                   localPoints[nL]        = localFace;
557                   remotePoints[nL].rank  = neighbor;
558                   remotePoints[nL].index = remoteFace;
559                 }
560               }
561             }
562           } else {
563             if (yp < 0) { /* bottom */
564               if (zp < 0) { /* back */
565                 nleavesCheck += nVx; /* bottom back vertices */
566                 for (xv = 0; xv < nVx; ++xv, ++nL) {
567                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC;
568                   const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
569 
570                   localPoints[nL]        = localVertex;
571                   remotePoints[nL].rank  = neighbor;
572                   remotePoints[nL].index = remoteVertex;
573                 }
574               } else if (zp > 0) { /* front */
575                 nleavesCheck += nVx; /* bottom front vertices */
576                 for (xv = 0; xv < nVx; ++xv, ++nL) {
577                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC;
578                   const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
579 
580                   localPoints[nL]        = localVertex;
581                   remotePoints[nL].rank  = neighbor;
582                   remotePoints[nL].index = remoteVertex;
583                 }
584               } else {
585                 nleavesCheck += nVx*nVz; /* bottom vertices */
586                 for (zv = 0; zv < nVz; ++zv) {
587                   for (xv = 0; xv < nVx; ++xv, ++nL) {
588                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC;
589                     const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
590 
591                     localPoints[nL]        = localVertex;
592                     remotePoints[nL].rank  = neighbor;
593                     remotePoints[nL].index = remoteVertex;
594                   }
595                 }
596                 nleavesCheck += nyF;     /* bottom faces */
597                 for (yf = 0; yf < nyF; ++yf, ++nL) {
598                   /* THIS IS WRONG */
599                   const PetscInt localFace  = 0 + nC+nV;
600                   const PetscInt remoteFace = 0 + nC+nV;
601 
602                   localPoints[nL]        = localFace;
603                   remotePoints[nL].rank  = neighbor;
604                   remotePoints[nL].index = remoteFace;
605                 }
606               }
607             } else if (yp > 0) { /* top */
608               if (zp < 0) { /* back */
609                 nleavesCheck += nVx; /* top back vertices */
610                 for (xv = 0; xv < nVx; ++xv, ++nL) {
611                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC;
612                   const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
613 
614                   localPoints[nL]        = localVertex;
615                   remotePoints[nL].rank  = neighbor;
616                   remotePoints[nL].index = remoteVertex;
617                 }
618               } else if (zp > 0) { /* front */
619                 nleavesCheck += nVx; /* top front vertices */
620                 for (xv = 0; xv < nVx; ++xv, ++nL) {
621                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC;
622                   const PetscInt remoteVertex = (      0*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
623 
624                   localPoints[nL]        = localVertex;
625                   remotePoints[nL].rank  = neighbor;
626                   remotePoints[nL].index = remoteVertex;
627                 }
628               } else {
629                 nleavesCheck += nVx*nVz; /* top vertices */
630                 for (zv = 0; zv < nVz; ++zv) {
631                   for (xv = 0; xv < nVx; ++xv, ++nL) {
632                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC;
633                     const PetscInt remoteVertex = (zv*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
634 
635                     localPoints[nL]        = localVertex;
636                     remotePoints[nL].rank  = neighbor;
637                     remotePoints[nL].index = remoteVertex;
638                   }
639                 }
640                 nleavesCheck += nyF;     /* top faces */
641                 for (yf = 0; yf < nyF; ++yf, ++nL) {
642                   /* THIS IS WRONG */
643                   const PetscInt localFace  = 0 + nC+nV;
644                   const PetscInt remoteFace = 0 + nC+nV;
645 
646                   localPoints[nL]        = localFace;
647                   remotePoints[nL].rank  = neighbor;
648                   remotePoints[nL].index = remoteFace;
649                 }
650               }
651             } else {
652               if (zp < 0) { /* back */
653                 nleavesCheck += nVx*nVy; /* back vertices */
654                 for (yv = 0; yv < nVy; ++yv) {
655                   for (xv = 0; xv < nVx; ++xv, ++nL) {
656                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC;
657                     const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
658 
659                     localPoints[nL]        = localVertex;
660                     remotePoints[nL].rank  = neighbor;
661                     remotePoints[nL].index = remoteVertex;
662                   }
663                 }
664                 nleavesCheck += nzF;     /* back faces */
665                 for (zf = 0; zf < nzF; ++zf, ++nL) {
666                   /* THIS IS WRONG */
667                   const PetscInt localFace  = 0 + nC+nV;
668                   const PetscInt remoteFace = 0 + nC+nV;
669 
670                   localPoints[nL]        = localFace;
671                   remotePoints[nL].rank  = neighbor;
672                   remotePoints[nL].index = remoteFace;
673                 }
674               } else if (zp > 0) { /* front */
675                 nleavesCheck += nVx*nVy; /* front vertices */
676                 for (yv = 0; yv < nVy; ++yv) {
677                   for (xv = 0; xv < nVx; ++xv, ++nL) {
678                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC;
679                     const PetscInt remoteVertex = (      0*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
680 
681                     localPoints[nL]        = localVertex;
682                     remotePoints[nL].rank  = neighbor;
683                     remotePoints[nL].index = remoteVertex;
684                   }
685                 }
686                 nleavesCheck += nzF;     /* front faces */
687                 for (zf = 0; zf < nzF; ++zf, ++nL) {
688                   /* THIS IS WRONG */
689                   const PetscInt localFace  = 0 + nC+nV;
690                   const PetscInt remoteFace = 0 + nC+nV;
691 
692                   localPoints[nL]        = localFace;
693                   remotePoints[nL].rank  = neighbor;
694                   remotePoints[nL].index = remoteFace;
695                 }
696               } else {
697                 /* Nothing is shared from the interior */
698               }
699             }
700           }
701         }
702       }
703     }
704   }
705   /* TODO: Remove duplication in leaf determination */
706   if (nleaves != nleavesCheck) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "The number of leaves %d did not match the number of remote leaves %d", nleaves, nleavesCheck);
707   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf);CHKERRQ(ierr);
708   ierr = PetscSFSetGraph(sf, pEnd, nleaves, localPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
709   /* Create global section */
710   ierr = PetscSectionCreateGlobalSection(dm->defaultSection, sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
711   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
712   /* Create default SF */
713   ierr = DMCreateDefaultSF(dm, dm->defaultSection, dm->defaultGlobalSection);CHKERRQ(ierr);
714   PetscFunctionReturn(0);
715 }
716 
717 /* ------------------------------------------------------------------- */
718 
719 #undef __FUNCT__
720 #define __FUNCT__ "DMDAGetArray"
721 /*@C
722      DMDAGetArray - Gets a work array for a DMDA
723 
724     Input Parameter:
725 +    da - information about my local patch
726 -    ghosted - do you want arrays for the ghosted or nonghosted patch
727 
728     Output Parameters:
729 .    vptr - array data structured
730 
731     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
732            to zero them.
733 
734   Level: advanced
735 
736 .seealso: DMDARestoreArray()
737 
738 @*/
739 PetscErrorCode  DMDAGetArray(DM da,PetscBool ghosted,void *vptr)
740 {
741   PetscErrorCode ierr;
742   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
743   char           *iarray_start;
744   void           **iptr = (void**)vptr;
745   DM_DA          *dd    = (DM_DA*)da->data;
746 
747   PetscFunctionBegin;
748   PetscValidHeaderSpecific(da,DM_CLASSID,1);
749   if (ghosted) {
750     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
751       if (dd->arrayghostedin[i]) {
752         *iptr                 = dd->arrayghostedin[i];
753         iarray_start          = (char*)dd->startghostedin[i];
754         dd->arrayghostedin[i] = NULL;
755         dd->startghostedin[i] = NULL;
756 
757         goto done;
758       }
759     }
760     xs = dd->Xs;
761     ys = dd->Ys;
762     zs = dd->Zs;
763     xm = dd->Xe-dd->Xs;
764     ym = dd->Ye-dd->Ys;
765     zm = dd->Ze-dd->Zs;
766   } else {
767     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
768       if (dd->arrayin[i]) {
769         *iptr          = dd->arrayin[i];
770         iarray_start   = (char*)dd->startin[i];
771         dd->arrayin[i] = NULL;
772         dd->startin[i] = NULL;
773 
774         goto done;
775       }
776     }
777     xs = dd->xs;
778     ys = dd->ys;
779     zs = dd->zs;
780     xm = dd->xe-dd->xs;
781     ym = dd->ye-dd->ys;
782     zm = dd->ze-dd->zs;
783   }
784 
785   switch (dd->dim) {
786   case 1: {
787     void *ptr;
788 
789     ierr = PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
790 
791     ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
792     *iptr = (void*)ptr;
793     break;
794   }
795   case 2: {
796     void **ptr;
797 
798     ierr = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
799 
800     ptr = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
801     for (j=ys; j<ys+ym; j++) ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
802     *iptr = (void*)ptr;
803     break;
804   }
805   case 3: {
806     void ***ptr,**bptr;
807 
808     ierr = PetscMalloc((zm+1)*sizeof(void**)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
809 
810     ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
811     bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
812     for (i=zs; i<zs+zm; i++) ptr[i] = bptr + ((i-zs)*ym - ys);
813     for (i=zs; i<zs+zm; i++) {
814       for (j=ys; j<ys+ym; j++) {
815         ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
816       }
817     }
818     *iptr = (void*)ptr;
819     break;
820   }
821   default:
822     SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
823   }
824 
825 done:
826   /* add arrays to the checked out list */
827   if (ghosted) {
828     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
829       if (!dd->arrayghostedout[i]) {
830         dd->arrayghostedout[i] = *iptr;
831         dd->startghostedout[i] = iarray_start;
832         break;
833       }
834     }
835   } else {
836     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
837       if (!dd->arrayout[i]) {
838         dd->arrayout[i] = *iptr;
839         dd->startout[i] = iarray_start;
840         break;
841       }
842     }
843   }
844   PetscFunctionReturn(0);
845 }
846 
847 #undef __FUNCT__
848 #define __FUNCT__ "DMDARestoreArray"
849 /*@C
850      DMDARestoreArray - Restores an array of derivative types for a DMDA
851 
852     Input Parameter:
853 +    da - information about my local patch
854 .    ghosted - do you want arrays for the ghosted or nonghosted patch
855 -    vptr - array data structured to be passed to ad_FormFunctionLocal()
856 
857      Level: advanced
858 
859 .seealso: DMDAGetArray()
860 
861 @*/
862 PetscErrorCode  DMDARestoreArray(DM da,PetscBool ghosted,void *vptr)
863 {
864   PetscInt i;
865   void     **iptr = (void**)vptr,*iarray_start = 0;
866   DM_DA    *dd    = (DM_DA*)da->data;
867 
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(da,DM_CLASSID,1);
870   if (ghosted) {
871     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
872       if (dd->arrayghostedout[i] == *iptr) {
873         iarray_start           = dd->startghostedout[i];
874         dd->arrayghostedout[i] = NULL;
875         dd->startghostedout[i] = NULL;
876         break;
877       }
878     }
879     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
880       if (!dd->arrayghostedin[i]) {
881         dd->arrayghostedin[i] = *iptr;
882         dd->startghostedin[i] = iarray_start;
883         break;
884       }
885     }
886   } else {
887     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
888       if (dd->arrayout[i] == *iptr) {
889         iarray_start    = dd->startout[i];
890         dd->arrayout[i] = NULL;
891         dd->startout[i] = NULL;
892         break;
893       }
894     }
895     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
896       if (!dd->arrayin[i]) {
897         dd->arrayin[i] = *iptr;
898         dd->startin[i] = iarray_start;
899         break;
900       }
901     }
902   }
903   PetscFunctionReturn(0);
904 }
905 
906