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