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