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