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