Actual source code: gts.c
1: #ifdef PETSC_RCS_HEADER
2: static char vcid[] = "$Id: gts.c,v 1.9 2000/01/10 03:54:19 knepley Exp $";
3: #endif
5: #include src/ts/tsimpl.h
6: #include src/gvec/gvecimpl.h
7: #include gsolver.h
9: /* Logging support */
10: int GTS_Reform, GTS_Reallocate;
12: /*
13: This file provides routines for grid TS objects. They support solution of
14: systems of time-dependent nonlinear equations generated from a mesh and
15: discretization specified by a Grid object.
16: */
18: /*@C
19: GTSDestroy - Destroys a grid TS.
21: Collective on GTS
23: Input Parameters:
24: . ts - The nonlinear solver context
26: Level: beginner
28: .keywords: grid TS, destroy
29: .seealso: TSDestroy(), GTSDuplicate()
30: @*/
31: int GTSDestroy(GTS ts)
32: {
33: TSProblemType type;
34: int ierr;
38: if (--ts->refct > 0)
39: return(0);
40: TSGetProblemType(ts, &type);
41: if (type == TS_LINEAR) {
42: GMatDestroy(ts->A);
43: }
44: PetscFree(ts->isExplicit);
45: PetscFree(ts->Iindex);
46: if (ts->snes) {
47: GSNESDestroy(ts->snes);
48: ts->snes = PETSC_NULL;
49: }
50: TSDestroy(ts);
51: return(0);
52: }
54: /*@
55: GTSView - Views a grid TS.
57: Collective on GTS
59: Input Parameters:
60: . ts - The grid TS
61: . viewer - An optional visualization context
63: Options Database Key:
64: $ -ts_view : calls TSView() at end of TSSolve()
66: Notes:
67: The available visualization contexts include
68: $ VIEWER_STDOUT_SELF - standard output (default)
69: $ VIEWER_STDOUT_WORLD - synchronized standard
70: $ output where only the first processor opens
71: $ the file. All other processors send their
72: $ data to the first processor to print.
74: The user can open alternative vistualization contexts with
75: $ PetscViewerFileOpenASCII() - output vector to a specified file
77: Level: beginner
79: .keywords: view, visualize, output, print, write, draw
80: .seealso: TSView()
81: @*/
82: int GTSView(GTS ts, PetscViewer viewer)
83: {
84: Grid grid;
85: FILE *fd;
86: int numActiveFields;
87: int field, func, op;
88: PetscTruth isascii;
89: int ierr;
93: if (!viewer) {
94: viewer = PETSC_VIEWER_STDOUT_SELF;
95: } else {
97: }
99: GTSGetGrid(ts, &grid);
100: PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_ASCII, &isascii);
101: if (isascii == PETSC_TRUE) {
102: GridView(grid, viewer);
103: PetscViewerFlush(viewer);
104: PetscViewerASCIIGetPointer(viewer, &fd);
105: PetscFPrintf(ts->comm, fd, "GTS Object:n");
106: GridGetNumActiveFields(grid, &numActiveFields);
107: if (numActiveFields == 1) {
108: PetscFPrintf(ts->comm, fd, " %d active field:n", numActiveFields);
109: } else {
110: PetscFPrintf(ts->comm, fd, " %d active fields:n", numActiveFields);
111: }
112: for(field = 0; field < grid->numFields; field++) {
113: if (grid->fields[field].isActive == PETSC_FALSE) continue;
114: if (grid->fields[field].name) {
115: PetscFPrintf(grid->comm, fd, " %s field with %d components:n", grid->fields[field].name, grid->fields[field].numComp);
116: } else {
117: PetscFPrintf(grid->comm, fd, " field %d with %d components:n", field, grid->fields[field].numComp);
118: }
119: if (ts->isExplicit[field]) PetscFPrintf(ts->comm, fd, " Explicitly time dependentn");
120: for(func = 0; func < grid->numRhsFuncs; func++) {
121: if (grid->rhsFuncs[func].field == field) {
122: PetscFPrintf(grid->comm, fd, " Rhs function with scalar multiplier %gn", PetscRealPart(grid->rhsFuncs[func].alpha));
123: }
124: }
125: for(op = 0; op < grid->numRhsOps; op++) {
126: if (grid->rhsOps[op].field == field) {
127: if (grid->rhsOps[op].nonlinearOp != PETSC_NULL) {
128: PetscFPrintf(grid->comm, fd, " Rhs nonlinear operator with scalar multiplier %gn",
129: PetscRealPart(grid->rhsOps[field].alpha));
130: } else {
131: PetscFPrintf(grid->comm, fd, " Rhs operator %d with scalar multiplier %gn",
132: grid->rhsOps[op].op, PetscRealPart(grid->rhsOps[op].alpha));
133: }
134: }
135: }
136: for(op = 0; op < grid->numMatOps; op++) {
137: if (grid->matOps[op].field == field) {
138: PetscFPrintf(grid->comm, fd, " Jacobian operator %d with scalar multiplier %gn",
139: grid->matOps[op].op, PetscRealPart(grid->matOps[op].alpha));
140: }
141: }
142: }
143: TSView(ts, viewer);
144: }
146: return(0);
147: }
149: /*@
150: GTSSerialize - This function stores or recreates a grid TS using a viewer for a binary file.
152: Collective on grid
154: Input Parameters:
155: . comm - The communicator for the grid TS object
156: . viewer - The viewer context
157: . store - This flag is PETSC_TRUE is data is being written, otherwise it will be read
159: Output Parameter:
160: . ts - The grid TS
162: Level: beginner
164: .keywords: grid TS, serialize
165: .seealso: GridSerialize()
166: @*/
167: int GTSSerialize(Grid grid, GTS *ts, PetscViewer viewer, PetscTruth store)
168: {
169: MPI_Comm comm;
170: int ierr;
176: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
177: GSolverInitializePackage(PETSC_NULL);
178: #endif
181: PetscObjectGetComm((PetscObject) grid, &comm);
182: /* We need a way to communicate the grid to the TS */
183: if (store == PETSC_FALSE) {
184: *ts = (GTS) grid;
185: }
186: TSSerialize(comm, ts, viewer, store);
187: /* Newly created object should have grid as a parent */
188: if (store == PETSC_FALSE) {
189: PetscObjectCompose((PetscObject) *ts, "Grid", (PetscObject) grid);
191: /* Set boundary conditions */
192: TSSetRhsBC(*ts, GTSRhsBC);
193: TSSetSolutionBC(*ts, GTSSolutionBC);
194: /* Save space/time by reducing the system at the element level */
195: if ((*ts)->problem_type == TS_NONLINEAR) {
196: GridSetReduceElement(grid, PETSC_TRUE);
197: }
199: /* Set update functions */
200: TSSetPreStep(*ts, GTSPreStep);
201: TSSetUpdate(*ts, GTSUpdate);
202: TSSetPostStep(*ts, GTSPostStep);
203: }
205: return(0);
206: }
208: /*@C
209: GTSDuplicate - Duplicates a grid TS.
211: Collective on GTS
213: Input Parameter:
214: . ts - The grid TS
216: Output Parameter:
217: . newts - The new grid TS
219: Level: beginner
221: .keywords: grid ts, duplicate
222: .seealso: TSDuplicate(), GTSDestroy()
223: @*/
224: int GTSDuplicate(GTS ts, GTS *newts)
225: {
228: SETERRQ(PETSC_ERR_SUP, " ");
229: #if 0
230: return(0);
231: #endif
232: }
234: /*@C
235: GTSReform - Cleans up any auxilliary structures in the GTS. Should
236: be called after GridReform(), but before any user specific changes
237: to the grid. Usually followed by GTSReallocate().
239: Collective on GTS
241: Input Parameter:
242: . ts - The grid TS
244: Level: advanced
246: .keywords: grid ts, reform
247: .seealso: GTSReallocate(), GridReform()
248: @*/
249: int GTSReform(GTS ts)
250: {
255: if (ts->ops->reform) {
256: PetscLogEventBegin(GTS_Reform, ts, 0, 0, 0);
257: (*ts->ops->reform)(ts);
258: PetscLogEventEnd(GTS_Reform, ts, 0, 0, 0);
259: }
260: return(0);
261: }
263: /*@C
264: GTSReallocate - Reallocates the storage for a grid TS. Should be
265: called after GTSReform() and any user updating of the grid.
267: Collective on GTS
269: Input Parameters:
270: . ts - The grid TS
271: . x - The new solution vector
273: Level: advanced
275: .keywords: grid ts, reallocate
276: .seealso: GTSReform(), GridReform()
277: @*/
278: int GTSReallocate(GTS ts, GVec x)
279: {
285: TSSetSolution(ts, x);
286: if (ts->ops->reallocate) {
287: PetscLogEventBegin(GTS_Reallocate, ts, 0, 0, 0);
288: (*ts->ops->reallocate)(ts);
289: PetscLogEventEnd(GTS_Reallocate, ts, 0, 0, 0);
290: }
291: return(0);
292: }
294: /*@
295: GTSGetGrid - Gets the grid from a grid TS.
297: Not collective
299: Input Parameter:
300: . ts - The grid TS
302: Output Parameter:
303: . grid - The grid context
305: Level: intermediate
307: .keywords: grid ts, get
308: .seealso: GVecGetGrid(), GMatGetGrid(), GSNESGetGrid()
309: @*/
310: int GTSGetGrid(GTS ts, Grid *grid)
311: {
318: PetscObjectQuery((PetscObject) ts, "Grid", (PetscObject *) grid);
320: return(0);
321: }
323: /*@
324: GTSGetInitialTimeStep - Returns the initial time step
326: Not collective
328: Input Parameter:
329: . ts - The grid TS
331: Output Parameter:
332: . dt - The initial time step
334: Level: intermediate
336: .keywords: grid ts, get, time step
337: .seealso: TSSetInitialTimeStep()
338: @*/
339: int GTSGetInitialTimeStep(GTS ts, double *dt)
340: {
344: *dt = ts->initial_time_step;
345: return(0);
346: }
348: /*@
349: GTSGetTimeDependence - Determines whether or not a field has
350: explicit time dependence.
352: Not collective
354: Input Parameters:
355: . ts - The grid TS
356: . field - The field
358: Output Parameter:
359: . flag - Indicates whether or not the field has explicit time dependence
361: Level: intermediate
363: .keywords: grid ts, get
364: .seealso: GTSSetTimeDependence()
365: @*/
366: int GTSGetTimeDependence(GTS ts, int field, PetscTruth *flag)
367: {
368: Grid grid;
369: int numFields;
370: int ierr;
375: GTSGetGrid(ts, &grid);
377: GridGetNumFields(grid, &numFields);
378: if ((field < 0) || (field > numFields)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number");
379: *flag = ts->isExplicit[field];
380: return(0);
381: }
383: /*@
384: GTSSetContext - Sets a user-defined context for use in calculation.
386: Collective on GTS
388: Input Parameters:
389: . ts - The grid TS
390: . ctx - The context
392: Level: intermediate
394: .keywords: grid ts, context
395: .seealso: GTSGetContext()
396: @*/
397: int GTSSetContext(GTS ts, void *ctx)
398: {
401: ts->funP = ctx;
402: ts->jacP = ctx;
403: return(0);
404: }
406: /*@
407: GTSSetTimeDependence - Sets the explicit time dependence of a field.
409: Collective on GTS
411: Input Parameters:
412: . ts - The grid TS
413: . field - The field
414: . flag - Indicates whether or not the field has explicit time dependence
416: Level: intermediate
418: .keywords: grid ts, get
419: .seealso: GTSGetTimeDependence()
420: @*/
421: int GTSSetTimeDependence(GTS ts, int field, PetscTruth flag)
422: {
423: Grid grid;
424: int numFields;
425: int ierr;
429: GTSGetGrid(ts, &grid);
431: GridGetNumFields(grid, &numFields);
432: if ((field < 0) || (field > numFields)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number");
433: ts->isExplicit[field] = flag;
434: return(0);
435: }
437: /*@
438: GTSEvaluateRhs - Constructs the Rhs vector for U_t = F(U, t).
440: Collective on GTS
442: Input Parameters:
443: . ts - The grid TS
444: . x - The current iterate
445: . ctx - The optional user context
447: Output Parameter:
448: . f - The function value
450: Level: advanced
452: .keywords: grid ts, rhs
453: .seealso: GSNESEvaluateRhs()
454: @*/
455: int GTSEvaluateRhs(GTS ts, double t, GVec x, GVec f, PetscObject ctx)
456: {
457: Grid grid;
458: PetscObject oldCtx;
459: PetscScalar zero = 0.0;
460: int ierr;
464: GTSGetGrid(ts, &grid);
466: /* Initialize vector */
467: VecSet(&zero, f);
468: /* Setup new context */
469: GTSCreateContext(ts, t, ctx, &oldCtx);
470: /* Form function */
471: GridEvaluateRhs(grid, x, f, ctx);
472: /* Cleanup */
473: GTSDestroyContext(ts, ctx, oldCtx);
474: return(0);
475: }
477: /*@
478: GTSEvaluateJacobian - Constructs the Jacobian matrix for U_t = F(U,t)
480: Collective on GTS
482: Input Parameters:
483: . ts - The grid TS
484: . x - The current iterate
485: . flag - The matrix structure flag
486: . ctx - The optional user context
488: Output Parameters:
489: . J - The Jacobian matrix
490: . M - The preconditioner for the Jacobian matrix, usually the same as J
492: Level: advanced
494: .keywords: grid ts, evaluate, jacobian
495: .seealso: SNESComputeJacobian(), GridEvaluateSystemMatrix()
496: @*/
497: int GTSEvaluateJacobian(GTS ts, double t, GVec x, GMat *J, GMat *M, MatStructure *flag, PetscObject ctx)
498: {
499: Grid grid;
500: PetscObject oldCtx;
501: int ierr;
505: GTSGetGrid(ts, &grid);
507: /* Initialize matrix */
508: MatZeroEntries(*J);
509: /* Setup new context */
510: GTSCreateContext(ts, t, ctx, &oldCtx);
511: /* Form function */
512: GridEvaluateSystemMatrix(grid, x, J, M, flag, ctx);
513: /* Apply boundary conditions */
514: GMatSetBoundary(*J, 1.0, ctx);
515: /* Cleanup */
516: GTSDestroyContext(ts, ctx, oldCtx);
517: return(0);
518: }
520: /*@
521: GTSEvaluateSystemMatrix - Constructs the system matrix for U_t = A(U,t) U
523: Collective on GTS
525: Input Parameters:
526: . ts - The grid TS
527: . flag - The matrix structure flag
528: . ctx - The optional user context
530: Output Parameters:
531: . A - The system matrix
532: . M - The preconditioner for the system matrix, usually the same as A
534: Level: advanced
536: .keywords: grid ts, evaluate, jacobian
537: .seealso: SNESComputeJacobian(), GridEvaluateSystemMatrix()
538: @*/
539: int GTSEvaluateSystemMatrix(GTS ts, double t, GMat *A, GMat *M, MatStructure *flag, PetscObject ctx)
540: {
541: Grid grid;
542: PetscObject oldCtx;
543: int ierr;
547: GTSGetGrid(ts, &grid);
549: /* Initialize matrix */
550: MatZeroEntries(*A);
551: /* Setup new context */
552: GTSCreateContext(ts, t, ctx, &oldCtx);
553: /* Form function */
554: GridEvaluateSystemMatrix(grid, PETSC_NULL, A, M, flag, ctx);
555: /* Apply boundary conditions */
556: GMatSetBoundary(*A, 1.0, ctx);
557: /* Cleanup */
558: GTSDestroyContext(ts, ctx, oldCtx);
559: return(0);
560: }
562: /*@
563: GTSCalcBCValues - This function calculates the boundary values. It
564: is normally called once a timestep when using time dependent boundary
565: conditions.
567: Collective on GTS
569: Input Parameter:
570: . ts - The GTS
572: Level: advanced
574: .keywords: grid ts, reduction, boundary conditions
575: .seealso: GridSetBCContext(), GridSetBC(), GridAddBC()
576: @*/
577: int GTSCalcBCValues(GTS ts)
578: {
579: Grid grid;
580: PetscObject oldCtx;
581: int ierr;
585: GTSGetGrid(ts, &grid);
586: /* Setup new context */
587: GTSCreateContext(ts, ts->ptime, (PetscObject) ts->funP, &oldCtx);
588: /* Form function */
589: GridCalcBCValues(grid, PETSC_TRUE, ts->funP);
590: /* Cleanup */
591: GTSDestroyContext(ts, (PetscObject) ts->funP, oldCtx);
592: return(0);
593: }
595: /*@
596: GTSRhsBC - This sets the boundary conditions registered with the grid
597: on the Rhs vector, or zero boundary conditions for nonlinear systems.
599: Collective on GTS
601: Input Parameters:
602: . ts - The TS context obtained from TSCreate()
603: . ctx - The user-supplied context
605: Output Parameter:
606: . rhs - The Rhs
608: Level: advanced
610: .keywords: grid ts, timestep, set, boundary conditions
611: .seealso: GridSetBCContext(), GridSetBC(), GridAddBC()
612: @*/
613: int GTSRhsBC(GTS ts, GVec rhs, void *ctx)
614: {
615: TSProblemType type;
616: PetscObject oldCtx;
617: int ierr;
622: TSGetProblemType(ts, &type);
623: /* Setup new context */
624: GTSCreateContext(ts, ts->ptime, (PetscObject) ctx, &oldCtx);
625: switch(type)
626: {
627: case TS_LINEAR:
628: GVecSetBoundary(rhs, ctx);
629: break;
630: case TS_NONLINEAR:
631: GVecSetBoundaryZero(rhs, ctx);
632: /* TSGetSolution(ts, &u); */
633: /* GVecSetBoundaryDifference(rhs, u, >Sctx); */
634: break;
635: default:
636: SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid TS problem type %d", type);
637: }
638: /* Cleanup */
639: GTSDestroyContext(ts, (PetscObject) ctx, oldCtx);
640: return(0);
641: }
643: /*@
644: GTSSolutionBC - This sets the boundary conditions registered with the grid
645: on the solution vector.
647: Collective on GTS
649: Input Parameters:
650: . ts - The TS context obtained from TSCreate()
651: . ctx - The user-supplied context
653: Output Parameter:
654: . sol - The solution
656: Level: advanced
658: .keywords: grid ts, timestep, set, boundary conditions
659: .seealso: GridSetBCContext(), GridSetBC(), GridAddBC()
660: @*/
661: int GTSSolutionBC(GTS ts, GVec sol, void *ctx)
662: {
663: PetscObject oldCtx;
664: int ierr;
669: /* Setup new context */
670: GTSCreateContext(ts, ts->ptime, (PetscObject) ctx, &oldCtx);
671: /* Apply solution BC */
672: GVecSetBoundary(sol, ctx);
673: /* Cleanup */
674: GTSDestroyContext(ts, (PetscObject) ctx, oldCtx);
675: return(0);
676: }
678: /*@
679: GTSSolutionBCforGSNES - This functions allows a GSNES
680: imbedded in a GTS to correctly set time dependent boundary
681: conditions on the initial solution at each time step.
683: Collective on GTS
685: Input Parameters:
686: . ts - The TS context obtained from TSCreate()
687: . ctx - The user-supplied context
689: Output Parameter:
690: . sol - The solution
692: Level: advanced
694: .keywords: grid ts, timestep, set, boundary conditions
695: .seealso: GridSetBCContext(), GridSetBC(), GridAddBC()
696: @*/
697: int GTSSolutionBCforGSNES(GSNES snes, GVec sol, void *ctx)
698: {
699: GTS ts = (GTS) ctx;
705: GTSSolutionBC(ts, sol, ts->funP);
706: return(0);
707: }
709: /*@
710: GTSPreStep - This is a general purpose function which
711: is called once at the beginning of time stepping. It
712: currently performs context wrapping and grid manipulation.
714: Collective on GTS
716: Input Parameters:
717: . ts - The GTS context
719: Level: advanced
721: .keywords: grid ts, timestep
722: .seealso: GTSUpdate(), GTSPostStep()
723: @*/
724: int GTSPreStep(GTS ts)
725: {
726: Grid grid;
727: PetscScalar mdt = 1.0/ts->time_step;
728: PetscTruth isTimeDependent;
729: int numFields;
730: int field, f;
731: int ierr;
736: /* Scale Rhs so we get u_t - F = 0 */
737: GTSGetGrid(ts, &grid);
738: GridScaleRhs(grid, -1.0);
740: /* Add the identity operator and scale to get J = Delta t^{-1} I - J_{F} where J_{F} is the given Jacobian of F */
741: GridScaleSystemMatrix(grid, -1.0);
742: GridGetNumActiveFields(grid, &numFields);
743: for(f = 0; f < numFields; f++) {
744: GridGetActiveField(grid, f, &field);
745: GTSGetTimeDependence(ts, field, &isTimeDependent);
746: if (isTimeDependent) {
747: GridAddMatOperator(grid, field, field, IDENTITY, mdt, PETSC_FALSE, &ts->Iindex[field]);
748: }
749: }
751: return(0);
752: }
754: /*@
755: GTSUpdate - This is a general purpose function which
756: is called at the beginning of every time step. It
757: currently calculates the mesh acceleration and moves
758: the mesh.
760: Collective on GTS
762: Input Parameters:
763: . ts - The GTS context
764: . t - The current time
766: Output Parameter:
767: . dt - The current time step
769: Level: advanced
771: .keywords: grid ts, timestep
772: .seealso: GTSPreStep(), GTSPostStep()
773: @*/
774: int GTSUpdate(GTS ts, PetscReal t, PetscReal *dt)
775: {
776: Grid grid;
777: Mesh mesh;
778: MeshMover mover;
779: int ierr;
784: GTSGetGrid(ts, &grid);
785: GridGetMesh(grid, &mesh);
786: MeshGetMover(mesh, &mover);
787: /* Calculate mesh acceleration */
788: MeshMoverCalcNodeAccelerations(mover, PETSC_TRUE);
789: /* Move the mesh */
790: MeshMoveMesh(mesh, ts->time_step);
791: return(0);
792: }
794: /*@
795: GTSPostStep - This is a general purpose function which
796: is called once at the end of time stepping. It currently
797: performs context unwrapping and grid manipulation.
799: Collective on GTS
801: Input Parameters:
802: . ts - The GTS context
804: Level: advanced
806: .keywords: grid ts, timestep
807: .seealso: GTSPreStep(), GTSUpdate()
808: @*/
809: int GTSPostStep(GTS ts)
810: {
811: Grid grid;
812: PetscTruth isTimeDependent;
813: int numFields;
814: int field, f;
815: int ierr;
820: /* Scale Rhs back to the original state */
821: GTSGetGrid(ts, &grid);
822: GridScaleRhs(grid, -1.0);
824: /* Remove the identity and scale back */
825: GridScaleSystemMatrix(grid, -1.0);
826: GridGetNumActiveFields(grid, &numFields);
827: for(f = 0; f < numFields; f++) {
828: GridGetActiveField(grid, f, &field);
829: GTSGetTimeDependence(ts, field, &isTimeDependent);
830: if (isTimeDependent) {
831: /* GridRemoveMatOperator(grid, ts->Iindex[field]); */
832: }
833: }
835: return(0);
836: }
838: /*@
839: GTSCreate - Creates a grid TS associated with a
840: particular discretization context.
842: Collective on Grid
844: Input Parameter:
845: . grid - The discretization context
846: . ctx - The optional user context
848: Output Parameter:
849: . ts - The integrator context
851: Level: beginner
853: Note:
854: The TS type is TS_NONLINEAR if any nonlinear operators have
855: been activated on the grid.
857: .keywords: grid ts, create
858: .seealso: TSCreate(), TSSetType()
859: @*/
860: int GTSCreate(Grid grid, void *ctx, GTS *ts)
861: {
862: MPI_Comm comm;
863: TSProblemType type;
864: GTS gts;
865: GMat A;
866: int numFields, numRhsOps;
867: int field, op;
868: int ierr;
873: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
874: GSolverInitializePackage(PETSC_NULL);
875: #endif
877: /* Get TS type */
878: type = TS_LINEAR;
879: GridGetNumRhsOperators(grid, &numRhsOps);
880: for(op = 0; op < grid->numRhsOps; op++) {
881: if (grid->rhsOps[op].nonlinearOp != PETSC_NULL) {
882: type = TS_NONLINEAR;
883: break;
884: }
885: }
887: /* Create the TS */
888: PetscObjectGetComm((PetscObject) grid, &comm);
889: TSCreate(comm, >s);
890: TSSetProblemType(gts, type);
891: gts->isGTS = PETSC_TRUE;
892: gts->bops->destroy = (int (*)(PetscObject)) GTSDestroy;
893: gts->bops->view = (int (*)(PetscObject, PetscViewer)) GTSView;
895: /* Set boundary conditions */
896: TSSetRhsBC(gts, GTSRhsBC);
897: TSSetSolutionBC(gts, GTSSolutionBC);
898: /* Save space/time by reducing the system at the element level */
899: if (type == TS_NONLINEAR) {
900: GridSetReduceElement(grid, PETSC_TRUE);
901: }
903: /* Set update functions */
904: TSSetPreStep(gts, GTSPreStep);
905: TSSetUpdate(gts, GTSUpdate);
906: TSSetPostStep(gts, GTSPostStep);
908: /* Create the array which indicates time dependent fields */
909: GridGetNumFields(grid, &numFields);
910: PetscMalloc(numFields * sizeof(PetscTruth), >s->isExplicit);
911: PetscLogObjectMemory(gts, numFields * sizeof(PetscTruth));
912: for(field = 0; field < numFields; field++) {
913: gts->isExplicit[field] = PETSC_TRUE;
914: }
916: /* Create the array which holds the index of the identity operator for each time dependent field */
917: PetscMalloc(numFields * sizeof(int), >s->Iindex);
918: PetscLogObjectMemory(gts, numFields * sizeof(int));
919: for(field = 0; field < numFields; field++)
920: gts->Iindex[field] = -1;
922: /* Setup TS data structures */
923: gts->funP = ctx;
924: gts->jacP = ctx;
925: if (type == TS_LINEAR) {
926: GMatCreate(grid, &A);
927: gts->A = A;
928: gts->B = A;
929: PetscLogObjectParent(grid, A);
930: }
932: PetscObjectCompose((PetscObject) gts, "Grid", (PetscObject) grid);
933: *ts = gts;
934: return(0);
935: }
937: /*@
938: GTSSolutionMonitor - Monitors solution at each GTS iteration.
940: Collective on GTS
942: Input Parameters:
943: . ts - The integrator context
944: . step - The current time step
945: . ltime - The current time
946: . sol - The current solution vector
947: . ctx - The viewer
949: Level: intermediate
951: .keywords: grid ts, monitor, solution
952: .seealso: TSDefaultMonitor(),TSSetMonitor(),GTSResidualMonitor(),
953: GTSErrorMonitor()
954: @*/
955: int GTSSolutionMonitor(GTS ts, int step, PetscReal ltime, GVec sol, void *ctx)
956: {
957: PetscViewer viewer = (PetscViewer) ctx;
958: int ierr;
963: GVecView(sol, viewer);
964: return(0);
965: }
967: /*@
968: GTSErrorMonitor - Displays the error at each iteration.
970: Collective on GTS
972: Input Parameters:
973: + ts - The integrator context
974: . step - The current time step
975: . ltime - The current time
976: . sol - The current solution vector
977: - monCtx - The GTSErrorMonitorCxt
979: Notes:
980: The final argument to TSSetMonitor() with this routine must be
981: a pointer to a GTSErrorMonitorCtx.
983: Level: intermediate
985: .keywords: grid ts, monitor, error
986: .seealso: TSDefaultMonitor(),TSSetMonitor(),GTSSolutionMonitor(), GTSResidualMonitor()
987: @*/
988: int GTSErrorMonitor(GTS ts, int step, PetscReal ltime, GVec sol, void *monCtx)
989: {
990: GTSErrorMonitorCtx *errorCtx = (GTSErrorMonitorCtx *) monCtx;
991: PetscObject oldCtx;
992: PetscScalar minusOne = -1.0;
993: GVec e;
994: MPI_Comm comm;
995: FILE *file;
996: PetscReal norm_2, norm_max, sol_norm_2;
997: int ierr;
1003: GTSCreateContext(ts, ltime, (PetscObject) errorCtx->ctx, &oldCtx);
1004: (*errorCtx->solutionFunc)(errorCtx->solution, errorCtx->ctx);
1005: GVecGetWorkGVec(errorCtx->solution, &e);
1006: VecWAXPY(&minusOne, sol, errorCtx->solution, e);
1007: GVecView(e, errorCtx->error_viewer);
1008: GTSDestroyContext(ts, (PetscObject) errorCtx->ctx, oldCtx);
1010: /* Compute 2-norm and max-norm of error */
1011: if (errorCtx->norm_error_viewer) {
1012: PetscObjectGetComm((PetscObject) ts, &comm);
1013: PetscViewerASCIIGetPointer(errorCtx->norm_error_viewer, &file);
1014: VecNorm(e, NORM_2, &norm_2);
1015: VecNorm(e, NORM_MAX, &norm_max);
1016: VecNorm(errorCtx->solution, NORM_2, &sol_norm_2);
1017: PetscFPrintf(comm, file, "Timestep %d time %g error 2-norm %g error max-norm %g exact sol 2-norm %gn",
1018: step, ltime, norm_2, norm_max, sol_norm_2);
1019: }
1020: GVecRestoreWorkGVec(errorCtx->solution, &e);
1021: return(0);
1022: }
1024: EXTERN_C_BEGIN
1025: int GTSOptionsChecker_Private(GTS ts)
1026: {
1027: char *prefix;
1028: int loc[4], nmax;
1029: MPI_Comm comm;
1030: PetscViewer viewer;
1031: PetscDraw draw;
1032: PetscTruth opt;
1033: int ierr;
1036: TSGetOptionsPrefix(ts, &prefix);
1037: PetscObjectGetComm((PetscObject) ts, &comm);
1039: nmax = 4;
1040: loc[0] = PETSC_DECIDE; loc[1] = PETSC_DECIDE; loc[2] = 300; loc[3] = 300;
1041: PetscOptionsGetIntArray(prefix, "-gvec_ts_solutionmonitor", loc, &nmax, &opt);
1042: if (opt) {
1043: PetscViewerDrawOpen(comm, 0, 0, loc[0], loc[1], loc[2], loc[3], &viewer);
1044: PetscViewerDrawGetDraw(viewer, 0, &draw);
1045: PetscDrawSetTitle(draw, "Approx. Solution");
1046: PetscLogObjectParent(ts, (PetscObject) viewer);
1047: TSSetMonitor(ts, GTSSolutionMonitor, (void *) viewer, PETSC_NULL);
1048: }
1049: #if 0
1050: nmax = 4;
1051: loc[0] = PETSC_DECIDE; loc[1] = PETSC_DECIDE; loc[2] = 300; loc[3] = 300;
1052: PetscOptionsGetIntArray(prefix, "-gvec_ts_errormonitor", loc, &nmax, &opt);
1053: if (opt) {
1054: PetscViewerDrawOpenX(comm, 0, 0, loc[0], loc[1], loc[2], loc[3], &viewer);
1055: PetscViewerDrawGetDraw(viewer, &draw);
1056: PetscDrawSetTitle(draw, "Error");
1057: PetscLogObjectParent(ts, (PetscObject) viewer);
1058: TSSetMonitor(ts, GTSErrorMonitor, (void *) viewer);
1059: }
1060: #endif
1061: /*--------------------------------------------------------------------- */
1062: PetscOptionsHasName(PETSC_NULL, "-help", &opt);
1063: if (opt) {
1064: char *pprefix;
1065: int len = 2;
1066: if (prefix != PETSC_NULL) {
1067: PetscStrlen(prefix, &len);
1068: }
1069: PetscMalloc((len+2) * sizeof(char), &pprefix);
1070: PetscStrcpy(pprefix, "-");
1071: if (prefix != PETSC_NULL)
1072: PetscStrcat(pprefix, prefix);
1073: PetscPrintf(comm," Additional TS Monitor options for grid vectorsn");
1074: PetscPrintf(comm," %sgvec_ts_solutionmonitorn", pprefix);
1075: PetscPrintf(comm," %sgvec_ts_errormonitor -- not working yetn", pprefix);
1076: PetscFree(pprefix);
1077: }
1078: return(0);
1079: }
1080: EXTERN_C_END
1082: /*---------------------------------------------- Context Functions --------------------------------------------------*/
1083: EXTERN_C_BEGIN
1084: int GTSContextDestroy_Private(GTSContext ctx)
1085: {
1087: if (--ctx->refct > 0)
1088: return(0);
1089: PetscLogObjectDestroy(ctx);
1090: PetscHeaderDestroy(ctx);
1091: return(0);
1092: }
1093: EXTERN_C_END
1095: /*@
1096: GTSCreateContext - This functions creates a GTSContext attached to the given context.
1098: Collective on GTS
1100: Input Parameters:
1101: . ts - The GTS
1102: . ltime - The time for the context
1103: . ctx - The parent context
1105: Output Parameter:
1106: . oldCtx - The previous GTSContext
1108: Level: developer
1110: .keywords: grid ts, context, create
1111: .seealso: GTSDestroyContext(), GTSCreateConstraintContext()
1112: @*/
1113: int GTSCreateContext(GTS ts, double ltime, PetscObject ctx, PetscObject *oldCtx)
1114: {
1115: GTSContext GTSctx;
1116: int ierr;
1119: /* Preserve previous context */
1120: PetscObjectQuery(ctx, "GTSContext", oldCtx);
1121: if (*oldCtx != PETSC_NULL) {
1122: PetscObjectReference(*oldCtx);
1123: }
1124: /* Setup new context */
1125: PetscHeaderCreate(GTSctx, _GTSContext, int, TS_COOKIE, -1, "context", ts->comm, GTSContextDestroy_Private, 0);
1126: PetscLogObjectCreate(GTSctx);
1127: GTSctx->t = ltime;
1128: GTSctx->dt = ts->time_step;
1129: GTSctx->sol = ts->vec_sol;
1130: GTSctx->nwork = ts->nwork;
1131: GTSctx->work = ts->work;
1132: PetscObjectCompose(ctx, "GTSContext", (PetscObject) GTSctx);
1133: /* This makes sure the context is destroyed when the object is destroyed */
1134: PetscObjectDereference((PetscObject) GTSctx);
1135: return(0);
1136: }
1138: /*@
1139: GTSDestroyContext - This functions destroys a GTSContext attached to the given context and
1140: reattaches the old context.
1142: Collective on GTS
1144: Input Parameters:
1145: . ts - The GTS
1146: . ctx - The parent context
1147: . oldCtx - The previous GTSContext
1149: Level: developer
1151: .keywords: grid ts, context, destroy
1152: .seealso: GTSCreateContext(), GTSCreateConstraintContext()
1153: @*/
1154: int GTSDestroyContext(GTS ts, PetscObject ctx, PetscObject oldCtx)
1155: {
1159: if (oldCtx != PETSC_NULL) {
1160: /* Restore previous context -- New one is destroyed automatically */
1161: PetscObjectCompose(ctx, "GTSContext", oldCtx);
1162: PetscObjectDereference(oldCtx);
1163: }
1164: return(0);
1165: }
1167: /*@
1168: GTSCreateConstraintContext - This functions creates a GTSContext attached to the
1169: constraint context of the underlying grid.
1171: Collective on GTS
1173: Input Parameter:
1174: . ts - The GTS
1176: Level: developer
1178: .keywords: grid ts, context
1179: .seealso: GTSCreateContext(), GTSDestroyContext()
1180: @*/
1181: int GTSCreateConstraintContext(GTS ts)
1182: {
1183: Grid grid;
1184: PetscTruth isConstrained;
1185: PetscConstraintObject constCtx;
1186: PetscObject oldCtx;
1187: int ierr;
1191: if (ts->isGTS == PETSC_FALSE)
1192: return(0);
1193: GTSGetGrid(ts, &grid);
1194: GridIsConstrained(grid, &isConstrained);
1195: if (isConstrained == PETSC_TRUE) {
1196: GridGetConstraintContext(grid, &constCtx);
1197: GTSCreateContext(ts, ts->ptime, (PetscObject) constCtx, &oldCtx);
1198: /* Remove the extra reference from GTSCreateContext() */
1199: if (oldCtx != PETSC_NULL) {
1200: PetscObjectDereference(oldCtx);
1201: }
1202: }
1203: return(0);
1204: }