xref: /petsc/src/ts/interface/tsmon.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
1 #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2 #include <petscdm.h>
3 #include <petscds.h>
4 #include <petscdmswarm.h>
5 #include <petscdraw.h>
6 
7 /*@C
8    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
9 
10    Collective on TS
11 
12    Input Parameters:
13 +  ts - time stepping context obtained from TSCreate()
14 .  step - step number that has just completed
15 .  ptime - model time of the state
16 -  u - state at the current model time
17 
18    Notes:
19    TSMonitor() is typically used automatically within the time stepping implementations.
20    Users would almost never call this routine directly.
21 
22    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
23 
24    Level: developer
25 
26 @*/
27 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
28 {
29   DM             dm;
30   PetscInt       i,n = ts->numbermonitors;
31 
32   PetscFunctionBegin;
33   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
34   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
35 
36   CHKERRQ(TSGetDM(ts,&dm));
37   CHKERRQ(DMSetOutputSequenceNumber(dm,step,ptime));
38 
39   CHKERRQ(VecLockReadPush(u));
40   for (i=0; i<n; i++) {
41     CHKERRQ((*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]));
42   }
43   CHKERRQ(VecLockReadPop(u));
44   PetscFunctionReturn(0);
45 }
46 
47 /*@C
48    TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
49 
50    Collective on TS
51 
52    Input Parameters:
53 +  ts - TS object you wish to monitor
54 .  name - the monitor type one is seeking
55 .  help - message indicating what monitoring is done
56 .  manual - manual page for the monitor
57 .  monitor - the monitor function
58 -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the TS or PetscViewer objects
59 
60    Level: developer
61 
62 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
63           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
64           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
65           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
66           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
67           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
68           PetscOptionsFList(), PetscOptionsEList()
69 @*/
70 PetscErrorCode  TSMonitorSetFromOptions(TS ts,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(TS,PetscViewerAndFormat*))
71 {
72   PetscViewer       viewer;
73   PetscViewerFormat format;
74   PetscBool         flg;
75 
76   PetscFunctionBegin;
77   CHKERRQ(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg));
78   if (flg) {
79     PetscViewerAndFormat *vf;
80     CHKERRQ(PetscViewerAndFormatCreate(viewer,format,&vf));
81     CHKERRQ(PetscObjectDereference((PetscObject)viewer));
82     if (monitorsetup) {
83       CHKERRQ((*monitorsetup)(ts,vf));
84     }
85     CHKERRQ(TSMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy));
86   }
87   PetscFunctionReturn(0);
88 }
89 
90 /*@C
91    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
92    timestep to display the iteration's  progress.
93 
94    Logically Collective on TS
95 
96    Input Parameters:
97 +  ts - the TS context obtained from TSCreate()
98 .  monitor - monitoring routine
99 .  mctx - [optional] user-defined context for private data for the
100              monitor routine (use NULL if no context is desired)
101 -  monitordestroy - [optional] routine that frees monitor context
102           (may be NULL)
103 
104    Calling sequence of monitor:
105 $    PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
106 
107 +    ts - the TS context
108 .    steps - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
109 .    time - current time
110 .    u - current iterate
111 -    mctx - [optional] monitoring context
112 
113    Notes:
114    This routine adds an additional monitor to the list of monitors that
115    already has been loaded.
116 
117    Fortran Notes:
118     Only a single monitor function can be set for each TS object
119 
120    Level: intermediate
121 
122 .seealso: TSMonitorDefault(), TSMonitorCancel()
123 @*/
124 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
125 {
126   PetscInt       i;
127   PetscBool      identical;
128 
129   PetscFunctionBegin;
130   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
131   for (i=0; i<ts->numbermonitors;i++) {
132     CHKERRQ(PetscMonitorCompare((PetscErrorCode (*)(void))monitor,mctx,mdestroy,(PetscErrorCode (*)(void))ts->monitor[i],ts->monitorcontext[i],ts->monitordestroy[i],&identical));
133     if (identical) PetscFunctionReturn(0);
134   }
135   PetscCheck(ts->numbermonitors < MAXTSMONITORS,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
136   ts->monitor[ts->numbermonitors]          = monitor;
137   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
138   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
139   PetscFunctionReturn(0);
140 }
141 
142 /*@C
143    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
144 
145    Logically Collective on TS
146 
147    Input Parameters:
148 .  ts - the TS context obtained from TSCreate()
149 
150    Notes:
151    There is no way to remove a single, specific monitor.
152 
153    Level: intermediate
154 
155 .seealso: TSMonitorDefault(), TSMonitorSet()
156 @*/
157 PetscErrorCode  TSMonitorCancel(TS ts)
158 {
159   PetscInt       i;
160 
161   PetscFunctionBegin;
162   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
163   for (i=0; i<ts->numbermonitors; i++) {
164     if (ts->monitordestroy[i]) {
165       CHKERRQ((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
166     }
167   }
168   ts->numbermonitors = 0;
169   PetscFunctionReturn(0);
170 }
171 
172 /*@C
173    TSMonitorDefault - The Default monitor, prints the timestep and time for each step
174 
175    Level: intermediate
176 
177 .seealso:  TSMonitorSet()
178 @*/
179 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
180 {
181   PetscViewer    viewer =  vf->viewer;
182   PetscBool      iascii,ibinary;
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,5);
186   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
187   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary));
188   CHKERRQ(PetscViewerPushFormat(viewer,vf->format));
189   if (iascii) {
190     CHKERRQ(PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel));
191     if (step == -1) { /* this indicates it is an interpolated solution */
192       CHKERRQ(PetscViewerASCIIPrintf(viewer,"Interpolated solution at time %g between steps %D and %D\n",(double)ptime,ts->steps-1,ts->steps));
193     } else {
194       CHKERRQ(PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n"));
195     }
196     CHKERRQ(PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel));
197   } else if (ibinary) {
198     PetscMPIInt rank;
199     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank));
200     if (!rank) {
201       PetscBool skipHeader;
202       PetscInt  classid = REAL_FILE_CLASSID;
203 
204       CHKERRQ(PetscViewerBinaryGetSkipHeader(viewer,&skipHeader));
205       if (!skipHeader) {
206          CHKERRQ(PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT));
207        }
208       CHKERRQ(PetscRealView(1,&ptime,viewer));
209     } else {
210       CHKERRQ(PetscRealView(0,&ptime,viewer));
211     }
212   }
213   CHKERRQ(PetscViewerPopFormat(viewer));
214   PetscFunctionReturn(0);
215 }
216 
217 /*@C
218    TSMonitorExtreme - Prints the extreme values of the solution at each timestep
219 
220    Level: intermediate
221 
222 .seealso:  TSMonitorSet()
223 @*/
224 PetscErrorCode TSMonitorExtreme(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
225 {
226   PetscViewer    viewer =  vf->viewer;
227   PetscBool      iascii;
228   PetscReal      max,min;
229 
230   PetscFunctionBegin;
231   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,5);
232   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
233   CHKERRQ(PetscViewerPushFormat(viewer,vf->format));
234   if (iascii) {
235     CHKERRQ(VecMax(v,NULL,&max));
236     CHKERRQ(VecMin(v,NULL,&min));
237     CHKERRQ(PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel));
238     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s max %g min %g\n",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)" : "",(double)max,(double)min));
239     CHKERRQ(PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel));
240   }
241   CHKERRQ(PetscViewerPopFormat(viewer));
242   PetscFunctionReturn(0);
243 }
244 
245 /*@C
246    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
247    TS to monitor the solution process graphically in various ways
248 
249    Collective on TS
250 
251    Input Parameters:
252 +  host - the X display to open, or null for the local machine
253 .  label - the title to put in the title bar
254 .  x, y - the screen coordinates of the upper left coordinate of the window
255 .  m, n - the screen width and height in pixels
256 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
257 
258    Output Parameter:
259 .  ctx - the context
260 
261    Options Database Key:
262 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
263 +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
264 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
265 .  -ts_monitor_lg_error -  monitor the error
266 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
267 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
268 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
269 
270    Notes:
271    Use TSMonitorLGCtxDestroy() to destroy.
272 
273    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
274 
275    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
276    first argument (if that TS object does not have a TSMonitorLGCtx associated with it the function call is ignored) and the second takes a TSMonitorLGCtx object
277    as the first argument.
278 
279    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
280 
281    Level: intermediate
282 
283 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
284            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
285            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
286            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
287            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
288 
289 @*/
290 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
291 {
292   PetscDraw      draw;
293 
294   PetscFunctionBegin;
295   CHKERRQ(PetscNew(ctx));
296   CHKERRQ(PetscDrawCreate(comm,host,label,x,y,m,n,&draw));
297   CHKERRQ(PetscDrawSetFromOptions(draw));
298   CHKERRQ(PetscDrawLGCreate(draw,1,&(*ctx)->lg));
299   CHKERRQ(PetscDrawLGSetFromOptions((*ctx)->lg));
300   CHKERRQ(PetscDrawDestroy(&draw));
301   (*ctx)->howoften = howoften;
302   PetscFunctionReturn(0);
303 }
304 
305 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
306 {
307   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
308   PetscReal      x   = ptime,y;
309 
310   PetscFunctionBegin;
311   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
312   if (!step) {
313     PetscDrawAxis axis;
314     const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
315     CHKERRQ(PetscDrawLGGetAxis(ctx->lg,&axis));
316     CHKERRQ(PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time",ylabel));
317     CHKERRQ(PetscDrawLGReset(ctx->lg));
318   }
319   CHKERRQ(TSGetTimeStep(ts,&y));
320   if (ctx->semilogy) y = PetscLog10Real(y);
321   CHKERRQ(PetscDrawLGAddPoint(ctx->lg,&x,&y));
322   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
323     CHKERRQ(PetscDrawLGDraw(ctx->lg));
324     CHKERRQ(PetscDrawLGSave(ctx->lg));
325   }
326   PetscFunctionReturn(0);
327 }
328 
329 /*@C
330    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
331    with TSMonitorLGCtxCreate().
332 
333    Collective on TSMonitorLGCtx
334 
335    Input Parameter:
336 .  ctx - the monitor context
337 
338    Level: intermediate
339 
340 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
341 @*/
342 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
343 {
344   PetscFunctionBegin;
345   if ((*ctx)->transformdestroy) {
346     CHKERRQ(((*ctx)->transformdestroy)((*ctx)->transformctx));
347   }
348   CHKERRQ(PetscDrawLGDestroy(&(*ctx)->lg));
349   CHKERRQ(PetscStrArrayDestroy(&(*ctx)->names));
350   CHKERRQ(PetscStrArrayDestroy(&(*ctx)->displaynames));
351   CHKERRQ(PetscFree((*ctx)->displayvariables));
352   CHKERRQ(PetscFree((*ctx)->displayvalues));
353   CHKERRQ(PetscFree(*ctx));
354   PetscFunctionReturn(0);
355 }
356 
357 /* Creates a TS Monitor SPCtx for use with DMSwarm particle visualizations */
358 PetscErrorCode TSMonitorSPCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,PetscInt retain,PetscBool phase,TSMonitorSPCtx *ctx)
359 {
360   PetscDraw      draw;
361 
362   PetscFunctionBegin;
363   CHKERRQ(PetscNew(ctx));
364   CHKERRQ(PetscDrawCreate(comm,host,label,x,y,m,n,&draw));
365   CHKERRQ(PetscDrawSetFromOptions(draw));
366   CHKERRQ(PetscDrawSPCreate(draw,1,&(*ctx)->sp));
367   CHKERRQ(PetscDrawDestroy(&draw));
368   (*ctx)->howoften = howoften;
369   (*ctx)->retain   = retain;
370   (*ctx)->phase    = phase;
371   PetscFunctionReturn(0);
372 }
373 
374 /*
375   Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate
376 */
377 PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
378 {
379   PetscFunctionBegin;
380 
381   CHKERRQ(PetscDrawSPDestroy(&(*ctx)->sp));
382   CHKERRQ(PetscFree(*ctx));
383 
384   PetscFunctionReturn(0);
385 
386 }
387 
388 /*@C
389    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
390    VecView() for the solution at each timestep
391 
392    Collective on TS
393 
394    Input Parameters:
395 +  ts - the TS context
396 .  step - current time-step
397 .  ptime - current time
398 -  dummy - either a viewer or NULL
399 
400    Options Database:
401 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
402 
403    Notes:
404     the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
405        will look bad
406 
407    Level: intermediate
408 
409 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
410 @*/
411 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
412 {
413   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
414   PetscDraw        draw;
415 
416   PetscFunctionBegin;
417   if (!step && ictx->showinitial) {
418     if (!ictx->initialsolution) {
419       CHKERRQ(VecDuplicate(u,&ictx->initialsolution));
420     }
421     CHKERRQ(VecCopy(u,ictx->initialsolution));
422   }
423   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
424 
425   if (ictx->showinitial) {
426     PetscReal pause;
427     CHKERRQ(PetscViewerDrawGetPause(ictx->viewer,&pause));
428     CHKERRQ(PetscViewerDrawSetPause(ictx->viewer,0.0));
429     CHKERRQ(VecView(ictx->initialsolution,ictx->viewer));
430     CHKERRQ(PetscViewerDrawSetPause(ictx->viewer,pause));
431     CHKERRQ(PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE));
432   }
433   CHKERRQ(VecView(u,ictx->viewer));
434   if (ictx->showtimestepandtime) {
435     PetscReal xl,yl,xr,yr,h;
436     char      time[32];
437 
438     CHKERRQ(PetscViewerDrawGetDraw(ictx->viewer,0,&draw));
439     CHKERRQ(PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime));
440     CHKERRQ(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr));
441     h    = yl + .95*(yr - yl);
442     CHKERRQ(PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time));
443     CHKERRQ(PetscDrawFlush(draw));
444   }
445 
446   if (ictx->showinitial) {
447     CHKERRQ(PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE));
448   }
449   PetscFunctionReturn(0);
450 }
451 
452 /*@C
453    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
454 
455    Collective on TS
456 
457    Input Parameters:
458 +  ts - the TS context
459 .  step - current time-step
460 .  ptime - current time
461 -  dummy - either a viewer or NULL
462 
463    Level: intermediate
464 
465 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
466 @*/
467 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
468 {
469   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
470   PetscDraw         draw;
471   PetscDrawAxis     axis;
472   PetscInt          n;
473   PetscMPIInt       size;
474   PetscReal         U0,U1,xl,yl,xr,yr,h;
475   char              time[32];
476   const PetscScalar *U;
477   PetscErrorCode    ierr;
478 
479   PetscFunctionBegin;
480   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size));
481   PetscCheck(size == 1,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
482   CHKERRQ(VecGetSize(u,&n));
483   PetscCheck(n == 2,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
484 
485   CHKERRQ(PetscViewerDrawGetDraw(ictx->viewer,0,&draw));
486   CHKERRQ(PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis));
487   CHKERRQ(PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr));
488   if (!step) {
489     CHKERRQ(PetscDrawClear(draw));
490     CHKERRQ(PetscDrawAxisDraw(axis));
491   }
492 
493   CHKERRQ(VecGetArrayRead(u,&U));
494   U0 = PetscRealPart(U[0]);
495   U1 = PetscRealPart(U[1]);
496   CHKERRQ(VecRestoreArrayRead(u,&U));
497   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
498 
499   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
500   CHKERRQ(PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK));
501   if (ictx->showtimestepandtime) {
502     CHKERRQ(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr));
503     CHKERRQ(PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime));
504     h    = yl + .95*(yr - yl);
505     CHKERRQ(PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time));
506   }
507   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
508   CHKERRQ(PetscDrawFlush(draw));
509   CHKERRQ(PetscDrawPause(draw));
510   CHKERRQ(PetscDrawSave(draw));
511   PetscFunctionReturn(0);
512 }
513 
514 /*@C
515    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
516 
517    Collective on TS
518 
519    Input Parameters:
520 .    ctx - the monitor context
521 
522    Level: intermediate
523 
524 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
525 @*/
526 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
527 {
528   PetscFunctionBegin;
529   CHKERRQ(PetscViewerDestroy(&(*ictx)->viewer));
530   CHKERRQ(VecDestroy(&(*ictx)->initialsolution));
531   CHKERRQ(PetscFree(*ictx));
532   PetscFunctionReturn(0);
533 }
534 
535 /*@C
536    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
537 
538    Collective on TS
539 
540    Input Parameter:
541 .    ts - time-step context
542 
543    Output Patameter:
544 .    ctx - the monitor context
545 
546    Options Database:
547 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
548 
549    Level: intermediate
550 
551 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
552 @*/
553 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
554 {
555   PetscFunctionBegin;
556   CHKERRQ(PetscNew(ctx));
557   CHKERRQ(PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer));
558   CHKERRQ(PetscViewerSetFromOptions((*ctx)->viewer));
559 
560   (*ctx)->howoften    = howoften;
561   (*ctx)->showinitial = PETSC_FALSE;
562   CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL));
563 
564   (*ctx)->showtimestepandtime = PETSC_FALSE;
565   CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL));
566   PetscFunctionReturn(0);
567 }
568 
569 /*@C
570    TSMonitorDrawSolutionFunction - Monitors progress of the TS solvers by calling
571    VecView() for the solution provided by TSSetSolutionFunction() at each timestep
572 
573    Collective on TS
574 
575    Input Parameters:
576 +  ts - the TS context
577 .  step - current time-step
578 .  ptime - current time
579 -  dummy - either a viewer or NULL
580 
581    Options Database:
582 .  -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
583 
584    Level: intermediate
585 
586 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
587 @*/
588 PetscErrorCode  TSMonitorDrawSolutionFunction(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
589 {
590   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
591   PetscViewer      viewer = ctx->viewer;
592   Vec              work;
593 
594   PetscFunctionBegin;
595   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
596   CHKERRQ(VecDuplicate(u,&work));
597   CHKERRQ(TSComputeSolutionFunction(ts,ptime,work));
598   CHKERRQ(VecView(work,viewer));
599   CHKERRQ(VecDestroy(&work));
600   PetscFunctionReturn(0);
601 }
602 
603 /*@C
604    TSMonitorDrawError - Monitors progress of the TS solvers by calling
605    VecView() for the error at each timestep
606 
607    Collective on TS
608 
609    Input Parameters:
610 +  ts - the TS context
611 .  step - current time-step
612 .  ptime - current time
613 -  dummy - either a viewer or NULL
614 
615    Options Database:
616 .  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
617 
618    Level: intermediate
619 
620 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
621 @*/
622 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
623 {
624   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
625   PetscViewer      viewer = ctx->viewer;
626   Vec              work;
627 
628   PetscFunctionBegin;
629   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
630   CHKERRQ(VecDuplicate(u,&work));
631   CHKERRQ(TSComputeSolutionFunction(ts,ptime,work));
632   CHKERRQ(VecAXPY(work,-1.0,u));
633   CHKERRQ(VecView(work,viewer));
634   CHKERRQ(VecDestroy(&work));
635   PetscFunctionReturn(0);
636 }
637 
638 /*@C
639    TSMonitorSolution - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file or a PetscDraw object
640 
641    Collective on TS
642 
643    Input Parameters:
644 +  ts - the TS context
645 .  step - current time-step
646 .  ptime - current time
647 .  u - current state
648 -  vf - viewer and its format
649 
650    Level: intermediate
651 
652 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
653 @*/
654 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
655 {
656   PetscFunctionBegin;
657   CHKERRQ(PetscViewerPushFormat(vf->viewer,vf->format));
658   CHKERRQ(VecView(u,vf->viewer));
659   CHKERRQ(PetscViewerPopFormat(vf->viewer));
660   PetscFunctionReturn(0);
661 }
662 
663 /*@C
664    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
665 
666    Collective on TS
667 
668    Input Parameters:
669 +  ts - the TS context
670 .  step - current time-step
671 .  ptime - current time
672 .  u - current state
673 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
674 
675    Level: intermediate
676 
677    Notes:
678    The VTK format does not allow writing multiple time steps in the same file, therefore a different file will be written for each time step.
679    These are named according to the file name template.
680 
681    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
682 
683 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
684 @*/
685 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
686 {
687   char           filename[PETSC_MAX_PATH_LEN];
688   PetscViewer    viewer;
689 
690   PetscFunctionBegin;
691   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
692   CHKERRQ(PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step));
693   CHKERRQ(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer));
694   CHKERRQ(VecView(u,viewer));
695   CHKERRQ(PetscViewerDestroy(&viewer));
696   PetscFunctionReturn(0);
697 }
698 
699 /*@C
700    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
701 
702    Collective on TS
703 
704    Input Parameters:
705 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
706 
707    Level: intermediate
708 
709    Note:
710    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
711 
712 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
713 @*/
714 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
715 {
716   PetscFunctionBegin;
717   CHKERRQ(PetscFree(*(char**)filenametemplate));
718   PetscFunctionReturn(0);
719 }
720 
721 /*@C
722    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
723        in a time based line graph
724 
725    Collective on TS
726 
727    Input Parameters:
728 +  ts - the TS context
729 .  step - current time-step
730 .  ptime - current time
731 .  u - current solution
732 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
733 
734    Options Database:
735 .   -ts_monitor_lg_solution_variables - enable monitor of lg solution variables
736 
737    Level: intermediate
738 
739    Notes:
740     Each process in a parallel run displays its component solutions in a separate window
741 
742 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
743            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
744            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
745            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
746 @*/
747 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
748 {
749   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
750   const PetscScalar *yy;
751   Vec               v;
752 
753   PetscFunctionBegin;
754   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
755   if (!step) {
756     PetscDrawAxis axis;
757     PetscInt      dim;
758     CHKERRQ(PetscDrawLGGetAxis(ctx->lg,&axis));
759     CHKERRQ(PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution"));
760     if (!ctx->names) {
761       PetscBool flg;
762       /* user provides names of variables to plot but no names has been set so assume names are integer values */
763       CHKERRQ(PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg));
764       if (flg) {
765         PetscInt i,n;
766         char     **names;
767         CHKERRQ(VecGetSize(u,&n));
768         CHKERRQ(PetscMalloc1(n+1,&names));
769         for (i=0; i<n; i++) {
770           CHKERRQ(PetscMalloc1(5,&names[i]));
771           CHKERRQ(PetscSNPrintf(names[i],5,"%D",i));
772         }
773         names[n] = NULL;
774         ctx->names = names;
775       }
776     }
777     if (ctx->names && !ctx->displaynames) {
778       char      **displaynames;
779       PetscBool flg;
780       CHKERRQ(VecGetLocalSize(u,&dim));
781       CHKERRQ(PetscCalloc1(dim+1,&displaynames));
782       CHKERRQ(PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg));
783       if (flg) {
784         CHKERRQ(TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames));
785       }
786       CHKERRQ(PetscStrArrayDestroy(&displaynames));
787     }
788     if (ctx->displaynames) {
789       CHKERRQ(PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables));
790       CHKERRQ(PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames));
791     } else if (ctx->names) {
792       CHKERRQ(VecGetLocalSize(u,&dim));
793       CHKERRQ(PetscDrawLGSetDimension(ctx->lg,dim));
794       CHKERRQ(PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names));
795     } else {
796       CHKERRQ(VecGetLocalSize(u,&dim));
797       CHKERRQ(PetscDrawLGSetDimension(ctx->lg,dim));
798     }
799     CHKERRQ(PetscDrawLGReset(ctx->lg));
800   }
801 
802   if (!ctx->transform) v = u;
803   else CHKERRQ((*ctx->transform)(ctx->transformctx,u,&v));
804   CHKERRQ(VecGetArrayRead(v,&yy));
805   if (ctx->displaynames) {
806     PetscInt i;
807     for (i=0; i<ctx->ndisplayvariables; i++)
808       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
809     CHKERRQ(PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues));
810   } else {
811 #if defined(PETSC_USE_COMPLEX)
812     PetscInt  i,n;
813     PetscReal *yreal;
814     CHKERRQ(VecGetLocalSize(v,&n));
815     CHKERRQ(PetscMalloc1(n,&yreal));
816     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
817     CHKERRQ(PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal));
818     CHKERRQ(PetscFree(yreal));
819 #else
820     CHKERRQ(PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy));
821 #endif
822   }
823   CHKERRQ(VecRestoreArrayRead(v,&yy));
824   if (ctx->transform) CHKERRQ(VecDestroy(&v));
825 
826   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
827     CHKERRQ(PetscDrawLGDraw(ctx->lg));
828     CHKERRQ(PetscDrawLGSave(ctx->lg));
829   }
830   PetscFunctionReturn(0);
831 }
832 
833 /*@C
834    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
835 
836    Collective on TS
837 
838    Input Parameters:
839 +  ts - the TS context
840 -  names - the names of the components, final string must be NULL
841 
842    Level: intermediate
843 
844    Notes:
845     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
846 
847 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
848 @*/
849 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
850 {
851   PetscInt          i;
852 
853   PetscFunctionBegin;
854   for (i=0; i<ts->numbermonitors; i++) {
855     if (ts->monitor[i] == TSMonitorLGSolution) {
856       CHKERRQ(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names));
857       break;
858     }
859   }
860   PetscFunctionReturn(0);
861 }
862 
863 /*@C
864    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
865 
866    Collective on TS
867 
868    Input Parameters:
869 +  ts - the TS context
870 -  names - the names of the components, final string must be NULL
871 
872    Level: intermediate
873 
874 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
875 @*/
876 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
877 {
878   PetscFunctionBegin;
879   CHKERRQ(PetscStrArrayDestroy(&ctx->names));
880   CHKERRQ(PetscStrArrayallocpy(names,&ctx->names));
881   PetscFunctionReturn(0);
882 }
883 
884 /*@C
885    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
886 
887    Collective on TS
888 
889    Input Parameter:
890 .  ts - the TS context
891 
892    Output Parameter:
893 .  names - the names of the components, final string must be NULL
894 
895    Level: intermediate
896 
897    Notes:
898     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
899 
900 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
901 @*/
902 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
903 {
904   PetscInt       i;
905 
906   PetscFunctionBegin;
907   *names = NULL;
908   for (i=0; i<ts->numbermonitors; i++) {
909     if (ts->monitor[i] == TSMonitorLGSolution) {
910       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
911       *names = (const char *const *)ctx->names;
912       break;
913     }
914   }
915   PetscFunctionReturn(0);
916 }
917 
918 /*@C
919    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
920 
921    Collective on TS
922 
923    Input Parameters:
924 +  ctx - the TSMonitorLG context
925 -  displaynames - the names of the components, final string must be NULL
926 
927    Level: intermediate
928 
929 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
930 @*/
931 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
932 {
933   PetscInt          j = 0,k;
934 
935   PetscFunctionBegin;
936   if (!ctx->names) PetscFunctionReturn(0);
937   CHKERRQ(PetscStrArrayDestroy(&ctx->displaynames));
938   CHKERRQ(PetscStrArrayallocpy(displaynames,&ctx->displaynames));
939   while (displaynames[j]) j++;
940   ctx->ndisplayvariables = j;
941   CHKERRQ(PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables));
942   CHKERRQ(PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues));
943   j = 0;
944   while (displaynames[j]) {
945     k = 0;
946     while (ctx->names[k]) {
947       PetscBool flg;
948       CHKERRQ(PetscStrcmp(displaynames[j],ctx->names[k],&flg));
949       if (flg) {
950         ctx->displayvariables[j] = k;
951         break;
952       }
953       k++;
954     }
955     j++;
956   }
957   PetscFunctionReturn(0);
958 }
959 
960 /*@C
961    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
962 
963    Collective on TS
964 
965    Input Parameters:
966 +  ts - the TS context
967 -  displaynames - the names of the components, final string must be NULL
968 
969    Notes:
970     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
971 
972    Level: intermediate
973 
974 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
975 @*/
976 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
977 {
978   PetscInt          i;
979 
980   PetscFunctionBegin;
981   for (i=0; i<ts->numbermonitors; i++) {
982     if (ts->monitor[i] == TSMonitorLGSolution) {
983       CHKERRQ(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames));
984       break;
985     }
986   }
987   PetscFunctionReturn(0);
988 }
989 
990 /*@C
991    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
992 
993    Collective on TS
994 
995    Input Parameters:
996 +  ts - the TS context
997 .  transform - the transform function
998 .  destroy - function to destroy the optional context
999 -  ctx - optional context used by transform function
1000 
1001    Notes:
1002     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
1003 
1004    Level: intermediate
1005 
1006 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
1007 @*/
1008 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
1009 {
1010   PetscInt          i;
1011 
1012   PetscFunctionBegin;
1013   for (i=0; i<ts->numbermonitors; i++) {
1014     if (ts->monitor[i] == TSMonitorLGSolution) {
1015       CHKERRQ(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx));
1016     }
1017   }
1018   PetscFunctionReturn(0);
1019 }
1020 
1021 /*@C
1022    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
1023 
1024    Collective on TSLGCtx
1025 
1026    Input Parameters:
1027 +  ts - the TS context
1028 .  transform - the transform function
1029 .  destroy - function to destroy the optional context
1030 -  ctx - optional context used by transform function
1031 
1032    Level: intermediate
1033 
1034 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
1035 @*/
1036 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
1037 {
1038   PetscFunctionBegin;
1039   ctx->transform    = transform;
1040   ctx->transformdestroy = destroy;
1041   ctx->transformctx = tctx;
1042   PetscFunctionReturn(0);
1043 }
1044 
1045 /*@C
1046    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the error
1047        in a time based line graph
1048 
1049    Collective on TS
1050 
1051    Input Parameters:
1052 +  ts - the TS context
1053 .  step - current time-step
1054 .  ptime - current time
1055 .  u - current solution
1056 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
1057 
1058    Level: intermediate
1059 
1060    Notes:
1061     Each process in a parallel run displays its component errors in a separate window
1062 
1063    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
1064 
1065    Options Database Keys:
1066 .  -ts_monitor_lg_error - create a graphical monitor of error history
1067 
1068 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
1069 @*/
1070 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
1071 {
1072   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
1073   const PetscScalar *yy;
1074   Vec               y;
1075 
1076   PetscFunctionBegin;
1077   if (!step) {
1078     PetscDrawAxis axis;
1079     PetscInt      dim;
1080     CHKERRQ(PetscDrawLGGetAxis(ctx->lg,&axis));
1081     CHKERRQ(PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Error"));
1082     CHKERRQ(VecGetLocalSize(u,&dim));
1083     CHKERRQ(PetscDrawLGSetDimension(ctx->lg,dim));
1084     CHKERRQ(PetscDrawLGReset(ctx->lg));
1085   }
1086   CHKERRQ(VecDuplicate(u,&y));
1087   CHKERRQ(TSComputeSolutionFunction(ts,ptime,y));
1088   CHKERRQ(VecAXPY(y,-1.0,u));
1089   CHKERRQ(VecGetArrayRead(y,&yy));
1090 #if defined(PETSC_USE_COMPLEX)
1091   {
1092     PetscReal *yreal;
1093     PetscInt  i,n;
1094     CHKERRQ(VecGetLocalSize(y,&n));
1095     CHKERRQ(PetscMalloc1(n,&yreal));
1096     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
1097     CHKERRQ(PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal));
1098     CHKERRQ(PetscFree(yreal));
1099   }
1100 #else
1101   CHKERRQ(PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy));
1102 #endif
1103   CHKERRQ(VecRestoreArrayRead(y,&yy));
1104   CHKERRQ(VecDestroy(&y));
1105   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1106     CHKERRQ(PetscDrawLGDraw(ctx->lg));
1107     CHKERRQ(PetscDrawLGSave(ctx->lg));
1108   }
1109   PetscFunctionReturn(0);
1110 }
1111 
1112 /*@C
1113    TSMonitorSPSwarmSolution - Graphically displays phase plots of DMSwarm particles on a scatter plot
1114 
1115    Input Parameters:
1116 +  ts - the TS context
1117 .  step - current time-step
1118 .  ptime - current time
1119 .  u - current solution
1120 -  dctx - the TSMonitorSPCtx object that contains all the options for the monitoring, this is created with TSMonitorSPCtxCreate()
1121 
1122    Options Database:
1123 + -ts_monitor_sp_swarm <n>          - Monitor the solution every n steps, or -1 for plotting only the final solution
1124 . -ts_monitor_sp_swarm_retain <n>   - Retain n old points so we can see the history, or -1 for all points
1125 - -ts_monitor_sp_swarm_phase <bool> - Plot in phase space, as opposed to coordinate space
1126 
1127    Level: intermediate
1128 
1129 .seealso: TSMonitoSet()
1130 @*/
1131 PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1132 {
1133   TSMonitorSPCtx     ctx = (TSMonitorSPCtx) dctx;
1134   DM                 dm, cdm;
1135   const PetscScalar *yy;
1136   PetscReal         *y, *x;
1137   PetscInt           Np, p, dim = 2;
1138 
1139   PetscFunctionBegin;
1140   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
1141   if (!step) {
1142     PetscDrawAxis axis;
1143     PetscReal     dmboxlower[2], dmboxupper[2];
1144     CHKERRQ(TSGetDM(ts, &dm));
1145     CHKERRQ(DMGetDimension(dm, &dim));
1146     PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
1147     CHKERRQ(DMSwarmGetCellDM(dm, &cdm));
1148     CHKERRQ(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
1149     CHKERRQ(VecGetLocalSize(u, &Np));
1150     Np /= dim*2;
1151     CHKERRQ(PetscDrawSPGetAxis(ctx->sp,&axis));
1152     if (ctx->phase) {
1153       CHKERRQ(PetscDrawAxisSetLabels(axis,"Particles","X","V"));
1154       CHKERRQ(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -5, 5));
1155     } else {
1156       CHKERRQ(PetscDrawAxisSetLabels(axis,"Particles","X","Y"));
1157       CHKERRQ(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
1158     }
1159     CHKERRQ(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
1160     CHKERRQ(PetscDrawSPSetDimension(ctx->sp, Np));
1161     CHKERRQ(PetscDrawSPReset(ctx->sp));
1162   }
1163   CHKERRQ(VecGetLocalSize(u, &Np));
1164   Np /= dim*2;
1165   CHKERRQ(VecGetArrayRead(u,&yy));
1166   CHKERRQ(PetscMalloc2(Np, &x, Np, &y));
1167   /* get points from solution vector */
1168   for (p = 0; p < Np; ++p) {
1169     if (ctx->phase) {
1170       x[p] = PetscRealPart(yy[p*dim*2]);
1171       y[p] = PetscRealPart(yy[p*dim*2 + dim]);
1172     } else {
1173       x[p] = PetscRealPart(yy[p*dim*2]);
1174       y[p] = PetscRealPart(yy[p*dim*2 + 1]);
1175     }
1176   }
1177   CHKERRQ(VecRestoreArrayRead(u,&yy));
1178   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1179     PetscDraw draw;
1180     CHKERRQ(PetscDrawSPGetDraw(ctx->sp, &draw));
1181     if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) {
1182       CHKERRQ(PetscDrawClear(draw));
1183     }
1184     CHKERRQ(PetscDrawFlush(draw));
1185     CHKERRQ(PetscDrawSPReset(ctx->sp));
1186     CHKERRQ(PetscDrawSPAddPoint(ctx->sp, x, y));
1187     CHKERRQ(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
1188     CHKERRQ(PetscDrawSPSave(ctx->sp));
1189   }
1190   CHKERRQ(PetscFree2(x, y));
1191   PetscFunctionReturn(0);
1192 }
1193 
1194 /*@C
1195    TSMonitorError - Monitors progress of the TS solvers by printing the 2 norm of the error at each timestep
1196 
1197    Collective on TS
1198 
1199    Input Parameters:
1200 +  ts - the TS context
1201 .  step - current time-step
1202 .  ptime - current time
1203 .  u - current solution
1204 -  dctx - unused context
1205 
1206    Level: intermediate
1207 
1208    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
1209 
1210    Options Database Keys:
1211 .  -ts_monitor_error - create a graphical monitor of error history
1212 
1213 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
1214 @*/
1215 PetscErrorCode TSMonitorError(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
1216 {
1217   DM             dm;
1218   PetscDS        ds = NULL;
1219   PetscInt       Nf = -1, f;
1220   PetscBool      flg;
1221 
1222   PetscFunctionBegin;
1223   CHKERRQ(TSGetDM(ts, &dm));
1224   if (dm) CHKERRQ(DMGetDS(dm, &ds));
1225   if (ds) CHKERRQ(PetscDSGetNumFields(ds, &Nf));
1226   if (Nf <= 0) {
1227     Vec       y;
1228     PetscReal nrm;
1229 
1230     CHKERRQ(VecDuplicate(u,&y));
1231     CHKERRQ(TSComputeSolutionFunction(ts,ptime,y));
1232     CHKERRQ(VecAXPY(y,-1.0,u));
1233     CHKERRQ(PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERASCII,&flg));
1234     if (flg) {
1235       CHKERRQ(VecNorm(y,NORM_2,&nrm));
1236       CHKERRQ(PetscViewerASCIIPrintf(vf->viewer,"2-norm of error %g\n",(double)nrm));
1237     }
1238     CHKERRQ(PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERDRAW,&flg));
1239     if (flg) {
1240       CHKERRQ(VecView(y,vf->viewer));
1241     }
1242     CHKERRQ(VecDestroy(&y));
1243   } else {
1244     PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1245     void            **ctxs;
1246     Vec               v;
1247     PetscReal         ferrors[1];
1248 
1249     CHKERRQ(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
1250     for (f = 0; f < Nf; ++f) CHKERRQ(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
1251     CHKERRQ(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
1252     CHKERRQ(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int) step, (double) ptime));
1253     for (f = 0; f < Nf; ++f) {
1254       if (f > 0) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD, ", "));
1255       CHKERRQ(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double) ferrors[f]));
1256     }
1257     CHKERRQ(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
1258 
1259     CHKERRQ(VecViewFromOptions(u, NULL, "-sol_vec_view"));
1260 
1261     CHKERRQ(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
1262     if (flg) {
1263       CHKERRQ(DMGetGlobalVector(dm, &v));
1264       CHKERRQ(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
1265       CHKERRQ(PetscObjectSetName((PetscObject) v, "Exact Solution"));
1266       CHKERRQ(VecViewFromOptions(v, NULL, "-exact_vec_view"));
1267       CHKERRQ(DMRestoreGlobalVector(dm, &v));
1268     }
1269     CHKERRQ(PetscFree2(exactFuncs, ctxs));
1270   }
1271   PetscFunctionReturn(0);
1272 }
1273 
1274 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
1275 {
1276   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
1277   PetscReal      x   = ptime,y;
1278   PetscInt       its;
1279 
1280   PetscFunctionBegin;
1281   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
1282   if (!n) {
1283     PetscDrawAxis axis;
1284     CHKERRQ(PetscDrawLGGetAxis(ctx->lg,&axis));
1285     CHKERRQ(PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations"));
1286     CHKERRQ(PetscDrawLGReset(ctx->lg));
1287     ctx->snes_its = 0;
1288   }
1289   CHKERRQ(TSGetSNESIterations(ts,&its));
1290   y    = its - ctx->snes_its;
1291   CHKERRQ(PetscDrawLGAddPoint(ctx->lg,&x,&y));
1292   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1293     CHKERRQ(PetscDrawLGDraw(ctx->lg));
1294     CHKERRQ(PetscDrawLGSave(ctx->lg));
1295   }
1296   ctx->snes_its = its;
1297   PetscFunctionReturn(0);
1298 }
1299 
1300 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
1301 {
1302   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
1303   PetscReal      x   = ptime,y;
1304   PetscInt       its;
1305 
1306   PetscFunctionBegin;
1307   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
1308   if (!n) {
1309     PetscDrawAxis axis;
1310     CHKERRQ(PetscDrawLGGetAxis(ctx->lg,&axis));
1311     CHKERRQ(PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations"));
1312     CHKERRQ(PetscDrawLGReset(ctx->lg));
1313     ctx->ksp_its = 0;
1314   }
1315   CHKERRQ(TSGetKSPIterations(ts,&its));
1316   y    = its - ctx->ksp_its;
1317   CHKERRQ(PetscDrawLGAddPoint(ctx->lg,&x,&y));
1318   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1319     CHKERRQ(PetscDrawLGDraw(ctx->lg));
1320     CHKERRQ(PetscDrawLGSave(ctx->lg));
1321   }
1322   ctx->ksp_its = its;
1323   PetscFunctionReturn(0);
1324 }
1325 
1326 /*@C
1327    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
1328 
1329    Collective on TS
1330 
1331    Input Parameters:
1332 .  ts  - the ODE solver object
1333 
1334    Output Parameter:
1335 .  ctx - the context
1336 
1337    Level: intermediate
1338 
1339 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
1340 
1341 @*/
1342 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
1343 {
1344   PetscFunctionBegin;
1345   CHKERRQ(PetscNew(ctx));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 /*@C
1350    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
1351 
1352    Collective on TS
1353 
1354    Input Parameters:
1355 +  ts - the TS context
1356 .  step - current time-step
1357 .  ptime - current time
1358 .  u  - current solution
1359 -  dctx - the envelope context
1360 
1361    Options Database:
1362 .  -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
1363 
1364    Level: intermediate
1365 
1366    Notes:
1367     after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
1368 
1369 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
1370 @*/
1371 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
1372 {
1373   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
1374 
1375   PetscFunctionBegin;
1376   if (!ctx->max) {
1377     CHKERRQ(VecDuplicate(u,&ctx->max));
1378     CHKERRQ(VecDuplicate(u,&ctx->min));
1379     CHKERRQ(VecCopy(u,ctx->max));
1380     CHKERRQ(VecCopy(u,ctx->min));
1381   } else {
1382     CHKERRQ(VecPointwiseMax(ctx->max,u,ctx->max));
1383     CHKERRQ(VecPointwiseMin(ctx->min,u,ctx->min));
1384   }
1385   PetscFunctionReturn(0);
1386 }
1387 
1388 /*@C
1389    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
1390 
1391    Collective on TS
1392 
1393    Input Parameter:
1394 .  ts - the TS context
1395 
1396    Output Parameters:
1397 +  max - the maximum values
1398 -  min - the minimum values
1399 
1400    Notes:
1401     If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
1402 
1403    Level: intermediate
1404 
1405 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
1406 @*/
1407 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
1408 {
1409   PetscInt i;
1410 
1411   PetscFunctionBegin;
1412   if (max) *max = NULL;
1413   if (min) *min = NULL;
1414   for (i=0; i<ts->numbermonitors; i++) {
1415     if (ts->monitor[i] == TSMonitorEnvelope) {
1416       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
1417       if (max) *max = ctx->max;
1418       if (min) *min = ctx->min;
1419       break;
1420     }
1421   }
1422   PetscFunctionReturn(0);
1423 }
1424 
1425 /*@C
1426    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
1427 
1428    Collective on TSMonitorEnvelopeCtx
1429 
1430    Input Parameter:
1431 .  ctx - the monitor context
1432 
1433    Level: intermediate
1434 
1435 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
1436 @*/
1437 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1438 {
1439   PetscFunctionBegin;
1440   CHKERRQ(VecDestroy(&(*ctx)->min));
1441   CHKERRQ(VecDestroy(&(*ctx)->max));
1442   CHKERRQ(PetscFree(*ctx));
1443   PetscFunctionReturn(0);
1444 }
1445 
1446 /*@C
1447   TSDMSwarmMonitorMoments - Monitors the first three moments of a DMSarm being evolved by the TS
1448 
1449   Not collective
1450 
1451   Input Parameters:
1452 + ts   - the TS context
1453 . step - current timestep
1454 . t    - current time
1455 . u    - current solution
1456 - ctx  - not used
1457 
1458   Options Database:
1459 . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution
1460 
1461   Level: intermediate
1462 
1463   Notes:
1464   This requires a DMSwarm be attached to the TS.
1465 
1466 .seealso: TSMonitorSet(), TSMonitorDefault(), DMSWARM
1467 @*/
1468 PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1469 {
1470   DM                 sw;
1471   const PetscScalar *u;
1472   PetscReal          m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1473   PetscInt           dim, d, Np, p;
1474   MPI_Comm           comm;
1475 
1476   PetscFunctionBeginUser;
1477   CHKERRQ(TSGetDM(ts, &sw));
1478   if (!sw || step%ts->monitorFrequency != 0) PetscFunctionReturn(0);
1479   CHKERRQ(PetscObjectGetComm((PetscObject) ts, &comm));
1480   CHKERRQ(DMGetDimension(sw, &dim));
1481   CHKERRQ(VecGetLocalSize(U, &Np));
1482   Np  /= dim;
1483   CHKERRQ(VecGetArrayRead(U, &u));
1484   for (p = 0; p < Np; ++p) {
1485     for (d = 0; d < dim; ++d) {
1486       totE      += PetscRealPart(u[p*dim+d]*u[p*dim+d]);
1487       totMom[d] += PetscRealPart(u[p*dim+d]);
1488     }
1489   }
1490   CHKERRQ(VecRestoreArrayRead(U, &u));
1491   for (d = 0; d < dim; ++d) totMom[d] *= m;
1492   totE *= 0.5*m;
1493   CHKERRQ(PetscPrintf(comm, "Step %4D Total Energy: %10.8lf", step, (double) totE));
1494   for (d = 0; d < dim; ++d) CHKERRQ(PetscPrintf(comm, "    Total Momentum %c: %10.8lf", 'x'+d, (double) totMom[d]));
1495   CHKERRQ(PetscPrintf(comm, "\n"));
1496   PetscFunctionReturn(0);
1497 }
1498