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