xref: /petsc/src/ts/interface/ts.c (revision 87f4e208db4ba8acce282dbb9e30381b0b02445e)
1 #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2 #include <petscdmshell.h>
3 #include <petscdmda.h>
4 #include <petscviewer.h>
5 #include <petscdraw.h>
6 
7 /* Logging support */
8 PetscClassId  TS_CLASSID, DMTS_CLASSID;
9 PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
10 
11 const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED","STEPOVER","INTERPOLATE","MATCHSTEP","TSExactFinalTimeOption","TS_EXACTFINALTIME_",0};
12 
13 /*@C
14    TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
15 
16    Collective on TS
17 
18    Input Parameters:
19 +  ts - TS object you wish to monitor
20 .  name - the monitor type one is seeking
21 .  help - message indicating what monitoring is done
22 .  manual - manual page for the monitor
23 .  monitor - the monitor function
24 -  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
25 
26    Level: developer
27 
28 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
29           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
30           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
31           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
32           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
33           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
34           PetscOptionsFList(), PetscOptionsEList()
35 @*/
36 PetscErrorCode  TSMonitorSetFromOptions(TS ts,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(TS,PetscViewerAndFormat*))
37 {
38   PetscErrorCode    ierr;
39   PetscViewer       viewer;
40   PetscViewerFormat format;
41   PetscBool         flg;
42 
43   PetscFunctionBegin;
44   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr);
45   if (flg) {
46     PetscViewerAndFormat *vf;
47     ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
48     ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
49     if (monitorsetup) {
50       ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr);
51     }
52     ierr = TSMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr);
53   }
54   PetscFunctionReturn(0);
55 }
56 
57 static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt,TSAdaptType default_type)
58 {
59   PetscErrorCode ierr;
60 
61   PetscFunctionBegin;
62   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
63   PetscValidCharPointer(default_type,2);
64   if (!((PetscObject)adapt)->type_name) {
65     ierr = TSAdaptSetType(adapt,default_type);CHKERRQ(ierr);
66   }
67   PetscFunctionReturn(0);
68 }
69 
70 /*@
71    TSSetFromOptions - Sets various TS parameters from user options.
72 
73    Collective on TS
74 
75    Input Parameter:
76 .  ts - the TS context obtained from TSCreate()
77 
78    Options Database Keys:
79 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSALPHA, TSGLLE, TSSSP, TSGLEE, TSBSI
80 .  -ts_save_trajectory - checkpoint the solution at each time-step
81 .  -ts_max_time <time> - maximum time to compute to
82 .  -ts_max_steps <steps> - maximum number of time-steps to take
83 .  -ts_init_time <time> - initial time to start computation
84 .  -ts_final_time <time> - final time to compute to
85 .  -ts_dt <dt> - initial time step
86 .  -ts_exact_final_time <stepover,interpolate,matchstep> whether to stop at the exact given final time and how to compute the solution at that ti,e
87 .  -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed
88 .  -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails
89 .  -ts_error_if_step_fails <true,false> - Error if no step succeeds
90 .  -ts_rtol <rtol> - relative tolerance for local truncation error
91 .  -ts_atol <atol> Absolute tolerance for local truncation error
92 .  -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function
93 .  -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - test the Jacobian at each iteration against finite difference with RHS function
94 .  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
95 .  -ts_fd_color - Use finite differences with coloring to compute IJacobian
96 .  -ts_monitor - print information at each timestep
97 .  -ts_monitor_lg_solution - Monitor solution graphically
98 .  -ts_monitor_lg_error - Monitor error graphically
99 .  -ts_monitor_error - Monitors norm of error
100 .  -ts_monitor_lg_timestep - Monitor timestep size graphically
101 .  -ts_monitor_lg_timestep_log - Monitor log timestep size graphically
102 .  -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
103 .  -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
104 .  -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
105 .  -ts_monitor_draw_solution - Monitor solution graphically
106 .  -ts_monitor_draw_solution_phase  <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
107 .  -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
108 .  -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
109 .  -ts_monitor_solution_vtk <filename.vts,filename.vtu> - Save each time step to a binary file, use filename-%%03D.vts (filename-%%03D.vtu)
110 .  -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
111 
112    Developer Note: We should unify all the -ts_monitor options in the way that -xxx_view has been unified
113 
114    Level: beginner
115 
116 .keywords: TS, timestep, set, options, database
117 
118 .seealso: TSGetType()
119 @*/
120 PetscErrorCode  TSSetFromOptions(TS ts)
121 {
122   PetscBool              opt,flg,tflg;
123   PetscErrorCode         ierr;
124   char                   monfilename[PETSC_MAX_PATH_LEN];
125   PetscReal              time_step;
126   TSExactFinalTimeOption eftopt;
127   char                   dir[16];
128   TSIFunction            ifun;
129   const char             *defaultType;
130   char                   typeName[256];
131 
132   PetscFunctionBegin;
133   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
134 
135   ierr = TSRegisterAll();CHKERRQ(ierr);
136   ierr = TSGetIFunction(ts,NULL,&ifun,NULL);CHKERRQ(ierr);
137 
138   ierr = PetscObjectOptionsBegin((PetscObject)ts);CHKERRQ(ierr);
139   if (((PetscObject)ts)->type_name)
140     defaultType = ((PetscObject)ts)->type_name;
141   else
142     defaultType = ifun ? TSBEULER : TSEULER;
143   ierr = PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt);CHKERRQ(ierr);
144   if (opt) {
145     ierr = TSSetType(ts,typeName);CHKERRQ(ierr);
146   } else {
147     ierr = TSSetType(ts,defaultType);CHKERRQ(ierr);
148   }
149 
150   /* Handle generic TS options */
151   ierr = PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL);CHKERRQ(ierr);
152   ierr = PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL);CHKERRQ(ierr);
153   ierr = PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL);CHKERRQ(ierr);
154   ierr = PetscOptionsReal("-ts_final_time","Final time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL);CHKERRQ(ierr);
155   ierr = PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg);CHKERRQ(ierr);
156   if (flg) {ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);}
157   ierr = PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg);CHKERRQ(ierr);
158   if (flg) {ierr = TSSetExactFinalTime(ts,eftopt);CHKERRQ(ierr);}
159   ierr = PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL);CHKERRQ(ierr);
160   ierr = PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL);CHKERRQ(ierr);
161   ierr = PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL);CHKERRQ(ierr);
162   ierr = PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL);CHKERRQ(ierr);
163   ierr = PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL);CHKERRQ(ierr);
164 
165   ierr = PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL);CHKERRQ(ierr);
166   ierr = PetscOptionsBool("-ts_rhs_jacobian_test_mult_transpose","Test the RHS Jacobian transpose for consistency with RHS at each solve ","None",ts->testjacobiantranspose,&ts->testjacobiantranspose,NULL);CHKERRQ(ierr);
167 #if defined(PETSC_HAVE_SAWS)
168   {
169   PetscBool set;
170   flg  = PETSC_FALSE;
171   ierr = PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set);CHKERRQ(ierr);
172   if (set) {
173     ierr = PetscObjectSAWsSetBlock((PetscObject)ts,flg);CHKERRQ(ierr);
174   }
175   }
176 #endif
177 
178   /* Monitor options */
179   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL);CHKERRQ(ierr);
180   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL);CHKERRQ(ierr);
181 
182   ierr = PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
183   if (flg) {ierr = PetscPythonMonitorSet((PetscObject)ts,monfilename);CHKERRQ(ierr);}
184 
185   ierr = PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt);CHKERRQ(ierr);
186   if (opt) {
187     TSMonitorLGCtx ctx;
188     PetscInt       howoften = 1;
189 
190     ierr = PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
191     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
192     ierr = TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
193   }
194 
195   ierr = PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt);CHKERRQ(ierr);
196   if (opt) {
197     TSMonitorLGCtx ctx;
198     PetscInt       howoften = 1;
199 
200     ierr = PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL);CHKERRQ(ierr);
201     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
202     ierr = TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
203   }
204   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL);CHKERRQ(ierr);
205 
206   ierr = PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
207   if (opt) {
208     TSMonitorLGCtx ctx;
209     PetscInt       howoften = 1;
210 
211     ierr = PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);CHKERRQ(ierr);
212     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
213     ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
214   }
215   ierr = PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
216   if (opt) {
217     TSMonitorLGCtx ctx;
218     PetscInt       howoften = 1;
219 
220     ierr = PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);CHKERRQ(ierr);
221     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
222     ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
223     ctx->semilogy = PETSC_TRUE;
224   }
225 
226   ierr = PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt);CHKERRQ(ierr);
227   if (opt) {
228     TSMonitorLGCtx ctx;
229     PetscInt       howoften = 1;
230 
231     ierr = PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
232     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
233     ierr = TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
234   }
235   ierr = PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt);CHKERRQ(ierr);
236   if (opt) {
237     TSMonitorLGCtx ctx;
238     PetscInt       howoften = 1;
239 
240     ierr = PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
241     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
242     ierr = TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
243   }
244   ierr = PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt);CHKERRQ(ierr);
245   if (opt) {
246     TSMonitorSPEigCtx ctx;
247     PetscInt          howoften = 1;
248 
249     ierr = PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL);CHKERRQ(ierr);
250     ierr = TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
251     ierr = TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy);CHKERRQ(ierr);
252   }
253   opt  = PETSC_FALSE;
254   ierr = PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt);CHKERRQ(ierr);
255   if (opt) {
256     TSMonitorDrawCtx ctx;
257     PetscInt         howoften = 1;
258 
259     ierr = PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
260     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
261     ierr = TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
262   }
263   opt  = PETSC_FALSE;
264   ierr = PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt);CHKERRQ(ierr);
265   if (opt) {
266     TSMonitorDrawCtx ctx;
267     PetscReal        bounds[4];
268     PetscInt         n = 4;
269     PetscDraw        draw;
270     PetscDrawAxis    axis;
271 
272     ierr = PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL);CHKERRQ(ierr);
273     if (n != 4) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
274     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx);CHKERRQ(ierr);
275     ierr = PetscViewerDrawGetDraw(ctx->viewer,0,&draw);CHKERRQ(ierr);
276     ierr = PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis);CHKERRQ(ierr);
277     ierr = PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3]);CHKERRQ(ierr);
278     ierr = PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2");CHKERRQ(ierr);
279     ierr = TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
280   }
281   opt  = PETSC_FALSE;
282   ierr = PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt);CHKERRQ(ierr);
283   if (opt) {
284     TSMonitorDrawCtx ctx;
285     PetscInt         howoften = 1;
286 
287     ierr = PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL);CHKERRQ(ierr);
288     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
289     ierr = TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
290   }
291   opt  = PETSC_FALSE;
292   ierr = PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt);CHKERRQ(ierr);
293   if (opt) {
294     TSMonitorDrawCtx ctx;
295     PetscInt         howoften = 1;
296 
297     ierr = PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL);CHKERRQ(ierr);
298     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
299     ierr = TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
300   }
301 
302   opt  = PETSC_FALSE;
303   ierr = PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
304   if (flg) {
305     const char *ptr,*ptr2;
306     char       *filetemplate;
307     if (!monfilename[0]) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
308     /* Do some cursory validation of the input. */
309     ierr = PetscStrstr(monfilename,"%",(char**)&ptr);CHKERRQ(ierr);
310     if (!ptr) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
311     for (ptr++; ptr && *ptr; ptr++) {
312       ierr = PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);CHKERRQ(ierr);
313       if (!ptr2 && (*ptr < '0' || '9' < *ptr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03D.vts");
314       if (ptr2) break;
315     }
316     ierr = PetscStrallocpy(monfilename,&filetemplate);CHKERRQ(ierr);
317     ierr = TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy);CHKERRQ(ierr);
318   }
319 
320   ierr = PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,16,&flg);CHKERRQ(ierr);
321   if (flg) {
322     TSMonitorDMDARayCtx *rayctx;
323     int                  ray = 0;
324     DMDADirection        ddir;
325     DM                   da;
326     PetscMPIInt          rank;
327 
328     if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
329     if (dir[0] == 'x') ddir = DMDA_X;
330     else if (dir[0] == 'y') ddir = DMDA_Y;
331     else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
332     sscanf(dir+2,"%d",&ray);
333 
334     ierr = PetscInfo2(((PetscObject)ts),"Displaying DMDA ray %c = %D\n",dir[0],ray);CHKERRQ(ierr);
335     ierr = PetscNew(&rayctx);CHKERRQ(ierr);
336     ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
337     ierr = DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter);CHKERRQ(ierr);
338     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank);CHKERRQ(ierr);
339     if (!rank) {
340       ierr = PetscViewerDrawOpen(PETSC_COMM_SELF,0,0,0,0,600,300,&rayctx->viewer);CHKERRQ(ierr);
341     }
342     rayctx->lgctx = NULL;
343     ierr = TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy);CHKERRQ(ierr);
344   }
345   ierr = PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,16,&flg);CHKERRQ(ierr);
346   if (flg) {
347     TSMonitorDMDARayCtx *rayctx;
348     int                 ray = 0;
349     DMDADirection       ddir;
350     DM                  da;
351     PetscInt            howoften = 1;
352 
353     if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
354     if      (dir[0] == 'x') ddir = DMDA_X;
355     else if (dir[0] == 'y') ddir = DMDA_Y;
356     else SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
357     sscanf(dir+2, "%d", &ray);
358 
359     ierr = PetscInfo2(((PetscObject) ts),"Displaying LG DMDA ray %c = %D\n", dir[0], ray);CHKERRQ(ierr);
360     ierr = PetscNew(&rayctx);CHKERRQ(ierr);
361     ierr = TSGetDM(ts, &da);CHKERRQ(ierr);
362     ierr = DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter);CHKERRQ(ierr);
363     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx);CHKERRQ(ierr);
364     ierr = TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy);CHKERRQ(ierr);
365   }
366 
367   ierr = PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt);CHKERRQ(ierr);
368   if (opt) {
369     TSMonitorEnvelopeCtx ctx;
370 
371     ierr = TSMonitorEnvelopeCtxCreate(ts,&ctx);CHKERRQ(ierr);
372     ierr = TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy);CHKERRQ(ierr);
373   }
374 
375   flg  = PETSC_FALSE;
376   ierr = PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL);CHKERRQ(ierr);
377   if (flg) {
378     DM   dm;
379     DMTS tdm;
380 
381     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
382     ierr = DMGetDMTS(dm, &tdm);CHKERRQ(ierr);
383     tdm->ijacobianctx = NULL;
384     ierr = TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, 0);CHKERRQ(ierr);
385     ierr = PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n");CHKERRQ(ierr);
386   }
387 
388   /* Handle specific TS options */
389   if (ts->ops->setfromoptions) {
390     ierr = (*ts->ops->setfromoptions)(PetscOptionsObject,ts);CHKERRQ(ierr);
391   }
392 
393   /* Handle TSAdapt options */
394   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
395   ierr = TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type);CHKERRQ(ierr);
396   ierr = TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt);CHKERRQ(ierr);
397 
398   /* TS trajectory must be set after TS, since it may use some TS options above */
399   tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
400   ierr = PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL);CHKERRQ(ierr);
401   if (tflg) {
402     ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr);
403   }
404 
405   ierr = TSAdjointSetFromOptions(PetscOptionsObject,ts);CHKERRQ(ierr);
406 
407   /* process any options handlers added with PetscObjectAddOptionsHandler() */
408   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts);CHKERRQ(ierr);
409   ierr = PetscOptionsEnd();CHKERRQ(ierr);
410 
411   if (ts->trajectory) {
412     ierr = TSTrajectorySetFromOptions(ts->trajectory,ts);CHKERRQ(ierr);
413   }
414 
415   ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr);
416   if (ts->problem_type == TS_LINEAR) {ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);}
417   ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr);
418   PetscFunctionReturn(0);
419 }
420 
421 /*@
422    TSGetTrajectory - Gets the trajectory from a TS if it exists
423 
424    Collective on TS
425 
426    Input Parameters:
427 .  ts - the TS context obtained from TSCreate()
428 
429    Output Parameters;
430 .  tr - the TSTrajectory object, if it exists
431 
432    Note: This routine should be called after all TS options have been set
433 
434    Level: advanced
435 
436 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSTrajectory, TSTrajectoryCreate()
437 
438 .keywords: TS, set, checkpoint,
439 @*/
440 PetscErrorCode  TSGetTrajectory(TS ts,TSTrajectory *tr)
441 {
442   PetscFunctionBegin;
443   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
444   *tr = ts->trajectory;
445   PetscFunctionReturn(0);
446 }
447 
448 /*@
449    TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object
450 
451    Collective on TS
452 
453    Input Parameters:
454 .  ts - the TS context obtained from TSCreate()
455 
456    Options Database:
457 +  -ts_save_trajectory - saves the trajectory to a file
458 -  -ts_trajectory_type type
459 
460 Note: This routine should be called after all TS options have been set
461 
462     The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
463    MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
464 
465    Level: intermediate
466 
467 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSTrajectoryType, TSSetTrajectoryType()
468 
469 .keywords: TS, set, checkpoint,
470 @*/
471 PetscErrorCode  TSSetSaveTrajectory(TS ts)
472 {
473   PetscErrorCode ierr;
474 
475   PetscFunctionBegin;
476   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
477   if (!ts->trajectory) {
478     ierr = TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory);CHKERRQ(ierr);
479   }
480   PetscFunctionReturn(0);
481 }
482 
483 /*@
484    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
485       set with TSSetRHSJacobian().
486 
487    Collective on TS and Vec
488 
489    Input Parameters:
490 +  ts - the TS context
491 .  t - current timestep
492 -  U - input vector
493 
494    Output Parameters:
495 +  A - Jacobian matrix
496 .  B - optional preconditioning matrix
497 -  flag - flag indicating matrix structure
498 
499    Notes:
500    Most users should not need to explicitly call this routine, as it
501    is used internally within the nonlinear solvers.
502 
503    See KSPSetOperators() for important information about setting the
504    flag parameter.
505 
506    Level: developer
507 
508 .keywords: SNES, compute, Jacobian, matrix
509 
510 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
511 @*/
512 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B)
513 {
514   PetscErrorCode   ierr;
515   PetscObjectState Ustate;
516   PetscObjectId    Uid;
517   DM               dm;
518   DMTS             tsdm;
519   TSRHSJacobian    rhsjacobianfunc;
520   void             *ctx;
521   TSIJacobian      ijacobianfunc;
522   TSRHSFunction    rhsfunction;
523 
524   PetscFunctionBegin;
525   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
526   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
527   PetscCheckSameComm(ts,1,U,3);
528   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
529   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
530   ierr = DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx);CHKERRQ(ierr);
531   ierr = DMTSGetIJacobian(dm,&ijacobianfunc,NULL);CHKERRQ(ierr);
532   ierr = DMTSGetRHSFunction(dm,&rhsfunction,&ctx);CHKERRQ(ierr);
533   ierr = PetscObjectStateGet((PetscObject)U,&Ustate);CHKERRQ(ierr);
534   ierr = PetscObjectGetId((PetscObject)U,&Uid);CHKERRQ(ierr);
535   if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) {
536     PetscFunctionReturn(0);
537   }
538 
539   if (!rhsjacobianfunc && !ijacobianfunc) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
540 
541   if (ts->rhsjacobian.reuse) {
542     ierr = MatShift(A,-ts->rhsjacobian.shift);CHKERRQ(ierr);
543     ierr = MatScale(A,1./ts->rhsjacobian.scale);CHKERRQ(ierr);
544     if (B && A != B) {
545       ierr = MatShift(B,-ts->rhsjacobian.shift);CHKERRQ(ierr);
546       ierr = MatScale(B,1./ts->rhsjacobian.scale);CHKERRQ(ierr);
547     }
548     ts->rhsjacobian.shift = 0;
549     ts->rhsjacobian.scale = 1.;
550   }
551 
552   if (rhsjacobianfunc) {
553     PetscBool missing;
554     ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,A,B);CHKERRQ(ierr);
555     PetscStackPush("TS user Jacobian function");
556     ierr = (*rhsjacobianfunc)(ts,t,U,A,B,ctx);CHKERRQ(ierr);
557     PetscStackPop;
558     ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,A,B);CHKERRQ(ierr);
559     if (A) {
560       ierr = MatMissingDiagonal(A,&missing,NULL);CHKERRQ(ierr);
561       if (missing) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Amat passed to TSSetRHSJacobian() must have all diagonal entries set, if they are zero you must still set them with a zero value");
562     }
563     if (B && B != A) {
564       ierr = MatMissingDiagonal(B,&missing,NULL);CHKERRQ(ierr);
565       if (missing) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Bmat passed to TSSetRHSJacobian() must have all diagonal entries set, if they are zero you must still set them with a zero value");
566     }
567   } else {
568     ierr = MatZeroEntries(A);CHKERRQ(ierr);
569     if (A != B) {ierr = MatZeroEntries(B);CHKERRQ(ierr);}
570   }
571   ts->rhsjacobian.time       = t;
572   ierr                       = PetscObjectGetId((PetscObject)U,&ts->rhsjacobian.Xid);CHKERRQ(ierr);
573   ierr                       = PetscObjectStateGet((PetscObject)U,&ts->rhsjacobian.Xstate);CHKERRQ(ierr);
574   PetscFunctionReturn(0);
575 }
576 
577 /*@
578    TSComputeRHSFunction - Evaluates the right-hand-side function.
579 
580    Collective on TS and Vec
581 
582    Input Parameters:
583 +  ts - the TS context
584 .  t - current time
585 -  U - state vector
586 
587    Output Parameter:
588 .  y - right hand side
589 
590    Note:
591    Most users should not need to explicitly call this routine, as it
592    is used internally within the nonlinear solvers.
593 
594    Level: developer
595 
596 .keywords: TS, compute
597 
598 .seealso: TSSetRHSFunction(), TSComputeIFunction()
599 @*/
600 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y)
601 {
602   PetscErrorCode ierr;
603   TSRHSFunction  rhsfunction;
604   TSIFunction    ifunction;
605   void           *ctx;
606   DM             dm;
607 
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
610   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
611   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
612   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
613   ierr = DMTSGetRHSFunction(dm,&rhsfunction,&ctx);CHKERRQ(ierr);
614   ierr = DMTSGetIFunction(dm,&ifunction,NULL);CHKERRQ(ierr);
615 
616   if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
617 
618   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
619   if (rhsfunction) {
620     PetscStackPush("TS user right-hand-side function");
621     ierr = (*rhsfunction)(ts,t,U,y,ctx);CHKERRQ(ierr);
622     PetscStackPop;
623   } else {
624     ierr = VecZeroEntries(y);CHKERRQ(ierr);
625   }
626 
627   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
628   PetscFunctionReturn(0);
629 }
630 
631 /*@
632    TSComputeSolutionFunction - Evaluates the solution function.
633 
634    Collective on TS and Vec
635 
636    Input Parameters:
637 +  ts - the TS context
638 -  t - current time
639 
640    Output Parameter:
641 .  U - the solution
642 
643    Note:
644    Most users should not need to explicitly call this routine, as it
645    is used internally within the nonlinear solvers.
646 
647    Level: developer
648 
649 .keywords: TS, compute
650 
651 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
652 @*/
653 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U)
654 {
655   PetscErrorCode     ierr;
656   TSSolutionFunction solutionfunction;
657   void               *ctx;
658   DM                 dm;
659 
660   PetscFunctionBegin;
661   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
662   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
663   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
664   ierr = DMTSGetSolutionFunction(dm,&solutionfunction,&ctx);CHKERRQ(ierr);
665 
666   if (solutionfunction) {
667     PetscStackPush("TS user solution function");
668     ierr = (*solutionfunction)(ts,t,U,ctx);CHKERRQ(ierr);
669     PetscStackPop;
670   }
671   PetscFunctionReturn(0);
672 }
673 /*@
674    TSComputeForcingFunction - Evaluates the forcing function.
675 
676    Collective on TS and Vec
677 
678    Input Parameters:
679 +  ts - the TS context
680 -  t - current time
681 
682    Output Parameter:
683 .  U - the function value
684 
685    Note:
686    Most users should not need to explicitly call this routine, as it
687    is used internally within the nonlinear solvers.
688 
689    Level: developer
690 
691 .keywords: TS, compute
692 
693 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
694 @*/
695 PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U)
696 {
697   PetscErrorCode     ierr, (*forcing)(TS,PetscReal,Vec,void*);
698   void               *ctx;
699   DM                 dm;
700 
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
703   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
704   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
705   ierr = DMTSGetForcingFunction(dm,&forcing,&ctx);CHKERRQ(ierr);
706 
707   if (forcing) {
708     PetscStackPush("TS user forcing function");
709     ierr = (*forcing)(ts,t,U,ctx);CHKERRQ(ierr);
710     PetscStackPop;
711   }
712   PetscFunctionReturn(0);
713 }
714 
715 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
716 {
717   Vec            F;
718   PetscErrorCode ierr;
719 
720   PetscFunctionBegin;
721   *Frhs = NULL;
722   ierr  = TSGetIFunction(ts,&F,NULL,NULL);CHKERRQ(ierr);
723   if (!ts->Frhs) {
724     ierr = VecDuplicate(F,&ts->Frhs);CHKERRQ(ierr);
725   }
726   *Frhs = ts->Frhs;
727   PetscFunctionReturn(0);
728 }
729 
730 static PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
731 {
732   Mat            A,B;
733   PetscErrorCode ierr;
734   TSIJacobian    ijacobian;
735 
736   PetscFunctionBegin;
737   if (Arhs) *Arhs = NULL;
738   if (Brhs) *Brhs = NULL;
739   ierr = TSGetIJacobian(ts,&A,&B,&ijacobian,NULL);CHKERRQ(ierr);
740   if (Arhs) {
741     if (!ts->Arhs) {
742       if (ijacobian) {
743         ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs);CHKERRQ(ierr);
744       } else {
745         ts->Arhs = A;
746         ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
747       }
748     } else {
749       PetscBool flg;
750       ierr = SNESGetUseMatrixFree(ts->snes,NULL,&flg);CHKERRQ(ierr);
751       /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */
752       if (flg && !ijacobian && ts->Arhs == ts->Brhs){
753         ierr = PetscObjectDereference((PetscObject)ts->Arhs);CHKERRQ(ierr);
754         ts->Arhs = A;
755         ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
756       }
757     }
758     *Arhs = ts->Arhs;
759   }
760   if (Brhs) {
761     if (!ts->Brhs) {
762       if (A != B) {
763         if (ijacobian) {
764           ierr = MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs);CHKERRQ(ierr);
765         } else {
766           ts->Brhs = B;
767           ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
768         }
769       } else {
770         ierr = PetscObjectReference((PetscObject)ts->Arhs);CHKERRQ(ierr);
771         ts->Brhs = ts->Arhs;
772       }
773     }
774     *Brhs = ts->Brhs;
775   }
776   PetscFunctionReturn(0);
777 }
778 
779 /*@
780    TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0
781 
782    Collective on TS and Vec
783 
784    Input Parameters:
785 +  ts - the TS context
786 .  t - current time
787 .  U - state vector
788 .  Udot - time derivative of state vector
789 -  imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
790 
791    Output Parameter:
792 .  Y - right hand side
793 
794    Note:
795    Most users should not need to explicitly call this routine, as it
796    is used internally within the nonlinear solvers.
797 
798    If the user did did not write their equations in implicit form, this
799    function recasts them in implicit form.
800 
801    Level: developer
802 
803 .keywords: TS, compute
804 
805 .seealso: TSSetIFunction(), TSComputeRHSFunction()
806 @*/
807 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex)
808 {
809   PetscErrorCode ierr;
810   TSIFunction    ifunction;
811   TSRHSFunction  rhsfunction;
812   void           *ctx;
813   DM             dm;
814 
815   PetscFunctionBegin;
816   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
817   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
818   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
819   PetscValidHeaderSpecific(Y,VEC_CLASSID,5);
820 
821   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
822   ierr = DMTSGetIFunction(dm,&ifunction,&ctx);CHKERRQ(ierr);
823   ierr = DMTSGetRHSFunction(dm,&rhsfunction,NULL);CHKERRQ(ierr);
824 
825   if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
826 
827   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
828   if (ifunction) {
829     PetscStackPush("TS user implicit function");
830     ierr = (*ifunction)(ts,t,U,Udot,Y,ctx);CHKERRQ(ierr);
831     PetscStackPop;
832   }
833   if (imex) {
834     if (!ifunction) {
835       ierr = VecCopy(Udot,Y);CHKERRQ(ierr);
836     }
837   } else if (rhsfunction) {
838     if (ifunction) {
839       Vec Frhs;
840       ierr = TSGetRHSVec_Private(ts,&Frhs);CHKERRQ(ierr);
841       ierr = TSComputeRHSFunction(ts,t,U,Frhs);CHKERRQ(ierr);
842       ierr = VecAXPY(Y,-1,Frhs);CHKERRQ(ierr);
843     } else {
844       ierr = TSComputeRHSFunction(ts,t,U,Y);CHKERRQ(ierr);
845       ierr = VecAYPX(Y,-1,Udot);CHKERRQ(ierr);
846     }
847   }
848   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
849   PetscFunctionReturn(0);
850 }
851 
852 /*@
853    TSComputeIJacobian - Evaluates the Jacobian of the DAE
854 
855    Collective on TS and Vec
856 
857    Input
858       Input Parameters:
859 +  ts - the TS context
860 .  t - current timestep
861 .  U - state vector
862 .  Udot - time derivative of state vector
863 .  shift - shift to apply, see note below
864 -  imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
865 
866    Output Parameters:
867 +  A - Jacobian matrix
868 -  B - matrix from which the preconditioner is constructed; often the same as A
869 
870    Notes:
871    If F(t,U,Udot)=0 is the DAE, the required Jacobian is
872 
873    dF/dU + shift*dF/dUdot
874 
875    Most users should not need to explicitly call this routine, as it
876    is used internally within the nonlinear solvers.
877 
878    Level: developer
879 
880 .keywords: TS, compute, Jacobian, matrix
881 
882 .seealso:  TSSetIJacobian()
883 @*/
884 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,PetscBool imex)
885 {
886   PetscErrorCode ierr;
887   TSIJacobian    ijacobian;
888   TSRHSJacobian  rhsjacobian;
889   DM             dm;
890   void           *ctx;
891 
892   PetscFunctionBegin;
893   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
894   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
895   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
896   PetscValidPointer(A,6);
897   PetscValidHeaderSpecific(A,MAT_CLASSID,6);
898   PetscValidPointer(B,7);
899   PetscValidHeaderSpecific(B,MAT_CLASSID,7);
900 
901   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
902   ierr = DMTSGetIJacobian(dm,&ijacobian,&ctx);CHKERRQ(ierr);
903   ierr = DMTSGetRHSJacobian(dm,&rhsjacobian,NULL);CHKERRQ(ierr);
904 
905   if (!rhsjacobian && !ijacobian) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
906 
907   ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,A,B);CHKERRQ(ierr);
908   if (ijacobian) {
909     PetscBool missing;
910     PetscStackPush("TS user implicit Jacobian");
911     ierr = (*ijacobian)(ts,t,U,Udot,shift,A,B,ctx);CHKERRQ(ierr);
912     PetscStackPop;
913     ierr = MatMissingDiagonal(A,&missing,NULL);CHKERRQ(ierr);
914     if (missing) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Amat passed to TSSetIJacobian() must have all diagonal entries set, if they are zero you must still set them with a zero value");
915     if (B != A) {
916       ierr = MatMissingDiagonal(B,&missing,NULL);CHKERRQ(ierr);
917       if (missing) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Bmat passed to TSSetIJacobian() must have all diagonal entries set, if they are zero you must still set them with a zero value");
918     }
919   }
920   if (imex) {
921     if (!ijacobian) {  /* system was written as Udot = G(t,U) */
922       PetscBool assembled;
923       ierr = MatZeroEntries(A);CHKERRQ(ierr);
924       ierr = MatAssembled(A,&assembled);CHKERRQ(ierr);
925       if (!assembled) {
926         ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
927         ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
928       }
929       ierr = MatShift(A,shift);CHKERRQ(ierr);
930       if (A != B) {
931         ierr = MatZeroEntries(B);CHKERRQ(ierr);
932         ierr = MatAssembled(B,&assembled);CHKERRQ(ierr);
933         if (!assembled) {
934           ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
935           ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
936         }
937         ierr = MatShift(B,shift);CHKERRQ(ierr);
938       }
939     }
940   } else {
941     Mat Arhs = NULL,Brhs = NULL;
942     if (rhsjacobian) {
943       ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
944       ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
945     }
946     if (Arhs == A) {           /* No IJacobian, so we only have the RHS matrix */
947       PetscBool flg;
948       ts->rhsjacobian.scale = -1;
949       ts->rhsjacobian.shift = shift;
950       ierr = SNESGetUseMatrixFree(ts->snes,NULL,&flg);CHKERRQ(ierr);
951       /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */
952       if (!flg) {
953         ierr = MatScale(A,-1);CHKERRQ(ierr);
954         ierr = MatShift(A,shift);CHKERRQ(ierr);
955       }
956       if (A != B) {
957         ierr = MatScale(B,-1);CHKERRQ(ierr);
958         ierr = MatShift(B,shift);CHKERRQ(ierr);
959       }
960     } else if (Arhs) {          /* Both IJacobian and RHSJacobian */
961       MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
962       if (!ijacobian) {         /* No IJacobian provided, but we have a separate RHS matrix */
963         ierr = MatZeroEntries(A);CHKERRQ(ierr);
964         ierr = MatShift(A,shift);CHKERRQ(ierr);
965         if (A != B) {
966           ierr = MatZeroEntries(B);CHKERRQ(ierr);
967           ierr = MatShift(B,shift);CHKERRQ(ierr);
968         }
969       }
970       ierr = MatAXPY(A,-1,Arhs,axpy);CHKERRQ(ierr);
971       if (A != B) {
972         ierr = MatAXPY(B,-1,Brhs,axpy);CHKERRQ(ierr);
973       }
974     }
975   }
976   ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,A,B);CHKERRQ(ierr);
977   PetscFunctionReturn(0);
978 }
979 
980 /*@C
981     TSSetRHSFunction - Sets the routine for evaluating the function,
982     where U_t = G(t,u).
983 
984     Logically Collective on TS
985 
986     Input Parameters:
987 +   ts - the TS context obtained from TSCreate()
988 .   r - vector to put the computed right hand side (or NULL to have it created)
989 .   f - routine for evaluating the right-hand-side function
990 -   ctx - [optional] user-defined context for private data for the
991           function evaluation routine (may be NULL)
992 
993     Calling sequence of func:
994 $     func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
995 
996 +   t - current timestep
997 .   u - input vector
998 .   F - function vector
999 -   ctx - [optional] user-defined function context
1000 
1001     Level: beginner
1002 
1003     Notes:
1004     You must call this function or TSSetIFunction() to define your ODE. You cannot use this function when solving a DAE.
1005 
1006 .keywords: TS, timestep, set, right-hand-side, function
1007 
1008 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSSetIFunction()
1009 @*/
1010 PetscErrorCode  TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
1011 {
1012   PetscErrorCode ierr;
1013   SNES           snes;
1014   Vec            ralloc = NULL;
1015   DM             dm;
1016 
1017   PetscFunctionBegin;
1018   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1019   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
1020 
1021   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1022   ierr = DMTSSetRHSFunction(dm,f,ctx);CHKERRQ(ierr);
1023   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1024   if (!r && !ts->dm && ts->vec_sol) {
1025     ierr = VecDuplicate(ts->vec_sol,&ralloc);CHKERRQ(ierr);
1026     r = ralloc;
1027   }
1028   ierr = SNESSetFunction(snes,r,SNESTSFormFunction,ts);CHKERRQ(ierr);
1029   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
1030   PetscFunctionReturn(0);
1031 }
1032 
1033 /*@C
1034     TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
1035 
1036     Logically Collective on TS
1037 
1038     Input Parameters:
1039 +   ts - the TS context obtained from TSCreate()
1040 .   f - routine for evaluating the solution
1041 -   ctx - [optional] user-defined context for private data for the
1042           function evaluation routine (may be NULL)
1043 
1044     Calling sequence of func:
1045 $     func (TS ts,PetscReal t,Vec u,void *ctx);
1046 
1047 +   t - current timestep
1048 .   u - output vector
1049 -   ctx - [optional] user-defined function context
1050 
1051     Options Database:
1052 +  -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided TSSetSolutionFunction()
1053 -  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
1054 
1055     Notes:
1056     This routine is used for testing accuracy of time integration schemes when you already know the solution.
1057     If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
1058     create closed-form solutions with non-physical forcing terms.
1059 
1060     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
1061 
1062     Level: beginner
1063 
1064 .keywords: TS, timestep, set, right-hand-side, function
1065 
1066 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetForcingFunction(), TSSetSolution(), TSGetSolution(), TSMonitorLGError(), TSMonitorDrawError()
1067 @*/
1068 PetscErrorCode  TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
1069 {
1070   PetscErrorCode ierr;
1071   DM             dm;
1072 
1073   PetscFunctionBegin;
1074   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1075   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1076   ierr = DMTSSetSolutionFunction(dm,f,ctx);CHKERRQ(ierr);
1077   PetscFunctionReturn(0);
1078 }
1079 
1080 /*@C
1081     TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
1082 
1083     Logically Collective on TS
1084 
1085     Input Parameters:
1086 +   ts - the TS context obtained from TSCreate()
1087 .   func - routine for evaluating the forcing function
1088 -   ctx - [optional] user-defined context for private data for the
1089           function evaluation routine (may be NULL)
1090 
1091     Calling sequence of func:
1092 $     func (TS ts,PetscReal t,Vec f,void *ctx);
1093 
1094 +   t - current timestep
1095 .   f - output vector
1096 -   ctx - [optional] user-defined function context
1097 
1098     Notes:
1099     This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
1100     create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the
1101     definition of the problem you are solving and hence possibly introducing bugs.
1102 
1103     This replaces the ODE F(u,u_t,t) = 0 the TS is solving with F(u,u_t,t) - func(t) = 0
1104 
1105     This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the
1106     parameters can be passed in the ctx variable.
1107 
1108     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
1109 
1110     Level: beginner
1111 
1112 .keywords: TS, timestep, set, right-hand-side, function
1113 
1114 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetSolutionFunction()
1115 @*/
1116 PetscErrorCode  TSSetForcingFunction(TS ts,TSForcingFunction func,void *ctx)
1117 {
1118   PetscErrorCode ierr;
1119   DM             dm;
1120 
1121   PetscFunctionBegin;
1122   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1123   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1124   ierr = DMTSSetForcingFunction(dm,func,ctx);CHKERRQ(ierr);
1125   PetscFunctionReturn(0);
1126 }
1127 
1128 /*@C
1129    TSSetRHSJacobian - Sets the function to compute the Jacobian of G,
1130    where U_t = G(U,t), as well as the location to store the matrix.
1131 
1132    Logically Collective on TS
1133 
1134    Input Parameters:
1135 +  ts  - the TS context obtained from TSCreate()
1136 .  Amat - (approximate) Jacobian matrix
1137 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1138 .  f   - the Jacobian evaluation routine
1139 -  ctx - [optional] user-defined context for private data for the
1140          Jacobian evaluation routine (may be NULL)
1141 
1142    Calling sequence of f:
1143 $     func (TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx);
1144 
1145 +  t - current timestep
1146 .  u - input vector
1147 .  Amat - (approximate) Jacobian matrix
1148 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1149 -  ctx - [optional] user-defined context for matrix evaluation routine
1150 
1151    Notes:
1152    You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1153 
1154    The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f()
1155    You should not assume the values are the same in the next call to f() as you set them in the previous call.
1156 
1157    Level: beginner
1158 
1159 .keywords: TS, timestep, set, right-hand-side, Jacobian
1160 
1161 .seealso: SNESComputeJacobianDefaultColor(), TSSetRHSFunction(), TSRHSJacobianSetReuse(), TSSetIJacobian()
1162 
1163 @*/
1164 PetscErrorCode  TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx)
1165 {
1166   PetscErrorCode ierr;
1167   SNES           snes;
1168   DM             dm;
1169   TSIJacobian    ijacobian;
1170 
1171   PetscFunctionBegin;
1172   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1173   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1174   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1175   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
1176   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
1177 
1178   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1179   ierr = DMTSSetRHSJacobian(dm,f,ctx);CHKERRQ(ierr);
1180   if (f == TSComputeRHSJacobianConstant) {
1181     /* Handle this case automatically for the user; otherwise user should call themselves. */
1182     ierr = TSRHSJacobianSetReuse(ts,PETSC_TRUE);CHKERRQ(ierr);
1183   }
1184   ierr = DMTSGetIJacobian(dm,&ijacobian,NULL);CHKERRQ(ierr);
1185   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1186   if (!ijacobian) {
1187     ierr = SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1188   }
1189   if (Amat) {
1190     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
1191     ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
1192     ts->Arhs = Amat;
1193   }
1194   if (Pmat) {
1195     ierr = PetscObjectReference((PetscObject)Pmat);CHKERRQ(ierr);
1196     ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
1197     ts->Brhs = Pmat;
1198   }
1199   PetscFunctionReturn(0);
1200 }
1201 
1202 /*@C
1203    TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
1204 
1205    Logically Collective on TS
1206 
1207    Input Parameters:
1208 +  ts  - the TS context obtained from TSCreate()
1209 .  r   - vector to hold the residual (or NULL to have it created internally)
1210 .  f   - the function evaluation routine
1211 -  ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1212 
1213    Calling sequence of f:
1214 $  f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
1215 
1216 +  t   - time at step/stage being solved
1217 .  u   - state vector
1218 .  u_t - time derivative of state vector
1219 .  F   - function vector
1220 -  ctx - [optional] user-defined context for matrix evaluation routine
1221 
1222    Important:
1223    The user MUST call either this routine or TSSetRHSFunction() to define the ODE.  When solving DAEs you must use this function.
1224 
1225    Level: beginner
1226 
1227 .keywords: TS, timestep, set, DAE, Jacobian
1228 
1229 .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian()
1230 @*/
1231 PetscErrorCode  TSSetIFunction(TS ts,Vec r,TSIFunction f,void *ctx)
1232 {
1233   PetscErrorCode ierr;
1234   SNES           snes;
1235   Vec            ralloc = NULL;
1236   DM             dm;
1237 
1238   PetscFunctionBegin;
1239   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1240   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
1241 
1242   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1243   ierr = DMTSSetIFunction(dm,f,ctx);CHKERRQ(ierr);
1244 
1245   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1246   if (!r && !ts->dm && ts->vec_sol) {
1247     ierr = VecDuplicate(ts->vec_sol,&ralloc);CHKERRQ(ierr);
1248     r  = ralloc;
1249   }
1250   ierr = SNESSetFunction(snes,r,SNESTSFormFunction,ts);CHKERRQ(ierr);
1251   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
1252   PetscFunctionReturn(0);
1253 }
1254 
1255 /*@C
1256    TSGetIFunction - Returns the vector where the implicit residual is stored and the function/contex to compute it.
1257 
1258    Not Collective
1259 
1260    Input Parameter:
1261 .  ts - the TS context
1262 
1263    Output Parameter:
1264 +  r - vector to hold residual (or NULL)
1265 .  func - the function to compute residual (or NULL)
1266 -  ctx - the function context (or NULL)
1267 
1268    Level: advanced
1269 
1270 .keywords: TS, nonlinear, get, function
1271 
1272 .seealso: TSSetIFunction(), SNESGetFunction()
1273 @*/
1274 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
1275 {
1276   PetscErrorCode ierr;
1277   SNES           snes;
1278   DM             dm;
1279 
1280   PetscFunctionBegin;
1281   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1282   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1283   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1284   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1285   ierr = DMTSGetIFunction(dm,func,ctx);CHKERRQ(ierr);
1286   PetscFunctionReturn(0);
1287 }
1288 
1289 /*@C
1290    TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
1291 
1292    Not Collective
1293 
1294    Input Parameter:
1295 .  ts - the TS context
1296 
1297    Output Parameter:
1298 +  r - vector to hold computed right hand side (or NULL)
1299 .  func - the function to compute right hand side (or NULL)
1300 -  ctx - the function context (or NULL)
1301 
1302    Level: advanced
1303 
1304 .keywords: TS, nonlinear, get, function
1305 
1306 .seealso: TSSetRHSFunction(), SNESGetFunction()
1307 @*/
1308 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
1309 {
1310   PetscErrorCode ierr;
1311   SNES           snes;
1312   DM             dm;
1313 
1314   PetscFunctionBegin;
1315   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1316   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1317   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1318   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1319   ierr = DMTSGetRHSFunction(dm,func,ctx);CHKERRQ(ierr);
1320   PetscFunctionReturn(0);
1321 }
1322 
1323 /*@C
1324    TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1325         provided with TSSetIFunction().
1326 
1327    Logically Collective on TS
1328 
1329    Input Parameters:
1330 +  ts  - the TS context obtained from TSCreate()
1331 .  Amat - (approximate) Jacobian matrix
1332 .  Pmat - matrix used to compute preconditioner (usually the same as Amat)
1333 .  f   - the Jacobian evaluation routine
1334 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1335 
1336    Calling sequence of f:
1337 $  f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx);
1338 
1339 +  t    - time at step/stage being solved
1340 .  U    - state vector
1341 .  U_t  - time derivative of state vector
1342 .  a    - shift
1343 .  Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1344 .  Pmat - matrix used for constructing preconditioner, usually the same as Amat
1345 -  ctx  - [optional] user-defined context for matrix evaluation routine
1346 
1347    Notes:
1348    The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve.
1349 
1350    If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null
1351    space to Amat and the KSP solvers will automatically use that null space as needed during the solution process.
1352 
1353    The matrix dF/dU + a*dF/dU_t you provide turns out to be
1354    the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1355    The time integrator internally approximates U_t by W+a*U where the positive "shift"
1356    a and vector W depend on the integration method, step size, and past states. For example with
1357    the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1358    W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1359 
1360    You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1361 
1362    The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f()
1363    You should not assume the values are the same in the next call to f() as you set them in the previous call.
1364 
1365    Level: beginner
1366 
1367 .keywords: TS, timestep, DAE, Jacobian
1368 
1369 .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESComputeJacobianDefaultColor(), SNESComputeJacobianDefault(), TSSetRHSFunction()
1370 
1371 @*/
1372 PetscErrorCode  TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx)
1373 {
1374   PetscErrorCode ierr;
1375   SNES           snes;
1376   DM             dm;
1377 
1378   PetscFunctionBegin;
1379   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1380   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1381   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1382   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
1383   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
1384 
1385   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1386   ierr = DMTSSetIJacobian(dm,f,ctx);CHKERRQ(ierr);
1387 
1388   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1389   ierr = SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1390   PetscFunctionReturn(0);
1391 }
1392 
1393 /*@
1394    TSRHSJacobianSetReuse - restore RHS Jacobian before re-evaluating.  Without this flag, TS will change the sign and
1395    shift the RHS Jacobian for a finite-time-step implicit solve, in which case the user function will need to recompute
1396    the entire Jacobian.  The reuse flag must be set if the evaluation function will assume that the matrix entries have
1397    not been changed by the TS.
1398 
1399    Logically Collective
1400 
1401    Input Arguments:
1402 +  ts - TS context obtained from TSCreate()
1403 -  reuse - PETSC_TRUE if the RHS Jacobian
1404 
1405    Level: intermediate
1406 
1407 .seealso: TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
1408 @*/
1409 PetscErrorCode TSRHSJacobianSetReuse(TS ts,PetscBool reuse)
1410 {
1411   PetscFunctionBegin;
1412   ts->rhsjacobian.reuse = reuse;
1413   PetscFunctionReturn(0);
1414 }
1415 
1416 /*@C
1417    TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved.
1418 
1419    Logically Collective on TS
1420 
1421    Input Parameters:
1422 +  ts  - the TS context obtained from TSCreate()
1423 .  F   - vector to hold the residual (or NULL to have it created internally)
1424 .  fun - the function evaluation routine
1425 -  ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1426 
1427    Calling sequence of fun:
1428 $  fun(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,Vec F,ctx);
1429 
1430 +  t    - time at step/stage being solved
1431 .  U    - state vector
1432 .  U_t  - time derivative of state vector
1433 .  U_tt - second time derivative of state vector
1434 .  F    - function vector
1435 -  ctx  - [optional] user-defined context for matrix evaluation routine (may be NULL)
1436 
1437    Level: beginner
1438 
1439 .keywords: TS, timestep, set, ODE, DAE, Function
1440 
1441 .seealso: TSSetI2Jacobian()
1442 @*/
1443 PetscErrorCode TSSetI2Function(TS ts,Vec F,TSI2Function fun,void *ctx)
1444 {
1445   DM             dm;
1446   PetscErrorCode ierr;
1447 
1448   PetscFunctionBegin;
1449   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1450   if (F) PetscValidHeaderSpecific(F,VEC_CLASSID,2);
1451   ierr = TSSetIFunction(ts,F,NULL,NULL);CHKERRQ(ierr);
1452   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1453   ierr = DMTSSetI2Function(dm,fun,ctx);CHKERRQ(ierr);
1454   PetscFunctionReturn(0);
1455 }
1456 
1457 /*@C
1458   TSGetI2Function - Returns the vector where the implicit residual is stored and the function/contex to compute it.
1459 
1460   Not Collective
1461 
1462   Input Parameter:
1463 . ts - the TS context
1464 
1465   Output Parameter:
1466 + r - vector to hold residual (or NULL)
1467 . fun - the function to compute residual (or NULL)
1468 - ctx - the function context (or NULL)
1469 
1470   Level: advanced
1471 
1472 .keywords: TS, nonlinear, get, function
1473 
1474 .seealso: TSSetI2Function(), SNESGetFunction()
1475 @*/
1476 PetscErrorCode TSGetI2Function(TS ts,Vec *r,TSI2Function *fun,void **ctx)
1477 {
1478   PetscErrorCode ierr;
1479   SNES           snes;
1480   DM             dm;
1481 
1482   PetscFunctionBegin;
1483   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1484   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1485   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1486   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1487   ierr = DMTSGetI2Function(dm,fun,ctx);CHKERRQ(ierr);
1488   PetscFunctionReturn(0);
1489 }
1490 
1491 /*@C
1492    TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t  + a*dF/dU_tt
1493         where F(t,U,U_t,U_tt) is the function you provided with TSSetI2Function().
1494 
1495    Logically Collective on TS
1496 
1497    Input Parameters:
1498 +  ts  - the TS context obtained from TSCreate()
1499 .  J   - Jacobian matrix
1500 .  P   - preconditioning matrix for J (may be same as J)
1501 .  jac - the Jacobian evaluation routine
1502 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1503 
1504    Calling sequence of jac:
1505 $  jac(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,PetscReal v,PetscReal a,Mat J,Mat P,void *ctx);
1506 
1507 +  t    - time at step/stage being solved
1508 .  U    - state vector
1509 .  U_t  - time derivative of state vector
1510 .  U_tt - second time derivative of state vector
1511 .  v    - shift for U_t
1512 .  a    - shift for U_tt
1513 .  J    - Jacobian of G(U) = F(t,U,W+v*U,W'+a*U), equivalent to dF/dU + v*dF/dU_t  + a*dF/dU_tt
1514 .  P    - preconditioning matrix for J, may be same as J
1515 -  ctx  - [optional] user-defined context for matrix evaluation routine
1516 
1517    Notes:
1518    The matrices J and P are exactly the matrices that are used by SNES for the nonlinear solve.
1519 
1520    The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be
1521    the Jacobian of G(U) = F(t,U,W+v*U,W'+a*U) where F(t,U,U_t,U_tt) = 0 is the DAE to be solved.
1522    The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U  where the positive "shift"
1523    parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states.
1524 
1525    Level: beginner
1526 
1527 .keywords: TS, timestep, set, ODE, DAE, Jacobian
1528 
1529 .seealso: TSSetI2Function()
1530 @*/
1531 PetscErrorCode TSSetI2Jacobian(TS ts,Mat J,Mat P,TSI2Jacobian jac,void *ctx)
1532 {
1533   DM             dm;
1534   PetscErrorCode ierr;
1535 
1536   PetscFunctionBegin;
1537   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1538   if (J) PetscValidHeaderSpecific(J,MAT_CLASSID,2);
1539   if (P) PetscValidHeaderSpecific(P,MAT_CLASSID,3);
1540   ierr = TSSetIJacobian(ts,J,P,NULL,NULL);CHKERRQ(ierr);
1541   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1542   ierr = DMTSSetI2Jacobian(dm,jac,ctx);CHKERRQ(ierr);
1543   PetscFunctionReturn(0);
1544 }
1545 
1546 /*@C
1547   TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.
1548 
1549   Not Collective, but parallel objects are returned if TS is parallel
1550 
1551   Input Parameter:
1552 . ts  - The TS context obtained from TSCreate()
1553 
1554   Output Parameters:
1555 + J  - The (approximate) Jacobian of F(t,U,U_t,U_tt)
1556 . P - The matrix from which the preconditioner is constructed, often the same as J
1557 . jac - The function to compute the Jacobian matrices
1558 - ctx - User-defined context for Jacobian evaluation routine
1559 
1560   Notes:
1561     You can pass in NULL for any return argument you do not need.
1562 
1563   Level: advanced
1564 
1565 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
1566 
1567 .keywords: TS, timestep, get, matrix, Jacobian
1568 @*/
1569 PetscErrorCode  TSGetI2Jacobian(TS ts,Mat *J,Mat *P,TSI2Jacobian *jac,void **ctx)
1570 {
1571   PetscErrorCode ierr;
1572   SNES           snes;
1573   DM             dm;
1574 
1575   PetscFunctionBegin;
1576   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1577   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
1578   ierr = SNESGetJacobian(snes,J,P,NULL,NULL);CHKERRQ(ierr);
1579   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1580   ierr = DMTSGetI2Jacobian(dm,jac,ctx);CHKERRQ(ierr);
1581   PetscFunctionReturn(0);
1582 }
1583 
1584 /*@
1585   TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0
1586 
1587   Collective on TS and Vec
1588 
1589   Input Parameters:
1590 + ts - the TS context
1591 . t - current time
1592 . U - state vector
1593 . V - time derivative of state vector (U_t)
1594 - A - second time derivative of state vector (U_tt)
1595 
1596   Output Parameter:
1597 . F - the residual vector
1598 
1599   Note:
1600   Most users should not need to explicitly call this routine, as it
1601   is used internally within the nonlinear solvers.
1602 
1603   Level: developer
1604 
1605 .keywords: TS, compute, function, vector
1606 
1607 .seealso: TSSetI2Function()
1608 @*/
1609 PetscErrorCode TSComputeI2Function(TS ts,PetscReal t,Vec U,Vec V,Vec A,Vec F)
1610 {
1611   DM             dm;
1612   TSI2Function   I2Function;
1613   void           *ctx;
1614   TSRHSFunction  rhsfunction;
1615   PetscErrorCode ierr;
1616 
1617   PetscFunctionBegin;
1618   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1619   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1620   PetscValidHeaderSpecific(V,VEC_CLASSID,4);
1621   PetscValidHeaderSpecific(A,VEC_CLASSID,5);
1622   PetscValidHeaderSpecific(F,VEC_CLASSID,6);
1623 
1624   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1625   ierr = DMTSGetI2Function(dm,&I2Function,&ctx);CHKERRQ(ierr);
1626   ierr = DMTSGetRHSFunction(dm,&rhsfunction,NULL);CHKERRQ(ierr);
1627 
1628   if (!I2Function) {
1629     ierr = TSComputeIFunction(ts,t,U,A,F,PETSC_FALSE);CHKERRQ(ierr);
1630     PetscFunctionReturn(0);
1631   }
1632 
1633   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,V,F);CHKERRQ(ierr);
1634 
1635   PetscStackPush("TS user implicit function");
1636   ierr = I2Function(ts,t,U,V,A,F,ctx);CHKERRQ(ierr);
1637   PetscStackPop;
1638 
1639   if (rhsfunction) {
1640     Vec Frhs;
1641     ierr = TSGetRHSVec_Private(ts,&Frhs);CHKERRQ(ierr);
1642     ierr = TSComputeRHSFunction(ts,t,U,Frhs);CHKERRQ(ierr);
1643     ierr = VecAXPY(F,-1,Frhs);CHKERRQ(ierr);
1644   }
1645 
1646   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,V,F);CHKERRQ(ierr);
1647   PetscFunctionReturn(0);
1648 }
1649 
1650 /*@
1651   TSComputeI2Jacobian - Evaluates the Jacobian of the DAE
1652 
1653   Collective on TS and Vec
1654 
1655   Input Parameters:
1656 + ts - the TS context
1657 . t - current timestep
1658 . U - state vector
1659 . V - time derivative of state vector
1660 . A - second time derivative of state vector
1661 . shiftV - shift to apply, see note below
1662 - shiftA - shift to apply, see note below
1663 
1664   Output Parameters:
1665 + J - Jacobian matrix
1666 - P - optional preconditioning matrix
1667 
1668   Notes:
1669   If F(t,U,V,A)=0 is the DAE, the required Jacobian is
1670 
1671   dF/dU + shiftV*dF/dV + shiftA*dF/dA
1672 
1673   Most users should not need to explicitly call this routine, as it
1674   is used internally within the nonlinear solvers.
1675 
1676   Level: developer
1677 
1678 .keywords: TS, compute, Jacobian, matrix
1679 
1680 .seealso:  TSSetI2Jacobian()
1681 @*/
1682 PetscErrorCode TSComputeI2Jacobian(TS ts,PetscReal t,Vec U,Vec V,Vec A,PetscReal shiftV,PetscReal shiftA,Mat J,Mat P)
1683 {
1684   DM             dm;
1685   TSI2Jacobian   I2Jacobian;
1686   void           *ctx;
1687   TSRHSJacobian  rhsjacobian;
1688   PetscErrorCode ierr;
1689 
1690   PetscFunctionBegin;
1691   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1692   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1693   PetscValidHeaderSpecific(V,VEC_CLASSID,4);
1694   PetscValidHeaderSpecific(A,VEC_CLASSID,5);
1695   PetscValidHeaderSpecific(J,MAT_CLASSID,8);
1696   PetscValidHeaderSpecific(P,MAT_CLASSID,9);
1697 
1698   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1699   ierr = DMTSGetI2Jacobian(dm,&I2Jacobian,&ctx);CHKERRQ(ierr);
1700   ierr = DMTSGetRHSJacobian(dm,&rhsjacobian,NULL);CHKERRQ(ierr);
1701 
1702   if (!I2Jacobian) {
1703     ierr = TSComputeIJacobian(ts,t,U,A,shiftA,J,P,PETSC_FALSE);CHKERRQ(ierr);
1704     PetscFunctionReturn(0);
1705   }
1706 
1707   ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,J,P);CHKERRQ(ierr);
1708 
1709   PetscStackPush("TS user implicit Jacobian");
1710   ierr = I2Jacobian(ts,t,U,V,A,shiftV,shiftA,J,P,ctx);CHKERRQ(ierr);
1711   PetscStackPop;
1712 
1713   if (rhsjacobian) {
1714     Mat Jrhs,Prhs; MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
1715     ierr = TSGetRHSMats_Private(ts,&Jrhs,&Prhs);CHKERRQ(ierr);
1716     ierr = TSComputeRHSJacobian(ts,t,U,Jrhs,Prhs);CHKERRQ(ierr);
1717     ierr = MatAXPY(J,-1,Jrhs,axpy);CHKERRQ(ierr);
1718     if (P != J) {ierr = MatAXPY(P,-1,Prhs,axpy);CHKERRQ(ierr);}
1719   }
1720 
1721   ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,J,P);CHKERRQ(ierr);
1722   PetscFunctionReturn(0);
1723 }
1724 
1725 /*@
1726    TS2SetSolution - Sets the initial solution and time derivative vectors
1727    for use by the TS routines handling second order equations.
1728 
1729    Logically Collective on TS and Vec
1730 
1731    Input Parameters:
1732 +  ts - the TS context obtained from TSCreate()
1733 .  u - the solution vector
1734 -  v - the time derivative vector
1735 
1736    Level: beginner
1737 
1738 .keywords: TS, timestep, set, solution, initial conditions
1739 @*/
1740 PetscErrorCode  TS2SetSolution(TS ts,Vec u,Vec v)
1741 {
1742   PetscErrorCode ierr;
1743 
1744   PetscFunctionBegin;
1745   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1746   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
1747   PetscValidHeaderSpecific(v,VEC_CLASSID,3);
1748   ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
1749   ierr = PetscObjectReference((PetscObject)v);CHKERRQ(ierr);
1750   ierr = VecDestroy(&ts->vec_dot);CHKERRQ(ierr);
1751   ts->vec_dot = v;
1752   PetscFunctionReturn(0);
1753 }
1754 
1755 /*@
1756    TS2GetSolution - Returns the solution and time derivative at the present timestep
1757    for second order equations. It is valid to call this routine inside the function
1758    that you are evaluating in order to move to the new timestep. This vector not
1759    changed until the solution at the next timestep has been calculated.
1760 
1761    Not Collective, but Vec returned is parallel if TS is parallel
1762 
1763    Input Parameter:
1764 .  ts - the TS context obtained from TSCreate()
1765 
1766    Output Parameter:
1767 +  u - the vector containing the solution
1768 -  v - the vector containing the time derivative
1769 
1770    Level: intermediate
1771 
1772 .seealso: TS2SetSolution(), TSGetTimeStep(), TSGetTime()
1773 
1774 .keywords: TS, timestep, get, solution
1775 @*/
1776 PetscErrorCode  TS2GetSolution(TS ts,Vec *u,Vec *v)
1777 {
1778   PetscFunctionBegin;
1779   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1780   if (u) PetscValidPointer(u,2);
1781   if (v) PetscValidPointer(v,3);
1782   if (u) *u = ts->vec_sol;
1783   if (v) *v = ts->vec_dot;
1784   PetscFunctionReturn(0);
1785 }
1786 
1787 /*@C
1788    TSSetRHSSplits - Set the number of splits for the RHS function
1789 
1790    Logically Collective on TS
1791 
1792    Input Parameters:
1793    + ts        - the TS context obtained from TSCreate()
1794    - numsplits - the number of splits for the RHS function
1795 
1796    Level: intermediate
1797 
1798 .seealso: TSSetRHSSplitFunction, TSGetRHSSplitFunction
1799 
1800 .keywords: TS, multirate
1801 @*/
1802 PetscErrorCode TSSetRHSSplits(TS ts,PetscInt numsplits)
1803 {
1804   PetscFunctionBegin;
1805   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1806   if (numsplits > MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of splits set for RHSFunction exceeds the maximum number allowed");
1807   ts->num_rhs_splits = numsplits;
1808   PetscFunctionReturn(0);
1809 }
1810 
1811 /*@C
1812    TSSetRHSSplitIS - Set the index set for the specified split
1813 
1814    Logically Collective on TS
1815 
1816    Input Parameters:
1817    + ts  - the TS context obtained from TSCreate()
1818    . ind - the index of the split, starting from 1
1819    - is  - the index set for part of the solution vector
1820 
1821    Level: intermediate
1822 
1823 .seealso: TSSetRHSSplits
1824 
1825 .keywords: TS, multirate
1826 @*/
1827 PetscErrorCode TSSetRHSSplitIS(TS ts,PetscInt ind,IS is)
1828 {
1829   PetscErrorCode ierr;
1830   PetscFunctionBegin;
1831   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1832   PetscValidHeaderSpecific(is,IS_CLASSID,3);
1833   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1834   if (!ts->num_rhs_splits) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Call TSSetRHSSplits() to set the Number of splits first");
1835   if (ind > ts->num_rhs_splits || ind <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Second argument is out of range");
1836   ierr = ISDestroy(&ts->iss[ind-1]);CHKERRQ(ierr);
1837   ts->iss[ind-1] = is;
1838   PetscFunctionReturn(0);
1839 }
1840 
1841 /*@C
1842  TSSetRHSSplitFunction - Set the split right-hand-side functions.
1843 
1844  Logically Collective on TS
1845 
1846  Input Parameters:
1847  +  ts      - the TS context obtained from TSCreate()
1848  .  ind     - the index of split RHS function
1849  .  r       - vector to hold the residual (or NULL to have it created internally)
1850  .  rhsfunc - the RHS function evaluation routine
1851  -  ctx     - user-defined context for private data for the split function evaluation routine (may be NULL)
1852 
1853  Calling sequence of fun:
1854  $  rhsfunc(TS ts,PetscReal t,Vec u,Vec f,ctx);
1855 
1856  +  t    - time at step/stage being solved
1857  .  u    - state vector
1858  .  f    - function vector
1859  -  ctx  - [optional] user-defined context for matrix evaluation routine (may be NULL)
1860 
1861  Level: beginner
1862 
1863  .keywords: TS, timestep, set, ODE, Hamiltonian, Function
1864 
1865  .seealso: TSGetRHSSplitFunction()
1866  @*/
1867 PetscErrorCode TSSetRHSSplitFunction(TS ts,PetscInt ind,Vec r,TSRHSFunction rhsfunc,void *ctx)
1868 {
1869   DM             dm;
1870   SNES           snes;
1871   Vec            ralloc = NULL;
1872   PetscErrorCode ierr;
1873 
1874   PetscFunctionBegin;
1875   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1876   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
1877 
1878   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1879   ierr = DMTSSetRHSSplitFunction(dm,ind,rhsfunc,ctx);CHKERRQ(ierr);
1880 
1881   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1882   if (!r && !ts->dm && ts->vec_sol) {
1883     ierr = VecDuplicate(ts->vec_sol,&ralloc);CHKERRQ(ierr);
1884     r = ralloc;
1885   }
1886   ierr = SNESSetFunction(snes,r,SNESTSFormFunction,ts);CHKERRQ(ierr);
1887   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
1888   PetscFunctionReturn(0);
1889 }
1890 
1891 /*@C
1892  TSGetRHSSplitFunction - Returns the vector where the split RHS residual is stored and the functions to compute it.
1893 
1894  Not Collective
1895 
1896  Input Parameter:
1897  . ts - the TS context
1898 
1899  Output Parameter:
1900  + r       - vector to hold residual (or NULL)
1901  . rhsfunc - the function to compute part of the residual (or NULL)
1902  - ctx     - the function context (or NULL)
1903 
1904  Level: advanced
1905 
1906  .keywords: TS, nonlinear, get, function
1907 
1908  .seealso: TSSetRHSSplitFunction(), SNESGetFunction()
1909  @*/
1910 PetscErrorCode TSGetRHSSplitFunction(TS ts,PetscInt ind,Vec *r,TSRHSFunction *rhsfunc,void **ctx)
1911 {
1912   PetscErrorCode ierr;
1913   SNES           snes;
1914   DM             dm;
1915 
1916   PetscFunctionBegin;
1917   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1918   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1919   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1920   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1921   ierr = DMTSGetRHSSplitFunction(dm,ind,rhsfunc,ctx);CHKERRQ(ierr);
1922   PetscFunctionReturn(0);
1923 }
1924 
1925 /*@
1926  TSComputeRHSSplitFunction - Evaluates the right-hand-side function.
1927 
1928  Collective on TS and Vec
1929 
1930  Input Parameters:
1931  +  ts - the TS context
1932  .  t - current time
1933  -  U - state vector
1934 
1935  Output Parameter:
1936  .  y - right hand side
1937 
1938  Note:
1939  Most users should not need to explicitly call this routine, as it
1940  is used internally within the nonlinear solvers.
1941 
1942  Level: developer
1943 
1944  .keywords: TS, compute
1945 
1946  .seealso: TSSetRHSSplitFunction()
1947  @*/
1948 PetscErrorCode TSComputeRHSSplitFunction(TS ts,PetscInt ind,PetscReal t,Vec U,Vec y)
1949 {
1950   PetscErrorCode ierr;
1951   TSRHSFunction  rhsfunc;
1952   void           *ctx;
1953   DM             dm;
1954 
1955   PetscFunctionBegin;
1956   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1957   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1958   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
1959   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1960 
1961   ierr = DMTSGetRHSSplitFunction(dm,ind,&rhsfunc,&ctx);CHKERRQ(ierr);
1962 
1963   if (!rhsfunc) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSSplitFunction()");
1964 
1965   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
1966 
1967   PetscStackPush("TS user right-hand-side function");
1968   ierr = (*rhsfunc)(ts,t,U,y,ctx);CHKERRQ(ierr);
1969   PetscStackPop;
1970 
1971   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
1972   PetscFunctionReturn(0);
1973 }
1974 
1975 /*@C
1976   TSLoad - Loads a KSP that has been stored in binary  with KSPView().
1977 
1978   Collective on PetscViewer
1979 
1980   Input Parameters:
1981 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or
1982            some related function before a call to TSLoad().
1983 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1984 
1985    Level: intermediate
1986 
1987   Notes:
1988    The type is determined by the data in the file, any type set into the TS before this call is ignored.
1989 
1990   Notes for advanced users:
1991   Most users should not need to know the details of the binary storage
1992   format, since TSLoad() and TSView() completely hide these details.
1993   But for anyone who's interested, the standard binary matrix storage
1994   format is
1995 .vb
1996      has not yet been determined
1997 .ve
1998 
1999 .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad()
2000 @*/
2001 PetscErrorCode  TSLoad(TS ts, PetscViewer viewer)
2002 {
2003   PetscErrorCode ierr;
2004   PetscBool      isbinary;
2005   PetscInt       classid;
2006   char           type[256];
2007   DMTS           sdm;
2008   DM             dm;
2009 
2010   PetscFunctionBegin;
2011   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2012   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2013   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2014   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
2015 
2016   ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
2017   if (classid != TS_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file");
2018   ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
2019   ierr = TSSetType(ts, type);CHKERRQ(ierr);
2020   if (ts->ops->load) {
2021     ierr = (*ts->ops->load)(ts,viewer);CHKERRQ(ierr);
2022   }
2023   ierr = DMCreate(PetscObjectComm((PetscObject)ts),&dm);CHKERRQ(ierr);
2024   ierr = DMLoad(dm,viewer);CHKERRQ(ierr);
2025   ierr = TSSetDM(ts,dm);CHKERRQ(ierr);
2026   ierr = DMCreateGlobalVector(ts->dm,&ts->vec_sol);CHKERRQ(ierr);
2027   ierr = VecLoad(ts->vec_sol,viewer);CHKERRQ(ierr);
2028   ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
2029   ierr = DMTSLoad(sdm,viewer);CHKERRQ(ierr);
2030   PetscFunctionReturn(0);
2031 }
2032 
2033 #include <petscdraw.h>
2034 #if defined(PETSC_HAVE_SAWS)
2035 #include <petscviewersaws.h>
2036 #endif
2037 /*@C
2038     TSView - Prints the TS data structure.
2039 
2040     Collective on TS
2041 
2042     Input Parameters:
2043 +   ts - the TS context obtained from TSCreate()
2044 -   viewer - visualization context
2045 
2046     Options Database Key:
2047 .   -ts_view - calls TSView() at end of TSStep()
2048 
2049     Notes:
2050     The available visualization contexts include
2051 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
2052 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
2053          output where only the first processor opens
2054          the file.  All other processors send their
2055          data to the first processor to print.
2056 
2057     The user can open an alternative visualization context with
2058     PetscViewerASCIIOpen() - output to a specified file.
2059 
2060     Level: beginner
2061 
2062 .keywords: TS, timestep, view
2063 
2064 .seealso: PetscViewerASCIIOpen()
2065 @*/
2066 PetscErrorCode  TSView(TS ts,PetscViewer viewer)
2067 {
2068   PetscErrorCode ierr;
2069   TSType         type;
2070   PetscBool      iascii,isstring,isundials,isbinary,isdraw;
2071   DMTS           sdm;
2072 #if defined(PETSC_HAVE_SAWS)
2073   PetscBool      issaws;
2074 #endif
2075 
2076   PetscFunctionBegin;
2077   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2078   if (!viewer) {
2079     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer);CHKERRQ(ierr);
2080   }
2081   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2082   PetscCheckSameComm(ts,1,viewer,2);
2083 
2084   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2085   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2086   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2087   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
2088 #if defined(PETSC_HAVE_SAWS)
2089   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr);
2090 #endif
2091   if (iascii) {
2092     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer);CHKERRQ(ierr);
2093     if (ts->ops->view) {
2094       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2095       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2096       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2097     }
2098     if (ts->max_steps < PETSC_MAX_INT) {
2099       ierr = PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps);CHKERRQ(ierr);
2100     }
2101     if (ts->max_time < PETSC_MAX_REAL) {
2102       ierr = PetscViewerASCIIPrintf(viewer,"  maximum time=%g\n",(double)ts->max_time);CHKERRQ(ierr);
2103     }
2104     if (ts->usessnes) {
2105       PetscBool lin;
2106       if (ts->problem_type == TS_NONLINEAR) {
2107         ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->snes_its);CHKERRQ(ierr);
2108       }
2109       ierr = PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->ksp_its);CHKERRQ(ierr);
2110       ierr = PetscObjectTypeCompare((PetscObject)ts->snes,SNESKSPONLY,&lin);CHKERRQ(ierr);
2111       ierr = PetscViewerASCIIPrintf(viewer,"  total number of %slinear solve failures=%D\n",lin ? "" : "non",ts->num_snes_failures);CHKERRQ(ierr);
2112     }
2113     ierr = PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%D\n",ts->reject);CHKERRQ(ierr);
2114     if (ts->vrtol) {
2115       ierr = PetscViewerASCIIPrintf(viewer,"  using vector of relative error tolerances, ");CHKERRQ(ierr);
2116     } else {
2117       ierr = PetscViewerASCIIPrintf(viewer,"  using relative error tolerance of %g, ",(double)ts->rtol);CHKERRQ(ierr);
2118     }
2119     if (ts->vatol) {
2120       ierr = PetscViewerASCIIPrintf(viewer,"  using vector of absolute error tolerances\n");CHKERRQ(ierr);
2121     } else {
2122       ierr = PetscViewerASCIIPrintf(viewer,"  using absolute error tolerance of %g\n",(double)ts->atol);CHKERRQ(ierr);
2123     }
2124     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2125     ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);
2126     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2127     if (ts->snes && ts->usessnes)  {
2128       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2129       ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);
2130       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2131     }
2132     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
2133     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
2134   } else if (isstring) {
2135     ierr = TSGetType(ts,&type);CHKERRQ(ierr);
2136     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",type);CHKERRQ(ierr);
2137   } else if (isbinary) {
2138     PetscInt    classid = TS_FILE_CLASSID;
2139     MPI_Comm    comm;
2140     PetscMPIInt rank;
2141     char        type[256];
2142 
2143     ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
2144     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
2145     if (!rank) {
2146       ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
2147       ierr = PetscStrncpy(type,((PetscObject)ts)->type_name,256);CHKERRQ(ierr);
2148       ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
2149     }
2150     if (ts->ops->view) {
2151       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2152     }
2153     if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);}
2154     ierr = DMView(ts->dm,viewer);CHKERRQ(ierr);
2155     ierr = VecView(ts->vec_sol,viewer);CHKERRQ(ierr);
2156     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
2157     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
2158   } else if (isdraw) {
2159     PetscDraw draw;
2160     char      str[36];
2161     PetscReal x,y,bottom,h;
2162 
2163     ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
2164     ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
2165     ierr   = PetscStrcpy(str,"TS: ");CHKERRQ(ierr);
2166     ierr   = PetscStrcat(str,((PetscObject)ts)->type_name);CHKERRQ(ierr);
2167     ierr   = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2168     bottom = y - h;
2169     ierr   = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
2170     if (ts->ops->view) {
2171       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2172     }
2173     if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);}
2174     if (ts->snes)  {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);}
2175     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2176 #if defined(PETSC_HAVE_SAWS)
2177   } else if (issaws) {
2178     PetscMPIInt rank;
2179     const char  *name;
2180 
2181     ierr = PetscObjectGetName((PetscObject)ts,&name);CHKERRQ(ierr);
2182     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
2183     if (!((PetscObject)ts)->amsmem && !rank) {
2184       char       dir[1024];
2185 
2186       ierr = PetscObjectViewSAWs((PetscObject)ts,viewer);CHKERRQ(ierr);
2187       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name);CHKERRQ(ierr);
2188       PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT));
2189       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name);CHKERRQ(ierr);
2190       PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE));
2191     }
2192     if (ts->ops->view) {
2193       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2194     }
2195 #endif
2196   }
2197 
2198   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2199   ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);CHKERRQ(ierr);
2200   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2201   PetscFunctionReturn(0);
2202 }
2203 
2204 /*@
2205    TSSetApplicationContext - Sets an optional user-defined context for
2206    the timesteppers.
2207 
2208    Logically Collective on TS
2209 
2210    Input Parameters:
2211 +  ts - the TS context obtained from TSCreate()
2212 -  usrP - optional user context
2213 
2214    Fortran Notes:
2215     To use this from Fortran you must write a Fortran interface definition for this
2216     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2217 
2218    Level: intermediate
2219 
2220 .keywords: TS, timestep, set, application, context
2221 
2222 .seealso: TSGetApplicationContext()
2223 @*/
2224 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
2225 {
2226   PetscFunctionBegin;
2227   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2228   ts->user = usrP;
2229   PetscFunctionReturn(0);
2230 }
2231 
2232 /*@
2233     TSGetApplicationContext - Gets the user-defined context for the
2234     timestepper.
2235 
2236     Not Collective
2237 
2238     Input Parameter:
2239 .   ts - the TS context obtained from TSCreate()
2240 
2241     Output Parameter:
2242 .   usrP - user context
2243 
2244    Fortran Notes:
2245     To use this from Fortran you must write a Fortran interface definition for this
2246     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2247 
2248     Level: intermediate
2249 
2250 .keywords: TS, timestep, get, application, context
2251 
2252 .seealso: TSSetApplicationContext()
2253 @*/
2254 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
2255 {
2256   PetscFunctionBegin;
2257   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2258   *(void**)usrP = ts->user;
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@
2263    TSGetStepNumber - Gets the number of steps completed.
2264 
2265    Not Collective
2266 
2267    Input Parameter:
2268 .  ts - the TS context obtained from TSCreate()
2269 
2270    Output Parameter:
2271 .  steps - number of steps completed so far
2272 
2273    Level: intermediate
2274 
2275 .keywords: TS, timestep, get, iteration, number
2276 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSSetPostStep()
2277 @*/
2278 PetscErrorCode TSGetStepNumber(TS ts,PetscInt *steps)
2279 {
2280   PetscFunctionBegin;
2281   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2282   PetscValidIntPointer(steps,2);
2283   *steps = ts->steps;
2284   PetscFunctionReturn(0);
2285 }
2286 
2287 /*@
2288    TSSetStepNumber - Sets the number of steps completed.
2289 
2290    Logically Collective on TS
2291 
2292    Input Parameters:
2293 +  ts - the TS context
2294 -  steps - number of steps completed so far
2295 
2296    Notes:
2297    For most uses of the TS solvers the user need not explicitly call
2298    TSSetStepNumber(), as the step counter is appropriately updated in
2299    TSSolve()/TSStep()/TSRollBack(). Power users may call this routine to
2300    reinitialize timestepping by setting the step counter to zero (and time
2301    to the initial time) to solve a similar problem with different initial
2302    conditions or parameters. Other possible use case is to continue
2303    timestepping from a previously interrupted run in such a way that TS
2304    monitors will be called with a initial nonzero step counter.
2305 
2306    Level: advanced
2307 
2308 .keywords: TS, timestep, set, iteration, number
2309 .seealso: TSGetStepNumber(), TSSetTime(), TSSetTimeStep(), TSSetSolution()
2310 @*/
2311 PetscErrorCode TSSetStepNumber(TS ts,PetscInt steps)
2312 {
2313   PetscFunctionBegin;
2314   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2315   PetscValidLogicalCollectiveInt(ts,steps,2);
2316   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Step number must be non-negative");
2317   ts->steps = steps;
2318   PetscFunctionReturn(0);
2319 }
2320 
2321 /*@
2322    TSSetTimeStep - Allows one to reset the timestep at any time,
2323    useful for simple pseudo-timestepping codes.
2324 
2325    Logically Collective on TS
2326 
2327    Input Parameters:
2328 +  ts - the TS context obtained from TSCreate()
2329 -  time_step - the size of the timestep
2330 
2331    Level: intermediate
2332 
2333 .seealso: TSGetTimeStep(), TSSetTime()
2334 
2335 .keywords: TS, set, timestep
2336 @*/
2337 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
2338 {
2339   PetscFunctionBegin;
2340   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2341   PetscValidLogicalCollectiveReal(ts,time_step,2);
2342   ts->time_step = time_step;
2343   PetscFunctionReturn(0);
2344 }
2345 
2346 /*@
2347    TSSetExactFinalTime - Determines whether to adapt the final time step to
2348      match the exact final time, interpolate solution to the exact final time,
2349      or just return at the final time TS computed.
2350 
2351   Logically Collective on TS
2352 
2353    Input Parameter:
2354 +   ts - the time-step context
2355 -   eftopt - exact final time option
2356 
2357 $  TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded
2358 $  TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time
2359 $  TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time
2360 
2361    Options Database:
2362 .   -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime
2363 
2364    Warning: If you use the option TS_EXACTFINALTIME_STEPOVER the solution may be at a very different time
2365     then the final time you selected.
2366 
2367    Level: beginner
2368 
2369 .seealso: TSExactFinalTimeOption, TSGetExactFinalTime()
2370 @*/
2371 PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
2372 {
2373   PetscFunctionBegin;
2374   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2375   PetscValidLogicalCollectiveEnum(ts,eftopt,2);
2376   ts->exact_final_time = eftopt;
2377   PetscFunctionReturn(0);
2378 }
2379 
2380 /*@
2381    TSGetExactFinalTime - Gets the exact final time option.
2382 
2383    Not Collective
2384 
2385    Input Parameter:
2386 .  ts - the TS context
2387 
2388    Output Parameter:
2389 .  eftopt - exact final time option
2390 
2391    Level: beginner
2392 
2393 .seealso: TSExactFinalTimeOption, TSSetExactFinalTime()
2394 @*/
2395 PetscErrorCode TSGetExactFinalTime(TS ts,TSExactFinalTimeOption *eftopt)
2396 {
2397   PetscFunctionBegin;
2398   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2399   PetscValidPointer(eftopt,2);
2400   *eftopt = ts->exact_final_time;
2401   PetscFunctionReturn(0);
2402 }
2403 
2404 /*@
2405    TSGetTimeStep - Gets the current timestep size.
2406 
2407    Not Collective
2408 
2409    Input Parameter:
2410 .  ts - the TS context obtained from TSCreate()
2411 
2412    Output Parameter:
2413 .  dt - the current timestep size
2414 
2415    Level: intermediate
2416 
2417 .seealso: TSSetTimeStep(), TSGetTime()
2418 
2419 .keywords: TS, get, timestep
2420 @*/
2421 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal *dt)
2422 {
2423   PetscFunctionBegin;
2424   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2425   PetscValidRealPointer(dt,2);
2426   *dt = ts->time_step;
2427   PetscFunctionReturn(0);
2428 }
2429 
2430 /*@
2431    TSGetSolution - Returns the solution at the present timestep. It
2432    is valid to call this routine inside the function that you are evaluating
2433    in order to move to the new timestep. This vector not changed until
2434    the solution at the next timestep has been calculated.
2435 
2436    Not Collective, but Vec returned is parallel if TS is parallel
2437 
2438    Input Parameter:
2439 .  ts - the TS context obtained from TSCreate()
2440 
2441    Output Parameter:
2442 .  v - the vector containing the solution
2443 
2444    Note: If you used TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); this does not return the solution at the requested
2445    final time. It returns the solution at the next timestep.
2446 
2447    Level: intermediate
2448 
2449 .seealso: TSGetTimeStep(), TSGetTime(), TSGetSolveTime(), TSGetSolutionComponents(), TSSetSolutionFunction()
2450 
2451 .keywords: TS, timestep, get, solution
2452 @*/
2453 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
2454 {
2455   PetscFunctionBegin;
2456   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2457   PetscValidPointer(v,2);
2458   *v = ts->vec_sol;
2459   PetscFunctionReturn(0);
2460 }
2461 
2462 /*@
2463    TSGetSolutionComponents - Returns any solution components at the present
2464    timestep, if available for the time integration method being used.
2465    Solution components are quantities that share the same size and
2466    structure as the solution vector.
2467 
2468    Not Collective, but Vec returned is parallel if TS is parallel
2469 
2470    Parameters :
2471 .  ts - the TS context obtained from TSCreate() (input parameter).
2472 .  n - If v is PETSC_NULL, then the number of solution components is
2473        returned through n, else the n-th solution component is
2474        returned in v.
2475 .  v - the vector containing the n-th solution component
2476        (may be PETSC_NULL to use this function to find out
2477         the number of solutions components).
2478 
2479    Level: advanced
2480 
2481 .seealso: TSGetSolution()
2482 
2483 .keywords: TS, timestep, get, solution
2484 @*/
2485 PetscErrorCode  TSGetSolutionComponents(TS ts,PetscInt *n,Vec *v)
2486 {
2487   PetscErrorCode ierr;
2488 
2489   PetscFunctionBegin;
2490   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2491   if (!ts->ops->getsolutioncomponents) *n = 0;
2492   else {
2493     ierr = (*ts->ops->getsolutioncomponents)(ts,n,v);CHKERRQ(ierr);
2494   }
2495   PetscFunctionReturn(0);
2496 }
2497 
2498 /*@
2499    TSGetAuxSolution - Returns an auxiliary solution at the present
2500    timestep, if available for the time integration method being used.
2501 
2502    Not Collective, but Vec returned is parallel if TS is parallel
2503 
2504    Parameters :
2505 .  ts - the TS context obtained from TSCreate() (input parameter).
2506 .  v - the vector containing the auxiliary solution
2507 
2508    Level: intermediate
2509 
2510 .seealso: TSGetSolution()
2511 
2512 .keywords: TS, timestep, get, solution
2513 @*/
2514 PetscErrorCode  TSGetAuxSolution(TS ts,Vec *v)
2515 {
2516   PetscErrorCode ierr;
2517 
2518   PetscFunctionBegin;
2519   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2520   if (ts->ops->getauxsolution) {
2521     ierr = (*ts->ops->getauxsolution)(ts,v);CHKERRQ(ierr);
2522   } else {
2523     ierr = VecZeroEntries(*v); CHKERRQ(ierr);
2524   }
2525   PetscFunctionReturn(0);
2526 }
2527 
2528 /*@
2529    TSGetTimeError - Returns the estimated error vector, if the chosen
2530    TSType has an error estimation functionality.
2531 
2532    Not Collective, but Vec returned is parallel if TS is parallel
2533 
2534    Note: MUST call after TSSetUp()
2535 
2536    Parameters :
2537 .  ts - the TS context obtained from TSCreate() (input parameter).
2538 .  n - current estimate (n=0) or previous one (n=-1)
2539 .  v - the vector containing the error (same size as the solution).
2540 
2541    Level: intermediate
2542 
2543 .seealso: TSGetSolution(), TSSetTimeError()
2544 
2545 .keywords: TS, timestep, get, error
2546 @*/
2547 PetscErrorCode  TSGetTimeError(TS ts,PetscInt n,Vec *v)
2548 {
2549   PetscErrorCode ierr;
2550 
2551   PetscFunctionBegin;
2552   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2553   if (ts->ops->gettimeerror) {
2554     ierr = (*ts->ops->gettimeerror)(ts,n,v);CHKERRQ(ierr);
2555   } else {
2556     ierr = VecZeroEntries(*v);CHKERRQ(ierr);
2557   }
2558   PetscFunctionReturn(0);
2559 }
2560 
2561 /*@
2562    TSSetTimeError - Sets the estimated error vector, if the chosen
2563    TSType has an error estimation functionality. This can be used
2564    to restart such a time integrator with a given error vector.
2565 
2566    Not Collective, but Vec returned is parallel if TS is parallel
2567 
2568    Parameters :
2569 .  ts - the TS context obtained from TSCreate() (input parameter).
2570 .  v - the vector containing the error (same size as the solution).
2571 
2572    Level: intermediate
2573 
2574 .seealso: TSSetSolution(), TSGetTimeError)
2575 
2576 .keywords: TS, timestep, get, error
2577 @*/
2578 PetscErrorCode  TSSetTimeError(TS ts,Vec v)
2579 {
2580   PetscErrorCode ierr;
2581 
2582   PetscFunctionBegin;
2583   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2584   if (!ts->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetUp() first");
2585   if (ts->ops->settimeerror) {
2586     ierr = (*ts->ops->settimeerror)(ts,v);CHKERRQ(ierr);
2587   }
2588   PetscFunctionReturn(0);
2589 }
2590 
2591 /* ----- Routines to initialize and destroy a timestepper ---- */
2592 /*@
2593   TSSetProblemType - Sets the type of problem to be solved.
2594 
2595   Not collective
2596 
2597   Input Parameters:
2598 + ts   - The TS
2599 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2600 .vb
2601          U_t - A U = 0      (linear)
2602          U_t - A(t) U = 0   (linear)
2603          F(t,U,U_t) = 0     (nonlinear)
2604 .ve
2605 
2606    Level: beginner
2607 
2608 .keywords: TS, problem type
2609 .seealso: TSSetUp(), TSProblemType, TS
2610 @*/
2611 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
2612 {
2613   PetscErrorCode ierr;
2614 
2615   PetscFunctionBegin;
2616   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2617   ts->problem_type = type;
2618   if (type == TS_LINEAR) {
2619     SNES snes;
2620     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2621     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
2622   }
2623   PetscFunctionReturn(0);
2624 }
2625 
2626 /*@C
2627   TSGetProblemType - Gets the type of problem to be solved.
2628 
2629   Not collective
2630 
2631   Input Parameter:
2632 . ts   - The TS
2633 
2634   Output Parameter:
2635 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2636 .vb
2637          M U_t = A U
2638          M(t) U_t = A(t) U
2639          F(t,U,U_t)
2640 .ve
2641 
2642    Level: beginner
2643 
2644 .keywords: TS, problem type
2645 .seealso: TSSetUp(), TSProblemType, TS
2646 @*/
2647 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
2648 {
2649   PetscFunctionBegin;
2650   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2651   PetscValidIntPointer(type,2);
2652   *type = ts->problem_type;
2653   PetscFunctionReturn(0);
2654 }
2655 
2656 /*@
2657    TSSetUp - Sets up the internal data structures for the later use
2658    of a timestepper.
2659 
2660    Collective on TS
2661 
2662    Input Parameter:
2663 .  ts - the TS context obtained from TSCreate()
2664 
2665    Notes:
2666    For basic use of the TS solvers the user need not explicitly call
2667    TSSetUp(), since these actions will automatically occur during
2668    the call to TSStep() or TSSolve().  However, if one wishes to control this
2669    phase separately, TSSetUp() should be called after TSCreate()
2670    and optional routines of the form TSSetXXX(), but before TSStep() and TSSolve().
2671 
2672    Level: advanced
2673 
2674 .keywords: TS, timestep, setup
2675 
2676 .seealso: TSCreate(), TSStep(), TSDestroy(), TSSolve()
2677 @*/
2678 PetscErrorCode  TSSetUp(TS ts)
2679 {
2680   PetscErrorCode ierr;
2681   DM             dm;
2682   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2683   PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
2684   TSIFunction    ifun;
2685   TSIJacobian    ijac;
2686   TSI2Jacobian   i2jac;
2687   TSRHSJacobian  rhsjac;
2688   PetscBool      isnone;
2689 
2690   PetscFunctionBegin;
2691   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2692   if (ts->setupcalled) PetscFunctionReturn(0);
2693 
2694   if (!((PetscObject)ts)->type_name) {
2695     ierr = TSGetIFunction(ts,NULL,&ifun,NULL);CHKERRQ(ierr);
2696     ierr = TSSetType(ts,ifun ? TSBEULER : TSEULER);CHKERRQ(ierr);
2697   }
2698 
2699   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
2700 
2701   if (ts->rhsjacobian.reuse) {
2702     Mat Amat,Pmat;
2703     SNES snes;
2704     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2705     ierr = SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL);CHKERRQ(ierr);
2706     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2707      * have displaced the RHS matrix */
2708     if (Amat == ts->Arhs) {
2709       /* we need to copy the values of the matrix because for the constant Jacobian case the user will never set the numerical values in this new location */
2710       ierr = MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat);CHKERRQ(ierr);
2711       ierr = SNESSetJacobian(snes,Amat,NULL,NULL,NULL);CHKERRQ(ierr);
2712       ierr = MatDestroy(&Amat);CHKERRQ(ierr);
2713     }
2714     if (Pmat == ts->Brhs) {
2715       ierr = MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat);CHKERRQ(ierr);
2716       ierr = SNESSetJacobian(snes,NULL,Pmat,NULL,NULL);CHKERRQ(ierr);
2717       ierr = MatDestroy(&Pmat);CHKERRQ(ierr);
2718     }
2719   }
2720 
2721   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
2722   ierr = TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type);CHKERRQ(ierr);
2723 
2724   if (ts->ops->setup) {
2725     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
2726   }
2727 
2728   /* Attempt to check/preset a default value for the exact final time option */
2729   ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone);CHKERRQ(ierr);
2730   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED)
2731     ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2732 
2733   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2734      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2735    */
2736   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2737   ierr = DMSNESGetFunction(dm,&func,NULL);CHKERRQ(ierr);
2738   if (!func) {
2739     ierr = DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
2740   }
2741   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2742      Otherwise, the SNES will use coloring internally to form the Jacobian.
2743    */
2744   ierr = DMSNESGetJacobian(dm,&jac,NULL);CHKERRQ(ierr);
2745   ierr = DMTSGetIJacobian(dm,&ijac,NULL);CHKERRQ(ierr);
2746   ierr = DMTSGetI2Jacobian(dm,&i2jac,NULL);CHKERRQ(ierr);
2747   ierr = DMTSGetRHSJacobian(dm,&rhsjac,NULL);CHKERRQ(ierr);
2748   if (!jac && (ijac || i2jac || rhsjac)) {
2749     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2750   }
2751 
2752   /* if time integration scheme has a starting method, call it */
2753   if (ts->ops->startingmethod) {
2754     ierr = (*ts->ops->startingmethod)(ts);CHKERRQ(ierr);
2755   }
2756 
2757   ts->setupcalled = PETSC_TRUE;
2758   PetscFunctionReturn(0);
2759 }
2760 
2761 /*@
2762    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
2763 
2764    Collective on TS
2765 
2766    Input Parameter:
2767 .  ts - the TS context obtained from TSCreate()
2768 
2769    Level: beginner
2770 
2771 .keywords: TS, timestep, reset
2772 
2773 .seealso: TSCreate(), TSSetup(), TSDestroy()
2774 @*/
2775 PetscErrorCode  TSReset(TS ts)
2776 {
2777   PetscInt       i;
2778   PetscErrorCode ierr;
2779 
2780   PetscFunctionBegin;
2781   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2782 
2783   if (ts->ops->reset) {
2784     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
2785   }
2786   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
2787   if (ts->adapt) {ierr = TSAdaptReset(ts->adapt);CHKERRQ(ierr);}
2788 
2789   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
2790   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
2791   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
2792   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2793   ierr = VecDestroy(&ts->vec_dot);CHKERRQ(ierr);
2794   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
2795   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
2796   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
2797 
2798   ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
2799   ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
2800 
2801   ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2802   ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
2803   ierr = VecDestroy(&ts->vec_costintegrand);CHKERRQ(ierr);
2804   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
2805 
2806   for (i=0; i<ts->num_rhs_splits; i++) {
2807     ierr = ISDestroy(&ts->iss[i]);CHKERRQ(ierr);
2808   }
2809   ts->setupcalled = PETSC_FALSE;
2810   PetscFunctionReturn(0);
2811 }
2812 
2813 /*@
2814    TSDestroy - Destroys the timestepper context that was created
2815    with TSCreate().
2816 
2817    Collective on TS
2818 
2819    Input Parameter:
2820 .  ts - the TS context obtained from TSCreate()
2821 
2822    Level: beginner
2823 
2824 .keywords: TS, timestepper, destroy
2825 
2826 .seealso: TSCreate(), TSSetUp(), TSSolve()
2827 @*/
2828 PetscErrorCode  TSDestroy(TS *ts)
2829 {
2830   PetscErrorCode ierr;
2831 
2832   PetscFunctionBegin;
2833   if (!*ts) PetscFunctionReturn(0);
2834   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
2835   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
2836 
2837   ierr = TSReset((*ts));CHKERRQ(ierr);
2838 
2839   /* if memory was published with SAWs then destroy it */
2840   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
2841   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
2842 
2843   ierr = TSTrajectoryDestroy(&(*ts)->trajectory);CHKERRQ(ierr);
2844 
2845   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
2846   ierr = TSEventDestroy(&(*ts)->event);CHKERRQ(ierr);
2847 
2848   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
2849   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
2850   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
2851   ierr = TSAdjointMonitorCancel((*ts));CHKERRQ(ierr);
2852 
2853   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
2854   PetscFunctionReturn(0);
2855 }
2856 
2857 /*@
2858    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2859    a TS (timestepper) context. Valid only for nonlinear problems.
2860 
2861    Not Collective, but SNES is parallel if TS is parallel
2862 
2863    Input Parameter:
2864 .  ts - the TS context obtained from TSCreate()
2865 
2866    Output Parameter:
2867 .  snes - the nonlinear solver context
2868 
2869    Notes:
2870    The user can then directly manipulate the SNES context to set various
2871    options, etc.  Likewise, the user can then extract and manipulate the
2872    KSP, KSP, and PC contexts as well.
2873 
2874    TSGetSNES() does not work for integrators that do not use SNES; in
2875    this case TSGetSNES() returns NULL in snes.
2876 
2877    Level: beginner
2878 
2879 .keywords: timestep, get, SNES
2880 @*/
2881 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2882 {
2883   PetscErrorCode ierr;
2884 
2885   PetscFunctionBegin;
2886   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2887   PetscValidPointer(snes,2);
2888   if (!ts->snes) {
2889     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
2890     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2891     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);CHKERRQ(ierr);
2892     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
2893     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2894     if (ts->problem_type == TS_LINEAR) {
2895       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
2896     }
2897   }
2898   *snes = ts->snes;
2899   PetscFunctionReturn(0);
2900 }
2901 
2902 /*@
2903    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2904 
2905    Collective
2906 
2907    Input Parameter:
2908 +  ts - the TS context obtained from TSCreate()
2909 -  snes - the nonlinear solver context
2910 
2911    Notes:
2912    Most users should have the TS created by calling TSGetSNES()
2913 
2914    Level: developer
2915 
2916 .keywords: timestep, set, SNES
2917 @*/
2918 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2919 {
2920   PetscErrorCode ierr;
2921   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2922 
2923   PetscFunctionBegin;
2924   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2925   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2926   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
2927   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
2928 
2929   ts->snes = snes;
2930 
2931   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2932   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
2933   if (func == SNESTSFormJacobian) {
2934     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2935   }
2936   PetscFunctionReturn(0);
2937 }
2938 
2939 /*@
2940    TSGetKSP - Returns the KSP (linear solver) associated with
2941    a TS (timestepper) context.
2942 
2943    Not Collective, but KSP is parallel if TS is parallel
2944 
2945    Input Parameter:
2946 .  ts - the TS context obtained from TSCreate()
2947 
2948    Output Parameter:
2949 .  ksp - the nonlinear solver context
2950 
2951    Notes:
2952    The user can then directly manipulate the KSP context to set various
2953    options, etc.  Likewise, the user can then extract and manipulate the
2954    KSP and PC contexts as well.
2955 
2956    TSGetKSP() does not work for integrators that do not use KSP;
2957    in this case TSGetKSP() returns NULL in ksp.
2958 
2959    Level: beginner
2960 
2961 .keywords: timestep, get, KSP
2962 @*/
2963 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2964 {
2965   PetscErrorCode ierr;
2966   SNES           snes;
2967 
2968   PetscFunctionBegin;
2969   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2970   PetscValidPointer(ksp,2);
2971   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2972   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2973   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2974   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2975   PetscFunctionReturn(0);
2976 }
2977 
2978 /* ----------- Routines to set solver parameters ---------- */
2979 
2980 /*@
2981    TSSetMaxSteps - Sets the maximum number of steps to use.
2982 
2983    Logically Collective on TS
2984 
2985    Input Parameters:
2986 +  ts - the TS context obtained from TSCreate()
2987 -  maxsteps - maximum number of steps to use
2988 
2989    Options Database Keys:
2990 .  -ts_max_steps <maxsteps> - Sets maxsteps
2991 
2992    Notes:
2993    The default maximum number of steps is 5000
2994 
2995    Level: intermediate
2996 
2997 .keywords: TS, timestep, set, maximum, steps
2998 
2999 .seealso: TSGetMaxSteps(), TSSetMaxTime(), TSSetExactFinalTime()
3000 @*/
3001 PetscErrorCode TSSetMaxSteps(TS ts,PetscInt maxsteps)
3002 {
3003   PetscFunctionBegin;
3004   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3005   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
3006   if (maxsteps < 0 ) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of steps must be non-negative");
3007   ts->max_steps = maxsteps;
3008   PetscFunctionReturn(0);
3009 }
3010 
3011 /*@
3012    TSGetMaxSteps - Gets the maximum number of steps to use.
3013 
3014    Not Collective
3015 
3016    Input Parameters:
3017 .  ts - the TS context obtained from TSCreate()
3018 
3019    Output Parameter:
3020 .  maxsteps - maximum number of steps to use
3021 
3022    Level: advanced
3023 
3024 .keywords: TS, timestep, get, maximum, steps
3025 
3026 .seealso: TSSetMaxSteps(), TSGetMaxTime(), TSSetMaxTime()
3027 @*/
3028 PetscErrorCode TSGetMaxSteps(TS ts,PetscInt *maxsteps)
3029 {
3030   PetscFunctionBegin;
3031   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3032   PetscValidIntPointer(maxsteps,2);
3033   *maxsteps = ts->max_steps;
3034   PetscFunctionReturn(0);
3035 }
3036 
3037 /*@
3038    TSSetMaxTime - Sets the maximum (or final) time for timestepping.
3039 
3040    Logically Collective on TS
3041 
3042    Input Parameters:
3043 +  ts - the TS context obtained from TSCreate()
3044 -  maxtime - final time to step to
3045 
3046    Options Database Keys:
3047 .  -ts_max_time <maxtime> - Sets maxtime
3048 
3049    Notes:
3050    The default maximum time is 5.0
3051 
3052    Level: intermediate
3053 
3054 .keywords: TS, timestep, set, maximum, time
3055 
3056 .seealso: TSGetMaxTime(), TSSetMaxSteps(), TSSetExactFinalTime()
3057 @*/
3058 PetscErrorCode TSSetMaxTime(TS ts,PetscReal maxtime)
3059 {
3060   PetscFunctionBegin;
3061   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3062   PetscValidLogicalCollectiveReal(ts,maxtime,2);
3063   ts->max_time = maxtime;
3064   PetscFunctionReturn(0);
3065 }
3066 
3067 /*@
3068    TSGetMaxTime - Gets the maximum (or final) time for timestepping.
3069 
3070    Not Collective
3071 
3072    Input Parameters:
3073 .  ts - the TS context obtained from TSCreate()
3074 
3075    Output Parameter:
3076 .  maxtime - final time to step to
3077 
3078    Level: advanced
3079 
3080 .keywords: TS, timestep, get, maximum, time
3081 
3082 .seealso: TSSetMaxTime(), TSGetMaxSteps(), TSSetMaxSteps()
3083 @*/
3084 PetscErrorCode TSGetMaxTime(TS ts,PetscReal *maxtime)
3085 {
3086   PetscFunctionBegin;
3087   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3088   PetscValidRealPointer(maxtime,2);
3089   *maxtime = ts->max_time;
3090   PetscFunctionReturn(0);
3091 }
3092 
3093 /*@
3094    TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep().
3095 
3096    Level: deprecated
3097 
3098 @*/
3099 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
3100 {
3101   PetscErrorCode ierr;
3102   PetscFunctionBegin;
3103   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3104   ierr = TSSetTime(ts,initial_time);CHKERRQ(ierr);
3105   ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
3106   PetscFunctionReturn(0);
3107 }
3108 
3109 /*@
3110    TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime().
3111 
3112    Level: deprecated
3113 
3114 @*/
3115 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
3116 {
3117   PetscFunctionBegin;
3118   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3119   if (maxsteps) {
3120     PetscValidIntPointer(maxsteps,2);
3121     *maxsteps = ts->max_steps;
3122   }
3123   if (maxtime) {
3124     PetscValidScalarPointer(maxtime,3);
3125     *maxtime = ts->max_time;
3126   }
3127   PetscFunctionReturn(0);
3128 }
3129 
3130 /*@
3131    TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime().
3132 
3133    Level: deprecated
3134 
3135 @*/
3136 PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
3137 {
3138   PetscFunctionBegin;
3139   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3140   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
3141   PetscValidLogicalCollectiveReal(ts,maxtime,2);
3142   if (maxsteps >= 0) ts->max_steps = maxsteps;
3143   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
3144   PetscFunctionReturn(0);
3145 }
3146 
3147 /*@
3148    TSGetTimeStepNumber - Deprecated, use TSGetStepNumber().
3149 
3150    Level: deprecated
3151 
3152 @*/
3153 PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3154 
3155 /*@
3156    TSGetTotalSteps - Deprecated, use TSGetStepNumber().
3157 
3158    Level: deprecated
3159 
3160 @*/
3161 PetscErrorCode TSGetTotalSteps(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3162 
3163 /*@
3164    TSSetSolution - Sets the initial solution vector
3165    for use by the TS routines.
3166 
3167    Logically Collective on TS and Vec
3168 
3169    Input Parameters:
3170 +  ts - the TS context obtained from TSCreate()
3171 -  u - the solution vector
3172 
3173    Level: beginner
3174 
3175 .keywords: TS, timestep, set, solution, initial values
3176 
3177 .seealso: TSSetSolutionFunction(), TSGetSolution(), TSCreate()
3178 @*/
3179 PetscErrorCode  TSSetSolution(TS ts,Vec u)
3180 {
3181   PetscErrorCode ierr;
3182   DM             dm;
3183 
3184   PetscFunctionBegin;
3185   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3186   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3187   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
3188   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
3189   ts->vec_sol = u;
3190 
3191   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3192   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
3193   PetscFunctionReturn(0);
3194 }
3195 
3196 /*@C
3197   TSSetPreStep - Sets the general-purpose function
3198   called once at the beginning of each time step.
3199 
3200   Logically Collective on TS
3201 
3202   Input Parameters:
3203 + ts   - The TS context obtained from TSCreate()
3204 - func - The function
3205 
3206   Calling sequence of func:
3207 . func (TS ts);
3208 
3209   Level: intermediate
3210 
3211 .keywords: TS, timestep
3212 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep(), TSRestartStep()
3213 @*/
3214 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
3215 {
3216   PetscFunctionBegin;
3217   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3218   ts->prestep = func;
3219   PetscFunctionReturn(0);
3220 }
3221 
3222 /*@
3223   TSPreStep - Runs the user-defined pre-step function.
3224 
3225   Collective on TS
3226 
3227   Input Parameters:
3228 . ts   - The TS context obtained from TSCreate()
3229 
3230   Notes:
3231   TSPreStep() is typically used within time stepping implementations,
3232   so most users would not generally call this routine themselves.
3233 
3234   Level: developer
3235 
3236 .keywords: TS, timestep
3237 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
3238 @*/
3239 PetscErrorCode  TSPreStep(TS ts)
3240 {
3241   PetscErrorCode ierr;
3242 
3243   PetscFunctionBegin;
3244   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3245   if (ts->prestep) {
3246     Vec              U;
3247     PetscObjectState sprev,spost;
3248 
3249     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3250     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3251     PetscStackCallStandard((*ts->prestep),(ts));
3252     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3253     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3254   }
3255   PetscFunctionReturn(0);
3256 }
3257 
3258 /*@C
3259   TSSetPreStage - Sets the general-purpose function
3260   called once at the beginning of each stage.
3261 
3262   Logically Collective on TS
3263 
3264   Input Parameters:
3265 + ts   - The TS context obtained from TSCreate()
3266 - func - The function
3267 
3268   Calling sequence of func:
3269 . PetscErrorCode func(TS ts, PetscReal stagetime);
3270 
3271   Level: intermediate
3272 
3273   Note:
3274   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3275   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3276   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3277 
3278 .keywords: TS, timestep
3279 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3280 @*/
3281 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
3282 {
3283   PetscFunctionBegin;
3284   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3285   ts->prestage = func;
3286   PetscFunctionReturn(0);
3287 }
3288 
3289 /*@C
3290   TSSetPostStage - Sets the general-purpose function
3291   called once at the end of each stage.
3292 
3293   Logically Collective on TS
3294 
3295   Input Parameters:
3296 + ts   - The TS context obtained from TSCreate()
3297 - func - The function
3298 
3299   Calling sequence of func:
3300 . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
3301 
3302   Level: intermediate
3303 
3304   Note:
3305   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3306   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3307   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3308 
3309 .keywords: TS, timestep
3310 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3311 @*/
3312 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
3313 {
3314   PetscFunctionBegin;
3315   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3316   ts->poststage = func;
3317   PetscFunctionReturn(0);
3318 }
3319 
3320 /*@C
3321   TSSetPostEvaluate - Sets the general-purpose function
3322   called once at the end of each step evaluation.
3323 
3324   Logically Collective on TS
3325 
3326   Input Parameters:
3327 + ts   - The TS context obtained from TSCreate()
3328 - func - The function
3329 
3330   Calling sequence of func:
3331 . PetscErrorCode func(TS ts);
3332 
3333   Level: intermediate
3334 
3335   Note:
3336   Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling
3337   thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep()
3338   may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step
3339   solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step
3340   with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime()
3341 
3342 .keywords: TS, timestep
3343 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3344 @*/
3345 PetscErrorCode  TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS))
3346 {
3347   PetscFunctionBegin;
3348   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3349   ts->postevaluate = func;
3350   PetscFunctionReturn(0);
3351 }
3352 
3353 /*@
3354   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
3355 
3356   Collective on TS
3357 
3358   Input Parameters:
3359 . ts          - The TS context obtained from TSCreate()
3360   stagetime   - The absolute time of the current stage
3361 
3362   Notes:
3363   TSPreStage() is typically used within time stepping implementations,
3364   most users would not generally call this routine themselves.
3365 
3366   Level: developer
3367 
3368 .keywords: TS, timestep
3369 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3370 @*/
3371 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
3372 {
3373   PetscErrorCode ierr;
3374 
3375   PetscFunctionBegin;
3376   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3377   if (ts->prestage) {
3378     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
3379   }
3380   PetscFunctionReturn(0);
3381 }
3382 
3383 /*@
3384   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3385 
3386   Collective on TS
3387 
3388   Input Parameters:
3389 . ts          - The TS context obtained from TSCreate()
3390   stagetime   - The absolute time of the current stage
3391   stageindex  - Stage number
3392   Y           - Array of vectors (of size = total number
3393                 of stages) with the stage solutions
3394 
3395   Notes:
3396   TSPostStage() is typically used within time stepping implementations,
3397   most users would not generally call this routine themselves.
3398 
3399   Level: developer
3400 
3401 .keywords: TS, timestep
3402 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3403 @*/
3404 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3405 {
3406   PetscErrorCode ierr;
3407 
3408   PetscFunctionBegin;
3409   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3410   if (ts->poststage) {
3411     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
3412   }
3413   PetscFunctionReturn(0);
3414 }
3415 
3416 /*@
3417   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3418 
3419   Collective on TS
3420 
3421   Input Parameters:
3422 . ts          - The TS context obtained from TSCreate()
3423 
3424   Notes:
3425   TSPostEvaluate() is typically used within time stepping implementations,
3426   most users would not generally call this routine themselves.
3427 
3428   Level: developer
3429 
3430 .keywords: TS, timestep
3431 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep()
3432 @*/
3433 PetscErrorCode  TSPostEvaluate(TS ts)
3434 {
3435   PetscErrorCode ierr;
3436 
3437   PetscFunctionBegin;
3438   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3439   if (ts->postevaluate) {
3440     Vec              U;
3441     PetscObjectState sprev,spost;
3442 
3443     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3444     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3445     PetscStackCallStandard((*ts->postevaluate),(ts));
3446     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3447     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3448   }
3449   PetscFunctionReturn(0);
3450 }
3451 
3452 /*@C
3453   TSSetPostStep - Sets the general-purpose function
3454   called once at the end of each time step.
3455 
3456   Logically Collective on TS
3457 
3458   Input Parameters:
3459 + ts   - The TS context obtained from TSCreate()
3460 - func - The function
3461 
3462   Calling sequence of func:
3463 $ func (TS ts);
3464 
3465   Notes:
3466   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3467   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3468   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3469 
3470   Level: intermediate
3471 
3472 .keywords: TS, timestep
3473 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetStepNumber(), TSGetTime(), TSRestartStep()
3474 @*/
3475 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
3476 {
3477   PetscFunctionBegin;
3478   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3479   ts->poststep = func;
3480   PetscFunctionReturn(0);
3481 }
3482 
3483 /*@
3484   TSPostStep - Runs the user-defined post-step function.
3485 
3486   Collective on TS
3487 
3488   Input Parameters:
3489 . ts   - The TS context obtained from TSCreate()
3490 
3491   Notes:
3492   TSPostStep() is typically used within time stepping implementations,
3493   so most users would not generally call this routine themselves.
3494 
3495   Level: developer
3496 
3497 .keywords: TS, timestep
3498 @*/
3499 PetscErrorCode  TSPostStep(TS ts)
3500 {
3501   PetscErrorCode ierr;
3502 
3503   PetscFunctionBegin;
3504   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3505   if (ts->poststep) {
3506     Vec              U;
3507     PetscObjectState sprev,spost;
3508 
3509     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3510     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3511     PetscStackCallStandard((*ts->poststep),(ts));
3512     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3513     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3514   }
3515   PetscFunctionReturn(0);
3516 }
3517 
3518 /* ------------ Routines to set performance monitoring options ----------- */
3519 
3520 /*@C
3521    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
3522    timestep to display the iteration's  progress.
3523 
3524    Logically Collective on TS
3525 
3526    Input Parameters:
3527 +  ts - the TS context obtained from TSCreate()
3528 .  monitor - monitoring routine
3529 .  mctx - [optional] user-defined context for private data for the
3530              monitor routine (use NULL if no context is desired)
3531 -  monitordestroy - [optional] routine that frees monitor context
3532           (may be NULL)
3533 
3534    Calling sequence of monitor:
3535 $    PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
3536 
3537 +    ts - the TS context
3538 .    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)
3539 .    time - current time
3540 .    u - current iterate
3541 -    mctx - [optional] monitoring context
3542 
3543    Notes:
3544    This routine adds an additional monitor to the list of monitors that
3545    already has been loaded.
3546 
3547    Fortran Notes:
3548     Only a single monitor function can be set for each TS object
3549 
3550    Level: intermediate
3551 
3552 .keywords: TS, timestep, set, monitor
3553 
3554 .seealso: TSMonitorDefault(), TSMonitorCancel()
3555 @*/
3556 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
3557 {
3558   PetscErrorCode ierr;
3559   PetscInt       i;
3560   PetscBool      identical;
3561 
3562   PetscFunctionBegin;
3563   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3564   for (i=0; i<ts->numbermonitors;i++) {
3565     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))monitor,mctx,mdestroy,(PetscErrorCode (*)(void))ts->monitor[i],ts->monitorcontext[i],ts->monitordestroy[i],&identical);CHKERRQ(ierr);
3566     if (identical) PetscFunctionReturn(0);
3567   }
3568   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3569   ts->monitor[ts->numbermonitors]          = monitor;
3570   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
3571   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
3572   PetscFunctionReturn(0);
3573 }
3574 
3575 /*@C
3576    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
3577 
3578    Logically Collective on TS
3579 
3580    Input Parameters:
3581 .  ts - the TS context obtained from TSCreate()
3582 
3583    Notes:
3584    There is no way to remove a single, specific monitor.
3585 
3586    Level: intermediate
3587 
3588 .keywords: TS, timestep, set, monitor
3589 
3590 .seealso: TSMonitorDefault(), TSMonitorSet()
3591 @*/
3592 PetscErrorCode  TSMonitorCancel(TS ts)
3593 {
3594   PetscErrorCode ierr;
3595   PetscInt       i;
3596 
3597   PetscFunctionBegin;
3598   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3599   for (i=0; i<ts->numbermonitors; i++) {
3600     if (ts->monitordestroy[i]) {
3601       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
3602     }
3603   }
3604   ts->numbermonitors = 0;
3605   PetscFunctionReturn(0);
3606 }
3607 
3608 /*@C
3609    TSMonitorDefault - The Default monitor, prints the timestep and time for each step
3610 
3611    Level: intermediate
3612 
3613 .keywords: TS, set, monitor
3614 
3615 .seealso:  TSMonitorSet()
3616 @*/
3617 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
3618 {
3619   PetscErrorCode ierr;
3620   PetscViewer    viewer =  vf->viewer;
3621   PetscBool      iascii,ibinary;
3622 
3623   PetscFunctionBegin;
3624   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3625   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3626   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
3627   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3628   if (iascii) {
3629     ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3630     if (step == -1){ /* this indicates it is an interpolated solution */
3631       ierr = PetscViewerASCIIPrintf(viewer,"Interpolated solution at time %g between steps %D and %D\n",(double)ptime,ts->steps-1,ts->steps);CHKERRQ(ierr);
3632     } else {
3633       ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
3634     }
3635     ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3636   } else if (ibinary) {
3637     PetscMPIInt rank;
3638     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
3639     if (!rank) {
3640       PetscBool skipHeader;
3641       PetscInt  classid = REAL_FILE_CLASSID;
3642 
3643       ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
3644       if (!skipHeader) {
3645          ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
3646        }
3647       ierr = PetscRealView(1,&ptime,viewer);CHKERRQ(ierr);
3648     } else {
3649       ierr = PetscRealView(0,&ptime,viewer);CHKERRQ(ierr);
3650     }
3651   }
3652   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3653   PetscFunctionReturn(0);
3654 }
3655 
3656 /*@
3657    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3658 
3659    Collective on TS
3660 
3661    Input Argument:
3662 +  ts - time stepping context
3663 -  t - time to interpolate to
3664 
3665    Output Argument:
3666 .  U - state at given time
3667 
3668    Level: intermediate
3669 
3670    Developer Notes:
3671    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3672 
3673 .keywords: TS, set
3674 
3675 .seealso: TSSetExactFinalTime(), TSSolve()
3676 @*/
3677 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
3678 {
3679   PetscErrorCode ierr;
3680 
3681   PetscFunctionBegin;
3682   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3683   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3684   if (t < ts->ptime_prev || t > ts->ptime) SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Requested time %g not in last time steps [%g,%g]",t,(double)ts->ptime_prev,(double)ts->ptime);
3685   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
3686   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
3687   PetscFunctionReturn(0);
3688 }
3689 
3690 /*@
3691    TSStep - Steps one time step
3692 
3693    Collective on TS
3694 
3695    Input Parameter:
3696 .  ts - the TS context obtained from TSCreate()
3697 
3698    Level: developer
3699 
3700    Notes:
3701    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3702 
3703    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3704    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3705 
3706    This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the
3707    time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3708 
3709 .keywords: TS, timestep, solve
3710 
3711 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3712 @*/
3713 PetscErrorCode  TSStep(TS ts)
3714 {
3715   PetscErrorCode   ierr;
3716   static PetscBool cite = PETSC_FALSE;
3717   PetscReal        ptime;
3718 
3719   PetscFunctionBegin;
3720   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3721   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
3722                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3723                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
3724                                 "  type        = {Preprint},\n"
3725                                 "  number      = {ANL/MCS-P5061-0114},\n"
3726                                 "  institution = {Argonne National Laboratory},\n"
3727                                 "  year        = {2014}\n}\n",&cite);CHKERRQ(ierr);
3728 
3729   ierr = TSSetUp(ts);CHKERRQ(ierr);
3730   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
3731 
3732   if (ts->max_time >= PETSC_MAX_REAL && ts->max_steps == PETSC_MAX_INT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>");
3733   if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSStep()");
3734   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP && !ts->adapt) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE");
3735 
3736   if (!ts->steps) ts->ptime_prev = ts->ptime;
3737   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
3738   ts->reason = TS_CONVERGED_ITERATING;
3739   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3740   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3741   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
3742   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3743   ts->ptime_prev = ptime;
3744   ts->steps++;
3745   ts->steprollback = PETSC_FALSE;
3746   ts->steprestart  = PETSC_FALSE;
3747 
3748   if (ts->reason < 0) {
3749     if (ts->errorifstepfailed) {
3750       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s, increase -ts_max_snes_failures or make negative to attempt recovery",TSConvergedReasons[ts->reason]);
3751       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3752     }
3753   } else if (!ts->reason) {
3754     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3755     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3756   }
3757   PetscFunctionReturn(0);
3758 }
3759 
3760 /*@
3761    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3762    at the end of a time step with a given order of accuracy.
3763 
3764    Collective on TS
3765 
3766    Input Arguments:
3767 +  ts - time stepping context
3768 .  wnormtype - norm type, either NORM_2 or NORM_INFINITY
3769 -  order - optional, desired order for the error evaluation or PETSC_DECIDE
3770 
3771    Output Arguments:
3772 +  order - optional, the actual order of the error evaluation
3773 -  wlte - the weighted local truncation error norm
3774 
3775    Level: advanced
3776 
3777    Notes:
3778    If the timestepper cannot evaluate the error in a particular step
3779    (eg. in the first step or restart steps after event handling),
3780    this routine returns wlte=-1.0 .
3781 
3782 .seealso: TSStep(), TSAdapt, TSErrorWeightedNorm()
3783 @*/
3784 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
3785 {
3786   PetscErrorCode ierr;
3787 
3788   PetscFunctionBegin;
3789   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3790   PetscValidType(ts,1);
3791   PetscValidLogicalCollectiveEnum(ts,wnormtype,4);
3792   if (order) PetscValidIntPointer(order,3);
3793   if (order) PetscValidLogicalCollectiveInt(ts,*order,3);
3794   PetscValidRealPointer(wlte,4);
3795   if (wnormtype != NORM_2 && wnormtype != NORM_INFINITY) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
3796   if (!ts->ops->evaluatewlte) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name);
3797   ierr = (*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte);CHKERRQ(ierr);
3798   PetscFunctionReturn(0);
3799 }
3800 
3801 /*@
3802    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3803 
3804    Collective on TS
3805 
3806    Input Arguments:
3807 +  ts - time stepping context
3808 .  order - desired order of accuracy
3809 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
3810 
3811    Output Arguments:
3812 .  U - state at the end of the current step
3813 
3814    Level: advanced
3815 
3816    Notes:
3817    This function cannot be called until all stages have been evaluated.
3818    It is normally called by adaptive controllers before a step has been accepted and may also be called by the user after TSStep() has returned.
3819 
3820 .seealso: TSStep(), TSAdapt
3821 @*/
3822 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
3823 {
3824   PetscErrorCode ierr;
3825 
3826   PetscFunctionBegin;
3827   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3828   PetscValidType(ts,1);
3829   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3830   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3831   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
3832   PetscFunctionReturn(0);
3833 }
3834 
3835 /*@
3836    TSSolve - Steps the requested number of timesteps.
3837 
3838    Collective on TS
3839 
3840    Input Parameter:
3841 +  ts - the TS context obtained from TSCreate()
3842 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
3843                              otherwise must contain the initial conditions and will contain the solution at the final requested time
3844 
3845    Level: beginner
3846 
3847    Notes:
3848    The final time returned by this function may be different from the time of the internally
3849    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3850    stepped over the final time.
3851 
3852 .keywords: TS, timestep, solve
3853 
3854 .seealso: TSCreate(), TSSetSolution(), TSStep(), TSGetTime(), TSGetSolveTime()
3855 @*/
3856 PetscErrorCode TSSolve(TS ts,Vec u)
3857 {
3858   Vec               solution;
3859   PetscErrorCode    ierr;
3860 
3861   PetscFunctionBegin;
3862   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3863   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3864 
3865   if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && u) {   /* Need ts->vec_sol to be distinct so it is not overwritten when we interpolate at the end */
3866     if (!ts->vec_sol || u == ts->vec_sol) {
3867       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
3868       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
3869       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
3870     }
3871     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
3872     if (ts->forward_solve) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3873   } else if (u) {
3874     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
3875   }
3876   ierr = TSSetUp(ts);CHKERRQ(ierr);
3877   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
3878 
3879   if (ts->max_time >= PETSC_MAX_REAL && ts->max_steps == PETSC_MAX_INT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>");
3880   if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSSolve()");
3881   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP && !ts->adapt) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE");
3882 
3883   if (ts->forward_solve) {
3884     ierr = TSForwardSetUp(ts);CHKERRQ(ierr);
3885   }
3886 
3887   /* reset number of steps only when the step is not restarted. ARKIMEX
3888      restarts the step after an event. Resetting these counters in such case causes
3889      TSTrajectory to incorrectly save the output files
3890   */
3891   /* reset time step and iteration counters */
3892   if (!ts->steps) {
3893     ts->ksp_its           = 0;
3894     ts->snes_its          = 0;
3895     ts->num_snes_failures = 0;
3896     ts->reject            = 0;
3897     ts->steprestart       = PETSC_TRUE;
3898     ts->steprollback      = PETSC_FALSE;
3899   }
3900   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP && ts->ptime + ts->time_step > ts->max_time) ts->time_step = ts->max_time - ts->ptime;
3901   ts->reason = TS_CONVERGED_ITERATING;
3902 
3903   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
3904 
3905   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
3906     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
3907     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
3908     ts->solvetime = ts->ptime;
3909     solution = ts->vec_sol;
3910   } else { /* Step the requested number of timesteps. */
3911     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3912     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3913 
3914     if (!ts->steps) {
3915       ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3916       ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3917     }
3918 
3919     while (!ts->reason) {
3920       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3921       if (!ts->steprollback) {
3922         ierr = TSPreStep(ts);CHKERRQ(ierr);
3923       }
3924       ierr = TSStep(ts);CHKERRQ(ierr);
3925       if (ts->testjacobian) {
3926         ierr = TSRHSJacobianTest(ts,NULL);CHKERRQ(ierr);
3927       }
3928       if (ts->testjacobiantranspose) {
3929         ierr = TSRHSJacobianTestTranspose(ts,NULL);CHKERRQ(ierr);
3930       }
3931       if (ts->vec_costintegral && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
3932         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
3933       }
3934       if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
3935         ierr = TSForwardStep(ts);CHKERRQ(ierr);
3936       }
3937       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
3938       ierr = TSEventHandler(ts);CHKERRQ(ierr); /* The right-hand side may be changed due to event. Be careful with Any computation using the RHS information after this point. */
3939       if (ts->steprollback) {
3940         ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
3941       }
3942       if (!ts->steprollback) {
3943         ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3944         ierr = TSPostStep(ts);CHKERRQ(ierr);
3945       }
3946     }
3947     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3948 
3949     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
3950       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
3951       ts->solvetime = ts->max_time;
3952       solution = u;
3953       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
3954     } else {
3955       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
3956       ts->solvetime = ts->ptime;
3957       solution = ts->vec_sol;
3958     }
3959   }
3960 
3961   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
3962   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
3963   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
3964   if (ts->adjoint_solve) {
3965     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
3966   }
3967   PetscFunctionReturn(0);
3968 }
3969 
3970 /*@C
3971    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
3972 
3973    Collective on TS
3974 
3975    Input Parameters:
3976 +  ts - time stepping context obtained from TSCreate()
3977 .  step - step number that has just completed
3978 .  ptime - model time of the state
3979 -  u - state at the current model time
3980 
3981    Notes:
3982    TSMonitor() is typically used automatically within the time stepping implementations.
3983    Users would almost never call this routine directly.
3984 
3985    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
3986 
3987    Level: developer
3988 
3989 .keywords: TS, timestep
3990 @*/
3991 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
3992 {
3993   DM             dm;
3994   PetscInt       i,n = ts->numbermonitors;
3995   PetscErrorCode ierr;
3996 
3997   PetscFunctionBegin;
3998   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3999   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4000 
4001   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4002   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
4003 
4004   ierr = VecLockPush(u);CHKERRQ(ierr);
4005   for (i=0; i<n; i++) {
4006     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
4007   }
4008   ierr = VecLockPop(u);CHKERRQ(ierr);
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /* ------------------------------------------------------------------------*/
4013 /*@C
4014    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
4015    TS to monitor the solution process graphically in various ways
4016 
4017    Collective on TS
4018 
4019    Input Parameters:
4020 +  host - the X display to open, or null for the local machine
4021 .  label - the title to put in the title bar
4022 .  x, y - the screen coordinates of the upper left coordinate of the window
4023 .  m, n - the screen width and height in pixels
4024 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
4025 
4026    Output Parameter:
4027 .  ctx - the context
4028 
4029    Options Database Key:
4030 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
4031 +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
4032 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
4033 .  -ts_monitor_lg_error -  monitor the error
4034 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
4035 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
4036 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
4037 
4038    Notes:
4039    Use TSMonitorLGCtxDestroy() to destroy.
4040 
4041    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
4042 
4043    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
4044    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
4045    as the first argument.
4046 
4047    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
4048 
4049    Level: intermediate
4050 
4051 .keywords: TS, monitor, line graph, residual
4052 
4053 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
4054            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
4055            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
4056            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
4057            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
4058 
4059 @*/
4060 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
4061 {
4062   PetscDraw      draw;
4063   PetscErrorCode ierr;
4064 
4065   PetscFunctionBegin;
4066   ierr = PetscNew(ctx);CHKERRQ(ierr);
4067   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4068   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4069   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
4070   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
4071   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4072   (*ctx)->howoften = howoften;
4073   PetscFunctionReturn(0);
4074 }
4075 
4076 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
4077 {
4078   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4079   PetscReal      x   = ptime,y;
4080   PetscErrorCode ierr;
4081 
4082   PetscFunctionBegin;
4083   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4084   if (!step) {
4085     PetscDrawAxis axis;
4086     const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
4087     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4088     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time",ylabel);CHKERRQ(ierr);
4089     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4090   }
4091   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4092   if (ctx->semilogy) y = PetscLog10Real(y);
4093   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4094   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4095     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4096     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4097   }
4098   PetscFunctionReturn(0);
4099 }
4100 
4101 /*@C
4102    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4103    with TSMonitorLGCtxCreate().
4104 
4105    Collective on TSMonitorLGCtx
4106 
4107    Input Parameter:
4108 .  ctx - the monitor context
4109 
4110    Level: intermediate
4111 
4112 .keywords: TS, monitor, line graph, destroy
4113 
4114 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4115 @*/
4116 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4117 {
4118   PetscErrorCode ierr;
4119 
4120   PetscFunctionBegin;
4121   if ((*ctx)->transformdestroy) {
4122     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4123   }
4124   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4125   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4126   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4127   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4128   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4129   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4130   PetscFunctionReturn(0);
4131 }
4132 
4133 /*@
4134    TSGetTime - Gets the time of the most recently completed step.
4135 
4136    Not Collective
4137 
4138    Input Parameter:
4139 .  ts - the TS context obtained from TSCreate()
4140 
4141    Output Parameter:
4142 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
4143 
4144    Level: beginner
4145 
4146    Note:
4147    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4148    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4149 
4150 .seealso:  TSGetSolveTime(), TSSetTime(), TSGetTimeStep()
4151 
4152 .keywords: TS, get, time
4153 @*/
4154 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4155 {
4156   PetscFunctionBegin;
4157   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4158   PetscValidRealPointer(t,2);
4159   *t = ts->ptime;
4160   PetscFunctionReturn(0);
4161 }
4162 
4163 /*@
4164    TSGetPrevTime - Gets the starting time of the previously completed step.
4165 
4166    Not Collective
4167 
4168    Input Parameter:
4169 .  ts - the TS context obtained from TSCreate()
4170 
4171    Output Parameter:
4172 .  t  - the previous time
4173 
4174    Level: beginner
4175 
4176 .seealso: TSGetTime(), TSGetSolveTime(), TSGetTimeStep()
4177 
4178 .keywords: TS, get, time
4179 @*/
4180 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4181 {
4182   PetscFunctionBegin;
4183   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4184   PetscValidRealPointer(t,2);
4185   *t = ts->ptime_prev;
4186   PetscFunctionReturn(0);
4187 }
4188 
4189 /*@
4190    TSSetTime - Allows one to reset the time.
4191 
4192    Logically Collective on TS
4193 
4194    Input Parameters:
4195 +  ts - the TS context obtained from TSCreate()
4196 -  time - the time
4197 
4198    Level: intermediate
4199 
4200 .seealso: TSGetTime(), TSSetMaxSteps()
4201 
4202 .keywords: TS, set, time
4203 @*/
4204 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4205 {
4206   PetscFunctionBegin;
4207   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4208   PetscValidLogicalCollectiveReal(ts,t,2);
4209   ts->ptime = t;
4210   PetscFunctionReturn(0);
4211 }
4212 
4213 /*@C
4214    TSSetOptionsPrefix - Sets the prefix used for searching for all
4215    TS options in the database.
4216 
4217    Logically Collective on TS
4218 
4219    Input Parameter:
4220 +  ts     - The TS context
4221 -  prefix - The prefix to prepend to all option names
4222 
4223    Notes:
4224    A hyphen (-) must NOT be given at the beginning of the prefix name.
4225    The first character of all runtime options is AUTOMATICALLY the
4226    hyphen.
4227 
4228    Level: advanced
4229 
4230 .keywords: TS, set, options, prefix, database
4231 
4232 .seealso: TSSetFromOptions()
4233 
4234 @*/
4235 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4236 {
4237   PetscErrorCode ierr;
4238   SNES           snes;
4239 
4240   PetscFunctionBegin;
4241   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4242   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4243   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4244   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4245   PetscFunctionReturn(0);
4246 }
4247 
4248 /*@C
4249    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4250    TS options in the database.
4251 
4252    Logically Collective on TS
4253 
4254    Input Parameter:
4255 +  ts     - The TS context
4256 -  prefix - The prefix to prepend to all option names
4257 
4258    Notes:
4259    A hyphen (-) must NOT be given at the beginning of the prefix name.
4260    The first character of all runtime options is AUTOMATICALLY the
4261    hyphen.
4262 
4263    Level: advanced
4264 
4265 .keywords: TS, append, options, prefix, database
4266 
4267 .seealso: TSGetOptionsPrefix()
4268 
4269 @*/
4270 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4271 {
4272   PetscErrorCode ierr;
4273   SNES           snes;
4274 
4275   PetscFunctionBegin;
4276   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4277   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4278   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4279   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4280   PetscFunctionReturn(0);
4281 }
4282 
4283 /*@C
4284    TSGetOptionsPrefix - Sets the prefix used for searching for all
4285    TS options in the database.
4286 
4287    Not Collective
4288 
4289    Input Parameter:
4290 .  ts - The TS context
4291 
4292    Output Parameter:
4293 .  prefix - A pointer to the prefix string used
4294 
4295    Notes:
4296     On the fortran side, the user should pass in a string 'prifix' of
4297    sufficient length to hold the prefix.
4298 
4299    Level: intermediate
4300 
4301 .keywords: TS, get, options, prefix, database
4302 
4303 .seealso: TSAppendOptionsPrefix()
4304 @*/
4305 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4306 {
4307   PetscErrorCode ierr;
4308 
4309   PetscFunctionBegin;
4310   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4311   PetscValidPointer(prefix,2);
4312   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4313   PetscFunctionReturn(0);
4314 }
4315 
4316 /*@C
4317    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4318 
4319    Not Collective, but parallel objects are returned if TS is parallel
4320 
4321    Input Parameter:
4322 .  ts  - The TS context obtained from TSCreate()
4323 
4324    Output Parameters:
4325 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4326 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4327 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4328 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4329 
4330    Notes:
4331     You can pass in NULL for any return argument you do not need.
4332 
4333    Level: intermediate
4334 
4335 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4336 
4337 .keywords: TS, timestep, get, matrix, Jacobian
4338 @*/
4339 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4340 {
4341   PetscErrorCode ierr;
4342   DM             dm;
4343 
4344   PetscFunctionBegin;
4345   if (Amat || Pmat) {
4346     SNES snes;
4347     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4348     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4349     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4350   }
4351   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4352   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4353   PetscFunctionReturn(0);
4354 }
4355 
4356 /*@C
4357    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4358 
4359    Not Collective, but parallel objects are returned if TS is parallel
4360 
4361    Input Parameter:
4362 .  ts  - The TS context obtained from TSCreate()
4363 
4364    Output Parameters:
4365 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4366 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4367 .  f   - The function to compute the matrices
4368 - ctx - User-defined context for Jacobian evaluation routine
4369 
4370    Notes:
4371     You can pass in NULL for any return argument you do not need.
4372 
4373    Level: advanced
4374 
4375 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4376 
4377 .keywords: TS, timestep, get, matrix, Jacobian
4378 @*/
4379 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4380 {
4381   PetscErrorCode ierr;
4382   DM             dm;
4383 
4384   PetscFunctionBegin;
4385   if (Amat || Pmat) {
4386     SNES snes;
4387     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4388     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4389     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4390   }
4391   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4392   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4393   PetscFunctionReturn(0);
4394 }
4395 
4396 /*@C
4397    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4398    VecView() for the solution at each timestep
4399 
4400    Collective on TS
4401 
4402    Input Parameters:
4403 +  ts - the TS context
4404 .  step - current time-step
4405 .  ptime - current time
4406 -  dummy - either a viewer or NULL
4407 
4408    Options Database:
4409 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4410 
4411    Notes:
4412     the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
4413        will look bad
4414 
4415    Level: intermediate
4416 
4417 .keywords: TS,  vector, monitor, view
4418 
4419 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4420 @*/
4421 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4422 {
4423   PetscErrorCode   ierr;
4424   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4425   PetscDraw        draw;
4426 
4427   PetscFunctionBegin;
4428   if (!step && ictx->showinitial) {
4429     if (!ictx->initialsolution) {
4430       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
4431     }
4432     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
4433   }
4434   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4435 
4436   if (ictx->showinitial) {
4437     PetscReal pause;
4438     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
4439     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
4440     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
4441     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
4442     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
4443   }
4444   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
4445   if (ictx->showtimestepandtime) {
4446     PetscReal xl,yl,xr,yr,h;
4447     char      time[32];
4448 
4449     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4450     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4451     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4452     h    = yl + .95*(yr - yl);
4453     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4454     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4455   }
4456 
4457   if (ictx->showinitial) {
4458     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
4459   }
4460   PetscFunctionReturn(0);
4461 }
4462 
4463 /*@C
4464    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
4465 
4466    Collective on TS
4467 
4468    Input Parameters:
4469 +  ts - the TS context
4470 .  step - current time-step
4471 .  ptime - current time
4472 -  dummy - either a viewer or NULL
4473 
4474    Level: intermediate
4475 
4476 .keywords: TS,  vector, monitor, view
4477 
4478 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4479 @*/
4480 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4481 {
4482   PetscErrorCode    ierr;
4483   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
4484   PetscDraw         draw;
4485   PetscDrawAxis     axis;
4486   PetscInt          n;
4487   PetscMPIInt       size;
4488   PetscReal         U0,U1,xl,yl,xr,yr,h;
4489   char              time[32];
4490   const PetscScalar *U;
4491 
4492   PetscFunctionBegin;
4493   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
4494   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
4495   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
4496   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
4497 
4498   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4499   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
4500   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
4501   if (!step) {
4502     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
4503     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
4504   }
4505 
4506   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
4507   U0 = PetscRealPart(U[0]);
4508   U1 = PetscRealPart(U[1]);
4509   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
4510   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
4511 
4512   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4513   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
4514   if (ictx->showtimestepandtime) {
4515     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4516     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4517     h    = yl + .95*(yr - yl);
4518     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4519   }
4520   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
4521   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4522   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
4523   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
4524   PetscFunctionReturn(0);
4525 }
4526 
4527 /*@C
4528    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
4529 
4530    Collective on TS
4531 
4532    Input Parameters:
4533 .    ctx - the monitor context
4534 
4535    Level: intermediate
4536 
4537 .keywords: TS,  vector, monitor, view
4538 
4539 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
4540 @*/
4541 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
4542 {
4543   PetscErrorCode ierr;
4544 
4545   PetscFunctionBegin;
4546   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
4547   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
4548   ierr = PetscFree(*ictx);CHKERRQ(ierr);
4549   PetscFunctionReturn(0);
4550 }
4551 
4552 /*@C
4553    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
4554 
4555    Collective on TS
4556 
4557    Input Parameter:
4558 .    ts - time-step context
4559 
4560    Output Patameter:
4561 .    ctx - the monitor context
4562 
4563    Options Database:
4564 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4565 
4566    Level: intermediate
4567 
4568 .keywords: TS,  vector, monitor, view
4569 
4570 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
4571 @*/
4572 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
4573 {
4574   PetscErrorCode   ierr;
4575 
4576   PetscFunctionBegin;
4577   ierr = PetscNew(ctx);CHKERRQ(ierr);
4578   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
4579   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
4580 
4581   (*ctx)->howoften    = howoften;
4582   (*ctx)->showinitial = PETSC_FALSE;
4583   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
4584 
4585   (*ctx)->showtimestepandtime = PETSC_FALSE;
4586   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
4587   PetscFunctionReturn(0);
4588 }
4589 
4590 /*@C
4591    TSMonitorDrawSolutionFunction - Monitors progress of the TS solvers by calling
4592    VecView() for the solution provided by TSSetSolutionFunction() at each timestep
4593 
4594    Collective on TS
4595 
4596    Input Parameters:
4597 +  ts - the TS context
4598 .  step - current time-step
4599 .  ptime - current time
4600 -  dummy - either a viewer or NULL
4601 
4602    Options Database:
4603 .  -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4604 
4605    Level: intermediate
4606 
4607 .keywords: TS,  vector, monitor, view
4608 
4609 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4610 @*/
4611 PetscErrorCode  TSMonitorDrawSolutionFunction(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4612 {
4613   PetscErrorCode   ierr;
4614   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4615   PetscViewer      viewer = ctx->viewer;
4616   Vec              work;
4617 
4618   PetscFunctionBegin;
4619   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4620   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4621   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4622   ierr = VecView(work,viewer);CHKERRQ(ierr);
4623   ierr = VecDestroy(&work);CHKERRQ(ierr);
4624   PetscFunctionReturn(0);
4625 }
4626 
4627 /*@C
4628    TSMonitorDrawError - Monitors progress of the TS solvers by calling
4629    VecView() for the error at each timestep
4630 
4631    Collective on TS
4632 
4633    Input Parameters:
4634 +  ts - the TS context
4635 .  step - current time-step
4636 .  ptime - current time
4637 -  dummy - either a viewer or NULL
4638 
4639    Options Database:
4640 .  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4641 
4642    Level: intermediate
4643 
4644 .keywords: TS,  vector, monitor, view
4645 
4646 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4647 @*/
4648 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4649 {
4650   PetscErrorCode   ierr;
4651   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4652   PetscViewer      viewer = ctx->viewer;
4653   Vec              work;
4654 
4655   PetscFunctionBegin;
4656   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4657   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4658   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4659   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
4660   ierr = VecView(work,viewer);CHKERRQ(ierr);
4661   ierr = VecDestroy(&work);CHKERRQ(ierr);
4662   PetscFunctionReturn(0);
4663 }
4664 
4665 #include <petsc/private/dmimpl.h>
4666 /*@
4667    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
4668 
4669    Logically Collective on TS and DM
4670 
4671    Input Parameters:
4672 +  ts - the ODE integrator object
4673 -  dm - the dm, cannot be NULL
4674 
4675    Level: intermediate
4676 
4677 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
4678 @*/
4679 PetscErrorCode  TSSetDM(TS ts,DM dm)
4680 {
4681   PetscErrorCode ierr;
4682   SNES           snes;
4683   DMTS           tsdm;
4684 
4685   PetscFunctionBegin;
4686   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4687   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
4688   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
4689   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
4690     if (ts->dm->dmts && !dm->dmts) {
4691       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
4692       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
4693       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
4694         tsdm->originaldm = dm;
4695       }
4696     }
4697     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
4698   }
4699   ts->dm = dm;
4700 
4701   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4702   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
4703   PetscFunctionReturn(0);
4704 }
4705 
4706 /*@
4707    TSGetDM - Gets the DM that may be used by some preconditioners
4708 
4709    Not Collective
4710 
4711    Input Parameter:
4712 . ts - the preconditioner context
4713 
4714    Output Parameter:
4715 .  dm - the dm
4716 
4717    Level: intermediate
4718 
4719 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
4720 @*/
4721 PetscErrorCode  TSGetDM(TS ts,DM *dm)
4722 {
4723   PetscErrorCode ierr;
4724 
4725   PetscFunctionBegin;
4726   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4727   if (!ts->dm) {
4728     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
4729     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
4730   }
4731   *dm = ts->dm;
4732   PetscFunctionReturn(0);
4733 }
4734 
4735 /*@
4736    SNESTSFormFunction - Function to evaluate nonlinear residual
4737 
4738    Logically Collective on SNES
4739 
4740    Input Parameter:
4741 + snes - nonlinear solver
4742 . U - the current state at which to evaluate the residual
4743 - ctx - user context, must be a TS
4744 
4745    Output Parameter:
4746 . F - the nonlinear residual
4747 
4748    Notes:
4749    This function is not normally called by users and is automatically registered with the SNES used by TS.
4750    It is most frequently passed to MatFDColoringSetFunction().
4751 
4752    Level: advanced
4753 
4754 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
4755 @*/
4756 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
4757 {
4758   TS             ts = (TS)ctx;
4759   PetscErrorCode ierr;
4760 
4761   PetscFunctionBegin;
4762   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4763   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4764   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
4765   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
4766   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
4767   PetscFunctionReturn(0);
4768 }
4769 
4770 /*@
4771    SNESTSFormJacobian - Function to evaluate the Jacobian
4772 
4773    Collective on SNES
4774 
4775    Input Parameter:
4776 + snes - nonlinear solver
4777 . U - the current state at which to evaluate the residual
4778 - ctx - user context, must be a TS
4779 
4780    Output Parameter:
4781 + A - the Jacobian
4782 . B - the preconditioning matrix (may be the same as A)
4783 - flag - indicates any structure change in the matrix
4784 
4785    Notes:
4786    This function is not normally called by users and is automatically registered with the SNES used by TS.
4787 
4788    Level: developer
4789 
4790 .seealso: SNESSetJacobian()
4791 @*/
4792 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
4793 {
4794   TS             ts = (TS)ctx;
4795   PetscErrorCode ierr;
4796 
4797   PetscFunctionBegin;
4798   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4799   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4800   PetscValidPointer(A,3);
4801   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
4802   PetscValidPointer(B,4);
4803   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
4804   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
4805   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
4806   PetscFunctionReturn(0);
4807 }
4808 
4809 /*@C
4810    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
4811 
4812    Collective on TS
4813 
4814    Input Arguments:
4815 +  ts - time stepping context
4816 .  t - time at which to evaluate
4817 .  U - state at which to evaluate
4818 -  ctx - context
4819 
4820    Output Arguments:
4821 .  F - right hand side
4822 
4823    Level: intermediate
4824 
4825    Notes:
4826    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
4827    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
4828 
4829 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
4830 @*/
4831 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
4832 {
4833   PetscErrorCode ierr;
4834   Mat            Arhs,Brhs;
4835 
4836   PetscFunctionBegin;
4837   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
4838   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
4839   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
4840   PetscFunctionReturn(0);
4841 }
4842 
4843 /*@C
4844    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4845 
4846    Collective on TS
4847 
4848    Input Arguments:
4849 +  ts - time stepping context
4850 .  t - time at which to evaluate
4851 .  U - state at which to evaluate
4852 -  ctx - context
4853 
4854    Output Arguments:
4855 +  A - pointer to operator
4856 .  B - pointer to preconditioning matrix
4857 -  flg - matrix structure flag
4858 
4859    Level: intermediate
4860 
4861    Notes:
4862    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
4863 
4864 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
4865 @*/
4866 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
4867 {
4868   PetscFunctionBegin;
4869   PetscFunctionReturn(0);
4870 }
4871 
4872 /*@C
4873    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4874 
4875    Collective on TS
4876 
4877    Input Arguments:
4878 +  ts - time stepping context
4879 .  t - time at which to evaluate
4880 .  U - state at which to evaluate
4881 .  Udot - time derivative of state vector
4882 -  ctx - context
4883 
4884    Output Arguments:
4885 .  F - left hand side
4886 
4887    Level: intermediate
4888 
4889    Notes:
4890    The assumption here is that the left hand side is of the form A*Udot (and not A*Udot + B*U). For other cases, the
4891    user is required to write their own TSComputeIFunction.
4892    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4893    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4894 
4895    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
4896 
4897 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
4898 @*/
4899 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
4900 {
4901   PetscErrorCode ierr;
4902   Mat            A,B;
4903 
4904   PetscFunctionBegin;
4905   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
4906   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
4907   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
4908   PetscFunctionReturn(0);
4909 }
4910 
4911 /*@C
4912    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4913 
4914    Collective on TS
4915 
4916    Input Arguments:
4917 +  ts - time stepping context
4918 .  t - time at which to evaluate
4919 .  U - state at which to evaluate
4920 .  Udot - time derivative of state vector
4921 .  shift - shift to apply
4922 -  ctx - context
4923 
4924    Output Arguments:
4925 +  A - pointer to operator
4926 .  B - pointer to preconditioning matrix
4927 -  flg - matrix structure flag
4928 
4929    Level: advanced
4930 
4931    Notes:
4932    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4933 
4934    It is only appropriate for problems of the form
4935 
4936 $     M Udot = F(U,t)
4937 
4938   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4939   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4940   an implicit operator of the form
4941 
4942 $    shift*M + J
4943 
4944   where J is the Jacobian of -F(U).  Support may be added in a future version of PETSc, but for now, the user must store
4945   a copy of M or reassemble it when requested.
4946 
4947 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
4948 @*/
4949 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
4950 {
4951   PetscErrorCode ierr;
4952 
4953   PetscFunctionBegin;
4954   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
4955   ts->ijacobian.shift = shift;
4956   PetscFunctionReturn(0);
4957 }
4958 
4959 /*@
4960    TSGetEquationType - Gets the type of the equation that TS is solving.
4961 
4962    Not Collective
4963 
4964    Input Parameter:
4965 .  ts - the TS context
4966 
4967    Output Parameter:
4968 .  equation_type - see TSEquationType
4969 
4970    Level: beginner
4971 
4972 .keywords: TS, equation type
4973 
4974 .seealso: TSSetEquationType(), TSEquationType
4975 @*/
4976 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
4977 {
4978   PetscFunctionBegin;
4979   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4980   PetscValidPointer(equation_type,2);
4981   *equation_type = ts->equation_type;
4982   PetscFunctionReturn(0);
4983 }
4984 
4985 /*@
4986    TSSetEquationType - Sets the type of the equation that TS is solving.
4987 
4988    Not Collective
4989 
4990    Input Parameter:
4991 +  ts - the TS context
4992 -  equation_type - see TSEquationType
4993 
4994    Level: advanced
4995 
4996 .keywords: TS, equation type
4997 
4998 .seealso: TSGetEquationType(), TSEquationType
4999 @*/
5000 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
5001 {
5002   PetscFunctionBegin;
5003   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5004   ts->equation_type = equation_type;
5005   PetscFunctionReturn(0);
5006 }
5007 
5008 /*@
5009    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
5010 
5011    Not Collective
5012 
5013    Input Parameter:
5014 .  ts - the TS context
5015 
5016    Output Parameter:
5017 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5018             manual pages for the individual convergence tests for complete lists
5019 
5020    Level: beginner
5021 
5022    Notes:
5023    Can only be called after the call to TSSolve() is complete.
5024 
5025 .keywords: TS, nonlinear, set, convergence, test
5026 
5027 .seealso: TSSetConvergenceTest(), TSConvergedReason
5028 @*/
5029 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
5030 {
5031   PetscFunctionBegin;
5032   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5033   PetscValidPointer(reason,2);
5034   *reason = ts->reason;
5035   PetscFunctionReturn(0);
5036 }
5037 
5038 /*@
5039    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
5040 
5041    Not Collective
5042 
5043    Input Parameter:
5044 +  ts - the TS context
5045 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5046             manual pages for the individual convergence tests for complete lists
5047 
5048    Level: advanced
5049 
5050    Notes:
5051    Can only be called during TSSolve() is active.
5052 
5053 .keywords: TS, nonlinear, set, convergence, test
5054 
5055 .seealso: TSConvergedReason
5056 @*/
5057 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
5058 {
5059   PetscFunctionBegin;
5060   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5061   ts->reason = reason;
5062   PetscFunctionReturn(0);
5063 }
5064 
5065 /*@
5066    TSGetSolveTime - Gets the time after a call to TSSolve()
5067 
5068    Not Collective
5069 
5070    Input Parameter:
5071 .  ts - the TS context
5072 
5073    Output Parameter:
5074 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
5075 
5076    Level: beginner
5077 
5078    Notes:
5079    Can only be called after the call to TSSolve() is complete.
5080 
5081 .keywords: TS, nonlinear, set, convergence, test
5082 
5083 .seealso: TSSetConvergenceTest(), TSConvergedReason
5084 @*/
5085 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5086 {
5087   PetscFunctionBegin;
5088   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5089   PetscValidPointer(ftime,2);
5090   *ftime = ts->solvetime;
5091   PetscFunctionReturn(0);
5092 }
5093 
5094 /*@
5095    TSGetSNESIterations - Gets the total number of nonlinear iterations
5096    used by the time integrator.
5097 
5098    Not Collective
5099 
5100    Input Parameter:
5101 .  ts - TS context
5102 
5103    Output Parameter:
5104 .  nits - number of nonlinear iterations
5105 
5106    Notes:
5107    This counter is reset to zero for each successive call to TSSolve().
5108 
5109    Level: intermediate
5110 
5111 .keywords: TS, get, number, nonlinear, iterations
5112 
5113 .seealso:  TSGetKSPIterations()
5114 @*/
5115 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5116 {
5117   PetscFunctionBegin;
5118   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5119   PetscValidIntPointer(nits,2);
5120   *nits = ts->snes_its;
5121   PetscFunctionReturn(0);
5122 }
5123 
5124 /*@
5125    TSGetKSPIterations - Gets the total number of linear iterations
5126    used by the time integrator.
5127 
5128    Not Collective
5129 
5130    Input Parameter:
5131 .  ts - TS context
5132 
5133    Output Parameter:
5134 .  lits - number of linear iterations
5135 
5136    Notes:
5137    This counter is reset to zero for each successive call to TSSolve().
5138 
5139    Level: intermediate
5140 
5141 .keywords: TS, get, number, linear, iterations
5142 
5143 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5144 @*/
5145 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5146 {
5147   PetscFunctionBegin;
5148   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5149   PetscValidIntPointer(lits,2);
5150   *lits = ts->ksp_its;
5151   PetscFunctionReturn(0);
5152 }
5153 
5154 /*@
5155    TSGetStepRejections - Gets the total number of rejected steps.
5156 
5157    Not Collective
5158 
5159    Input Parameter:
5160 .  ts - TS context
5161 
5162    Output Parameter:
5163 .  rejects - number of steps rejected
5164 
5165    Notes:
5166    This counter is reset to zero for each successive call to TSSolve().
5167 
5168    Level: intermediate
5169 
5170 .keywords: TS, get, number
5171 
5172 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5173 @*/
5174 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5175 {
5176   PetscFunctionBegin;
5177   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5178   PetscValidIntPointer(rejects,2);
5179   *rejects = ts->reject;
5180   PetscFunctionReturn(0);
5181 }
5182 
5183 /*@
5184    TSGetSNESFailures - Gets the total number of failed SNES solves
5185 
5186    Not Collective
5187 
5188    Input Parameter:
5189 .  ts - TS context
5190 
5191    Output Parameter:
5192 .  fails - number of failed nonlinear solves
5193 
5194    Notes:
5195    This counter is reset to zero for each successive call to TSSolve().
5196 
5197    Level: intermediate
5198 
5199 .keywords: TS, get, number
5200 
5201 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5202 @*/
5203 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5204 {
5205   PetscFunctionBegin;
5206   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5207   PetscValidIntPointer(fails,2);
5208   *fails = ts->num_snes_failures;
5209   PetscFunctionReturn(0);
5210 }
5211 
5212 /*@
5213    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5214 
5215    Not Collective
5216 
5217    Input Parameter:
5218 +  ts - TS context
5219 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5220 
5221    Notes:
5222    The counter is reset to zero for each step
5223 
5224    Options Database Key:
5225  .  -ts_max_reject - Maximum number of step rejections before a step fails
5226 
5227    Level: intermediate
5228 
5229 .keywords: TS, set, maximum, number
5230 
5231 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5232 @*/
5233 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5234 {
5235   PetscFunctionBegin;
5236   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5237   ts->max_reject = rejects;
5238   PetscFunctionReturn(0);
5239 }
5240 
5241 /*@
5242    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5243 
5244    Not Collective
5245 
5246    Input Parameter:
5247 +  ts - TS context
5248 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5249 
5250    Notes:
5251    The counter is reset to zero for each successive call to TSSolve().
5252 
5253    Options Database Key:
5254  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5255 
5256    Level: intermediate
5257 
5258 .keywords: TS, set, maximum, number
5259 
5260 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5261 @*/
5262 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5263 {
5264   PetscFunctionBegin;
5265   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5266   ts->max_snes_failures = fails;
5267   PetscFunctionReturn(0);
5268 }
5269 
5270 /*@
5271    TSSetErrorIfStepFails - Error if no step succeeds
5272 
5273    Not Collective
5274 
5275    Input Parameter:
5276 +  ts - TS context
5277 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5278 
5279    Options Database Key:
5280  .  -ts_error_if_step_fails - Error if no step succeeds
5281 
5282    Level: intermediate
5283 
5284 .keywords: TS, set, error
5285 
5286 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5287 @*/
5288 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5289 {
5290   PetscFunctionBegin;
5291   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5292   ts->errorifstepfailed = err;
5293   PetscFunctionReturn(0);
5294 }
5295 
5296 /*@C
5297    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
5298 
5299    Collective on TS
5300 
5301    Input Parameters:
5302 +  ts - the TS context
5303 .  step - current time-step
5304 .  ptime - current time
5305 .  u - current state
5306 -  vf - viewer and its format
5307 
5308    Level: intermediate
5309 
5310 .keywords: TS,  vector, monitor, view
5311 
5312 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5313 @*/
5314 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5315 {
5316   PetscErrorCode ierr;
5317 
5318   PetscFunctionBegin;
5319   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5320   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5321   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5322   PetscFunctionReturn(0);
5323 }
5324 
5325 /*@C
5326    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5327 
5328    Collective on TS
5329 
5330    Input Parameters:
5331 +  ts - the TS context
5332 .  step - current time-step
5333 .  ptime - current time
5334 .  u - current state
5335 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5336 
5337    Level: intermediate
5338 
5339    Notes:
5340    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.
5341    These are named according to the file name template.
5342 
5343    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5344 
5345 .keywords: TS,  vector, monitor, view
5346 
5347 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5348 @*/
5349 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5350 {
5351   PetscErrorCode ierr;
5352   char           filename[PETSC_MAX_PATH_LEN];
5353   PetscViewer    viewer;
5354 
5355   PetscFunctionBegin;
5356   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5357   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5358   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5359   ierr = VecView(u,viewer);CHKERRQ(ierr);
5360   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5361   PetscFunctionReturn(0);
5362 }
5363 
5364 /*@C
5365    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
5366 
5367    Collective on TS
5368 
5369    Input Parameters:
5370 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5371 
5372    Level: intermediate
5373 
5374    Note:
5375    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
5376 
5377 .keywords: TS,  vector, monitor, view
5378 
5379 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
5380 @*/
5381 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
5382 {
5383   PetscErrorCode ierr;
5384 
5385   PetscFunctionBegin;
5386   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
5387   PetscFunctionReturn(0);
5388 }
5389 
5390 /*@
5391    TSGetAdapt - Get the adaptive controller context for the current method
5392 
5393    Collective on TS if controller has not been created yet
5394 
5395    Input Arguments:
5396 .  ts - time stepping context
5397 
5398    Output Arguments:
5399 .  adapt - adaptive controller
5400 
5401    Level: intermediate
5402 
5403 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
5404 @*/
5405 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
5406 {
5407   PetscErrorCode ierr;
5408 
5409   PetscFunctionBegin;
5410   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5411   PetscValidPointer(adapt,2);
5412   if (!ts->adapt) {
5413     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
5414     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
5415     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
5416   }
5417   *adapt = ts->adapt;
5418   PetscFunctionReturn(0);
5419 }
5420 
5421 /*@
5422    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
5423 
5424    Logically Collective
5425 
5426    Input Arguments:
5427 +  ts - time integration context
5428 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
5429 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
5430 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
5431 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
5432 
5433    Options Database keys:
5434 +  -ts_rtol <rtol> - relative tolerance for local truncation error
5435 -  -ts_atol <atol> Absolute tolerance for local truncation error
5436 
5437    Notes:
5438    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5439    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5440    computed only for the differential or the algebraic part then this can be done using the vector of
5441    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5442    differential part and infinity for the algebraic part, the LTE calculation will include only the
5443    differential variables.
5444 
5445    Level: beginner
5446 
5447 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
5448 @*/
5449 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
5450 {
5451   PetscErrorCode ierr;
5452 
5453   PetscFunctionBegin;
5454   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
5455   if (vatol) {
5456     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
5457     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
5458     ts->vatol = vatol;
5459   }
5460   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
5461   if (vrtol) {
5462     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
5463     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
5464     ts->vrtol = vrtol;
5465   }
5466   PetscFunctionReturn(0);
5467 }
5468 
5469 /*@
5470    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5471 
5472    Logically Collective
5473 
5474    Input Arguments:
5475 .  ts - time integration context
5476 
5477    Output Arguments:
5478 +  atol - scalar absolute tolerances, NULL to ignore
5479 .  vatol - vector of absolute tolerances, NULL to ignore
5480 .  rtol - scalar relative tolerances, NULL to ignore
5481 -  vrtol - vector of relative tolerances, NULL to ignore
5482 
5483    Level: beginner
5484 
5485 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
5486 @*/
5487 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
5488 {
5489   PetscFunctionBegin;
5490   if (atol)  *atol  = ts->atol;
5491   if (vatol) *vatol = ts->vatol;
5492   if (rtol)  *rtol  = ts->rtol;
5493   if (vrtol) *vrtol = ts->vrtol;
5494   PetscFunctionReturn(0);
5495 }
5496 
5497 /*@
5498    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
5499 
5500    Collective on TS
5501 
5502    Input Arguments:
5503 +  ts - time stepping context
5504 .  U - state vector, usually ts->vec_sol
5505 -  Y - state vector to be compared to U
5506 
5507    Output Arguments:
5508 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5509 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5510 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5511 
5512    Level: developer
5513 
5514 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
5515 @*/
5516 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5517 {
5518   PetscErrorCode    ierr;
5519   PetscInt          i,n,N,rstart;
5520   PetscInt          n_loc,na_loc,nr_loc;
5521   PetscReal         n_glb,na_glb,nr_glb;
5522   const PetscScalar *u,*y;
5523   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
5524   PetscReal         tol,tola,tolr;
5525   PetscReal         err_loc[6],err_glb[6];
5526 
5527   PetscFunctionBegin;
5528   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5529   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5530   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5531   PetscValidType(U,2);
5532   PetscValidType(Y,3);
5533   PetscCheckSameComm(U,2,Y,3);
5534   PetscValidPointer(norm,4);
5535   PetscValidPointer(norma,5);
5536   PetscValidPointer(normr,6);
5537   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5538 
5539   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5540   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5541   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5542   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5543   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5544   sum  = 0.; n_loc  = 0;
5545   suma = 0.; na_loc = 0;
5546   sumr = 0.; nr_loc = 0;
5547   if (ts->vatol && ts->vrtol) {
5548     const PetscScalar *atol,*rtol;
5549     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5550     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5551     for (i=0; i<n; i++) {
5552       diff = PetscAbsScalar(y[i] - u[i]);
5553       tola = PetscRealPart(atol[i]);
5554       if(tola>0.){
5555         suma  += PetscSqr(diff/tola);
5556         na_loc++;
5557       }
5558       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5559       if(tolr>0.){
5560         sumr  += PetscSqr(diff/tolr);
5561         nr_loc++;
5562       }
5563       tol=tola+tolr;
5564       if(tol>0.){
5565         sum  += PetscSqr(diff/tol);
5566         n_loc++;
5567       }
5568     }
5569     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5570     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5571   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5572     const PetscScalar *atol;
5573     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5574     for (i=0; i<n; i++) {
5575       diff = PetscAbsScalar(y[i] - u[i]);
5576       tola = PetscRealPart(atol[i]);
5577       if(tola>0.){
5578         suma  += PetscSqr(diff/tola);
5579         na_loc++;
5580       }
5581       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5582       if(tolr>0.){
5583         sumr  += PetscSqr(diff/tolr);
5584         nr_loc++;
5585       }
5586       tol=tola+tolr;
5587       if(tol>0.){
5588         sum  += PetscSqr(diff/tol);
5589         n_loc++;
5590       }
5591     }
5592     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5593   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5594     const PetscScalar *rtol;
5595     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5596     for (i=0; i<n; i++) {
5597       diff = PetscAbsScalar(y[i] - u[i]);
5598       tola = ts->atol;
5599       if(tola>0.){
5600         suma  += PetscSqr(diff/tola);
5601         na_loc++;
5602       }
5603       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5604       if(tolr>0.){
5605         sumr  += PetscSqr(diff/tolr);
5606         nr_loc++;
5607       }
5608       tol=tola+tolr;
5609       if(tol>0.){
5610         sum  += PetscSqr(diff/tol);
5611         n_loc++;
5612       }
5613     }
5614     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5615   } else {                      /* scalar atol, scalar rtol */
5616     for (i=0; i<n; i++) {
5617       diff = PetscAbsScalar(y[i] - u[i]);
5618      tola = ts->atol;
5619       if(tola>0.){
5620         suma  += PetscSqr(diff/tola);
5621         na_loc++;
5622       }
5623       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5624       if(tolr>0.){
5625         sumr  += PetscSqr(diff/tolr);
5626         nr_loc++;
5627       }
5628       tol=tola+tolr;
5629       if(tol>0.){
5630         sum  += PetscSqr(diff/tol);
5631         n_loc++;
5632       }
5633     }
5634   }
5635   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5636   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5637 
5638   err_loc[0] = sum;
5639   err_loc[1] = suma;
5640   err_loc[2] = sumr;
5641   err_loc[3] = (PetscReal)n_loc;
5642   err_loc[4] = (PetscReal)na_loc;
5643   err_loc[5] = (PetscReal)nr_loc;
5644 
5645   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5646 
5647   gsum   = err_glb[0];
5648   gsuma  = err_glb[1];
5649   gsumr  = err_glb[2];
5650   n_glb  = err_glb[3];
5651   na_glb = err_glb[4];
5652   nr_glb = err_glb[5];
5653 
5654   *norm  = 0.;
5655   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
5656   *norma = 0.;
5657   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
5658   *normr = 0.;
5659   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
5660 
5661   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5662   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5663   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5664   PetscFunctionReturn(0);
5665 }
5666 
5667 /*@
5668    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
5669 
5670    Collective on TS
5671 
5672    Input Arguments:
5673 +  ts - time stepping context
5674 .  U - state vector, usually ts->vec_sol
5675 -  Y - state vector to be compared to U
5676 
5677    Output Arguments:
5678 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5679 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5680 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5681 
5682    Level: developer
5683 
5684 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
5685 @*/
5686 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5687 {
5688   PetscErrorCode    ierr;
5689   PetscInt          i,n,N,rstart;
5690   const PetscScalar *u,*y;
5691   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
5692   PetscReal         tol,tola,tolr,diff;
5693   PetscReal         err_loc[3],err_glb[3];
5694 
5695   PetscFunctionBegin;
5696   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5697   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5698   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5699   PetscValidType(U,2);
5700   PetscValidType(Y,3);
5701   PetscCheckSameComm(U,2,Y,3);
5702   PetscValidPointer(norm,4);
5703   PetscValidPointer(norma,5);
5704   PetscValidPointer(normr,6);
5705   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5706 
5707   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5708   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5709   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5710   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5711   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5712 
5713   max=0.;
5714   maxa=0.;
5715   maxr=0.;
5716 
5717   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
5718     const PetscScalar *atol,*rtol;
5719     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5720     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5721 
5722     for (i=0; i<n; i++) {
5723       diff = PetscAbsScalar(y[i] - u[i]);
5724       tola = PetscRealPart(atol[i]);
5725       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5726       tol  = tola+tolr;
5727       if(tola>0.){
5728         maxa = PetscMax(maxa,diff / tola);
5729       }
5730       if(tolr>0.){
5731         maxr = PetscMax(maxr,diff / tolr);
5732       }
5733       if(tol>0.){
5734         max = PetscMax(max,diff / tol);
5735       }
5736     }
5737     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5738     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5739   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5740     const PetscScalar *atol;
5741     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5742     for (i=0; i<n; i++) {
5743       diff = PetscAbsScalar(y[i] - u[i]);
5744       tola = PetscRealPart(atol[i]);
5745       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5746       tol  = tola+tolr;
5747       if(tola>0.){
5748         maxa = PetscMax(maxa,diff / tola);
5749       }
5750       if(tolr>0.){
5751         maxr = PetscMax(maxr,diff / tolr);
5752       }
5753       if(tol>0.){
5754         max = PetscMax(max,diff / tol);
5755       }
5756     }
5757     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5758   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5759     const PetscScalar *rtol;
5760     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5761 
5762     for (i=0; i<n; i++) {
5763       diff = PetscAbsScalar(y[i] - u[i]);
5764       tola = ts->atol;
5765       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5766       tol  = tola+tolr;
5767       if(tola>0.){
5768         maxa = PetscMax(maxa,diff / tola);
5769       }
5770       if(tolr>0.){
5771         maxr = PetscMax(maxr,diff / tolr);
5772       }
5773       if(tol>0.){
5774         max = PetscMax(max,diff / tol);
5775       }
5776     }
5777     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5778   } else {                      /* scalar atol, scalar rtol */
5779 
5780     for (i=0; i<n; i++) {
5781       diff = PetscAbsScalar(y[i] - u[i]);
5782       tola = ts->atol;
5783       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5784       tol  = tola+tolr;
5785       if(tola>0.){
5786         maxa = PetscMax(maxa,diff / tola);
5787       }
5788       if(tolr>0.){
5789         maxr = PetscMax(maxr,diff / tolr);
5790       }
5791       if(tol>0.){
5792         max = PetscMax(max,diff / tol);
5793       }
5794     }
5795   }
5796   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5797   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5798   err_loc[0] = max;
5799   err_loc[1] = maxa;
5800   err_loc[2] = maxr;
5801   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5802   gmax   = err_glb[0];
5803   gmaxa  = err_glb[1];
5804   gmaxr  = err_glb[2];
5805 
5806   *norm = gmax;
5807   *norma = gmaxa;
5808   *normr = gmaxr;
5809   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5810     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5811     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5812   PetscFunctionReturn(0);
5813 }
5814 
5815 /*@
5816    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5817 
5818    Collective on TS
5819 
5820    Input Arguments:
5821 +  ts - time stepping context
5822 .  U - state vector, usually ts->vec_sol
5823 .  Y - state vector to be compared to U
5824 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5825 
5826    Output Arguments:
5827 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5828 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5829 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5830 
5831    Options Database Keys:
5832 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5833 
5834    Level: developer
5835 
5836 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
5837 @*/
5838 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5839 {
5840   PetscErrorCode ierr;
5841 
5842   PetscFunctionBegin;
5843   if (wnormtype == NORM_2) {
5844     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
5845   } else if(wnormtype == NORM_INFINITY) {
5846     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
5847   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
5848   PetscFunctionReturn(0);
5849 }
5850 
5851 
5852 /*@
5853    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
5854 
5855    Collective on TS
5856 
5857    Input Arguments:
5858 +  ts - time stepping context
5859 .  E - error vector
5860 .  U - state vector, usually ts->vec_sol
5861 -  Y - state vector, previous time step
5862 
5863    Output Arguments:
5864 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5865 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5866 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5867 
5868    Level: developer
5869 
5870 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
5871 @*/
5872 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5873 {
5874   PetscErrorCode    ierr;
5875   PetscInt          i,n,N,rstart;
5876   PetscInt          n_loc,na_loc,nr_loc;
5877   PetscReal         n_glb,na_glb,nr_glb;
5878   const PetscScalar *e,*u,*y;
5879   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
5880   PetscReal         tol,tola,tolr;
5881   PetscReal         err_loc[6],err_glb[6];
5882 
5883   PetscFunctionBegin;
5884   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5885   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
5886   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
5887   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
5888   PetscValidType(E,2);
5889   PetscValidType(U,3);
5890   PetscValidType(Y,4);
5891   PetscCheckSameComm(E,2,U,3);
5892   PetscCheckSameComm(U,2,Y,3);
5893   PetscValidPointer(norm,5);
5894   PetscValidPointer(norma,6);
5895   PetscValidPointer(normr,7);
5896 
5897   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
5898   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
5899   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
5900   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
5901   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5902   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5903   sum  = 0.; n_loc  = 0;
5904   suma = 0.; na_loc = 0;
5905   sumr = 0.; nr_loc = 0;
5906   if (ts->vatol && ts->vrtol) {
5907     const PetscScalar *atol,*rtol;
5908     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5909     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5910     for (i=0; i<n; i++) {
5911       err = PetscAbsScalar(e[i]);
5912       tola = PetscRealPart(atol[i]);
5913       if(tola>0.){
5914         suma  += PetscSqr(err/tola);
5915         na_loc++;
5916       }
5917       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5918       if(tolr>0.){
5919         sumr  += PetscSqr(err/tolr);
5920         nr_loc++;
5921       }
5922       tol=tola+tolr;
5923       if(tol>0.){
5924         sum  += PetscSqr(err/tol);
5925         n_loc++;
5926       }
5927     }
5928     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5929     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5930   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5931     const PetscScalar *atol;
5932     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5933     for (i=0; i<n; i++) {
5934       err = PetscAbsScalar(e[i]);
5935       tola = PetscRealPart(atol[i]);
5936       if(tola>0.){
5937         suma  += PetscSqr(err/tola);
5938         na_loc++;
5939       }
5940       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5941       if(tolr>0.){
5942         sumr  += PetscSqr(err/tolr);
5943         nr_loc++;
5944       }
5945       tol=tola+tolr;
5946       if(tol>0.){
5947         sum  += PetscSqr(err/tol);
5948         n_loc++;
5949       }
5950     }
5951     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5952   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5953     const PetscScalar *rtol;
5954     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5955     for (i=0; i<n; i++) {
5956       err = PetscAbsScalar(e[i]);
5957       tola = ts->atol;
5958       if(tola>0.){
5959         suma  += PetscSqr(err/tola);
5960         na_loc++;
5961       }
5962       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5963       if(tolr>0.){
5964         sumr  += PetscSqr(err/tolr);
5965         nr_loc++;
5966       }
5967       tol=tola+tolr;
5968       if(tol>0.){
5969         sum  += PetscSqr(err/tol);
5970         n_loc++;
5971       }
5972     }
5973     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5974   } else {                      /* scalar atol, scalar rtol */
5975     for (i=0; i<n; i++) {
5976       err = PetscAbsScalar(e[i]);
5977      tola = ts->atol;
5978       if(tola>0.){
5979         suma  += PetscSqr(err/tola);
5980         na_loc++;
5981       }
5982       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5983       if(tolr>0.){
5984         sumr  += PetscSqr(err/tolr);
5985         nr_loc++;
5986       }
5987       tol=tola+tolr;
5988       if(tol>0.){
5989         sum  += PetscSqr(err/tol);
5990         n_loc++;
5991       }
5992     }
5993   }
5994   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
5995   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5996   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5997 
5998   err_loc[0] = sum;
5999   err_loc[1] = suma;
6000   err_loc[2] = sumr;
6001   err_loc[3] = (PetscReal)n_loc;
6002   err_loc[4] = (PetscReal)na_loc;
6003   err_loc[5] = (PetscReal)nr_loc;
6004 
6005   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6006 
6007   gsum   = err_glb[0];
6008   gsuma  = err_glb[1];
6009   gsumr  = err_glb[2];
6010   n_glb  = err_glb[3];
6011   na_glb = err_glb[4];
6012   nr_glb = err_glb[5];
6013 
6014   *norm  = 0.;
6015   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6016   *norma = 0.;
6017   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6018   *normr = 0.;
6019   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6020 
6021   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6022   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6023   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6024   PetscFunctionReturn(0);
6025 }
6026 
6027 /*@
6028    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
6029    Collective on TS
6030 
6031    Input Arguments:
6032 +  ts - time stepping context
6033 .  E - error vector
6034 .  U - state vector, usually ts->vec_sol
6035 -  Y - state vector, previous time step
6036 
6037    Output Arguments:
6038 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6039 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6040 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6041 
6042    Level: developer
6043 
6044 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
6045 @*/
6046 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6047 {
6048   PetscErrorCode    ierr;
6049   PetscInt          i,n,N,rstart;
6050   const PetscScalar *e,*u,*y;
6051   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
6052   PetscReal         tol,tola,tolr;
6053   PetscReal         err_loc[3],err_glb[3];
6054 
6055   PetscFunctionBegin;
6056   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6057   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6058   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6059   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6060   PetscValidType(E,2);
6061   PetscValidType(U,3);
6062   PetscValidType(Y,4);
6063   PetscCheckSameComm(E,2,U,3);
6064   PetscCheckSameComm(U,2,Y,3);
6065   PetscValidPointer(norm,5);
6066   PetscValidPointer(norma,6);
6067   PetscValidPointer(normr,7);
6068 
6069   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6070   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6071   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6072   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6073   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6074   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6075 
6076   max=0.;
6077   maxa=0.;
6078   maxr=0.;
6079 
6080   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6081     const PetscScalar *atol,*rtol;
6082     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6083     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6084 
6085     for (i=0; i<n; i++) {
6086       err = PetscAbsScalar(e[i]);
6087       tola = PetscRealPart(atol[i]);
6088       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6089       tol  = tola+tolr;
6090       if(tola>0.){
6091         maxa = PetscMax(maxa,err / tola);
6092       }
6093       if(tolr>0.){
6094         maxr = PetscMax(maxr,err / tolr);
6095       }
6096       if(tol>0.){
6097         max = PetscMax(max,err / tol);
6098       }
6099     }
6100     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6101     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6102   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6103     const PetscScalar *atol;
6104     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6105     for (i=0; i<n; i++) {
6106       err = PetscAbsScalar(e[i]);
6107       tola = PetscRealPart(atol[i]);
6108       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6109       tol  = tola+tolr;
6110       if(tola>0.){
6111         maxa = PetscMax(maxa,err / tola);
6112       }
6113       if(tolr>0.){
6114         maxr = PetscMax(maxr,err / tolr);
6115       }
6116       if(tol>0.){
6117         max = PetscMax(max,err / tol);
6118       }
6119     }
6120     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6121   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6122     const PetscScalar *rtol;
6123     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6124 
6125     for (i=0; i<n; i++) {
6126       err = PetscAbsScalar(e[i]);
6127       tola = ts->atol;
6128       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6129       tol  = tola+tolr;
6130       if(tola>0.){
6131         maxa = PetscMax(maxa,err / tola);
6132       }
6133       if(tolr>0.){
6134         maxr = PetscMax(maxr,err / tolr);
6135       }
6136       if(tol>0.){
6137         max = PetscMax(max,err / tol);
6138       }
6139     }
6140     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6141   } else {                      /* scalar atol, scalar rtol */
6142 
6143     for (i=0; i<n; i++) {
6144       err = PetscAbsScalar(e[i]);
6145       tola = ts->atol;
6146       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6147       tol  = tola+tolr;
6148       if(tola>0.){
6149         maxa = PetscMax(maxa,err / tola);
6150       }
6151       if(tolr>0.){
6152         maxr = PetscMax(maxr,err / tolr);
6153       }
6154       if(tol>0.){
6155         max = PetscMax(max,err / tol);
6156       }
6157     }
6158   }
6159   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6160   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6161   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6162   err_loc[0] = max;
6163   err_loc[1] = maxa;
6164   err_loc[2] = maxr;
6165   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6166   gmax   = err_glb[0];
6167   gmaxa  = err_glb[1];
6168   gmaxr  = err_glb[2];
6169 
6170   *norm = gmax;
6171   *norma = gmaxa;
6172   *normr = gmaxr;
6173   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6174     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6175     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6176   PetscFunctionReturn(0);
6177 }
6178 
6179 /*@
6180    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6181 
6182    Collective on TS
6183 
6184    Input Arguments:
6185 +  ts - time stepping context
6186 .  E - error vector
6187 .  U - state vector, usually ts->vec_sol
6188 .  Y - state vector, previous time step
6189 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6190 
6191    Output Arguments:
6192 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6193 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6194 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6195 
6196    Options Database Keys:
6197 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6198 
6199    Level: developer
6200 
6201 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6202 @*/
6203 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6204 {
6205   PetscErrorCode ierr;
6206 
6207   PetscFunctionBegin;
6208   if (wnormtype == NORM_2) {
6209     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6210   } else if(wnormtype == NORM_INFINITY) {
6211     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6212   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6213   PetscFunctionReturn(0);
6214 }
6215 
6216 
6217 /*@
6218    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6219 
6220    Logically Collective on TS
6221 
6222    Input Arguments:
6223 +  ts - time stepping context
6224 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6225 
6226    Note:
6227    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6228 
6229    Level: intermediate
6230 
6231 .seealso: TSGetCFLTime(), TSADAPTCFL
6232 @*/
6233 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6234 {
6235   PetscFunctionBegin;
6236   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6237   ts->cfltime_local = cfltime;
6238   ts->cfltime       = -1.;
6239   PetscFunctionReturn(0);
6240 }
6241 
6242 /*@
6243    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6244 
6245    Collective on TS
6246 
6247    Input Arguments:
6248 .  ts - time stepping context
6249 
6250    Output Arguments:
6251 .  cfltime - maximum stable time step for forward Euler
6252 
6253    Level: advanced
6254 
6255 .seealso: TSSetCFLTimeLocal()
6256 @*/
6257 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6258 {
6259   PetscErrorCode ierr;
6260 
6261   PetscFunctionBegin;
6262   if (ts->cfltime < 0) {
6263     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6264   }
6265   *cfltime = ts->cfltime;
6266   PetscFunctionReturn(0);
6267 }
6268 
6269 /*@
6270    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6271 
6272    Input Parameters:
6273 .  ts   - the TS context.
6274 .  xl   - lower bound.
6275 .  xu   - upper bound.
6276 
6277    Notes:
6278    If this routine is not called then the lower and upper bounds are set to
6279    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6280 
6281    Level: advanced
6282 
6283 @*/
6284 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6285 {
6286   PetscErrorCode ierr;
6287   SNES           snes;
6288 
6289   PetscFunctionBegin;
6290   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6291   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6292   PetscFunctionReturn(0);
6293 }
6294 
6295 #if defined(PETSC_HAVE_MATLAB_ENGINE)
6296 #include <mex.h>
6297 
6298 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
6299 
6300 /*
6301    TSComputeFunction_Matlab - Calls the function that has been set with
6302                          TSSetFunctionMatlab().
6303 
6304    Collective on TS
6305 
6306    Input Parameters:
6307 +  snes - the TS context
6308 -  u - input vector
6309 
6310    Output Parameter:
6311 .  y - function vector, as set by TSSetFunction()
6312 
6313    Notes:
6314    TSComputeFunction() is typically used within nonlinear solvers
6315    implementations, so most users would not generally call this routine
6316    themselves.
6317 
6318    Level: developer
6319 
6320 .keywords: TS, nonlinear, compute, function
6321 
6322 .seealso: TSSetFunction(), TSGetFunction()
6323 */
6324 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
6325 {
6326   PetscErrorCode  ierr;
6327   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6328   int             nlhs  = 1,nrhs = 7;
6329   mxArray         *plhs[1],*prhs[7];
6330   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
6331 
6332   PetscFunctionBegin;
6333   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
6334   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6335   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
6336   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
6337   PetscCheckSameComm(snes,1,u,3);
6338   PetscCheckSameComm(snes,1,y,5);
6339 
6340   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
6341   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6342   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
6343   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
6344 
6345   prhs[0] =  mxCreateDoubleScalar((double)ls);
6346   prhs[1] =  mxCreateDoubleScalar(time);
6347   prhs[2] =  mxCreateDoubleScalar((double)lx);
6348   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6349   prhs[4] =  mxCreateDoubleScalar((double)ly);
6350   prhs[5] =  mxCreateString(sctx->funcname);
6351   prhs[6] =  sctx->ctx;
6352   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
6353   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6354   mxDestroyArray(prhs[0]);
6355   mxDestroyArray(prhs[1]);
6356   mxDestroyArray(prhs[2]);
6357   mxDestroyArray(prhs[3]);
6358   mxDestroyArray(prhs[4]);
6359   mxDestroyArray(prhs[5]);
6360   mxDestroyArray(plhs[0]);
6361   PetscFunctionReturn(0);
6362 }
6363 
6364 /*
6365    TSSetFunctionMatlab - Sets the function evaluation routine and function
6366    vector for use by the TS routines in solving ODEs
6367    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
6368 
6369    Logically Collective on TS
6370 
6371    Input Parameters:
6372 +  ts - the TS context
6373 -  func - function evaluation routine
6374 
6375    Calling sequence of func:
6376 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
6377 
6378    Level: beginner
6379 
6380 .keywords: TS, nonlinear, set, function
6381 
6382 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6383 */
6384 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
6385 {
6386   PetscErrorCode  ierr;
6387   TSMatlabContext *sctx;
6388 
6389   PetscFunctionBegin;
6390   /* currently sctx is memory bleed */
6391   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6392   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6393   /*
6394      This should work, but it doesn't
6395   sctx->ctx = ctx;
6396   mexMakeArrayPersistent(sctx->ctx);
6397   */
6398   sctx->ctx = mxDuplicateArray(ctx);
6399 
6400   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
6401   PetscFunctionReturn(0);
6402 }
6403 
6404 /*
6405    TSComputeJacobian_Matlab - Calls the function that has been set with
6406                          TSSetJacobianMatlab().
6407 
6408    Collective on TS
6409 
6410    Input Parameters:
6411 +  ts - the TS context
6412 .  u - input vector
6413 .  A, B - the matrices
6414 -  ctx - user context
6415 
6416    Level: developer
6417 
6418 .keywords: TS, nonlinear, compute, function
6419 
6420 .seealso: TSSetFunction(), TSGetFunction()
6421 @*/
6422 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
6423 {
6424   PetscErrorCode  ierr;
6425   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6426   int             nlhs  = 2,nrhs = 9;
6427   mxArray         *plhs[2],*prhs[9];
6428   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
6429 
6430   PetscFunctionBegin;
6431   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6432   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6433 
6434   /* call Matlab function in ctx with arguments u and y */
6435 
6436   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6437   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6438   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
6439   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
6440   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
6441 
6442   prhs[0] =  mxCreateDoubleScalar((double)ls);
6443   prhs[1] =  mxCreateDoubleScalar((double)time);
6444   prhs[2] =  mxCreateDoubleScalar((double)lx);
6445   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6446   prhs[4] =  mxCreateDoubleScalar((double)shift);
6447   prhs[5] =  mxCreateDoubleScalar((double)lA);
6448   prhs[6] =  mxCreateDoubleScalar((double)lB);
6449   prhs[7] =  mxCreateString(sctx->funcname);
6450   prhs[8] =  sctx->ctx;
6451   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
6452   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6453   mxDestroyArray(prhs[0]);
6454   mxDestroyArray(prhs[1]);
6455   mxDestroyArray(prhs[2]);
6456   mxDestroyArray(prhs[3]);
6457   mxDestroyArray(prhs[4]);
6458   mxDestroyArray(prhs[5]);
6459   mxDestroyArray(prhs[6]);
6460   mxDestroyArray(prhs[7]);
6461   mxDestroyArray(plhs[0]);
6462   mxDestroyArray(plhs[1]);
6463   PetscFunctionReturn(0);
6464 }
6465 
6466 /*
6467    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
6468    vector for use by the TS routines in solving ODEs from MATLAB. Here the function is a string containing the name of a MATLAB function
6469 
6470    Logically Collective on TS
6471 
6472    Input Parameters:
6473 +  ts - the TS context
6474 .  A,B - Jacobian matrices
6475 .  func - function evaluation routine
6476 -  ctx - user context
6477 
6478    Calling sequence of func:
6479 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
6480 
6481    Level: developer
6482 
6483 .keywords: TS, nonlinear, set, function
6484 
6485 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6486 */
6487 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
6488 {
6489   PetscErrorCode  ierr;
6490   TSMatlabContext *sctx;
6491 
6492   PetscFunctionBegin;
6493   /* currently sctx is memory bleed */
6494   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6495   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6496   /*
6497      This should work, but it doesn't
6498   sctx->ctx = ctx;
6499   mexMakeArrayPersistent(sctx->ctx);
6500   */
6501   sctx->ctx = mxDuplicateArray(ctx);
6502 
6503   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
6504   PetscFunctionReturn(0);
6505 }
6506 
6507 /*
6508    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
6509 
6510    Collective on TS
6511 
6512 .seealso: TSSetFunction(), TSGetFunction()
6513 @*/
6514 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
6515 {
6516   PetscErrorCode  ierr;
6517   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6518   int             nlhs  = 1,nrhs = 6;
6519   mxArray         *plhs[1],*prhs[6];
6520   long long int   lx = 0,ls = 0;
6521 
6522   PetscFunctionBegin;
6523   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6524   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
6525 
6526   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6527   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6528 
6529   prhs[0] =  mxCreateDoubleScalar((double)ls);
6530   prhs[1] =  mxCreateDoubleScalar((double)it);
6531   prhs[2] =  mxCreateDoubleScalar((double)time);
6532   prhs[3] =  mxCreateDoubleScalar((double)lx);
6533   prhs[4] =  mxCreateString(sctx->funcname);
6534   prhs[5] =  sctx->ctx;
6535   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
6536   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6537   mxDestroyArray(prhs[0]);
6538   mxDestroyArray(prhs[1]);
6539   mxDestroyArray(prhs[2]);
6540   mxDestroyArray(prhs[3]);
6541   mxDestroyArray(prhs[4]);
6542   mxDestroyArray(plhs[0]);
6543   PetscFunctionReturn(0);
6544 }
6545 
6546 /*
6547    TSMonitorSetMatlab - Sets the monitor function from Matlab
6548 
6549    Level: developer
6550 
6551 .keywords: TS, nonlinear, set, function
6552 
6553 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6554 */
6555 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
6556 {
6557   PetscErrorCode  ierr;
6558   TSMatlabContext *sctx;
6559 
6560   PetscFunctionBegin;
6561   /* currently sctx is memory bleed */
6562   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6563   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6564   /*
6565      This should work, but it doesn't
6566   sctx->ctx = ctx;
6567   mexMakeArrayPersistent(sctx->ctx);
6568   */
6569   sctx->ctx = mxDuplicateArray(ctx);
6570 
6571   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
6572   PetscFunctionReturn(0);
6573 }
6574 #endif
6575 
6576 /*@C
6577    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
6578        in a time based line graph
6579 
6580    Collective on TS
6581 
6582    Input Parameters:
6583 +  ts - the TS context
6584 .  step - current time-step
6585 .  ptime - current time
6586 .  u - current solution
6587 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
6588 
6589    Options Database:
6590 .   -ts_monitor_lg_solution_variables
6591 
6592    Level: intermediate
6593 
6594    Notes:
6595     Each process in a parallel run displays its component solutions in a separate window
6596 
6597 .keywords: TS,  vector, monitor, view
6598 
6599 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
6600            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
6601            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
6602            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
6603 @*/
6604 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
6605 {
6606   PetscErrorCode    ierr;
6607   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
6608   const PetscScalar *yy;
6609   Vec               v;
6610 
6611   PetscFunctionBegin;
6612   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
6613   if (!step) {
6614     PetscDrawAxis axis;
6615     PetscInt      dim;
6616     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6617     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
6618     if (!ctx->names) {
6619       PetscBool flg;
6620       /* user provides names of variables to plot but no names has been set so assume names are integer values */
6621       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
6622       if (flg) {
6623         PetscInt i,n;
6624         char     **names;
6625         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
6626         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
6627         for (i=0; i<n; i++) {
6628           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
6629           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
6630         }
6631         names[n] = NULL;
6632         ctx->names = names;
6633       }
6634     }
6635     if (ctx->names && !ctx->displaynames) {
6636       char      **displaynames;
6637       PetscBool flg;
6638       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6639       ierr = PetscMalloc1(dim+1,&displaynames);CHKERRQ(ierr);
6640       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
6641       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
6642       if (flg) {
6643         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
6644       }
6645       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
6646     }
6647     if (ctx->displaynames) {
6648       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
6649       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
6650     } else if (ctx->names) {
6651       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6652       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6653       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
6654     } else {
6655       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6656       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6657     }
6658     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6659   }
6660 
6661   if (!ctx->transform) v = u;
6662   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
6663   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
6664   if (ctx->displaynames) {
6665     PetscInt i;
6666     for (i=0; i<ctx->ndisplayvariables; i++)
6667       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
6668     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
6669   } else {
6670 #if defined(PETSC_USE_COMPLEX)
6671     PetscInt  i,n;
6672     PetscReal *yreal;
6673     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
6674     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6675     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6676     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6677     ierr = PetscFree(yreal);CHKERRQ(ierr);
6678 #else
6679     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6680 #endif
6681   }
6682   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
6683   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
6684 
6685   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6686     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6687     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6688   }
6689   PetscFunctionReturn(0);
6690 }
6691 
6692 /*@C
6693    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6694 
6695    Collective on TS
6696 
6697    Input Parameters:
6698 +  ts - the TS context
6699 -  names - the names of the components, final string must be NULL
6700 
6701    Level: intermediate
6702 
6703    Notes:
6704     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6705 
6706 .keywords: TS,  vector, monitor, view
6707 
6708 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
6709 @*/
6710 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
6711 {
6712   PetscErrorCode    ierr;
6713   PetscInt          i;
6714 
6715   PetscFunctionBegin;
6716   for (i=0; i<ts->numbermonitors; i++) {
6717     if (ts->monitor[i] == TSMonitorLGSolution) {
6718       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
6719       break;
6720     }
6721   }
6722   PetscFunctionReturn(0);
6723 }
6724 
6725 /*@C
6726    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6727 
6728    Collective on TS
6729 
6730    Input Parameters:
6731 +  ts - the TS context
6732 -  names - the names of the components, final string must be NULL
6733 
6734    Level: intermediate
6735 
6736 .keywords: TS,  vector, monitor, view
6737 
6738 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
6739 @*/
6740 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
6741 {
6742   PetscErrorCode    ierr;
6743 
6744   PetscFunctionBegin;
6745   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
6746   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
6747   PetscFunctionReturn(0);
6748 }
6749 
6750 /*@C
6751    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
6752 
6753    Collective on TS
6754 
6755    Input Parameter:
6756 .  ts - the TS context
6757 
6758    Output Parameter:
6759 .  names - the names of the components, final string must be NULL
6760 
6761    Level: intermediate
6762 
6763    Notes:
6764     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6765 
6766 .keywords: TS,  vector, monitor, view
6767 
6768 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
6769 @*/
6770 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
6771 {
6772   PetscInt       i;
6773 
6774   PetscFunctionBegin;
6775   *names = NULL;
6776   for (i=0; i<ts->numbermonitors; i++) {
6777     if (ts->monitor[i] == TSMonitorLGSolution) {
6778       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
6779       *names = (const char *const *)ctx->names;
6780       break;
6781     }
6782   }
6783   PetscFunctionReturn(0);
6784 }
6785 
6786 /*@C
6787    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
6788 
6789    Collective on TS
6790 
6791    Input Parameters:
6792 +  ctx - the TSMonitorLG context
6793 .  displaynames - the names of the components, final string must be NULL
6794 
6795    Level: intermediate
6796 
6797 .keywords: TS,  vector, monitor, view
6798 
6799 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6800 @*/
6801 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
6802 {
6803   PetscInt          j = 0,k;
6804   PetscErrorCode    ierr;
6805 
6806   PetscFunctionBegin;
6807   if (!ctx->names) PetscFunctionReturn(0);
6808   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
6809   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
6810   while (displaynames[j]) j++;
6811   ctx->ndisplayvariables = j;
6812   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
6813   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
6814   j = 0;
6815   while (displaynames[j]) {
6816     k = 0;
6817     while (ctx->names[k]) {
6818       PetscBool flg;
6819       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
6820       if (flg) {
6821         ctx->displayvariables[j] = k;
6822         break;
6823       }
6824       k++;
6825     }
6826     j++;
6827   }
6828   PetscFunctionReturn(0);
6829 }
6830 
6831 /*@C
6832    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
6833 
6834    Collective on TS
6835 
6836    Input Parameters:
6837 +  ts - the TS context
6838 .  displaynames - the names of the components, final string must be NULL
6839 
6840    Notes:
6841     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6842 
6843    Level: intermediate
6844 
6845 .keywords: TS,  vector, monitor, view
6846 
6847 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6848 @*/
6849 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
6850 {
6851   PetscInt          i;
6852   PetscErrorCode    ierr;
6853 
6854   PetscFunctionBegin;
6855   for (i=0; i<ts->numbermonitors; i++) {
6856     if (ts->monitor[i] == TSMonitorLGSolution) {
6857       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
6858       break;
6859     }
6860   }
6861   PetscFunctionReturn(0);
6862 }
6863 
6864 /*@C
6865    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
6866 
6867    Collective on TS
6868 
6869    Input Parameters:
6870 +  ts - the TS context
6871 .  transform - the transform function
6872 .  destroy - function to destroy the optional context
6873 -  ctx - optional context used by transform function
6874 
6875    Notes:
6876     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6877 
6878    Level: intermediate
6879 
6880 .keywords: TS,  vector, monitor, view
6881 
6882 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
6883 @*/
6884 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6885 {
6886   PetscInt          i;
6887   PetscErrorCode    ierr;
6888 
6889   PetscFunctionBegin;
6890   for (i=0; i<ts->numbermonitors; i++) {
6891     if (ts->monitor[i] == TSMonitorLGSolution) {
6892       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
6893     }
6894   }
6895   PetscFunctionReturn(0);
6896 }
6897 
6898 /*@C
6899    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
6900 
6901    Collective on TSLGCtx
6902 
6903    Input Parameters:
6904 +  ts - the TS context
6905 .  transform - the transform function
6906 .  destroy - function to destroy the optional context
6907 -  ctx - optional context used by transform function
6908 
6909    Level: intermediate
6910 
6911 .keywords: TS,  vector, monitor, view
6912 
6913 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
6914 @*/
6915 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6916 {
6917   PetscFunctionBegin;
6918   ctx->transform    = transform;
6919   ctx->transformdestroy = destroy;
6920   ctx->transformctx = tctx;
6921   PetscFunctionReturn(0);
6922 }
6923 
6924 /*@C
6925    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the error
6926        in a time based line graph
6927 
6928    Collective on TS
6929 
6930    Input Parameters:
6931 +  ts - the TS context
6932 .  step - current time-step
6933 .  ptime - current time
6934 .  u - current solution
6935 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
6936 
6937    Level: intermediate
6938 
6939    Notes:
6940     Each process in a parallel run displays its component errors in a separate window
6941 
6942    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
6943 
6944    Options Database Keys:
6945 .  -ts_monitor_lg_error - create a graphical monitor of error history
6946 
6947 .keywords: TS,  vector, monitor, view
6948 
6949 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
6950 @*/
6951 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
6952 {
6953   PetscErrorCode    ierr;
6954   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
6955   const PetscScalar *yy;
6956   Vec               y;
6957 
6958   PetscFunctionBegin;
6959   if (!step) {
6960     PetscDrawAxis axis;
6961     PetscInt      dim;
6962     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6963     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Error");CHKERRQ(ierr);
6964     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6965     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6966     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6967   }
6968   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
6969   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
6970   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
6971   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
6972 #if defined(PETSC_USE_COMPLEX)
6973   {
6974     PetscReal *yreal;
6975     PetscInt  i,n;
6976     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
6977     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6978     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6979     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6980     ierr = PetscFree(yreal);CHKERRQ(ierr);
6981   }
6982 #else
6983   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6984 #endif
6985   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
6986   ierr = VecDestroy(&y);CHKERRQ(ierr);
6987   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6988     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6989     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6990   }
6991   PetscFunctionReturn(0);
6992 }
6993 
6994 /*@C
6995    TSMonitorError - Monitors progress of the TS solvers by printing the 2 norm of the error at each timestep
6996 
6997    Collective on TS
6998 
6999    Input Parameters:
7000 +  ts - the TS context
7001 .  step - current time-step
7002 .  ptime - current time
7003 .  u - current solution
7004 -  dctx - unused context
7005 
7006    Level: intermediate
7007 
7008    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
7009 
7010    Options Database Keys:
7011 .  -ts_monitor_error - create a graphical monitor of error history
7012 
7013 .keywords: TS,  vector, monitor, view
7014 
7015 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
7016 @*/
7017 PetscErrorCode  TSMonitorError(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
7018 {
7019   PetscErrorCode    ierr;
7020   Vec               y;
7021   PetscReal         nrm;
7022   PetscBool         flg;
7023 
7024   PetscFunctionBegin;
7025   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
7026   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
7027   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
7028   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERASCII,&flg);CHKERRQ(ierr);
7029   if (flg) {
7030     ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr);
7031     ierr = PetscViewerASCIIPrintf(vf->viewer,"2-norm of error %g\n",(double)nrm);CHKERRQ(ierr);
7032   }
7033   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERDRAW,&flg);CHKERRQ(ierr);
7034   if (flg) {
7035     ierr = VecView(y,vf->viewer);CHKERRQ(ierr);
7036   }
7037   ierr = VecDestroy(&y);CHKERRQ(ierr);
7038   PetscFunctionReturn(0);
7039 }
7040 
7041 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7042 {
7043   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7044   PetscReal      x   = ptime,y;
7045   PetscErrorCode ierr;
7046   PetscInt       its;
7047 
7048   PetscFunctionBegin;
7049   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7050   if (!n) {
7051     PetscDrawAxis axis;
7052     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7053     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
7054     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7055     ctx->snes_its = 0;
7056   }
7057   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
7058   y    = its - ctx->snes_its;
7059   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7060   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7061     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7062     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7063   }
7064   ctx->snes_its = its;
7065   PetscFunctionReturn(0);
7066 }
7067 
7068 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7069 {
7070   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7071   PetscReal      x   = ptime,y;
7072   PetscErrorCode ierr;
7073   PetscInt       its;
7074 
7075   PetscFunctionBegin;
7076   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7077   if (!n) {
7078     PetscDrawAxis axis;
7079     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7080     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7081     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7082     ctx->ksp_its = 0;
7083   }
7084   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7085   y    = its - ctx->ksp_its;
7086   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7087   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7088     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7089     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7090   }
7091   ctx->ksp_its = its;
7092   PetscFunctionReturn(0);
7093 }
7094 
7095 /*@
7096    TSComputeLinearStability - computes the linear stability function at a point
7097 
7098    Collective on TS and Vec
7099 
7100    Input Parameters:
7101 +  ts - the TS context
7102 -  xr,xi - real and imaginary part of input arguments
7103 
7104    Output Parameters:
7105 .  yr,yi - real and imaginary part of function value
7106 
7107    Level: developer
7108 
7109 .keywords: TS, compute
7110 
7111 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7112 @*/
7113 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7114 {
7115   PetscErrorCode ierr;
7116 
7117   PetscFunctionBegin;
7118   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7119   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7120   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7121   PetscFunctionReturn(0);
7122 }
7123 
7124 /* ------------------------------------------------------------------------*/
7125 /*@C
7126    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7127 
7128    Collective on TS
7129 
7130    Input Parameters:
7131 .  ts  - the ODE solver object
7132 
7133    Output Parameter:
7134 .  ctx - the context
7135 
7136    Level: intermediate
7137 
7138 .keywords: TS, monitor, line graph, residual, seealso
7139 
7140 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7141 
7142 @*/
7143 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7144 {
7145   PetscErrorCode ierr;
7146 
7147   PetscFunctionBegin;
7148   ierr = PetscNew(ctx);CHKERRQ(ierr);
7149   PetscFunctionReturn(0);
7150 }
7151 
7152 /*@C
7153    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7154 
7155    Collective on TS
7156 
7157    Input Parameters:
7158 +  ts - the TS context
7159 .  step - current time-step
7160 .  ptime - current time
7161 .  u  - current solution
7162 -  dctx - the envelope context
7163 
7164    Options Database:
7165 .  -ts_monitor_envelope
7166 
7167    Level: intermediate
7168 
7169    Notes:
7170     after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7171 
7172 .keywords: TS,  vector, monitor, view
7173 
7174 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7175 @*/
7176 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7177 {
7178   PetscErrorCode       ierr;
7179   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7180 
7181   PetscFunctionBegin;
7182   if (!ctx->max) {
7183     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7184     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7185     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7186     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7187   } else {
7188     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7189     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7190   }
7191   PetscFunctionReturn(0);
7192 }
7193 
7194 /*@C
7195    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7196 
7197    Collective on TS
7198 
7199    Input Parameter:
7200 .  ts - the TS context
7201 
7202    Output Parameter:
7203 +  max - the maximum values
7204 -  min - the minimum values
7205 
7206    Notes:
7207     If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7208 
7209    Level: intermediate
7210 
7211 .keywords: TS,  vector, monitor, view
7212 
7213 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7214 @*/
7215 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7216 {
7217   PetscInt i;
7218 
7219   PetscFunctionBegin;
7220   if (max) *max = NULL;
7221   if (min) *min = NULL;
7222   for (i=0; i<ts->numbermonitors; i++) {
7223     if (ts->monitor[i] == TSMonitorEnvelope) {
7224       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7225       if (max) *max = ctx->max;
7226       if (min) *min = ctx->min;
7227       break;
7228     }
7229   }
7230   PetscFunctionReturn(0);
7231 }
7232 
7233 /*@C
7234    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7235 
7236    Collective on TSMonitorEnvelopeCtx
7237 
7238    Input Parameter:
7239 .  ctx - the monitor context
7240 
7241    Level: intermediate
7242 
7243 .keywords: TS, monitor, line graph, destroy
7244 
7245 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7246 @*/
7247 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7248 {
7249   PetscErrorCode ierr;
7250 
7251   PetscFunctionBegin;
7252   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7253   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7254   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7255   PetscFunctionReturn(0);
7256 }
7257 
7258 /*@
7259    TSRestartStep - Flags the solver to restart the next step
7260 
7261    Collective on TS
7262 
7263    Input Parameter:
7264 .  ts - the TS context obtained from TSCreate()
7265 
7266    Level: advanced
7267 
7268    Notes:
7269    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
7270    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
7271    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
7272    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
7273    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
7274    discontinuous source terms).
7275 
7276 .keywords: TS, timestep, restart
7277 
7278 .seealso: TSSolve(), TSSetPreStep(), TSSetPostStep()
7279 @*/
7280 PetscErrorCode TSRestartStep(TS ts)
7281 {
7282   PetscFunctionBegin;
7283   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7284   ts->steprestart = PETSC_TRUE;
7285   PetscFunctionReturn(0);
7286 }
7287 
7288 /*@
7289    TSRollBack - Rolls back one time step
7290 
7291    Collective on TS
7292 
7293    Input Parameter:
7294 .  ts - the TS context obtained from TSCreate()
7295 
7296    Level: advanced
7297 
7298 .keywords: TS, timestep, rollback
7299 
7300 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7301 @*/
7302 PetscErrorCode  TSRollBack(TS ts)
7303 {
7304   PetscErrorCode ierr;
7305 
7306   PetscFunctionBegin;
7307   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7308   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7309   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7310   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7311   ts->time_step = ts->ptime - ts->ptime_prev;
7312   ts->ptime = ts->ptime_prev;
7313   ts->ptime_prev = ts->ptime_prev_rollback;
7314   ts->steps--;
7315   ts->steprollback = PETSC_TRUE;
7316   PetscFunctionReturn(0);
7317 }
7318 
7319 /*@
7320    TSGetStages - Get the number of stages and stage values
7321 
7322    Input Parameter:
7323 .  ts - the TS context obtained from TSCreate()
7324 
7325    Level: advanced
7326 
7327 .keywords: TS, getstages
7328 
7329 .seealso: TSCreate()
7330 @*/
7331 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7332 {
7333   PetscErrorCode ierr;
7334 
7335   PetscFunctionBegin;
7336   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7337   PetscValidPointer(ns,2);
7338 
7339   if (!ts->ops->getstages) *ns=0;
7340   else {
7341     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7342   }
7343   PetscFunctionReturn(0);
7344 }
7345 
7346 /*@C
7347   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7348 
7349   Collective on SNES
7350 
7351   Input Parameters:
7352 + ts - the TS context
7353 . t - current timestep
7354 . U - state vector
7355 . Udot - time derivative of state vector
7356 . shift - shift to apply, see note below
7357 - ctx - an optional user context
7358 
7359   Output Parameters:
7360 + J - Jacobian matrix (not altered in this routine)
7361 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7362 
7363   Level: intermediate
7364 
7365   Notes:
7366   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7367 
7368   dF/dU + shift*dF/dUdot
7369 
7370   Most users should not need to explicitly call this routine, as it
7371   is used internally within the nonlinear solvers.
7372 
7373   This will first try to get the coloring from the DM.  If the DM type has no coloring
7374   routine, then it will try to get the coloring from the matrix.  This requires that the
7375   matrix have nonzero entries precomputed.
7376 
7377 .keywords: TS, finite differences, Jacobian, coloring, sparse
7378 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
7379 @*/
7380 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
7381 {
7382   SNES           snes;
7383   MatFDColoring  color;
7384   PetscBool      hascolor, matcolor = PETSC_FALSE;
7385   PetscErrorCode ierr;
7386 
7387   PetscFunctionBegin;
7388   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
7389   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
7390   if (!color) {
7391     DM         dm;
7392     ISColoring iscoloring;
7393 
7394     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
7395     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
7396     if (hascolor && !matcolor) {
7397       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
7398       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7399       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7400       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7401       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7402       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7403     } else {
7404       MatColoring mc;
7405 
7406       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
7407       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
7408       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
7409       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
7410       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
7411       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
7412       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7413       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7414       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7415       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7416       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7417     }
7418     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
7419     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
7420   }
7421   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
7422   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
7423   if (J != B) {
7424     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7425     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7426   }
7427   PetscFunctionReturn(0);
7428 }
7429 
7430 /*@
7431     TSSetFunctionDomainError - Set the function testing if the current state vector is valid
7432 
7433     Input Parameters:
7434     ts - the TS context
7435     func - function called within TSFunctionDomainError
7436 
7437     Level: intermediate
7438 
7439 .keywords: TS, state, domain
7440 .seealso: TSAdaptCheckStage(), TSFunctionDomainError()
7441 @*/
7442 
7443 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
7444 {
7445   PetscFunctionBegin;
7446   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7447   ts->functiondomainerror = func;
7448   PetscFunctionReturn(0);
7449 }
7450 
7451 /*@
7452     TSFunctionDomainError - Check if the current state is valid
7453 
7454     Input Parameters:
7455     ts - the TS context
7456     stagetime - time of the simulation
7457     Y - state vector to check.
7458 
7459     Output Parameter:
7460     accept - Set to PETSC_FALSE if the current state vector is valid.
7461 
7462     Note:
7463     This function should be used to ensure the state is in a valid part of the space.
7464     For example, one can ensure here all values are positive.
7465 
7466     Level: advanced
7467 @*/
7468 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
7469 {
7470   PetscErrorCode ierr;
7471 
7472   PetscFunctionBegin;
7473 
7474   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7475   *accept = PETSC_TRUE;
7476   if (ts->functiondomainerror) {
7477     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
7478   }
7479   PetscFunctionReturn(0);
7480 }
7481 
7482 /*@C
7483   TSClone - This function clones a time step object.
7484 
7485   Collective on MPI_Comm
7486 
7487   Input Parameter:
7488 . tsin    - The input TS
7489 
7490   Output Parameter:
7491 . tsout   - The output TS (cloned)
7492 
7493   Notes:
7494   This function is used to create a clone of a TS object. It is used in ARKIMEX for initializing the slope for first stage explicit methods. It will likely be replaced in the future with a mechanism of switching methods on the fly.
7495 
7496   When using TSDestroy() on a clone the user has to first reset the correct TS reference in the embedded SNES object: e.g.: by running SNES snes_dup=NULL; TSGetSNES(ts,&snes_dup); ierr = TSSetSNES(ts,snes_dup);
7497 
7498   Level: developer
7499 
7500 .keywords: TS, clone
7501 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
7502 @*/
7503 PetscErrorCode  TSClone(TS tsin, TS *tsout)
7504 {
7505   TS             t;
7506   PetscErrorCode ierr;
7507   SNES           snes_start;
7508   DM             dm;
7509   TSType         type;
7510 
7511   PetscFunctionBegin;
7512   PetscValidPointer(tsin,1);
7513   *tsout = NULL;
7514 
7515   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
7516 
7517   /* General TS description */
7518   t->numbermonitors    = 0;
7519   t->setupcalled       = 0;
7520   t->ksp_its           = 0;
7521   t->snes_its          = 0;
7522   t->nwork             = 0;
7523   t->rhsjacobian.time  = -1e20;
7524   t->rhsjacobian.scale = 1.;
7525   t->ijacobian.shift   = 1.;
7526 
7527   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
7528   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
7529 
7530   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
7531   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
7532 
7533   t->adapt = tsin->adapt;
7534   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
7535 
7536   t->trajectory = tsin->trajectory;
7537   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
7538 
7539   t->event = tsin->event;
7540   if (t->event) t->event->refct++;
7541 
7542   t->problem_type      = tsin->problem_type;
7543   t->ptime             = tsin->ptime;
7544   t->ptime_prev        = tsin->ptime_prev;
7545   t->time_step         = tsin->time_step;
7546   t->max_time          = tsin->max_time;
7547   t->steps             = tsin->steps;
7548   t->max_steps         = tsin->max_steps;
7549   t->equation_type     = tsin->equation_type;
7550   t->atol              = tsin->atol;
7551   t->rtol              = tsin->rtol;
7552   t->max_snes_failures = tsin->max_snes_failures;
7553   t->max_reject        = tsin->max_reject;
7554   t->errorifstepfailed = tsin->errorifstepfailed;
7555 
7556   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
7557   ierr = TSSetType(t,type);CHKERRQ(ierr);
7558 
7559   t->vec_sol           = NULL;
7560 
7561   t->cfltime          = tsin->cfltime;
7562   t->cfltime_local    = tsin->cfltime_local;
7563   t->exact_final_time = tsin->exact_final_time;
7564 
7565   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
7566 
7567   if (((PetscObject)tsin)->fortran_func_pointers) {
7568     PetscInt i;
7569     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
7570     for (i=0; i<10; i++) {
7571       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
7572     }
7573   }
7574   *tsout = t;
7575   PetscFunctionReturn(0);
7576 }
7577 
7578 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y)
7579 {
7580   PetscErrorCode ierr;
7581   TS             ts = (TS) ctx;
7582 
7583   PetscFunctionBegin;
7584   ierr = TSComputeRHSFunction(ts,0,x,y);CHKERRQ(ierr);
7585   PetscFunctionReturn(0);
7586 }
7587 
7588 /*@
7589     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
7590 
7591    Logically Collective on TS and Mat
7592 
7593     Input Parameters:
7594     TS - the time stepping routine
7595 
7596    Output Parameter:
7597 .   flg - PETSC_TRUE if the multiply is likely correct
7598 
7599    Options Database:
7600  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
7601 
7602    Level: advanced
7603 
7604    Notes:
7605     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7606 
7607 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTestTranspose()
7608 @*/
7609 PetscErrorCode  TSRHSJacobianTest(TS ts,PetscBool *flg)
7610 {
7611   Mat            J,B;
7612   PetscErrorCode ierr;
7613   TSRHSJacobian  func;
7614   void*          ctx;
7615 
7616   PetscFunctionBegin;
7617   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7618   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7619   ierr = MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7620   PetscFunctionReturn(0);
7621 }
7622 
7623 /*@C
7624     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
7625 
7626    Logically Collective on TS and Mat
7627 
7628     Input Parameters:
7629     TS - the time stepping routine
7630 
7631    Output Parameter:
7632 .   flg - PETSC_TRUE if the multiply is likely correct
7633 
7634    Options Database:
7635 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
7636 
7637    Notes:
7638     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7639 
7640    Level: advanced
7641 
7642 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTest()
7643 @*/
7644 PetscErrorCode  TSRHSJacobianTestTranspose(TS ts,PetscBool *flg)
7645 {
7646   Mat            J,B;
7647   PetscErrorCode ierr;
7648   void           *ctx;
7649   TSRHSJacobian  func;
7650 
7651   PetscFunctionBegin;
7652   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7653   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7654   ierr = MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7655   PetscFunctionReturn(0);
7656 }
7657