Actual source code: tri1d.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: tri1d.c,v 1.38 2000/10/17 13:48:55 knepley Exp $";
  3: #endif

  5: /* Implements 1d unstructured grids */
  6: #include "src/mesh/impls/triangular/1d/1dimpl.h"         /*I "mesh.h" I*/
  7: #include "tri1d.h"
  8: #include "tri1d_Simple.h"

 10: extern int PartitionGhostNodeIndex_Private(Partition, int, int *);

 12: /*--------------------------------------------- Generic Operations ---------------------------------------------------*/
 13: static int MeshDestroy_Triangular_1D(Mesh mesh) {
 14:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
 15:   int              ierr;

 18:   if (tri->nodes != PETSC_NULL) {
 19:     PetscFree(tri->nodes);
 20:     PetscFree(tri->markers);
 21:     PetscFree(tri->degrees);
 22:   }
 23:   if (tri->nodesOld != PETSC_NULL) {
 24:     PetscFree(tri->nodesOld);
 25:   }
 26:   if (tri->edges != PETSC_NULL) {
 27:     PetscFree(tri->edges);
 28:   }
 29:   if (tri->faces != PETSC_NULL) {
 30:     PetscFree(tri->faces);
 31:   }
 32:   if (tri->neighbors != PETSC_NULL) {
 33:     PetscFree(tri->neighbors);
 34:   }
 35:   if (tri->bdNodes != PETSC_NULL) {
 36:     PetscFree(tri->bdNodes);
 37:     PetscFree(tri->bdMarkers);
 38:     PetscFree(tri->bdBegin);
 39:   }
 40: #if 0
 41:   if (tri->bdCtx != PETSC_NULL) {
 42:     MeshBoundaryDestroy(tri->bdCtx);
 43:   }
 44:   if (tri->bdCtxNew != PETSC_NULL) {
 45:     MeshBoundaryDestroy(tri->bdCtxNew);
 46:   }
 47: #endif
 48:   if (tri->areas != PETSC_NULL) {
 49:     PetscFree(tri->areas);
 50:   }
 51:   PetscFree(tri);
 52:   if (mesh->support != PETSC_NULL) {
 53:     PetscFree(mesh->support);
 54:   }
 55:   PartitionDestroy(mesh->part);
 56:   if (mesh->nodeOrdering != PETSC_NULL) {
 57:     AODestroy(mesh->nodeOrdering);
 58:   }
 59:   if (mesh->coarseMap != PETSC_NULL) {
 60:     AODestroy(mesh->coarseMap);
 61:   }

 63:   return(0);
 64: }

 66: /*------------------------------------------ Mesh-Specific Operations ------------------------------------------------*/
 67: static int MeshPartition_Triangular_1D(Mesh mesh) {

 71:   PartitionCreate(mesh, &mesh->part);
 72:   PartitionSetType(mesh->part, PARTITION_TRIANGULAR_1D);
 73:   mesh->partitioned = 1;
 74:   PetscFunctionReturn(ierr);
 75: }

 77: static int MeshCoarsen_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
 78:   SETERRQ(PETSC_ERR_SUP, " ");
 79: }

 81: static int MeshResetNodes_Triangular_1D(Mesh mesh, PetscTruth resetBd) {
 82:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
 83:   int             *elements   = tri->edges;
 84:   double          *nodes      = tri->nodes;
 85:   int              numCorners = mesh->numCorners;
 86:   int              elem, node1, node2, midNode;

 89:   if (numCorners == 2) return(0);

 91:   for(elem = 0; elem < mesh->part->numOverlapElements; elem++) {
 92:     node1   = elements[elem*numCorners+0];
 93:     node2   = elements[elem*numCorners+1];
 94:     midNode = elements[elem*numCorners+2];
 95:     nodes[midNode*2]   = MeshPeriodicX(mesh, 0.5*(nodes[node1*2]   +
 96:                                                   MeshPeriodicRelativeX(mesh, nodes[node2*2],   nodes[node1*2])));
 97:     nodes[midNode*2+1] = MeshPeriodicY(mesh, 0.5*(nodes[node1*2+1] +
 98:                                                   MeshPeriodicRelativeY(mesh, nodes[node2*2+1], nodes[node1*2+1])));
 99:   }
100:   return(0);
101: }

103: static int MeshSaveMesh_Triangular_1D(Mesh mesh) {
104:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
105:   int              dim = mesh->dim;
106:   int              numOverlapNodes;
107:   int              ierr;

110:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
111:   if (tri->nodesOld == PETSC_NULL) {
112:     PetscMalloc(numOverlapNodes*dim * sizeof(double), &tri->nodesOld);
113:     PetscLogObjectMemory(mesh, numOverlapNodes*dim * sizeof(double));
114:   }
115:   PetscMemcpy(tri->nodesOld, tri->nodes, numOverlapNodes*dim * sizeof(double));
116:   return(0);
117: }

119: static int MeshRestoreMesh_Triangular_1D(Mesh mesh) {
120:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
121:   int              dim = mesh->dim;
122:   int              numOverlapNodes;
123:   int              ierr;

126:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
127:   if (tri->nodesOld != PETSC_NULL) {
128:     PetscMemcpy(tri->nodes, tri->nodesOld, numOverlapNodes*dim * sizeof(double));
129:   }
130:   return(0);
131: }

133: /*-------------------------------------------- Mesh Query Functions --------------------------------------------------*/
134: static int MeshUpdateBoundingBox_Triangular_1D(Mesh mesh) {
135:   Mesh_Triangular *tri   = (Mesh_Triangular *) mesh->data;
136:   double          *nodes = tri->nodes;
137:   Partition        part;
138:   int              numOverlapNodes;
139:   int              node;
140:   int              ierr;

142:   /* Calculate the local bounding box */
144:   MeshGetPartition(mesh, &part);
145:   PartitionGetNumOverlapNodes(part, &numOverlapNodes);
146:   if (numOverlapNodes > 0) {
147:     mesh->locStartX = mesh->locEndX = nodes[0];
148:   } else {
149:     mesh->locStartX = mesh->locEndX = 0.0;
150:   }
151:   for(node = 0; node < numOverlapNodes; node++) {
152:     if (nodes[node] < mesh->locStartX) mesh->locStartX = nodes[node];
153:     if (nodes[node] > mesh->locEndX)   mesh->locEndX   = nodes[node];
154:   }
155:   mesh->locSizeX = mesh->locEndX - mesh->locStartX;
156:   return(0);
157: }

159: static int MeshIsDistorted_Triangular_1D(Mesh mesh, PetscTruth *flag) {
160:   Mesh_Triangular *tri            = (Mesh_Triangular *) mesh->data;
161:   double          *nodes          = tri->nodes;
162:   int             *elements       = tri->edges;
163:   int              numCorners     = mesh->numCorners;
164:   int              numElements    = mesh->numEdges;
165:   double           maxAspectRatio = mesh->maxAspectRatio;
166:   double           area;        /* Twice the area of the triangle */
167:   double           min;
168:   PetscTruth       locFlag;
169:   int              elem;
170:   int              locRetVal;
171:   int              retVal;
172:   int              ierr;

175:   for(elem = 0, locFlag = PETSC_FALSE, locRetVal = 0, min = mesh->sizeX; elem < numElements; elem++) {
176:     /* Find the area */
177:     area = MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+1]*2] - nodes[elements[elem*numCorners]*2]);
178:     /* Check for inverted elements */
179:     if (area < 0.0) {
180:       locFlag   = PETSC_TRUE;
181:       locRetVal = 1;
182:       break;
183:     } else if (area == 0.0) {
184:       SETERRQ1(PETSC_ERR_ARG_CORRUPT, "Element %d has no area", elem);
185:     }

187:     /* We cannot bail here since we must check for inverted elements */
188:     min = PetscMin(min, area);
189:   }
190:   if (min < 1.0/maxAspectRatio) {
191:     PetscLogInfo(mesh, "Area too small in element %d: %g < %gn", elem, min, 1.0/maxAspectRatio);
192:     locFlag = PETSC_TRUE;
193:   } else {
194:     PetscLogInfo(mesh, "Area in element %d: %gn", elem, min);
195:   }
196:   PetscLogFlops(elem);
197:   MPI_Allreduce(&locFlag,   flag,    1, MPI_INT, MPI_LOR, mesh->comm);
198:   MPI_Allreduce(&locRetVal, &retVal, 1, MPI_INT, MPI_LOR, mesh->comm);
199:   PetscFunctionReturn(retVal);
200: }

202: /*---------------------------------------- Mesh Boundary Query Functions ---------------------------------------------*/
203: static int MeshGetBoundarySize_Triangular_1D(Mesh mesh, int boundary, int *size) {
204:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
205:   int              b; /* Canonical boundary number */

208:   /* Find canonical boundary number */
209:   for(b = 0; b < mesh->numBd; b++) {
210:     if (tri->bdMarkers[b] == boundary) break;
211:   }
212:   if (b == mesh->numBd) SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid boundary specified");
213:   *size = tri->bdBegin[b+1] - tri->bdBegin[b];
214:   if ((*size != 0) && (*size != 1)) SETERRQ1(PETSC_ERR_PLIB, "Invalid boundary size %d", *size);
215:   return(0);
216: }

218: static int MeshGetBoundaryIndex_Triangular_1D(Mesh mesh, int boundary, int *index) {
219:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
220:   int              b; /* Canonical boundary number */

223:   /* Find canonical boundary number */
224:   for(b = 0; b < mesh->numBd; b++) {
225:     if (tri->bdMarkers[b] == boundary) break;
226:   }
227:   if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary marker %d", boundary);
228:   *index = b;
229:   return(0);
230: }

232: static int MeshGetBoundaryStart_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
233:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
234:   int              b; /* Canonical boundary number */
235:   int              ierr;

238:   /* Find canonical boundary number */
239:   for(b = 0; b < mesh->numBd; b++) {
240:     if (tri->bdMarkers[b] == boundary) break;
241:   }
242:   if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary  %d specified", boundary);
243:   if (mesh->activeBd != -1) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE, "Already iterating over boundary %d", mesh->activeBd);
244:   /* Find first boundary node */
245:   mesh->activeBd     = b;
246:   mesh->activeBdOld  = b;
247:   mesh->activeBdNode = tri->bdBegin[b] - 1;
248:   MeshGetBoundaryNext(mesh, boundary, ghost, node);
249:   PetscFunctionReturn(ierr);
250: }

252: static int MeshGetBoundaryNext_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
253:   Mesh_Triangular         *tri      = (Mesh_Triangular *) mesh->data;
254:   Partition                p        = mesh->part;
255:   Partition_Triangular_1D *q        = (Partition_Triangular_1D *) p->data;
256:   int                      numBd    = mesh->numBd;
257:   int                      numNodes = mesh->numNodes;
258:   int                      b;        /* Canonical boundary number */
259:   int                      tempNode; /* Canonical local node number */
260:   int                      ierr;

263:   /* Find canonical boundary number */
264:   for(b = 0; b < numBd; b++) {
265:     if (tri->bdMarkers[b] == boundary) break;
266:   }
267:   if (b == numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary %d specified", boundary);
268:   /* Find next boundary node */
269:   if (mesh->activeBd != b) SETERRQ1(PETSC_ERR_ARG_WRONG, "Boundary %d not active", boundary);
270:   do {
271:     mesh->activeBdNode++;
272:     if (mesh->activeBdNode == tri->bdBegin[b+1]) {
273:       mesh->activeBd = mesh->activeBdNode = -1;
274:       *node = -1;
275:       return(0);
276:     }
277:     tempNode = tri->bdNodes[mesh->activeBdNode] - q->firstNode[p->rank];
278:     /* Translate ghost nodes */
279:     if (ghost == PETSC_TRUE) {
280:       if ((tempNode < 0) || (tempNode >= numNodes)) {
281:         PartitionGhostNodeIndex_Private(p, tri->bdNodes[mesh->activeBdNode], &tempNode);
282:         if (ierr == 0) {
283:           tempNode += numNodes;
284:           break;
285:         }
286:       }
287:     }
288:   }
289:   while((tempNode < 0) || (tempNode >= numNodes));
290:   *node = tempNode;
291:   return(0);
292: }

294: static int MeshGetActiveBoundary_Triangular_1D(Mesh mesh, int *boundary) {
295:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;

298:   if (mesh->activeBdOld >= 0) {
299:     *boundary = tri->bdMarkers[mesh->activeBdOld];
300:   } else {
301:     *boundary = 0;
302:   }
303:   return(0);
304: }

306: /*------------------------------------------ Mesh Node Query Functions -----------------------------------------------*/
307: static int MeshGetNodeBoundary_Triangular_1D(Mesh mesh, int node, int *bd) {
308:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
309: #ifdef PETSC_USE_BOPT_g
310:   int              numOverlapNodes;
311:   int              ierr;
312: #endif

315: #ifdef PETSC_USE_BOPT_g
316:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
317:   if ((node < 0) || (node >= numOverlapNodes)) {
318:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
319:   }
320: #endif
321:   *bd = tri->markers[node];
322:   return(0);
323: }

325: static int MeshNodeIsVertex_Triangular_1D(Mesh mesh, int node, PetscTruth *isVertex) {
326:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
327: #ifdef PETSC_USE_BOPT_g
328:   int              numOverlapNodes;
329:   int              ierr;
330: #endif

333: #ifdef PETSC_USE_BOPT_g
334:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
335:   if ((node < 0) || (node >= numOverlapNodes)) {
336:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
337:   }
338: #endif
339:   if (tri->degrees[node] == 0) {
340:     *isVertex = PETSC_FALSE;
341:   } else {
342:     *isVertex = PETSC_TRUE;
343:   }
344:   return(0);
345: }

347: static int MeshGetNodeCoords_Triangular_1D(Mesh mesh, int node, double *x, double *y, double *z) {
348:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
349: #ifdef PETSC_USE_BOPT_g
350:   int              numOverlapNodes;
351:   int              ierr;
352: #endif

355: #ifdef PETSC_USE_BOPT_g
356:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
357:   if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
358: #endif
359:   if (x != PETSC_NULL) *x = tri->nodes[node];
360:   return(0);
361: }

363: static int MeshSetNodeCoords_Triangular_1D(Mesh mesh, int node, double x, double y, double z) {
364:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
365: #ifdef PETSC_USE_BOPT_g
366:   int              numOverlapNodes;
367:   int              ierr;
368: #endif

371: #ifdef PETSC_USE_BOPT_g
372:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
373:   if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
374: #endif
375:   tri->nodes[node] = MeshPeriodicX(mesh, x);
376:   return(0);
377: }

379: static int MeshGetNodeCoordsSaved_Triangular_1D(Mesh mesh, int node, double *x, double *y, double *z) {
380:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
381: #ifdef PETSC_USE_BOPT_g
382:   int              numOverlapNodes;
383:   int              ierr;
384: #endif

387: #ifdef PETSC_USE_BOPT_g
388:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
389:   if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
390: #endif
391:   if (tri->nodesOld != PETSC_NULL) {
392:     if (x != PETSC_NULL) *x = tri->nodesOld[node];
393:   } else {
394:     if (x != PETSC_NULL) *x = tri->nodes[node];
395:   }
396:   return(0);
397: }

399: static int MeshNearestNode_Triangular_1D(Mesh mesh, double x, double y, double z, PetscTruth outsideDomain, int *node) {
400:   Mesh_Triangular         *tri        = (Mesh_Triangular *) mesh->data;
401:   Partition                p          = mesh->part;
402:   Partition_Triangular_1D *q          = (Partition_Triangular_1D *) p->data;
403:   int                      numCorners = mesh->numCorners;
404:   int                     *elements   = tri->edges;
405:   int                      numNodes   = mesh->numNodes;
406:   double                  *nodes      = tri->nodes;
407:   int                     *firstNode  = q->firstNode;
408:   int                      rank       = p->rank;
409:   int                      elem;
410:   double                   minDist, dist, allMinDist;
411:   int                      minNode, globalMinNode, allMinNode;
412:   int                      corner, n;
413:   int                      ierr;

416:   if (outsideDomain == PETSC_FALSE) {
417:     MeshLocatePoint(mesh, x, y, z, &elem);
418:     if (elem >= 0) {
419:       minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners]] - x));
420:       minNode = elements[elem*numCorners];
421:       for(corner = 1; corner < numCorners; corner++) {
422:         dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+corner]] - x));
423:         if (dist < minDist) {
424:           minDist = dist;
425:           minNode = elements[elem*numCorners+corner];
426:         }
427:       }
428:       PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
429:     } else {
430:       minNode       = -1;
431:       globalMinNode = -1;
432:     }
433:   } else {
434:     /* Brute force check */
435:     minNode = 0;
436:     minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[0] - x));
437:     for(n = 1; n < numNodes; n++) {
438:       dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[n] - x));
439:       if (dist < minDist) {
440:         minDist = dist;
441:         minNode = n;
442:       }
443:     }

445:     /* Find the minimum distance */
446:     MPI_Allreduce(&minDist, &allMinDist, 1, MPI_DOUBLE, MPI_MIN, p->comm);
447:     if (minDist == allMinDist) {
448:       PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
449:     } else {
450:       globalMinNode = -1;
451:     }
452:   }

454:   /* We might still have ties, i.e. the minimum node is a ghost node */
455:   MPI_Allreduce(&globalMinNode, &allMinNode, 1, MPI_INT, MPI_MAX, p->comm);
456:   if ((allMinNode >= firstNode[rank]) && (allMinNode < firstNode[rank+1])) {
457:     *node = allMinNode - firstNode[rank];
458:   } else {
459:     *node = -1;
460:   }
461:   if (allMinNode < 0) PetscFunctionReturn(1);

463:   return(0);
464: }

466: static int MeshGetNodeSupport_Triangular_1D(Mesh mesh, int node, int startElem, int *degree, int **support) {
467:   Mesh_Triangular *tri                = (Mesh_Triangular *) mesh->data;
468:   int              numOverlapElements = mesh->numEdges;
469:   int              numCorners         = mesh->numCorners;
470:   int             *elements           = tri->edges;
471:   int             *neighbors          = tri->neighbors;
472:   int              deg                = -1;
473:   int              firstElem;
474:   int              elem, neighbor, corner;

477:   /* First check suggested element */
478:   firstElem = -1;
479:   for(corner = 0; corner < numCorners; corner++) {
480:     if (elements[startElem*numCorners+corner] == node) {
481:       firstElem = startElem;
482:       if (corner >= 2) {
483:         deg = 1;
484:       } else {
485:         deg = 0;
486:       }
487:       break;
488:     }
489:   }

491:   /* Locate an element containing the node */
492:   if (mesh->part != PETSC_NULL) {
493:     numOverlapElements = mesh->part->numOverlapElements;
494:   }
495:   for(elem = 0; (elem < numOverlapElements) && (firstElem < 0); elem++) {
496:     for(corner = 0; corner < numCorners; corner++) {
497:       if (elements[elem*numCorners+corner] == node) {
498:         firstElem = elem;
499:         if (corner >= 2) {
500:           deg = 1;
501:         } else {
502:           deg = 0;
503:         }
504:         break;
505:       }
506:     }
507:   }
508:   if (firstElem < 0) {
509:     SETERRQ1(PETSC_ERR_ARG_WRONG, "Node %d not found in mesh", node);
510:   }

512:   /* Check for midnode */
513:   if (deg != 0) {
514:     mesh->support[0] = firstElem;
515:     mesh->support[1] = -1;
516:     *support = mesh->support;
517:     *degree  = deg;
518:     return(0);
519:   }

521:   /* Add element to the list */
522:   mesh->support[deg++] = firstElem;
523:   /* Look for a neighbor containing the node */
524:   for(neighbor = 0; neighbor < 2; neighbor++) {
525:     elem = neighbors[firstElem*2+neighbor];
526:     if (elem < 0) continue;

528:     for(corner = 0; corner < 2; corner++) {
529:       if (elements[elem*numCorners+corner] == node) {
530:         mesh->support[deg++] = elem;
531:         break;
532:       }
533:     }
534:   }

536:   if (deg > 2) {
537:     SETERRQ1(PETSC_ERR_PLIB, "Node %d has invalid support", node);
538:   } else if (deg < 2) {
539:     /* Make sure that this is a boundary node */
540:     if (tri->markers[node] == 0) SETERRQ1(PETSC_ERR_PLIB, "Interior node %d with incomplete support", node);
541:   }

543: #ifdef PETSC_USE_BOPT_g
544:   /* Check for overflow */
545:   if (deg > mesh->maxDegree) SETERRQ1(PETSC_ERR_MEM, "Maximum degree %d exceeded", mesh->maxDegree);
546: #endif

548:   *support = mesh->support;
549:   *degree  = deg;
550:   return(0);
551: }

553: /*----------------------------------------- Mesh Element Query Functions ---------------------------------------------*/
554: static int MeshGetElemNeighbor_Triangular_1D(Mesh mesh, int elem, int corner, int *neighbor) {
555:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
556: #ifdef PETSC_USE_BOPT_g
557:   int              numOverlapElements;
558:   int              ierr;
559: #endif

562: #ifdef PETSC_USE_BOPT_g
563:   PartitionGetNumOverlapElements(mesh->part, &numOverlapElements);
564:   if ((elem < 0)   || (elem >= numOverlapElements)) {
565:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid element %d should be in [0,%d)", elem, numOverlapElements);
566:   }
567:   if ((corner < 0) || (corner >= mesh->numCorners)) {
568:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid corner %d should be in [0,%d)", corner, mesh->numCorners);
569:   }
570: #endif
571:   *neighbor = tri->neighbors[elem*2+corner];
572:   return(0);
573: }

575: #if 0
576: static int MeshLocatePoint_Triangular_1D_Directed(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
577:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;

580:   /* We should use bisection here */
581:   return(0);
582: }
583: #endif

585: static int MeshLocatePoint_Triangular_1D(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
586:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
587:   int              numCorners  = mesh->numCorners;
588:   int              numElements = mesh->numEdges;
589:   double          *nodes       = tri->nodes;
590:   int             *elements    = tri->edges;
591:   double           x           = xx;
592:   double           coords[2];
593:   int              elem;

596:   *containingElem = -1;
597:   /* Quick bounding rectangle check */
598:   if ((mesh->isPeriodic == PETSC_FALSE) && ((mesh->locStartX > x) || (mesh->locEndX < x))) return(0);
599:   /* Simple search */
600:   for(elem = 0; elem < numElements; elem++) {
601:     coords[0] = nodes[elements[elem*numCorners]];
602:     coords[1] = MeshPeriodicRelativeX(mesh, nodes[elements[elem*numCorners+1]],   nodes[elements[elem*numCorners]]);
603:     x         = MeshPeriodicRelativeX(mesh, xx, nodes[elements[elem*numCorners]]);

605:     if ((x >= coords[0]) && (x < coords[1])) {
606:       *containingElem = elem;
607:       break;
608:     }
609:   }
610:   /* Check for the right endpoint */
611:   if ((x >= coords[0]) && (x <= coords[1])) *containingElem = numElements-1;

613:   return(0);
614: }

616: /*------------------------------------------- Mesh Embedding Functions -----------------------------------------------*/
617: static int MeshGetNodeFromElement_Triangular_1D(Mesh mesh, int elem, int corner, int *node) {
618:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
619:   int              numCorners = mesh->numCorners;

622:   *node = tri->edges[elem*numCorners+corner];
623:   return(0);
624: }

626: static int MeshGetNodeFromEdge_Triangular_1D(Mesh mesh, int edge, int corner, int *node) {
627:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
628:   int              numCorners = mesh->numCorners;

631:   *node = tri->edges[edge*numCorners+corner];
632:   return(0);
633: }

635: /*----------------------------------------------- Internal Functions -------------------------------------------------*/
636: static int MeshSetupSupport_Triangular_1D(Mesh mesh) {
637:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
638:   int              edge, node;
639:   int              ierr;

642:   /* Calculate maximum degree of vertices */
643:   if (mesh->numNodes > 0) {
644:     PetscMalloc(mesh->numNodes * sizeof(int), &tri->degrees);
645:   }
646:   PetscMemzero(tri->degrees, mesh->numNodes * sizeof(int));
647:   for(edge = 0; edge < mesh->numEdges; edge++) {
648:     tri->degrees[tri->edges[edge*mesh->numCorners]]++;
649:     tri->degrees[tri->edges[edge*mesh->numCorners+1]]++;
650:   }
651:   for(node = 0, mesh->maxDegree = 0; node < mesh->numNodes; node++) {
652:     mesh->maxDegree = PetscMax(mesh->maxDegree, tri->degrees[node]);
653:   }
654:   if (mesh->maxDegree > 0) {
655:     PetscMalloc(mesh->maxDegree * sizeof(int), &mesh->support);
656:   }
657:   mesh->supportTaken = PETSC_FALSE;
658:   return(0);
659: }

661: static int MeshCheckBoundary_Triangular_1D(Mesh mesh) {
662:   MeshBoundary2D *bdCtx         = mesh->bdCtx;
663:   int            *markers       = bdCtx->markers;
664:   int             numBd         = 0;
665:   int             numBdVertices = 0;
666:   int            *bdMarkers;
667:   int            *bdBegin;
668:   int             bd, vertex, rank;
669:   int             ierr;

673:   MPI_Comm_rank(mesh->comm, &rank);
674:   if (rank != 0) return(0);

676:   if (bdCtx->numBd != bdCtx->numVertices) {
677:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "All boundaries must be points: %d != %d", bdCtx->numBd, bdCtx->numVertices);
678:   }
679:   if ((bdCtx->numVertices != 0) && (bdCtx->numVertices != 2)) {
680:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of boundary points %d", bdCtx->numVertices);
681:   }
682:   if ((bdCtx->numVertices == 0) && (mesh->isPeriodic == PETSC_FALSE)) {
683:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Non-periodic domain must have 2 boundary points");
684:   }
685:   if (bdCtx->numVertices > 0) {
688:   }
689:   PetscMalloc(bdCtx->numBd     * sizeof(int), &bdMarkers);
690:   PetscMalloc((bdCtx->numBd+1) * sizeof(int), &bdBegin);
691:   PetscMemzero(bdBegin,        (bdCtx->numBd+1) * sizeof(int));
692:   for(vertex = 0; vertex < bdCtx->numVertices; vertex++) {
693:     if (markers[vertex] == 0) continue;
694:     numBdVertices++;
695:     /* Check for new marker */
696:     for(bd = 0; bd < numBd; bd++) {
697:       if (markers[vertex] == bdMarkers[bd]) break;
698:     }
699:     if (bd == numBd) {
700:       if (numBd >= bdCtx->numBd) SETERRQ1(PETSC_ERR_ARG_CORRUPT, "More markers present than declared: %d", bdCtx->numBd);
701:       /* Insert new marker */
702:       for(bd = 0; bd < numBd; bd++) {
703:         if (markers[vertex] < bdMarkers[bd]) break;
704:       }
705:       if (bd < numBd) {
706:         PetscMemmove(&bdMarkers[bd+1], &bdMarkers[bd], (numBd-bd) * sizeof(int));
707:         PetscMemmove(&bdBegin[bd+2],   &bdBegin[bd+1], (numBd-bd) * sizeof(int));
708:         bdBegin[bd+1] = 0;
709:       }
710:       bdMarkers[bd] = markers[vertex];
711:       numBd++;
712:       bdBegin[bd+1]++;
713:     } else {
714:       bdBegin[bd+1]++;
715:     }
716:   }

718:   /* Do prefix sums to get position offsets */
719:   for(bd = 2; bd <= numBd; bd++) {
720:     bdBegin[bd] = bdBegin[bd-1] + bdBegin[bd];
721:   }

723:   if (numBd != bdCtx->numBd) {
724:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", numBd, bdCtx->numBd);
725:   }
726:   if (bdBegin[numBd] != numBdVertices) {
727:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary vertices %d should be %d", bdBegin[numBd], numBdVertices);
728:   }
729:   PetscFree(bdMarkers);
730:   PetscFree(bdBegin);
731:   return(0);
732: }

734: static int MeshSetupBoundary_Triangular_1D(Mesh mesh) {
735:   Mesh_Triangular *tri      = (Mesh_Triangular *) mesh->data;
736:   int              numBd    = mesh->numBd;
737:   int              numNodes = mesh->numNodes;
738:   int             *markers  = tri->markers;
739:   int              newNumBd;   /* Current number of different boundary markers */
740:   int             *bdNodes;    /* Node numbers for boundary nodes ordered by boundary */
741:   int             *bdBeginOff; /* Current offset into the bdNodes or bdEdges array */
742:   int              rank, bd, node;
743:   int              ierr;

746:   MPI_Comm_rank(mesh->comm, &rank);
747:   PetscLogEventBegin(MESH_SetupBoundary, mesh, 0, 0, 0);
748:   mesh->numBdNodes = 0;
749:   if (numBd == 0) {
750:     tri->bdMarkers = PETSC_NULL;
751:     tri->bdBegin   = PETSC_NULL;
752:     tri->bdNodes   = PETSC_NULL;
753:     return(0);
754:   }
755:   PetscMalloc(numBd     * sizeof(int), &tri->bdMarkers);
756:   PetscMalloc((numBd+1) * sizeof(int), &tri->bdBegin);
757:   PetscMalloc((numBd+1) * sizeof(int), &bdBeginOff);
758:   PetscLogObjectMemory(mesh, (numBd + (numBd+1)) * sizeof(int));
759:   PetscMemzero(tri->bdMarkers,   numBd     * sizeof(int));
760:   PetscMemzero(tri->bdBegin,     (numBd+1) * sizeof(int));
761:   PetscMemzero(bdBeginOff,       (numBd+1) * sizeof(int));

763:   for(node = 0, newNumBd = 0; node < numNodes; node++) {
764:     /* Get number of boundary nodes and markers */
765:     if (markers[node]) {
766:       mesh->numBdNodes++;
767:       /* Check for new marker */
768:       for(bd = 0; bd < newNumBd; bd++) {
769:         if (markers[node] == tri->bdMarkers[bd]) break;
770:       }
771:       if (bd == newNumBd) {
772:         /* Insert new marker */
773:         for(bd = 0; bd < newNumBd; bd++) {
774:           if (markers[node] < tri->bdMarkers[bd]) break;
775:         }
776:         if (bd < newNumBd) {
777:           PetscMemmove(&tri->bdMarkers[bd+1], &tri->bdMarkers[bd], (newNumBd-bd) * sizeof(int));
778:           PetscMemmove(&tri->bdBegin[bd+2],   &tri->bdBegin[bd+1], (newNumBd-bd) * sizeof(int));
779:           tri->bdBegin[bd+1] = 0;
780:         }
781:         tri->bdMarkers[bd] = markers[node];
782:         newNumBd++;
783:         tri->bdBegin[bd+1]++;
784:       } else {
785:         tri->bdBegin[bd+1]++;
786:       }
787:     }
788:   }

790:   /* Do prefix sums to get position offsets */
791:   for(bd = 2; bd <= numBd; bd++) {
792:     tri->bdBegin[bd] = tri->bdBegin[bd-1] + tri->bdBegin[bd];
793:   }

795:   /* Check boundary information consistency */
796:   if (newNumBd != numBd) {
797:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", newNumBd, numBd);
798:   }
799:   if (tri->bdBegin[numBd] != mesh->numBdNodes) {
800:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d should be %d", tri->bdBegin[numBd], mesh->numBdNodes);
801:   }
802:   if ((mesh->numBdNodes != 0) && (mesh->numBdNodes != 2)) {
803:     SETERRQ1(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d", mesh->numBdNodes);
804:   }
805:   if (mesh->numBdNodes != mesh->numBd) {
806:     SETERRQ2(PETSC_ERR_PLIB, "Inconsistent boundary information: numBd %d != numBdNodes %d", mesh->numBd, mesh->numBdNodes);
807:   }

809:   PetscMalloc(mesh->numBdNodes * sizeof(int), &bdNodes);
810:   PetscLogObjectMemory(mesh, mesh->numBdNodes * sizeof(int));

812:   /* Split nodes by marker */
813:   PetscMemcpy(bdBeginOff, tri->bdBegin, (numBd+1) * sizeof(int));
814:   for(node = 0; node < numNodes; node++) {
815:     for(bd = 0; bd < numBd; bd++) {
816:       if (markers[node] == tri->bdMarkers[bd]) {
817: #ifdef MESH_TRACE_BOUNDARY_CREATE
818:         PetscPrintf(PETSC_COMM_WORLD, "bd: %d bdNode[%d] = %dn", bd, bdBeginOff[bd], node);
819: #endif
820:         bdNodes[bdBeginOff[bd]++] = node;
821:       }
822:     }
823:   }
824:   for(bd = 0; bd < numBd; bd++) {
825:     if (tri->bdBegin[bd+1] != bdBeginOff[bd])
826:       SETERRQ(PETSC_ERR_PLIB, "Invalid boundary node marker information");
827:   }
828:   PetscFree(bdBeginOff);

830:   /* Set fields */
831:   tri->bdNodes = bdNodes;

833:   PetscLogEventEnd(MESH_SetupBoundary, mesh, 0, 0, 0);
834:   return(0);
835: }

837: /*
838:   MeshAssemble_Triangular_1D - This function assembles the mesh entirely on the first processor.

840:   Collective on Mesh

842:   Input Parameters:
843: . mesh    - The mesh being refined

845:   Output Parameter:
846: + nodes   - The node coordinates
847: . markers - The node markers
848: - edges   - The nodes for each edge

850:   Level: developer

852: .keywords mesh, assemble
853: .seealso MeshInitRefineInput_Triangle()
854: */
855: int MeshAssemble_Triangular_1D(Mesh mesh, double **nodes, int **markers, int **faces, int **edges) {
856:   Mesh_Triangular         *tri        = (Mesh_Triangular *) mesh->data;
857:   Partition                p          = mesh->part;
858:   Partition_Triangular_1D *q          = (Partition_Triangular_1D *) p->data;
859:   int                      numNodes   = q->numNodes;
860:   int                      numEdges   = p->numElements;
861:   int                      numCorners = mesh->numCorners;
862:   int                      numProcs   = p->numProcs;
863:   int                      rank       = p->rank;
864:   int                     *locEdges   = PETSC_NULL;
865:   int                     *numRecvNodes, *numRecvMarkers, *numRecvEdges;
866:   int                     *nodeOffsets,  *markerOffsets,  *edgeOffsets;
867:   int                      proc, edge, size;
868:   int                      ierr;

871:   /* Allocate global arrays */
872:   if (rank == 0) {
873:     PetscMalloc(numNodes*2          * sizeof(double), nodes);
874:     PetscMalloc(numNodes            * sizeof(int),    markers);
875:     PetscMalloc(numEdges*numCorners * sizeof(int),    edges);
876:   }

878:   if (numProcs > 1) {
879:     if (mesh->numEdges > 0) {
880:       PetscMalloc(mesh->numEdges*numCorners * sizeof(int), &locEdges);
881:     }

883:     /* Calculate offsets */
884:     PetscMalloc(numProcs * sizeof(int), &numRecvNodes);
885:     PetscMalloc(numProcs * sizeof(int), &numRecvMarkers);
886:     PetscMalloc(numProcs * sizeof(int), &numRecvEdges);
887:     PetscMalloc(numProcs * sizeof(int), &nodeOffsets);
888:     PetscMalloc(numProcs * sizeof(int), &markerOffsets);
889:     PetscMalloc(numProcs * sizeof(int), &edgeOffsets);
890:     for(proc = 0; proc < numProcs; proc++) {
891:       numRecvNodes[proc]   = (q->firstNode[proc+1]    - q->firstNode[proc])*2;
892:       numRecvMarkers[proc] = (q->firstNode[proc+1]    - q->firstNode[proc]);
893:       numRecvEdges[proc]   = (p->firstElement[proc+1] - p->firstElement[proc])*numCorners;
894:     }
895:     nodeOffsets[0]   = 0;
896:     markerOffsets[0] = 0;
897:     edgeOffsets[0]   = 0;
898:     for(proc = 1; proc < numProcs; proc++) {
899:       nodeOffsets[proc]   = numRecvNodes[proc-1]   + nodeOffsets[proc-1];
900:       markerOffsets[proc] = numRecvMarkers[proc-1] + markerOffsets[proc-1];
901:       edgeOffsets[proc]   = numRecvEdges[proc-1]   + edgeOffsets[proc-1];
902:     }

904:     /* Local to global node number conversion */
905:     for(edge = 0; edge < mesh->numEdges*numCorners; edge++) {
906:       PartitionLocalToGlobalNodeIndex(p, tri->edges[edge], &locEdges[edge]);
907:     }

909:     /* Collect global arrays */
910:     size = mesh->numNodes*2;
911:     MPI_Gatherv(tri->nodes,   size, MPI_DOUBLE, *nodes,   numRecvNodes,   nodeOffsets,   MPI_DOUBLE, 0, p->comm);
912: 
913:     size = mesh->numNodes;
914:     MPI_Gatherv(tri->markers, size, MPI_INT,    *markers, numRecvMarkers, markerOffsets, MPI_INT,    0, p->comm);
915: 
916:     size = mesh->numEdges*numCorners;
917:     MPI_Gatherv(locEdges,     size, MPI_INT,    *edges,   numRecvEdges,   edgeOffsets,   MPI_INT,    0, p->comm);
918: 

920:     /* Cleanup */
921:     if (locEdges != PETSC_NULL) {
922:       PetscFree(locEdges);
923:     }
924:     PetscFree(numRecvNodes);
925:     PetscFree(numRecvMarkers);
926:     PetscFree(numRecvEdges);
927:     PetscFree(nodeOffsets);
928:     PetscFree(markerOffsets);
929:     PetscFree(edgeOffsets);
930:   } else {
931:     /* Uniprocessor case */
932:     PetscMemcpy(*nodes,   tri->nodes,   numNodes*2          * sizeof(double));
933:     PetscMemcpy(*markers, tri->markers, numNodes            * sizeof(int));
934:     PetscMemcpy(*edges,   tri->edges,   numEdges*numCorners * sizeof(int));
935:   }
936:   return(0);
937: }

939: int MeshDebug_Triangular_1D(Mesh mesh, PetscTruth distributed) {
940:   Mesh_Triangular         *tri = (Mesh_Triangular *) mesh->data;
941:   Partition                p   = mesh->part;
942:   Partition_Triangular_1D *q   = PETSC_NULL;
943:   int                      numBd       = mesh->numBd;
944:   int                      numElements = mesh->numFaces;
945:   int                      numCorners  = mesh->numCorners;
946:   int                      numNodes    = mesh->numNodes;
947:   int                     *elements    = tri->faces;
948:   int                     *markers     = tri->markers;
949:   int                     *bdMarkers   = tri->bdMarkers;
950:   int                      degree;
951:   int                     *support;
952:   int                     *degrees;
953:   int                     *supports;
954:   int                     *sizes;
955:   int                      numProcs, rank;
956:   PetscTruth               isMidnode;
957:   int                      proc, bd, elem, nElem, sElem, sElem2, corner, node, newNode, size;
958:   int                      ierr;

961:   MPI_Comm_size(mesh->comm, &numProcs);
962:   MPI_Comm_rank(mesh->comm, &rank);
963:   if (p != PETSC_NULL) {
964:     q = (Partition_Triangular_1D *) p->data;
965:   }

967:   /* Check basic sizes */
968:   PetscMalloc(numProcs * sizeof(int), &sizes);
969:   MPI_Allgather(&mesh->numBd, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
970:   for(proc = 0, 0; proc < numProcs-1; proc++) {
971:     if (sizes[proc] != sizes[proc+1]) {
972:       PetscPrintf(mesh->comm, "The number of boundaries is different on proc %d(%d) and proc %d(%d)n",
973:                   proc, sizes[proc], proc+1, sizes[proc+1]);
974:       1;
975:     }
976:   }
977: 
978: #if 0
979:   /* I made vertices distributed in linear meshes */
980:   MPI_Allgather(&tri->numVertices, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
981:   for(proc = 0, 0; proc < numProcs-1; proc++) {
982:     if (sizes[proc] != sizes[proc+1]) {
983:       PetscPrintf(mesh->comm, "The number of vertices is different on proc %d(%d) and proc %d(%d)n",
984:                   proc, sizes[proc], proc+1, sizes[proc+1]);
985:       1;
986:     }
987:   }
988: 
989: #endif
990:   MPI_Allgather(&mesh->numCorners, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
991:   for(proc = 0, 0; proc < numProcs-1; proc++) {
992:     if (sizes[proc] != sizes[proc+1]) {
993:       PetscPrintf(mesh->comm, "The number of face corners is different on proc %d(%d) and proc %d(%d)n",
994:                   proc, sizes[proc], proc+1, sizes[proc+1]);
995:       1;
996:     }
997:   }
998: 
999:   MPI_Allgather(&mesh->numBdEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1000:   for(proc = 0, 0; proc < numProcs-1; proc++) {
1001:     if (sizes[proc] != sizes[proc+1]) {
1002:       PetscPrintf(mesh->comm, "The number of boundary edges is different on proc %d(%d) and proc %d(%d)n",
1003:                   proc, sizes[proc], proc+1, sizes[proc+1]);
1004:       1;
1005:     }
1006:   }
1007: 
1008:   if (distributed == PETSC_FALSE) {
1009:     MPI_Allgather(&mesh->numNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1010:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1011:       if (sizes[proc] != sizes[proc+1]) {
1012:         PetscPrintf(mesh->comm, "The number of nodes is different on proc %d(%d) and proc %d(%d)n",
1013:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1014:         1;
1015:       }
1016:     }
1017: 
1018:     MPI_Allgather(&mesh->numBdNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1019:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1020:       if (sizes[proc] != sizes[proc+1]) {
1021:         PetscPrintf(mesh->comm, "The number of boundary nodes is different on proc %d(%d) and proc %d(%d)n",
1022:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1023:         1;
1024:       }
1025:     }
1026: 
1027:     MPI_Allgather(&mesh->numEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1028:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1029:       if (sizes[proc] != sizes[proc+1]) {
1030:         PetscPrintf(mesh->comm, "The number of edges is different on proc %d(%d) and proc %d(%d)n",
1031:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1032:         1;
1033:       }
1034:     }
1035: 
1036:     MPI_Allgather(&mesh->numFaces, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1037:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1038:       if (sizes[proc] != sizes[proc+1]) {
1039:         PetscPrintf(mesh->comm, "The number of faces is different on proc %d(%d) and proc %d(%d)n",
1040:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1041:         1;
1042:       }
1043:     }
1044: 
1045:   } else {
1046:     MPI_Allreduce(&mesh->numNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1047:     if (size != q->numNodes) {
1048:       SETERRQ2(PETSC_ERR_PLIB, "The total number of nodes %d should be %dn", size, q->numNodes);
1049:     }
1050: #if 0
1051:     MPI_Allreduce(&tri->numBdNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1052: #else
1053:     size = mesh->numBdNodes;
1054: #endif
1055:     if (size != q->numBdNodes) {
1056:       SETERRQ2(PETSC_ERR_PLIB, "The total number of boundary nodes %d should be %dn", size, q->numBdNodes);
1057:     }
1058:     MPI_Allreduce(&mesh->numEdges, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1059:     if (size != mesh->part->numElements) {
1060:       SETERRQ2(PETSC_ERR_PLIB, "The total number of edges %d should be %dn", size, mesh->part->numElements);
1061:     }
1062:   }
1063:   PetscFree(sizes);

1065:   if (distributed == PETSC_FALSE) {
1066:     /* Check markers */
1067:     for(node = 0; node < numNodes; node++) {
1068:       if (!markers[node]) continue;

1070:       for(bd = 0; bd < numBd; bd++)
1071:         if(bdMarkers[bd] == markers[node])
1072:           break;
1073:       if (bd == numBd) {
1074:         SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1075:       }
1076:     }
1077:     /* Check mesh connectivity */
1078:     for(node = 0; node < numNodes; node++) {
1079:       MeshGetNodeSupport(mesh, node, 0, &degree, &support);

1081:       /* Check node degree */
1082:       PetscMalloc(numProcs * sizeof(int), &degrees);
1083:       MPI_Allgather(&degree, 1, MPI_INT, degrees, 1, MPI_INT, mesh->comm);
1084:       for(proc = 0, 0; proc < numProcs-1; proc++)
1085:         if (degrees[proc] != degrees[proc+1]) {
1086:           PetscPrintf(mesh->comm, "Degree of node %d is different on proc %d(%d) and proc %d(%d)n",
1087:                       node, proc, degrees[proc], proc+1, degrees[proc+1]);
1088:           PetscPrintf(mesh->comm, "Node Information:n");
1089:           PetscSequentialPhaseBegin(mesh->comm, 1);
1090:             PetscPrintf(PETSC_COMM_SELF, "  Processor %dn", rank);
1091:             if ((rank == proc) || (rank == proc+1))
1092:               for(sElem = 0; sElem < degree; sElem++)
1093:                 PetscPrintf(PETSC_COMM_SELF, "  Support    : %dn", support[sElem]);
1094:             PetscPrintf(PETSC_COMM_SELF, "  Marker     : %dn", tri->markers[node]);
1095:             PetscPrintf(PETSC_COMM_SELF, "  Location   : (%g,%g)n", tri->nodes[node*2], tri->nodes[node*2+1]);
1096:             PetscPrintf(PETSC_COMM_SELF, "  In Elements:");
1097:             for(elem = 0, isMidnode = PETSC_FALSE; elem < numElements; elem++)
1098:               for(corner = 0; corner < numCorners; corner++)
1099:                 if (elements[elem*numCorners+corner] == node) {
1100:                   PetscPrintf(PETSC_COMM_SELF, " %d", elem);
1101:                   if (corner >= 3)
1102:                     isMidnode = PETSC_TRUE;
1103:                 }
1104:             PetscPrintf(PETSC_COMM_SELF, "n");
1105:             if (isMidnode == PETSC_TRUE)
1106:               PetscPrintf(PETSC_COMM_SELF, "  Midnoden");
1107:             else
1108:               PetscPrintf(PETSC_COMM_SELF, "  Vertexn");
1109:           PetscSequentialPhaseEnd(mesh->comm, 1);
1110:           1;
1111:         }
1112: 
1113:       PetscFree(degrees);

1115:       /* Check support elements */
1116:       PetscMalloc(degree*numProcs * sizeof(int), &supports);
1117:       MPI_Allgather(support, degree, MPI_INT, supports, degree, MPI_INT, mesh->comm);
1118:       for(sElem = 0, 0; sElem < degree; sElem++) {
1119:         nElem = supports[sElem];
1120:         for(proc = 1; proc < numProcs; proc++) {
1121:           for(sElem2 = 0; sElem2 < degree; sElem2++)
1122:             if (supports[proc*degree+sElem2] == nElem)
1123:               break;
1124:           if (sElem2 == degree) {
1125:             PetscPrintf(mesh->comm, "Support element %d of node %d on proc %d(%d) is not present on proc %dn",
1126:                         sElem, node, 0, supports[sElem], proc);
1127:             PetscPrintf(mesh->comm, "  Support of node %d on proc %d:n   ", node, proc);
1128:             for(sElem2 = 0; sElem2 < degree; sElem2++)
1129:               PetscPrintf(mesh->comm, " %d", supports[proc*degree+sElem2]);
1130:             PetscPrintf(mesh->comm, "n");
1131:             1;
1132:           }
1133:         }
1134:       }
1135: 
1136:       PetscFree(supports);

1138:       /* Check that node only appears inside elements in the support */
1139:       for(elem = 0, 0; elem < numElements; elem++)
1140:         for(corner = 0; corner < numCorners; corner++) {
1141:           newNode = elements[elem*numCorners+corner];
1142:           if (node == newNode) {
1143:             for(sElem = 0; sElem < degree; sElem++)
1144:               if (support[sElem] == elem)
1145:                 break;
1146:             if (sElem == degree) {
1147:               PetscPrintf(mesh->comm, "Node %d found in element %d which is not present in the supportn",
1148:                           node, elem);
1149:               1;
1150:             }
1151:           }
1152:         }
1153: 

1155:       MeshRestoreNodeSupport(mesh, node, 0, &degree, &support);
1156:     }
1157:   } else {
1158:     /* Check markers */
1159:     for(node = 0; node < q->numOverlapNodes; node++) {
1160:       if (!markers[node]) continue;

1162:       for(bd = 0; bd < numBd; bd++)
1163:         if(bdMarkers[bd] == markers[node])
1164:           break;
1165:       if (bd == numBd) {
1166:         SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1167:       }
1168:     }
1169:     /* Check mesh connectivity */
1170:     for(node = 0; node < q->numLocNodes; node++) {
1171:       MeshGetNodeSupport(mesh, node, 0, &degree, &support);

1173:       /* Check that node only appears inside elements in the support */
1174:       for(elem = 0, 0; elem < p->numOverlapElements; elem++) {
1175:         for(corner = 0; corner < numCorners; corner++) {
1176:           newNode = elements[elem*numCorners+corner];
1177:           if (node == newNode) {
1178:             for(sElem = 0; sElem < degree; sElem++) {
1179:               if (support[sElem] == elem) break;
1180:             }
1181:             if (sElem == degree) {
1182:               PetscPrintf(PETSC_COMM_SELF, "[%d]Node %d found in element %d which is not present in the supportn",
1183:                           p->rank, node, elem);
1184:               1;
1185:             }
1186:           }
1187:         }
1188:       }
1189: 

1191:       MeshRestoreNodeSupport(mesh, node, 0, &degree, &support);
1192:     }
1193:   }
1194:   return(0);
1195: }

1197: static struct _MeshOps MeshOps = {/* Generic Operations */
1198:                                   PETSC_NULL/* MeshSetup */,
1199:                                   PETSC_NULL/* MeshSetFromOptions */,
1200:                                   MeshView_Triangular_1D,
1201:                                   PETSC_NULL/* MeshCopy */,
1202:                                   PETSC_NULL/* MeshDuplicate */,
1203:                                   MeshDestroy_Triangular_1D,
1204:                                   /* Mesh-Specific Operations */
1205:                                   MeshPartition_Triangular_1D,
1206:                                   MeshCoarsen_Triangular_1D,
1207:                                   MeshRefine_Triangular_1D,
1208:                                   MeshResetNodes_Triangular_1D,
1209:                                   MeshSaveMesh_Triangular_1D,
1210:                                   MeshRestoreMesh_Triangular_1D,
1211:                                   /* Mesh Query Functions */
1212:                                   MeshUpdateBoundingBox_Triangular_1D,
1213:                                   MeshIsDistorted_Triangular_1D,
1214:                                   /* Mesh Boundary Query Functions */
1215:                                   MeshGetBoundarySize_Triangular_1D,
1216:                                   MeshGetBoundaryIndex_Triangular_1D,
1217:                                   MeshGetBoundaryStart_Triangular_1D,
1218:                                   MeshGetBoundaryNext_Triangular_1D,
1219:                                   MeshGetActiveBoundary_Triangular_1D,
1220:                                   /* Mesh Node Query Functions */
1221:                                   MeshGetNodeBoundary_Triangular_1D,
1222:                                   MeshNodeIsVertex_Triangular_1D,
1223:                                   MeshGetNodeCoords_Triangular_1D,
1224:                                   MeshSetNodeCoords_Triangular_1D,
1225:                                   MeshGetNodeCoordsSaved_Triangular_1D,
1226:                                   MeshNearestNode_Triangular_1D,
1227:                                   MeshGetNodeSupport_Triangular_1D,
1228:                                   /* Mesh Element Query Functions */
1229:                                   MeshGetElemNeighbor_Triangular_1D,
1230:                                   MeshLocatePoint_Triangular_1D,
1231:                                   /* Mesh Embedding Query Functions */
1232:                                   MeshGetNodeFromElement_Triangular_1D,
1233:                                   MeshGetNodeFromEdge_Triangular_1D,
1234:                                   /* CSR Support Functions */
1235:                                   PETSC_NULL,
1236:                                   PETSC_NULL,
1237:                                   PETSC_NULL};

1239: #if 0
1240: EXTERN_C_BEGIN
1241: int MeshSerialize_Triangular_1D(MPI_Comm comm, Mesh *mesh, PetscViewer viewer, PetscTruth store) {
1242:   Mesh             m;
1243:   Mesh_Triangular *tri;
1244:   int              fd;
1245:   int              zero = 0;
1246:   int              one  = 1;
1247:   int              numNodes, numEdges, numFaces, numCorners, numBd, numBdNodes, numBdEdges, old;
1248:   int              ierr;

1251:   PetscViewerBinaryGetDescriptor(viewer, &fd);
1252:   if (store) {
1253:     m    = *mesh;
1254:     PetscBinaryWrite(fd, &m->highlightElement, 1,                   PETSC_INT,    0);
1255:     PetscBinaryWrite(fd, &m->maxDegree,        1,                   PETSC_INT,    0);
1256:     PetscBinaryWrite(fd, &m->startX,           1,                   PETSC_DOUBLE, 0);
1257:     PetscBinaryWrite(fd, &m->endX,             1,                   PETSC_DOUBLE, 0);
1258:     PetscBinaryWrite(fd, &m->sizeX,            1,                   PETSC_DOUBLE, 0);
1259:     PetscBinaryWrite(fd, &m->startY,           1,                   PETSC_DOUBLE, 0);
1260:     PetscBinaryWrite(fd, &m->endY,             1,                   PETSC_DOUBLE, 0);
1261:     PetscBinaryWrite(fd, &m->sizeY,            1,                   PETSC_DOUBLE, 0);
1262:     PetscBinaryWrite(fd, &m->startZ,           1,                   PETSC_DOUBLE, 0);
1263:     PetscBinaryWrite(fd, &m->endZ,             1,                   PETSC_DOUBLE, 0);
1264:     PetscBinaryWrite(fd, &m->sizeZ,            1,                   PETSC_DOUBLE, 0);
1265:     PetscBinaryWrite(fd, &m->locStartX,        1,                   PETSC_DOUBLE, 0);
1266:     PetscBinaryWrite(fd, &m->locEndX,          1,                   PETSC_DOUBLE, 0);
1267:     PetscBinaryWrite(fd, &m->locSizeX,         1,                   PETSC_DOUBLE, 0);
1268:     PetscBinaryWrite(fd, &m->locStartY,        1,                   PETSC_DOUBLE, 0);
1269:     PetscBinaryWrite(fd, &m->locEndY,          1,                   PETSC_DOUBLE, 0);
1270:     PetscBinaryWrite(fd, &m->locSizeY,         1,                   PETSC_DOUBLE, 0);
1271:     PetscBinaryWrite(fd, &m->locStartZ,        1,                   PETSC_DOUBLE, 0);
1272:     PetscBinaryWrite(fd, &m->locEndZ,          1,                   PETSC_DOUBLE, 0);
1273:     PetscBinaryWrite(fd, &m->locSizeZ,         1,                   PETSC_DOUBLE, 0);
1274:     PetscBinaryWrite(fd, &m->isPeriodic,       1,                   PETSC_INT,    0);
1275:     PetscBinaryWrite(fd, &m->isPeriodicDim,    3,                   PETSC_INT,    0);

1277:     PetscBinaryWrite(fd, &m->numBd,            1,                   PETSC_INT,    0);
1278:     PetscBinaryWrite(fd, &m->numVertices,      1,                   PETSC_INT,    0);
1279:     PetscBinaryWrite(fd, &m->numNodes,         1,                   PETSC_INT,    0);
1280:     PetscBinaryWrite(fd, &m->numBdNodes,       1,                   PETSC_INT,    0);
1281:     PetscBinaryWrite(fd, &m->numEdges,         1,                   PETSC_INT,    0);
1282:     PetscBinaryWrite(fd, &m->numBdEdges,       1,                   PETSC_INT,    0);
1283:     PetscBinaryWrite(fd, &m->numFaces,         1,                   PETSC_INT,    0);
1284:     PetscBinaryWrite(fd, &m->numBdFaces,       1,                   PETSC_INT,    0);
1285:     PetscBinaryWrite(fd, &m->numCells,         1,                   PETSC_INT,    0);
1286:     PetscBinaryWrite(fd, &m->numCorners,       1,                   PETSC_INT,    0);
1287:     PetscBinaryWrite(fd, &m->numCellCorners,   1,                   PETSC_INT,    0);
1288:     PetscBinaryWrite(fd, &m->numHoles,         1,                   PETSC_INT,    0);

1290:     PartitionSerialize(m, &m->part, viewer, store);

1292:     PartitionGetNumOverlapElements(m->part, &numFaces);
1293:     PartitionGetNumOverlapNodes(m->part, &numNodes);
1294:     numEdges   = m->numEdges;
1295:     numCorners = m->numCorners;
1296:     numBd      = m->numBd;
1297:     numBdNodes = m->numBdNodes;
1298:     numBdEdges = m->numBdEdges;

1300:     tri  = (Mesh_Triangular *) (*mesh)->data;
1301:     PetscBinaryWrite(fd,  tri->nodes,          numNodes*2,          PETSC_DOUBLE, 0);
1302:     if (tri->nodesOld == PETSC_NULL) {
1303:       PetscBinaryWrite(fd, &zero,              1,                   PETSC_INT,    0);
1304:     } else {
1305:       PetscBinaryWrite(fd, &one,               1,                   PETSC_INT,    0);
1306:       PetscBinaryWrite(fd,  tri->nodesOld,     numNodes*2,          PETSC_DOUBLE, 0);
1307:     }
1308:     PetscBinaryWrite(fd,  tri->markers,        numNodes,            PETSC_INT,    0);
1309:     PetscBinaryWrite(fd,  tri->degrees,        numNodes,            PETSC_INT,    0);
1310:     PetscBinaryWrite(fd,  tri->edges,          numEdges*2,          PETSC_INT,    0);
1311:     PetscBinaryWrite(fd,  tri->edgemarkers,    numEdges,            PETSC_INT,    0);
1312:     PetscBinaryWrite(fd,  tri->faces,          numFaces*numCorners, PETSC_INT,    0);
1313:     PetscBinaryWrite(fd,  tri->neighbors,      numFaces*3,          PETSC_INT,    0);
1314:     PetscBinaryWrite(fd,  tri->bdNodes,        numBdNodes,          PETSC_INT,    0);
1315:     PetscBinaryWrite(fd,  tri->bdEdges,        numBdEdges,          PETSC_INT,    0);
1316:     PetscBinaryWrite(fd,  tri->bdMarkers,      numBd,               PETSC_INT,    0);
1317:     PetscBinaryWrite(fd,  tri->bdBegin,        numBd+1,             PETSC_INT,    0);
1318:     PetscBinaryWrite(fd,  tri->bdEdgeBegin,    numBd+1,             PETSC_INT,    0);
1319:     PetscBinaryWrite(fd,  m->holes,            m->numHoles*2,       PETSC_DOUBLE, 0);

1321:     PetscBinaryWrite(fd, &m->maxAspectRatio,   1,                   PETSC_DOUBLE, 0);
1322:   } else {
1323:     /* Create the mesh context */
1324:     MeshCreate(comm, &m);
1325:     PetscNew(Mesh_Triangular, &tri);
1326:     PetscLogObjectMemory(m, sizeof(Mesh_Triangular));
1327:     PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1328:     PetscStrallocpy(MESH_TRIANGULAR_2D, &m->type_name);
1329:     m->data = (void *) tri;
1330:     m->dim  = 2;

1332:     PetscBinaryRead(fd, &m->highlightElement, 1, PETSC_INT);
1333:     PetscBinaryRead(fd, &m->maxDegree,        1, PETSC_INT);
1334:     PetscMalloc(m->maxDegree * sizeof(int), &m->support);

1336:     PetscBinaryRead(fd, &m->startX,           1, PETSC_DOUBLE);
1337:     PetscBinaryRead(fd, &m->endX,             1, PETSC_DOUBLE);
1338:     PetscBinaryRead(fd, &m->sizeX,            1, PETSC_DOUBLE);
1339:     PetscBinaryRead(fd, &m->startY,           1, PETSC_DOUBLE);
1340:     PetscBinaryRead(fd, &m->endY,             1, PETSC_DOUBLE);
1341:     PetscBinaryRead(fd, &m->sizeY,            1, PETSC_DOUBLE);
1342:     PetscBinaryRead(fd, &m->startZ,           1, PETSC_DOUBLE);
1343:     PetscBinaryRead(fd, &m->endZ,             1, PETSC_DOUBLE);
1344:     PetscBinaryRead(fd, &m->sizeZ,            1, PETSC_DOUBLE);
1345:     PetscBinaryRead(fd, &m->locStartX,        1, PETSC_DOUBLE);
1346:     PetscBinaryRead(fd, &m->locEndX,          1, PETSC_DOUBLE);
1347:     PetscBinaryRead(fd, &m->locSizeX,         1, PETSC_DOUBLE);
1348:     PetscBinaryRead(fd, &m->locStartY,        1, PETSC_DOUBLE);
1349:     PetscBinaryRead(fd, &m->locEndY,          1, PETSC_DOUBLE);
1350:     PetscBinaryRead(fd, &m->locSizeY,         1, PETSC_DOUBLE);
1351:     PetscBinaryRead(fd, &m->locStartZ,        1, PETSC_DOUBLE);
1352:     PetscBinaryRead(fd, &m->locEndZ,          1, PETSC_DOUBLE);
1353:     PetscBinaryRead(fd, &m->locSizeZ,         1, PETSC_DOUBLE);
1354:     PetscBinaryRead(fd, &m->isPeriodic,       1, PETSC_INT);
1355:     PetscBinaryRead(fd, &m->isPeriodicDim,    3, PETSC_INT);

1357:     m->activeBd       = -1;
1358:     m->activeBdOld    = -1;
1359:     m->activeBdNode   = -1;
1360:     tri->areas        = PETSC_NULL;
1361:     tri->aspectRatios = PETSC_NULL;

1363:     PetscBinaryRead(fd, &m->numBd,            1,                   PETSC_INT);
1364:     PetscBinaryRead(fd, &m->numVertices,      1,                   PETSC_INT);
1365:     PetscBinaryRead(fd, &m->numNodes,         1,                   PETSC_INT);
1366:     PetscBinaryRead(fd, &m->numBdNodes,       1,                   PETSC_INT);
1367:     PetscBinaryRead(fd, &m->numEdges,         1,                   PETSC_INT);
1368:     PetscBinaryRead(fd, &m->numBdEdges,       1,                   PETSC_INT);
1369:     PetscBinaryRead(fd, &m->numFaces,         1,                   PETSC_INT);
1370:     PetscBinaryRead(fd, &m->numBdFaces,       1,                   PETSC_INT);
1371:     PetscBinaryRead(fd, &m->numCells,         1,                   PETSC_INT);
1372:     PetscBinaryRead(fd, &m->numCorners,       1,                   PETSC_INT);
1373:     PetscBinaryRead(fd, &m->numCellCorners,   1,                   PETSC_INT);
1374:     PetscBinaryRead(fd, &m->numHoles,         1,                   PETSC_INT);

1376:     PartitionSerialize(m, &m->part, viewer, store);
1377:     PetscLogObjectParent(m, m->part);

1379:     PartitionGetNumOverlapElements(m->part, &numFaces);
1380:     PartitionGetNumOverlapNodes(m->part, &numNodes);
1381:     numEdges   = m->numEdges;
1382:     numCorners = m->numCorners;
1383:     numBd      = m->numBd;
1384:     numBdNodes = m->numBdNodes;
1385:     numBdEdges = m->numBdEdges;
1386:     PetscMalloc(numNodes*2          * sizeof(double), &tri->nodes);
1387:     PetscMalloc(numNodes            * sizeof(int),    &tri->markers);
1388:     PetscMalloc(numNodes            * sizeof(int),    &tri->degrees);
1389:     PetscMalloc(numEdges*2          * sizeof(int),    &tri->edges);
1390:     PetscMalloc(numEdges            * sizeof(int),    &tri->edgemarkers);
1391:     PetscMalloc(numFaces*numCorners * sizeof(int),    &tri->faces);
1392:     PetscMalloc(numFaces*3          * sizeof(int),    &tri->neighbors);
1393:     PetscMalloc(numBdNodes          * sizeof(int),    &tri->bdNodes);
1394:     PetscMalloc(numBdEdges          * sizeof(int),    &tri->bdEdges);
1395:     PetscMalloc(numBd               * sizeof(int),    &tri->bdMarkers);
1396:     PetscMalloc((numBd+1)           * sizeof(int),    &tri->bdBegin);
1397:     PetscMalloc((numBd+1)           * sizeof(int),    &tri->bdEdgeBegin);
1398:     if (m->numHoles > 0) {
1399:       PetscMalloc(m->numHoles*2     * sizeof(double), &m->holes);
1400:     } else {
1401:       m->holes = PETSC_NULL;
1402:     }
1403:     PetscLogObjectMemory(m, (numNodes*2 + m->numHoles*2) * sizeof(double) +
1404:                          (numNodes*2 + numEdges*3 + numFaces*(numCorners+1) + numBdNodes + numBdEdges + numBd*3+2)*sizeof(int));
1405:     PetscBinaryRead(fd,  tri->nodes,          numNodes*2,          PETSC_DOUBLE);
1406:     PetscBinaryRead(fd, &old,                 1,                   PETSC_INT);
1407:     if (old) {
1408:       PetscMalloc(numNodes*2 * sizeof(double), &tri->nodesOld);
1409:       PetscLogObjectMemory(m, numNodes*2 * sizeof(double));
1410:       PetscBinaryRead(fd,  tri->nodesOld,     numNodes*2,          PETSC_DOUBLE);
1411:     } else {
1412:       tri->nodesOld = PETSC_NULL;
1413:     }
1414:     PetscBinaryRead(fd,  tri->markers,        numNodes,            PETSC_INT);
1415:     PetscBinaryRead(fd,  tri->degrees,        numNodes,            PETSC_INT);
1416:     PetscBinaryRead(fd,  tri->edges,          numEdges*2,          PETSC_INT);
1417:     PetscBinaryRead(fd,  tri->edgemarkers,    numEdges,            PETSC_INT);
1418:     PetscBinaryRead(fd,  tri->faces,          numFaces*numCorners, PETSC_INT);
1419:     PetscBinaryRead(fd,  tri->neighbors,      numFaces*3,          PETSC_INT);
1420:     PetscBinaryRead(fd,  tri->bdNodes,        numBdNodes,          PETSC_INT);
1421:     PetscBinaryRead(fd,  tri->bdEdges,        numBdEdges,          PETSC_INT);
1422:     PetscBinaryRead(fd,  tri->bdMarkers,      numBd,               PETSC_INT);
1423:     PetscBinaryRead(fd,  tri->bdBegin,        numBd+1,             PETSC_INT);
1424:     PetscBinaryRead(fd,  tri->bdEdgeBegin,    numBd+1,             PETSC_INT);
1425:     PetscBinaryRead(fd,  m->holes,            m->numHoles*m->dim,  PETSC_DOUBLE);

1427:     PetscBinaryRead(fd, &m->maxAspectRatio,   1,                   PETSC_DOUBLE);

1429: #ifdef PETSC_USE_BOPT_g
1430:     /* Check mesh integrity */
1431:     MeshDebug_Triangular_1D(m, PETSC_TRUE);
1432: #endif
1433:     *mesh = m;
1434:   }

1436:   return(0);
1437: }
1438: EXTERN_C_END
1439: #endif

1441: EXTERN_C_BEGIN
1442: int MeshCreate_Triangular_1D(Mesh mesh) {
1443:   Mesh_Triangular *tri;
1444:   int            (*f)(MeshBoundary2D *, int, Mesh);
1445:   int              ierr;

1448:   PetscNew(Mesh_Triangular, &tri);
1449:   PetscMemzero(tri, sizeof(Mesh_Triangular));
1450:   PetscMemcpy(mesh->ops, &MeshOps, sizeof(struct _MeshOps));
1451:   mesh->data = (void *) tri;
1452:   PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &mesh->serialize_name);
1453:   mesh->dim = 1;

1455:   /* Setup the periodic domain */
1456:   if (mesh->isPeriodic == PETSC_TRUE) {
1457:     MeshBoundary2DSetBoundingBox(mesh, mesh->bdCtx);
1458:   }

1460:   /* Setup default mechanisms */
1461:   PetscObjectQueryFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", (PetscVoidFunction) &f);
1462:   if (f == PETSC_NULL) {
1463:     if (mesh->isPeriodic == PETSC_TRUE) {
1464:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Periodic",
1465:                                         (void (*)(void)) MeshTriangular1D_Create_Periodic);
1466: 
1467:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Periodic",
1468:                                         (void (*)(void)) MeshTriangular1D_Refine_Periodic);
1469: 
1470:     } else {
1471:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Triangle",
1472:                                         (void (*)(void)) MeshTriangular1D_Create_Simple);
1473: 
1474:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Triangle",
1475:                                         (void (*)(void)) MeshTriangular1D_Refine_Simple);
1476:     }
1477:   }

1479:   MeshCheckBoundary_Triangular_1D(mesh);

1481:   PetscObjectQueryFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", (PetscVoidFunction) &f);
1482:   (*f)(mesh->bdCtx, mesh->numCorners, mesh);

1484:   /* Calculate maximum degree of vertices */
1485:   MeshSetupSupport_Triangular_1D(mesh);

1487:   /* Construct derived and boundary information */
1488:   MeshSetupBoundary_Triangular_1D(mesh);

1490: #if 0
1491:   /* Reorder nodes before distributing mesh */
1492:   PetscOptionsHasName(mesh->prefix, "-mesh_reorder", &opt);
1493:   if (opt == PETSC_TRUE) {
1494:     /* MUST FIX: Since we have duplicated the whole mesh, we may impersonate a serial mesh */
1495:     comm       = mesh->comm;
1496:     mesh->comm = PETSC_COMM_SELF;
1497:     MeshGetOrdering(mesh, MESH_ORDER_TRIANGULAR_1D_RCM, &mesh->nodeOrdering);
1498:     mesh->comm = comm;

1500:     /* Permute arrays implicitly numbered by node numbers */
1501:     AOApplicationToPetscPermuteReal(mesh->nodeOrdering, mesh->dim, tri->nodes);
1502:     AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->markers);
1503:     AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->degrees);
1504:     /* Renumber arrays dependent on the canonical node numbering */
1505:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numEdges*2,                tri->edges);
1506:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numFaces*mesh->numCorners, tri->faces);
1507:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numBdNodes,                tri->bdNodes);
1508:   }
1509: #endif

1511:   /* Initialize partition */
1512:   MeshPartition(mesh);

1514:   /* Initialize save space */
1515:   tri->nodesOld = PETSC_NULL;

1517:   /* Reset the midnodes */
1518:   if (mesh->isPeriodic == PETSC_TRUE) {
1519:     MeshResetNodes(mesh, PETSC_TRUE);
1520:   }

1522:   return(0);
1523: }
1524: EXTERN_C_END

1526: int MeshRefine_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
1527:   Mesh             m;
1528:   Mesh_Triangular *tri;
1529:   int            (*f)(Mesh, PointFunction, Mesh);
1530:   int              ierr;

1533:   MeshCreate(mesh->comm, &m);

1535:   PetscNew(Mesh_Triangular, &tri);
1536:   PetscMemzero(tri, sizeof(Mesh_Triangular));
1537:   PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1538:   m->data = (void *) tri;
1539:   PetscStrallocpy(MESH_TRIANGULAR_1D, &m->type_name);
1540:   PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &m->serialize_name);
1541:   m->dim   = 1;
1542:   m->numBd = mesh->numBd;

1544:   /* Setup the periodic domain */
1545:   m->bdCtx = mesh->bdCtx;
1546:   if (m->isPeriodic == PETSC_TRUE) {
1547:     MeshBoundary2DSetBoundingBox(m, m->bdCtx);
1548:   }

1550:   /* Setup default mechanisms */
1551:   PetscFListDuplicate(((PetscObject) mesh)->qlist, &((PetscObject) m)->qlist);

1553:   /* Refine mesh */
1554:   PetscObjectQueryFunction((PetscObject) m, "MeshTriangular1D_Refine_C", (PetscVoidFunction) &f);
1555:   (*f)(mesh, area, m);

1557:   /* Calculate maximum degree of vertices */
1558:   MeshSetupSupport_Triangular_1D(m);

1560:   /* Construct derived and boundary information */
1561:   MeshSetupBoundary_Triangular_1D(m);

1563:   /* Initialize partition */
1564:   MeshPartition(m);

1566:   /* Initialize save space */
1567:   tri->nodesOld = PETSC_NULL;

1569:   /* Reset the midnodes */
1570:   if (m->isPeriodic == PETSC_TRUE) {
1571:     MeshResetNodes(m, PETSC_TRUE);
1572:   }
1573:   *newmesh = m;
1574:   return(0);
1575: }