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