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