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