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, °ree, &support);
1141: /* Check node degree */
1142: PetscMalloc(numProcs * sizeof(int), °rees);
1143: MPI_Allgather(°ree, 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, °ree, &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, °ree, &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, °ree, &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: }