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: }