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