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