Actual source code: tri1d.c
1: #ifdef PETSC_RCS_HEADER
2: static char vcid[] = "$Id: tri1d.c,v 1.38 2000/10/17 13:48:55 knepley Exp $";
3: #endif
5: /* Implements 1d unstructured grids */
6: #include "src/mesh/impls/triangular/1d/1dimpl.h" /*I "mesh.h" I*/
7: #include "tri1d.h"
8: #include "tri1d_Simple.h"
10: extern int PartitionGhostNodeIndex_Private(Partition, int, int *);
12: /*--------------------------------------------- Generic Operations ---------------------------------------------------*/
13: static int MeshDestroy_Triangular_1D(Mesh mesh) {
14: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
15: int ierr;
18: if (tri->nodes != PETSC_NULL) {
19: PetscFree(tri->nodes);
20: PetscFree(tri->markers);
21: PetscFree(tri->degrees);
22: }
23: if (tri->nodesOld != PETSC_NULL) {
24: PetscFree(tri->nodesOld);
25: }
26: if (tri->edges != PETSC_NULL) {
27: PetscFree(tri->edges);
28: }
29: if (tri->faces != PETSC_NULL) {
30: PetscFree(tri->faces);
31: }
32: if (tri->neighbors != PETSC_NULL) {
33: PetscFree(tri->neighbors);
34: }
35: if (tri->bdNodes != PETSC_NULL) {
36: PetscFree(tri->bdNodes);
37: PetscFree(tri->bdMarkers);
38: PetscFree(tri->bdBegin);
39: }
40: #if 0
41: if (tri->bdCtx != PETSC_NULL) {
42: MeshBoundaryDestroy(tri->bdCtx);
43: }
44: if (tri->bdCtxNew != PETSC_NULL) {
45: MeshBoundaryDestroy(tri->bdCtxNew);
46: }
47: #endif
48: if (tri->areas != PETSC_NULL) {
49: PetscFree(tri->areas);
50: }
51: PetscFree(tri);
52: if (mesh->support != PETSC_NULL) {
53: PetscFree(mesh->support);
54: }
55: PartitionDestroy(mesh->part);
56: if (mesh->nodeOrdering != PETSC_NULL) {
57: AODestroy(mesh->nodeOrdering);
58: }
59: if (mesh->coarseMap != PETSC_NULL) {
60: AODestroy(mesh->coarseMap);
61: }
63: return(0);
64: }
66: /*------------------------------------------ Mesh-Specific Operations ------------------------------------------------*/
67: static int MeshPartition_Triangular_1D(Mesh mesh) {
71: PartitionCreate(mesh, &mesh->part);
72: PartitionSetType(mesh->part, PARTITION_TRIANGULAR_1D);
73: mesh->partitioned = 1;
74: PetscFunctionReturn(ierr);
75: }
77: static int MeshCoarsen_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
78: SETERRQ(PETSC_ERR_SUP, " ");
79: }
81: static int MeshResetNodes_Triangular_1D(Mesh mesh, PetscTruth resetBd) {
82: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
83: int *elements = tri->edges;
84: double *nodes = tri->nodes;
85: int numCorners = mesh->numCorners;
86: int elem, node1, node2, midNode;
89: if (numCorners == 2) return(0);
91: for(elem = 0; elem < mesh->part->numOverlapElements; elem++) {
92: node1 = elements[elem*numCorners+0];
93: node2 = elements[elem*numCorners+1];
94: midNode = elements[elem*numCorners+2];
95: nodes[midNode*2] = MeshPeriodicX(mesh, 0.5*(nodes[node1*2] +
96: MeshPeriodicRelativeX(mesh, nodes[node2*2], nodes[node1*2])));
97: nodes[midNode*2+1] = MeshPeriodicY(mesh, 0.5*(nodes[node1*2+1] +
98: MeshPeriodicRelativeY(mesh, nodes[node2*2+1], nodes[node1*2+1])));
99: }
100: return(0);
101: }
103: static int MeshSaveMesh_Triangular_1D(Mesh mesh) {
104: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
105: int dim = mesh->dim;
106: int numOverlapNodes;
107: int ierr;
110: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
111: if (tri->nodesOld == PETSC_NULL) {
112: PetscMalloc(numOverlapNodes*dim * sizeof(double), &tri->nodesOld);
113: PetscLogObjectMemory(mesh, numOverlapNodes*dim * sizeof(double));
114: }
115: PetscMemcpy(tri->nodesOld, tri->nodes, numOverlapNodes*dim * sizeof(double));
116: return(0);
117: }
119: static int MeshRestoreMesh_Triangular_1D(Mesh mesh) {
120: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
121: int dim = mesh->dim;
122: int numOverlapNodes;
123: int ierr;
126: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
127: if (tri->nodesOld != PETSC_NULL) {
128: PetscMemcpy(tri->nodes, tri->nodesOld, numOverlapNodes*dim * sizeof(double));
129: }
130: return(0);
131: }
133: /*-------------------------------------------- Mesh Query Functions --------------------------------------------------*/
134: static int MeshUpdateBoundingBox_Triangular_1D(Mesh mesh) {
135: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
136: double *nodes = tri->nodes;
137: Partition part;
138: int numOverlapNodes;
139: int node;
140: int ierr;
142: /* Calculate the local bounding box */
144: MeshGetPartition(mesh, &part);
145: PartitionGetNumOverlapNodes(part, &numOverlapNodes);
146: if (numOverlapNodes > 0) {
147: mesh->locStartX = mesh->locEndX = nodes[0];
148: } else {
149: mesh->locStartX = mesh->locEndX = 0.0;
150: }
151: for(node = 0; node < numOverlapNodes; node++) {
152: if (nodes[node] < mesh->locStartX) mesh->locStartX = nodes[node];
153: if (nodes[node] > mesh->locEndX) mesh->locEndX = nodes[node];
154: }
155: mesh->locSizeX = mesh->locEndX - mesh->locStartX;
156: return(0);
157: }
159: static int MeshIsDistorted_Triangular_1D(Mesh mesh, PetscTruth *flag) {
160: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
161: double *nodes = tri->nodes;
162: int *elements = tri->edges;
163: int numCorners = mesh->numCorners;
164: int numElements = mesh->numEdges;
165: double maxAspectRatio = mesh->maxAspectRatio;
166: double area; /* Twice the area of the triangle */
167: double min;
168: PetscTruth locFlag;
169: int elem;
170: int locRetVal;
171: int retVal;
172: int ierr;
175: for(elem = 0, locFlag = PETSC_FALSE, locRetVal = 0, min = mesh->sizeX; elem < numElements; elem++) {
176: /* Find the area */
177: area = MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+1]*2] - nodes[elements[elem*numCorners]*2]);
178: /* Check for inverted elements */
179: if (area < 0.0) {
180: locFlag = PETSC_TRUE;
181: locRetVal = 1;
182: break;
183: } else if (area == 0.0) {
184: SETERRQ1(PETSC_ERR_ARG_CORRUPT, "Element %d has no area", elem);
185: }
187: /* We cannot bail here since we must check for inverted elements */
188: min = PetscMin(min, area);
189: }
190: if (min < 1.0/maxAspectRatio) {
191: PetscLogInfo(mesh, "Area too small in element %d: %g < %gn", elem, min, 1.0/maxAspectRatio);
192: locFlag = PETSC_TRUE;
193: } else {
194: PetscLogInfo(mesh, "Area in element %d: %gn", elem, min);
195: }
196: PetscLogFlops(elem);
197: MPI_Allreduce(&locFlag, flag, 1, MPI_INT, MPI_LOR, mesh->comm);
198: MPI_Allreduce(&locRetVal, &retVal, 1, MPI_INT, MPI_LOR, mesh->comm);
199: PetscFunctionReturn(retVal);
200: }
202: /*---------------------------------------- Mesh Boundary Query Functions ---------------------------------------------*/
203: static int MeshGetBoundarySize_Triangular_1D(Mesh mesh, int boundary, int *size) {
204: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
205: int b; /* Canonical boundary number */
208: /* Find canonical boundary number */
209: for(b = 0; b < mesh->numBd; b++) {
210: if (tri->bdMarkers[b] == boundary) break;
211: }
212: if (b == mesh->numBd) SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid boundary specified");
213: *size = tri->bdBegin[b+1] - tri->bdBegin[b];
214: if ((*size != 0) && (*size != 1)) SETERRQ1(PETSC_ERR_PLIB, "Invalid boundary size %d", *size);
215: return(0);
216: }
218: static int MeshGetBoundaryIndex_Triangular_1D(Mesh mesh, int boundary, int *index) {
219: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
220: int b; /* Canonical boundary number */
223: /* Find canonical boundary number */
224: for(b = 0; b < mesh->numBd; b++) {
225: if (tri->bdMarkers[b] == boundary) break;
226: }
227: if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary marker %d", boundary);
228: *index = b;
229: return(0);
230: }
232: static int MeshGetBoundaryStart_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
233: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
234: int b; /* Canonical boundary number */
235: int ierr;
238: /* Find canonical boundary number */
239: for(b = 0; b < mesh->numBd; b++) {
240: if (tri->bdMarkers[b] == boundary) break;
241: }
242: if (b == mesh->numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary %d specified", boundary);
243: if (mesh->activeBd != -1) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE, "Already iterating over boundary %d", mesh->activeBd);
244: /* Find first boundary node */
245: mesh->activeBd = b;
246: mesh->activeBdOld = b;
247: mesh->activeBdNode = tri->bdBegin[b] - 1;
248: MeshGetBoundaryNext(mesh, boundary, ghost, node);
249: PetscFunctionReturn(ierr);
250: }
252: static int MeshGetBoundaryNext_Triangular_1D(Mesh mesh, int boundary, PetscTruth ghost, int *node) {
253: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
254: Partition p = mesh->part;
255: Partition_Triangular_1D *q = (Partition_Triangular_1D *) p->data;
256: int numBd = mesh->numBd;
257: int numNodes = mesh->numNodes;
258: int b; /* Canonical boundary number */
259: int tempNode; /* Canonical local node number */
260: int ierr;
263: /* Find canonical boundary number */
264: for(b = 0; b < numBd; b++) {
265: if (tri->bdMarkers[b] == boundary) break;
266: }
267: if (b == numBd) SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid boundary %d specified", boundary);
268: /* Find next boundary node */
269: if (mesh->activeBd != b) SETERRQ1(PETSC_ERR_ARG_WRONG, "Boundary %d not active", boundary);
270: do {
271: mesh->activeBdNode++;
272: if (mesh->activeBdNode == tri->bdBegin[b+1]) {
273: mesh->activeBd = mesh->activeBdNode = -1;
274: *node = -1;
275: return(0);
276: }
277: tempNode = tri->bdNodes[mesh->activeBdNode] - q->firstNode[p->rank];
278: /* Translate ghost nodes */
279: if (ghost == PETSC_TRUE) {
280: if ((tempNode < 0) || (tempNode >= numNodes)) {
281: PartitionGhostNodeIndex_Private(p, tri->bdNodes[mesh->activeBdNode], &tempNode);
282: if (ierr == 0) {
283: tempNode += numNodes;
284: break;
285: }
286: }
287: }
288: }
289: while((tempNode < 0) || (tempNode >= numNodes));
290: *node = tempNode;
291: return(0);
292: }
294: static int MeshGetActiveBoundary_Triangular_1D(Mesh mesh, int *boundary) {
295: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
298: if (mesh->activeBdOld >= 0) {
299: *boundary = tri->bdMarkers[mesh->activeBdOld];
300: } else {
301: *boundary = 0;
302: }
303: return(0);
304: }
306: /*------------------------------------------ Mesh Node Query Functions -----------------------------------------------*/
307: static int MeshGetNodeBoundary_Triangular_1D(Mesh mesh, int node, int *bd) {
308: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
309: #ifdef PETSC_USE_BOPT_g
310: int numOverlapNodes;
311: int ierr;
312: #endif
315: #ifdef PETSC_USE_BOPT_g
316: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
317: if ((node < 0) || (node >= numOverlapNodes)) {
318: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
319: }
320: #endif
321: *bd = tri->markers[node];
322: return(0);
323: }
325: static int MeshNodeIsVertex_Triangular_1D(Mesh mesh, int node, PetscTruth *isVertex) {
326: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
327: #ifdef PETSC_USE_BOPT_g
328: int numOverlapNodes;
329: int ierr;
330: #endif
333: #ifdef PETSC_USE_BOPT_g
334: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
335: if ((node < 0) || (node >= numOverlapNodes)) {
336: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", node, numOverlapNodes);
337: }
338: #endif
339: if (tri->degrees[node] == 0) {
340: *isVertex = PETSC_FALSE;
341: } else {
342: *isVertex = PETSC_TRUE;
343: }
344: return(0);
345: }
347: static int MeshGetNodeCoords_Triangular_1D(Mesh mesh, int node, double *x, double *y, double *z) {
348: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
349: #ifdef PETSC_USE_BOPT_g
350: int numOverlapNodes;
351: int ierr;
352: #endif
355: #ifdef PETSC_USE_BOPT_g
356: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
357: if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
358: #endif
359: if (x != PETSC_NULL) *x = tri->nodes[node];
360: return(0);
361: }
363: static int MeshSetNodeCoords_Triangular_1D(Mesh mesh, int node, double x, double y, double z) {
364: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
365: #ifdef PETSC_USE_BOPT_g
366: int numOverlapNodes;
367: int ierr;
368: #endif
371: #ifdef PETSC_USE_BOPT_g
372: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
373: if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
374: #endif
375: tri->nodes[node] = MeshPeriodicX(mesh, x);
376: return(0);
377: }
379: static int MeshGetNodeCoordsSaved_Triangular_1D(Mesh mesh, int node, double *x, double *y, double *z) {
380: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
381: #ifdef PETSC_USE_BOPT_g
382: int numOverlapNodes;
383: int ierr;
384: #endif
387: #ifdef PETSC_USE_BOPT_g
388: ierr = PartitionGetNumOverlapNodes(mesh->part, &numOverlapNodes);
389: if ((node < 0) || (node >= numOverlapNodes)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node specified");
390: #endif
391: if (tri->nodesOld != PETSC_NULL) {
392: if (x != PETSC_NULL) *x = tri->nodesOld[node];
393: } else {
394: if (x != PETSC_NULL) *x = tri->nodes[node];
395: }
396: return(0);
397: }
399: static int MeshNearestNode_Triangular_1D(Mesh mesh, double x, double y, double z, PetscTruth outsideDomain, int *node) {
400: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
401: Partition p = mesh->part;
402: Partition_Triangular_1D *q = (Partition_Triangular_1D *) p->data;
403: int numCorners = mesh->numCorners;
404: int *elements = tri->edges;
405: int numNodes = mesh->numNodes;
406: double *nodes = tri->nodes;
407: int *firstNode = q->firstNode;
408: int rank = p->rank;
409: int elem;
410: double minDist, dist, allMinDist;
411: int minNode, globalMinNode, allMinNode;
412: int corner, n;
413: int ierr;
416: if (outsideDomain == PETSC_FALSE) {
417: MeshLocatePoint(mesh, x, y, z, &elem);
418: if (elem >= 0) {
419: minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners]] - x));
420: minNode = elements[elem*numCorners];
421: for(corner = 1; corner < numCorners; corner++) {
422: dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[elements[elem*numCorners+corner]] - x));
423: if (dist < minDist) {
424: minDist = dist;
425: minNode = elements[elem*numCorners+corner];
426: }
427: }
428: PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
429: } else {
430: minNode = -1;
431: globalMinNode = -1;
432: }
433: } else {
434: /* Brute force check */
435: minNode = 0;
436: minDist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[0] - x));
437: for(n = 1; n < numNodes; n++) {
438: dist = PetscSqr(MeshPeriodicDiffX(mesh, nodes[n] - x));
439: if (dist < minDist) {
440: minDist = dist;
441: minNode = n;
442: }
443: }
445: /* Find the minimum distance */
446: MPI_Allreduce(&minDist, &allMinDist, 1, MPI_DOUBLE, MPI_MIN, p->comm);
447: if (minDist == allMinDist) {
448: PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
449: } else {
450: globalMinNode = -1;
451: }
452: }
454: /* We might still have ties, i.e. the minimum node is a ghost node */
455: MPI_Allreduce(&globalMinNode, &allMinNode, 1, MPI_INT, MPI_MAX, p->comm);
456: if ((allMinNode >= firstNode[rank]) && (allMinNode < firstNode[rank+1])) {
457: *node = allMinNode - firstNode[rank];
458: } else {
459: *node = -1;
460: }
461: if (allMinNode < 0) PetscFunctionReturn(1);
463: return(0);
464: }
466: static int MeshGetNodeSupport_Triangular_1D(Mesh mesh, int node, int startElem, int *degree, int **support) {
467: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
468: int numOverlapElements = mesh->numEdges;
469: int numCorners = mesh->numCorners;
470: int *elements = tri->edges;
471: int *neighbors = tri->neighbors;
472: int deg = -1;
473: int firstElem;
474: int elem, neighbor, corner;
477: /* First check suggested element */
478: firstElem = -1;
479: for(corner = 0; corner < numCorners; corner++) {
480: if (elements[startElem*numCorners+corner] == node) {
481: firstElem = startElem;
482: if (corner >= 2) {
483: deg = 1;
484: } else {
485: deg = 0;
486: }
487: break;
488: }
489: }
491: /* Locate an element containing the node */
492: if (mesh->part != PETSC_NULL) {
493: numOverlapElements = mesh->part->numOverlapElements;
494: }
495: for(elem = 0; (elem < numOverlapElements) && (firstElem < 0); elem++) {
496: for(corner = 0; corner < numCorners; corner++) {
497: if (elements[elem*numCorners+corner] == node) {
498: firstElem = elem;
499: if (corner >= 2) {
500: deg = 1;
501: } else {
502: deg = 0;
503: }
504: break;
505: }
506: }
507: }
508: if (firstElem < 0) {
509: SETERRQ1(PETSC_ERR_ARG_WRONG, "Node %d not found in mesh", node);
510: }
512: /* Check for midnode */
513: if (deg != 0) {
514: mesh->support[0] = firstElem;
515: mesh->support[1] = -1;
516: *support = mesh->support;
517: *degree = deg;
518: return(0);
519: }
521: /* Add element to the list */
522: mesh->support[deg++] = firstElem;
523: /* Look for a neighbor containing the node */
524: for(neighbor = 0; neighbor < 2; neighbor++) {
525: elem = neighbors[firstElem*2+neighbor];
526: if (elem < 0) continue;
528: for(corner = 0; corner < 2; corner++) {
529: if (elements[elem*numCorners+corner] == node) {
530: mesh->support[deg++] = elem;
531: break;
532: }
533: }
534: }
536: if (deg > 2) {
537: SETERRQ1(PETSC_ERR_PLIB, "Node %d has invalid support", node);
538: } else if (deg < 2) {
539: /* Make sure that this is a boundary node */
540: if (tri->markers[node] == 0) SETERRQ1(PETSC_ERR_PLIB, "Interior node %d with incomplete support", node);
541: }
543: #ifdef PETSC_USE_BOPT_g
544: /* Check for overflow */
545: if (deg > mesh->maxDegree) SETERRQ1(PETSC_ERR_MEM, "Maximum degree %d exceeded", mesh->maxDegree);
546: #endif
548: *support = mesh->support;
549: *degree = deg;
550: return(0);
551: }
553: /*----------------------------------------- Mesh Element Query Functions ---------------------------------------------*/
554: static int MeshGetElemNeighbor_Triangular_1D(Mesh mesh, int elem, int corner, int *neighbor) {
555: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
556: #ifdef PETSC_USE_BOPT_g
557: int numOverlapElements;
558: int ierr;
559: #endif
562: #ifdef PETSC_USE_BOPT_g
563: PartitionGetNumOverlapElements(mesh->part, &numOverlapElements);
564: if ((elem < 0) || (elem >= numOverlapElements)) {
565: SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid element %d should be in [0,%d)", elem, numOverlapElements);
566: }
567: if ((corner < 0) || (corner >= mesh->numCorners)) {
568: SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid corner %d should be in [0,%d)", corner, mesh->numCorners);
569: }
570: #endif
571: *neighbor = tri->neighbors[elem*2+corner];
572: return(0);
573: }
575: #if 0
576: static int MeshLocatePoint_Triangular_1D_Directed(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
577: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
580: /* We should use bisection here */
581: return(0);
582: }
583: #endif
585: static int MeshLocatePoint_Triangular_1D(Mesh mesh, double xx, double yy, double zz, int *containingElem) {
586: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
587: int numCorners = mesh->numCorners;
588: int numElements = mesh->numEdges;
589: double *nodes = tri->nodes;
590: int *elements = tri->edges;
591: double x = xx;
592: double coords[2];
593: int elem;
596: *containingElem = -1;
597: /* Quick bounding rectangle check */
598: if ((mesh->isPeriodic == PETSC_FALSE) && ((mesh->locStartX > x) || (mesh->locEndX < x))) return(0);
599: /* Simple search */
600: for(elem = 0; elem < numElements; elem++) {
601: coords[0] = nodes[elements[elem*numCorners]];
602: coords[1] = MeshPeriodicRelativeX(mesh, nodes[elements[elem*numCorners+1]], nodes[elements[elem*numCorners]]);
603: x = MeshPeriodicRelativeX(mesh, xx, nodes[elements[elem*numCorners]]);
605: if ((x >= coords[0]) && (x < coords[1])) {
606: *containingElem = elem;
607: break;
608: }
609: }
610: /* Check for the right endpoint */
611: if ((x >= coords[0]) && (x <= coords[1])) *containingElem = numElements-1;
613: return(0);
614: }
616: /*------------------------------------------- Mesh Embedding Functions -----------------------------------------------*/
617: static int MeshGetNodeFromElement_Triangular_1D(Mesh mesh, int elem, int corner, int *node) {
618: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
619: int numCorners = mesh->numCorners;
622: *node = tri->edges[elem*numCorners+corner];
623: return(0);
624: }
626: static int MeshGetNodeFromEdge_Triangular_1D(Mesh mesh, int edge, int corner, int *node) {
627: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
628: int numCorners = mesh->numCorners;
631: *node = tri->edges[edge*numCorners+corner];
632: return(0);
633: }
635: /*----------------------------------------------- Internal Functions -------------------------------------------------*/
636: static int MeshSetupSupport_Triangular_1D(Mesh mesh) {
637: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
638: int edge, node;
639: int ierr;
642: /* Calculate maximum degree of vertices */
643: if (mesh->numNodes > 0) {
644: PetscMalloc(mesh->numNodes * sizeof(int), &tri->degrees);
645: }
646: PetscMemzero(tri->degrees, mesh->numNodes * sizeof(int));
647: for(edge = 0; edge < mesh->numEdges; edge++) {
648: tri->degrees[tri->edges[edge*mesh->numCorners]]++;
649: tri->degrees[tri->edges[edge*mesh->numCorners+1]]++;
650: }
651: for(node = 0, mesh->maxDegree = 0; node < mesh->numNodes; node++) {
652: mesh->maxDegree = PetscMax(mesh->maxDegree, tri->degrees[node]);
653: }
654: if (mesh->maxDegree > 0) {
655: PetscMalloc(mesh->maxDegree * sizeof(int), &mesh->support);
656: }
657: mesh->supportTaken = PETSC_FALSE;
658: return(0);
659: }
661: static int MeshCheckBoundary_Triangular_1D(Mesh mesh) {
662: MeshBoundary2D *bdCtx = mesh->bdCtx;
663: int *markers = bdCtx->markers;
664: int numBd = 0;
665: int numBdVertices = 0;
666: int *bdMarkers;
667: int *bdBegin;
668: int bd, vertex, rank;
669: int ierr;
673: MPI_Comm_rank(mesh->comm, &rank);
674: if (rank != 0) return(0);
676: if (bdCtx->numBd != bdCtx->numVertices) {
677: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "All boundaries must be points: %d != %d", bdCtx->numBd, bdCtx->numVertices);
678: }
679: if ((bdCtx->numVertices != 0) && (bdCtx->numVertices != 2)) {
680: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of boundary points %d", bdCtx->numVertices);
681: }
682: if ((bdCtx->numVertices == 0) && (mesh->isPeriodic == PETSC_FALSE)) {
683: SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Non-periodic domain must have 2 boundary points");
684: }
685: if (bdCtx->numVertices > 0) {
688: }
689: PetscMalloc(bdCtx->numBd * sizeof(int), &bdMarkers);
690: PetscMalloc((bdCtx->numBd+1) * sizeof(int), &bdBegin);
691: PetscMemzero(bdBegin, (bdCtx->numBd+1) * sizeof(int));
692: for(vertex = 0; vertex < bdCtx->numVertices; vertex++) {
693: if (markers[vertex] == 0) continue;
694: numBdVertices++;
695: /* Check for new marker */
696: for(bd = 0; bd < numBd; bd++) {
697: if (markers[vertex] == bdMarkers[bd]) break;
698: }
699: if (bd == numBd) {
700: if (numBd >= bdCtx->numBd) SETERRQ1(PETSC_ERR_ARG_CORRUPT, "More markers present than declared: %d", bdCtx->numBd);
701: /* Insert new marker */
702: for(bd = 0; bd < numBd; bd++) {
703: if (markers[vertex] < bdMarkers[bd]) break;
704: }
705: if (bd < numBd) {
706: PetscMemmove(&bdMarkers[bd+1], &bdMarkers[bd], (numBd-bd) * sizeof(int));
707: PetscMemmove(&bdBegin[bd+2], &bdBegin[bd+1], (numBd-bd) * sizeof(int));
708: bdBegin[bd+1] = 0;
709: }
710: bdMarkers[bd] = markers[vertex];
711: numBd++;
712: bdBegin[bd+1]++;
713: } else {
714: bdBegin[bd+1]++;
715: }
716: }
718: /* Do prefix sums to get position offsets */
719: for(bd = 2; bd <= numBd; bd++) {
720: bdBegin[bd] = bdBegin[bd-1] + bdBegin[bd];
721: }
723: if (numBd != bdCtx->numBd) {
724: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", numBd, bdCtx->numBd);
725: }
726: if (bdBegin[numBd] != numBdVertices) {
727: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary vertices %d should be %d", bdBegin[numBd], numBdVertices);
728: }
729: PetscFree(bdMarkers);
730: PetscFree(bdBegin);
731: return(0);
732: }
734: static int MeshSetupBoundary_Triangular_1D(Mesh mesh) {
735: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
736: int numBd = mesh->numBd;
737: int numNodes = mesh->numNodes;
738: int *markers = tri->markers;
739: int newNumBd; /* Current number of different boundary markers */
740: int *bdNodes; /* Node numbers for boundary nodes ordered by boundary */
741: int *bdBeginOff; /* Current offset into the bdNodes or bdEdges array */
742: int rank, bd, node;
743: int ierr;
746: MPI_Comm_rank(mesh->comm, &rank);
747: PetscLogEventBegin(MESH_SetupBoundary, mesh, 0, 0, 0);
748: mesh->numBdNodes = 0;
749: if (numBd == 0) {
750: tri->bdMarkers = PETSC_NULL;
751: tri->bdBegin = PETSC_NULL;
752: tri->bdNodes = PETSC_NULL;
753: return(0);
754: }
755: PetscMalloc(numBd * sizeof(int), &tri->bdMarkers);
756: PetscMalloc((numBd+1) * sizeof(int), &tri->bdBegin);
757: PetscMalloc((numBd+1) * sizeof(int), &bdBeginOff);
758: PetscLogObjectMemory(mesh, (numBd + (numBd+1)) * sizeof(int));
759: PetscMemzero(tri->bdMarkers, numBd * sizeof(int));
760: PetscMemzero(tri->bdBegin, (numBd+1) * sizeof(int));
761: PetscMemzero(bdBeginOff, (numBd+1) * sizeof(int));
763: for(node = 0, newNumBd = 0; node < numNodes; node++) {
764: /* Get number of boundary nodes and markers */
765: if (markers[node]) {
766: mesh->numBdNodes++;
767: /* Check for new marker */
768: for(bd = 0; bd < newNumBd; bd++) {
769: if (markers[node] == tri->bdMarkers[bd]) break;
770: }
771: if (bd == newNumBd) {
772: /* Insert new marker */
773: for(bd = 0; bd < newNumBd; bd++) {
774: if (markers[node] < tri->bdMarkers[bd]) break;
775: }
776: if (bd < newNumBd) {
777: PetscMemmove(&tri->bdMarkers[bd+1], &tri->bdMarkers[bd], (newNumBd-bd) * sizeof(int));
778: PetscMemmove(&tri->bdBegin[bd+2], &tri->bdBegin[bd+1], (newNumBd-bd) * sizeof(int));
779: tri->bdBegin[bd+1] = 0;
780: }
781: tri->bdMarkers[bd] = markers[node];
782: newNumBd++;
783: tri->bdBegin[bd+1]++;
784: } else {
785: tri->bdBegin[bd+1]++;
786: }
787: }
788: }
790: /* Do prefix sums to get position offsets */
791: for(bd = 2; bd <= numBd; bd++) {
792: tri->bdBegin[bd] = tri->bdBegin[bd-1] + tri->bdBegin[bd];
793: }
795: /* Check boundary information consistency */
796: if (newNumBd != numBd) {
797: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundaries %d should be %d", newNumBd, numBd);
798: }
799: if (tri->bdBegin[numBd] != mesh->numBdNodes) {
800: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d should be %d", tri->bdBegin[numBd], mesh->numBdNodes);
801: }
802: if ((mesh->numBdNodes != 0) && (mesh->numBdNodes != 2)) {
803: SETERRQ1(PETSC_ERR_PLIB, "Invalid number of boundary nodes %d", mesh->numBdNodes);
804: }
805: if (mesh->numBdNodes != mesh->numBd) {
806: SETERRQ2(PETSC_ERR_PLIB, "Inconsistent boundary information: numBd %d != numBdNodes %d", mesh->numBd, mesh->numBdNodes);
807: }
809: PetscMalloc(mesh->numBdNodes * sizeof(int), &bdNodes);
810: PetscLogObjectMemory(mesh, mesh->numBdNodes * sizeof(int));
812: /* Split nodes by marker */
813: PetscMemcpy(bdBeginOff, tri->bdBegin, (numBd+1) * sizeof(int));
814: for(node = 0; node < numNodes; node++) {
815: for(bd = 0; bd < numBd; bd++) {
816: if (markers[node] == tri->bdMarkers[bd]) {
817: #ifdef MESH_TRACE_BOUNDARY_CREATE
818: PetscPrintf(PETSC_COMM_WORLD, "bd: %d bdNode[%d] = %dn", bd, bdBeginOff[bd], node);
819: #endif
820: bdNodes[bdBeginOff[bd]++] = node;
821: }
822: }
823: }
824: for(bd = 0; bd < numBd; bd++) {
825: if (tri->bdBegin[bd+1] != bdBeginOff[bd])
826: SETERRQ(PETSC_ERR_PLIB, "Invalid boundary node marker information");
827: }
828: PetscFree(bdBeginOff);
830: /* Set fields */
831: tri->bdNodes = bdNodes;
833: PetscLogEventEnd(MESH_SetupBoundary, mesh, 0, 0, 0);
834: return(0);
835: }
837: /*
838: MeshAssemble_Triangular_1D - This function assembles the mesh entirely on the first processor.
840: Collective on Mesh
842: Input Parameters:
843: . mesh - The mesh being refined
845: Output Parameter:
846: + nodes - The node coordinates
847: . markers - The node markers
848: - edges - The nodes for each edge
850: Level: developer
852: .keywords mesh, assemble
853: .seealso MeshInitRefineInput_Triangle()
854: */
855: int MeshAssemble_Triangular_1D(Mesh mesh, double **nodes, int **markers, int **faces, int **edges) {
856: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
857: Partition p = mesh->part;
858: Partition_Triangular_1D *q = (Partition_Triangular_1D *) p->data;
859: int numNodes = q->numNodes;
860: int numEdges = p->numElements;
861: int numCorners = mesh->numCorners;
862: int numProcs = p->numProcs;
863: int rank = p->rank;
864: int *locEdges = PETSC_NULL;
865: int *numRecvNodes, *numRecvMarkers, *numRecvEdges;
866: int *nodeOffsets, *markerOffsets, *edgeOffsets;
867: int proc, edge, size;
868: int ierr;
871: /* Allocate global arrays */
872: if (rank == 0) {
873: PetscMalloc(numNodes*2 * sizeof(double), nodes);
874: PetscMalloc(numNodes * sizeof(int), markers);
875: PetscMalloc(numEdges*numCorners * sizeof(int), edges);
876: }
878: if (numProcs > 1) {
879: if (mesh->numEdges > 0) {
880: PetscMalloc(mesh->numEdges*numCorners * sizeof(int), &locEdges);
881: }
883: /* Calculate offsets */
884: PetscMalloc(numProcs * sizeof(int), &numRecvNodes);
885: PetscMalloc(numProcs * sizeof(int), &numRecvMarkers);
886: PetscMalloc(numProcs * sizeof(int), &numRecvEdges);
887: PetscMalloc(numProcs * sizeof(int), &nodeOffsets);
888: PetscMalloc(numProcs * sizeof(int), &markerOffsets);
889: PetscMalloc(numProcs * sizeof(int), &edgeOffsets);
890: for(proc = 0; proc < numProcs; proc++) {
891: numRecvNodes[proc] = (q->firstNode[proc+1] - q->firstNode[proc])*2;
892: numRecvMarkers[proc] = (q->firstNode[proc+1] - q->firstNode[proc]);
893: numRecvEdges[proc] = (p->firstElement[proc+1] - p->firstElement[proc])*numCorners;
894: }
895: nodeOffsets[0] = 0;
896: markerOffsets[0] = 0;
897: edgeOffsets[0] = 0;
898: for(proc = 1; proc < numProcs; proc++) {
899: nodeOffsets[proc] = numRecvNodes[proc-1] + nodeOffsets[proc-1];
900: markerOffsets[proc] = numRecvMarkers[proc-1] + markerOffsets[proc-1];
901: edgeOffsets[proc] = numRecvEdges[proc-1] + edgeOffsets[proc-1];
902: }
904: /* Local to global node number conversion */
905: for(edge = 0; edge < mesh->numEdges*numCorners; edge++) {
906: PartitionLocalToGlobalNodeIndex(p, tri->edges[edge], &locEdges[edge]);
907: }
909: /* Collect global arrays */
910: size = mesh->numNodes*2;
911: MPI_Gatherv(tri->nodes, size, MPI_DOUBLE, *nodes, numRecvNodes, nodeOffsets, MPI_DOUBLE, 0, p->comm);
912:
913: size = mesh->numNodes;
914: MPI_Gatherv(tri->markers, size, MPI_INT, *markers, numRecvMarkers, markerOffsets, MPI_INT, 0, p->comm);
915:
916: size = mesh->numEdges*numCorners;
917: MPI_Gatherv(locEdges, size, MPI_INT, *edges, numRecvEdges, edgeOffsets, MPI_INT, 0, p->comm);
918:
920: /* Cleanup */
921: if (locEdges != PETSC_NULL) {
922: PetscFree(locEdges);
923: }
924: PetscFree(numRecvNodes);
925: PetscFree(numRecvMarkers);
926: PetscFree(numRecvEdges);
927: PetscFree(nodeOffsets);
928: PetscFree(markerOffsets);
929: PetscFree(edgeOffsets);
930: } else {
931: /* Uniprocessor case */
932: PetscMemcpy(*nodes, tri->nodes, numNodes*2 * sizeof(double));
933: PetscMemcpy(*markers, tri->markers, numNodes * sizeof(int));
934: PetscMemcpy(*edges, tri->edges, numEdges*numCorners * sizeof(int));
935: }
936: return(0);
937: }
939: int MeshDebug_Triangular_1D(Mesh mesh, PetscTruth distributed) {
940: Mesh_Triangular *tri = (Mesh_Triangular *) mesh->data;
941: Partition p = mesh->part;
942: Partition_Triangular_1D *q = PETSC_NULL;
943: int numBd = mesh->numBd;
944: int numElements = mesh->numFaces;
945: int numCorners = mesh->numCorners;
946: int numNodes = mesh->numNodes;
947: int *elements = tri->faces;
948: int *markers = tri->markers;
949: int *bdMarkers = tri->bdMarkers;
950: int degree;
951: int *support;
952: int *degrees;
953: int *supports;
954: int *sizes;
955: int numProcs, rank;
956: PetscTruth isMidnode;
957: int proc, bd, elem, nElem, sElem, sElem2, corner, node, newNode, size;
958: int ierr;
961: MPI_Comm_size(mesh->comm, &numProcs);
962: MPI_Comm_rank(mesh->comm, &rank);
963: if (p != PETSC_NULL) {
964: q = (Partition_Triangular_1D *) p->data;
965: }
967: /* Check basic sizes */
968: PetscMalloc(numProcs * sizeof(int), &sizes);
969: MPI_Allgather(&mesh->numBd, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
970: for(proc = 0, 0; proc < numProcs-1; proc++) {
971: if (sizes[proc] != sizes[proc+1]) {
972: PetscPrintf(mesh->comm, "The number of boundaries is different on proc %d(%d) and proc %d(%d)n",
973: proc, sizes[proc], proc+1, sizes[proc+1]);
974: 1;
975: }
976: }
977:
978: #if 0
979: /* I made vertices distributed in linear meshes */
980: MPI_Allgather(&tri->numVertices, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
981: for(proc = 0, 0; proc < numProcs-1; proc++) {
982: if (sizes[proc] != sizes[proc+1]) {
983: PetscPrintf(mesh->comm, "The number of vertices is different on proc %d(%d) and proc %d(%d)n",
984: proc, sizes[proc], proc+1, sizes[proc+1]);
985: 1;
986: }
987: }
988:
989: #endif
990: MPI_Allgather(&mesh->numCorners, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
991: for(proc = 0, 0; proc < numProcs-1; proc++) {
992: if (sizes[proc] != sizes[proc+1]) {
993: PetscPrintf(mesh->comm, "The number of face corners is different on proc %d(%d) and proc %d(%d)n",
994: proc, sizes[proc], proc+1, sizes[proc+1]);
995: 1;
996: }
997: }
998:
999: MPI_Allgather(&mesh->numBdEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1000: for(proc = 0, 0; proc < numProcs-1; proc++) {
1001: if (sizes[proc] != sizes[proc+1]) {
1002: PetscPrintf(mesh->comm, "The number of boundary edges is different on proc %d(%d) and proc %d(%d)n",
1003: proc, sizes[proc], proc+1, sizes[proc+1]);
1004: 1;
1005: }
1006: }
1007:
1008: if (distributed == PETSC_FALSE) {
1009: MPI_Allgather(&mesh->numNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1010: for(proc = 0, 0; proc < numProcs-1; proc++) {
1011: if (sizes[proc] != sizes[proc+1]) {
1012: PetscPrintf(mesh->comm, "The number of nodes is different on proc %d(%d) and proc %d(%d)n",
1013: proc, sizes[proc], proc+1, sizes[proc+1]);
1014: 1;
1015: }
1016: }
1017:
1018: MPI_Allgather(&mesh->numBdNodes, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1019: for(proc = 0, 0; proc < numProcs-1; proc++) {
1020: if (sizes[proc] != sizes[proc+1]) {
1021: PetscPrintf(mesh->comm, "The number of boundary nodes is different on proc %d(%d) and proc %d(%d)n",
1022: proc, sizes[proc], proc+1, sizes[proc+1]);
1023: 1;
1024: }
1025: }
1026:
1027: MPI_Allgather(&mesh->numEdges, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1028: for(proc = 0, 0; proc < numProcs-1; proc++) {
1029: if (sizes[proc] != sizes[proc+1]) {
1030: PetscPrintf(mesh->comm, "The number of edges is different on proc %d(%d) and proc %d(%d)n",
1031: proc, sizes[proc], proc+1, sizes[proc+1]);
1032: 1;
1033: }
1034: }
1035:
1036: MPI_Allgather(&mesh->numFaces, 1, MPI_INT, sizes, 1, MPI_INT, mesh->comm);
1037: for(proc = 0, 0; proc < numProcs-1; proc++) {
1038: if (sizes[proc] != sizes[proc+1]) {
1039: PetscPrintf(mesh->comm, "The number of faces is different on proc %d(%d) and proc %d(%d)n",
1040: proc, sizes[proc], proc+1, sizes[proc+1]);
1041: 1;
1042: }
1043: }
1044:
1045: } else {
1046: MPI_Allreduce(&mesh->numNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1047: if (size != q->numNodes) {
1048: SETERRQ2(PETSC_ERR_PLIB, "The total number of nodes %d should be %dn", size, q->numNodes);
1049: }
1050: #if 0
1051: MPI_Allreduce(&tri->numBdNodes, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1052: #else
1053: size = mesh->numBdNodes;
1054: #endif
1055: if (size != q->numBdNodes) {
1056: SETERRQ2(PETSC_ERR_PLIB, "The total number of boundary nodes %d should be %dn", size, q->numBdNodes);
1057: }
1058: MPI_Allreduce(&mesh->numEdges, &size, 1, MPI_INT, MPI_SUM, mesh->comm);
1059: if (size != mesh->part->numElements) {
1060: SETERRQ2(PETSC_ERR_PLIB, "The total number of edges %d should be %dn", size, mesh->part->numElements);
1061: }
1062: }
1063: PetscFree(sizes);
1065: if (distributed == PETSC_FALSE) {
1066: /* Check markers */
1067: for(node = 0; node < numNodes; node++) {
1068: if (!markers[node]) continue;
1070: for(bd = 0; bd < numBd; bd++)
1071: if(bdMarkers[bd] == markers[node])
1072: break;
1073: if (bd == numBd) {
1074: SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1075: }
1076: }
1077: /* Check mesh connectivity */
1078: for(node = 0; node < numNodes; node++) {
1079: MeshGetNodeSupport(mesh, node, 0, °ree, &support);
1081: /* Check node degree */
1082: PetscMalloc(numProcs * sizeof(int), °rees);
1083: MPI_Allgather(°ree, 1, MPI_INT, degrees, 1, MPI_INT, mesh->comm);
1084: for(proc = 0, 0; proc < numProcs-1; proc++)
1085: if (degrees[proc] != degrees[proc+1]) {
1086: PetscPrintf(mesh->comm, "Degree of node %d is different on proc %d(%d) and proc %d(%d)n",
1087: node, proc, degrees[proc], proc+1, degrees[proc+1]);
1088: PetscPrintf(mesh->comm, "Node Information:n");
1089: PetscSequentialPhaseBegin(mesh->comm, 1);
1090: PetscPrintf(PETSC_COMM_SELF, " Processor %dn", rank);
1091: if ((rank == proc) || (rank == proc+1))
1092: for(sElem = 0; sElem < degree; sElem++)
1093: PetscPrintf(PETSC_COMM_SELF, " Support : %dn", support[sElem]);
1094: PetscPrintf(PETSC_COMM_SELF, " Marker : %dn", tri->markers[node]);
1095: PetscPrintf(PETSC_COMM_SELF, " Location : (%g,%g)n", tri->nodes[node*2], tri->nodes[node*2+1]);
1096: PetscPrintf(PETSC_COMM_SELF, " In Elements:");
1097: for(elem = 0, isMidnode = PETSC_FALSE; elem < numElements; elem++)
1098: for(corner = 0; corner < numCorners; corner++)
1099: if (elements[elem*numCorners+corner] == node) {
1100: PetscPrintf(PETSC_COMM_SELF, " %d", elem);
1101: if (corner >= 3)
1102: isMidnode = PETSC_TRUE;
1103: }
1104: PetscPrintf(PETSC_COMM_SELF, "n");
1105: if (isMidnode == PETSC_TRUE)
1106: PetscPrintf(PETSC_COMM_SELF, " Midnoden");
1107: else
1108: PetscPrintf(PETSC_COMM_SELF, " Vertexn");
1109: PetscSequentialPhaseEnd(mesh->comm, 1);
1110: 1;
1111: }
1112:
1113: PetscFree(degrees);
1115: /* Check support elements */
1116: PetscMalloc(degree*numProcs * sizeof(int), &supports);
1117: MPI_Allgather(support, degree, MPI_INT, supports, degree, MPI_INT, mesh->comm);
1118: for(sElem = 0, 0; sElem < degree; sElem++) {
1119: nElem = supports[sElem];
1120: for(proc = 1; proc < numProcs; proc++) {
1121: for(sElem2 = 0; sElem2 < degree; sElem2++)
1122: if (supports[proc*degree+sElem2] == nElem)
1123: break;
1124: if (sElem2 == degree) {
1125: PetscPrintf(mesh->comm, "Support element %d of node %d on proc %d(%d) is not present on proc %dn",
1126: sElem, node, 0, supports[sElem], proc);
1127: PetscPrintf(mesh->comm, " Support of node %d on proc %d:n ", node, proc);
1128: for(sElem2 = 0; sElem2 < degree; sElem2++)
1129: PetscPrintf(mesh->comm, " %d", supports[proc*degree+sElem2]);
1130: PetscPrintf(mesh->comm, "n");
1131: 1;
1132: }
1133: }
1134: }
1135:
1136: PetscFree(supports);
1138: /* Check that node only appears inside elements in the support */
1139: for(elem = 0, 0; elem < numElements; elem++)
1140: for(corner = 0; corner < numCorners; corner++) {
1141: newNode = elements[elem*numCorners+corner];
1142: if (node == newNode) {
1143: for(sElem = 0; sElem < degree; sElem++)
1144: if (support[sElem] == elem)
1145: break;
1146: if (sElem == degree) {
1147: PetscPrintf(mesh->comm, "Node %d found in element %d which is not present in the supportn",
1148: node, elem);
1149: 1;
1150: }
1151: }
1152: }
1153:
1155: MeshRestoreNodeSupport(mesh, node, 0, °ree, &support);
1156: }
1157: } else {
1158: /* Check markers */
1159: for(node = 0; node < q->numOverlapNodes; node++) {
1160: if (!markers[node]) continue;
1162: for(bd = 0; bd < numBd; bd++)
1163: if(bdMarkers[bd] == markers[node])
1164: break;
1165: if (bd == numBd) {
1166: SETERRQ2(PETSC_ERR_PLIB, "The marker %d for node %d is invalidn", markers[node], node);
1167: }
1168: }
1169: /* Check mesh connectivity */
1170: for(node = 0; node < q->numLocNodes; node++) {
1171: MeshGetNodeSupport(mesh, node, 0, °ree, &support);
1173: /* Check that node only appears inside elements in the support */
1174: for(elem = 0, 0; elem < p->numOverlapElements; elem++) {
1175: for(corner = 0; corner < numCorners; corner++) {
1176: newNode = elements[elem*numCorners+corner];
1177: if (node == newNode) {
1178: for(sElem = 0; sElem < degree; sElem++) {
1179: if (support[sElem] == elem) break;
1180: }
1181: if (sElem == degree) {
1182: PetscPrintf(PETSC_COMM_SELF, "[%d]Node %d found in element %d which is not present in the supportn",
1183: p->rank, node, elem);
1184: 1;
1185: }
1186: }
1187: }
1188: }
1189:
1191: MeshRestoreNodeSupport(mesh, node, 0, °ree, &support);
1192: }
1193: }
1194: return(0);
1195: }
1197: static struct _MeshOps MeshOps = {/* Generic Operations */
1198: PETSC_NULL/* MeshSetup */,
1199: PETSC_NULL/* MeshSetFromOptions */,
1200: MeshView_Triangular_1D,
1201: PETSC_NULL/* MeshCopy */,
1202: PETSC_NULL/* MeshDuplicate */,
1203: MeshDestroy_Triangular_1D,
1204: /* Mesh-Specific Operations */
1205: MeshPartition_Triangular_1D,
1206: MeshCoarsen_Triangular_1D,
1207: MeshRefine_Triangular_1D,
1208: MeshResetNodes_Triangular_1D,
1209: MeshSaveMesh_Triangular_1D,
1210: MeshRestoreMesh_Triangular_1D,
1211: /* Mesh Query Functions */
1212: MeshUpdateBoundingBox_Triangular_1D,
1213: MeshIsDistorted_Triangular_1D,
1214: /* Mesh Boundary Query Functions */
1215: MeshGetBoundarySize_Triangular_1D,
1216: MeshGetBoundaryIndex_Triangular_1D,
1217: MeshGetBoundaryStart_Triangular_1D,
1218: MeshGetBoundaryNext_Triangular_1D,
1219: MeshGetActiveBoundary_Triangular_1D,
1220: /* Mesh Node Query Functions */
1221: MeshGetNodeBoundary_Triangular_1D,
1222: MeshNodeIsVertex_Triangular_1D,
1223: MeshGetNodeCoords_Triangular_1D,
1224: MeshSetNodeCoords_Triangular_1D,
1225: MeshGetNodeCoordsSaved_Triangular_1D,
1226: MeshNearestNode_Triangular_1D,
1227: MeshGetNodeSupport_Triangular_1D,
1228: /* Mesh Element Query Functions */
1229: MeshGetElemNeighbor_Triangular_1D,
1230: MeshLocatePoint_Triangular_1D,
1231: /* Mesh Embedding Query Functions */
1232: MeshGetNodeFromElement_Triangular_1D,
1233: MeshGetNodeFromEdge_Triangular_1D,
1234: /* CSR Support Functions */
1235: PETSC_NULL,
1236: PETSC_NULL,
1237: PETSC_NULL};
1239: #if 0
1240: EXTERN_C_BEGIN
1241: int MeshSerialize_Triangular_1D(MPI_Comm comm, Mesh *mesh, PetscViewer viewer, PetscTruth store) {
1242: Mesh m;
1243: Mesh_Triangular *tri;
1244: int fd;
1245: int zero = 0;
1246: int one = 1;
1247: int numNodes, numEdges, numFaces, numCorners, numBd, numBdNodes, numBdEdges, old;
1248: int ierr;
1251: PetscViewerBinaryGetDescriptor(viewer, &fd);
1252: if (store) {
1253: m = *mesh;
1254: PetscBinaryWrite(fd, &m->highlightElement, 1, PETSC_INT, 0);
1255: PetscBinaryWrite(fd, &m->maxDegree, 1, PETSC_INT, 0);
1256: PetscBinaryWrite(fd, &m->startX, 1, PETSC_DOUBLE, 0);
1257: PetscBinaryWrite(fd, &m->endX, 1, PETSC_DOUBLE, 0);
1258: PetscBinaryWrite(fd, &m->sizeX, 1, PETSC_DOUBLE, 0);
1259: PetscBinaryWrite(fd, &m->startY, 1, PETSC_DOUBLE, 0);
1260: PetscBinaryWrite(fd, &m->endY, 1, PETSC_DOUBLE, 0);
1261: PetscBinaryWrite(fd, &m->sizeY, 1, PETSC_DOUBLE, 0);
1262: PetscBinaryWrite(fd, &m->startZ, 1, PETSC_DOUBLE, 0);
1263: PetscBinaryWrite(fd, &m->endZ, 1, PETSC_DOUBLE, 0);
1264: PetscBinaryWrite(fd, &m->sizeZ, 1, PETSC_DOUBLE, 0);
1265: PetscBinaryWrite(fd, &m->locStartX, 1, PETSC_DOUBLE, 0);
1266: PetscBinaryWrite(fd, &m->locEndX, 1, PETSC_DOUBLE, 0);
1267: PetscBinaryWrite(fd, &m->locSizeX, 1, PETSC_DOUBLE, 0);
1268: PetscBinaryWrite(fd, &m->locStartY, 1, PETSC_DOUBLE, 0);
1269: PetscBinaryWrite(fd, &m->locEndY, 1, PETSC_DOUBLE, 0);
1270: PetscBinaryWrite(fd, &m->locSizeY, 1, PETSC_DOUBLE, 0);
1271: PetscBinaryWrite(fd, &m->locStartZ, 1, PETSC_DOUBLE, 0);
1272: PetscBinaryWrite(fd, &m->locEndZ, 1, PETSC_DOUBLE, 0);
1273: PetscBinaryWrite(fd, &m->locSizeZ, 1, PETSC_DOUBLE, 0);
1274: PetscBinaryWrite(fd, &m->isPeriodic, 1, PETSC_INT, 0);
1275: PetscBinaryWrite(fd, &m->isPeriodicDim, 3, PETSC_INT, 0);
1277: PetscBinaryWrite(fd, &m->numBd, 1, PETSC_INT, 0);
1278: PetscBinaryWrite(fd, &m->numVertices, 1, PETSC_INT, 0);
1279: PetscBinaryWrite(fd, &m->numNodes, 1, PETSC_INT, 0);
1280: PetscBinaryWrite(fd, &m->numBdNodes, 1, PETSC_INT, 0);
1281: PetscBinaryWrite(fd, &m->numEdges, 1, PETSC_INT, 0);
1282: PetscBinaryWrite(fd, &m->numBdEdges, 1, PETSC_INT, 0);
1283: PetscBinaryWrite(fd, &m->numFaces, 1, PETSC_INT, 0);
1284: PetscBinaryWrite(fd, &m->numBdFaces, 1, PETSC_INT, 0);
1285: PetscBinaryWrite(fd, &m->numCells, 1, PETSC_INT, 0);
1286: PetscBinaryWrite(fd, &m->numCorners, 1, PETSC_INT, 0);
1287: PetscBinaryWrite(fd, &m->numCellCorners, 1, PETSC_INT, 0);
1288: PetscBinaryWrite(fd, &m->numHoles, 1, PETSC_INT, 0);
1290: PartitionSerialize(m, &m->part, viewer, store);
1292: PartitionGetNumOverlapElements(m->part, &numFaces);
1293: PartitionGetNumOverlapNodes(m->part, &numNodes);
1294: numEdges = m->numEdges;
1295: numCorners = m->numCorners;
1296: numBd = m->numBd;
1297: numBdNodes = m->numBdNodes;
1298: numBdEdges = m->numBdEdges;
1300: tri = (Mesh_Triangular *) (*mesh)->data;
1301: PetscBinaryWrite(fd, tri->nodes, numNodes*2, PETSC_DOUBLE, 0);
1302: if (tri->nodesOld == PETSC_NULL) {
1303: PetscBinaryWrite(fd, &zero, 1, PETSC_INT, 0);
1304: } else {
1305: PetscBinaryWrite(fd, &one, 1, PETSC_INT, 0);
1306: PetscBinaryWrite(fd, tri->nodesOld, numNodes*2, PETSC_DOUBLE, 0);
1307: }
1308: PetscBinaryWrite(fd, tri->markers, numNodes, PETSC_INT, 0);
1309: PetscBinaryWrite(fd, tri->degrees, numNodes, PETSC_INT, 0);
1310: PetscBinaryWrite(fd, tri->edges, numEdges*2, PETSC_INT, 0);
1311: PetscBinaryWrite(fd, tri->edgemarkers, numEdges, PETSC_INT, 0);
1312: PetscBinaryWrite(fd, tri->faces, numFaces*numCorners, PETSC_INT, 0);
1313: PetscBinaryWrite(fd, tri->neighbors, numFaces*3, PETSC_INT, 0);
1314: PetscBinaryWrite(fd, tri->bdNodes, numBdNodes, PETSC_INT, 0);
1315: PetscBinaryWrite(fd, tri->bdEdges, numBdEdges, PETSC_INT, 0);
1316: PetscBinaryWrite(fd, tri->bdMarkers, numBd, PETSC_INT, 0);
1317: PetscBinaryWrite(fd, tri->bdBegin, numBd+1, PETSC_INT, 0);
1318: PetscBinaryWrite(fd, tri->bdEdgeBegin, numBd+1, PETSC_INT, 0);
1319: PetscBinaryWrite(fd, m->holes, m->numHoles*2, PETSC_DOUBLE, 0);
1321: PetscBinaryWrite(fd, &m->maxAspectRatio, 1, PETSC_DOUBLE, 0);
1322: } else {
1323: /* Create the mesh context */
1324: MeshCreate(comm, &m);
1325: PetscNew(Mesh_Triangular, &tri);
1326: PetscLogObjectMemory(m, sizeof(Mesh_Triangular));
1327: PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1328: PetscStrallocpy(MESH_TRIANGULAR_2D, &m->type_name);
1329: m->data = (void *) tri;
1330: m->dim = 2;
1332: PetscBinaryRead(fd, &m->highlightElement, 1, PETSC_INT);
1333: PetscBinaryRead(fd, &m->maxDegree, 1, PETSC_INT);
1334: PetscMalloc(m->maxDegree * sizeof(int), &m->support);
1336: PetscBinaryRead(fd, &m->startX, 1, PETSC_DOUBLE);
1337: PetscBinaryRead(fd, &m->endX, 1, PETSC_DOUBLE);
1338: PetscBinaryRead(fd, &m->sizeX, 1, PETSC_DOUBLE);
1339: PetscBinaryRead(fd, &m->startY, 1, PETSC_DOUBLE);
1340: PetscBinaryRead(fd, &m->endY, 1, PETSC_DOUBLE);
1341: PetscBinaryRead(fd, &m->sizeY, 1, PETSC_DOUBLE);
1342: PetscBinaryRead(fd, &m->startZ, 1, PETSC_DOUBLE);
1343: PetscBinaryRead(fd, &m->endZ, 1, PETSC_DOUBLE);
1344: PetscBinaryRead(fd, &m->sizeZ, 1, PETSC_DOUBLE);
1345: PetscBinaryRead(fd, &m->locStartX, 1, PETSC_DOUBLE);
1346: PetscBinaryRead(fd, &m->locEndX, 1, PETSC_DOUBLE);
1347: PetscBinaryRead(fd, &m->locSizeX, 1, PETSC_DOUBLE);
1348: PetscBinaryRead(fd, &m->locStartY, 1, PETSC_DOUBLE);
1349: PetscBinaryRead(fd, &m->locEndY, 1, PETSC_DOUBLE);
1350: PetscBinaryRead(fd, &m->locSizeY, 1, PETSC_DOUBLE);
1351: PetscBinaryRead(fd, &m->locStartZ, 1, PETSC_DOUBLE);
1352: PetscBinaryRead(fd, &m->locEndZ, 1, PETSC_DOUBLE);
1353: PetscBinaryRead(fd, &m->locSizeZ, 1, PETSC_DOUBLE);
1354: PetscBinaryRead(fd, &m->isPeriodic, 1, PETSC_INT);
1355: PetscBinaryRead(fd, &m->isPeriodicDim, 3, PETSC_INT);
1357: m->activeBd = -1;
1358: m->activeBdOld = -1;
1359: m->activeBdNode = -1;
1360: tri->areas = PETSC_NULL;
1361: tri->aspectRatios = PETSC_NULL;
1363: PetscBinaryRead(fd, &m->numBd, 1, PETSC_INT);
1364: PetscBinaryRead(fd, &m->numVertices, 1, PETSC_INT);
1365: PetscBinaryRead(fd, &m->numNodes, 1, PETSC_INT);
1366: PetscBinaryRead(fd, &m->numBdNodes, 1, PETSC_INT);
1367: PetscBinaryRead(fd, &m->numEdges, 1, PETSC_INT);
1368: PetscBinaryRead(fd, &m->numBdEdges, 1, PETSC_INT);
1369: PetscBinaryRead(fd, &m->numFaces, 1, PETSC_INT);
1370: PetscBinaryRead(fd, &m->numBdFaces, 1, PETSC_INT);
1371: PetscBinaryRead(fd, &m->numCells, 1, PETSC_INT);
1372: PetscBinaryRead(fd, &m->numCorners, 1, PETSC_INT);
1373: PetscBinaryRead(fd, &m->numCellCorners, 1, PETSC_INT);
1374: PetscBinaryRead(fd, &m->numHoles, 1, PETSC_INT);
1376: PartitionSerialize(m, &m->part, viewer, store);
1377: PetscLogObjectParent(m, m->part);
1379: PartitionGetNumOverlapElements(m->part, &numFaces);
1380: PartitionGetNumOverlapNodes(m->part, &numNodes);
1381: numEdges = m->numEdges;
1382: numCorners = m->numCorners;
1383: numBd = m->numBd;
1384: numBdNodes = m->numBdNodes;
1385: numBdEdges = m->numBdEdges;
1386: PetscMalloc(numNodes*2 * sizeof(double), &tri->nodes);
1387: PetscMalloc(numNodes * sizeof(int), &tri->markers);
1388: PetscMalloc(numNodes * sizeof(int), &tri->degrees);
1389: PetscMalloc(numEdges*2 * sizeof(int), &tri->edges);
1390: PetscMalloc(numEdges * sizeof(int), &tri->edgemarkers);
1391: PetscMalloc(numFaces*numCorners * sizeof(int), &tri->faces);
1392: PetscMalloc(numFaces*3 * sizeof(int), &tri->neighbors);
1393: PetscMalloc(numBdNodes * sizeof(int), &tri->bdNodes);
1394: PetscMalloc(numBdEdges * sizeof(int), &tri->bdEdges);
1395: PetscMalloc(numBd * sizeof(int), &tri->bdMarkers);
1396: PetscMalloc((numBd+1) * sizeof(int), &tri->bdBegin);
1397: PetscMalloc((numBd+1) * sizeof(int), &tri->bdEdgeBegin);
1398: if (m->numHoles > 0) {
1399: PetscMalloc(m->numHoles*2 * sizeof(double), &m->holes);
1400: } else {
1401: m->holes = PETSC_NULL;
1402: }
1403: PetscLogObjectMemory(m, (numNodes*2 + m->numHoles*2) * sizeof(double) +
1404: (numNodes*2 + numEdges*3 + numFaces*(numCorners+1) + numBdNodes + numBdEdges + numBd*3+2)*sizeof(int));
1405: PetscBinaryRead(fd, tri->nodes, numNodes*2, PETSC_DOUBLE);
1406: PetscBinaryRead(fd, &old, 1, PETSC_INT);
1407: if (old) {
1408: PetscMalloc(numNodes*2 * sizeof(double), &tri->nodesOld);
1409: PetscLogObjectMemory(m, numNodes*2 * sizeof(double));
1410: PetscBinaryRead(fd, tri->nodesOld, numNodes*2, PETSC_DOUBLE);
1411: } else {
1412: tri->nodesOld = PETSC_NULL;
1413: }
1414: PetscBinaryRead(fd, tri->markers, numNodes, PETSC_INT);
1415: PetscBinaryRead(fd, tri->degrees, numNodes, PETSC_INT);
1416: PetscBinaryRead(fd, tri->edges, numEdges*2, PETSC_INT);
1417: PetscBinaryRead(fd, tri->edgemarkers, numEdges, PETSC_INT);
1418: PetscBinaryRead(fd, tri->faces, numFaces*numCorners, PETSC_INT);
1419: PetscBinaryRead(fd, tri->neighbors, numFaces*3, PETSC_INT);
1420: PetscBinaryRead(fd, tri->bdNodes, numBdNodes, PETSC_INT);
1421: PetscBinaryRead(fd, tri->bdEdges, numBdEdges, PETSC_INT);
1422: PetscBinaryRead(fd, tri->bdMarkers, numBd, PETSC_INT);
1423: PetscBinaryRead(fd, tri->bdBegin, numBd+1, PETSC_INT);
1424: PetscBinaryRead(fd, tri->bdEdgeBegin, numBd+1, PETSC_INT);
1425: PetscBinaryRead(fd, m->holes, m->numHoles*m->dim, PETSC_DOUBLE);
1427: PetscBinaryRead(fd, &m->maxAspectRatio, 1, PETSC_DOUBLE);
1429: #ifdef PETSC_USE_BOPT_g
1430: /* Check mesh integrity */
1431: MeshDebug_Triangular_1D(m, PETSC_TRUE);
1432: #endif
1433: *mesh = m;
1434: }
1436: return(0);
1437: }
1438: EXTERN_C_END
1439: #endif
1441: EXTERN_C_BEGIN
1442: int MeshCreate_Triangular_1D(Mesh mesh) {
1443: Mesh_Triangular *tri;
1444: int (*f)(MeshBoundary2D *, int, Mesh);
1445: int ierr;
1448: PetscNew(Mesh_Triangular, &tri);
1449: PetscMemzero(tri, sizeof(Mesh_Triangular));
1450: PetscMemcpy(mesh->ops, &MeshOps, sizeof(struct _MeshOps));
1451: mesh->data = (void *) tri;
1452: PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &mesh->serialize_name);
1453: mesh->dim = 1;
1455: /* Setup the periodic domain */
1456: if (mesh->isPeriodic == PETSC_TRUE) {
1457: MeshBoundary2DSetBoundingBox(mesh, mesh->bdCtx);
1458: }
1460: /* Setup default mechanisms */
1461: PetscObjectQueryFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", (PetscVoidFunction) &f);
1462: if (f == PETSC_NULL) {
1463: if (mesh->isPeriodic == PETSC_TRUE) {
1464: PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Periodic",
1465: (void (*)(void)) MeshTriangular1D_Create_Periodic);
1466:
1467: PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Periodic",
1468: (void (*)(void)) MeshTriangular1D_Refine_Periodic);
1469:
1470: } else {
1471: PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", "MeshCreate_Triangle",
1472: (void (*)(void)) MeshTriangular1D_Create_Simple);
1473:
1474: PetscObjectComposeFunction((PetscObject) mesh, "MeshTriangular1D_Refine_C", "MeshRefine_Triangle",
1475: (void (*)(void)) MeshTriangular1D_Refine_Simple);
1476: }
1477: }
1479: MeshCheckBoundary_Triangular_1D(mesh);
1481: PetscObjectQueryFunction((PetscObject) mesh, "MeshTriangular1D_Create_C", (PetscVoidFunction) &f);
1482: (*f)(mesh->bdCtx, mesh->numCorners, mesh);
1484: /* Calculate maximum degree of vertices */
1485: MeshSetupSupport_Triangular_1D(mesh);
1487: /* Construct derived and boundary information */
1488: MeshSetupBoundary_Triangular_1D(mesh);
1490: #if 0
1491: /* Reorder nodes before distributing mesh */
1492: PetscOptionsHasName(mesh->prefix, "-mesh_reorder", &opt);
1493: if (opt == PETSC_TRUE) {
1494: /* MUST FIX: Since we have duplicated the whole mesh, we may impersonate a serial mesh */
1495: comm = mesh->comm;
1496: mesh->comm = PETSC_COMM_SELF;
1497: MeshGetOrdering(mesh, MESH_ORDER_TRIANGULAR_1D_RCM, &mesh->nodeOrdering);
1498: mesh->comm = comm;
1500: /* Permute arrays implicitly numbered by node numbers */
1501: AOApplicationToPetscPermuteReal(mesh->nodeOrdering, mesh->dim, tri->nodes);
1502: AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->markers);
1503: AOApplicationToPetscPermuteInt(mesh->nodeOrdering, 1, tri->degrees);
1504: /* Renumber arrays dependent on the canonical node numbering */
1505: AOApplicationToPetsc(mesh->nodeOrdering, mesh->numEdges*2, tri->edges);
1506: AOApplicationToPetsc(mesh->nodeOrdering, mesh->numFaces*mesh->numCorners, tri->faces);
1507: AOApplicationToPetsc(mesh->nodeOrdering, mesh->numBdNodes, tri->bdNodes);
1508: }
1509: #endif
1511: /* Initialize partition */
1512: MeshPartition(mesh);
1514: /* Initialize save space */
1515: tri->nodesOld = PETSC_NULL;
1517: /* Reset the midnodes */
1518: if (mesh->isPeriodic == PETSC_TRUE) {
1519: MeshResetNodes(mesh, PETSC_TRUE);
1520: }
1522: return(0);
1523: }
1524: EXTERN_C_END
1526: int MeshRefine_Triangular_1D(Mesh mesh, PointFunction area, Mesh *newmesh) {
1527: Mesh m;
1528: Mesh_Triangular *tri;
1529: int (*f)(Mesh, PointFunction, Mesh);
1530: int ierr;
1533: MeshCreate(mesh->comm, &m);
1535: PetscNew(Mesh_Triangular, &tri);
1536: PetscMemzero(tri, sizeof(Mesh_Triangular));
1537: PetscMemcpy(m->ops, &MeshOps, sizeof(struct _MeshOps));
1538: m->data = (void *) tri;
1539: PetscStrallocpy(MESH_TRIANGULAR_1D, &m->type_name);
1540: PetscStrallocpy(MESH_SER_TRIANGULAR_1D_BINARY, &m->serialize_name);
1541: m->dim = 1;
1542: m->numBd = mesh->numBd;
1544: /* Setup the periodic domain */
1545: m->bdCtx = mesh->bdCtx;
1546: if (m->isPeriodic == PETSC_TRUE) {
1547: MeshBoundary2DSetBoundingBox(m, m->bdCtx);
1548: }
1550: /* Setup default mechanisms */
1551: PetscFListDuplicate(((PetscObject) mesh)->qlist, &((PetscObject) m)->qlist);
1553: /* Refine mesh */
1554: PetscObjectQueryFunction((PetscObject) m, "MeshTriangular1D_Refine_C", (PetscVoidFunction) &f);
1555: (*f)(mesh, area, m);
1557: /* Calculate maximum degree of vertices */
1558: MeshSetupSupport_Triangular_1D(m);
1560: /* Construct derived and boundary information */
1561: MeshSetupBoundary_Triangular_1D(m);
1563: /* Initialize partition */
1564: MeshPartition(m);
1566: /* Initialize save space */
1567: tri->nodesOld = PETSC_NULL;
1569: /* Reset the midnodes */
1570: if (m->isPeriodic == PETSC_TRUE) {
1571: MeshResetNodes(m, PETSC_TRUE);
1572: }
1573: *newmesh = m;
1574: return(0);
1575: }