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