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: #undef  __FUNCT__
 15: static int MeshDestroy_Triangular_1D(Mesh mesh) {
 16:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
 17:   int              ierr;

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

 65:   return(0);
 66: }

 68: /*------------------------------------------ Mesh-Specific Operations ------------------------------------------------*/
 69: #undef  __FUNCT__
 71: static int MeshPartition_Triangular_1D(Mesh mesh) {

 75:   PartitionCreate(mesh, &mesh->part);
 76:   PartitionSetType(mesh->part, PARTITION_TRIANGULAR_1D);
 77:   mesh->partitioned = 1;
 78:   PetscFunctionReturn(ierr);
 79: }

 81: #undef  __FUNCT__
 83: static int MeshCoarsen_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
 84:   SETERRQ(PETSC_ERR_SUP, " ");
 85: }

 87: #undef  __FUNCT__
 89: static int MeshResetNodes_Triangular_1D(Mesh mesh, PetscTruth resetBd) {
 90:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
 91:   int             *elements   = tri->edges;
 92:   double          *nodes      = tri->nodes;
 93:   int              numCorners = mesh->numCorners;
 94:   int              elem, node1, node2, midNode;

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

 99:   for(elem = 0; elem < mesh->part->numOverlapElements; elem++) {
100:     node1   = elements[elem*numCorners+0];
101:     node2   = elements[elem*numCorners+1];
102:     midNode = elements[elem*numCorners+2];
103:     nodes[midNode*2]   = MeshPeriodicX(mesh, 0.5*(nodes[node1*2]   +
104:                                                   MeshPeriodicRelativeX(mesh, nodes[node2*2],   nodes[node1*2])));
105:     nodes[midNode*2+1] = MeshPeriodicY(mesh, 0.5*(nodes[node1*2+1] +
106:                                                   MeshPeriodicRelativeY(mesh, nodes[node2*2+1], nodes[node1*2+1])));
107:   }
108:   return(0);
109: }

111: #undef  __FUNCT__
113: static int MeshSaveMesh_Triangular_1D(Mesh mesh) {
114:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
115:   int              dim = mesh->dim;
116:   int              numOverlapNodes;
117:   int              ierr;

120:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
121:   if (tri->nodesOld == PETSC_NULL) {
122:     PetscMalloc(numOverlapNodes*dim * sizeof(double), &tri->nodesOld);
123:     PetscLogObjectMemory(mesh, numOverlapNodes*dim * sizeof(double));
124:   }
125:   PetscMemcpy(tri->nodesOld, tri->nodes, numOverlapNodes*dim * sizeof(double));
126:   return(0);
127: }

129: #undef  __FUNCT__
131: static int MeshRestoreMesh_Triangular_1D(Mesh mesh) {
132:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
133:   int              dim = mesh->dim;
134:   int              numOverlapNodes;
135:   int              ierr;

138:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
139:   if (tri->nodesOld != PETSC_NULL) {
140:     PetscMemcpy(tri->nodes, tri->nodesOld, numOverlapNodes*dim * sizeof(double));
141:   }
142:   return(0);
143: }

145: /*-------------------------------------------- Mesh Query Functions --------------------------------------------------*/
146: #undef  __FUNCT__
148: static int MeshUpdateBoundingBox_Triangular_1D(Mesh mesh) {
149:   Mesh_Triangular *tri   = (Mesh_Triangular *) mesh->data;
150:   double          *nodes = tri->nodes;
151:   Partition        part;
152:   int              numOverlapNodes;
153:   int              node;
154:   int              ierr;

156:   /* Calculate the local bounding box */
158:   MeshGetPartition(mesh, &part);
159:   PartitionGetNumOverlapNodes(part, &numOverlapNodes);
160:   if (numOverlapNodes > 0) {
161:     mesh->locStartX = mesh->locEndX = nodes[0];
162:   } else {
163:     mesh->locStartX = mesh->locEndX = 0.0;
164:   }
165:   for(node = 0; node < numOverlapNodes; node++) {
166:     if (nodes[node] < mesh->locStartX) mesh->locStartX = nodes[node];
167:     if (nodes[node] > mesh->locEndX)   mesh->locEndX   = nodes[node];
168:   }
169:   mesh->locSizeX = mesh->locEndX - mesh->locStartX;
170:   return(0);
171: }

173: #undef  __FUNCT__
175: static int MeshIsDistorted_Triangular_1D(Mesh mesh, PetscTruth *flag) {
176:   Mesh_Triangular *tri            = (Mesh_Triangular *) mesh->data;
177:   double          *nodes          = tri->nodes;
178:   int             *elements       = tri->edges;
179:   int              numCorners     = mesh->numCorners;
180:   int              numElements    = mesh->numEdges;
181:   double           maxAspectRatio = mesh->maxAspectRatio;
182:   double           area;        /* Twice the area of the triangle */
183:   double           min;
184:   PetscTruth       locFlag;
185:   int              elem;
186:   int              locRetVal;
187:   int              retVal;
188:   int              ierr;

191:   for(elem = 0, locFlag = PETSC_FALSE, locRetVal = 0, min = mesh->sizeX; elem < numElements; elem++) {
192:     /* Find the area */
193:     area = MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+1]*2] - nodes[elements[elem*numCorners]*2]);
194:     /* Check for inverted elements */
195:     if (area < 0.0) {
196:       locFlag   = PETSC_TRUE;
197:       locRetVal = 1;
198:       break;
199:     } else if (area == 0.0) {
200:       SETERRQ1(PETSC_ERR_ARG_CORRUPT, "Element %d has no area", elem);
201:     }

203:     /* We cannot bail here since we must check for inverted elements */
204:     min = PetscMin(min, area);
205:   }
206:   if (min < 1.0/maxAspectRatio) {
207:     PetscLogInfo(mesh, "Area too small in element %d: %g < %gn", elem, min, 1.0/maxAspectRatio);
208:     locFlag = PETSC_TRUE;
209:   } else {
210:     PetscLogInfo(mesh, "Area in element %d: %gn", elem, min);
211:   }
212:   PetscLogFlops(elem);
213:   MPI_Allreduce(&locFlag,   flag,    1, MPI_INT, MPI_LOR, mesh->comm);
214:   MPI_Allreduce(&locRetVal, &retVal, 1, MPI_INT, MPI_LOR, mesh->comm);
215:   PetscFunctionReturn(retVal);
216: }

218: /*---------------------------------------- Mesh Boundary Query Functions ---------------------------------------------*/
219: #undef  __FUNCT__
221: static int MeshGetBoundarySize_Triangular_1D(Mesh mesh, int boundary, int *size) {
222:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
223:   int              b; /* Canonical boundary number */

226:   /* Find canonical boundary number */
227:   for(b = 0; b < mesh->numBd; b++) {
228:     if (tri->bdMarkers[b] == boundary) break;
229:   }
230:   if (b == mesh->numBd) SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid boundary specified");
231:   *size = tri->bdBegin[b+1] - tri->bdBegin[b];
232:   if ((*size != 0) && (*size != 1)) SETERRQ1(PETSC_ERR_PLIB, "Invalid boundary size %d", *size);
233:   return(0);
234: }

236: #undef  __FUNCT__
238: static int MeshGetBoundaryIndex_Triangular_1D(Mesh mesh, int boundary, int *index) {
239:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
240:   int              b; /* Canonical boundary number */

243:   /* Find canonical boundary number */
244:   for(b = 0; b < mesh->numBd; b++) {
245:     if (tri->bdMarkers[b] == boundary) break;
246:   }
247:   if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary marker %d", boundary);
248:   *index = b;
249:   return(0);
250: }

252: #undef  __FUNCT__
254: static int MeshGetBoundaryStart_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
255:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
256:   int              b; /* Canonical boundary number */
257:   int              ierr;

260:   /* Find canonical boundary number */
261:   for(b = 0; b < mesh->numBd; b++) {
262:     if (tri->bdMarkers[b] == boundary) break;
263:   }
264:   if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary  %d specified", boundary);
265:   if (mesh->activeBd != -1) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE, "Already iterating over boundary %d", mesh->activeBd);
266:   /* Find first boundary node */
267:   mesh->activeBd     = b;
268:   mesh->activeBdOld  = b;
269:   mesh->activeBdNode = tri->bdBegin[b] - 1;
270:   MeshGetBoundaryNext(mesh, boundary, ghost, node);
271:   PetscFunctionReturn(ierr);
272: }

274: #undef  __FUNCT__
276: static int MeshGetBoundaryNext_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
277:   Mesh_Triangular         *tri      = (Mesh_Triangular *) mesh->data;
278:   Partition                p        = mesh->part;
279:   Partition_Triangular_1D *q        = (Partition_Triangular_1D *) p->data;
280:   int                      numBd    = mesh->numBd;
281:   int                      numNodes = mesh->numNodes;
282:   int                      b;        /* Canonical boundary number */
283:   int                      tempNode; /* Canonical local node number */
284:   int                      ierr;

287:   /* Find canonical boundary number */
288:   for(b = 0; b < numBd; b++) {
289:     if (tri->bdMarkers[b] == boundary) break;
290:   }
291:   if (b == numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary %d specified", boundary);
292:   /* Find next boundary node */
293:   if (mesh->activeBd != b) SETERRQ1(PETSC_ERR_ARG_WRONG, "Boundary %d not active", boundary);
294:   do {
295:     mesh->activeBdNode++;
296:     if (mesh->activeBdNode == tri->bdBegin[b+1]) {
297:       mesh->activeBd = mesh->activeBdNode = -1;
298:       *node = -1;
299:       return(0);
300:     }
301:     tempNode = tri->bdNodes[mesh->activeBdNode] - q->firstNode[p->rank];
302:     /* Translate ghost nodes */
303:     if (ghost == PETSC_TRUE) {
304:       if ((tempNode < 0) || (tempNode >= numNodes)) {
305:         PartitionGhostNodeIndex_Private(p, tri->bdNodes[mesh->activeBdNode], &tempNode);
306:         if (ierr == 0) {
307:           tempNode += numNodes;
308:           break;
309:         }
310:       }
311:     }
312:   }
313:   while((tempNode < 0) || (tempNode >= numNodes));
314:   *node = tempNode;
315:   return(0);
316: }

318: #undef  __FUNCT__
320: static int MeshGetActiveBoundary_Triangular_1D(Mesh mesh, int *boundary) {
321:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;

324:   if (mesh->activeBdOld >= 0) {
325:     *boundary = tri->bdMarkers[mesh->activeBdOld];
326:   } else {
327:     *boundary = 0;
328:   }
329:   return(0);
330: }

332: /*------------------------------------------ Mesh Node Query Functions -----------------------------------------------*/
333: #undef  __FUNCT__
335: static int MeshGetNodeBoundary_Triangular_1D(Mesh mesh, int node, int *bd) {
336:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
337: #ifdef PETSC_USE_BOPT_g
338:   int              numOverlapNodes;
339:   int              ierr;
340: #endif

343: #ifdef PETSC_USE_BOPT_g
344:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
345:   if ((node < 0) || (node >= numOverlapNodes)) {
346:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
347:   }
348: #endif
349:   *bd = tri->markers[node];
350:   return(0);
351: }

353: #undef  __FUNCT__
355: static int MeshNodeIsVertex_Triangular_1D(Mesh mesh, int node, PetscTruth *isVertex) {
356:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
357: #ifdef PETSC_USE_BOPT_g
358:   int              numOverlapNodes;
359:   int              ierr;
360: #endif

363: #ifdef PETSC_USE_BOPT_g
364:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
365:   if ((node < 0) || (node >= numOverlapNodes)) {
366:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
367:   }
368: #endif
369:   if (tri->degrees[node] == 0) {
370:     *isVertex = PETSC_FALSE;
371:   } else {
372:     *isVertex = PETSC_TRUE;
373:   }
374:   return(0);
375: }

377: #undef  __FUNCT__
379: static int MeshGetNodeCoords_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 (x != PETSC_NULL) *x = tri->nodes[node];
392:   return(0);
393: }

395: #undef  __FUNCT__
397: static int MeshSetNodeCoords_Triangular_1D(Mesh mesh, int node, double x, double y, double z) {
398:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
399: #ifdef PETSC_USE_BOPT_g
400:   int              numOverlapNodes;
401:   int              ierr;
402: #endif

405: #ifdef PETSC_USE_BOPT_g
406:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
407:   if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
408: #endif
409:   tri->nodes[node] = MeshPeriodicX(mesh, x);
410:   return(0);
411: }

413: #undef  __FUNCT__
415: static int MeshGetNodeCoordsSaved_Triangular_1D(Mesh mesh, int node, double *x, double *y, double *z) {
416:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
417: #ifdef PETSC_USE_BOPT_g
418:   int              numOverlapNodes;
419:   int              ierr;
420: #endif

423: #ifdef PETSC_USE_BOPT_g
424:   ierr  = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
425:   if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
426: #endif
427:   if (tri->nodesOld != PETSC_NULL) {
428:     if (x != PETSC_NULL) *x = tri->nodesOld[node];
429:   } else {
430:     if (x != PETSC_NULL) *x = tri->nodes[node];
431:   }
432:   return(0);
433: }

435: #undef  __FUNCT__
437: static int MeshNearestNode_Triangular_1D(Mesh mesh, double x, double y, double z, PetscTruth outsideDomain, int *node) {
438:   Mesh_Triangular         *tri        = (Mesh_Triangular *) mesh->data;
439:   Partition                p          = mesh->part;
440:   Partition_Triangular_1D *q          = (Partition_Triangular_1D *) p->data;
441:   int                      numCorners = mesh->numCorners;
442:   int                     *elements   = tri->edges;
443:   int                      numNodes   = mesh->numNodes;
444:   double                  *nodes      = tri->nodes;
445:   int                     *firstNode  = q->firstNode;
446:   int                      rank       = p->rank;
447:   int                      elem;
448:   double                   minDist, dist, allMinDist;
449:   int                      minNode, globalMinNode, allMinNode;
450:   int                      corner, n;
451:   int                      ierr;

454:   if (outsideDomain == PETSC_FALSE) {
455:     MeshLocatePoint(mesh, x, y, z, &elem);
456:     if (elem >= 0) {
457:       minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners]] - x));
458:       minNode = elements[elem*numCorners];
459:       for(corner = 1; corner < numCorners; corner++) {
460:         dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+corner]] - x));
461:         if (dist < minDist) {
462:           minDist = dist;
463:           minNode = elements[elem*numCorners+corner];
464:         }
465:       }
466:       PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
467:     } else {
468:       minNode       = -1;
469:       globalMinNode = -1;
470:     }
471:   } else {
472:     /* Brute force check */
473:     minNode = 0;
474:     minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[0] - x));
475:     for(n = 1; n < numNodes; n++) {
476:       dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[n] - x));
477:       if (dist < minDist) {
478:         minDist = dist;
479:         minNode = n;
480:       }
481:     }

483:     /* Find the minimum distance */
484:     MPI_Allreduce(&minDist, &allMinDist, 1, MPI_DOUBLE, MPI_MIN, p->comm);
485:     if (minDist == allMinDist) {
486:       PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
487:     } else {
488:       globalMinNode = -1;
489:     }
490:   }

492:   /* We might still have ties, i.e. the minimum node is a ghost node */
493:   MPI_Allreduce(&globalMinNode, &allMinNode, 1, MPI_INT, MPI_MAX, p->comm);
494:   if ((allMinNode >= firstNode[rank]) && (allMinNode < firstNode[rank+1])) {
495:     *node = allMinNode - firstNode[rank];
496:   } else {
497:     *node = -1;
498:   }
499:   if (allMinNode < 0) PetscFunctionReturn(1);

501:   return(0);
502: }

504: #undef  __FUNCT__
506: static int MeshGetNodeSupport_Triangular_1D(Mesh mesh, int node, int startElem, int *degree, int **support) {
507:   Mesh_Triangular *tri                = (Mesh_Triangular *) mesh->data;
508:   int              numOverlapElements = mesh->numEdges;
509:   int              numCorners         = mesh->numCorners;
510:   int             *elements           = tri->edges;
511:   int             *neighbors          = tri->neighbors;
512:   int              deg                = -1;
513:   int              firstElem;
514:   int              elem, neighbor, corner;

517:   /* First check suggested element */
518:   firstElem = -1;
519:   for(corner = 0; corner < numCorners; corner++) {
520:     if (elements[startElem*numCorners+corner] == node) {
521:       firstElem = startElem;
522:       if (corner >= 2) {
523:         deg = 1;
524:       } else {
525:         deg = 0;
526:       }
527:       break;
528:     }
529:   }

531:   /* Locate an element containing the node */
532:   if (mesh->part != PETSC_NULL) {
533:     numOverlapElements = mesh->part->numOverlapElements;
534:   }
535:   for(elem = 0; (elem < numOverlapElements) && (firstElem < 0); elem++) {
536:     for(corner = 0; corner < numCorners; corner++) {
537:       if (elements[elem*numCorners+corner] == node) {
538:         firstElem = elem;
539:         if (corner >= 2) {
540:           deg = 1;
541:         } else {
542:           deg = 0;
543:         }
544:         break;
545:       }
546:     }
547:   }
548:   if (firstElem < 0) {
549:     SETERRQ1(PETSC_ERR_ARG_WRONG, "Node %d not found in mesh", node);
550:   }

552:   /* Check for midnode */
553:   if (deg != 0) {
554:     mesh->support[0] = firstElem;
555:     mesh->support[1] = -1;
556:     *support = mesh->support;
557:     *degree  = deg;
558:     return(0);
559:   }

561:   /* Add element to the list */
562:   mesh->support[deg++] = firstElem;
563:   /* Look for a neighbor containing the node */
564:   for(neighbor = 0; neighbor < 2; neighbor++) {
565:     elem = neighbors[firstElem*2+neighbor];
566:     if (elem < 0) continue;

568:     for(corner = 0; corner < 2; corner++) {
569:       if (elements[elem*numCorners+corner] == node) {
570:         mesh->support[deg++] = elem;
571:         break;
572:       }
573:     }
574:   }

576:   if (deg > 2) {
577:     SETERRQ1(PETSC_ERR_PLIB, "Node %d has invalid support", node);
578:   } else if (deg < 2) {
579:     /* Make sure that this is a boundary node */
580:     if (tri->markers[node] == 0) SETERRQ1(PETSC_ERR_PLIB, "Interior node %d with incomplete support", node);
581:   }

583: #ifdef PETSC_USE_BOPT_g
584:   /* Check for overflow */
585:   if (deg > mesh->maxDegree) SETERRQ1(PETSC_ERR_MEM, "Maximum degree %d exceeded", mesh->maxDegree);
586: #endif

588:   *support = mesh->support;
589:   *degree  = deg;
590:   return(0);
591: }

593: /*----------------------------------------- Mesh Element Query Functions ---------------------------------------------*/
594: #undef  __FUNCT__
596: static int MeshGetElemNeighbor_Triangular_1D(Mesh mesh, int elem, int corner, int *neighbor) {
597:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
598: #ifdef PETSC_USE_BOPT_g
599:   int              numOverlapElements;
600:   int              ierr;
601: #endif

604: #ifdef PETSC_USE_BOPT_g
605:   PartitionGetNumOverlapElements(mesh->part, &numOverlapElements);
606:   if ((elem < 0)   || (elem >= numOverlapElements)) {
607:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid element %d should be in [0,%d)", elem, numOverlapElements);
608:   }
609:   if ((corner < 0) || (corner >= mesh->numCorners)) {
610:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid corner %d should be in [0,%d)", corner, mesh->numCorners);
611:   }
612: #endif
613:   *neighbor = tri->neighbors[elem*2+corner];
614:   return(0);
615: }

617: #if 0
618: #undef  __FUNCT__
620: static int MeshLocatePoint_Triangular_1D_Directed(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
621:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;

624:   /* We should use bisection here */
625:   return(0);
626: }
627: #endif

629: #undef  __FUNCT__
631: static int MeshLocatePoint_Triangular_1D(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
632:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
633:   int              numCorners  = mesh->numCorners;
634:   int              numElements = mesh->numEdges;
635:   double          *nodes       = tri->nodes;
636:   int             *elements    = tri->edges;
637:   double           x           = xx;
638:   double           coords[2];
639:   int              elem;

642:   *containingElem = -1;
643:   /* Quick bounding rectangle check */
644:   if ((mesh->isPeriodic == PETSC_FALSE) && ((mesh->locStartX > x) || (mesh->locEndX < x))) return(0);
645:   /* Simple search */
646:   for(elem = 0; elem < numElements; elem++) {
647:     coords[0] = nodes[elements[elem*numCorners]];
648:     coords[1] = MeshPeriodicRelativeX(mesh, nodes[elements[elem*numCorners+1]],   nodes[elements[elem*numCorners]]);
649:     x         = MeshPeriodicRelativeX(mesh, xx, nodes[elements[elem*numCorners]]);

651:     if ((x >= coords[0]) && (x < coords[1])) {
652:       *containingElem = elem;
653:       break;
654:     }
655:   }
656:   /* Check for the right endpoint */
657:   if ((x >= coords[0]) && (x <= coords[1])) *containingElem = numElements-1;

659:   return(0);
660: }

662: /*------------------------------------------- Mesh Embedding Functions -----------------------------------------------*/
663: #undef  __FUNCT__
665: static int MeshGetNodeFromElement_Triangular_1D(Mesh mesh, int elem, int corner, int *node) {
666:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
667:   int              numCorners = mesh->numCorners;

670:   *node = tri->edges[elem*numCorners+corner];
671:   return(0);
672: }

674: #undef  __FUNCT__
676: static int MeshGetNodeFromEdge_Triangular_1D(Mesh mesh, int edge, int corner, int *node) {
677:   Mesh_Triangular *tri        = (Mesh_Triangular *) mesh->data;
678:   int              numCorners = mesh->numCorners;

681:   *node = tri->edges[edge*numCorners+corner];
682:   return(0);
683: }

685: /*----------------------------------------------- Internal Functions -------------------------------------------------*/
686: #undef  __FUNCT__
688: static int MeshSetupSupport_Triangular_1D(Mesh mesh) {
689:   Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
690:   int              edge, node;
691:   int              ierr;

694:   /* Calculate maximum degree of vertices */
695:   if (mesh->numNodes > 0) {
696:     PetscMalloc(mesh->numNodes * sizeof(int), &tri->degrees);
697:   }
698:   PetscMemzero(tri->degrees, mesh->numNodes * sizeof(int));
699:   for(edge = 0; edge < mesh->numEdges; edge++) {
700:     tri->degrees[tri->edges[edge*mesh->numCorners]]++;
701:     tri->degrees[tri->edges[edge*mesh->numCorners+1]]++;
702:   }
703:   for(node = 0, mesh->maxDegree = 0; node < mesh->numNodes; node++) {
704:     mesh->maxDegree = PetscMax(mesh->maxDegree, tri->degrees[node]);
705:   }
706:   if (mesh->maxDegree > 0) {
707:     PetscMalloc(mesh->maxDegree * sizeof(int), &mesh->support);
708:   }
709:   mesh->supportTaken = PETSC_FALSE;
710:   return(0);
711: }

713: #undef  __FUNCT__
715: static int MeshCheckBoundary_Triangular_1D(Mesh mesh) {
716:   MeshBoundary2D *bdCtx         = mesh->bdCtx;
717:   int            *markers       = bdCtx->markers;
718:   int             numBd         = 0;
719:   int             numBdVertices = 0;
720:   int            *bdMarkers;
721:   int            *bdBegin;
722:   int             bd, vertex, rank;
723:   int             ierr;

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

730:   if (bdCtx->numBd != bdCtx->numVertices) {
731:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "All boundaries must be points: %d != %d", bdCtx->numBd, bdCtx->numVertices);
732:   }
733:   if ((bdCtx->numVertices != 0) && (bdCtx->numVertices != 2)) {
734:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of boundary points %d", bdCtx->numVertices);
735:   }
736:   if ((bdCtx->numVertices == 0) && (mesh->isPeriodic == PETSC_FALSE)) {
737:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Non-periodic domain must have 2 boundary points");
738:   }
739:   if (bdCtx->numVertices > 0) {
742:   }
743:   PetscMalloc(bdCtx->numBd     * sizeof(int), &bdMarkers);
744:   PetscMalloc((bdCtx->numBd+1) * sizeof(int), &bdBegin);
745:   PetscMemzero(bdBegin,        (bdCtx->numBd+1) * sizeof(int));
746:   for(vertex = 0; vertex < bdCtx->numVertices; vertex++) {
747:     if (markers[vertex] == 0) continue;
748:     numBdVertices++;
749:     /* Check for new marker */
750:     for(bd = 0; bd < numBd; bd++) {
751:       if (markers[vertex] == bdMarkers[bd]) break;
752:     }
753:     if (bd == numBd) {
754:       if (numBd >= bdCtx->numBd) SETERRQ1(PETSC_ERR_ARG_CORRUPT, "More markers present than declared: %d", bdCtx->numBd);
755:       /* Insert new marker */
756:       for(bd = 0; bd < numBd; bd++) {
757:         if (markers[vertex] < bdMarkers[bd]) break;
758:       }
759:       if (bd < numBd) {
760:         PetscMemmove(&bdMarkers[bd+1], &bdMarkers[bd], (numBd-bd) * sizeof(int));
761:         PetscMemmove(&bdBegin[bd+2],   &bdBegin[bd+1], (numBd-bd) * sizeof(int));
762:         bdBegin[bd+1] = 0;
763:       }
764:       bdMarkers[bd] = markers[vertex];
765:       numBd++;
766:       bdBegin[bd+1]++;
767:     } else {
768:       bdBegin[bd+1]++;
769:     }
770:   }

772:   /* Do prefix sums to get position offsets */
773:   for(bd = 2; bd <= numBd; bd++) {
774:     bdBegin[bd] = bdBegin[bd-1] + bdBegin[bd];
775:   }

777:   if (numBd != bdCtx->numBd) {
778:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", numBd, bdCtx->numBd);
779:   }
780:   if (bdBegin[numBd] != numBdVertices) {
781:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary vertices %d should be %d", bdBegin[numBd], numBdVertices);
782:   }
783:   PetscFree(bdMarkers);
784:   PetscFree(bdBegin);
785:   return(0);
786: }

788: #undef  __FUNCT__
790: static int MeshSetupBoundary_Triangular_1D(Mesh mesh) {
791:   Mesh_Triangular *tri      = (Mesh_Triangular *) mesh->data;
792:   int              numBd    = mesh->numBd;
793:   int              numNodes = mesh->numNodes;
794:   int             *markers  = tri->markers;
795:   int              newNumBd;   /* Current number of different boundary markers */
796:   int             *bdNodes;    /* Node numbers for boundary nodes ordered by boundary */
797:   int             *bdBeginOff; /* Current offset into the bdNodes or bdEdges array */
798:   int              rank, bd, node;
799:   int              ierr;

802:   MPI_Comm_rank(mesh->comm, &rank);
803:   PetscLogEventBegin(MESH_SetupBoundary, mesh, 0, 0, 0);
804:   mesh->numBdNodes = 0;
805:   if (numBd == 0) {
806:     tri->bdMarkers = PETSC_NULL;
807:     tri->bdBegin   = PETSC_NULL;
808:     tri->bdNodes   = PETSC_NULL;
809:     return(0);
810:   }
811:   PetscMalloc(numBd     * sizeof(int), &tri->bdMarkers);
812:   PetscMalloc((numBd+1) * sizeof(int), &tri->bdBegin);
813:   PetscMalloc((numBd+1) * sizeof(int), &bdBeginOff);
814:   PetscLogObjectMemory(mesh, (numBd + (numBd+1)) * sizeof(int));
815:   PetscMemzero(tri->bdMarkers,   numBd     * sizeof(int));
816:   PetscMemzero(tri->bdBegin,     (numBd+1) * sizeof(int));
817:   PetscMemzero(bdBeginOff,       (numBd+1) * sizeof(int));

819:   for(node = 0, newNumBd = 0; node < numNodes; node++) {
820:     /* Get number of boundary nodes and markers */
821:     if (markers[node]) {
822:       mesh->numBdNodes++;
823:       /* Check for new marker */
824:       for(bd = 0; bd < newNumBd; bd++) {
825:         if (markers[node] == tri->bdMarkers[bd]) break;
826:       }
827:       if (bd == newNumBd) {
828:         /* Insert new marker */
829:         for(bd = 0; bd < newNumBd; bd++) {
830:           if (markers[node] < tri->bdMarkers[bd]) break;
831:         }
832:         if (bd < newNumBd) {
833:           PetscMemmove(&tri->bdMarkers[bd+1], &tri->bdMarkers[bd], (newNumBd-bd) * sizeof(int));
834:           PetscMemmove(&tri->bdBegin[bd+2],   &tri->bdBegin[bd+1], (newNumBd-bd) * sizeof(int));
835:           tri->bdBegin[bd+1] = 0;
836:         }
837:         tri->bdMarkers[bd] = markers[node];
838:         newNumBd++;
839:         tri->bdBegin[bd+1]++;
840:       } else {
841:         tri->bdBegin[bd+1]++;
842:       }
843:     }
844:   }

846:   /* Do prefix sums to get position offsets */
847:   for(bd = 2; bd <= numBd; bd++) {
848:     tri->bdBegin[bd] = tri->bdBegin[bd-1] + tri->bdBegin[bd];
849:   }

851:   /* Check boundary information consistency */
852:   if (newNumBd != numBd) {
853:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", newNumBd, numBd);
854:   }
855:   if (tri->bdBegin[numBd] != mesh->numBdNodes) {
856:     SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d should be %d", tri->bdBegin[numBd], mesh->numBdNodes);
857:   }
858:   if ((mesh->numBdNodes != 0) && (mesh->numBdNodes != 2)) {
859:     SETERRQ1(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d", mesh->numBdNodes);
860:   }
861:   if (mesh->numBdNodes != mesh->numBd) {
862:     SETERRQ2(PETSC_ERR_PLIB, "Inconsistent boundary information: numBd %d != numBdNodes %d", mesh->numBd, mesh->numBdNodes);
863:   }

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

868:   /* Split nodes by marker */
869:   PetscMemcpy(bdBeginOff, tri->bdBegin, (numBd+1) * sizeof(int));
870:   for(node = 0; node < numNodes; node++) {
871:     for(bd = 0; bd < numBd; bd++) {
872:       if (markers[node] == tri->bdMarkers[bd]) {
873: #ifdef MESH_TRACE_BOUNDARY_CREATE
874:         PetscPrintf(PETSC_COMM_WORLD, "bd: %d bdNode[%d] = %dn", bd, bdBeginOff[bd], node);
875: #endif
876:         bdNodes[bdBeginOff[bd]++] = node;
877:       }
878:     }
879:   }
880:   for(bd = 0; bd < numBd; bd++) {
881:     if (tri->bdBegin[bd+1] != bdBeginOff[bd])
882:       SETERRQ(PETSC_ERR_PLIB, "Invalid boundary node marker information");
883:   }
884:   PetscFree(bdBeginOff);

886:   /* Set fields */
887:   tri->bdNodes = bdNodes;

889:   PetscLogEventEnd(MESH_SetupBoundary, mesh, 0, 0, 0);
890:   return(0);
891: }

893: #undef  __FUNCT__
895: /*
896:   MeshAssemble_Triangular_1D - This function assembles the mesh entirely on the first processor.

898:   Collective on Mesh

900:   Input Parameters:
901: . mesh    - The mesh being refined

903:   Output Parameter:
904: + nodes   - The node coordinates
905: . markers - The node markers
906: - edges   - The nodes for each edge

908:   Level: developer

910: .keywords mesh, assemble
911: .seealso MeshInitRefineInput_Triangle()
912: */
913: int MeshAssemble_Triangular_1D(Mesh mesh, double **nodes, int **markers, int **faces, int **edges) {
914:   Mesh_Triangular         *tri        = (Mesh_Triangular *) mesh->data;
915:   Partition                p          = mesh->part;
916:   Partition_Triangular_1D *q          = (Partition_Triangular_1D *) p->data;
917:   int                      numNodes   = q->numNodes;
918:   int                      numEdges   = p->numElements;
919:   int                      numCorners = mesh->numCorners;
920:   int                      numProcs   = p->numProcs;
921:   int                      rank       = p->rank;
922:   int                     *locEdges   = PETSC_NULL;
923:   int                     *numRecvNodes, *numRecvMarkers, *numRecvEdges;
924:   int                     *nodeOffsets,  *markerOffsets,  *edgeOffsets;
925:   int                      proc, edge, size;
926:   int                      ierr;

929:   /* Allocate global arrays */
930:   if (rank == 0) {
931:     PetscMalloc(numNodes*2          * sizeof(double), nodes);
932:     PetscMalloc(numNodes            * sizeof(int),    markers);
933:     PetscMalloc(numEdges*numCorners * sizeof(int),    edges);
934:   }

936:   if (numProcs > 1) {
937:     if (mesh->numEdges > 0) {
938:       PetscMalloc(mesh->numEdges*numCorners * sizeof(int), &locEdges);
939:     }

941:     /* Calculate offsets */
942:     PetscMalloc(numProcs * sizeof(int), &numRecvNodes);
943:     PetscMalloc(numProcs * sizeof(int), &numRecvMarkers);
944:     PetscMalloc(numProcs * sizeof(int), &numRecvEdges);
945:     PetscMalloc(numProcs * sizeof(int), &nodeOffsets);
946:     PetscMalloc(numProcs * sizeof(int), &markerOffsets);
947:     PetscMalloc(numProcs * sizeof(int), &edgeOffsets);
948:     for(proc = 0; proc < numProcs; proc++) {
949:       numRecvNodes[proc]   = (q->firstNode[proc+1]    - q->firstNode[proc])*2;
950:       numRecvMarkers[proc] = (q->firstNode[proc+1]    - q->firstNode[proc]);
951:       numRecvEdges[proc]   = (p->firstElement[proc+1] - p->firstElement[proc])*numCorners;
952:     }
953:     nodeOffsets[0]   = 0;
954:     markerOffsets[0] = 0;
955:     edgeOffsets[0]   = 0;
956:     for(proc = 1; proc < numProcs; proc++) {
957:       nodeOffsets[proc]   = numRecvNodes[proc-1]   + nodeOffsets[proc-1];
958:       markerOffsets[proc] = numRecvMarkers[proc-1] + markerOffsets[proc-1];
959:       edgeOffsets[proc]   = numRecvEdges[proc-1]   + edgeOffsets[proc-1];
960:     }

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

967:     /* Collect global arrays */
968:     size = mesh->numNodes*2;
969:     MPI_Gatherv(tri->nodes,   size, MPI_DOUBLE, *nodes,   numRecvNodes,   nodeOffsets,   MPI_DOUBLE, 0, p->comm);
970: 
971:     size = mesh->numNodes;
972:     MPI_Gatherv(tri->markers, size, MPI_INT,    *markers, numRecvMarkers, markerOffsets, MPI_INT,    0, p->comm);
973: 
974:     size = mesh->numEdges*numCorners;
975:     MPI_Gatherv(locEdges,     size, MPI_INT,    *edges,   numRecvEdges,   edgeOffsets,   MPI_INT,    0, p->comm);
976: 

978:     /* Cleanup */
979:     if (locEdges != PETSC_NULL) {
980:       PetscFree(locEdges);
981:     }
982:     PetscFree(numRecvNodes);
983:     PetscFree(numRecvMarkers);
984:     PetscFree(numRecvEdges);
985:     PetscFree(nodeOffsets);
986:     PetscFree(markerOffsets);
987:     PetscFree(edgeOffsets);
988:   } else {
989:     /* Uniprocessor case */
990:     PetscMemcpy(*nodes,   tri->nodes,   numNodes*2          * sizeof(double));
991:     PetscMemcpy(*markers, tri->markers, numNodes            * sizeof(int));
992:     PetscMemcpy(*edges,   tri->edges,   numEdges*numCorners * sizeof(int));
993:   }
994:   return(0);
995: }

997: #undef  __FUNCT__
999: int MeshDebug_Triangular_1D(Mesh mesh, PetscTruth distributed) {
1000:   Mesh_Triangular         *tri = (Mesh_Triangular *) mesh->data;
1001:   Partition                p   = mesh->part;
1002:   Partition_Triangular_1D *q   = PETSC_NULL;
1003:   int                      numBd       = mesh->numBd;
1004:   int                      numElements = mesh->numFaces;
1005:   int                      numCorners  = mesh->numCorners;
1006:   int                      numNodes    = mesh->numNodes;
1007:   int                     *elements    = tri->faces;
1008:   int                     *markers     = tri->markers;
1009:   int                     *bdMarkers   = tri->bdMarkers;
1010:   int                      degree;
1011:   int                     *support;
1012:   int                     *degrees;
1013:   int                     *supports;
1014:   int                     *sizes;
1015:   int                      numProcs, rank;
1016:   PetscTruth               isMidnode;
1017:   int                      proc, bd, elem, nElem, sElem, sElem2, corner, node, newNode, size;
1018:   int                      ierr;

1021:   MPI_Comm_size(mesh->comm, &numProcs);
1022:   MPI_Comm_rank(mesh->comm, &rank);
1023:   if (p != PETSC_NULL) {
1024:     q = (Partition_Triangular_1D *) p->data;
1025:   }

1027:   /* Check basic sizes */
1028:   PetscMalloc(numProcs * sizeof(int), &sizes);
1029:   MPI_Allgather(&mesh->numBd, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1030:   for(proc = 0, 0; proc < numProcs-1; proc++) {
1031:     if (sizes[proc] != sizes[proc+1]) {
1032:       PetscPrintf(mesh->comm, "The number of boundaries is different on proc %d(%d) and proc %d(%d)n",
1033:                   proc, sizes[proc], proc+1, sizes[proc+1]);
1034:       1;
1035:     }
1036:   }
1037: 
1038: #if 0
1039:   /* I made vertices distributed in linear meshes */
1040:   MPI_Allgather(&tri->numVertices, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1041:   for(proc = 0, 0; proc < numProcs-1; proc++) {
1042:     if (sizes[proc] != sizes[proc+1]) {
1043:       PetscPrintf(mesh->comm, "The number of vertices is different on proc %d(%d) and proc %d(%d)n",
1044:                   proc, sizes[proc], proc+1, sizes[proc+1]);
1045:       1;
1046:     }
1047:   }
1048: 
1049: #endif
1050:   MPI_Allgather(&mesh->numCorners, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1051:   for(proc = 0, 0; proc < numProcs-1; proc++) {
1052:     if (sizes[proc] != sizes[proc+1]) {
1053:       PetscPrintf(mesh->comm, "The number of face corners is different on proc %d(%d) and proc %d(%d)n",
1054:                   proc, sizes[proc], proc+1, sizes[proc+1]);
1055:       1;
1056:     }
1057:   }
1058: 
1059:   MPI_Allgather(&mesh->numBdEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1060:   for(proc = 0, 0; proc < numProcs-1; proc++) {
1061:     if (sizes[proc] != sizes[proc+1]) {
1062:       PetscPrintf(mesh->comm, "The number of boundary edges is different on proc %d(%d) and proc %d(%d)n",
1063:                   proc, sizes[proc], proc+1, sizes[proc+1]);
1064:       1;
1065:     }
1066:   }
1067: 
1068:   if (distributed == PETSC_FALSE) {
1069:     MPI_Allgather(&mesh->numNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1070:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1071:       if (sizes[proc] != sizes[proc+1]) {
1072:         PetscPrintf(mesh->comm, "The number of nodes is different on proc %d(%d) and proc %d(%d)n",
1073:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1074:         1;
1075:       }
1076:     }
1077: 
1078:     MPI_Allgather(&mesh->numBdNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1079:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1080:       if (sizes[proc] != sizes[proc+1]) {
1081:         PetscPrintf(mesh->comm, "The number of boundary nodes is different on proc %d(%d) and proc %d(%d)n",
1082:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1083:         1;
1084:       }
1085:     }
1086: 
1087:     MPI_Allgather(&mesh->numEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1088:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1089:       if (sizes[proc] != sizes[proc+1]) {
1090:         PetscPrintf(mesh->comm, "The number of edges is different on proc %d(%d) and proc %d(%d)n",
1091:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1092:         1;
1093:       }
1094:     }
1095: 
1096:     MPI_Allgather(&mesh->numFaces, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1097:     for(proc = 0, 0; proc < numProcs-1; proc++) {
1098:       if (sizes[proc] != sizes[proc+1]) {
1099:         PetscPrintf(mesh->comm, "The number of faces is different on proc %d(%d) and proc %d(%d)n",
1100:                     proc, sizes[proc], proc+1, sizes[proc+1]);
1101:         1;
1102:       }
1103:     }
1104: 
1105:   } else {
1106:     MPI_Allreduce(&mesh->numNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1107:     if (size != q->numNodes) {
1108:       SETERRQ2(PETSC_ERR_PLIB, "The total number of nodes %d should be %dn", size, q->numNodes);
1109:     }
1110: #if 0
1111:     MPI_Allreduce(&tri->numBdNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1112: #else
1113:     size = mesh->numBdNodes;
1114: #endif
1115:     if (size != q->numBdNodes) {
1116:       SETERRQ2(PETSC_ERR_PLIB, "The total number of boundary nodes %d should be %dn", size, q->numBdNodes);
1117:     }
1118:     MPI_Allreduce(&mesh->numEdges, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1119:     if (size != mesh->part->numElements) {
1120:       SETERRQ2(PETSC_ERR_PLIB, "The total number of edges %d should be %dn", size, mesh->part->numElements);
1121:     }
1122:   }
1123:   PetscFree(sizes);

1125:   if (distributed == PETSC_FALSE) {
1126:     /* Check markers */
1127:     for(node = 0; node < numNodes; node++) {
1128:       if (!markers[node]) continue;

1130:       for(bd = 0; bd < numBd; bd++)
1131:         if(bdMarkers[bd] == markers[node])
1132:           break;
1133:       if (bd == numBd) {
1134:         SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1135:       }
1136:     }
1137:     /* Check mesh connectivity */
1138:     for(node = 0; node < numNodes; node++) {
1139:       MeshGetNodeSupport(mesh, node, 0, &degree, &support);

1141:       /* Check node degree */
1142:       PetscMalloc(numProcs * sizeof(int), &degrees);
1143:       MPI_Allgather(&degree, 1, MPI_INT, degrees, 1, MPI_INT, mesh->comm);
1144:       for(proc = 0, 0; proc < numProcs-1; proc++)
1145:         if (degrees[proc] != degrees[proc+1]) {
1146:           PetscPrintf(mesh->comm, "Degree of node %d is different on proc %d(%d) and proc %d(%d)n",
1147:                       node, proc, degrees[proc], proc+1, degrees[proc+1]);
1148:           PetscPrintf(mesh->comm, "Node Information:n");
1149:           PetscSequentialPhaseBegin(mesh->comm, 1);
1150:             PetscPrintf(PETSC_COMM_SELF, "  Processor %dn", rank);
1151:             if ((rank == proc) || (rank == proc+1))
1152:               for(sElem = 0; sElem < degree; sElem++)
1153:                 PetscPrintf(PETSC_COMM_SELF, "  Support    : %dn", support[sElem]);
1154:             PetscPrintf(PETSC_COMM_SELF, "  Marker     : %dn", tri->markers[node]);
1155:             PetscPrintf(PETSC_COMM_SELF, "  Location   : (%g,%g)n", tri->nodes[node*2], tri->nodes[node*2+1]);
1156:             PetscPrintf(PETSC_COMM_SELF, "  In Elements:");
1157:             for(elem = 0, isMidnode = PETSC_FALSE; elem < numElements; elem++)
1158:               for(corner = 0; corner < numCorners; corner++)
1159:                 if (elements[elem*numCorners+corner] == node) {
1160:                   PetscPrintf(PETSC_COMM_SELF, " %d", elem);
1161:                   if (corner >= 3)
1162:                     isMidnode = PETSC_TRUE;
1163:                 }
1164:             PetscPrintf(PETSC_COMM_SELF, "n");
1165:             if (isMidnode == PETSC_TRUE)
1166:               PetscPrintf(PETSC_COMM_SELF, "  Midnoden");
1167:             else
1168:               PetscPrintf(PETSC_COMM_SELF, "  Vertexn");
1169:           PetscSequentialPhaseEnd(mesh->comm, 1);
1170:           1;
1171:         }
1172: 
1173:       PetscFree(degrees);

1175:       /* Check support elements */
1176:       PetscMalloc(degree*numProcs * sizeof(int), &supports);
1177:       MPI_Allgather(support, degree, MPI_INT, supports, degree, MPI_INT, mesh->comm);
1178:       for(sElem = 0, 0; sElem < degree; sElem++) {
1179:         nElem = supports[sElem];
1180:         for(proc = 1; proc < numProcs; proc++) {
1181:           for(sElem2 = 0; sElem2 < degree; sElem2++)
1182:             if (supports[proc*degree+sElem2] == nElem)
1183:               break;
1184:           if (sElem2 == degree) {
1185:             PetscPrintf(mesh->comm, "Support element %d of node %d on proc %d(%d) is not present on proc %dn",
1186:                         sElem, node, 0, supports[sElem], proc);
1187:             PetscPrintf(mesh->comm, "  Support of node %d on proc %d:n   ", node, proc);
1188:             for(sElem2 = 0; sElem2 < degree; sElem2++)
1189:               PetscPrintf(mesh->comm, " %d", supports[proc*degree+sElem2]);
1190:             PetscPrintf(mesh->comm, "n");
1191:             1;
1192:           }
1193:         }
1194:       }
1195: 
1196:       PetscFree(supports);

1198:       /* Check that node only appears inside elements in the support */
1199:       for(elem = 0, 0; elem < numElements; elem++)
1200:         for(corner = 0; corner < numCorners; corner++) {
1201:           newNode = elements[elem*numCorners+corner];
1202:           if (node == newNode) {
1203:             for(sElem = 0; sElem < degree; sElem++)
1204:               if (support[sElem] == elem)
1205:                 break;
1206:             if (sElem == degree) {
1207:               PetscPrintf(mesh->comm, "Node %d found in element %d which is not present in the supportn",
1208:                           node, elem);
1209:               1;
1210:             }
1211:           }
1212:         }
1213: 

1215:       MeshRestoreNodeSupport(mesh, node, 0, &degree, &support);
1216:     }
1217:   } else {
1218:     /* Check markers */
1219:     for(node = 0; node < q->numOverlapNodes; node++) {
1220:       if (!markers[node]) continue;

1222:       for(bd = 0; bd < numBd; bd++)
1223:         if(bdMarkers[bd] == markers[node])
1224:           break;
1225:       if (bd == numBd) {
1226:         SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1227:       }
1228:     }
1229:     /* Check mesh connectivity */
1230:     for(node = 0; node < q->numLocNodes; node++) {
1231:       MeshGetNodeSupport(mesh, node, 0, &degree, &support);

1233:       /* Check that node only appears inside elements in the support */
1234:       for(elem = 0, 0; elem < p->numOverlapElements; elem++) {
1235:         for(corner = 0; corner < numCorners; corner++) {
1236:           newNode = elements[elem*numCorners+corner];
1237:           if (node == newNode) {
1238:             for(sElem = 0; sElem < degree; sElem++) {
1239:               if (support[sElem] == elem) break;
1240:             }
1241:             if (sElem == degree) {
1242:               PetscPrintf(PETSC_COMM_SELF, "[%d]Node %d found in element %d which is not present in the supportn",
1243:                           p->rank, node, elem);
1244:               1;
1245:             }
1246:           }
1247:         }
1248:       }
1249: 

1251:       MeshRestoreNodeSupport(mesh, node, 0, &degree, &support);
1252:     }
1253:   }
1254:   return(0);
1255: }

1257: static struct _MeshOps MeshOps = {/* Generic Operations */
1258:                                   PETSC_NULL/* MeshSetup */,
1259:                                   PETSC_NULL/* MeshSetFromOptions */,
1260:                                   MeshView_Triangular_1D,
1261:                                   PETSC_NULL/* MeshCopy */,
1262:                                   PETSC_NULL/* MeshDuplicate */,
1263:                                   MeshDestroy_Triangular_1D,
1264:                                   /* Mesh-Specific Operations */
1265:                                   MeshPartition_Triangular_1D,
1266:                                   MeshCoarsen_Triangular_1D,
1267:                                   MeshRefine_Triangular_1D,
1268:                                   MeshResetNodes_Triangular_1D,
1269:                                   MeshSaveMesh_Triangular_1D,
1270:                                   MeshRestoreMesh_Triangular_1D,
1271:                                   /* Mesh Query Functions */
1272:                                   MeshUpdateBoundingBox_Triangular_1D,
1273:                                   MeshIsDistorted_Triangular_1D,
1274:                                   /* Mesh Boundary Query Functions */
1275:                                   MeshGetBoundarySize_Triangular_1D,
1276:                                   MeshGetBoundaryIndex_Triangular_1D,
1277:                                   MeshGetBoundaryStart_Triangular_1D,
1278:                                   MeshGetBoundaryNext_Triangular_1D,
1279:                                   MeshGetActiveBoundary_Triangular_1D,
1280:                                   /* Mesh Node Query Functions */
1281:                                   MeshGetNodeBoundary_Triangular_1D,
1282:                                   MeshNodeIsVertex_Triangular_1D,
1283:                                   MeshGetNodeCoords_Triangular_1D,
1284:                                   MeshSetNodeCoords_Triangular_1D,
1285:                                   MeshGetNodeCoordsSaved_Triangular_1D,
1286:                                   MeshNearestNode_Triangular_1D,
1287:                                   MeshGetNodeSupport_Triangular_1D,
1288:                                   /* Mesh Element Query Functions */
1289:                                   MeshGetElemNeighbor_Triangular_1D,
1290:                                   MeshLocatePoint_Triangular_1D,
1291:                                   /* Mesh Embedding Query Functions */
1292:                                   MeshGetNodeFromElement_Triangular_1D,
1293:                                   MeshGetNodeFromEdge_Triangular_1D,
1294:                                   /* CSR Support Functions */
1295:                                   PETSC_NULL,
1296:                                   PETSC_NULL,
1297:                                   PETSC_NULL};

1299: #if 0
1300: EXTERN_C_BEGIN
1301: #undef  __FUNCT__
1303: int MeshSerialize_Triangular_1D(MPI_Comm comm, Mesh *mesh, PetscViewer viewer, PetscTruth store) {
1304:   Mesh             m;
1305:   Mesh_Triangular *tri;
1306:   int              fd;
1307:   int              zero = 0;
1308:   int              one  = 1;
1309:   int              numNodes, numEdges, numFaces, numCorners, numBd, numBdNodes, numBdEdges, old;
1310:   int              ierr;

1313:   PetscViewerBinaryGetDescriptor(viewer, &fd);
1314:   if (store) {
1315:     m    = *mesh;
1316:     PetscBinaryWrite(fd, &m->highlightElement, 1,                   PETSC_INT,    0);
1317:     PetscBinaryWrite(fd, &m->maxDegree,        1,                   PETSC_INT,    0);
1318:     PetscBinaryWrite(fd, &m->startX,           1,                   PETSC_DOUBLE, 0);
1319:     PetscBinaryWrite(fd, &m->endX,             1,                   PETSC_DOUBLE, 0);
1320:     PetscBinaryWrite(fd, &m->sizeX,            1,                   PETSC_DOUBLE, 0);
1321:     PetscBinaryWrite(fd, &m->startY,           1,                   PETSC_DOUBLE, 0);
1322:     PetscBinaryWrite(fd, &m->endY,             1,                   PETSC_DOUBLE, 0);
1323:     PetscBinaryWrite(fd, &m->sizeY,            1,                   PETSC_DOUBLE, 0);
1324:     PetscBinaryWrite(fd, &m->startZ,           1,                   PETSC_DOUBLE, 0);
1325:     PetscBinaryWrite(fd, &m->endZ,             1,                   PETSC_DOUBLE, 0);
1326:     PetscBinaryWrite(fd, &m->sizeZ,            1,                   PETSC_DOUBLE, 0);
1327:     PetscBinaryWrite(fd, &m->locStartX,        1,                   PETSC_DOUBLE, 0);
1328:     PetscBinaryWrite(fd, &m->locEndX,          1,                   PETSC_DOUBLE, 0);
1329:     PetscBinaryWrite(fd, &m->locSizeX,         1,                   PETSC_DOUBLE, 0);
1330:     PetscBinaryWrite(fd, &m->locStartY,        1,                   PETSC_DOUBLE, 0);
1331:     PetscBinaryWrite(fd, &m->locEndY,          1,                   PETSC_DOUBLE, 0);
1332:     PetscBinaryWrite(fd, &m->locSizeY,         1,                   PETSC_DOUBLE, 0);
1333:     PetscBinaryWrite(fd, &m->locStartZ,        1,                   PETSC_DOUBLE, 0);
1334:     PetscBinaryWrite(fd, &m->locEndZ,          1,                   PETSC_DOUBLE, 0);
1335:     PetscBinaryWrite(fd, &m->locSizeZ,         1,                   PETSC_DOUBLE, 0);
1336:     PetscBinaryWrite(fd, &m->isPeriodic,       1,                   PETSC_INT,    0);
1337:     PetscBinaryWrite(fd, &m->isPeriodicDim,    3,                   PETSC_INT,    0);

1339:     PetscBinaryWrite(fd, &m->numBd,            1,                   PETSC_INT,    0);
1340:     PetscBinaryWrite(fd, &m->numVertices,      1,                   PETSC_INT,    0);
1341:     PetscBinaryWrite(fd, &m->numNodes,         1,                   PETSC_INT,    0);
1342:     PetscBinaryWrite(fd, &m->numBdNodes,       1,                   PETSC_INT,    0);
1343:     PetscBinaryWrite(fd, &m->numEdges,         1,                   PETSC_INT,    0);
1344:     PetscBinaryWrite(fd, &m->numBdEdges,       1,                   PETSC_INT,    0);
1345:     PetscBinaryWrite(fd, &m->numFaces,         1,                   PETSC_INT,    0);
1346:     PetscBinaryWrite(fd, &m->numBdFaces,       1,                   PETSC_INT,    0);
1347:     PetscBinaryWrite(fd, &m->numCells,         1,                   PETSC_INT,    0);
1348:     PetscBinaryWrite(fd, &m->numCorners,       1,                   PETSC_INT,    0);
1349:     PetscBinaryWrite(fd, &m->numCellCorners,   1,                   PETSC_INT,    0);
1350:     PetscBinaryWrite(fd, &m->numHoles,         1,                   PETSC_INT,    0);

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

1354:     PartitionGetNumOverlapElements(m->part, &numFaces);
1355:     PartitionGetNumOverlapNodes(m->part, &numNodes);
1356:     numEdges   = m->numEdges;
1357:     numCorners = m->numCorners;
1358:     numBd      = m->numBd;
1359:     numBdNodes = m->numBdNodes;
1360:     numBdEdges = m->numBdEdges;

1362:     tri  = (Mesh_Triangular *) (*mesh)->data;
1363:     PetscBinaryWrite(fd,  tri->nodes,          numNodes*2,          PETSC_DOUBLE, 0);
1364:     if (tri->nodesOld == PETSC_NULL) {
1365:       PetscBinaryWrite(fd, &zero,              1,                   PETSC_INT,    0);
1366:     } else {
1367:       PetscBinaryWrite(fd, &one,               1,                   PETSC_INT,    0);
1368:       PetscBinaryWrite(fd,  tri->nodesOld,     numNodes*2,          PETSC_DOUBLE, 0);
1369:     }
1370:     PetscBinaryWrite(fd,  tri->markers,        numNodes,            PETSC_INT,    0);
1371:     PetscBinaryWrite(fd,  tri->degrees,        numNodes,            PETSC_INT,    0);
1372:     PetscBinaryWrite(fd,  tri->edges,          numEdges*2,          PETSC_INT,    0);
1373:     PetscBinaryWrite(fd,  tri->edgemarkers,    numEdges,            PETSC_INT,    0);
1374:     PetscBinaryWrite(fd,  tri->faces,          numFaces*numCorners, PETSC_INT,    0);
1375:     PetscBinaryWrite(fd,  tri->neighbors,      numFaces*3,          PETSC_INT,    0);
1376:     PetscBinaryWrite(fd,  tri->bdNodes,        numBdNodes,          PETSC_INT,    0);
1377:     PetscBinaryWrite(fd,  tri->bdEdges,        numBdEdges,          PETSC_INT,    0);
1378:     PetscBinaryWrite(fd,  tri->bdMarkers,      numBd,               PETSC_INT,    0);
1379:     PetscBinaryWrite(fd,  tri->bdBegin,        numBd+1,             PETSC_INT,    0);
1380:     PetscBinaryWrite(fd,  tri->bdEdgeBegin,    numBd+1,             PETSC_INT,    0);
1381:     PetscBinaryWrite(fd,  m->holes,            m->numHoles*2,       PETSC_DOUBLE, 0);

1383:     PetscBinaryWrite(fd, &m->maxAspectRatio,   1,                   PETSC_DOUBLE, 0);
1384:   } else {
1385:     /* Create the mesh context */
1386:     MeshCreate(comm, &m);
1387:     PetscNew(Mesh_Triangular, &tri);
1388:     PetscLogObjectMemory(m, sizeof(Mesh_Triangular));
1389:     PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1390:     PetscStrallocpy(MESH_TRIANGULAR_2D, &m->type_name);
1391:     m->data = (void *) tri;
1392:     m->dim  = 2;

1394:     PetscBinaryRead(fd, &m->highlightElement, 1, PETSC_INT);
1395:     PetscBinaryRead(fd, &m->maxDegree,        1, PETSC_INT);
1396:     PetscMalloc(m->maxDegree * sizeof(int), &m->support);

1398:     PetscBinaryRead(fd, &m->startX,           1, PETSC_DOUBLE);
1399:     PetscBinaryRead(fd, &m->endX,             1, PETSC_DOUBLE);
1400:     PetscBinaryRead(fd, &m->sizeX,            1, PETSC_DOUBLE);
1401:     PetscBinaryRead(fd, &m->startY,           1, PETSC_DOUBLE);
1402:     PetscBinaryRead(fd, &m->endY,             1, PETSC_DOUBLE);
1403:     PetscBinaryRead(fd, &m->sizeY,            1, PETSC_DOUBLE);
1404:     PetscBinaryRead(fd, &m->startZ,           1, PETSC_DOUBLE);
1405:     PetscBinaryRead(fd, &m->endZ,             1, PETSC_DOUBLE);
1406:     PetscBinaryRead(fd, &m->sizeZ,            1, PETSC_DOUBLE);
1407:     PetscBinaryRead(fd, &m->locStartX,        1, PETSC_DOUBLE);
1408:     PetscBinaryRead(fd, &m->locEndX,          1, PETSC_DOUBLE);
1409:     PetscBinaryRead(fd, &m->locSizeX,         1, PETSC_DOUBLE);
1410:     PetscBinaryRead(fd, &m->locStartY,        1, PETSC_DOUBLE);
1411:     PetscBinaryRead(fd, &m->locEndY,          1, PETSC_DOUBLE);
1412:     PetscBinaryRead(fd, &m->locSizeY,         1, PETSC_DOUBLE);
1413:     PetscBinaryRead(fd, &m->locStartZ,        1, PETSC_DOUBLE);
1414:     PetscBinaryRead(fd, &m->locEndZ,          1, PETSC_DOUBLE);
1415:     PetscBinaryRead(fd, &m->locSizeZ,         1, PETSC_DOUBLE);
1416:     PetscBinaryRead(fd, &m->isPeriodic,       1, PETSC_INT);
1417:     PetscBinaryRead(fd, &m->isPeriodicDim,    3, PETSC_INT);

1419:     m->activeBd       = -1;
1420:     m->activeBdOld    = -1;
1421:     m->activeBdNode   = -1;
1422:     tri->areas        = PETSC_NULL;
1423:     tri->aspectRatios = PETSC_NULL;

1425:     PetscBinaryRead(fd, &m->numBd,            1,                   PETSC_INT);
1426:     PetscBinaryRead(fd, &m->numVertices,      1,                   PETSC_INT);
1427:     PetscBinaryRead(fd, &m->numNodes,         1,                   PETSC_INT);
1428:     PetscBinaryRead(fd, &m->numBdNodes,       1,                   PETSC_INT);
1429:     PetscBinaryRead(fd, &m->numEdges,         1,                   PETSC_INT);
1430:     PetscBinaryRead(fd, &m->numBdEdges,       1,                   PETSC_INT);
1431:     PetscBinaryRead(fd, &m->numFaces,         1,                   PETSC_INT);
1432:     PetscBinaryRead(fd, &m->numBdFaces,       1,                   PETSC_INT);
1433:     PetscBinaryRead(fd, &m->numCells,         1,                   PETSC_INT);
1434:     PetscBinaryRead(fd, &m->numCorners,       1,                   PETSC_INT);
1435:     PetscBinaryRead(fd, &m->numCellCorners,   1,                   PETSC_INT);
1436:     PetscBinaryRead(fd, &m->numHoles,         1,                   PETSC_INT);

1438:     PartitionSerialize(m, &m->part, viewer, store);
1439:     PetscLogObjectParent(m, m->part);

1441:     PartitionGetNumOverlapElements(m->part, &numFaces);
1442:     PartitionGetNumOverlapNodes(m->part, &numNodes);
1443:     numEdges   = m->numEdges;
1444:     numCorners = m->numCorners;
1445:     numBd      = m->numBd;
1446:     numBdNodes = m->numBdNodes;
1447:     numBdEdges = m->numBdEdges;
1448:     PetscMalloc(numNodes*2          * sizeof(double), &tri->nodes);
1449:     PetscMalloc(numNodes            * sizeof(int),    &tri->markers);
1450:     PetscMalloc(numNodes            * sizeof(int),    &tri->degrees);
1451:     PetscMalloc(numEdges*2          * sizeof(int),    &tri->edges);
1452:     PetscMalloc(numEdges            * sizeof(int),    &tri->edgemarkers);
1453:     PetscMalloc(numFaces*numCorners * sizeof(int),    &tri->faces);
1454:     PetscMalloc(numFaces*3          * sizeof(int),    &tri->neighbors);
1455:     PetscMalloc(numBdNodes          * sizeof(int),    &tri->bdNodes);
1456:     PetscMalloc(numBdEdges          * sizeof(int),    &tri->bdEdges);
1457:     PetscMalloc(numBd               * sizeof(int),    &tri->bdMarkers);
1458:     PetscMalloc((numBd+1)           * sizeof(int),    &tri->bdBegin);
1459:     PetscMalloc((numBd+1)           * sizeof(int),    &tri->bdEdgeBegin);
1460:     if (m->numHoles > 0) {
1461:       PetscMalloc(m->numHoles*2     * sizeof(double), &m->holes);
1462:     } else {
1463:       m->holes = PETSC_NULL;
1464:     }
1465:     PetscLogObjectMemory(m, (numNodes*2 + m->numHoles*2) * sizeof(double) +
1466:                          (numNodes*2 + numEdges*3 + numFaces*(numCorners+1) + numBdNodes + numBdEdges + numBd*3+2)*sizeof(int));
1467:     PetscBinaryRead(fd,  tri->nodes,          numNodes*2,          PETSC_DOUBLE);
1468:     PetscBinaryRead(fd, &old,                 1,                   PETSC_INT);
1469:     if (old) {
1470:       PetscMalloc(numNodes*2 * sizeof(double), &tri->nodesOld);
1471:       PetscLogObjectMemory(m, numNodes*2 * sizeof(double));
1472:       PetscBinaryRead(fd,  tri->nodesOld,     numNodes*2,          PETSC_DOUBLE);
1473:     } else {
1474:       tri->nodesOld = PETSC_NULL;
1475:     }
1476:     PetscBinaryRead(fd,  tri->markers,        numNodes,            PETSC_INT);
1477:     PetscBinaryRead(fd,  tri->degrees,        numNodes,            PETSC_INT);
1478:     PetscBinaryRead(fd,  tri->edges,          numEdges*2,          PETSC_INT);
1479:     PetscBinaryRead(fd,  tri->edgemarkers,    numEdges,            PETSC_INT);
1480:     PetscBinaryRead(fd,  tri->faces,          numFaces*numCorners, PETSC_INT);
1481:     PetscBinaryRead(fd,  tri->neighbors,      numFaces*3,          PETSC_INT);
1482:     PetscBinaryRead(fd,  tri->bdNodes,        numBdNodes,          PETSC_INT);
1483:     PetscBinaryRead(fd,  tri->bdEdges,        numBdEdges,          PETSC_INT);
1484:     PetscBinaryRead(fd,  tri->bdMarkers,      numBd,               PETSC_INT);
1485:     PetscBinaryRead(fd,  tri->bdBegin,        numBd+1,             PETSC_INT);
1486:     PetscBinaryRead(fd,  tri->bdEdgeBegin,    numBd+1,             PETSC_INT);
1487:     PetscBinaryRead(fd,  m->holes,            m->numHoles*m->dim,  PETSC_DOUBLE);

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

1491: #ifdef PETSC_USE_BOPT_g
1492:     /* Check mesh integrity */
1493:     MeshDebug_Triangular_1D(m, PETSC_TRUE);
1494: #endif
1495:     *mesh = m;
1496:   }

1498:   return(0);
1499: }
1500: EXTERN_C_END
1501: #endif

1503: EXTERN_C_BEGIN
1504: #undef  __FUNCT__
1506: int MeshCreate_Triangular_1D(Mesh mesh) {
1507:   Mesh_Triangular *tri;
1508:   int            (*f)(MeshBoundary2D *, int, Mesh);
1509:   int              ierr;

1512:   PetscNew(Mesh_Triangular, &tri);
1513:   PetscMemzero(tri, sizeof(Mesh_Triangular));
1514:   PetscMemcpy(mesh->ops, &MeshOps, sizeof(struct _MeshOps));
1515:   mesh->data = (void *) tri;
1516:   PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &mesh->serialize_name);
1517:   mesh->dim = 1;

1519:   /* Setup the periodic domain */
1520:   if (mesh->isPeriodic == PETSC_TRUE) {
1521:     MeshBoundary2DSetBoundingBox(mesh, mesh->bdCtx);
1522:   }

1524:   /* Setup default mechanisms */
1525:   PetscObjectQueryFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", (PetscVoidFunction) &f);
1526:   if (f == PETSC_NULL) {
1527:     if (mesh->isPeriodic == PETSC_TRUE) {
1528:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Periodic",
1529:                                         (void (*)(void)) MeshTriangular1D_Create_Periodic);
1530: 
1531:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Periodic",
1532:                                         (void (*)(void)) MeshTriangular1D_Refine_Periodic);
1533: 
1534:     } else {
1535:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Triangle",
1536:                                         (void (*)(void)) MeshTriangular1D_Create_Simple);
1537: 
1538:       PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Triangle",
1539:                                         (void (*)(void)) MeshTriangular1D_Refine_Simple);
1540:     }
1541:   }

1543:   MeshCheckBoundary_Triangular_1D(mesh);

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

1548:   /* Calculate maximum degree of vertices */
1549:   MeshSetupSupport_Triangular_1D(mesh);

1551:   /* Construct derived and boundary information */
1552:   MeshSetupBoundary_Triangular_1D(mesh);

1554: #if 0
1555:   /* Reorder nodes before distributing mesh */
1556:   PetscOptionsHasName(mesh->prefix, "-mesh_reorder", &opt);
1557:   if (opt == PETSC_TRUE) {
1558:     /* MUST FIX: Since we have duplicated the whole mesh, we may impersonate a serial mesh */
1559:     comm       = mesh->comm;
1560:     mesh->comm = PETSC_COMM_SELF;
1561:     MeshGetOrdering(mesh, MESH_ORDER_TRIANGULAR_1D_RCM, &mesh->nodeOrdering);
1562:     mesh->comm = comm;

1564:     /* Permute arrays implicitly numbered by node numbers */
1565:     AOApplicationToPetscPermuteReal(mesh->nodeOrdering, mesh->dim, tri->nodes);
1566:     AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->markers);
1567:     AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->degrees);
1568:     /* Renumber arrays dependent on the canonical node numbering */
1569:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numEdges*2,                tri->edges);
1570:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numFaces*mesh->numCorners, tri->faces);
1571:     AOApplicationToPetsc(mesh->nodeOrdering, mesh->numBdNodes,                tri->bdNodes);
1572:   }
1573: #endif

1575:   /* Initialize partition */
1576:   MeshPartition(mesh);

1578:   /* Initialize save space */
1579:   tri->nodesOld = PETSC_NULL;

1581:   /* Reset the midnodes */
1582:   if (mesh->isPeriodic == PETSC_TRUE) {
1583:     MeshResetNodes(mesh, PETSC_TRUE);
1584:   }

1586:   return(0);
1587: }
1588: EXTERN_C_END

1590: #undef  __FUNCT__
1592: int MeshRefine_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
1593:   Mesh             m;
1594:   Mesh_Triangular *tri;
1595:   int            (*f)(Mesh, PointFunction, Mesh);
1596:   int              ierr;

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

1601:   PetscNew(Mesh_Triangular, &tri);
1602:   PetscMemzero(tri, sizeof(Mesh_Triangular));
1603:   PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1604:   m->data = (void *) tri;
1605:   PetscStrallocpy(MESH_TRIANGULAR_1D, &m->type_name);
1606:   PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &m->serialize_name);
1607:   m->dim   = 1;
1608:   m->numBd = mesh->numBd;

1610:   /* Setup the periodic domain */
1611:   m->bdCtx = mesh->bdCtx;
1612:   if (m->isPeriodic == PETSC_TRUE) {
1613:     MeshBoundary2DSetBoundingBox(m, m->bdCtx);
1614:   }

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

1619:   /* Refine mesh */
1620:   PetscObjectQueryFunction((PetscObject) m, "MeshTriangular1D_Refine_C", (PetscVoidFunction) &f);
1621:   (*f)(mesh, area, m);

1623:   /* Calculate maximum degree of vertices */
1624:   MeshSetupSupport_Triangular_1D(m);

1626:   /* Construct derived and boundary information */
1627:   MeshSetupBoundary_Triangular_1D(m);

1629:   /* Initialize partition */
1630:   MeshPartition(m);

1632:   /* Initialize save space */
1633:   tri->nodesOld = PETSC_NULL;

1635:   /* Reset the midnodes */
1636:   if (m->isPeriodic == PETSC_TRUE) {
1637:     MeshResetNodes(m, PETSC_TRUE);
1638:   }
1639:   *newmesh = m;
1640:   return(0);
1641: }