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