Actual source code: meshMovement.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: meshMovement.c,v 1.19 2000/10/17 13:48:57 knepley Exp $";
  3: #endif

  5: #include "src/gvec/meshMovementImpl.h" /*I "meshMovement.h" I*/
  6: #include "src/grid/gridimpl.h"    /*I "grid.h" I*//*I "gvec.h" I*/

  8: extern int MeshPreCopy_Private(Mesh);
  9: extern int MeshPostCopy_Private(Mesh, Mesh);

 11: /*-------------------------------------------------- Mesh Functions --------------------------------------------------*/
 12: /*@
 13:   MeshSetMover - This function provides the MeshMover object for this mesh.

 15:   Not collective

 17:   Input Parameters:
 18: + mesh  - The mesh
 19: - mover - The mover, or PETSC_NULL

 21:   Level: intermediate

 23: .keywords: Mesh, movement, mover
 24: .seealso: MeshGetMover(), MeshSetMovement()
 25: @*/
 26: int MeshSetMover(Mesh mesh, MeshMover mover) {

 31:   PetscObjectCompose((PetscObject) mesh, "MeshMover", (PetscObject) mover);
 32:   if (mover != PETSC_NULL) {
 34:     PetscObjectDereference((PetscObject) mover);
 35:     MeshMoverSetMesh(mover, mesh);
 36:   }
 37:   return(0);
 38: }

 40: /*@
 41:   MeshGetMover - This function returns the MeshMover object for this mesh.

 43:   Not collective

 45:   Input Parameter:
 46: . mesh  - The mesh

 48:   Output Parameters:
 49: . mover - The mover, or PETSC_NULL if it does not exist

 51:   Level: intermediate

 53: .keywords: Mesh, movement, mover
 54: .seealso: MeshSetMover(), MeshGetMovement()
 55: @*/
 56: int MeshGetMover(Mesh mesh, MeshMover *mover) {

 61:   PetscObjectQuery((PetscObject) mesh, "MeshMover", (PetscObject *) mover);
 62:   return(0);
 63: }

 65: /*@
 66:   MeshMoveMesh - Recalculates the node coordinates based on the
 67:   current velocities and accelerations.

 69:   Collective on Mesh

 71:   Input Parameters:
 72: . mesh - The mesh
 73: . dt   - The timestep

 75:   Level: advanced

 77: .keywords: mesh, movement
 78: .seealso: MeshCalcNodeVelocitiess(), MeshCalcNodeAccelerations()
 79: @*/
 80: int MeshMoveMesh(Mesh mesh, double dt)
 81: {
 82:   MeshMover  mover;
 83:   PetscTruth isMoving;
 84:   int        ierr;


 89:   MeshGetMovement(mesh, &isMoving);
 90:   if (isMoving == PETSC_FALSE) return(0);
 91:   PetscLogEventBegin(MESH_MoveMesh, mesh, 0, 0, 0);
 92:   MeshGetMover(mesh, &mover);
 93:   (*mover->ops->movemesh)(mover, dt);
 94:   PetscLogEventEnd(MESH_MoveMesh, mesh, 0, 0, 0);
 95:   return(0);
 96: }

 98: /*@
 99:   MeshUpdateNodeValues - Updates the mesh velocity, acceleration, or any other node-based quantity.

101:   Collective on Mesh

103:   Input Parameters:
104: + mesh     - The mesh
105: - sol      - The solution to an auxilliary problem

107:   Output Parameters:
108: + vec      - The vector which will hold he solution
109: - ghostVec - The corresponding ghost vector for vec

111:   Level: developer

113: .keywords: mesh, movement
114: .seealso: MeshMoverSetNodeVelocities()
115: @*/
116: int MeshUpdateNodeValues(Mesh mesh, GVec sol, Vec vec, Vec ghostVec)
117: {
118:   MeshMover mover;
119:   int       ierr;

126:   MeshGetMover(mesh, &mover);
127:   (*mover->ops->updatenodevalues)(mover, sol, vec, ghostVec);
128:   return(0);
129: }

131: EXTERN_C_BEGIN
132: /*
133:   MeshPostReform_Private - Create a suitable MeshMover after reforming a Mesh.

135:   Collective on Mesh

137:   Input Parameters:
138: + mesh    - The mesh
139: - newMesh - The reformed mesh

141:   Level: developer

143: .keywords: mesh, refine, reform
144: .seealso: MeshReform()
145: */
146: int MeshPostReform_Private(Mesh mesh, Mesh newMesh)
147: {
148:   MeshMover mover, newMover;
149:   int       ierr;

154:   MeshGetMover(mesh, &mover);
155:   if (mover != PETSC_NULL) {
156:     MeshMoverConvert(mover, newMesh, &newMover);
157:   }
158:   return(0);
159: }
160: EXTERN_C_END

162: /*@
163:   MeshReform - Reform a mesh using the original boundary.

165:   Collective on Mesh

167:   Input Parameters:
168: + mesh    - The previous mesh
169: . refine  - Flag indicating whether to refine or recreate the mesh
170: . area    - A function which gives an area constraint when evaluated inside an element
171: - newBd   - Flag to determine whether the boundary should be generated (PETSC_TRUE) or taken from storage

173:   Output Parameter:
174: . newMesh - The new mesh

176:   Level: beginner

178: .keywords: mesh, refinement, reform
179: .seealso: MeshReform(), MeshSetBoundary()
180: @*/
181: int MeshReform(Mesh mesh, PetscTruth refine, PointFunction area, PetscTruth newBd, Mesh *newMesh)
182: {
183:   PetscObject obj = (PetscObject) mesh;
184:   Mesh        refinedMesh;
185:   MeshMover   mover;
186:   PetscReal   maxArea, startX, endX, startY, endY;
187:   void       *tempCtx;
188:   int         ierr;

193:   PetscObjectComposeFunction(obj, "PostCopy", "MeshPostReform_Private", (void (*)(void)) MeshPostReform_Private);
194:   if (refine == PETSC_TRUE) {
195:     /* Refine grid with tolerance equal to the entire size
196:        This just "flips" the current mesh and does the necessary point insertion
197:     */
198:     MeshGetBoundingBox(mesh, &startX, &startY, PETSC_NULL, &endX, &endY, PETSC_NULL);
199:     maxArea = (endX - startX)*(endY - startY);
200:     MeshGetUserContext(mesh, &tempCtx);
201:     MeshSetUserContext(mesh, (void *) &maxArea);
202:     MeshRefine(mesh, PointFunctionConstant, newMesh);
203:     MeshSetUserContext(mesh, tempCtx);
204:     MeshSetUserContext(*newMesh, tempCtx);
205:   } else {
206:     MeshGetMover(mesh, &mover);
207:     if (mover->ops->reform == PETSC_NULL) SETERRQ(PETSC_ERR_SUP, " ");
208:     PetscLogEventBegin(MESH_Reform, mesh, 0, 0, 0);
209:     MeshPreCopy_Private(mesh);
210:     (*mover->ops->reform)(mesh, refine, area, newBd, newMesh);
211:     MeshPostCopy_Private(mesh, *newMesh);
212:     PetscLogEventEnd(MESH_Reform, mesh, 0, 0, 0);
213:   }

215:   /* Refine new mesh if necessary */
216:   if (area != PETSC_NULL) {
218:     PetscObjectComposeFunction((PetscObject) *newMesh, "PostCopy", "MeshPostReform_Private", (void (*)(void)) MeshPostReform_Private);
219:     MeshRefine(*newMesh, area, &refinedMesh);
220:     MeshDestroy(*newMesh);
221:     *newMesh = refinedMesh;
222:     PetscObjectComposeFunction((PetscObject) *newMesh, "PostCopy", "", PETSC_NULL);
223:   }
224:   PetscObjectComposeFunction(obj, "PostCopy", "", PETSC_NULL);

226:   return(0);
227: }

229: /*----------------------------------------------- MeshMover Functions ------------------------------------------------*/
230: /*@ 
231:   MeshMoverCreate - This function creates an empty mesh mover.

233:   Collective on Mesh

235:   Input Parameter:
236: . mesh  - The Mesh to be moved

238:   Output Parameter:
239: . mover - The mover

241:   Level: beginner

243: .keywords: Mesh, create, mover
244: .seealso: MeshSetUp(), MeshDestroy(), GridCreate()
245: @*/
246: int MeshMoverCreate(Mesh mesh, MeshMover *mover) {
247:   MeshMover m;
248:   MPI_Comm  comm;
249:   int       ierr;

253:   *mover = PETSC_NULL;

255:   PetscObjectGetComm((PetscObject) mesh, &comm);
256:   PetscHeaderCreate(m, _MeshMover, struct _MeshMoverOps, MESH_COOKIE, -1, "MeshMover", comm, MeshMoverDestroy, MeshMoverView);
257:   PetscLogObjectCreate(m);
258:   PetscLogObjectMemory(m, sizeof(struct _MeshMover));
259:   PetscMemzero(m->ops, sizeof(struct _MeshMoverOps));
260:   m->bops->publish  = PETSC_NULL /* MeshMoverPublish_Petsc */;
261:   m->type_name      = PETSC_NULL;
262:   m->serialize_name = PETSC_NULL;

264:   m->meshVelocityMethod      = MESH_LAPLACIAN;
265:   m->meshVelocityGrid        = PETSC_NULL;
266:   m->nodeVelocities          = PETSC_NULL;
267:   m->nodeVelocitiesGhost     = PETSC_NULL;
268:   m->meshVelocityMat         = PETSC_NULL;
269:   m->meshVelocityRhs         = PETSC_NULL;
270:   m->meshVelocitySol         = PETSC_NULL;
271:   m->meshVelocitySles        = PETSC_NULL;
272:   m->meshAccelerationMethod  = MESH_LAPLACIAN;
273:   m->meshAccelerationGrid    = PETSC_NULL;
274:   m->nodeAccelerations       = PETSC_NULL;
275:   m->nodeAccelerationsGhost  = PETSC_NULL;
276:   m->meshAccelerationMat     = PETSC_NULL;
277:   m->meshAccelerationRhs     = PETSC_NULL;
278:   m->meshAccelerationSol     = PETSC_NULL;
279:   m->meshAccelerationSles    = PETSC_NULL;
280:   m->meshVelocityScatter     = PETSC_NULL;
281:   m->movingMeshViewer        = PETSC_NULL;
282:   m->movingMeshViewerCaption = "Moving Mesh";
283:   m->movingMeshCtx           = PETSC_NULL;

285:   MeshSetMover(mesh, m);
286:   *mover = m;
287:   return(0);
288: }

290: /*@
291:   MeshMoverSetup - Creates all the necessary structures for mesh movement.

293:   Collective on MeshMover

295:   Input Parameter:
296: . mover - The mover

298:   Note:
299:   This function should be called directly before beginning the
300:   calculation, and after all options have been set. It is
301:   normally called automatically by the solver.

303:   Level: advanced

305: .keywords: mesh, movement
306: .seealso: MeshMoverGetMovement()
307: @*/
308: int MeshMoverSetup(MeshMover mover)
309: {
310:   Mesh       mesh;
311:   Partition  part;
312:   IS         globalIS, localIS;
313:   int        dim;
314:   int       *indices;
315:   int        numNodes, numOverlapNodes;
316:   int        node, gNode, j;
317:   PetscTruth reduceVel, reduceAcc;
318:   PetscTruth opt;
319:   int        ierr;

323:   /* Destroy old structures */
324:   if (mover->nodeVelocities != PETSC_NULL) {
325:     VecDestroy(mover->nodeVelocities);
326:     VecDestroy(mover->nodeVelocitiesGhost);
327:   }
328:   if (mover->meshVelocityGrid != PETSC_NULL) {
329:     GridDestroy(mover->meshVelocityGrid);
330:     mover->meshVelocityGrid = PETSC_NULL;
331:     GMatDestroy(mover->meshVelocityMat);
332:     mover->meshVelocityMat  = PETSC_NULL;
333:     GVecDestroy(mover->meshVelocityRhs);
334:     mover->meshVelocityRhs  = PETSC_NULL;
335:     GVecDestroy(mover->meshVelocitySol);
336:     mover->meshVelocitySol  = PETSC_NULL;
337:     SLESDestroy(mover->meshVelocitySles);
338:     mover->meshVelocitySles = PETSC_NULL;
339:   }
340:   if (mover->nodeAccelerations != PETSC_NULL) {
341:     VecDestroy(mover->nodeAccelerations);
342:     VecDestroy(mover->nodeAccelerationsGhost);
343:   }
344:   if (mover->meshAccelerationGrid != PETSC_NULL) {
345:     GridDestroy(mover->meshAccelerationGrid);
346:     mover->meshAccelerationGrid = PETSC_NULL;
347:     GMatDestroy(mover->meshAccelerationMat);
348:     mover->meshAccelerationMat  = PETSC_NULL;
349:     GVecDestroy(mover->meshAccelerationRhs);
350:     mover->meshAccelerationRhs  = PETSC_NULL;
351:     GVecDestroy(mover->meshAccelerationSol);
352:     mover->meshAccelerationSol  = PETSC_NULL;
353:     SLESDestroy(mover->meshAccelerationSles);
354:     mover->meshAccelerationSles = PETSC_NULL;
355:   }
356:   if (mover->meshVelocityScatter != PETSC_NULL) {
357:     VecScatterDestroy(mover->meshVelocityScatter);
358:   }
359:   /* Determine solution method */
360:   ierr  = PetscOptionsHasName(mover->prefix, "-mesh_move_lap", &opt);
361:   if (opt == PETSC_TRUE) {
362:     mover->meshVelocityMethod     = MESH_LAPLACIAN;
363:     mover->meshAccelerationMethod = MESH_LAPLACIAN;
364:   }
365:   ierr  = PetscOptionsHasName(mover->prefix, "-mesh_move_weighted_lap", &opt);
366:   if (opt == PETSC_TRUE) {
367:     mover->meshVelocityMethod     = MESH_WEIGHTED_LAPLACIAN;
368:     mover->meshAccelerationMethod = MESH_WEIGHTED_LAPLACIAN;
369:   }
370:   /* Setup mesh node velocities vector */
371:   MeshMoverGetMesh(mover, &mesh);
372:   MeshGetPartition(mesh, &part);
373:   MeshGetDimension(mesh, &dim);
374:   MeshGetInfo(mesh, PETSC_NULL, &numNodes, PETSC_NULL, PETSC_NULL);
375:   VecCreateMPI(mover->comm, numNodes*dim, PETSC_DECIDE, &mover->nodeVelocities);
376:   PartitionGetNumOverlapNodes(part, &numOverlapNodes);
377:   VecCreateSeq(PETSC_COMM_SELF, numOverlapNodes*dim, &mover->nodeVelocitiesGhost);
378:   /* Setup mesh node accelerations vector */
379:   VecCreateMPI(mover->comm, numNodes*dim, PETSC_DECIDE, &mover->nodeAccelerations);
380:   VecCreateSeq(PETSC_COMM_SELF, numOverlapNodes*dim, &mover->nodeAccelerationsGhost);
381:   /* Setup grids and other implementation specific stuff */
382:   (*mover->ops->setup)(mover);
383:   /* Setup scatter from node values vector to ghost vector */
384:   ISCreateStride(mover->comm, numOverlapNodes*dim, 0, 1, &localIS);
385:   PetscMalloc(numOverlapNodes*dim * sizeof(int), &indices);
386:   for(node = 0; node < numOverlapNodes; node++) {
387:     PartitionLocalToGlobalNodeIndex(part, node, &gNode);
388:     for(j = 0; j < dim; j++)
389:       indices[node*dim+j] = gNode*dim+j;
390:   }
391:   ISCreateGeneral(mover->comm, numOverlapNodes*dim, indices, &globalIS);
392:   VecScatterCreate(mover->nodeVelocities, globalIS, mover->nodeVelocitiesGhost, localIS, &mover->meshVelocityScatter);
393: 
394:   ISDestroy(localIS);
395:   ISDestroy(globalIS);
396:   PetscFree(indices);
397:   /* Setup viewer */
398:   PetscOptionsHasName(mover->prefix, "-mesh_moving_view", &opt);
399:   if ((opt == PETSC_TRUE) && (mover->movingMeshViewer == PETSC_NULL)) {
400:     mover->movingMeshViewer = PETSC_VIEWER_STDOUT_WORLD;
401:   }
402:   PetscOptionsHasName(mover->prefix, "-mesh_moving_view_draw", &opt);
403:   if ((opt == PETSC_TRUE) && (mover->movingMeshViewer == PETSC_NULL)) {
404:     PetscReal startX, startY, endX, endY, sizeX, sizeY;
405:     int       xsize, ysize;

407:     ierr  = MeshGetBoundingBox(mesh, &startX, &startY, 0, &endX, &endY, 0);
408:     sizeX = endX - startX;
409:     sizeY = endY - startY;
410:     if (sizeX > sizeY) {
411:       ysize  = 300;
412:       xsize  = ysize * (int) (sizeX/sizeY);
413:     } else {
414:       xsize  = 300;
415:       ysize  = xsize * (int) (sizeY/sizeX);
416:     }
417:     PetscViewerDrawOpen(mover->comm, 0, 0, 0, 315, xsize, ysize, &mover->movingMeshViewer);
418:   }
419:   /* Check grids */
420:   GridGetReduceSystem(mover->meshVelocityGrid,     &reduceVel);
421:   GridGetReduceSystem(mover->meshAccelerationGrid, &reduceAcc);
422:   if (reduceVel != reduceAcc) {
423:     SETERRQ(PETSC_ERR_ARG_WRONG, "Velocity and acceleration grids must have same BC reduction");
424:   }
425:   return(0);
426: }

428: /*
429:   MeshMoverSetTypeFromOptions - Sets the type of mesh movement from user options.

431:   Collective on MeshMover

433:   Input Parameter:
434: . mover - The mover

436:   Level: intermediate

438: .keywords: MeshMover, set, options, database, type
439: .seealso: MeshMoverSetFromOptions(), MeshMoverSetType()
440: */
441: static int MeshMoverSetTypeFromOptions(MeshMover mover)
442: {
443:   Mesh       mesh;
444:   PetscTruth opt;
445:   char      *defaultType;
446:   char       typeName[256];
447:   int        dim;
448:   int        ierr;

451:   MeshMoverGetMesh(mover, &mesh);
452:   MeshGetDimension(mesh, &dim);
453:   if (mover->type_name != PETSC_NULL) {
454:     defaultType = mover->type_name;
455:   } else {
456:     switch(dim)
457:     {
458:     case 2:
459:       defaultType = MESH_TRIANGULAR_2D;
460:       break;
461:     default:
462:       SETERRQ1(PETSC_ERR_SUP, "MeshMover dimension %d is not supported", dim);
463:     }
464:   }

466:   if (!MeshMoverRegisterAllCalled) {
467:     MeshMoverRegisterAll(PETSC_NULL);
468:   }
469:   PetscOptionsList("-mesh_mover_type", "Mesh movement method", "MeshMoverSetType", MeshMoverList, defaultType, typeName, 256, &opt);
470: 
471:   if (opt == PETSC_TRUE) {
472:     MeshMoverSetType(mover, typeName);
473:   } else {
474:     MeshMoverSetType(mover, defaultType);
475:   }
476:   return(0);
477: }

479: /*@
480:   MeshMoverSetFromOptions - Sets various MeshMover parameters from user options.

482:   Collective on MeshMover

484:   Input Parameter:
485: . mover - The mover

487:   Notes:  To see all options, run your program with the -help option, or consult the users manual.
488:           Must be called after MeshMoverCreate() but before the vector is used.

490:   Level: intermediate

492: .keywords: MeshMover, set, options, database
493: .seealso: MeshMoverCreate(), MeshMoverPrintHelp(), MeshMoverSetOptionsPrefix()
494: @*/
495: int MeshMoverSetFromOptions(MeshMover mover)
496: {
497:   PetscTruth opt;
498:   int        ierr;

502:   PetscOptionsBegin(mover->comm, mover->prefix, "MeshMover options", "MeshMover");

504:   /* Handle generic mesh options */
505:   PetscOptionsHasName(PETSC_NULL, "-help", &opt);
506:   if (opt == PETSC_TRUE) {
507:     MeshMoverPrintHelp(mover);
508:   }

510:   /* Handle mesh type options */
511:   MeshMoverSetTypeFromOptions(mover);

513:   /* Handle specific mesh options */
514:   if (mover->ops->setfromoptions != PETSC_NULL) {
515:     (*mover->ops->setfromoptions)(mover);
516:   }

518:   PetscOptionsEnd();

520:   /* Handle subobject options */
521:   return(0);
522: }

524: /*@
525:   MeshMoverPrintHelp - Prints all options for the MeshMover.

527:   Input Parameter:
528: . mover - The mover

530:   Options Database Keys:
531: $  -help, -h

533:   Level: intermediate

535: .keywords: MeshMover, help
536: .seealso: MeshMoverSetFromOptions()
537: @*/
538: int MeshMoverPrintHelp(MeshMover mover)
539: {
540:   char p[64];
541:   int  ierr;


546:   PetscStrcpy(p, "-");
547:   if (mover->prefix != PETSC_NULL) {
548:     PetscStrcat(p, mover->prefix);
549:   }

551:   (*PetscHelpPrintf)(mover->comm, "MeshMover options ------------------------------------------------n");
552:   (*PetscHelpPrintf)(mover->comm,"   %smesh_mover_type <typename> : Sets the mesh movement typen", p);
553:   return(0);
554: }

556: /*@
557:   MeshMoverDuplicate - This function returns an identical MeshMover.

559:   Not collective

561:   Input Parameter:
562: . mover    - The mover

564:   Output Parameter:
565: . newMover - The new mover

567:   Level: intermediate

569: .keywords: Mesh, movement, mover
570: .seealso: MeshMoverCopy()
571: @*/
572: int MeshMoverDuplicate(MeshMover mover, MeshMover *newMover) {
573:   Mesh mesh;
574:   int  ierr;

577:   MeshMoverGetMesh(mover, &mesh);
578:   MeshMoverConvert(mover, mesh, newMover);
579:   return(0);
580: }

582: /*@
583:   MeshMoverConvert - This function returns an identical MeshMover on the new Mesh.

585:   Not collective

587:   Input Parameters:
588: + mover   - The mover
589: - newMesh - The new Mesh

591:   Output Parameter:
592: . newMover - The new mover

594:   Level: intermediate

596: .keywords: Mesh, movement, mover
597: .seealso: MeshMoverCopy()
598: @*/
599: int MeshMoverConvert(MeshMover mover, Mesh newMesh, MeshMover *newMover) {
600:   MeshMover m;
601:   Mesh      mesh;
602:   int       ierr;

605:   MeshMoverGetMesh(mover, &mesh);
606:   if (mesh == newMesh) {
607:     /* Need to play reference games since MeshMoverCreate automatically sets it in the Mesh */
608:     PetscObjectReference((PetscObject) mover);
609:     MeshMoverCreate(newMesh, &m);
610:     PetscObjectReference((PetscObject) m);
611:     MeshSetMover(mesh, mover);
612:   } else {
613:     MeshMoverCreate(newMesh, &m);
614:   }

616:   MeshMoverSetFromOptions(m);
617:   m->meshVelocityMethod      = mover->meshVelocityMethod;
618:   m->meshAccelerationMethod  = mover->meshAccelerationMethod;
619:   m->movingMeshViewer        = mover->movingMeshViewer;
620:   if (mover->movingMeshViewer != PETSC_NULL) PetscObjectReference((PetscObject)  mover->movingMeshViewer);
621:   m->movingMeshViewerCaption = mover->movingMeshViewerCaption;
622:   m->movingMeshCtx           = mover->movingMeshCtx;
623:   MeshMoverSetup(m);
624:   GridDuplicateBC(mover->meshVelocityGrid,     m->meshVelocityGrid);
625:   GridDuplicateBC(mover->meshAccelerationGrid, m->meshAccelerationGrid);
626:   *newMover = m;
627:   return(0);
628: }

630: /*@
631:   MeshMoverView - Views a mesh mover object.

633:   Collective on MeshMover

635:   Input Parameters:
636: + mover  - The mover
637: - viewer - The viewer with which to view the mesh mover

639:   Level: beginner

641: .keywords: mesh, view, mover
642: .seealso: MeshMoverDestroy(), PetscViewerDrawOpen()
643: @*/
644: int MeshMoverView(MeshMover mover, PetscViewer viewer)
645: {
648:   if (viewer == PETSC_NULL) {
649:     viewer = PETSC_VIEWER_STDOUT_SELF;
650:   } else {
652:   }
653:   return(0);
654: }

656: /*@
657:   MeshMoverDestroy - Destroys a mesh mover object.

659:   Collective on MeshMover

661:   Input Parameter:
662: . mover - The mover

664:   Level: beginner

666: .keywords: mesh, destroy, mover
667: .seealso MeshMoverCreate()
668: @*/
669: int MeshMoverDestroy(MeshMover mover) {

674:   if (--mover->refct > 0) return(0);

676:   if (mover->nodeVelocities != PETSC_NULL) {
677:     GVecDestroy(mover->nodeVelocities);
678:     GVecDestroy(mover->nodeVelocitiesGhost);
679:   }
680:   if (mover->meshVelocitySles != PETSC_NULL) {
681:     GMatDestroy(mover->meshVelocityMat);
682:     GVecDestroy(mover->meshVelocityRhs);
683:     GVecDestroy(mover->meshVelocitySol);
684:     SLESDestroy(mover->meshVelocitySles);
685:   }
686:   if (mover->meshVelocityGrid != PETSC_NULL) {
687:     GridFinalizeBC(mover->meshVelocityGrid);
688:     GridDestroy(mover->meshVelocityGrid);
689:   }
690:   if (mover->nodeAccelerations != PETSC_NULL) {
691:     GVecDestroy(mover->nodeAccelerations);
692:     GVecDestroy(mover->nodeAccelerationsGhost);
693:   }
694:   if (mover->meshAccelerationSles != PETSC_NULL) {
695:     GMatDestroy(mover->meshAccelerationMat);
696:     GVecDestroy(mover->meshAccelerationRhs);
697:     GVecDestroy(mover->meshAccelerationSol);
698:     SLESDestroy(mover->meshAccelerationSles);
699:   }
700:   if (mover->meshAccelerationGrid != PETSC_NULL) {
701:     GridFinalizeBC(mover->meshAccelerationGrid);
702:     GridDestroy(mover->meshAccelerationGrid);
703:   }
704:   if (mover->meshVelocityScatter != PETSC_NULL) {
705:     VecScatterDestroy(mover->meshVelocityScatter);
706:   }
707:   if (mover->movingMeshViewer != PETSC_NULL) {
708:     PetscViewerDestroy(mover->movingMeshViewer);
709:   }

711:   (*mover->ops->destroy)(mover);

713:   PetscLogObjectDestroy(mover);
714:   PetscHeaderDestroy(mover);
715:   return(0);
716: }

718: /*@
719:   MeshMoverSetMesh - This function returns the associated Mesh.

721:   Not collective

723:   Input Parameter:
724: . mover - The mover

726:   Output Parameter:
727: . mesh  - The mesh, or PETSC_NULL if it does not exist

729:   Level: intermediate

731: .keywords: Mesh, movement, mover
732: .seealso: MeshSetMover()
733: @*/
734: int MeshMoverSetMesh(MeshMover mover, Mesh mesh) {
738:   mover->mesh = mesh;
739:   return(0);
740: }

742: /*@
743:   MeshMoverGetMesh - This function returns the associated Mesh.

745:   Not collective

747:   Input Parameter:
748: . mover - The mover

750:   Output Parameter:
751: . mesh  - The mesh, or PETSC_NULL if it does not exist

753:   Level: intermediate

755: .keywords: Mesh, movement, mover
756: .seealso: MeshGetMover()
757: @*/
758: int MeshMoverGetMesh(MeshMover mover, Mesh *mesh) {
762:   *mesh = mover->mesh;
763:   return(0);
764: }

766: /*@
767:   MeshMoverGetMovement - Returns the type of mesh movement calculation.

769:   Not collective

771:   Input Parameter:
772: . mover - The mover

774:   Output Parameters:
775: + vtype - The type of mesh velocity calculation, like MESH_LAPLACIAN
776: . atype - The type of mesh acceleration calculation, like MESH_LAPLACIAN
777: - ctx   - A user context

779:   Level: intermediate

781: .keywords: mesh, movement
782: .seealso: MeshMoverSetMovement()
783: @*/
784: int MeshMoverGetMovement(MeshMover mover, MeshSolveMethod *vtype, MeshSolveMethod *atype, PetscObject *ctx)
785: {
788:   if (vtype != PETSC_NULL) {
790:     *vtype = mover->meshVelocityMethod;
791:   }
792:   if (atype != PETSC_NULL) {
794:     *atype = mover->meshAccelerationMethod;
795:   }
796:   if (ctx   != PETSC_NULL) {
798:     *ctx   = mover->movingMeshCtx;
799:   }
800:   return(0);
801: }

803: /*@
804:   MeshMoverSetMovement - Determines the type of mesh mvoement calculation

806:   Collective on MeshMover

808:   Input Parameters:
809: + mover  - The mover
810: . vtype  - The type of mesh velocity calculation, like MESH_LAPLACIAN
811: . atype  - The type of mesh acceleration calculation, like MESH_LAPLACIAN
812: - ctx    - A user context

814:   Level: intermediate

816: .keywords: mesh, movement
817: .seealso: MeshMoverGetMovement()
818: @*/
819: int MeshMoverSetMovement(MeshMover mover, MeshSolveMethod vtype, MeshSolveMethod atype, PetscObject ctx)
820: {

825:   if (vtype != PETSC_DECIDE) mover->meshVelocityMethod     = vtype;
826:   if (atype != PETSC_DECIDE) mover->meshAccelerationMethod = atype;
827:   if (ctx   != PETSC_NULL)   mover->movingMeshCtx          = ctx;
828:   if (mover->meshVelocityGrid == PETSC_NULL) {
829:     MeshMoverSetup(mover);
830:   }
831:   return(0);
832: }

834: /*@
835:   MeshMoverGetVelocityGrid - Returns the grid which defines the mesh velocity.

837:   Not collective

839:   Input Parameter:
840: . mover    - The mover

842:   Output Parameter:
843: . velGrid - The mesh velocity grid

845:   Level: intermediate

847: .keywords: grid, mesh, mesh velocity, movement
848: .seealso: MeshMoverGetAccelerationGrid(), GridGetMeshMovement()
849: @*/
850: int MeshMoverGetVelocityGrid(MeshMover mover, Grid *velGrid)
851: {
854:   *velGrid = mover->meshVelocityGrid;
855:   return(0);
856: }

858: /*@
859:   MeshMoverGetAccelerationGrid - Returns the grid which defines the mesh acceleration.

861:   Not collective

863:   Input Parameter:
864: . mover    - The mover

866:   Output Parameter:
867: . accGrid - The mesh acceleration grid

869:   Level: intermediate

871: .keywords: grid, mesh, mesh acceleration, movement
872: .seealso: MeshMoverGetVelocityGrid(), GridGetMeshMovement()
873: @*/
874: int MeshMoverGetAccelerationGrid(MeshMover mover, Grid *accGrid)
875: {
878:   *accGrid = mover->meshAccelerationGrid;
879:   return(0);
880: }

882: /*@
883:   MeshMoverCalcVelocityBCValues - This function calculates the boundary values for the
884:   mesh velocity. It is normally called once a timestep when using time dependent boundary
885:   conditions.

887:   Collective on MeshMover

889:   Input Parameters:
890: + mover - The MeshMover
891: . save - A flag used to store old values, usually for timestepping
892: - ctx  - The context

894:   Level: advanced

896: .keywords: MeshMover, reduction, boundary conditions
897: .seealso: MeshMoverSetVelocityBCContext(), MeshMoverSetVelocityBC()
898: @*/
899: int MeshMoverCalcVelocityBCValues(MeshMover mover)
900: {
901:   Grid       g;
902:   PetscTruth reduce;
903:   void      *reduceCtx;
904:   int        ierr;

908:   MeshMoverGetMovement(mover, PETSC_NULL, PETSC_NULL, PETSC_NULL);
909:   MeshMoverGetVelocityGrid(mover, &g);
911:   GridGetReduceSystem(g, &reduce);
912:   if (reduce == PETSC_FALSE) return(0);
913:   GridSetUp(g);
914:   GridGetBCContext(g, &reduceCtx);
915:   GridCalcBCValues(g, PETSC_FALSE, reduceCtx);
916:   return(0);
917: }

919: /*@
920:   MeshMoverCalcAccelerationBCValues - This function calculates the boundary values for the
921:   mesh acceleration. It is normally called once a timestep when using time dependent boundary
922:   conditions.

924:   Collective on MeshMover

926:   Input Parameters:
927: + mover - The MeshMover
928: . save - A flag used to store old values, usually for timestepping
929: - ctx  - The context

931:   Level: advanced

933: .keywords: MeshMover, reduction, boundary conditions
934: .seealso: MeshMoverSetAccelerationBCContext(), MeshMoverSetAccelerationBC()
935: @*/
936: int MeshMoverCalcAccelerationBCValues(MeshMover mover)
937: {
938:   Grid       g;
939:   PetscTruth reduce;
940:   void      *reduceCtx;
941:   int        ierr;

945:   MeshMoverGetMovement(mover, PETSC_NULL, PETSC_NULL, PETSC_NULL);
946:   MeshMoverGetAccelerationGrid(mover, &g);
948:   GridGetReduceSystem(g, &reduce);
949:   if (reduce == PETSC_FALSE) return(0);
950:   GridSetUp(g);
951:   GridGetBCContext(g, &reduceCtx);
952:   GridCalcBCValues(g, PETSC_FALSE, reduceCtx);
953:   return(0);
954: }

956: /*@
957:   MeshMoverCalcNodeVelocities - Recalculates the node velocities.

959:   Collective on MeshMover

961:   Input Parameters:
962: + mover - The mover
963: - flag - Flag for reuse of old operator in calculation

965:   Level: advanced

967: .keywords: mesh, movement
968: .seealso: MeshMoverCalcNodeAccelerations()
969: @*/
970: int MeshMoverCalcNodeVelocities(MeshMover mover, PetscTruth flag)
971: {
972:   Grid         grid          = mover->meshVelocityGrid;
973:   MatStructure matStructFlag = DIFFERENT_NONZERO_PATTERN;
974:   Mesh         mesh;
975:   SLES         sles;
976:   GMat         mat;
977:   GVec         rhs, sol;
978:   PetscScalar  zero = 0.0;
979:   int          its;
980:   int          ierr;


985:   PetscLogEventBegin(MESH_CalcNodeVelocities, mover, 0, 0, 0);

987:   /* Allocation */
988:   if (mover->meshVelocitySles == PETSC_NULL) {
989:     GVecCreate(grid, &mover->meshVelocityRhs);
990:     PetscLogObjectParent(mover, mover->meshVelocityRhs);
991:     GVecCreate(grid, &mover->meshVelocitySol);
992:     PetscLogObjectParent(mover, mover->meshVelocitySol);
993:     GMatCreate(grid, &mover->meshVelocityMat);
994:     PetscLogObjectParent(mover, mover->meshVelocityMat);
995:     SLESCreate(mover->comm, &mover->meshVelocitySles);
996:     SLESAppendOptionsPrefix(mover->meshVelocitySles, "mesh_vel_");
997:     SLESSetFromOptions(mover->meshVelocitySles);
998:     PetscLogObjectParent(mover, mover->meshVelocitySles);
999:   }
1000:   sles = mover->meshVelocitySles;
1001:   mat  = mover->meshVelocityMat;
1002:   rhs  = mover->meshVelocityRhs;
1003:   sol  = mover->meshVelocitySol;

1005:   /* Form System Matrix */
1006:   if (flag == PETSC_TRUE) {
1007:     MatZeroEntries(mat);
1008:     GridEvaluateSystemMatrix(grid, PETSC_NULL, &mat, &mat, &matStructFlag, mover->movingMeshCtx);
1009:     GMatSetBoundary(mat, 1.0, mover->movingMeshCtx);
1010:     MatSetOption(mat, MAT_NO_NEW_NONZERO_LOCATIONS);
1011:   }
1012:   /* Form Rhs */
1013:   VecSet(&zero, rhs);
1014:   GridEvaluateRhs(grid, PETSC_NULL, rhs, mover->movingMeshCtx);
1015:   GVecSetBoundary(rhs, mover->movingMeshCtx);
1016:   /* Solve system */
1017:   SLESSetOperators(sles, mat, mat, SAME_NONZERO_PATTERN);
1018:   SLESSolve(sles, rhs, sol, &its);
1019:   /* Copy values into the mesh vector */
1020:   MeshMoverGetMesh(mover, &mesh);
1021:   MeshUpdateNodeValues(mesh, sol, mover->nodeVelocities, mover->nodeVelocitiesGhost);
1022:   PetscLogEventEnd(MESH_CalcNodeVelocities, mover, 0, 0, 0);
1023:   return(0);
1024: }

1026: /*@
1027:   MeshMoverCalcNodeAccelerations - Recalculates the node accelerations.

1029:   Collective on MeshMover

1031:   Input Parameters:
1032: + mover - The mover
1033: - flag - Flag for reuse of old operator in calculation

1035:   Level: advanced

1037: .keywords: mesh, movement
1038: .seealso: MeshMoverCalcNodeVelocities()
1039: @*/
1040: int MeshMoverCalcNodeAccelerations(MeshMover mover, PetscTruth flag)
1041: {
1042:   Grid         grid          = mover->meshAccelerationGrid;
1043:   MatStructure matStructFlag = DIFFERENT_NONZERO_PATTERN;
1044:   Mesh         mesh;
1045:   SLES         sles;
1046:   GMat         mat;
1047:   GVec         rhs, sol;
1048:   PetscScalar  zero = 0.0;
1049:   int          its;
1050:   int          ierr;


1055:   PetscLogEventBegin(MESH_CalcNodeAccelerations, mover, 0, 0, 0);

1057:   /* Allocation */
1058:   if (mover->meshAccelerationSles == PETSC_NULL) {
1059:     GVecCreate(grid, &mover->meshAccelerationRhs);
1060:     PetscLogObjectParent(mover, mover->meshAccelerationRhs);
1061:     GVecCreate(grid, &mover->meshAccelerationSol);
1062:     PetscLogObjectParent(mover, mover->meshAccelerationSol);
1063:     GMatCreate(grid, &mover->meshAccelerationMat);
1064:     PetscLogObjectParent(mover, mover->meshAccelerationMat);
1065:     SLESCreate(mover->comm, &mover->meshAccelerationSles);
1066:     SLESAppendOptionsPrefix(mover->meshAccelerationSles, "mesh_accel_");
1067:     SLESSetFromOptions(mover->meshAccelerationSles);
1068:     PetscLogObjectParent(mover, mover->meshAccelerationSles);
1069:   }
1070:   sles = mover->meshAccelerationSles;
1071:   mat  = mover->meshAccelerationMat;
1072:   rhs  = mover->meshAccelerationRhs;
1073:   sol  = mover->meshAccelerationSol;

1075:   /* Form System Matrix */
1076:   if (flag == PETSC_TRUE) {
1077:     MatZeroEntries(mat);
1078:     GridEvaluateSystemMatrix(grid, PETSC_NULL, &mat, &mat, &matStructFlag, mover->movingMeshCtx);
1079:     GMatSetBoundary(mat, 1.0, mover->movingMeshCtx);
1080:     MatSetOption(mat, MAT_NO_NEW_NONZERO_LOCATIONS);
1081:   }
1082:   /* Form Rhs */
1083:   VecSet(&zero, rhs);
1084:   GridEvaluateRhs(grid, PETSC_NULL, rhs, mover->movingMeshCtx);
1085:   GVecSetBoundary(rhs, mover->movingMeshCtx);
1086:   /* Solve system */
1087:   SLESSetOperators(sles, mat, mat, SAME_NONZERO_PATTERN);
1088:   SLESSolve(sles, rhs, sol, &its);
1089:   /* Copy values into the mesh vector */
1090:   MeshMoverGetMesh(mover, &mesh);
1091:   MeshUpdateNodeValues(mesh, sol, mover->nodeAccelerations, mover->nodeAccelerationsGhost);
1092:   PetscLogEventEnd(MESH_CalcNodeAccelerations, mover, 0, 0, 0);
1093:   return(0);
1094: }

1096: /*@
1097:   MeshMoverSetNodeVelocities - Allows the user to specify node velocities.

1099:   Collective on MeshMover

1101:   Input Parameters:
1102: + mover  - The mover
1103: . func  - A PointFunction defining the node velocities
1104: . alpha - A scalar multiplier
1105: - ctx   - A user context

1107:   Level: advanced

1109: .keywords: mesh, movement
1110: .seealso: MeshMoverSetNodeAccelerations()
1111: @*/
1112: int MeshMoverSetNodeVelocities(MeshMover mover, PointFunction func, PetscScalar alpha, void *ctx)
1113: {
1114: #if 0
1115:   int field = 0;

1119:   GVecEvaluateFunction(mover->nodeVelocities, 1, &field, func, alpha, ctx);
1120:   /* Now need a way to get mesh velocities back to the system */
1121:   return(0);
1122: #else
1123:   SETERRQ(PETSC_ERR_SUP, "Not yet a grid vector");
1124: #endif
1125: }

1127: /*@
1128:   MeshMoverSetNodeAccelerations - Allows the user to specify node accelerations.

1130:   Collective on MeshMover

1132:   Input Parameters:
1133: + mover  - The mover
1134: . func  - A function defining the node accelerations
1135: . alpha - A scalar multiplier
1136: - ctx   - A user context

1138:   Level: intermediate

1140: .keywords: mesh, movement
1141: .seealso: MeshMoverSetNodeVelocities()
1142: @*/
1143: int MeshMoverSetNodeAccelerations(MeshMover mover, PointFunction func, PetscScalar alpha, void *ctx)
1144: {
1145: #if 0
1146:   int field = 0;

1150:   GVecEvaluateFunction(mover->nodeAccelerations, 1, &field, func, alpha, ctx);
1151:   /* Now need a way to get mesh accelerations back to the system */
1152:   return(0);
1153: #else
1154:   SETERRQ(PETSC_ERR_SUP, "Not yet a grid vector");
1155: #endif
1156: }

1158: /*@C
1159:   MeshMoverSetVelocityBC -        This function sets the boundary conditions to use
1160:   for the mesh velocity calculation.

1162:   Collective on MeshMover

1164:   Input Parameters:
1165: + mover   - The mover
1166: . bd     - The marker for the boundary along which conditions are applied
1167: . f      - The function which defines the boundary condition
1168: - reduce - The flag for explicit reduction of the system

1170:   Note:
1171:   This function clears any previous conditions, whereas MeshMoverAddVelocityBC()
1172:   appends the condition.

1174:   Level: intermediate

1176: .keywords mesh, velocity, boundary condition
1177: .seealso MeshMoverAddVelocityBC(), MeshMoverSetAccelerationBC(), GridSetBC(), GridAddBC()
1178: @*/
1179: int MeshMoverSetVelocityBC(MeshMover mover, int bd, PointFunction f, PetscTruth reduce)
1180: {


1186:   if (mover->meshVelocityGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Velocity grid not created");
1187:   GridSetBC(mover->meshVelocityGrid, bd, 0, f, reduce);
1188:   return(0);
1189: }

1191: /*@C
1192:   MeshMoverAddVelocityBC - This function adds a boundary condition to use
1193:   for the mesh velocity calculation.

1195:   Collective on MeshMover

1197:   Input Parameters:
1198: + mover   - The mover
1199: . bd     - The marker for the boundary along which conditions are applied
1200: . f      - The function which defines the boundary condition
1201: - reduce - The flag for explicit reduction of the system

1203:   Note:
1204:   This function appends the condition, whereas MeshMoverSetVelocityBC()
1205:   clears any previous conditions.

1207:   Level: intermediate

1209: .keywords mesh, velocity, boundary condition
1210: .seealso MeshMoverSetVelocityBC(), MeshMoverAddAccelerationBC(), GridSetBC(), GridAddBC()
1211: @*/
1212: int MeshMoverAddVelocityBC(MeshMover mover, int bd, PointFunction f, PetscTruth reduce)
1213: {


1219:   if (mover->meshVelocityGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Velocity grid not created");
1220:   GridAddBC(mover->meshVelocityGrid, bd, 0, f, reduce);
1221:   return(0);
1222: }

1224: /*@C
1225:   MeshMoverSetVelocityBCContext - This function sets the boundary condition context
1226:   to use for the mesh velocity calculation.

1228:   Collective on MeshMover

1230:   Input Parameters:
1231: + mover - The mover
1232: - ctx  - The user context

1234:   Level: intermediate

1236: .keywords mesh, velocity, boundary condition
1237: .seealso MeshMoverAddVelocityBC(), MeshMoverSetVelocityBC()
1238: @*/
1239: int MeshMoverSetVelocityBCContext(MeshMover mover, void *ctx)
1240: {


1246:   if (mover->meshVelocityGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Velocity grid not created");
1247:   GridSetBCContext(mover->meshVelocityGrid, ctx);
1248:   return(0);
1249: }

1251: /*@C
1252:   MeshMoverSetAccelerationBC - This function sets the boundary condition to use
1253:   for the mesh acceleration calculation.

1255:   Collective on MeshMover

1257:   Input Parameters:
1258: + mover   - The mover
1259: . bd     - The marker for the boundary along which conditions are applied
1260: . f      - The function which defines the boundary condition
1261: - reduce - The flag for explicit reduction of the system

1263:   Note:
1264:   This function clears any previous conditions, whereas MeshMoverAddAccelerationBC()
1265:   appends the condition.

1267:   Level: intermediate

1269: .keywords mesh, velocity, boundary condition
1270: .seealso MeshMoverAddAccelerationBC(), MeshMoverSetVelocityBC(), GridSetBC(), GridAddBC()
1271: @*/
1272: int MeshMoverSetAccelerationBC(MeshMover mover, int bd, PointFunction f, PetscTruth reduce)
1273: {


1279:   if (mover->meshAccelerationGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Acceleration grid not created");
1280:   GridSetBC(mover->meshAccelerationGrid, bd, 0, f, reduce);
1281:   return(0);
1282: }

1284: /*@C
1285:   MeshMoverAddAccelerationBC - This function adds a boundary condition to use
1286:   for the mesh acceleration calculation.

1288:   Collective on MeshMover

1290:   Input Parameters:
1291: + mover   - The mover
1292: . bd     - The marker for the boundary along which conditions are applied
1293: . f      - The function which defines the boundary condition
1294: - reduce - The flag for explicit reduction of the system

1296:   Note:
1297:   This function appends the condition, whereas MeshMoverSetVelocityBC()
1298:   clears any previous conditions.

1300:   Level: intermediate

1302: .keywords mesh, velocity, boundary condition
1303: .seealso MeshMoverSetAccelerationBC(), MeshMoverAddVelocityBC(), GridSetBC(), GridAddBC()
1304: @*/
1305: int MeshMoverAddAccelerationBC(MeshMover mover, int bd, PointFunction f, PetscTruth reduce)
1306: {


1312:   if (mover->meshAccelerationGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Acceleration grid not created");
1313:   GridAddBC(mover->meshAccelerationGrid, bd, 0, f, reduce);
1314:   return(0);
1315: }

1317: /*@C
1318:   MeshMoverSetAccelerationBCContext - This function sets the boundary condition context
1319:   to use for the mesh acceleration calculation.

1321:   Collective on MeshMover

1323:   Input Parameter:
1324: + mover - The mover
1325: - ctx  - The user context

1327:   Level: intermediate

1329: .keywords mesh, velocity, boundary condition
1330: .seealso MeshMoverAddAccelerationBC(), MeshMoverSetAccelerationBC()
1331: @*/
1332: int MeshMoverSetAccelerationBCContext(MeshMover mover, void *ctx)
1333: {


1339:   if (mover->meshAccelerationGrid == PETSC_NULL) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Acceleration grid not created");
1340:   GridSetBCContext(mover->meshAccelerationGrid, ctx);
1341:   return(0);
1342: }

1344: /*@
1345:   MeshMoverSetMovementCaption - Sets the caption of the moving mesh
1346:   viewer. Can be used to provide auxilliary information, e.g. time.

1348:   Collective on MeshMover

1350:   Input Parameters:
1351: + mover    - The mover
1352: - caption - The caption

1354:   Level: intermediate

1356: .keywords: mesh, movement
1357: .seealso: MeshMoverMoveMesh()
1358: @*/
1359: int MeshMoverSetMovementCaption(MeshMover mover, char *caption)
1360: {
1364:   mover->movingMeshViewerCaption = caption;
1365:   return(0);
1366: }

1368: /*----------------------------------------- MeshMover Registration Functions -----------------------------------------*/
1369: PetscFList MeshMoverList              = 0;
1370: int        MeshMoverRegisterAllCalled = 0;

1372: /*@C
1373:   MeshMoverSetType - Builds a MeshMover, for a particular Mesh implementation.

1375:   Collective on MeshMover

1377:   Input Parameters:
1378: + mover - The MeshMover
1379: - type  - The type name

1381:   Options Database Key:
1382: . -mesh_mover_type <type> - Sets the mesh mvoer type

1384:   Level: intermediate

1386: .keywords: vector, set, type
1387: .seealso: MeshMoverCreate()
1388: @*/
1389: int MeshMoverSetType(MeshMover mover, MeshMoverType method) {
1390:   int      (*r)(MeshMover);
1391:   PetscTruth match;
1392:   int        ierr;

1396:   PetscTypeCompare((PetscObject) mover, method, &match);
1397:   if (match == PETSC_TRUE) return(0);

1399:   /* Get the function pointers for the vector requested */
1400:   if (!MeshMoverRegisterAllCalled) {
1401:     MeshMoverRegisterAll(PETSC_NULL);
1402:   }
1403:   PetscFListFind(mover->comm, MeshMoverList, method,(void (**)(void)) &r);
1404:   if (!r) SETERRQ1(PETSC_ERR_ARG_WRONG, "Unknown mesh mover type: %s", method);

1406:   if (mover->ops->destroy != PETSC_NULL) {
1407:     (*mover->ops->destroy)(mover);
1408:   }
1409:   (*r)(mover);

1411:   PetscObjectChangeTypeName((PetscObject) mover, method);
1412:   return(0);
1413: }

1415: /*@C
1416:   MeshMoverGetType - Gets the MeshMover method type name (as a string).

1418:   Not collective

1420:   Input Parameter:
1421: . mover - The mover

1423:   Output Parameter:
1424: . type - The name of MeshMover method

1426:   Level: intermediate

1428: .keywords: mover, get, type, name
1429: .seealso MeshMoverSetType()
1430: @*/
1431: int MeshMoverGetType(MeshMover mover, MeshMoverType *type)
1432: {

1438:   if (!MeshMoverRegisterAllCalled) {
1439:     MeshMoverRegisterAll(PETSC_NULL);
1440:   }
1441:   *type = mover->type_name;
1442:   return(0);
1443: }

1445: /*@C
1446:   MeshMoverRegister - Adds a creation method to the mesh movement package.

1448:   Synopsis:

1450:   MeshMoverRegister(char *name, char *path, char *func_name, int (*create_func)(MeshMover))

1452:   Not Collective

1454:   Input Parameters:
1455: + name        - The name of a new user-defined creation routine
1456: . path        - The path (either absolute or relative) of the library containing this routine
1457: . func_name   - The name of the creation routine
1458: - create_func - The creation routine itself

1460:   Notes:
1461:   MeshMoverRegister() may be called multiple times to add several user-defined meshes.

1463:   If dynamic libraries are used, then the fourth input argument (create_func) is ignored.

1465:   Sample usage:
1466: .vb
1467:   MeshMoverRegisterDynamic("my_mesh", "/home/username/my_lib/lib/libO/solaris/libmy.a", "MyMeshMoverCreate", MyMeshMoverCreate);
1468: .ve

1470:   Then, your mesh type can be chosen with the procedural interface via
1471: .vb
1472:     MeshMoverCreate(MPI_Comm, MeshMover *);
1473:     MeshMoverSetType(vec, "my_mesh_mover")
1474: .ve
1475:   or at runtime via the option
1476: .vb
1477:     -mesh_mover_type my_mesh_mover
1478: .ve

1480:   Note: $PETSC_ARCH and $BOPT occuring in pathname will be replaced with appropriate values.

1482:   Level: advanced

1484: .keywords: MeshMover, register
1485: .seealso: MeshMoverRegisterAll(), MeshMoverRegisterDestroy()
1486: @*/
1487: int MeshMoverRegister(const char sname[], const char path[], const char name[], int (*function)(MeshMover))
1488: {
1489:   char fullname[256];
1490:   int  ierr;

1493:   PetscStrcpy(fullname, path);
1494:   PetscStrcat(fullname, ":");
1495:   PetscStrcat(fullname, name);
1496:   PetscFListAdd(&MeshMoverList, sname, fullname, (void (*)(void)) function);
1497:   return(0);
1498: }

1500: /*@C
1501:   MeshMoverRegisterDestroy - Frees the list of creation routines for
1502:   meshes that were registered by MeshMoverRegister().

1504:   Not collective

1506:   Level: advanced

1508: .keywords: mesh, register, destroy
1509: .seealso: MeshMoverRegister(), MeshMoverRegisterAll()
1510: @*/
1511: int MeshMoverRegisterDestroy() {

1515:   if (MeshMoverList != PETSC_NULL) {
1516:     PetscFListDestroy(&MeshMoverList);
1517:     MeshMoverList = PETSC_NULL;
1518:   }
1519:   MeshMoverRegisterAllCalled = 0;
1520:   return(0);
1521: }

1523: EXTERN_C_BEGIN
1524: extern int MeshMoverCreate_Triangular_2D(MeshMover);
1525: EXTERN_C_END

1527: /*@C
1528:   MeshMoverRegisterAll - Registers all of the generation routines in the MeshMover package. 

1530:   Not Collective

1532:   Input parameter:
1533: . path - The dynamic library path

1535:   Level: advanced

1537: .keywords: MeshMover, register, all
1538: .seealso: MeshMoverRegister(), MeshMoverRegisterDestroy()
1539: @*/
1540: int MeshMoverRegisterAll(const char path[])
1541: {

1545:   MeshMoverRegisterAllCalled = 1;

1547:   MeshMoverRegister(MESH_MOVER_TRIANGULAR_2D, path, "MeshMoverCreate_Triangular_2D", MeshMoverCreate_Triangular_2D);
1548: 
1549:   return(0);
1550: }

1552: /*-------------------------------------------------- Grid Functions --------------------------------------------------*/
1553: /*@
1554:   GridReformMesh - Reconstruct the grid from the current description
1555:   and underlying mesh boundary. The old mesh is returned if requested.
1556:   This allows postprocessing of the mesh before GridReform() is called.

1558:   Collective on Grid

1560:   Input Parameters:
1561: + grid   - The grid
1562: . refine - Flag indicating whether to refine or recreate the mesh
1563: . area   - [Optional] A function which gives area constraints for refinement after reform, PETSC_NULL for no refinement
1564: - newBd  - Flag to determine whether the boundary should be generated (PETSC_TRUE) or taken from storage

1566:   Output Parameter:
1567: . oldMesh - The old mesh

1569:   Level: advanced

1571: .keywords: Grid, mesh, reform, refine
1572: .seealso: MeshReform(), GridReform(), GridRefineMesh()
1573: @*/
1574: int GridReformMesh(Grid grid, PetscTruth refine, PointFunction area, PetscTruth newBd, Mesh *oldMesh)
1575: {
1576:   Mesh mesh;
1577:   Mesh newMesh;
1578:   int  ierr;


1583:   /* Reform mesh */
1584:   GridGetMesh(grid, &mesh);
1585:   MeshReform(mesh, refine, area, newBd, &newMesh);

1587:   /* Save old information */
1588:   if (oldMesh != PETSC_NULL){
1590:     *oldMesh = mesh;
1591:   }
1592:   grid->mesh = newMesh;

1594:   /* Recalculate grid structures for mesh */
1595:   GridCalcPointBCNodes(grid);

1597:   /* Recreate class structure */
1598:   FieldClassMapDestroy(grid->cm);
1599:   FieldClassMapCreateTriangular2D(grid, grid->numActiveFields, grid->defaultFields, &grid->cm);

1601:   /* Specific setup */
1602:   if (grid->ops->gridreformmesh != PETSC_NULL) {
1603:     (*grid->ops->gridreformmesh)(grid);
1604:   }
1605:   return(0);
1606: }

1608: /*@
1609:   GridReform - Reconstruct the variable structures, usually after a change
1610:   in mesh structure. The optional arguments allow projection of the
1611:   previous solution onto the new mesh.

1613:   Collective on Grid

1615:   Input Parameters:
1616: + grid    - The grid
1617: . oldMesh - [Optional] The old mesh
1618: - x       - [Optional] A grid vector to project onto the new mesh

1620:   Output Parameter:
1621: . y       - [Optional] The projected grid vector

1623:   Level: advanced

1625: .keywords: grid, mesh, reform
1626: .seealso: GridReformMesh(), MeshReform()
1627: @*/
1628: int GridReform(Grid grid, Mesh oldMesh, GVec x, GVec *y)
1629: {
1630:   MPI_Comm             comm;
1631:   VarOrdering          order;
1632:   FieldClassMap        map;
1633:   int                  numFields;
1634:   int                 *fields;
1635:   PetscTruth           isConstrained, explicitConstraints;
1636:   InterpolationContext iCtx;             /* Used to form the rhs */
1637:   /* L_2 projection variables */
1638: #if 0
1639:   GMat                 M;                /* The (local) mass matrix M */
1640:   GMat                 m;                /* The restriction of M to the boundary m */
1641:   GMat                 S;                /* The Schur complement S = m^T M^{-1} m */
1642:   GVec                 sol, rhs;         /* The solution x and rhs f */
1643:   GVec                 projRhs;          /* The projection rhs g */
1644:   GVec                 uzawaRhs;         /* The Uzawa rhs m^T M^{-1} f - g */
1645:   GVec                 uzawaSol;         /* The Uzawa solution lambda = (m^T M^{-1} m)^{-1} (m^T M^{-1} f - g) */
1646:   KSP                  ksp;              /* The Krylov solver for M */
1647:   PC                   pc;               /* The preconditioner for M */
1648:   SLES                 sles;             /* The solver for M */
1649:   SLES                 uzawaSles;        /* The solver for S */
1650:   PetscScalar          minusOne = -1.0;
1651:   PetscScalar          zero     = 0.0;
1652:   int                  its;
1653: #endif
1654:   /* Local Interpolation variables */
1655:   VarOrdering          reduceOrder,     reduceOrderOld;      /* TEMPORARY, until I fix the interpolation */
1656:   GVec                 bdReduceVec,     prevBdReduceVec;     /* TEMPORARY, until I fix the interpolation */
1657:   GVec                 bdReduceVecOld,  prevBdReduceVecOld;  /* TEMPORARY, until I fix the interpolation */
1658:   GVec                 bdReduceVecDiff, prevBdReduceVecDiff; /* TEMPORARY, until I fix the interpolation */
1659:   PetscReal            norm;
1660:   int                  maxComp;
1661:   int                  field, f;
1662:   int                  ierr;

1666:   PetscLogEventBegin(GRID_Reform, grid, 0, 0, 0);
1667:   /* Make sure the vector is saved in local storage */
1668:   GridGlobalToLocal(grid, INSERT_VALUES, x);
1669:   /* Need to setup grid again */
1670:   grid->setupcalled   = PETSC_FALSE;
1671:   grid->bdSetupCalled = PETSC_FALSE;
1672:   /* Check arguments */
1673:   if ((x == PETSC_NULL) || (y == PETSC_NULL)) {
1674:     GridSetupGhostScatter(grid);
1675:     return(0);
1676:   }

1680:   PetscObjectGetComm((PetscObject) oldMesh, &comm);
1681:   GridIsConstrained(grid, &isConstrained);
1682:   GridGetExplicitConstraints(grid, &explicitConstraints);
1683:   if (explicitConstraints == PETSC_FALSE) {
1684:     order = grid->order;
1685:   } else {
1686:     order = grid->constraintOrder;
1687:   }
1688:   VarOrderingGetClassMap(order, &map);
1689: #ifdef INTERFACE_UPDATE
1690:   FieldClassMapGetNumFields(map, &numFields);
1691:   FieldClassMapGetFields(map, &fields);
1692: #endif
1693:   numFields = map->numFields;
1694:   fields    = map->fields;

1696:   /* Project fields onto new mesh */
1697:   switch(grid->interpolationType)
1698:   {
1699: #if 0
1700:   case INTERPOLATION_L2:
1701:     /* Interpolation Procedure:
1702:          We must locally interpolate the value of the old field at each Gaussian intergration
1703:          point in an element of the new field. The function PointFunctionInterpolateField()
1704:          calls GVecInterpolateField(), which calls DiscretizationInterpolateField(). The vector, field,
1705:          and old mesh are stored in a context so that PointFunctionInterpolateField() can pass
1706:          them to GVecInterpolateField(). The indices and values for DiscretizationInterpolateField() are
1707:          calculated by GridCalcLocalElementVecIndices() and GridLocalToElement(). These
1708:          functions need the old mesh, classes, variable ordering, and local vector ghostVec in
1709:          order to correctly calculate the old vector indices and values. However, the
1710:          GVecEvaluateFunctionGalerkin() uses the new values to get the weak form. The old mesh
1711:          we have, and the classes are stored in classesOld[]. We will keep the variable
1712:          ordering and local vector in temporary veriables. The old copies must be set to NULL
1713:          or they will be deleted.
1714:     */

1716:     /* Save old structures */
1717:     iCtx.vec      = x;
1718:     iCtx.mesh     = oldMesh;
1719:     iCtx.order    = order;
1720:     iCtx.ghostVec = grid->ghostVec;

1722:     /* Setup context */
1723:     for(f = 0, maxComp = 1; f < numFields; f++) {
1724:       maxComp = PetscMax(maxComp, grid->comp[fields[f]]);
1725:     }
1726:     MPI_Comm_size(comm, &iCtx.numProcs);
1727:     MPI_Comm_rank(comm, &iCtx.rank);
1728:     iCtx.batchMode = PETSC_FALSE;
1729:     iCtx.curPoint  = 0;
1730:     iCtx.maxPoints = iCtx.numProcs;
1731:     PetscMalloc((iCtx.numProcs+1)     * sizeof(int),         &iCtx.numPoints);
1732:     PetscMalloc(iCtx.numProcs         * sizeof(int),         &iCtx.activeProcs);
1733:     PetscMalloc(iCtx.numProcs         * sizeof(int),         &iCtx.calcProcs);
1734:     PetscMalloc(iCtx.maxPoints*3      * sizeof(PetscScalar), &iCtx.coords);
1735:     PetscMalloc(iCtx.numProcs*maxComp * sizeof(PetscScalar), &iCtx.values);

1737:     /* Create new variable numbering and ghost structures */
1738:     if (explicitConstraints == PETSC_TRUE) {
1739:       grid->constraintOrder = PETSC_NULL;
1740:     } else {
1741:       grid->order         = PETSC_NULL;
1742:     }
1743:     grid->ghostVec        = PETSC_NULL;
1744:     reduceOrderOld        = grid->reduceOrder;
1745:     prevBdReduceVec       = grid->bdReduceVec;
1746:     prevBdReduceVecOld    = grid->bdReduceVecOld;
1747:     prevBdReduceVecDiff   = grid->bdReduceVecDiff;
1748:     grid->reduceOrder     = PETSC_NULL;
1749:     grid->bdReduceVec     = PETSC_NULL;
1750:     grid->bdReduceVecOld  = PETSC_NULL;
1751:     grid->bdReduceVecDiff = PETSC_NULL;
1752:     GridSetupGhostScatter(grid);
1753:     reduceOrder           = grid->reduceOrder;
1754:     bdReduceVec           = grid->bdReduceVec;
1755:     bdReduceVecOld        = grid->bdReduceVecOld;
1756:     bdReduceVecDiff       = grid->bdReduceVecDiff;
1757:     grid->reduceOrder     = reduceOrderOld;
1758:     grid->bdReduceVec     = prevBdReduceVec;
1759:     grid->bdReduceVecOld  = prevBdReduceVecOld;
1760:     grid->bdReduceVecDiff = prevBdReduceVecDiff;
1761:     if (grid->bdReduceVecCur == bdReduceVec) {
1762:       grid->bdReduceVecCur = grid->bdReduceVec;
1763:     } else if (grid->bdReduceVecCur == bdReduceVecOld) {
1764:       grid->bdReduceVecCur = grid->bdReduceVecOld;
1765:     } else if (grid->bdReduceVecCur == bdReduceVecDiff) {
1766:       grid->bdReduceVecCur = grid->bdReduceVecDiff;
1767:     } else {
1768:       SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid reduction vector");
1769:     }

1771:     /* Allocate structures */
1772:     if (explicitConstraints) {
1773:       GVecCreateConstrained(grid, y);
1774:     } else {
1775:       GVecCreate(grid, y);
1776:     }
1777:     GVecDuplicate(*y, &rhs);
1778:     GVecDuplicate(*y, &sol);
1779:     GVecCreateBoundaryRestriction(grid, &uzawaSol);
1780:     GVecDuplicate(uzawaSol, &projRhs);
1781:     GVecDuplicate(uzawaSol, &uzawaRhs);

1783:     /* Create the rhs */
1784:     for(f = 0; f < numFields; f++) {
1785:       field = fields[f];
1786:       iCtx.field = field;
1787:       if (iCtx.batchMode == PETSC_FALSE) {
1788:         GVecEvaluateFunctionGalerkinCollective(rhs, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
1789: 
1790: #if 1
1791:         GVecEvaluateBoundaryFunctionGalerkinCollective(projRhs, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
1792: 
1793: #else
1794:         VecSet(&zero, projRhs);
1795: #endif
1796:       } else {
1797:         GVecEvaluateFunctionGalerkin(rhs, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
1798:         GVecInterpolateFieldBatch(rhs, field, &iCtx);
1799:         iCtx.curPoint = iCtx.numPoints[iCtx.rank];
1800:         GVecEvaluateFunctionGalerkin(rhs, 1, &field, PointFunctionInterpolateFieldBatch, 1.0, &iCtx);
1801: 
1802:         if (iCtx.curPoint != iCtx.numPoints[iCtx.rank+1]) SETERRQ(PETSC_ERR_PLIB, "Invalid batch point processing");
1803:         GVecEvaluateBoundaryFunctionGalerkin(projRhs, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
1804: 
1805:         GVecInterpolateFieldBatch(projRhs, field, &iCtx);
1806:         iCtx.curPoint = iCtx.numPoints[iCtx.rank];
1807:         GVecEvaluateFunctionGalerkin(projRhs, 1, &field, PointFunctionInterpolateFieldBatch, 1.0, &iCtx);
1808: 
1809:         if (iCtx.curPoint != iCtx.numPoints[iCtx.rank+1]) SETERRQ(PETSC_ERR_PLIB, "Invalid batch point processing");
1810:       }
1811:     }
1812:     if (grid->bdReduceVecCur == grid->bdReduceVec) {
1813:       grid->bdReduceVecCur = bdReduceVec;
1814:     } else if (grid->bdReduceVecCur == grid->bdReduceVecOld) {
1815:       grid->bdReduceVecCur = bdReduceVecOld;
1816:     } else if (grid->bdReduceVecCur == grid->bdReduceVecDiff) {
1817:       grid->bdReduceVecCur = bdReduceVecDiff;
1818:     } else {
1819:       SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid reduction vector");
1820:     }
1821:     grid->reduceOrder     = reduceOrder;
1822:     grid->bdReduceVec     = bdReduceVec;
1823:     grid->bdReduceVecOld  = bdReduceVecOld;
1824:     grid->bdReduceVecDiff = bdReduceVecDiff;
1825:     if (grid->reduceSystem == PETSC_TRUE) {
1826:       VarOrderingDestroy(reduceOrderOld);
1827:       VecDestroy(prevBdReduceVec);
1828:       VecDestroy(prevBdReduceVecOld);
1829:       VecDestroy(prevBdReduceVecDiff);
1830:     }

1832:     /* Destroy old structures */
1833:     VarOrderingDestroy(iCtx.order);
1834:     VecDestroy(iCtx.ghostVec);

1836:     /* Cleanup */
1837:     PetscFree(iCtx.numPoints);
1838:     PetscFree(iCtx.activeProcs);
1839:     PetscFree(iCtx.calcProcs);
1840:     PetscFree(iCtx.values);
1841:     PetscFree(iCtx.coords);

1843:     /* Create the inner solver */
1844:     SLESCreate(PETSC_COMM_SELF, &sles);
1845:     SLESAppendOptionsPrefix(sles, "grid_proj_");
1846:     SLESGetKSP(sles, &ksp);
1847:     SLESGetPC(sles, &pc);
1848:     KSPSetType(ksp, KSPCG);
1849:     PCSetType(pc, PCJACOBI);
1850:     SLESSetFromOptions(sles);
1851:     /* Create the outer solver */
1852:     SLESCreate(PETSC_COMM_SELF, &uzawaSles);
1853:     SLESAppendOptionsPrefix(uzawaSles, "grid_proj_uzawa_");
1854:     SLESGetKSP(uzawaSles, &ksp);
1855:     SLESGetPC(uzawaSles, &pc);
1856:     KSPSetType(ksp, KSPGMRES);
1857:     PCSetType(pc, PCNONE);
1858:     SLESSetFromOptions(uzawaSles);

1860:     /* Create M, the mass matrix */
1861:     GMatCreate(grid, &M);
1862:     GMatEvaluateOperatorGalerkin(M, PETSC_NULL, numFields, fields, fields, IDENTITY, 1.0, MAT_FINAL_ASSEMBLY, PETSC_NULL);
1863: 
1864:     MatNorm(M, NORM_FROBENIUS, &norm);
1865:     PetscPrintf(PETSC_COMM_SELF, "Mass matrix norm %lfn", norm);

1867:     /* Create m, the restriction of M to the boundary */
1868:     GMatCreateBoundaryRestriction(grid, &m);
1869: #if 1
1870:     GMatEvaluateBoundaryOperatorGalerkin(m, numFields, grid->cm->fields, grid->bdOrder, grid->bdLocOrder,
1871:                                                 fields, grid->order, grid->locOrder, IDENTITY, 1.0, MAT_FINAL_ASSEMBLY,
1872:                                                 PETSC_NULL);
1873: 
1874: #else
1875:     MatAssemblyBegin(m, MAT_FINAL_ASSEMBLY);
1876:     MatAssemblyEnd(m, MAT_FINAL_ASSEMBLY);
1877:     MatZeroEntries(m);
1878: #endif
1879:     MatNorm(m, NORM_FROBENIUS, &norm);
1880:     PetscPrintf(PETSC_COMM_SELF, "Restricted mass matrix norm %lfn", norm);

1882:     VecNorm(rhs,     NORM_2, &norm);
1883:     PetscPrintf(PETSC_COMM_SELF, "Rhs norm %lfn", norm);
1884:     VecNorm(projRhs, NORM_2, &norm);
1885:     PetscPrintf(PETSC_COMM_SELF, "Restricted rhs norm %lfn", norm);

1887:     /* Create the Schur complement */
1888:     SLESSetOperators(sles, M, M, SAME_NONZERO_PATTERN);
1889:     GMatCreateUzawa(M, m, sles, &S);

1891:     /* Create the restriction of the rhs */
1892:     SLESSolve(sles, rhs, sol, &its);
1893:     MatMultTranspose(m, sol, uzawaRhs);
1894:     VecAXPY(&minusOne, projRhs, uzawaRhs);
1895:     VecNorm(uzawaRhs, NORM_2, &norm);
1896:     PetscPrintf(PETSC_COMM_SELF, "Uzawa rhs norm %lfn", norm);

1898:     /* Solve system */
1899:     SLESSetOperators(uzawaSles, S, S, SAME_NONZERO_PATTERN);
1900:     SLESSolve(uzawaSles, uzawaRhs, uzawaSol, &its);
1901:     PetscPrintf(PETSC_COMM_SELF, "Uzawa solution took %d iterationsn", its);
1902:     VecNorm(uzawaSol, NORM_2, &norm);
1903:     PetscPrintf(PETSC_COMM_SELF, "Uzawa solution norm %lfn", norm);

1905:     /* Get solution */
1906:     MatMult(m, uzawaSol, sol);
1907:     VecNorm(sol, NORM_2, &norm);
1908:     PetscPrintf(PETSC_COMM_SELF, "Boundary solution update norm %lfn", norm);
1909:     VecAYPX(&minusOne, rhs, sol);
1910:     VecNorm(sol, NORM_2, &norm);
1911:     PetscPrintf(PETSC_COMM_SELF, "Solution update norm %lfn", norm);
1912:     SLESSolve(sles, sol, *y, &its);
1913:     PetscPrintf(PETSC_COMM_SELF, "Projection solution took %d iterationsn", its);

1915:     VecNorm(*y, NORM_2, &norm);
1916:     PetscPrintf(PETSC_COMM_SELF, "Projected solution norm %lfn", norm);

1918:     /* Cleanup */
1919:     SLESDestroy(sles);
1920:     SLESDestroy(uzawaSles);
1921:     GMatDestroyUzawa(S);
1922:     GMatDestroy(M);
1923:     GMatDestroy(m);
1924:     GVecDestroy(rhs);
1925:     GVecDestroy(sol);
1926:     GVecDestroy(projRhs);
1927:     GVecDestroy(uzawaRhs);
1928:     GVecDestroy(uzawaSol);

1930:     break;
1931: #endif
1932:   case INTERPOLATION_LOCAL:
1933:     /* Interpolation Procedure:
1934:          We must locally interpolate the value of the old field at each node in an element of
1935:          the new field. The function PointFunctionInterpolateField()calls GVecInterpolateField(),
1936:          which calls DiscretizationInterpolateField(). The vector, field, and old mesh are stored in a
1937:          context so that PointFunctionInterpolateField() can pass them to GVecInterpolateField().
1938:          The indices and values for DiscretizationInterpolateField() are calculated by
1939:          GridCalcLocalElementVecIndices() and GridLocalToElement(). These functions need the old
1940:          mesh, classes, variable ordering, and local vector ghostVec in order to correctly calculate
1941:          the old vector indices and values. The old mesh we have, and the classes are stored in
1942:          classesOld[]. We will keep the variable ordering and local vector in temporary veriables.
1943:          The old copies must be set to NULL or they will be deleted.
1944:     */

1946:     /* Save old structures */
1947:     iCtx.vec      = x;
1948:     iCtx.mesh     = oldMesh;
1949:     iCtx.order    = order;
1950:     iCtx.ghostVec = grid->ghostVec;

1952:     /* Setup context */
1953:     for(f = 0, maxComp = 1; f < numFields; f++) {
1954:       maxComp = PetscMax(maxComp, grid->fields[fields[f]].numComp);
1955:     }
1956:     MPI_Comm_size(comm, &iCtx.numProcs);
1957:     MPI_Comm_rank(comm, &iCtx.rank);
1958:     iCtx.batchMode   = PETSC_FALSE;
1959:     iCtx.curPoint    = 0;
1960:     iCtx.maxPoints   = iCtx.numProcs;
1961:     PetscMalloc((iCtx.numProcs+1)     * sizeof(int),         &iCtx.numPoints);
1962:     PetscMalloc(iCtx.numProcs         * sizeof(int),         &iCtx.activeProcs);
1963:     PetscMalloc(iCtx.numProcs         * sizeof(int),         &iCtx.calcProcs);
1964:     PetscMalloc(iCtx.maxPoints*3      * sizeof(PetscScalar), &iCtx.coords);
1965:     PetscMalloc(iCtx.numProcs*maxComp * sizeof(PetscScalar), &iCtx.values);
1966:     PetscMemzero(iCtx.numPoints, (iCtx.numProcs+1) * sizeof(int));
1967:     PetscOptionsHasName(PETSC_NULL, "-grid_int_mode", &iCtx.batchMode);

1969:     /* Create new variable numbering and ghost structures */
1970:     if (explicitConstraints == PETSC_TRUE) {
1971:       grid->constraintOrder = PETSC_NULL;
1972:     } else {
1973:       grid->order         = PETSC_NULL;
1974:     }
1975:     grid->ghostVec        = PETSC_NULL;
1976:     reduceOrderOld        = grid->reduceOrder;
1977:     prevBdReduceVec       = grid->bdReduceVec;
1978:     prevBdReduceVecOld    = grid->bdReduceVecOld;
1979:     prevBdReduceVecDiff   = grid->bdReduceVecDiff;
1980:     grid->reduceOrder     = PETSC_NULL;
1981:     grid->bdReduceVec     = PETSC_NULL;
1982:     grid->bdReduceVecOld  = PETSC_NULL;
1983:     grid->bdReduceVecDiff = PETSC_NULL;
1984:     GridSetupGhostScatter(grid);
1985:     reduceOrder           = grid->reduceOrder;
1986:     bdReduceVec           = grid->bdReduceVec;
1987:     bdReduceVecOld        = grid->bdReduceVecOld;
1988:     bdReduceVecDiff       = grid->bdReduceVecDiff;
1989:     grid->reduceOrder     = reduceOrderOld;
1990:     grid->bdReduceVec     = prevBdReduceVec;
1991:     grid->bdReduceVecOld  = prevBdReduceVecOld;
1992:     grid->bdReduceVecDiff = prevBdReduceVecDiff;
1993:     if (grid->bdReduceVecCur == bdReduceVec) {
1994:       grid->bdReduceVecCur = grid->bdReduceVec;
1995:     } else if (grid->bdReduceVecCur == bdReduceVecOld) {
1996:       grid->bdReduceVecCur = grid->bdReduceVecOld;
1997:     } else if (grid->bdReduceVecCur == bdReduceVecDiff) {
1998:       grid->bdReduceVecCur = grid->bdReduceVecDiff;
1999:     } else {
2000:       SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid reduction vector");
2001:     }

2003:     /* Allocate structures */
2004:     if (explicitConstraints) {
2005:       GVecCreateConstrained(grid, y);
2006:     } else {
2007:       GVecCreate(grid, y);
2008:     }

2010:     /* Locally interpolate the solution values */
2011:     for(f = 0; f < numFields; f++) {
2012:       field = fields[f];
2013:       iCtx.field = field;
2014:       if (iCtx.batchMode == PETSC_FALSE) {
2015:         GVecEvaluateFunctionCollective(*y, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
2016:       } else {
2017:         GVecEvaluateFunction(*y, 1, &field, PointFunctionInterpolateField, 1.0, &iCtx);
2018:         GVecInterpolateFieldBatch(*y, field, &iCtx);
2019:         iCtx.curPoint = iCtx.numPoints[iCtx.rank];
2020:         GVecEvaluateFunction(*y, 1, &field, PointFunctionInterpolateFieldBatch, 1.0, &iCtx);
2021:         if (iCtx.curPoint != iCtx.numPoints[iCtx.rank+1])
2022:           SETERRQ(PETSC_ERR_PLIB, "Invalid batch point processing");
2023:       }
2024:     }
2025:     if (grid->bdReduceVecCur == grid->bdReduceVec) {
2026:       grid->bdReduceVecCur = bdReduceVec;
2027:     } else if (grid->bdReduceVecCur == grid->bdReduceVecOld) {
2028:       grid->bdReduceVecCur = bdReduceVecOld;
2029:     } else if (grid->bdReduceVecCur == grid->bdReduceVecDiff) {
2030:       grid->bdReduceVecCur = bdReduceVecDiff;
2031:     } else {
2032:       SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid reduction vector");
2033:     }
2034:     grid->reduceOrder     = reduceOrder;
2035:     grid->bdReduceVec     = bdReduceVec;
2036:     grid->bdReduceVecOld  = bdReduceVecOld;
2037:     grid->bdReduceVecDiff = bdReduceVecDiff;
2038:     if (grid->reduceSystem == PETSC_TRUE) {
2039:       VarOrderingDestroy(reduceOrderOld);
2040:       VecDestroy(prevBdReduceVec);
2041:       VecDestroy(prevBdReduceVecOld);
2042:       VecDestroy(prevBdReduceVecDiff);
2043:     }

2045:     VecNorm(*y, NORM_2, &norm);
2046:     PetscPrintf(PETSC_COMM_SELF, "Projected solution norm %gn", norm);

2048:     /* Destroy old structures */
2049:     VarOrderingDestroy(iCtx.order);
2050:     VecDestroy(iCtx.ghostVec);

2052:     /* Cleanup */
2053:     PetscFree(iCtx.numPoints);
2054:     PetscFree(iCtx.activeProcs);
2055:     PetscFree(iCtx.calcProcs);
2056:     PetscFree(iCtx.values);
2057:     PetscFree(iCtx.coords);
2058:     break;
2059:   case INTERPOLATION_HALO:
2060:   case INTERPOLATION_L2_LOCAL:
2061:     SETERRQ1(PETSC_ERR_SUP, "Interpolation type %d not yet supported", grid->interpolationType);
2062:   default:
2063:     SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid interpolation type %d", grid->interpolationType);
2064:   }
2065:   /* Anything specific to the implementation */
2066:   if (grid->ops->gridreform != PETSC_NULL) {
2067:     (*grid->ops->gridreform)(grid, oldMesh, x, y);
2068:   }
2069:   PetscLogEventEnd(GRID_Reform, grid, 0, 0, 0);
2070:   return(0);
2071: }