Actual source code: mesh.c
1: #ifdef PETSC_RCS_HEADER
2: static char vcid[] = "$Id: mesh.c,v 1.19 2000/10/17 13:48:57 knepley Exp $";
3: #endif
5: /*
6: Defines the interface to the mesh functions
7: */
9: #include src/mesh/meshimpl.h
11: /* Logging support */
12: int MESH_COOKIE;
13: int MESH_Reform, MESH_IsDistorted, MESH_Partition, MESH_SetupBoundary, MESH_MoveMesh, MESH_CalcNodeVelocities;
14: int MESH_CalcNodeAccelerations, MESH_CreateLocalCSR, MESH_CreateFullCSR, MESH_CreateDualCSR, MESH_LocatePoint;
16: /*------------------------------------------------ Generic Operations ------------------------------------------------*/
17: /*@
18: MeshSetUp - Set up any required internal data structures for a Mesh.
20: Collective on Mesh
22: Input Parameter:
23: . mesh - The mesh
25: Level: beginner
27: .keywords: Mesh, setup
28: .seealso: MeshDestroy()
29: @*/
30: int MeshSetUp(Mesh mesh)
31: {
36: if (mesh->setupcalled) return(0);
37: if (mesh->ops->setup) {
38: (*mesh->ops->setup)(mesh);
39: }
40: return(0);
41: }
43: /*
44: MeshSetTypeFromOptions - Sets the type of mesh generation from user options.
46: Collective on Mesh
48: Input Parameter:
49: . mesh - The mesh
51: Level: intermediate
53: .keywords: Mesh, set, options, database, type
54: .seealso: MeshSetFromOptions(), MeshSetType()
55: */
56: static int MeshSetTypeFromOptions(Mesh mesh)
57: {
58: PetscTruth opt;
59: char *defaultType;
60: char typeName[256];
61: int dim;
62: int ierr;
65: MeshGetDimension(mesh, &dim);
66: if (mesh->dim == -1) {
67: dim = 2;
68: if (mesh->dict != PETSC_NULL) {
69: ParameterDictGetInteger(mesh->dict, "dim", &dim);
70: }
71: MeshSetDimension(mesh, dim);
72: }
73: if (mesh->type_name != PETSC_NULL) {
74: defaultType = mesh->type_name;
75: } else {
76: switch(dim)
77: {
78: case 1:
79: defaultType = MESH_TRIANGULAR_1D;
80: break;
81: case 2:
82: defaultType = MESH_TRIANGULAR_2D;
83: break;
84: default:
85: SETERRQ1(PETSC_ERR_SUP, "Mesh dimension %d is not supported", dim);
86: }
87: }
89: if (!MeshRegisterAllCalled) {
90: MeshRegisterAll(PETSC_NULL);
91: }
92: PetscOptionsList("-mesh_type", "Mesh generation method"," MeshSetType", MeshList, defaultType, typeName, 256, &opt);
93:
94: if (opt == PETSC_TRUE) {
95: MeshSetType(mesh, typeName);
96: } else {
97: MeshSetType(mesh, defaultType);
98: }
99: return(0);
100: }
102: /*@
103: MeshSetFromOptions - Sets various Mesh parameters from user options.
105: Collective on Mesh
107: Input Parameter:
108: . mesh - The mesh
110: Notes: To see all options, run your program with the -help option, or consult the users manual.
111: Must be called after MeshCreate() but before the Mesh is used.
113: Level: intermediate
115: .keywords: Mesh, set, options, database
116: .seealso: MeshCreate(), MeshPrintHelp(), MeshSetOptionsPrefix()
117: @*/
118: int MeshSetFromOptions(Mesh mesh)
119: {
120: Partition part;
121: PetscTruth opt;
122: int ierr;
126: PetscOptionsBegin(mesh->comm, mesh->prefix, "Mesh options", "Mesh");
128: /* Handle generic mesh options */
129: PetscOptionsHasName(PETSC_NULL, "-help", &opt);
130: if (opt == PETSC_TRUE) {
131: MeshPrintHelp(mesh);
132: }
133: PetscOptionsGetInt(mesh->prefix, "-mesh_dim", &mesh->dim, &opt);
134: PetscOptionsGetReal(mesh->prefix, "-mesh_max_aspect_ratio", &mesh->maxAspectRatio, &opt);
136: /* Handle mesh type options */
137: MeshSetTypeFromOptions(mesh);
139: /* Handle specific mesh options */
140: if (mesh->ops->setfromoptions != PETSC_NULL) {
141: (*mesh->ops->setfromoptions)(mesh);
142: }
144: PetscOptionsEnd();
146: /* Handle subobject options */
147: MeshGetPartition(mesh, &part);
148: PartitionSetFromOptions(part);
150: MeshViewFromOptions(mesh, mesh->name);
151: return(0);
152: }
154: /*@
155: MeshViewFromOptions - This function visualizes the mesh based upon user options.
157: Collective on Mesh
159: Input Parameter:
160: . mesh - The mesh
162: Level: intermediate
164: .keywords: Mesh, view, options, database
165: .seealso: MeshSetFromOptions(), MeshView()
166: @*/
167: int MeshViewFromOptions(Mesh mesh, char *title)
168: {
169: PetscViewer viewer;
170: PetscDraw draw;
171: PetscTruth opt;
172: char *titleStr;
173: char typeName[1024];
174: char fileName[1024];
175: int len;
176: int ierr;
179: PetscOptionsHasName(mesh->prefix, "-mesh_view", &opt);
180: if (opt == PETSC_TRUE) {
181: PetscOptionsGetString(mesh->prefix, "-mesh_view", typeName, 1024, &opt);
182: PetscStrlen(typeName, &len);
183: if (len > 0) {
184: PetscViewerCreate(mesh->comm, &viewer);
185: PetscViewerSetType(viewer, typeName);
186: PetscOptionsGetString(mesh->prefix, "-mesh_view_file", fileName, 1024, &opt);
187: if (opt == PETSC_TRUE) {
188: PetscViewerSetFilename(viewer, fileName);
189: } else {
190: PetscViewerSetFilename(viewer, mesh->name);
191: }
192: MeshView(mesh, viewer);
193: PetscViewerFlush(viewer);
194: PetscViewerDestroy(viewer);
195: } else {
196: MeshView(mesh, PETSC_NULL);
197: }
198: }
199: PetscOptionsHasName(mesh->prefix, "-mesh_view_draw", &opt);
200: if (opt == PETSC_TRUE) {
201: PetscViewerDrawOpen(mesh->comm, 0, 0, 0, 0, 300, 300, &viewer);
202: PetscViewerDrawGetDraw(viewer, 0, &draw);
203: if (title != PETSC_NULL) {
204: titleStr = title;
205: } else {
206: PetscObjectName((PetscObject) mesh); CHKERRQ(ierr) ;
207: titleStr = mesh->name;
208: }
209: PetscDrawSetTitle(draw, titleStr);
210: MeshView(mesh, viewer);
211: PetscViewerFlush(viewer);
212: PetscDrawPause(draw);
213: PetscViewerDestroy(viewer);
214: }
215: return(0);
216: }
218: /*@
219: MeshView - Views a mesh object.
221: Collective on Mesh
223: Input Parameters:
224: + mesh - The mesh
225: - viewer - The viewer with which to view the mesh
227: Level: beginner
229: .keywords: mesh, view
230: .seealso: MeshDestroy(), PetscViewerDrawOpen()
231: @*/
232: int MeshView(Mesh mesh, PetscViewer viewer)
233: {
238: if (viewer == PETSC_NULL) {
239: viewer = PETSC_VIEWER_STDOUT_SELF;
240: } else {
242: }
243: (*mesh->ops->view)(mesh, viewer);
244: return(0);
245: }
247: /*
248: MeshPreCopy_Private - Executes hook for generic pre-copying actions.
250: Collective on Mesh
252: Input Parameter:
253: . mesh - The mesh
255: Level: developer
257: .keywords: Mesh, copy
258: .seealso: MeshPosCopy_Private(), MeshCopy(), MeshDuplicate(), MeshRefine(), MeshReform()
259: */
260: int MeshPreCopy_Private(Mesh mesh) {
261: int (*precopy)(Mesh);
262: int ierr;
266: /* Specific operations */
267: PetscObjectQueryFunction((PetscObject) mesh, "PreCopy", (void (**)(void)) &precopy);
268: if (precopy != PETSC_NULL) {
269: (*precopy)(mesh);
270: }
271: return(0);
272: }
274: /*
275: MeshPostCopy_Private - Executes hook for generic post-copying actions.
277: Collective on Mesh
279: Input Parameters:
280: + mesh - The mesh
281: - newMesh - The new mesh
283: Level: developer
285: .keywords: Mesh, copy
286: .seealso: MeshPosCopy_Private(), MeshCopy(), MeshDuplicate(), MeshRefine(), MeshReform()
287: */
288: int MeshPostCopy_Private(Mesh mesh, Mesh newMesh) {
289: int (*postcopy)(Mesh, Mesh);
290: void *ctx;
291: PetscTruth isMoving;
292: int highlightElement;
293: int ierr;
298: /* Generic operations */
299: MeshGetUserContext(mesh, &ctx);
300: MeshSetUserContext(newMesh, ctx);
301: MeshGetHighlightElement(mesh, &highlightElement);
302: MeshSetHighlightElement(newMesh, highlightElement);
303: MeshGetMovement(mesh, &isMoving);
304: MeshSetMovement(newMesh, isMoving);
305: /* Specific operations */
306: PetscObjectQueryFunction((PetscObject) mesh, "PostCopy", (void (**)(void)) &postcopy);
307: if (postcopy != PETSC_NULL) {
308: (*postcopy)(mesh, newMesh);
309: }
310: return(0);
311: }
313: /*@
314: MeshCopy - Copies all the data from one mesh to another.
316: Collective on Mesh
318: Input Parameter:
319: . mesh - The mesh
321: Output Parameter:
322: . newmesh - The identical new mesh
324: Level: beginner
326: .keywords: Mesh, copy
327: .seealso: MeshDuplicate()
328: @*/
329: int MeshCopy(Mesh mesh, Mesh newmesh)
330: {
337: if (mesh->ops->copy == PETSC_NULL) SETERRQ(PETSC_ERR_SUP, " ");
338: MeshPreCopy_Private(mesh);
339: (*mesh->ops->copy)(mesh, newmesh);
340: MeshPostCopy_Private(mesh, newmesh);
341: return(0);
342: }
344: /*@
345: MeshDuplicate - Duplicates the Mesh.
347: Collective on Mesh
349: Input Parameter:
350: . mesh - The mesh
352: Output Parameter:
353: . newmesh - The duplicate mesh
355: Level: beginner
357: .keywords: mesh, duplicate, copy
358: .seealso: MeshCopy()
359: @*/
360: int MeshDuplicate(Mesh mesh, Mesh *newmesh)
361: {
362: int ierr;
367: if (mesh->ops->duplicate == PETSC_NULL) SETERRQ(PETSC_ERR_SUP, " ");
368: MeshPreCopy_Private(mesh);
369: (*mesh->ops->duplicate)(mesh, newmesh);
370: MeshPostCopy_Private(mesh, *newmesh);
371: return(0);
372: }
374: /*@
375: MeshDestroy - Destroys a mesh object.
377: Collective on Mesh
379: Input Parameter:
380: . mesh - The mesh
382: Level: beginner
384: .keywords: mesh, destroy
385: .seealso MeshCreate()
386: @*/
387: int MeshDestroy(Mesh mesh)
388: {
393: if (--mesh->refct > 0) return(0);
394: (*mesh->ops->destroy)(mesh);
395: if (mesh->holes != PETSC_NULL) {
396: PetscFree(mesh->holes);
397: }
398: PetscLogObjectDestroy(mesh);
399: PetscHeaderDestroy(mesh);
400: return(0);
401: }
403: /*@
404: MeshSetUserContext - Sets the optional user-defined context for a mesh object.
406: Collective on Mesh
408: Input Parameters:
409: + mesh - The mesh
410: - usrCtx - The optional user context
412: Level: intermediate
414: .keywords: mesh, set, context
415: .seealso: MeshGetUserContext(), GridSetMeshContext()
416: @*/
417: int MeshSetUserContext(Mesh mesh, void *usrCtx)
418: {
421: mesh->usr = usrCtx;
422: return(0);
423: }
425: /*@
426: MeshGetUserContext - Gets the optional user-defined context for a mesh object.
428: Not collective
430: Input Parameters:
431: . mesh - The mesh
433: Output Parameters:
434: . usrCtx - The optional user context
436: Level: intermediate
438: .keywords: mesh, set, context
439: .seealso: MeshSetUserContext(), GridGetMeshContext()
440: @*/
441: int MeshGetUserContext(Mesh mesh, void **usrCtx)
442: {
446: *usrCtx = mesh->usr;
447: return(0);
448: }
450: /*@C
451: MeshSetOptionsPrefix - Sets the prefix used for searching for all Mesh options in the database.
453: Not collective
455: Input Parameters:
456: + mesh - The mesh
457: - prefix - The prefix to prepend to all option names
459: Notes:
460: A hyphen (-) must NOT be given at the beginning of the prefix name.
461: The first character of all runtime options is AUTOMATICALLY the hyphen.
463: Level: intermediate
465: .keywords: Mesh, set, options, prefix, database
466: .seealso: MeshGetOptionsPrefix(), MeshAppendOptionsPrefix(), MeshSetFromOptions()
467: @*/
468: int MeshSetOptionsPrefix(Mesh mesh, char *prefix)
469: {
474: PetscObjectSetOptionsPrefix((PetscObject) mesh, prefix);
475: return(0);
476: }
478: /*@C
479: MeshAppendOptionsPrefix - Appends to the prefix used for searching for all Mesh options in the database.
481: Not collective
483: Input Parameters:
484: + mesh - The mesh
485: - prefix - The prefix to prepend to all option names
487: Notes:
488: A hyphen (-) must NOT be given at the beginning of the prefix name.
489: The first character of all runtime options is AUTOMATICALLY the hyphen.
491: Level: intermediate
493: .keywords: Mesh, append, options, prefix, database
494: .seealso: MeshGetOptionsPrefix(), MeshSetOptionsPrefix(), MeshSetFromOptions()
495: @*/
496: int MeshAppendOptionsPrefix(Mesh mesh, char *prefix)
497: {
499:
502: PetscObjectAppendOptionsPrefix((PetscObject) mesh, prefix);
503: return(0);
504: }
506: /*@
507: MeshGetOptionsPrefix - Returns the prefix used for searching for all Mesh options in the database.
509: Input Parameter:
510: . mesh - The mesh
512: Output Parameter:
513: . prefix - A pointer to the prefix string used
515: Level: intermediate
517: .keywords: Mesh, get, options, prefix, database
518: .seealso: MeshSetOptionsPrefix(), MeshSetOptionsPrefix(), MeshSetFromOptions()
519: @*/
520: int MeshGetOptionsPrefix(Mesh mesh, char **prefix)
521: {
526: PetscObjectGetOptionsPrefix((PetscObject) mesh, prefix);
527: return(0);
528: }
530: /*@
531: MeshPrintHelp - Prints all options for the Mesh.
533: Input Parameter:
534: . mesh - The mesh
536: Options Database Keys:
537: $ -help, -h
539: Level: intermediate
541: .keywords: Mesh, help
542: .seealso: MeshSetFromOptions()
543: @*/
544: int MeshPrintHelp(Mesh mesh)
545: {
546: char p[64];
547: int ierr;
552: PetscStrcpy(p, "-");
553: if (mesh->prefix != PETSC_NULL) {
554: PetscStrcat(p, mesh->prefix);
555: }
557: (*PetscHelpPrintf)(mesh->comm, "Mesh options ------------------------------------------------n");
558: (*PetscHelpPrintf)(mesh->comm," %smesh_type <typename> : Sets the mesh typen", p);
559: (*PetscHelpPrintf)(mesh->comm," %smesh_dim <num> : Sets the dimension of the meshn", p);
560: return(0);
561: }
563: /*--------------------------------------------- Mesh-Specific Operations ---------------------------------------------*/
564: /*
565: MeshCheckBoundary_Triangular_1D - Checks a boundary for validity.
567: Collective on Mesh
569: Input Parameter:
570: . mesh - The mesh
572: Input Parameters from bdCtx:
573: + numBD - The number of closed boundaries in the geometry, or different markers
574: . numVertices - The umber of boundary points
575: . vertices - The (x,y) coordinates of the boundary points
576: . markers - The boundary markers for nodes, 0 indicates an interior point, each boundary must have a different marker
578: Level: advanced
580: .keywords: mesh, boundary
581: .seealso: MeshSetBoundary(), MeshSetReformBoundary()
582: */
583: static int MeshCheckBoundary_Triangular_1D(Mesh mesh, MeshBoundary2D *bdCtx) {
584: int rank;
589: MPI_Comm_rank(mesh->comm, &rank);
590: if (rank == 0) {
591: if (bdCtx->numBd != bdCtx->numVertices) {
592: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "All boundaries must be points: %d != %d", bdCtx->numBd, bdCtx->numVertices);
593: }
594: if ((bdCtx->numVertices != 0) && (bdCtx->numVertices != 2)) {
595: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of boundary points %d", bdCtx->numVertices);
596: }
597: if (bdCtx->numVertices > 0) {
600: }
601: }
602: return(0);
603: }
605: /*
606: MeshCheckBoundary_Triangular_2D - Checks a boundary for validity.
608: Collective on Mesh
610: Input Parameter:
611: . mesh - The mesh
613: Input Parameters from bdCtx:
614: + numBD - The number of closed boundaries in the geometry, or different markers
615: . numVertices - The umber of boundary points
616: . vertices - The (x,y) coordinates of the boundary points
617: . markers - The boundary markers for nodes, 0 indicates an interior point, each boundary must have a different marker
618: . numSegments - The number of boundary segments
619: . segments - The endpoints of boundary segments or PETSC_NULL
620: . segMarkers - The boundary markers for each segment
621: . numHoles - The number of holes
622: - holes - The (x,y) coordinates of holes or PETSC_NULL
624: Level: advanced
626: .keywords: mesh, boundary
627: .seealso: MeshSetBoundary(), MeshSetReformBoundary()
628: */
629: static int MeshCheckBoundary_Triangular_2D(Mesh mesh, MeshBoundary2D *bdCtx) {
630: int rank;
635: MPI_Comm_rank(mesh->comm, &rank);
636: if (rank == 0) {
637: if (bdCtx->numVertices < 3) {
638: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Insufficient number of boundary points %d", bdCtx->numVertices);
639: }
640: if (bdCtx->numSegments < 3) {
641: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of boundary segments %d", bdCtx->numSegments);
642: }
643: if (bdCtx->numHoles < 0) {
644: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of holes %d", bdCtx->numHoles);
645: }
646: if (bdCtx->numVertices > 0) {
649: }
650: if (bdCtx->numSegments > 0) {
653: }
654: if (bdCtx->numHoles > 0) {
656: }
657: }
658: return(0);
659: }
661: /*@
662: MeshCheckBoundary - Checks the mesh boundary for validity.
664: Collective on Mesh
666: Input Parameters:
667: + mesh - The mesh
668: - bdCtx - The MeshBoundary
670: Level: intermediate
672: .keywords: mesh, partition
673: .seealso: MeshSetBoundary(), MeshSetReformBoundary()
674: @*/
675: int MeshCheckBoundary(Mesh mesh, MeshBoundary2D *bdCtx) {
680: /* This needs to go in MeshBoundary later */
681: if (mesh->dim == 1) {
682: MeshCheckBoundary_Triangular_1D(mesh, bdCtx);
683: } else if (mesh->dim == 2) {
684: MeshCheckBoundary_Triangular_2D(mesh, bdCtx);
685: } else {
686: SETERRQ(PETSC_ERR_ARG_WRONG, "Mehs dimension has to be set in order to validate boundary");
687: }
688: return(0);
689: }
691: /*@
692: MeshSetBoundary - Store a boundary to use for mesh generation.
694: Not collective
696: Input Parameters:
697: + mesh - The mesh
698: - bdCtx - The MeshBoundary
700: Level: intermediate
702: .keywords: mesh, boundary, refinement
703: .seealso: MeshReform()
704: @*/
705: int MeshSetBoundary(Mesh mesh, MeshBoundary2D *bdCtx) {
711: MeshCheckBoundary(mesh, bdCtx);
712: mesh->bdCtx = bdCtx;
713: return(0);
714: }
716: /*@
717: MeshSetReformBoundary - Store an alternate boundary to use for reforming.
719: Not collective
721: Input Parameters:
722: + mesh - The mesh
723: - bdCtx - The MeshBoundary
725: Level: intermediate
727: .keywords: mesh, boundary, refinement
728: .seealso: MeshReform()
729: @*/
730: int MeshSetReformBoundary(Mesh mesh, MeshBoundary2D *bdCtx) {
736: MeshCheckBoundary(mesh, bdCtx);
737: mesh->bdCtxNew = bdCtx;
738: return(0);
739: }
741: /*@
742: MeshPartition - Partitions the mesh among the processors
744: Collective on Mesh
746: Input Parameter:
747: . mesh - the mesh
749: Level: beginner
751: .keywords: mesh, partition
752: .seealso: MeshGetBoundaryStart()
753: @*/
754: int MeshPartition(Mesh mesh)
755: {
760: PetscLogEventBegin(MESH_Partition, mesh, 0, 0, 0);
761: (*mesh->ops->partition)(mesh);
762: PetscLogEventEnd(MESH_Partition, mesh, 0, 0, 0);
763: MeshUpdateBoundingBox(mesh);
764: return(0);
765: }
766:
767: /*@
768: MeshCoarsen - Coarsen a mesh based on area constraints.
770: Collective on Mesh
772: Input Parameters:
773: + mesh - The initial mesh
774: - area - A function which gives an area constraint when evaluated inside an element
776: Output Parameter:
777: . newmesh - The coarse mesh
779: Note:
780: If PETSC_NULL is used for the 'area' argument, then the mesh consisting only of vertices
781: is returned.
783: Level: beginner
785: .keywords: mesh, coarsening
786: .seealso: MeshRefine(), MeshDestroy()
787: @*/
788: int MeshCoarsen(Mesh mesh, PointFunction area, Mesh *newmesh)
789: {
795: if (mesh->ops->coarsen == PETSC_NULL) SETERRQ(PETSC_ERR_SUP, " ");
796: MeshPreCopy_Private(mesh);
797: (*mesh->ops->coarsen)(mesh, area, newmesh);
798: MeshPostCopy_Private(mesh, *newmesh);
799: return(0);
800: }
801:
802: /*@
803: MeshRefine - Refine a mesh based on area constraints.
805: Input Parameters:
806: + mesh - The initial mesh
807: - area - A function which gives an area constraint when evaluated inside an element
809: Output Parameter:
810: . newmesh - The refined mesh
812: Level: beginner
814: .keywords: mesh, refinement
815: .seealso: MeshCoarsen(), MeshDestroy()
816: @*/
817: int MeshRefine(Mesh mesh, PointFunction area, Mesh *newmesh)
818: {
824: if (mesh->ops->refine == PETSC_NULL) SETERRQ(PETSC_ERR_SUP, " ");
825: MeshPreCopy_Private(mesh);
826: (*mesh->ops->refine)(mesh, area, newmesh);
827: MeshPostCopy_Private(mesh, *newmesh);
828: return(0);
829: }
831: /*@
832: MeshResetNodes - Using the vertex and edge structure, move auxilliary nodes back to
833: their default positions.
835: Input Parameters:
836: + mesh - The mesh
837: - resetBd - The flag which indicates whether boundaries should also be reset
839: Note:
840: This function was developed to allow midnodes to be moved back onto the edges
841: with which they were associated. Midnodes on edges between nodes on the same
842: boundary are only reset if resetBd == PETSC_TRUE (to allow for curved boundaries).
844: Level: advanced
846: .keywords: mesh, reset, node
847: .seealso: MeshReform(), MeshSetBounday()
848: @*/
849: int MeshResetNodes(Mesh mesh, PetscTruth resetBd)
850: {
855: if (!mesh->ops->resetnodes) {
856: SETERRQ(PETSC_ERR_SUP, "Not supported by this Mesh object");
857: }
858: (*mesh->ops->resetnodes)(mesh, resetBd);
859: return(0);
860: }
862: /*@
863: MeshSaveMesh - This function saves the mesh coordinates.
865: Collective on Mesh
867: Input Parameter:
868: . mesh - The mesh
870: Level: advanced
872: Note:
873: This function is meant to be used in conjuction with MeshMoveMesh(),
874: and MeshRestoreMesh() so that the mesh may be moved, checked for
875: distortion, and if necessary moved back.
877: .keywords: mesh, movement
878: .seealso: MeshMoveMesh(), MeshRestoreMesh()
879: @*/
880: int MeshSaveMesh(Mesh mesh) {
885: (*mesh->ops->savemesh)(mesh);
886: return(0);
887: }
889: /*@
890: MeshRestoreMesh - This function restores the mesh coordinates which were
891: previously saved.
893: Collective on Mesh
895: Input Parameter:
896: . mesh - The mesh
898: Level: advanced
900: Note:
901: This function is meant to be used in conjuction with MeshMoveMesh(),
902: and MeshRestoreMesh() so that the mesh may be moved, checked for
903: distortion, and if necessary moved back.
905: .keywords: mesh, movement
906: .seealso: MeshMoveMesh(), MeshSaveMesh()
907: @*/
908: int MeshRestoreMesh(Mesh mesh) {
913: (*mesh->ops->restoremesh)(mesh);
914: return(0);
915: }
917: /*@
918: MeshIsDistorted - This function checks for more than the maximum
919: level of distortion in the mesh. It also returns an error when
920: encountering elements with negative area.
922: Collective on Mesh
924: Input Parameter:
925: . mesh - The mesh
927: Output Parameter:
928: . flag - Signals a distorted mesh
930: Level: intermediate
932: .keywords: mesh, distortion, movement
933: .seealso: MeshMoveMesh()
934: @*/
935: int MeshIsDistorted(Mesh mesh, PetscTruth *flag) {
941: PetscLogEventBegin(MESH_IsDistorted, mesh, 0, 0, 0);
942: /* Do not use CHKERRQ since we want the return value at the top level */
943: (*mesh->ops->isdistorted)(mesh, flag);
944: PetscLogEventEnd(MESH_IsDistorted, mesh, 0, 0, 0);
945: PetscFunctionReturn(ierr);
946: }