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