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