Actual source code: dageometry.c

petsc-3.7.5 2017-01-01
Report Typos and Errors
  1: #include <petsc/private/dmdaimpl.h>     /*I  "petscdmda.h"   I*/

  5: PETSC_STATIC_INLINE PetscErrorCode FillClosureArray_Static(DM dm, PetscSection section, PetscInt nP, const PetscInt points[], PetscScalar *vArray, PetscInt *csize, PetscScalar **array)
  6: {
  7:   PetscScalar    *a;
  8:   PetscInt       pStart, pEnd, size = 0, dof, off, d, k, i;

 12:   PetscSectionGetChart(section, &pStart, &pEnd);
 13:   for (i = 0; i < nP; ++i) {
 14:     const PetscInt p = points[i];

 16:     if ((p < pStart) || (p >= pEnd)) continue;
 17:     PetscSectionGetDof(section, p, &dof);
 18:     size += dof;
 19:   }
 20:   if (csize) *csize = size;
 21:   if (array) {
 22:     DMGetWorkArray(dm, size, PETSC_SCALAR, &a);
 23:     for (i = 0, k = 0; i < nP; ++i) {
 24:       const PetscInt p = points[i];

 26:       if ((p < pStart) || (p >= pEnd)) continue;
 27:       PetscSectionGetDof(section, p, &dof);
 28:       PetscSectionGetOffset(section, p, &off);

 30:       for (d = 0; d < dof; ++d, ++k) a[k] = vArray[off+d];
 31:     }
 32:     *array = a;
 33:   }
 34:   return(0);
 35: }

 39: PETSC_STATIC_INLINE PetscErrorCode FillClosureVec_Private(DM dm, PetscSection section, PetscInt nP, const PetscInt points[], PetscScalar *vArray, const PetscScalar *array, InsertMode mode)
 40: {
 41:   PetscInt       dof, off, d, k, i;

 45:   if ((mode == INSERT_VALUES) || (mode == INSERT_ALL_VALUES)) {
 46:     for (i = 0, k = 0; i < nP; ++i) {
 47:       PetscSectionGetDof(section, points[i], &dof);
 48:       PetscSectionGetOffset(section, points[i], &off);

 50:       for (d = 0; d < dof; ++d, ++k) vArray[off+d] = array[k];
 51:     }
 52:   } else {
 53:     for (i = 0, k = 0; i < nP; ++i) {
 54:       PetscSectionGetDof(section, points[i], &dof);
 55:       PetscSectionGetOffset(section, points[i], &off);

 57:       for (d = 0; d < dof; ++d, ++k) vArray[off+d] += array[k];
 58:     }
 59:   }
 60:   return(0);
 61: }

 65: PETSC_STATIC_INLINE PetscErrorCode GetPointArray_Private(DM dm,PetscInt n,PetscInt *points,PetscInt *rn,const PetscInt **rpoints)
 66: {
 68:   PetscInt       *work;

 71:   if (rn) *rn = n;
 72:   if (rpoints) {
 73:     DMGetWorkArray(dm,n,PETSC_INT,&work);
 74:     PetscMemcpy(work,points,n*sizeof(PetscInt));
 75:     *rpoints = work;
 76:   }
 77:   return(0);
 78: }

 82: PETSC_STATIC_INLINE PetscErrorCode RestorePointArray_Private(DM dm,PetscInt *rn,const PetscInt **rpoints)
 83: {

 87:   if (rn) *rn = 0;
 88:   if (rpoints) {
 89:     DMRestoreWorkArray(dm,*rn, PETSC_INT, (void*) rpoints);
 90:   }
 91:   return(0);
 92: }

 96: PetscErrorCode DMDAGetTransitiveClosure(DM dm, PetscInt p, PetscBool useClosure, PetscInt *closureSize, PetscInt **closure)
 97: {
 98:   PetscInt       dim = dm->dim;
 99:   PetscInt       nVx, nVy, nVz, nxF, nXF, nyF, nYF, nzF, nZF;
100:   PetscInt       pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart;

104:   if (!useClosure) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Star operation is not yet supported");
106:   DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);
107:   DMDAGetHeightStratum(dm,  0,  &cStart, &cEnd);
108:   DMDAGetHeightStratum(dm,  1,  &fStart, &fEnd);
109:   DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);
110:   DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, NULL);
111:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
112:   xfStart = fStart; xfEnd = xfStart+nXF;
113:   yfStart = xfEnd;
114:   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd);
115:   if ((p >= cStart) || (p < cEnd)) {
116:     /* Cell */
117:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
118:     else if (dim == 2) {
119:       /* 4 faces, 4 vertices
120:          Bottom-left vertex follows same order as cells
121:          Bottom y-face same order as cells
122:          Left x-face follows same order as cells
123:          We number the quad:

125:            8--3--7
126:            |     |
127:            4  0  2
128:            |     |
129:            5--1--6
130:       */
131:       PetscInt c  = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1);
132:       PetscInt v  = cy*nVx + cx +  vStart;
133:       PetscInt xf = cy*nxF + cx + xfStart;
134:       PetscInt yf = c + yfStart;

137:       if (!(*closure)) {DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);}
138:       (*closure)[0] = p; (*closure)[1] = yf; (*closure)[2] = xf+1; (*closure)[3] = yf+nyF; (*closure)[4] = xf+0; (*closure)[5] = v+0; (*closure)[6]= v+1; (*closure)[7] = v+nVx+1; (*closure)[8] = v+nVx+0;
139:     } else {
140:       /* 6 faces, 12 edges, 8 vertices
141:          Bottom-left vertex follows same order as cells
142:          Bottom y-face same order as cells
143:          Left x-face follows same order as cells
144:          We number the quad:

146:            8--3--7
147:            |     |
148:            4  0  2
149:            |     |
150:            5--1--6
151:       */
152: #if 0
153:       PetscInt c  = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1), cz = c / ((nVx-1)*(nVy-1));
154:       PetscInt v  = cy*nVx + cx +  vStart;
155:       PetscInt xf = cy*nxF + cx + xfStart;
156:       PetscInt yf = c + yfStart;

159:       if (!(*closure)) {DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);}
160: #endif
161:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
162:     }
163:   } else if ((p >= vStart) || (p < vEnd)) {
164:     /* Vertex */
166:     if (!(*closure)) {DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);}
167:     (*closure)[0] = p;
168:   } else if ((p >= fStart) || (p < fStart + nXF)) {
169:     /* X Face */
170:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
171:     else if (dim == 2) {
172:       /* 2 vertices: The bottom vertex has the same numbering as the face */
173:       PetscInt f = p - xfStart;

176:       if (!(*closure)) {DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);}
177:       (*closure)[0] = p; (*closure)[1] = f; (*closure)[2] = f+nVx;
178:     } else if (dim == 3) {
179:       /* 4 vertices */
180:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
181:     }
182:   } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) {
183:     /* Y Face */
184:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
185:     else if (dim == 2) {
186:       /* 2 vertices: The left vertex has the same numbering as the face */
187:       PetscInt f = p - yfStart;

190:       if (!(*closure)) {DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);}
191:       (*closure)[0] = p; (*closure)[1] = f; (*closure)[2]= f+1;
192:     } else if (dim == 3) {
193:       /* 4 vertices */
194:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
195:     }
196:   } else {
197:     /* Z Face */
198:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
199:     else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D");
200:     else if (dim == 3) {
201:       /* 4 vertices */
202:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
203:     }
204:   }
205:   return(0);
206: }

210: PetscErrorCode DMDARestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useClosure, PetscInt *closureSize, PetscInt **closure)
211: {

215:   DMRestoreWorkArray(dm, 0, PETSC_INT, closure);
216:   return(0);
217: }

221: PetscErrorCode DMDAGetClosure(DM dm, PetscSection section, PetscInt p,PetscInt *n,const PetscInt **closure)
222: {
223:   PetscInt       dim = dm->dim;
224:   PetscInt       nVx, nVy, nxF, nXF, nyF, nYF, nzF, nZF;
225:   PetscInt       pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart;

232:   if (!section) {DMGetDefaultSection(dm, &section);}
233:   if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This DM has not default PetscSection");
234:   DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);
235:   DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);
236:   DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);
237:   DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);
238:   DMDAGetNumVertices(dm, &nVx, &nVy, NULL, NULL);
239:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
240:   xfStart = fStart; xfEnd = xfStart+nXF;
241:   yfStart = xfEnd;
242:   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd);
243:   if ((p >= cStart) || (p < cEnd)) {
244:     /* Cell */
245:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
246:     else if (dim == 2) {
247:       /* 4 faces, 4 vertices
248:          Bottom-left vertex follows same order as cells
249:          Bottom y-face same order as cells
250:          Left x-face follows same order as cells
251:          We number the quad:

253:            8--3--7
254:            |     |
255:            4  0  2
256:            |     |
257:            5--1--6
258:       */
259:       PetscInt c  = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1);
260:       PetscInt v  = cy*nVx + cx +  vStart;
261:       PetscInt xf = cy*nxF + cx + xfStart;
262:       PetscInt yf = c + yfStart;
263:       PetscInt points[9];

265:       /* Note: initializer list is not computable at compile time, hence we fill the array manually */
266:       points[0] = p; points[1] = yf; points[2] = xf+1; points[3] = yf+nyF; points[4] = xf+0; points[5] = v+0; points[6]= v+1; points[7] = v+nVx+1; points[8] = v+nVx+0;

268:       GetPointArray_Private(dm,9,points,n,closure);
269:     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
270:   } else if ((p >= vStart) || (p < vEnd)) {
271:     /* Vertex */
272:     GetPointArray_Private(dm,1,&p,n,closure);
273:   } else if ((p >= fStart) || (p < fStart + nXF)) {
274:     /* X Face */
275:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
276:     else if (dim == 2) {
277:       /* 2 vertices: The bottom vertex has the same numbering as the face */
278:       PetscInt f = p - xfStart;
279:       PetscInt points[3];

281:       points[0] = p; points[1] = f; points[2] = f+nVx;
282:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken");
283:       GetPointArray_Private(dm,3,points,n,closure);
284:     } else if (dim == 3) {
285:       /* 4 vertices */
286:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
287:     }
288:   } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) {
289:     /* Y Face */
290:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
291:     else if (dim == 2) {
292:       /* 2 vertices: The left vertex has the same numbering as the face */
293:       PetscInt f = p - yfStart;
294:       PetscInt points[3];

296:       points[0] = p; points[1] = f; points[2]= f+1;
297:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken");
298:       GetPointArray_Private(dm, 3, points, n, closure);
299:     } else if (dim == 3) {
300:       /* 4 vertices */
301:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
302:     }
303:   } else {
304:     /* Z Face */
305:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
306:     else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D");
307:     else if (dim == 3) {
308:       /* 4 vertices */
309:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
310:     }
311:   }
312:   return(0);
313: }

317: /* Zeros n and closure. */
318: PetscErrorCode DMDARestoreClosure(DM dm, PetscSection section, PetscInt p,PetscInt *n,const PetscInt **closure)
319: {

326:   RestorePointArray_Private(dm,n,closure);
327:   return(0);
328: }

332: PetscErrorCode DMDAGetClosureScalar(DM dm, PetscSection section, PetscInt p, PetscScalar *vArray, PetscInt *csize, PetscScalar **values)
333: {
334:   PetscInt       dim = dm->dim;
335:   PetscInt       nVx, nVy, nxF, nXF, nyF, nYF, nzF, nZF;
336:   PetscInt       pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart;

343:   if (!section) {DMGetDefaultSection(dm, &section);}
344:   if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This DM has not default PetscSection");
345:   DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);
346:   DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);
347:   DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);
348:   DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);
349:   DMDAGetNumVertices(dm, &nVx, &nVy, NULL, NULL);
350:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
351:   xfStart = fStart; xfEnd = xfStart+nXF;
352:   yfStart = xfEnd;  yfEnd = yfStart+nYF;
353:   zfStart = yfEnd;
354:   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd);
355:   if ((p >= cStart) || (p < cEnd)) {
356:     /* Cell */
357:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
358:     else if (dim == 2) {
359:       /* 4 faces, 4 vertices
360:          Bottom-left vertex follows same order as cells
361:          Bottom y-face same order as cells
362:          Left x-face follows same order as cells
363:          We number the quad:

365:            8--3--7
366:            |     |
367:            4  0  2
368:            |     |
369:            5--1--6
370:       */
371:       PetscInt c  = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1);
372:       PetscInt v  = cy*nVx + cx +  vStart;
373:       PetscInt xf = cx*nxF + cy + xfStart;
374:       PetscInt yf = c + yfStart;
375:       PetscInt points[9];

377:       points[0] = p;
378:       points[1] = yf;  points[2] = xf+nxF; points[3] = yf+nyF;  points[4] = xf;
379:       points[5] = v+0; points[6] = v+1;    points[7] = v+nVx+1; points[8] = v+nVx+0;
380:       FillClosureArray_Static(dm, section, 9, points, vArray, csize, values);
381:     } else {
382:       /* 6 faces, 8 vertices
383:          Bottom-left-back vertex follows same order as cells
384:          Back z-face follows same order as cells
385:          Bottom y-face follows same order as cells
386:          Left x-face follows same order as cells

388:               14-----13
389:               /|    /|
390:              / | 2 / |
391:             / 5|  /  |
392:           10-----9  4|
393:            |  11-|---12
394:            |6 /  |  /
395:            | /1 3| /
396:            |/    |/
397:            7-----8
398:       */
399:       PetscInt c = p - cStart;
400:       PetscInt points[15];

402:       points[0]  = p; points[1] = c+zfStart; points[2] = c+zfStart+nzF; points[3] = c+yfStart; points[4] = c+xfStart+nxF; points[5] = c+yfStart+nyF; points[6] = c+xfStart;
403:       points[7]  = c+vStart+0; points[8] = c+vStart+1; points[9] = c+vStart+nVx+1; points[10] = c+vStart+nVx+0; points[11] = c+vStart+nVx*nVy+0;
404:       points[12] = c+vStart+nVx*nVy+1; points[13] = c+vStart+nVx*nVy+nVx+1; points[14] = c+vStart+nVx*nVy+nVx+0;

406:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken");
407:       FillClosureArray_Static(dm, section, 15, points, vArray, csize, values);
408:     }
409:   } else if ((p >= vStart) || (p < vEnd)) {
410:     /* Vertex */
411:     FillClosureArray_Static(dm, section, 1, &p, vArray, csize, values);
412:   } else if ((p >= fStart) || (p < fStart + nXF)) {
413:     /* X Face */
414:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
415:     else if (dim == 2) {
416:       /* 2 vertices: The bottom vertex has the same numbering as the face */
417:       PetscInt f = p - xfStart;
418:       PetscInt points[3];

420:       points[0] = p; points[1] = f; points[2] = f+nVx;
421:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken");
422:       FillClosureArray_Static(dm, section, 3, points, vArray, csize, values);
423:     } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
424:   } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) {
425:     /* Y Face */
426:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
427:     else if (dim == 2) {
428:       /* 2 vertices: The left vertex has the same numbering as the face */
429:       PetscInt f = p - yfStart;
430:       PetscInt points[3];

432:       points[0] = p; points[1] = f; points[2] = f+1;
433:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken");
434:       FillClosureArray_Static(dm, section, 3, points, vArray, csize, values);
435:     } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
436:   } else {
437:     /* Z Face */
438:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
439:     else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D");
440:     else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
441:   }
442:   return(0);
443: }

447: PetscErrorCode DMDAVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt p, PetscInt *csize, PetscScalar **values)
448: {
449:   PetscScalar    *vArray;

456:   VecGetArray(v, &vArray);
457:   DMDAGetClosureScalar(dm, section, p, vArray, csize, values);
458:   VecRestoreArray(v, &vArray);
459:   return(0);
460: }

464: PetscErrorCode DMDARestoreClosureScalar(DM dm, PetscSection section, PetscInt p, PetscScalar *vArray, PetscInt *csize, PetscScalar **values)
465: {

471:   DMRestoreWorkArray(dm, csize ? *csize : 0, PETSC_SCALAR, (void*) values);
472:   return(0);
473: }

477: PetscErrorCode DMDAVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt p, PetscInt *csize, PetscScalar **values)
478: {

485:   DMDARestoreClosureScalar(dm, section, p, NULL, csize, values);
486:   return(0);
487: }

491: PetscErrorCode DMDASetClosureScalar(DM dm, PetscSection section, PetscInt p,PetscScalar *vArray, const PetscScalar *values, InsertMode mode)
492: {
493:   PetscInt       dim = dm->dim;
494:   PetscInt       nVx, nVy, nxF, nXF, nyF, nYF, nzF, nZF, nCx, nCy;
495:   PetscInt       pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart;

502:   if (!section) {DMGetDefaultSection(dm, &section);}
503:   if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This DM has not default PetscSection");
504:   DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);
505:   DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);
506:   DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);
507:   DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);
508:   DMDAGetNumCells(dm, &nCx, &nCy, NULL, NULL);
509:   DMDAGetNumVertices(dm, &nVx, &nVy, NULL, NULL);
510:   DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);
511:   xfStart = fStart; xfEnd = xfStart+nXF;
512:   yfStart = xfEnd;  yfEnd = yfStart+nYF;
513:   zfStart = yfEnd;
514:   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd);
515:   if ((p >= cStart) || (p < cEnd)) {
516:     /* Cell */
517:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
518:     else if (dim == 2) {
519:       /* 4 faces, 4 vertices
520:          Bottom-left vertex follows same order as cells
521:          Bottom y-face same order as cells
522:          Left x-face follows same order as cells
523:          We number the quad:

525:            8--3--7
526:            |     |
527:            4  0  2
528:            |     |
529:            5--1--6
530:       */
531:       PetscInt c = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1);
532:       PetscInt v  = cy*nVx + cx +  vStart;
533:       PetscInt xf = cx*nxF + cy + xfStart;
534:       PetscInt yf = c + yfStart;
535:       PetscInt points[9];

537:       points[0] = p;
538:       points[1] = yf;  points[2] = xf+nxF; points[3] = yf+nyF;  points[4] = xf;
539:       points[5] = v+0; points[6] = v+1;    points[7] = v+nVx+1; points[8] = v+nVx+0;
540:       FillClosureVec_Private(dm, section, 9, points, vArray, values, mode);
541:     } else {
542:       /* 6 faces, 8 vertices
543:          Bottom-left-back vertex follows same order as cells
544:          Back z-face follows same order as cells
545:          Bottom y-face follows same order as cells
546:          Left x-face follows same order as cells

548:               14-----13
549:               /|    /|
550:              / | 2 / |
551:             / 5|  /  |
552:           10-----9  4|
553:            |  11-|---12
554:            |6 /  |  /
555:            | /1 3| /
556:            |/    |/
557:            7-----8
558:       */
559:       PetscInt c = p - cStart;
560:       PetscInt points[15];

562:       points[0]  = p; points[1] = c+zfStart; points[2] = c+zfStart+nzF; points[3] = c+yfStart; points[4] = c+xfStart+nxF; points[5] = c+yfStart+nyF; points[6] = c+xfStart;
563:       points[7]  = c+vStart+0; points[8] = c+vStart+1; points[9] = c+vStart+nVx+1; points[10] = c+vStart+nVx+0; points[11] = c+vStart+nVx*nVy+0; points[12] = c+vStart+nVx*nVy+1;
564:       points[13] = c+vStart+nVx*nVy+nVx+1; points[14] = c+vStart+nVx*nVy+nVx+0;
565:       FillClosureVec_Private(dm, section, 15, points, vArray, values, mode);
566:     }
567:   } else if ((p >= vStart) || (p < vEnd)) {
568:     /* Vertex */
569:     FillClosureVec_Private(dm, section, 1, &p, vArray, values, mode);
570:   } else if ((p >= fStart) || (p < fStart + nXF)) {
571:     /* X Face */
572:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
573:     else if (dim == 2) {
574:       /* 2 vertices: The bottom vertex has the same numbering as the face */
575:       PetscInt f = p - xfStart;
576:       PetscInt points[3];

578:       points[0] = p; points[1] = f; points[2] = f+nVx;
579:       FillClosureVec_Private(dm, section, 3, points, vArray, values, mode);
580:     } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
581:   } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) {
582:     /* Y Face */
583:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
584:     else if (dim == 2) {
585:       /* 2 vertices: The left vertex has the same numbering as the face */
586:       PetscInt f = p - yfStart;
587:       PetscInt points[3];

589:       points[0] = p; points[1] = f; points[2] = f+1;
590:       FillClosureVec_Private(dm, section, 3, points, vArray, values, mode);
591:     } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
592:   } else {
593:     /* Z Face */
594:     if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D");
595:     else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D");
596:     else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented");
597:   }
598:   return(0);
599: }

603: PetscErrorCode DMDAVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt p, const PetscScalar *values, InsertMode mode)
604: {
605:   PetscScalar    *vArray;

612:   VecGetArray(v,&vArray);
613:   DMDASetClosureScalar(dm,section,p,vArray,values,mode);
614:   VecRestoreArray(v,&vArray);
615:   return(0);
616: }

620: /*@
621:   DMDAConvertToCell - Convert (i,j,k) to local cell number

623:   Not Collective

625:   Input Parameter:
626: + da - the distributed array
627: - s - A MatStencil giving (i,j,k)

629:   Output Parameter:
630: . cell - the local cell number

632:   Level: developer

634: .seealso: DMDAVecGetClosure()
635: @*/
636: PetscErrorCode DMDAConvertToCell(DM dm, MatStencil s, PetscInt *cell)
637: {
638:   DM_DA          *da = (DM_DA*) dm->data;
639:   const PetscInt dim = dm->dim;
640:   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys /*, mz = da->Ze - da->Zs*/;
641:   const PetscInt il  = s.i - da->Xs/da->w, jl = dim > 1 ? s.j - da->Ys : 0, kl = dim > 2 ? s.k - da->Zs : 0;

644:   *cell = -1;
645:   if ((s.i < da->Xs/da->w) || (s.i >= da->Xe/da->w))    SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Stencil i %d should be in [%d, %d)", s.i, da->Xs/da->w, da->Xe/da->w);
646:   if ((dim > 1) && ((s.j < da->Ys) || (s.j >= da->Ye))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Stencil j %d should be in [%d, %d)", s.j, da->Ys, da->Ye);
647:   if ((dim > 2) && ((s.k < da->Zs) || (s.k >= da->Ze))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Stencil k %d should be in [%d, %d)", s.k, da->Zs, da->Ze);
648:   *cell = (kl*my + jl)*mx + il;
649:   return(0);
650: }

654: PetscErrorCode DMDAComputeCellGeometry_2D(DM dm, const PetscScalar vertices[], const PetscReal refPoint[], PetscReal J[], PetscReal invJ[], PetscReal *detJ)
655: {
656:   const PetscScalar x0   = vertices[0];
657:   const PetscScalar y0   = vertices[1];
658:   const PetscScalar x1   = vertices[2];
659:   const PetscScalar y1   = vertices[3];
660:   const PetscScalar x2   = vertices[4];
661:   const PetscScalar y2   = vertices[5];
662:   const PetscScalar x3   = vertices[6];
663:   const PetscScalar y3   = vertices[7];
664:   const PetscScalar f_01 = x2 - x1 - x3 + x0;
665:   const PetscScalar g_01 = y2 - y1 - y3 + y0;
666:   const PetscScalar x    = refPoint[0];
667:   const PetscScalar y    = refPoint[1];
668:   PetscReal         invDet;
669:   PetscErrorCode    ierr;

672: #if 0
673:   PetscPrintf(PETSC_COMM_SELF, "Cell (%g,%g)--(%g,%g)--(%g,%g)--(%g,%g)\n",
674:                      PetscRealPart(x0),PetscRealPart(y0),PetscRealPart(x1),PetscRealPart(y1),PetscRealPart(x2),PetscRealPart(y2),PetscRealPart(x3),PetscRealPart(y3));
675:   PetscPrintf(PETSC_COMM_SELF, "Ref Point (%g,%g)\n", PetscRealPart(x), PetscRealPart(y));
676: #endif
677:   J[0]    = PetscRealPart(x1 - x0 + f_01*y) * 0.5; J[1] = PetscRealPart(x3 - x0 + f_01*x) * 0.5;
678:   J[2]    = PetscRealPart(y1 - y0 + g_01*y) * 0.5; J[3] = PetscRealPart(y3 - y0 + g_01*x) * 0.5;
679:   *detJ   = J[0]*J[3] - J[1]*J[2];
680:   invDet  = 1.0/(*detJ);
681:   if (invJ) {
682:     invJ[0] =  invDet*J[3]; invJ[1] = -invDet*J[1];
683:     invJ[2] = -invDet*J[2]; invJ[3] =  invDet*J[0];
684:   }
685:   PetscLogFlops(30);
686:   return(0);
687: }

691: PetscErrorCode DMDAComputeCellGeometryFEM(DM dm, PetscInt cell, PetscQuadrature quad, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal detJ[])
692: {
693:   DM               cdm;
694:   Vec              coordinates;
695:   const PetscReal *quadPoints;
696:   PetscScalar     *vertices = NULL;
697:   PetscInt         numQuadPoints, csize, dim, d, q;
698:   PetscErrorCode   ierr;

702:   DMDAGetInfo(dm, &dim, 0,0,0,0,0,0,0,0,0,0,0,0);
703:   DMGetCoordinatesLocal(dm, &coordinates);
704:   DMGetCoordinateDM(dm, &cdm);
705:   DMDAVecGetClosure(cdm, NULL, coordinates, cell, &csize, &vertices);
706:   for (d = 0; d < dim; ++d) v0[d] = PetscRealPart(vertices[d]);
707:   switch (dim) {
708:   case 2:
709:     PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, NULL);
710:     for (q = 0; q < numQuadPoints; ++q) {
711:       DMDAComputeCellGeometry_2D(dm, vertices, &quadPoints[q*dim], J, invJ, detJ);
712:     }
713:     break;
714:   default:
715:     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Dimension %d not supported", dim);
716:   }
717:   DMDAVecRestoreClosure(cdm, NULL, coordinates, cell, &csize, &vertices);
718:   return(0);
719: }