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, &GTSctx);                                                  */
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, &gts);
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), &gts->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), &gts->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: }