Actual source code: ts.c
1: #include <petsc/private/tsimpl.h>
2: #include <petscdmda.h>
3: #include <petscdmshell.h>
4: #include <petscdmplex.h>
5: #include <petscdmswarm.h>
6: #include <petscviewer.h>
7: #include <petscdraw.h>
8: #include <petscconvest.h>
10: /* Logging support */
11: PetscClassId TS_CLASSID, DMTS_CLASSID;
12: PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
14: const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED", "STEPOVER", "INTERPOLATE", "MATCHSTEP", "TSExactFinalTimeOption", "TS_EXACTFINALTIME_", NULL};
16: static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt, TSAdaptType default_type)
17: {
18: PetscFunctionBegin;
20: PetscAssertPointer(default_type, 2);
21: if (!((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, default_type));
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: /*@
26: TSSetFromOptions - Sets various `TS` parameters from the options database
28: Collective
30: Input Parameter:
31: . ts - the `TS` context obtained from `TSCreate()`
33: Options Database Keys:
34: + -ts_type <type> - EULER, BEULER, SUNDIALS, PSEUDO, CN, RK, THETA, ALPHA, GLLE, SSP, GLEE, BSYMP, IRK, see `TSType`
35: . -ts_save_trajectory - checkpoint the solution at each time-step
36: . -ts_max_time <time> - maximum time to compute to
37: . -ts_time_span <t0,...tf> - sets the time span, solutions are computed and stored for each indicated time, init_time and max_time are set
38: . -ts_eval_times <t0,...tn> - time points where solutions are computed and stored for each indicated time
39: . -ts_max_steps <steps> - maximum time-step number to execute until (possibly with nonzero starting value)
40: . -ts_run_steps <steps> - maximum number of time steps for `TSSolve()` to take on each call
41: . -ts_init_time <time> - initial time to start computation
42: . -ts_final_time <time> - final time to compute to (deprecated: use `-ts_max_time`)
43: . -ts_time_step <dt> - initial time step (only a suggestion, the actual initial time step used differ)
44: . -ts_exact_final_time <stepover,interpolate,matchstep> - whether to stop at the exact given final time and how to compute the solution at that time
45: . -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed
46: . -ts_max_step_rejections <maxrejects> - Maximum number of step rejections before step fails
47: . -ts_error_if_step_fails <true,false> - Error if no step succeeds
48: . -ts_rtol <rtol> - relative tolerance for local truncation error
49: . -ts_atol <atol> - Absolute tolerance for local truncation error
50: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function
51: . -ts_rhs_jacobian_test_mult_transpose - test the Jacobian at each iteration against finite difference with RHS function
52: . -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
53: . -ts_fd_color - Use finite differences with coloring to compute IJacobian
54: . -ts_monitor - print information at each timestep
55: . -ts_monitor_cancel - Cancel all monitors
56: . -ts_monitor_wall_clock_time - Monitor wall-clock time, KSP iterations, and SNES iterations per step
57: . -ts_monitor_lg_solution - Monitor solution graphically
58: . -ts_monitor_lg_error - Monitor error graphically
59: . -ts_monitor_error - Monitors norm of error
60: . -ts_monitor_lg_timestep - Monitor timestep size graphically
61: . -ts_monitor_lg_timestep_log - Monitor log timestep size graphically
62: . -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
63: . -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
64: . -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
65: . -ts_monitor_draw_solution - Monitor solution graphically
66: . -ts_monitor_draw_solution_phase <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
67: . -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
68: . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
69: . -ts_monitor_solution_interval <interval> - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
70: . -ts_monitor_solution_skip_initial - skip writing of initial condition
71: . -ts_monitor_solution_vtk <filename.vts,filename.vtu> - Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts (filename-%%03" PetscInt_FMT ".vtu)
72: . -ts_monitor_solution_vtk_interval <interval> - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
73: - -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
75: Level: beginner
77: Notes:
78: See `SNESSetFromOptions()` and `KSPSetFromOptions()` for how to control the nonlinear and linear solves used by the time-stepper.
80: Certain `SNES` options get reset for each new nonlinear solver, for example `-snes_lag_jacobian its` and `-snes_lag_preconditioner its`, in order
81: to retain them over the multiple nonlinear solves that `TS` uses you must also provide `-snes_lag_jacobian_persists true` and
82: `-snes_lag_preconditioner_persists true`
84: Developer Notes:
85: We should unify all the -ts_monitor options in the way that -xxx_view has been unified
87: .seealso: [](ch_ts), `TS`, `TSGetType()`
88: @*/
89: PetscErrorCode TSSetFromOptions(TS ts)
90: {
91: PetscBool opt, flg, tflg;
92: char monfilename[PETSC_MAX_PATH_LEN];
93: PetscReal time_step, eval_times[100] = {0};
94: PetscInt num_eval_times = PETSC_STATIC_ARRAY_LENGTH(eval_times);
95: TSExactFinalTimeOption eftopt;
96: char dir[16];
97: TSIFunctionFn *ifun;
98: const char *defaultType;
99: char typeName[256];
101: PetscFunctionBegin;
104: PetscCall(TSRegisterAll());
105: PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
107: PetscObjectOptionsBegin((PetscObject)ts);
108: if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
109: else defaultType = ifun ? TSBEULER : TSEULER;
110: PetscCall(PetscOptionsFList("-ts_type", "TS method", "TSSetType", TSList, defaultType, typeName, 256, &opt));
111: if (opt) PetscCall(TSSetType(ts, typeName));
112: else PetscCall(TSSetType(ts, defaultType));
114: /* Handle generic TS options */
115: PetscCall(PetscOptionsDeprecated("-ts_final_time", "-ts_max_time", "3.10", NULL));
116: PetscCall(PetscOptionsReal("-ts_max_time", "Maximum time to run to", "TSSetMaxTime", ts->max_time, &ts->max_time, NULL));
117: PetscCall(PetscOptionsRealArray("-ts_time_span", "Time span", "TSSetTimeSpan", eval_times, &num_eval_times, &flg));
118: if (flg) PetscCall(TSSetTimeSpan(ts, num_eval_times, eval_times));
119: num_eval_times = PETSC_STATIC_ARRAY_LENGTH(eval_times);
120: PetscCall(PetscOptionsRealArray("-ts_eval_times", "Evaluation time points", "TSSetEvaluationTimes", eval_times, &num_eval_times, &opt));
121: PetscCheck(flg != opt || (!flg && !opt), PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "May not provide -ts_time_span and -ts_eval_times simultaneously");
122: if (opt) PetscCall(TSSetEvaluationTimes(ts, num_eval_times, eval_times));
123: PetscCall(PetscOptionsInt("-ts_max_steps", "Maximum time step number to execute to (possibly with non-zero starting value)", "TSSetMaxSteps", ts->max_steps, &ts->max_steps, NULL));
124: PetscCall(PetscOptionsInt("-ts_run_steps", "Maximum number of time steps to take on each call to TSSolve()", "TSSetRunSteps", ts->run_steps, &ts->run_steps, NULL));
125: PetscCall(PetscOptionsReal("-ts_init_time", "Initial time", "TSSetTime", ts->ptime, &ts->ptime, NULL));
126: PetscCall(PetscOptionsDeprecated("-ts_dt", "-ts_time_step", "3.25", NULL));
127: PetscCall(PetscOptionsReal("-ts_time_step", "Initial time step", "TSSetTimeStep", ts->time_step, &time_step, &flg));
128: if (flg) PetscCall(TSSetTimeStep(ts, time_step));
129: PetscCall(PetscOptionsEnum("-ts_exact_final_time", "Option for handling of final time step", "TSSetExactFinalTime", TSExactFinalTimeOptions, (PetscEnum)ts->exact_final_time, (PetscEnum *)&eftopt, &flg));
130: if (flg) PetscCall(TSSetExactFinalTime(ts, eftopt));
131: PetscCall(PetscOptionsInt("-ts_max_snes_failures", "Maximum number of nonlinear solve failures", "TSSetMaxSNESFailures", ts->max_snes_failures, &ts->max_snes_failures, &flg));
132: if (flg) PetscCall(TSSetMaxSNESFailures(ts, ts->max_snes_failures));
133: PetscCall(PetscOptionsDeprecated("-ts_max_reject", "-ts_max_step_rejections", "3.25", NULL));
134: PetscCall(PetscOptionsInt("-ts_max_step_rejections", "Maximum number of step rejections before step fails", "TSSetMaxStepRejections", ts->max_reject, &ts->max_reject, &flg));
135: if (flg) PetscCall(TSSetMaxStepRejections(ts, ts->max_reject));
136: PetscCall(PetscOptionsBool("-ts_error_if_step_fails", "Error if no step succeeds", "TSSetErrorIfStepFails", ts->errorifstepfailed, &ts->errorifstepfailed, NULL));
137: PetscCall(PetscOptionsBoundedReal("-ts_rtol", "Relative tolerance for local truncation error", "TSSetTolerances", ts->rtol, &ts->rtol, NULL, 0));
138: PetscCall(PetscOptionsBoundedReal("-ts_atol", "Absolute tolerance for local truncation error", "TSSetTolerances", ts->atol, &ts->atol, NULL, 0));
140: PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult", "Test the RHS Jacobian for consistency with RHS at each solve ", "None", ts->testjacobian, &ts->testjacobian, NULL));
141: PetscCall(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));
142: PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction", "Use the split RHS function for multirate solvers ", "TSSetUseSplitRHSFunction", ts->use_splitrhsfunction, &ts->use_splitrhsfunction, NULL));
143: #if defined(PETSC_HAVE_SAWS)
144: {
145: PetscBool set;
146: flg = PETSC_FALSE;
147: PetscCall(PetscOptionsBool("-ts_saws_block", "Block for SAWs memory snooper at end of TSSolve", "PetscObjectSAWsBlock", ((PetscObject)ts)->amspublishblock, &flg, &set));
148: if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts, flg));
149: }
150: #endif
152: /* Monitor options */
153: PetscCall(PetscOptionsDeprecated("-ts_monitor_frequency", "-ts_dmswarm_monitor_moments_interval", "3.24", "Retired in favor of monitor-specific intervals (ts_dmswarm_monitor_moments was the only monitor to use ts_monitor_frequency)"));
154: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor", "Monitor time and timestep size", "TSMonitorDefault", TSMonitorDefault, NULL));
155: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_wall_clock_time", "Monitor wall-clock time, KSP iterations, and SNES iterations per step", "TSMonitorWallClockTime", TSMonitorWallClockTime, TSMonitorWallClockTimeSetUp));
156: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_extreme", "Monitor extreme values of the solution", "TSMonitorExtreme", TSMonitorExtreme, NULL));
157: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_solution", "View the solution at each timestep", "TSMonitorSolution", TSMonitorSolution, TSMonitorSolutionSetup));
158: PetscCall(TSMonitorSetFromOptions(ts, "-ts_dmswarm_monitor_moments", "Monitor moments of particle distribution", "TSDMSwarmMonitorMoments", TSDMSwarmMonitorMoments, NULL));
159: PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
160: if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename));
162: PetscCall(PetscOptionsName("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", &opt));
163: if (opt) {
164: PetscInt howoften = 1;
165: DM dm;
166: PetscBool net;
168: PetscCall(PetscOptionsInt("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", howoften, &howoften, NULL));
169: PetscCall(TSGetDM(ts, &dm));
170: PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMNETWORK, &net));
171: if (net) {
172: TSMonitorLGCtxNetwork ctx;
173: PetscCall(TSMonitorLGCtxNetworkCreate(ts, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &ctx));
174: PetscCall(TSMonitorSet(ts, TSMonitorLGCtxNetworkSolution, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxNetworkDestroy));
175: PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy", "Plot the solution with a semi-log axis", "", ctx->semilogy, &ctx->semilogy, NULL));
176: } else {
177: TSMonitorLGCtx ctx;
178: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
179: PetscCall(TSMonitorSet(ts, TSMonitorLGSolution, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
180: }
181: }
183: PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt));
184: if (opt) {
185: TSMonitorLGCtx ctx;
186: PetscInt howoften = 1;
188: PetscCall(PetscOptionsInt("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", howoften, &howoften, NULL));
189: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
190: PetscCall(TSMonitorSet(ts, TSMonitorLGError, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
191: }
192: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_error", "View the error at each timestep", "TSMonitorError", TSMonitorError, NULL));
194: PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt));
195: if (opt) {
196: TSMonitorLGCtx ctx;
197: PetscInt howoften = 1;
199: PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
200: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
201: PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
202: }
203: PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", &opt));
204: if (opt) {
205: TSMonitorLGCtx ctx;
206: PetscInt howoften = 1;
208: PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
209: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
210: PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
211: ctx->semilogy = PETSC_TRUE;
212: }
214: PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", &opt));
215: if (opt) {
216: TSMonitorLGCtx ctx;
217: PetscInt howoften = 1;
219: PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", howoften, &howoften, NULL));
220: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
221: PetscCall(TSMonitorSet(ts, TSMonitorLGSNESIterations, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
222: }
223: PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", &opt));
224: if (opt) {
225: TSMonitorLGCtx ctx;
226: PetscInt howoften = 1;
228: PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", howoften, &howoften, NULL));
229: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
230: PetscCall(TSMonitorSet(ts, TSMonitorLGKSPIterations, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
231: }
232: PetscCall(PetscOptionsName("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", &opt));
233: if (opt) {
234: TSMonitorSPEigCtx ctx;
235: PetscInt howoften = 1;
237: PetscCall(PetscOptionsInt("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", howoften, &howoften, NULL));
238: PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
239: PetscCall(TSMonitorSet(ts, TSMonitorSPEig, ctx, (PetscCtxDestroyFn *)TSMonitorSPEigCtxDestroy));
240: }
241: PetscCall(PetscOptionsName("-ts_monitor_sp_swarm", "Display particle phase space from the DMSwarm", "TSMonitorSPSwarm", &opt));
242: if (opt) {
243: TSMonitorSPCtx ctx;
244: PetscInt howoften = 1, retain = 0;
245: PetscBool phase = PETSC_TRUE, create = PETSC_TRUE, multispecies = PETSC_FALSE;
247: for (PetscInt i = 0; i < ts->numbermonitors; ++i)
248: if (ts->monitor[i] == TSMonitorSPSwarmSolution) {
249: create = PETSC_FALSE;
250: break;
251: }
252: if (create) {
253: PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm", "Display particles phase space from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL));
254: PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL));
255: PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL));
256: PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_multi_species", "Color particles by particle species", "TSMonitorSPSwarm", multispecies, &multispecies, NULL));
257: PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, multispecies, &ctx));
258: PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscCtxDestroyFn *)TSMonitorSPCtxDestroy));
259: }
260: }
261: PetscCall(PetscOptionsName("-ts_monitor_hg_swarm", "Display particle histogram from the DMSwarm", "TSMonitorHGSwarm", &opt));
262: if (opt) {
263: TSMonitorHGCtx ctx;
264: PetscInt howoften = 1, Ns = 1;
265: PetscBool velocity = PETSC_FALSE, create = PETSC_TRUE;
267: for (PetscInt i = 0; i < ts->numbermonitors; ++i)
268: if (ts->monitor[i] == TSMonitorHGSwarmSolution) {
269: create = PETSC_FALSE;
270: break;
271: }
272: if (create) {
273: DM sw, dm;
274: PetscInt Nc, Nb;
276: PetscCall(TSGetDM(ts, &sw));
277: PetscCall(DMSwarmGetCellDM(sw, &dm));
278: PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &Nc));
279: Nb = PetscMin(20, PetscMax(10, Nc));
280: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm", "Display particles histogram from the DMSwarm", "TSMonitorHGSwarm", howoften, &howoften, NULL));
281: PetscCall(PetscOptionsBool("-ts_monitor_hg_swarm_velocity", "Plot in velocity space rather than coordinate space", "TSMonitorHGSwarm", velocity, &velocity, NULL));
282: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_species", "Number of species to histogram", "TSMonitorHGSwarm", Ns, &Ns, NULL));
283: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_bins", "Number of histogram bins", "TSMonitorHGSwarm", Nb, &Nb, NULL));
284: PetscCall(TSMonitorHGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, Ns, Nb, velocity, &ctx));
285: PetscCall(TSMonitorSet(ts, TSMonitorHGSwarmSolution, ctx, (PetscCtxDestroyFn *)TSMonitorHGCtxDestroy));
286: }
287: }
288: opt = PETSC_FALSE;
289: PetscCall(PetscOptionsName("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", &opt));
290: if (opt) {
291: TSMonitorDrawCtx ctx;
292: PetscInt howoften = 1;
294: PetscCall(PetscOptionsInt("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", howoften, &howoften, NULL));
295: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Computed Solution", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
296: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolution, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
297: }
298: opt = PETSC_FALSE;
299: PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", &opt));
300: if (opt) {
301: TSMonitorDrawCtx ctx;
302: PetscReal bounds[4];
303: PetscInt n = 4;
304: PetscDraw draw;
305: PetscDrawAxis axis;
307: PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", bounds, &n, NULL));
308: PetscCheck(n == 4, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Must provide bounding box of phase field");
309: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, 1, &ctx));
310: PetscCall(PetscViewerDrawGetDraw(ctx->viewer, 0, &draw));
311: PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer, 0, &axis));
312: PetscCall(PetscDrawAxisSetLimits(axis, bounds[0], bounds[2], bounds[1], bounds[3]));
313: PetscCall(PetscDrawAxisSetLabels(axis, "Phase Diagram", "Variable 1", "Variable 2"));
314: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionPhase, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
315: }
316: opt = PETSC_FALSE;
317: PetscCall(PetscOptionsName("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", &opt));
318: if (opt) {
319: TSMonitorDrawCtx ctx;
320: PetscInt howoften = 1;
322: PetscCall(PetscOptionsInt("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", howoften, &howoften, NULL));
323: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Error", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
324: PetscCall(TSMonitorSet(ts, TSMonitorDrawError, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
325: }
326: opt = PETSC_FALSE;
327: PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", &opt));
328: if (opt) {
329: TSMonitorDrawCtx ctx;
330: PetscInt howoften = 1;
332: PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", howoften, &howoften, NULL));
333: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Solution provided by user function", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
334: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionFunction, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
335: }
337: opt = PETSC_FALSE;
338: PetscCall(PetscOptionsString("-ts_monitor_solution_vtk", "Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts", "TSMonitorSolutionVTK", NULL, monfilename, sizeof(monfilename), &flg));
339: if (flg) {
340: TSMonitorVTKCtx ctx;
342: PetscCall(TSMonitorSolutionVTKCtxCreate(monfilename, &ctx));
343: PetscCall(PetscOptionsInt("-ts_monitor_solution_vtk_interval", "Save every interval time step (-1 for last step only)", NULL, ctx->interval, &ctx->interval, NULL));
344: PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscCtx))TSMonitorSolutionVTK, ctx, (PetscCtxDestroyFn *)TSMonitorSolutionVTKDestroy));
345: }
347: PetscCall(PetscOptionsString("-ts_monitor_dmda_ray", "Display a ray of the solution", "None", "y=0", dir, sizeof(dir), &flg));
348: if (flg) {
349: TSMonitorDMDARayCtx *rayctx;
350: int ray = 0;
351: DMDirection ddir;
352: DM da;
353: PetscMPIInt rank;
355: PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
356: if (dir[0] == 'x') ddir = DM_X;
357: else if (dir[0] == 'y') ddir = DM_Y;
358: else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
359: sscanf(dir + 2, "%d", &ray);
361: PetscCall(PetscInfo(ts, "Displaying DMDA ray %c = %d\n", dir[0], ray));
362: PetscCall(PetscNew(&rayctx));
363: PetscCall(TSGetDM(ts, &da));
364: PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
365: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts), &rank));
366: if (rank == 0) PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, NULL, NULL, 0, 0, 600, 300, &rayctx->viewer));
367: rayctx->lgctx = NULL;
368: PetscCall(TSMonitorSet(ts, TSMonitorDMDARay, rayctx, TSMonitorDMDARayDestroy));
369: }
370: PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray", "Display a ray of the solution", "None", "x=0", dir, sizeof(dir), &flg));
371: if (flg) {
372: TSMonitorDMDARayCtx *rayctx;
373: int ray = 0;
374: DMDirection ddir;
375: DM da;
376: PetscInt howoften = 1;
378: PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
379: if (dir[0] == 'x') ddir = DM_X;
380: else if (dir[0] == 'y') ddir = DM_Y;
381: else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
382: sscanf(dir + 2, "%d", &ray);
384: PetscCall(PetscInfo(ts, "Displaying LG DMDA ray %c = %d\n", dir[0], ray));
385: PetscCall(PetscNew(&rayctx));
386: PetscCall(TSGetDM(ts, &da));
387: PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
388: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &rayctx->lgctx));
389: PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
390: }
392: PetscCall(PetscOptionsName("-ts_monitor_envelope", "Monitor maximum and minimum value of each component of the solution", "TSMonitorEnvelope", &opt));
393: if (opt) {
394: TSMonitorEnvelopeCtx ctx;
396: PetscCall(TSMonitorEnvelopeCtxCreate(ts, &ctx));
397: PetscCall(TSMonitorSet(ts, TSMonitorEnvelope, ctx, (PetscCtxDestroyFn *)TSMonitorEnvelopeCtxDestroy));
398: }
399: flg = PETSC_FALSE;
400: PetscCall(PetscOptionsBool("-ts_monitor_cancel", "Remove all monitors", "TSMonitorCancel", flg, &flg, &opt));
401: if (opt && flg) PetscCall(TSMonitorCancel(ts));
403: flg = PETSC_FALSE;
404: PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeIJacobianDefaultColor", flg, &flg, NULL));
405: if (flg) {
406: DM dm;
408: PetscCall(TSGetDM(ts, &dm));
409: PetscCall(DMTSUnsetIJacobianContext_Internal(dm));
410: PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
411: PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
412: }
414: /* Handle specific TS options */
415: PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject);
417: /* Handle TSAdapt options */
418: PetscCall(TSGetAdapt(ts, &ts->adapt));
419: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
420: PetscCall(TSAdaptSetFromOptions(ts->adapt, PetscOptionsObject));
422: /* TS trajectory must be set after TS, since it may use some TS options above */
423: tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
424: PetscCall(PetscOptionsBool("-ts_save_trajectory", "Save the solution at each timestep", "TSSetSaveTrajectory", tflg, &tflg, NULL));
425: if (tflg) PetscCall(TSSetSaveTrajectory(ts));
427: PetscCall(TSAdjointSetFromOptions(ts, PetscOptionsObject));
429: /* process any options handlers added with PetscObjectAddOptionsHandler() */
430: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject));
431: PetscOptionsEnd();
433: if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory, ts));
435: /* why do we have to do this here and not during TSSetUp? */
436: PetscCall(TSGetSNES(ts, &ts->snes));
437: if (ts->problem_type == TS_LINEAR) {
438: PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &flg, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
439: if (!flg) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
440: }
441: PetscCall(SNESSetFromOptions(ts->snes));
442: PetscFunctionReturn(PETSC_SUCCESS);
443: }
445: /*@
446: TSGetTrajectory - Gets the trajectory from a `TS` if it exists
448: Collective
450: Input Parameter:
451: . ts - the `TS` context obtained from `TSCreate()`
453: Output Parameter:
454: . tr - the `TSTrajectory` object, if it exists
456: Level: advanced
458: Note:
459: This routine should be called after all `TS` options have been set
461: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()`
462: @*/
463: PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr)
464: {
465: PetscFunctionBegin;
467: *tr = ts->trajectory;
468: PetscFunctionReturn(PETSC_SUCCESS);
469: }
471: /*@
472: TSSetSaveTrajectory - Causes the `TS` to save its solutions as it iterates forward in time in a `TSTrajectory` object
474: Collective
476: Input Parameter:
477: . ts - the `TS` context obtained from `TSCreate()`
479: Options Database Keys:
480: + -ts_save_trajectory - saves the trajectory to a file
481: - -ts_trajectory_type type - set trajectory type
483: Level: intermediate
485: Notes:
486: This routine should be called after all `TS` options have been set
488: The `TSTRAJECTORYVISUALIZATION` files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
489: MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
491: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`
492: @*/
493: PetscErrorCode TSSetSaveTrajectory(TS ts)
494: {
495: PetscFunctionBegin;
497: if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
501: /*@
502: TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object
504: Collective
506: Input Parameter:
507: . ts - the `TS` context obtained from `TSCreate()`
509: Level: intermediate
511: .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()`
512: @*/
513: PetscErrorCode TSResetTrajectory(TS ts)
514: {
515: PetscFunctionBegin;
517: if (ts->trajectory) {
518: PetscCall(TSTrajectoryDestroy(&ts->trajectory));
519: PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
520: }
521: PetscFunctionReturn(PETSC_SUCCESS);
522: }
524: /*@
525: TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from a `TS`
527: Collective
529: Input Parameter:
530: . ts - the `TS` context obtained from `TSCreate()`
532: Level: intermediate
534: .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()`
535: @*/
536: PetscErrorCode TSRemoveTrajectory(TS ts)
537: {
538: PetscFunctionBegin;
540: if (ts->trajectory) PetscCall(TSTrajectoryDestroy(&ts->trajectory));
541: PetscFunctionReturn(PETSC_SUCCESS);
542: }
544: /*@
545: TSComputeRHSJacobian - Computes the Jacobian matrix that has been
546: set with `TSSetRHSJacobian()`.
548: Collective
550: Input Parameters:
551: + ts - the `TS` context
552: . t - current timestep
553: - U - input vector
555: Output Parameters:
556: + A - Jacobian matrix
557: - B - optional matrix used to compute the preconditioner, often the same as `A`
559: Level: developer
561: Note:
562: Most users should not need to explicitly call this routine, as it
563: is used internally within the ODE integrators.
565: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `KSPSetOperators()`
566: @*/
567: PetscErrorCode TSComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B)
568: {
569: PetscObjectState Ustate;
570: PetscObjectId Uid;
571: DM dm;
572: DMTS tsdm;
573: TSRHSJacobianFn *rhsjacobianfunc;
574: void *ctx;
575: TSRHSFunctionFn *rhsfunction;
577: PetscFunctionBegin;
580: PetscCheckSameComm(ts, 1, U, 3);
581: PetscCall(TSGetDM(ts, &dm));
582: PetscCall(DMGetDMTS(dm, &tsdm));
583: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
584: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobianfunc, &ctx));
585: PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
586: PetscCall(PetscObjectGetId((PetscObject)U, &Uid));
588: if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(PETSC_SUCCESS);
590: PetscCheck(ts->rhsjacobian.shift == 0.0 || !ts->rhsjacobian.reuse, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Should not call TSComputeRHSJacobian() on a shifted matrix (shift=%lf) when RHSJacobian is reusable.", (double)ts->rhsjacobian.shift);
591: if (rhsjacobianfunc) {
592: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
593: PetscCallBack("TS callback Jacobian", (*rhsjacobianfunc)(ts, t, U, A, B, ctx));
594: ts->rhsjacs++;
595: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
596: } else {
597: PetscCall(MatZeroEntries(A));
598: if (B && A != B) PetscCall(MatZeroEntries(B));
599: }
600: ts->rhsjacobian.time = t;
601: ts->rhsjacobian.shift = 0;
602: ts->rhsjacobian.scale = 1.;
603: PetscCall(PetscObjectGetId((PetscObject)U, &ts->rhsjacobian.Xid));
604: PetscCall(PetscObjectStateGet((PetscObject)U, &ts->rhsjacobian.Xstate));
605: PetscFunctionReturn(PETSC_SUCCESS);
606: }
608: /*@
609: TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS`
611: Collective
613: Input Parameters:
614: + ts - the `TS` context
615: . t - current time
616: - U - state vector
618: Output Parameter:
619: . y - right-hand side
621: Level: developer
623: Note:
624: Most users should not need to explicitly call this routine, as it
625: is used internally within the nonlinear solvers.
627: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
628: @*/
629: PetscErrorCode TSComputeRHSFunction(TS ts, PetscReal t, Vec U, Vec y)
630: {
631: TSRHSFunctionFn *rhsfunction;
632: TSIFunctionFn *ifunction;
633: void *ctx;
634: DM dm;
636: PetscFunctionBegin;
640: PetscCall(TSGetDM(ts, &dm));
641: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx));
642: PetscCall(DMTSGetIFunction(dm, &ifunction, NULL));
644: PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");
646: if (rhsfunction) {
647: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, y, 0));
648: PetscCall(VecLockReadPush(U));
649: PetscCallBack("TS callback right-hand-side", (*rhsfunction)(ts, t, U, y, ctx));
650: PetscCall(VecLockReadPop(U));
651: ts->rhsfuncs++;
652: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, y, 0));
653: } else PetscCall(VecZeroEntries(y));
654: PetscFunctionReturn(PETSC_SUCCESS);
655: }
657: /*@
658: TSComputeSolutionFunction - Evaluates the solution function.
660: Collective
662: Input Parameters:
663: + ts - the `TS` context
664: - t - current time
666: Output Parameter:
667: . U - the solution
669: Level: developer
671: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
672: @*/
673: PetscErrorCode TSComputeSolutionFunction(TS ts, PetscReal t, Vec U)
674: {
675: TSSolutionFn *solutionfunction;
676: void *ctx;
677: DM dm;
679: PetscFunctionBegin;
682: PetscCall(TSGetDM(ts, &dm));
683: PetscCall(DMTSGetSolutionFunction(dm, &solutionfunction, &ctx));
684: if (solutionfunction) PetscCallBack("TS callback solution", (*solutionfunction)(ts, t, U, ctx));
685: PetscFunctionReturn(PETSC_SUCCESS);
686: }
687: /*@
688: TSComputeForcingFunction - Evaluates the forcing function.
690: Collective
692: Input Parameters:
693: + ts - the `TS` context
694: - t - current time
696: Output Parameter:
697: . U - the function value
699: Level: developer
701: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
702: @*/
703: PetscErrorCode TSComputeForcingFunction(TS ts, PetscReal t, Vec U)
704: {
705: void *ctx;
706: DM dm;
707: TSForcingFn *forcing;
709: PetscFunctionBegin;
712: PetscCall(TSGetDM(ts, &dm));
713: PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx));
715: if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx));
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs)
720: {
721: Mat A, B;
722: TSIJacobianFn *ijacobian;
724: PetscFunctionBegin;
725: if (Arhs) *Arhs = NULL;
726: if (Brhs) *Brhs = NULL;
727: PetscCall(TSGetIJacobian(ts, &A, &B, &ijacobian, NULL));
728: if (Arhs) {
729: if (!ts->Arhs) {
730: if (ijacobian) {
731: PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &ts->Arhs));
732: PetscCall(TSSetMatStructure(ts, SAME_NONZERO_PATTERN));
733: } else {
734: ts->Arhs = A;
735: PetscCall(PetscObjectReference((PetscObject)A));
736: }
737: } else {
738: PetscBool flg;
739: PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
740: /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */
741: if (flg && !ijacobian && ts->Arhs == ts->Brhs) {
742: PetscCall(PetscObjectDereference((PetscObject)ts->Arhs));
743: ts->Arhs = A;
744: PetscCall(PetscObjectReference((PetscObject)A));
745: }
746: }
747: *Arhs = ts->Arhs;
748: }
749: if (Brhs) {
750: if (!ts->Brhs) {
751: if (A != B) {
752: if (ijacobian) {
753: PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &ts->Brhs));
754: } else {
755: ts->Brhs = B;
756: PetscCall(PetscObjectReference((PetscObject)B));
757: }
758: } else {
759: PetscCall(PetscObjectReference((PetscObject)ts->Arhs));
760: ts->Brhs = ts->Arhs;
761: }
762: }
763: *Brhs = ts->Brhs;
764: }
765: PetscFunctionReturn(PETSC_SUCCESS);
766: }
768: /*@
769: TSComputeIFunction - Evaluates the DAE residual written in the implicit form F(t,U,Udot)=0
771: Collective
773: Input Parameters:
774: + ts - the `TS` context
775: . t - current time
776: . U - state vector
777: . Udot - time derivative of state vector
778: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSFunction should be kept separate
780: Output Parameter:
781: . Y - right-hand side
783: Level: developer
785: Note:
786: Most users should not need to explicitly call this routine, as it
787: is used internally within the nonlinear solvers.
789: If the user did not write their equations in implicit form, this
790: function recasts them in implicit form.
792: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSComputeRHSFunction()`
793: @*/
794: PetscErrorCode TSComputeIFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec Y, PetscBool imex)
795: {
796: TSIFunctionFn *ifunction;
797: TSRHSFunctionFn *rhsfunction;
798: void *ctx;
799: DM dm;
801: PetscFunctionBegin;
807: PetscCall(TSGetDM(ts, &dm));
808: PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx));
809: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
811: PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");
813: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, Udot, Y));
814: if (ifunction) {
815: PetscCallBack("TS callback implicit function", (*ifunction)(ts, t, U, Udot, Y, ctx));
816: ts->ifuncs++;
817: }
818: if (imex) {
819: if (!ifunction) PetscCall(VecCopy(Udot, Y));
820: } else if (rhsfunction) {
821: if (ifunction) {
822: Vec Frhs;
824: PetscCall(DMGetGlobalVector(dm, &Frhs));
825: PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
826: PetscCall(VecAXPY(Y, -1, Frhs));
827: PetscCall(DMRestoreGlobalVector(dm, &Frhs));
828: } else {
829: PetscCall(TSComputeRHSFunction(ts, t, U, Y));
830: PetscCall(VecAYPX(Y, -1, Udot));
831: }
832: }
833: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, Udot, Y));
834: PetscFunctionReturn(PETSC_SUCCESS);
835: }
837: /*
838: TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call `TSComputeRHSJacobian()` on it.
840: Note:
841: This routine is needed when one switches from `TSComputeIJacobian()` to `TSComputeRHSJacobian()` because the Jacobian matrix may be shifted or scaled in `TSComputeIJacobian()`.
843: */
844: static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B)
845: {
846: PetscFunctionBegin;
848: PetscCheck(A == ts->Arhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Amat");
849: PetscCheck(B == ts->Brhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Bmat");
851: if (ts->rhsjacobian.shift) PetscCall(MatShift(A, -ts->rhsjacobian.shift));
852: if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(A, -1));
853: if (B && B == ts->Brhs && A != B) {
854: if (ts->rhsjacobian.shift) PetscCall(MatShift(B, -ts->rhsjacobian.shift));
855: if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(B, -1));
856: }
857: ts->rhsjacobian.shift = 0;
858: ts->rhsjacobian.scale = 1.;
859: PetscFunctionReturn(PETSC_SUCCESS);
860: }
862: /*@
863: TSComputeIJacobian - Evaluates the Jacobian of the DAE
865: Collective
867: Input Parameters:
868: + ts - the `TS` context
869: . t - current timestep
870: . U - state vector
871: . Udot - time derivative of state vector
872: . shift - shift to apply, see note below
873: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSJacobian should be kept separate
875: Output Parameters:
876: + A - Jacobian matrix
877: - B - matrix from which the preconditioner is constructed; often the same as `A`
879: Level: developer
881: Notes:
882: If $ F(t,U,\dot{U})=0 $ is the DAE, the required Jacobian is
883: .vb
884: dF/dU + shift*dF/dUdot
885: .ve
886: Most users should not need to explicitly call this routine, as it
887: is used internally within the nonlinear solvers.
889: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`
890: @*/
891: PetscErrorCode TSComputeIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex)
892: {
893: TSIJacobianFn *ijacobian;
894: TSRHSJacobianFn *rhsjacobian;
895: DM dm;
896: void *ctx;
898: PetscFunctionBegin;
905: PetscCall(TSGetDM(ts, &dm));
906: PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx));
907: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));
909: PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
911: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
912: if (ijacobian) {
913: PetscCallBack("TS callback implicit Jacobian", (*ijacobian)(ts, t, U, Udot, shift, A, B, ctx));
914: ts->ijacs++;
915: }
916: if (imex) {
917: if (!ijacobian) { /* system was written as Udot = G(t,U) */
918: PetscBool assembled;
919: if (rhsjacobian) {
920: Mat Arhs = NULL;
921: PetscCall(TSGetRHSMats_Private(ts, &Arhs, NULL));
922: if (A == Arhs) {
923: PetscCheck(rhsjacobian != TSComputeRHSJacobianConstant, 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 */
924: ts->rhsjacobian.time = PETSC_MIN_REAL;
925: }
926: }
927: PetscCall(MatZeroEntries(A));
928: PetscCall(MatAssembled(A, &assembled));
929: if (!assembled) {
930: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
931: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
932: }
933: PetscCall(MatShift(A, shift));
934: if (A != B) {
935: PetscCall(MatZeroEntries(B));
936: PetscCall(MatAssembled(B, &assembled));
937: if (!assembled) {
938: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
939: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
940: }
941: PetscCall(MatShift(B, shift));
942: }
943: }
944: } else {
945: Mat Arhs = NULL, Brhs = NULL;
947: /* RHSJacobian needs to be converted to part of IJacobian if exists */
948: if (rhsjacobian) PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
949: if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */
950: PetscObjectState Ustate;
951: PetscObjectId Uid;
952: TSRHSFunctionFn *rhsfunction;
954: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
955: PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
956: PetscCall(PetscObjectGetId((PetscObject)U, &Uid));
957: if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) &&
958: ts->rhsjacobian.scale == -1.) { /* No need to recompute RHSJacobian */
959: PetscCall(MatShift(A, shift - ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */
960: if (A != B) PetscCall(MatShift(B, shift - ts->rhsjacobian.shift));
961: } else {
962: PetscBool flg;
964: if (ts->rhsjacobian.reuse) { /* Undo the damage */
965: /* MatScale has a short path for this case.
966: However, this code path is taken the first time TSComputeRHSJacobian is called
967: and the matrices have not been assembled yet */
968: PetscCall(TSRecoverRHSJacobian(ts, A, B));
969: }
970: PetscCall(TSComputeRHSJacobian(ts, t, U, A, B));
971: PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
972: /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */
973: if (!flg) {
974: PetscCall(MatScale(A, -1));
975: PetscCall(MatShift(A, shift));
976: }
977: if (A != B) {
978: PetscCall(MatScale(B, -1));
979: PetscCall(MatShift(B, shift));
980: }
981: }
982: ts->rhsjacobian.scale = -1;
983: ts->rhsjacobian.shift = shift;
984: } else if (Arhs) { /* Both IJacobian and RHSJacobian */
985: if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */
986: PetscCall(MatZeroEntries(A));
987: PetscCall(MatShift(A, shift));
988: if (A != B) {
989: PetscCall(MatZeroEntries(B));
990: PetscCall(MatShift(B, shift));
991: }
992: }
993: PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
994: PetscCall(MatAXPY(A, -1, Arhs, ts->axpy_pattern));
995: if (A != B) PetscCall(MatAXPY(B, -1, Brhs, ts->axpy_pattern));
996: }
997: }
998: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
999: PetscFunctionReturn(PETSC_SUCCESS);
1000: }
1002: /*@C
1003: TSSetRHSFunction - Sets the routine for evaluating the function,
1004: where U_t = G(t,u).
1006: Logically Collective
1008: Input Parameters:
1009: + ts - the `TS` context obtained from `TSCreate()`
1010: . r - vector to put the computed right-hand side (or `NULL` to have it created)
1011: . f - routine for evaluating the right-hand-side function
1012: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
1014: Level: beginner
1016: Note:
1017: You must call this function or `TSSetIFunction()` to define your ODE. You cannot use this function when solving a DAE.
1019: .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1020: @*/
1021: PetscErrorCode TSSetRHSFunction(TS ts, Vec r, TSRHSFunctionFn *f, PetscCtx ctx)
1022: {
1023: SNES snes;
1024: Vec ralloc = NULL;
1025: DM dm;
1027: PetscFunctionBegin;
1031: PetscCall(TSGetDM(ts, &dm));
1032: PetscCall(DMTSSetRHSFunction(dm, f, ctx));
1033: PetscCall(TSGetSNES(ts, &snes));
1034: if (!r && !ts->dm && ts->vec_sol) {
1035: PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1036: r = ralloc;
1037: }
1038: PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1039: PetscCall(VecDestroy(&ralloc));
1040: PetscFunctionReturn(PETSC_SUCCESS);
1041: }
1043: /*@C
1044: TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
1046: Logically Collective
1048: Input Parameters:
1049: + ts - the `TS` context obtained from `TSCreate()`
1050: . f - routine for evaluating the solution
1051: - ctx - [optional] user-defined context for private data for the
1052: function evaluation routine (may be `NULL`)
1054: Options Database Keys:
1055: + -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided `TSSetSolutionFunction()`
1056: - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
1058: Level: intermediate
1060: Notes:
1061: This routine is used for testing accuracy of time integration schemes when you already know the solution.
1062: If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
1063: create closed-form solutions with non-physical forcing terms.
1065: For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.
1067: .seealso: [](ch_ts), `TS`, `TSSolutionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()`
1068: @*/
1069: PetscErrorCode TSSetSolutionFunction(TS ts, TSSolutionFn *f, PetscCtx ctx)
1070: {
1071: DM dm;
1073: PetscFunctionBegin;
1075: PetscCall(TSGetDM(ts, &dm));
1076: PetscCall(DMTSSetSolutionFunction(dm, f, ctx));
1077: PetscFunctionReturn(PETSC_SUCCESS);
1078: }
1080: /*@C
1081: TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
1083: Logically Collective
1085: Input Parameters:
1086: + ts - the `TS` context obtained from `TSCreate()`
1087: . func - routine for evaluating the forcing function
1088: - ctx - [optional] user-defined context for private data for the function evaluation routine
1089: (may be `NULL`)
1091: Level: intermediate
1093: Notes:
1094: This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
1095: create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the
1096: definition of the problem you are solving and hence possibly introducing bugs.
1098: This replaces the ODE F(u,u_t,t) = 0 the `TS` is solving with F(u,u_t,t) - func(t) = 0
1100: This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the
1101: parameters can be passed in the ctx variable.
1103: For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.
1105: .seealso: [](ch_ts), `TS`, `TSForcingFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`,
1106: `TSComputeSolutionFunction()`, `TSSetSolutionFunction()`
1107: @*/
1108: PetscErrorCode TSSetForcingFunction(TS ts, TSForcingFn *func, PetscCtx ctx)
1109: {
1110: DM dm;
1112: PetscFunctionBegin;
1114: PetscCall(TSGetDM(ts, &dm));
1115: PetscCall(DMTSSetForcingFunction(dm, func, ctx));
1116: PetscFunctionReturn(PETSC_SUCCESS);
1117: }
1119: /*@C
1120: TSSetRHSJacobian - Sets the function to compute the Jacobian of G,
1121: where U_t = G(U,t), as well as the location to store the matrix.
1123: Logically Collective
1125: Input Parameters:
1126: + ts - the `TS` context obtained from `TSCreate()`
1127: . Amat - (approximate) location to store Jacobian matrix entries computed by `f`
1128: . Pmat - matrix from which preconditioner is to be constructed (usually the same as `Amat`)
1129: . f - the Jacobian evaluation routine
1130: - ctx - [optional] user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1132: Level: beginner
1134: Notes:
1135: You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1137: The `TS` solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f()`
1138: You should not assume the values are the same in the next call to f() as you set them in the previous call.
1140: .seealso: [](ch_ts), `TS`, `TSRHSJacobianFn`, `SNESComputeJacobianDefaultColor()`,
1141: `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()`, `TSRHSFunctionFn`, `TSIFunctionFn`
1142: @*/
1143: PetscErrorCode TSSetRHSJacobian(TS ts, Mat Amat, Mat Pmat, TSRHSJacobianFn *f, PetscCtx ctx)
1144: {
1145: SNES snes;
1146: DM dm;
1147: TSIJacobianFn *ijacobian;
1149: PetscFunctionBegin;
1153: if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1154: if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);
1156: PetscCall(TSGetDM(ts, &dm));
1157: PetscCall(DMTSSetRHSJacobian(dm, f, ctx));
1158: PetscCall(DMTSGetIJacobian(dm, &ijacobian, NULL));
1159: PetscCall(TSGetSNES(ts, &snes));
1160: if (!ijacobian) PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1161: if (Amat) {
1162: PetscCall(PetscObjectReference((PetscObject)Amat));
1163: PetscCall(MatDestroy(&ts->Arhs));
1164: ts->Arhs = Amat;
1165: }
1166: if (Pmat) {
1167: PetscCall(PetscObjectReference((PetscObject)Pmat));
1168: PetscCall(MatDestroy(&ts->Brhs));
1169: ts->Brhs = Pmat;
1170: }
1171: PetscFunctionReturn(PETSC_SUCCESS);
1172: }
1174: /*@C
1175: TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
1177: Logically Collective
1179: Input Parameters:
1180: + ts - the `TS` context obtained from `TSCreate()`
1181: . r - vector to hold the residual (or `NULL` to have it created internally)
1182: . f - the function evaluation routine
1183: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)
1185: Level: beginner
1187: Note:
1188: The user MUST call either this routine or `TSSetRHSFunction()` to define the ODE. When solving DAEs you must use this function.
1190: .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `TSSetRHSJacobian()`, `TSSetRHSFunction()`,
1191: `TSSetIJacobian()`
1192: @*/
1193: PetscErrorCode TSSetIFunction(TS ts, Vec r, TSIFunctionFn *f, PetscCtx ctx)
1194: {
1195: SNES snes;
1196: Vec ralloc = NULL;
1197: DM dm;
1199: PetscFunctionBegin;
1203: PetscCall(TSGetDM(ts, &dm));
1204: PetscCall(DMTSSetIFunction(dm, f, ctx));
1206: PetscCall(TSGetSNES(ts, &snes));
1207: if (!r && !ts->dm && ts->vec_sol) {
1208: PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1209: r = ralloc;
1210: }
1211: PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1212: PetscCall(VecDestroy(&ralloc));
1213: PetscFunctionReturn(PETSC_SUCCESS);
1214: }
1216: /*@C
1217: TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it.
1219: Not Collective
1221: Input Parameter:
1222: . ts - the `TS` context
1224: Output Parameters:
1225: + r - vector to hold residual (or `NULL`)
1226: . func - the function to compute residual (or `NULL`)
1227: - ctx - the function context (or `NULL`)
1229: Level: advanced
1231: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`
1232: @*/
1233: PetscErrorCode TSGetIFunction(TS ts, Vec *r, TSIFunctionFn **func, PetscCtxRt ctx)
1234: {
1235: SNES snes;
1236: DM dm;
1238: PetscFunctionBegin;
1240: PetscCall(TSGetSNES(ts, &snes));
1241: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1242: PetscCall(TSGetDM(ts, &dm));
1243: PetscCall(DMTSGetIFunction(dm, func, ctx));
1244: PetscFunctionReturn(PETSC_SUCCESS);
1245: }
1247: /*@C
1248: TSGetRHSFunction - Returns the vector where the right-hand side is stored and the function/context to compute it.
1250: Not Collective
1252: Input Parameter:
1253: . ts - the `TS` context
1255: Output Parameters:
1256: + r - vector to hold computed right-hand side (or `NULL`)
1257: . func - the function to compute right-hand side (or `NULL`)
1258: - ctx - the function context (or `NULL`)
1260: Level: advanced
1262: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `SNESGetFunction()`
1263: @*/
1264: PetscErrorCode TSGetRHSFunction(TS ts, Vec *r, TSRHSFunctionFn **func, PetscCtxRt ctx)
1265: {
1266: SNES snes;
1267: DM dm;
1269: PetscFunctionBegin;
1271: PetscCall(TSGetSNES(ts, &snes));
1272: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1273: PetscCall(TSGetDM(ts, &dm));
1274: PetscCall(DMTSGetRHSFunction(dm, func, ctx));
1275: PetscFunctionReturn(PETSC_SUCCESS);
1276: }
1278: /*@C
1279: TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1280: provided with `TSSetIFunction()`.
1282: Logically Collective
1284: Input Parameters:
1285: + ts - the `TS` context obtained from `TSCreate()`
1286: . Amat - (approximate) matrix to store Jacobian entries computed by `f`
1287: . Pmat - matrix used to compute preconditioner (usually the same as `Amat`)
1288: . f - the Jacobian evaluation routine
1289: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1291: Level: beginner
1293: Notes:
1294: The matrices `Amat` and `Pmat` are exactly the matrices that are used by `SNES` for the nonlinear solve.
1296: If you know the operator Amat has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
1297: space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
1299: The matrix dF/dU + a*dF/dU_t you provide turns out to be
1300: the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1301: The time integrator internally approximates U_t by W+a*U where the positive "shift"
1302: a and vector W depend on the integration method, step size, and past states. For example with
1303: the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1304: W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1306: You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1308: The TS solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f`
1309: You should not assume the values are the same in the next call to `f` as you set them in the previous call.
1311: In case `TSSetRHSJacobian()` is also used in conjunction with a fully-implicit solver,
1312: multilevel linear solvers, e.g. `PCMG`, will likely not work due to the way `TS` handles rhs matrices.
1314: .seealso: [](ch_ts), `TS`, `TSIJacobianFn`, `TSSetIFunction()`, `TSSetRHSJacobian()`,
1315: `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()`
1316: @*/
1317: PetscErrorCode TSSetIJacobian(TS ts, Mat Amat, Mat Pmat, TSIJacobianFn *f, PetscCtx ctx)
1318: {
1319: SNES snes;
1320: DM dm;
1322: PetscFunctionBegin;
1326: if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1327: if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);
1329: PetscCall(TSGetDM(ts, &dm));
1330: PetscCall(DMTSSetIJacobian(dm, f, ctx));
1332: PetscCall(TSGetSNES(ts, &snes));
1333: PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1334: PetscFunctionReturn(PETSC_SUCCESS);
1335: }
1337: /*@
1338: TSRHSJacobianSetReuse - restore the RHS Jacobian before calling the user-provided `TSRHSJacobianFn` function again
1340: Logically Collective
1342: Input Parameters:
1343: + ts - `TS` context obtained from `TSCreate()`
1344: - reuse - `PETSC_TRUE` if the RHS Jacobian
1346: Level: intermediate
1348: Notes:
1349: Without this flag, `TS` will change the sign and shift the RHS Jacobian for a
1350: finite-time-step implicit solve, in which case the user function will need to recompute the
1351: entire Jacobian. The `reuse `flag must be set if the evaluation function assumes that the
1352: matrix entries have not been changed by the `TS`.
1354: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
1355: @*/
1356: PetscErrorCode TSRHSJacobianSetReuse(TS ts, PetscBool reuse)
1357: {
1358: PetscFunctionBegin;
1359: ts->rhsjacobian.reuse = reuse;
1360: PetscFunctionReturn(PETSC_SUCCESS);
1361: }
1363: /*@C
1364: TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved.
1366: Logically Collective
1368: Input Parameters:
1369: + ts - the `TS` context obtained from `TSCreate()`
1370: . F - vector to hold the residual (or `NULL` to have it created internally)
1371: . fun - the function evaluation routine
1372: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)
1374: Level: beginner
1376: .seealso: [](ch_ts), `TS`, `TSI2FunctionFn`, `TSSetI2Jacobian()`, `TSSetIFunction()`,
1377: `TSCreate()`, `TSSetRHSFunction()`
1378: @*/
1379: PetscErrorCode TSSetI2Function(TS ts, Vec F, TSI2FunctionFn *fun, PetscCtx ctx)
1380: {
1381: DM dm;
1383: PetscFunctionBegin;
1386: PetscCall(TSSetIFunction(ts, F, NULL, NULL));
1387: PetscCall(TSGetDM(ts, &dm));
1388: PetscCall(DMTSSetI2Function(dm, fun, ctx));
1389: PetscFunctionReturn(PETSC_SUCCESS);
1390: }
1392: /*@C
1393: TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it.
1395: Not Collective
1397: Input Parameter:
1398: . ts - the `TS` context
1400: Output Parameters:
1401: + r - vector to hold residual (or `NULL`)
1402: . fun - the function to compute residual (or `NULL`)
1403: - ctx - the function context (or `NULL`)
1405: Level: advanced
1407: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()`
1408: @*/
1409: PetscErrorCode TSGetI2Function(TS ts, Vec *r, TSI2FunctionFn **fun, PetscCtxRt ctx)
1410: {
1411: SNES snes;
1412: DM dm;
1414: PetscFunctionBegin;
1416: PetscCall(TSGetSNES(ts, &snes));
1417: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1418: PetscCall(TSGetDM(ts, &dm));
1419: PetscCall(DMTSGetI2Function(dm, fun, ctx));
1420: PetscFunctionReturn(PETSC_SUCCESS);
1421: }
1423: /*@C
1424: TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t + a*dF/dU_tt
1425: where F(t,U,U_t,U_tt) is the function you provided with `TSSetI2Function()`.
1427: Logically Collective
1429: Input Parameters:
1430: + ts - the `TS` context obtained from `TSCreate()`
1431: . J - matrix to hold the Jacobian values
1432: . P - matrix for constructing the preconditioner (may be same as `J`)
1433: . jac - the Jacobian evaluation routine, see `TSI2JacobianFn` for the calling sequence
1434: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1436: Level: beginner
1438: Notes:
1439: The matrices `J` and `P` are exactly the matrices that are used by `SNES` for the nonlinear solve.
1441: The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be
1442: 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.
1443: The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U where the positive "shift"
1444: parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states.
1446: .seealso: [](ch_ts), `TS`, `TSI2JacobianFn`, `TSSetI2Function()`, `TSGetI2Jacobian()`
1447: @*/
1448: PetscErrorCode TSSetI2Jacobian(TS ts, Mat J, Mat P, TSI2JacobianFn *jac, PetscCtx ctx)
1449: {
1450: DM dm;
1452: PetscFunctionBegin;
1456: PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL));
1457: PetscCall(TSGetDM(ts, &dm));
1458: PetscCall(DMTSSetI2Jacobian(dm, jac, ctx));
1459: PetscFunctionReturn(PETSC_SUCCESS);
1460: }
1462: /*@C
1463: TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.
1465: Not Collective, but parallel objects are returned if `TS` is parallel
1467: Input Parameter:
1468: . ts - The `TS` context obtained from `TSCreate()`
1470: Output Parameters:
1471: + J - The (approximate) Jacobian of F(t,U,U_t,U_tt)
1472: . P - The matrix from which the preconditioner is constructed, often the same as `J`
1473: . jac - The function to compute the Jacobian matrices
1474: - ctx - User-defined context for Jacobian evaluation routine
1476: Level: advanced
1478: Note:
1479: You can pass in `NULL` for any return argument you do not need.
1481: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()`
1482: @*/
1483: PetscErrorCode TSGetI2Jacobian(TS ts, Mat *J, Mat *P, TSI2JacobianFn **jac, PetscCtxRt ctx)
1484: {
1485: SNES snes;
1486: DM dm;
1488: PetscFunctionBegin;
1489: PetscCall(TSGetSNES(ts, &snes));
1490: PetscCall(SNESSetUpMatrices(snes));
1491: PetscCall(SNESGetJacobian(snes, J, P, NULL, NULL));
1492: PetscCall(TSGetDM(ts, &dm));
1493: PetscCall(DMTSGetI2Jacobian(dm, jac, ctx));
1494: PetscFunctionReturn(PETSC_SUCCESS);
1495: }
1497: /*@
1498: TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0
1500: Collective
1502: Input Parameters:
1503: + ts - the `TS` context
1504: . t - current time
1505: . U - state vector
1506: . V - time derivative of state vector (U_t)
1507: - A - second time derivative of state vector (U_tt)
1509: Output Parameter:
1510: . F - the residual vector
1512: Level: developer
1514: Note:
1515: Most users should not need to explicitly call this routine, as it
1516: is used internally within the nonlinear solvers.
1518: .seealso: [](ch_ts), `TS`, `TSSetI2Function()`, `TSGetI2Function()`
1519: @*/
1520: PetscErrorCode TSComputeI2Function(TS ts, PetscReal t, Vec U, Vec V, Vec A, Vec F)
1521: {
1522: DM dm;
1523: TSI2FunctionFn *I2Function;
1524: void *ctx;
1525: TSRHSFunctionFn *rhsfunction;
1527: PetscFunctionBegin;
1534: PetscCall(TSGetDM(ts, &dm));
1535: PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx));
1536: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
1538: if (!I2Function) {
1539: PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE));
1540: PetscFunctionReturn(PETSC_SUCCESS);
1541: }
1543: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, V, F));
1545: PetscCallBack("TS callback implicit function", I2Function(ts, t, U, V, A, F, ctx));
1547: if (rhsfunction) {
1548: Vec Frhs;
1550: PetscCall(DMGetGlobalVector(dm, &Frhs));
1551: PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
1552: PetscCall(VecAXPY(F, -1, Frhs));
1553: PetscCall(DMRestoreGlobalVector(dm, &Frhs));
1554: }
1556: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F));
1557: PetscFunctionReturn(PETSC_SUCCESS);
1558: }
1560: /*@
1561: TSComputeI2Jacobian - Evaluates the Jacobian of the DAE
1563: Collective
1565: Input Parameters:
1566: + ts - the `TS` context
1567: . t - current timestep
1568: . U - state vector
1569: . V - time derivative of state vector
1570: . A - second time derivative of state vector
1571: . shiftV - shift to apply, see note below
1572: - shiftA - shift to apply, see note below
1574: Output Parameters:
1575: + J - Jacobian matrix
1576: - P - optional matrix used to construct the preconditioner
1578: Level: developer
1580: Notes:
1581: If $F(t,U,V,A) = 0$ is the DAE, the required Jacobian is
1583: $$
1584: dF/dU + shiftV*dF/dV + shiftA*dF/dA
1585: $$
1587: Most users should not need to explicitly call this routine, as it
1588: is used internally within the ODE integrators.
1590: .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()`
1591: @*/
1592: PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P)
1593: {
1594: DM dm;
1595: TSI2JacobianFn *I2Jacobian;
1596: void *ctx;
1597: TSRHSJacobianFn *rhsjacobian;
1599: PetscFunctionBegin;
1607: PetscCall(TSGetDM(ts, &dm));
1608: PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx));
1609: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));
1611: if (!I2Jacobian) {
1612: PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE));
1613: PetscFunctionReturn(PETSC_SUCCESS);
1614: }
1616: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P));
1617: PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx));
1618: if (rhsjacobian) {
1619: Mat Jrhs, Prhs;
1620: PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs));
1621: PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs));
1622: PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern));
1623: if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern));
1624: }
1626: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P));
1627: PetscFunctionReturn(PETSC_SUCCESS);
1628: }
1630: /*@C
1631: TSSetTransientVariable - sets function to transform from state to transient variables
1633: Logically Collective
1635: Input Parameters:
1636: + ts - time stepping context on which to change the transient variable
1637: . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
1638: - ctx - a context for tvar
1640: Level: advanced
1642: Notes:
1643: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
1644: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
1645: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
1646: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
1647: evaluated via the chain rule, as in
1648: .vb
1649: dF/dP + shift * dF/dCdot dC/dP.
1650: .ve
1652: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()`
1653: @*/
1654: PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, PetscCtx ctx)
1655: {
1656: DM dm;
1658: PetscFunctionBegin;
1660: PetscCall(TSGetDM(ts, &dm));
1661: PetscCall(DMTSSetTransientVariable(dm, tvar, ctx));
1662: PetscFunctionReturn(PETSC_SUCCESS);
1663: }
1665: /*@
1666: TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables
1668: Logically Collective
1670: Input Parameters:
1671: + ts - TS on which to compute
1672: - U - state vector to be transformed to transient variables
1674: Output Parameter:
1675: . C - transient (conservative) variable
1677: Level: developer
1679: Developer Notes:
1680: If `DMTSSetTransientVariable()` has not been called, then C is not modified in this routine and C = `NULL` is allowed.
1681: This makes it safe to call without a guard. One can use `TSHasTransientVariable()` to check if transient variables are
1682: being used.
1684: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()`
1685: @*/
1686: PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C)
1687: {
1688: DM dm;
1689: DMTS dmts;
1691: PetscFunctionBegin;
1694: PetscCall(TSGetDM(ts, &dm));
1695: PetscCall(DMGetDMTS(dm, &dmts));
1696: if (dmts->ops->transientvar) {
1698: PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx));
1699: }
1700: PetscFunctionReturn(PETSC_SUCCESS);
1701: }
1703: /*@
1704: TSHasTransientVariable - determine whether transient variables have been set
1706: Logically Collective
1708: Input Parameter:
1709: . ts - `TS` on which to compute
1711: Output Parameter:
1712: . has - `PETSC_TRUE` if transient variables have been set
1714: Level: developer
1716: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()`
1717: @*/
1718: PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has)
1719: {
1720: DM dm;
1721: DMTS dmts;
1723: PetscFunctionBegin;
1725: PetscCall(TSGetDM(ts, &dm));
1726: PetscCall(DMGetDMTS(dm, &dmts));
1727: *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE;
1728: PetscFunctionReturn(PETSC_SUCCESS);
1729: }
1731: /*@
1732: TS2SetSolution - Sets the initial solution and time derivative vectors
1733: for use by the `TS` routines handling second order equations.
1735: Logically Collective
1737: Input Parameters:
1738: + ts - the `TS` context obtained from `TSCreate()`
1739: . u - the solution vector
1740: - v - the time derivative vector
1742: Level: beginner
1744: .seealso: [](ch_ts), `TS`
1745: @*/
1746: PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v)
1747: {
1748: PetscFunctionBegin;
1752: PetscCall(TSSetSolution(ts, u));
1753: PetscCall(PetscObjectReference((PetscObject)v));
1754: PetscCall(VecDestroy(&ts->vec_dot));
1755: ts->vec_dot = v;
1756: PetscFunctionReturn(PETSC_SUCCESS);
1757: }
1759: /*@
1760: TS2GetSolution - Returns the solution and time derivative at the present timestep
1761: for second order equations.
1763: Not Collective
1765: Input Parameter:
1766: . ts - the `TS` context obtained from `TSCreate()`
1768: Output Parameters:
1769: + u - the vector containing the solution
1770: - v - the vector containing the time derivative
1772: Level: intermediate
1774: Notes:
1775: It is valid to call this routine inside the function
1776: that you are evaluating in order to move to the new timestep. This vector not
1777: changed until the solution at the next timestep has been calculated.
1779: .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()`
1780: @*/
1781: PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v)
1782: {
1783: PetscFunctionBegin;
1785: if (u) PetscAssertPointer(u, 2);
1786: if (v) PetscAssertPointer(v, 3);
1787: if (u) *u = ts->vec_sol;
1788: if (v) *v = ts->vec_dot;
1789: PetscFunctionReturn(PETSC_SUCCESS);
1790: }
1792: /*@
1793: TSLoad - Loads a `TS` that has been stored in binary with `TSView()`.
1795: Collective
1797: Input Parameters:
1798: + ts - the newly loaded `TS`, this needs to have been created with `TSCreate()` or
1799: some related function before a call to `TSLoad()`.
1800: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
1802: Level: intermediate
1804: Note:
1805: The type is determined by the data in the file, any type set into the `TS` before this call is ignored.
1807: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()`
1808: @*/
1809: PetscErrorCode TSLoad(TS ts, PetscViewer viewer)
1810: {
1811: PetscBool isbinary;
1812: PetscInt classid;
1813: char type[256];
1814: DMTS sdm;
1815: DM dm;
1817: PetscFunctionBegin;
1820: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1821: PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1823: PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
1824: PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file");
1825: PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
1826: PetscCall(TSSetType(ts, type));
1827: PetscTryTypeMethod(ts, load, viewer);
1828: PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm));
1829: PetscCall(DMLoad(dm, viewer));
1830: PetscCall(TSSetDM(ts, dm));
1831: PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
1832: PetscCall(VecLoad(ts->vec_sol, viewer));
1833: PetscCall(DMGetDMTS(ts->dm, &sdm));
1834: PetscCall(DMTSLoad(sdm, viewer));
1835: PetscFunctionReturn(PETSC_SUCCESS);
1836: }
1838: #include <petscdraw.h>
1839: #if defined(PETSC_HAVE_SAWS)
1840: #include <petscviewersaws.h>
1841: #endif
1843: /*@
1844: TSViewFromOptions - View a `TS` based on values in the options database
1846: Collective
1848: Input Parameters:
1849: + ts - the `TS` context
1850: . obj - Optional object that provides the prefix for the options database keys
1851: - name - command line option string to be passed by user
1853: Level: intermediate
1855: .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()`
1856: @*/
1857: PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[])
1858: {
1859: PetscFunctionBegin;
1861: PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name));
1862: PetscFunctionReturn(PETSC_SUCCESS);
1863: }
1865: /*@
1866: TSView - Prints the `TS` data structure.
1868: Collective
1870: Input Parameters:
1871: + ts - the `TS` context obtained from `TSCreate()`
1872: - viewer - visualization context
1874: Options Database Key:
1875: . -ts_view - calls `TSView()` at end of `TSStep()`
1877: Level: beginner
1879: Notes:
1880: The available visualization contexts include
1881: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1882: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1883: output where only the first processor opens
1884: the file. All other processors send their
1885: data to the first processor to print.
1887: The user can open an alternative visualization context with
1888: `PetscViewerASCIIOpen()` - output to a specified file.
1890: In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer).
1892: The "initial time step" displayed is the default time step from `TSCreate()` or that set with `TSSetTimeStep()` or `-ts_time_step`
1894: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()`
1895: @*/
1896: PetscErrorCode TSView(TS ts, PetscViewer viewer)
1897: {
1898: TSType type;
1899: PetscBool isascii, isstring, issundials, isbinary, isdraw;
1900: DMTS sdm;
1901: #if defined(PETSC_HAVE_SAWS)
1902: PetscBool issaws;
1903: #endif
1905: PetscFunctionBegin;
1907: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer));
1909: PetscCheckSameComm(ts, 1, viewer, 2);
1911: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1912: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1913: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1914: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1915: #if defined(PETSC_HAVE_SAWS)
1916: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1917: #endif
1918: if (isascii) {
1919: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer));
1920: if (ts->ops->view) {
1921: PetscCall(PetscViewerASCIIPushTab(viewer));
1922: PetscUseTypeMethod(ts, view, viewer);
1923: PetscCall(PetscViewerASCIIPopTab(viewer));
1924: }
1925: PetscCall(PetscViewerASCIIPrintf(viewer, " initial time step=%g\n", (double)ts->initial_time_step));
1926: if (ts->max_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum steps=%" PetscInt_FMT "\n", ts->max_steps));
1927: if (ts->run_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, " run steps=%" PetscInt_FMT "\n", ts->run_steps));
1928: if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum time=%g\n", (double)ts->max_time));
1929: if (ts->max_reject != PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum number of step rejections=%" PetscInt_FMT "\n", ts->max_reject));
1930: if (ts->max_snes_failures != PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum number of SNES failures allowed=%" PetscInt_FMT "\n", ts->max_snes_failures));
1931: if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs));
1932: if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs));
1933: if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs));
1934: if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs));
1935: if (ts->usessnes) {
1936: PetscBool lin;
1937: if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its));
1938: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its));
1939: PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
1940: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures));
1941: }
1942: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of rejected steps=%" PetscInt_FMT "\n", ts->reject));
1943: if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of relative error tolerances, "));
1944: else PetscCall(PetscViewerASCIIPrintf(viewer, " using relative error tolerance of %g, ", (double)ts->rtol));
1945: if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, "using vector of absolute error tolerances\n"));
1946: else PetscCall(PetscViewerASCIIPrintf(viewer, "using absolute error tolerance of %g\n", (double)ts->atol));
1947: PetscCall(PetscViewerASCIIPushTab(viewer));
1948: PetscCall(TSAdaptView(ts->adapt, viewer));
1949: PetscCall(PetscViewerASCIIPopTab(viewer));
1950: } else if (isstring) {
1951: PetscCall(TSGetType(ts, &type));
1952: PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type));
1953: PetscTryTypeMethod(ts, view, viewer);
1954: } else if (isbinary) {
1955: PetscInt classid = TS_FILE_CLASSID;
1956: MPI_Comm comm;
1957: PetscMPIInt rank;
1958: char type[256];
1960: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1961: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1962: if (rank == 0) {
1963: PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
1964: PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256));
1965: PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
1966: }
1967: PetscTryTypeMethod(ts, view, viewer);
1968: if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
1969: PetscCall(DMView(ts->dm, viewer));
1970: PetscCall(VecView(ts->vec_sol, viewer));
1971: PetscCall(DMGetDMTS(ts->dm, &sdm));
1972: PetscCall(DMTSView(sdm, viewer));
1973: } else if (isdraw) {
1974: PetscDraw draw;
1975: char str[36];
1976: PetscReal x, y, bottom, h;
1978: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1979: PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
1980: PetscCall(PetscStrncpy(str, "TS: ", sizeof(str)));
1981: PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str)));
1982: PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h));
1983: bottom = y - h;
1984: PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
1985: PetscTryTypeMethod(ts, view, viewer);
1986: if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
1987: if (ts->snes) PetscCall(SNESView(ts->snes, viewer));
1988: PetscCall(PetscDrawPopCurrentPoint(draw));
1989: #if defined(PETSC_HAVE_SAWS)
1990: } else if (issaws) {
1991: PetscMPIInt rank;
1992: const char *name;
1994: PetscCall(PetscObjectGetName((PetscObject)ts, &name));
1995: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1996: if (!((PetscObject)ts)->amsmem && rank == 0) {
1997: char dir[1024];
1999: PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer));
2000: PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name));
2001: PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT));
2002: PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name));
2003: PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE));
2004: }
2005: PetscTryTypeMethod(ts, view, viewer);
2006: #endif
2007: }
2008: if (ts->snes && ts->usessnes) {
2009: PetscCall(PetscViewerASCIIPushTab(viewer));
2010: PetscCall(SNESView(ts->snes, viewer));
2011: PetscCall(PetscViewerASCIIPopTab(viewer));
2012: }
2013: PetscCall(DMGetDMTS(ts->dm, &sdm));
2014: PetscCall(DMTSView(sdm, viewer));
2016: PetscCall(PetscViewerASCIIPushTab(viewer));
2017: PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &issundials));
2018: PetscCall(PetscViewerASCIIPopTab(viewer));
2019: PetscFunctionReturn(PETSC_SUCCESS);
2020: }
2022: /*@
2023: TSSetApplicationContext - Sets an optional user-defined context for the timesteppers that may be accessed, for example inside the user provided
2024: `TS` callbacks with `TSGetApplicationContext()`
2026: Logically Collective
2028: Input Parameters:
2029: + ts - the `TS` context obtained from `TSCreate()`
2030: - ctx - user context
2032: Level: intermediate
2034: Fortran Note:
2035: This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2036: function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TSGetApplicationContext()` for
2037: an example.
2039: .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()`
2040: @*/
2041: PetscErrorCode TSSetApplicationContext(TS ts, PetscCtx ctx)
2042: {
2043: PetscFunctionBegin;
2045: ts->ctx = ctx;
2046: PetscFunctionReturn(PETSC_SUCCESS);
2047: }
2049: /*@
2050: TSGetApplicationContext - Gets the user-defined context for the
2051: timestepper that was set with `TSSetApplicationContext()`
2053: Not Collective
2055: Input Parameter:
2056: . ts - the `TS` context obtained from `TSCreate()`
2058: Output Parameter:
2059: . ctx - a pointer to the user context
2061: Level: intermediate
2063: Fortran Notes:
2064: This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with
2065: .vb
2066: type(tUsertype), pointer :: ctx
2067: .ve
2069: .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()`
2070: @*/
2071: PetscErrorCode TSGetApplicationContext(TS ts, PetscCtxRt ctx)
2072: {
2073: PetscFunctionBegin;
2075: *(void **)ctx = ts->ctx;
2076: PetscFunctionReturn(PETSC_SUCCESS);
2077: }
2079: /*@
2080: TSGetStepNumber - Gets the number of time steps completed.
2082: Not Collective
2084: Input Parameter:
2085: . ts - the `TS` context obtained from `TSCreate()`
2087: Output Parameter:
2088: . steps - number of steps completed so far
2090: Level: intermediate
2092: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`
2093: @*/
2094: PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps)
2095: {
2096: PetscFunctionBegin;
2098: PetscAssertPointer(steps, 2);
2099: *steps = ts->steps;
2100: PetscFunctionReturn(PETSC_SUCCESS);
2101: }
2103: /*@
2104: TSSetStepNumber - Sets the number of steps completed.
2106: Logically Collective
2108: Input Parameters:
2109: + ts - the `TS` context
2110: - steps - number of steps completed so far
2112: Level: developer
2114: Note:
2115: For most uses of the `TS` solvers the user need not explicitly call
2116: `TSSetStepNumber()`, as the step counter is appropriately updated in
2117: `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to
2118: reinitialize timestepping by setting the step counter to zero (and time
2119: to the initial time) to solve a similar problem with different initial
2120: conditions or parameters. Other possible use case is to continue
2121: timestepping from a previously interrupted run in such a way that `TS`
2122: monitors will be called with a initial nonzero step counter.
2124: .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()`
2125: @*/
2126: PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps)
2127: {
2128: PetscFunctionBegin;
2131: PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative");
2132: ts->steps = steps;
2133: PetscFunctionReturn(PETSC_SUCCESS);
2134: }
2136: /*@
2137: TSSetTimeStep - Allows one to reset the timestep at any time.
2139: Logically Collective
2141: Input Parameters:
2142: + ts - the `TS` context obtained from `TSCreate()`
2143: - time_step - the size of the timestep
2145: Options Database Key:
2146: . -ts_time_step <dt> - provide the initial time step
2148: Level: intermediate
2150: Notes:
2151: This is only a suggestion, the actual initial time step used may differ
2153: If this is called after `TSSetUp()`, it will not change the initial time step value printed by `TSView()`
2155: .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()`
2156: @*/
2157: PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step)
2158: {
2159: PetscFunctionBegin;
2162: ts->time_step = time_step;
2163: if (ts->setupcalled == PETSC_FALSE) ts->initial_time_step = time_step;
2164: PetscFunctionReturn(PETSC_SUCCESS);
2165: }
2167: /*@
2168: TSSetExactFinalTime - Determines whether to adapt the final time step to
2169: match the exact final time, to interpolate the solution to the exact final time,
2170: or to just return at the final time `TS` computed (which may be slightly larger
2171: than the requested final time).
2173: Logically Collective
2175: Input Parameters:
2176: + ts - the time-step context
2177: - eftopt - exact final time option
2178: .vb
2179: TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded, just use it
2180: TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded
2181: TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to ensure the computed final time exactly equals the requested final time
2182: .ve
2184: Options Database Key:
2185: . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime
2187: Level: beginner
2189: Note:
2190: If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time
2191: then the final time you selected.
2193: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()`
2194: @*/
2195: PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt)
2196: {
2197: PetscFunctionBegin;
2200: ts->exact_final_time = eftopt;
2201: PetscFunctionReturn(PETSC_SUCCESS);
2202: }
2204: /*@
2205: TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()`
2207: Not Collective
2209: Input Parameter:
2210: . ts - the `TS` context
2212: Output Parameter:
2213: . eftopt - exact final time option
2215: Level: beginner
2217: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()`
2218: @*/
2219: PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt)
2220: {
2221: PetscFunctionBegin;
2223: PetscAssertPointer(eftopt, 2);
2224: *eftopt = ts->exact_final_time;
2225: PetscFunctionReturn(PETSC_SUCCESS);
2226: }
2228: /*@
2229: TSGetTimeStep - Gets the current timestep size.
2231: Not Collective
2233: Input Parameter:
2234: . ts - the `TS` context obtained from `TSCreate()`
2236: Output Parameter:
2237: . dt - the current timestep size
2239: Level: intermediate
2241: .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()`
2242: @*/
2243: PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt)
2244: {
2245: PetscFunctionBegin;
2247: PetscAssertPointer(dt, 2);
2248: *dt = ts->time_step;
2249: PetscFunctionReturn(PETSC_SUCCESS);
2250: }
2252: /*@
2253: TSGetSolution - Returns the solution at the present timestep. It
2254: is valid to call this routine inside the function that you are evaluating
2255: in order to move to the new timestep. This vector not changed until
2256: the solution at the next timestep has been calculated.
2258: Not Collective, but v returned is parallel if ts is parallel
2260: Input Parameter:
2261: . ts - the `TS` context obtained from `TSCreate()`
2263: Output Parameter:
2264: . v - the vector containing the solution
2266: Level: intermediate
2268: Note:
2269: If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested
2270: final time. It returns the solution at the next timestep.
2272: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()`
2273: @*/
2274: PetscErrorCode TSGetSolution(TS ts, Vec *v)
2275: {
2276: PetscFunctionBegin;
2278: PetscAssertPointer(v, 2);
2279: *v = ts->vec_sol;
2280: PetscFunctionReturn(PETSC_SUCCESS);
2281: }
2283: /*@
2284: TSGetSolutionComponents - Returns any solution components at the present
2285: timestep, if available for the time integration method being used.
2286: Solution components are quantities that share the same size and
2287: structure as the solution vector.
2289: Not Collective, but v returned is parallel if ts is parallel
2291: Input Parameters:
2292: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2293: . n - If v is `NULL`, then the number of solution components is
2294: returned through n, else the n-th solution component is
2295: returned in v.
2296: - v - the vector containing the n-th solution component
2297: (may be `NULL` to use this function to find out
2298: the number of solutions components).
2300: Level: advanced
2302: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2303: @*/
2304: PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v)
2305: {
2306: PetscFunctionBegin;
2308: if (!ts->ops->getsolutioncomponents) *n = 0;
2309: else PetscUseTypeMethod(ts, getsolutioncomponents, n, v);
2310: PetscFunctionReturn(PETSC_SUCCESS);
2311: }
2313: /*@
2314: TSGetAuxSolution - Returns an auxiliary solution at the present
2315: timestep, if available for the time integration method being used.
2317: Not Collective, but v returned is parallel if ts is parallel
2319: Input Parameters:
2320: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2321: - v - the vector containing the auxiliary solution
2323: Level: intermediate
2325: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2326: @*/
2327: PetscErrorCode TSGetAuxSolution(TS ts, Vec *v)
2328: {
2329: PetscFunctionBegin;
2331: if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v);
2332: else PetscCall(VecZeroEntries(*v));
2333: PetscFunctionReturn(PETSC_SUCCESS);
2334: }
2336: /*@
2337: TSGetTimeError - Returns the estimated error vector, if the chosen
2338: `TSType` has an error estimation functionality and `TSSetTimeError()` was called
2340: Not Collective, but v returned is parallel if ts is parallel
2342: Input Parameters:
2343: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2344: . n - current estimate (n=0) or previous one (n=-1)
2345: - v - the vector containing the error (same size as the solution).
2347: Level: intermediate
2349: Note:
2350: MUST call after `TSSetUp()`
2352: .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()`
2353: @*/
2354: PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v)
2355: {
2356: PetscFunctionBegin;
2358: if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v);
2359: else PetscCall(VecZeroEntries(*v));
2360: PetscFunctionReturn(PETSC_SUCCESS);
2361: }
2363: /*@
2364: TSSetTimeError - Sets the estimated error vector, if the chosen
2365: `TSType` has an error estimation functionality. This can be used
2366: to restart such a time integrator with a given error vector.
2368: Not Collective, but v returned is parallel if ts is parallel
2370: Input Parameters:
2371: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2372: - v - the vector containing the error (same size as the solution).
2374: Level: intermediate
2376: .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()`
2377: @*/
2378: PetscErrorCode TSSetTimeError(TS ts, Vec v)
2379: {
2380: PetscFunctionBegin;
2382: PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first");
2383: PetscTryTypeMethod(ts, settimeerror, v);
2384: PetscFunctionReturn(PETSC_SUCCESS);
2385: }
2387: /* ----- Routines to initialize and destroy a timestepper ---- */
2388: /*@
2389: TSSetProblemType - Sets the type of problem to be solved.
2391: Not collective
2393: Input Parameters:
2394: + ts - The `TS`
2395: - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2396: .vb
2397: U_t - A U = 0 (linear)
2398: U_t - A(t) U = 0 (linear)
2399: F(t,U,U_t) = 0 (nonlinear)
2400: .ve
2402: Level: beginner
2404: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2405: @*/
2406: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
2407: {
2408: PetscFunctionBegin;
2410: ts->problem_type = type;
2411: if (type == TS_LINEAR) {
2412: SNES snes;
2413: PetscCall(TSGetSNES(ts, &snes));
2414: PetscCall(SNESSetType(snes, SNESKSPONLY));
2415: }
2416: PetscFunctionReturn(PETSC_SUCCESS);
2417: }
2419: /*@
2420: TSGetProblemType - Gets the type of problem to be solved.
2422: Not collective
2424: Input Parameter:
2425: . ts - The `TS`
2427: Output Parameter:
2428: . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2429: .vb
2430: M U_t = A U
2431: M(t) U_t = A(t) U
2432: F(t,U,U_t)
2433: .ve
2435: Level: beginner
2437: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2438: @*/
2439: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
2440: {
2441: PetscFunctionBegin;
2443: PetscAssertPointer(type, 2);
2444: *type = ts->problem_type;
2445: PetscFunctionReturn(PETSC_SUCCESS);
2446: }
2448: /*
2449: Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
2450: */
2451: static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
2452: {
2453: PetscBool isnone;
2455: PetscFunctionBegin;
2456: PetscCall(TSGetAdapt(ts, &ts->adapt));
2457: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2459: PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone));
2460: if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2461: else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
2462: PetscFunctionReturn(PETSC_SUCCESS);
2463: }
2465: /*@
2466: TSSetUp - Sets up the internal data structures for the later use of a timestepper.
2468: Collective
2470: Input Parameter:
2471: . ts - the `TS` context obtained from `TSCreate()`
2473: Level: advanced
2475: Note:
2476: For basic use of the `TS` solvers the user need not explicitly call
2477: `TSSetUp()`, since these actions will automatically occur during
2478: the call to `TSStep()` or `TSSolve()`. However, if one wishes to control this
2479: phase separately, `TSSetUp()` should be called after `TSCreate()`
2480: and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`.
2482: .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()`
2483: @*/
2484: PetscErrorCode TSSetUp(TS ts)
2485: {
2486: DM dm;
2487: PetscErrorCode (*func)(SNES, Vec, Vec, void *);
2488: PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
2489: TSIFunctionFn *ifun;
2490: TSIJacobianFn *ijac;
2491: TSI2JacobianFn *i2jac;
2492: TSRHSJacobianFn *rhsjac;
2494: PetscFunctionBegin;
2496: if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
2498: if (!((PetscObject)ts)->type_name) {
2499: PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
2500: PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER));
2501: }
2503: if (!ts->vec_sol) {
2504: PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first");
2505: PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
2506: }
2508: if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
2509: PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
2510: ts->Jacp = ts->Jacprhs;
2511: }
2513: if (ts->quadraturets) {
2514: PetscCall(TSSetUp(ts->quadraturets));
2515: PetscCall(VecDestroy(&ts->vec_costintegrand));
2516: PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand));
2517: }
2519: PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL));
2520: if (rhsjac == TSComputeRHSJacobianConstant) {
2521: Mat Amat, Pmat;
2522: SNES snes;
2523: PetscCall(TSGetSNES(ts, &snes));
2524: PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL));
2525: /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2526: * have displaced the RHS matrix */
2527: if (Amat && Amat == ts->Arhs) {
2528: /* 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 */
2529: PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat));
2530: PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL));
2531: PetscCall(MatDestroy(&Amat));
2532: }
2533: if (Pmat && Pmat == ts->Brhs) {
2534: PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat));
2535: PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL));
2536: PetscCall(MatDestroy(&Pmat));
2537: }
2538: }
2540: PetscCall(TSGetAdapt(ts, &ts->adapt));
2541: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2543: PetscTryTypeMethod(ts, setup);
2545: PetscCall(TSSetExactFinalTimeDefault(ts));
2547: /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2548: to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2549: */
2550: PetscCall(TSGetDM(ts, &dm));
2551: PetscCall(DMSNESGetFunction(dm, &func, NULL));
2552: if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts));
2554: /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2555: Otherwise, the SNES will use coloring internally to form the Jacobian.
2556: */
2557: PetscCall(DMSNESGetJacobian(dm, &jac, NULL));
2558: PetscCall(DMTSGetIJacobian(dm, &ijac, NULL));
2559: PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL));
2560: PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL));
2561: if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts));
2563: /* if time integration scheme has a starting method, call it */
2564: PetscTryTypeMethod(ts, startingmethod);
2566: ts->setupcalled = PETSC_TRUE;
2567: PetscFunctionReturn(PETSC_SUCCESS);
2568: }
2570: /*@
2571: TSReset - Resets a `TS` context to the state it was in before `TSSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures
2573: Collective
2575: Input Parameter:
2576: . ts - the `TS` context obtained from `TSCreate()`
2578: Level: developer
2580: Notes:
2581: Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain.
2583: See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration.
2585: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSetResize()`
2586: @*/
2587: PetscErrorCode TSReset(TS ts)
2588: {
2589: TS_RHSSplitLink ilink = ts->tsrhssplit, next;
2591: PetscFunctionBegin;
2594: PetscTryTypeMethod(ts, reset);
2595: if (ts->snes) PetscCall(SNESReset(ts->snes));
2596: if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));
2598: PetscCall(MatDestroy(&ts->Arhs));
2599: PetscCall(MatDestroy(&ts->Brhs));
2600: PetscCall(VecDestroy(&ts->Frhs));
2601: PetscCall(VecDestroy(&ts->vec_sol));
2602: PetscCall(VecDestroy(&ts->vec_sol0));
2603: PetscCall(VecDestroy(&ts->vec_dot));
2604: PetscCall(VecDestroy(&ts->vatol));
2605: PetscCall(VecDestroy(&ts->vrtol));
2606: PetscCall(VecDestroyVecs(ts->nwork, &ts->work));
2608: PetscCall(MatDestroy(&ts->Jacprhs));
2609: PetscCall(MatDestroy(&ts->Jacp));
2610: if (ts->forward_solve) PetscCall(TSForwardReset(ts));
2611: if (ts->quadraturets) {
2612: PetscCall(TSReset(ts->quadraturets));
2613: PetscCall(VecDestroy(&ts->vec_costintegrand));
2614: }
2615: while (ilink) {
2616: next = ilink->next;
2617: PetscCall(TSDestroy(&ilink->ts));
2618: PetscCall(PetscFree(ilink->splitname));
2619: PetscCall(ISDestroy(&ilink->is));
2620: PetscCall(PetscFree(ilink));
2621: ilink = next;
2622: }
2623: ts->tsrhssplit = NULL;
2624: ts->num_rhs_splits = 0;
2625: if (ts->eval_times) {
2626: PetscCall(PetscFree(ts->eval_times->time_points));
2627: PetscCall(PetscFree(ts->eval_times->sol_times));
2628: PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
2629: PetscCall(PetscFree(ts->eval_times));
2630: }
2631: ts->rhsjacobian.time = PETSC_MIN_REAL;
2632: ts->rhsjacobian.scale = 1.0;
2633: ts->ijacobian.shift = 1.0;
2634: ts->setupcalled = PETSC_FALSE;
2635: PetscFunctionReturn(PETSC_SUCCESS);
2636: }
2638: static PetscErrorCode TSResizeReset(TS);
2640: /*@
2641: TSDestroy - Destroys the timestepper context that was created
2642: with `TSCreate()`.
2644: Collective
2646: Input Parameter:
2647: . ts - the `TS` context obtained from `TSCreate()`
2649: Level: beginner
2651: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2652: @*/
2653: PetscErrorCode TSDestroy(TS *ts)
2654: {
2655: PetscFunctionBegin;
2656: if (!*ts) PetscFunctionReturn(PETSC_SUCCESS);
2658: if (--((PetscObject)*ts)->refct > 0) {
2659: *ts = NULL;
2660: PetscFunctionReturn(PETSC_SUCCESS);
2661: }
2663: PetscCall(TSReset(*ts));
2664: PetscCall(TSAdjointReset(*ts));
2665: if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts));
2666: PetscCall(TSResizeReset(*ts));
2668: /* if memory was published with SAWs then destroy it */
2669: PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
2670: PetscTryTypeMethod(*ts, destroy);
2672: PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory));
2674: PetscCall(TSAdaptDestroy(&(*ts)->adapt));
2675: PetscCall(TSEventDestroy(&(*ts)->event));
2677: PetscCall(SNESDestroy(&(*ts)->snes));
2678: PetscCall(SNESDestroy(&(*ts)->snesrhssplit));
2679: PetscCall(DMDestroy(&(*ts)->dm));
2680: PetscCall(TSMonitorCancel(*ts));
2681: PetscCall(TSAdjointMonitorCancel(*ts));
2683: PetscCall(TSDestroy(&(*ts)->quadraturets));
2684: PetscCall(PetscHeaderDestroy(ts));
2685: PetscFunctionReturn(PETSC_SUCCESS);
2686: }
2688: /*@
2689: TSGetSNES - Returns the `SNES` (nonlinear solver) associated with
2690: a `TS` (timestepper) context. Valid only for nonlinear problems.
2692: Not Collective, but snes is parallel if ts is parallel
2694: Input Parameter:
2695: . ts - the `TS` context obtained from `TSCreate()`
2697: Output Parameter:
2698: . snes - the nonlinear solver context
2700: Level: beginner
2702: Notes:
2703: The user can then directly manipulate the `SNES` context to set various
2704: options, etc. Likewise, the user can then extract and manipulate the
2705: `KSP`, and `PC` contexts as well.
2707: `TSGetSNES()` does not work for integrators that do not use `SNES`; in
2708: this case `TSGetSNES()` returns `NULL` in `snes`.
2710: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2711: @*/
2712: PetscErrorCode TSGetSNES(TS ts, SNES *snes)
2713: {
2714: PetscFunctionBegin;
2716: PetscAssertPointer(snes, 2);
2717: if (!ts->snes) {
2718: PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes));
2719: PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options));
2720: PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2721: PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
2722: if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
2723: if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
2724: }
2725: *snes = ts->snes;
2726: PetscFunctionReturn(PETSC_SUCCESS);
2727: }
2729: /*@
2730: TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context
2732: Collective
2734: Input Parameters:
2735: + ts - the `TS` context obtained from `TSCreate()`
2736: - snes - the nonlinear solver context
2738: Level: developer
2740: Note:
2741: Most users should have the `TS` created by calling `TSGetSNES()`
2743: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2744: @*/
2745: PetscErrorCode TSSetSNES(TS ts, SNES snes)
2746: {
2747: PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
2749: PetscFunctionBegin;
2752: PetscCall(PetscObjectReference((PetscObject)snes));
2753: PetscCall(SNESDestroy(&ts->snes));
2755: ts->snes = snes;
2757: PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2758: PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
2759: if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
2760: PetscFunctionReturn(PETSC_SUCCESS);
2761: }
2763: /*@
2764: TSGetKSP - Returns the `KSP` (linear solver) associated with
2765: a `TS` (timestepper) context.
2767: Not Collective, but `ksp` is parallel if `ts` is parallel
2769: Input Parameter:
2770: . ts - the `TS` context obtained from `TSCreate()`
2772: Output Parameter:
2773: . ksp - the nonlinear solver context
2775: Level: beginner
2777: Notes:
2778: The user can then directly manipulate the `KSP` context to set various
2779: options, etc. Likewise, the user can then extract and manipulate the
2780: `PC` context as well.
2782: `TSGetKSP()` does not work for integrators that do not use `KSP`;
2783: in this case `TSGetKSP()` returns `NULL` in `ksp`.
2785: .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2786: @*/
2787: PetscErrorCode TSGetKSP(TS ts, KSP *ksp)
2788: {
2789: SNES snes;
2791: PetscFunctionBegin;
2793: PetscAssertPointer(ksp, 2);
2794: PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
2795: PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()");
2796: PetscCall(TSGetSNES(ts, &snes));
2797: PetscCall(SNESGetKSP(snes, ksp));
2798: PetscFunctionReturn(PETSC_SUCCESS);
2799: }
2801: /* ----------- Routines to set solver parameters ---------- */
2803: /*@
2804: TSSetMaxSteps - Sets the maximum number of steps to use.
2806: Logically Collective
2808: Input Parameters:
2809: + ts - the `TS` context obtained from `TSCreate()`
2810: - maxsteps - maximum number of steps to use
2812: Options Database Key:
2813: . -ts_max_steps <maxsteps> - Sets maxsteps
2815: Level: intermediate
2817: Note:
2818: Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set
2820: The default maximum number of steps is 5,000
2822: Fortran Note:
2823: Use `PETSC_DETERMINE_INTEGER`
2825: .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
2826: @*/
2827: PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps)
2828: {
2829: PetscFunctionBegin;
2832: if (maxsteps == PETSC_DETERMINE) {
2833: ts->max_steps = ts->default_max_steps;
2834: } else {
2835: PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
2836: ts->max_steps = maxsteps;
2837: }
2838: PetscFunctionReturn(PETSC_SUCCESS);
2839: }
2841: /*@
2842: TSGetMaxSteps - Gets the maximum number of steps to use.
2844: Not Collective
2846: Input Parameter:
2847: . ts - the `TS` context obtained from `TSCreate()`
2849: Output Parameter:
2850: . maxsteps - maximum number of steps to use
2852: Level: advanced
2854: .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
2855: @*/
2856: PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps)
2857: {
2858: PetscFunctionBegin;
2860: PetscAssertPointer(maxsteps, 2);
2861: *maxsteps = ts->max_steps;
2862: PetscFunctionReturn(PETSC_SUCCESS);
2863: }
2865: /*@
2866: TSSetRunSteps - Sets the maximum number of steps to take in each call to `TSSolve()`.
2868: If the step count when `TSSolve()` is `start_step`, this will stop the simulation once `current_step - start_step >= run_steps`.
2869: Comparatively, `TSSetMaxSteps()` will stop if `current_step >= max_steps`.
2870: The simulation will stop when either condition is reached.
2872: Logically Collective
2874: Input Parameters:
2875: + ts - the `TS` context obtained from `TSCreate()`
2876: - runsteps - maximum number of steps to take in each call to `TSSolve()`;
2878: Options Database Key:
2879: . -ts_run_steps <runsteps> - Sets runsteps
2881: Level: intermediate
2883: Note:
2884: The default is `PETSC_UNLIMITED`
2886: .seealso: [](ch_ts), `TS`, `TSGetRunSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`, `TSSetMaxSteps()`
2887: @*/
2888: PetscErrorCode TSSetRunSteps(TS ts, PetscInt runsteps)
2889: {
2890: PetscFunctionBegin;
2893: if (runsteps == PETSC_DETERMINE) {
2894: ts->run_steps = PETSC_UNLIMITED;
2895: } else {
2896: PetscCheck(runsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Max number of steps to take in each call to TSSolve must be non-negative");
2897: ts->run_steps = runsteps;
2898: }
2899: PetscFunctionReturn(PETSC_SUCCESS);
2900: }
2902: /*@
2903: TSGetRunSteps - Gets the maximum number of steps to take in each call to `TSSolve()`.
2905: Not Collective
2907: Input Parameter:
2908: . ts - the `TS` context obtained from `TSCreate()`
2910: Output Parameter:
2911: . runsteps - maximum number of steps to take in each call to `TSSolve`.
2913: Level: advanced
2915: .seealso: [](ch_ts), `TS`, `TSSetRunSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`, `TSGetMaxSteps()`
2916: @*/
2917: PetscErrorCode TSGetRunSteps(TS ts, PetscInt *runsteps)
2918: {
2919: PetscFunctionBegin;
2921: PetscAssertPointer(runsteps, 2);
2922: *runsteps = ts->run_steps;
2923: PetscFunctionReturn(PETSC_SUCCESS);
2924: }
2926: /*@
2927: TSSetMaxTime - Sets the maximum (or final) time for timestepping.
2929: Logically Collective
2931: Input Parameters:
2932: + ts - the `TS` context obtained from `TSCreate()`
2933: - maxtime - final time to step to
2935: Options Database Key:
2936: . -ts_max_time <maxtime> - Sets maxtime
2938: Level: intermediate
2940: Notes:
2941: Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set
2943: The default maximum time is 5.0
2945: Fortran Note:
2946: Use `PETSC_DETERMINE_REAL`
2948: .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
2949: @*/
2950: PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime)
2951: {
2952: PetscFunctionBegin;
2955: if (maxtime == PETSC_DETERMINE) {
2956: ts->max_time = ts->default_max_time;
2957: } else {
2958: ts->max_time = maxtime;
2959: }
2960: PetscFunctionReturn(PETSC_SUCCESS);
2961: }
2963: /*@
2964: TSGetMaxTime - Gets the maximum (or final) time for timestepping.
2966: Not Collective
2968: Input Parameter:
2969: . ts - the `TS` context obtained from `TSCreate()`
2971: Output Parameter:
2972: . maxtime - final time to step to
2974: Level: advanced
2976: .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
2977: @*/
2978: PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime)
2979: {
2980: PetscFunctionBegin;
2982: PetscAssertPointer(maxtime, 2);
2983: *maxtime = ts->max_time;
2984: PetscFunctionReturn(PETSC_SUCCESS);
2985: }
2987: // PetscClangLinter pragma disable: -fdoc-*
2988: /*@
2989: TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`.
2991: Level: deprecated
2993: @*/
2994: PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step)
2995: {
2996: PetscFunctionBegin;
2998: PetscCall(TSSetTime(ts, initial_time));
2999: PetscCall(TSSetTimeStep(ts, time_step));
3000: PetscFunctionReturn(PETSC_SUCCESS);
3001: }
3003: // PetscClangLinter pragma disable: -fdoc-*
3004: /*@
3005: TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`.
3007: Level: deprecated
3009: @*/
3010: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
3011: {
3012: PetscFunctionBegin;
3014: if (maxsteps) {
3015: PetscAssertPointer(maxsteps, 2);
3016: *maxsteps = ts->max_steps;
3017: }
3018: if (maxtime) {
3019: PetscAssertPointer(maxtime, 3);
3020: *maxtime = ts->max_time;
3021: }
3022: PetscFunctionReturn(PETSC_SUCCESS);
3023: }
3025: // PetscClangLinter pragma disable: -fdoc-*
3026: /*@
3027: TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`.
3029: Level: deprecated
3031: @*/
3032: PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime)
3033: {
3034: PetscFunctionBegin;
3035: if (maxsteps != PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps));
3036: if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime));
3037: PetscFunctionReturn(PETSC_SUCCESS);
3038: }
3040: // PetscClangLinter pragma disable: -fdoc-*
3041: /*@
3042: TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`.
3044: Level: deprecated
3046: @*/
3047: PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps)
3048: {
3049: return TSGetStepNumber(ts, steps);
3050: }
3052: // PetscClangLinter pragma disable: -fdoc-*
3053: /*@
3054: TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`.
3056: Level: deprecated
3058: @*/
3059: PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps)
3060: {
3061: return TSGetStepNumber(ts, steps);
3062: }
3064: /*@
3065: TSSetSolution - Sets the initial solution vector
3066: for use by the `TS` routines.
3068: Logically Collective
3070: Input Parameters:
3071: + ts - the `TS` context obtained from `TSCreate()`
3072: - u - the solution vector
3074: Level: beginner
3076: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
3077: @*/
3078: PetscErrorCode TSSetSolution(TS ts, Vec u)
3079: {
3080: DM dm;
3082: PetscFunctionBegin;
3085: PetscCall(PetscObjectReference((PetscObject)u));
3086: PetscCall(VecDestroy(&ts->vec_sol));
3087: ts->vec_sol = u;
3089: PetscCall(TSGetDM(ts, &dm));
3090: PetscCall(DMShellSetGlobalVector(dm, u));
3091: PetscFunctionReturn(PETSC_SUCCESS);
3092: }
3094: /*@C
3095: TSSetPreStep - Sets the general-purpose function
3096: called once at the beginning of each time step.
3098: Logically Collective
3100: Input Parameters:
3101: + ts - The `TS` context obtained from `TSCreate()`
3102: - func - The function
3104: Calling sequence of `func`:
3105: . ts - the `TS` context
3107: Level: intermediate
3109: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
3110: @*/
3111: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts))
3112: {
3113: PetscFunctionBegin;
3115: ts->prestep = func;
3116: PetscFunctionReturn(PETSC_SUCCESS);
3117: }
3119: /*@
3120: TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()`
3122: Collective
3124: Input Parameter:
3125: . ts - The `TS` context obtained from `TSCreate()`
3127: Level: developer
3129: Note:
3130: `TSPreStep()` is typically used within time stepping implementations,
3131: so most users would not generally call this routine themselves.
3133: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
3134: @*/
3135: PetscErrorCode TSPreStep(TS ts)
3136: {
3137: PetscFunctionBegin;
3139: if (ts->prestep) {
3140: Vec U;
3141: PetscObjectId idprev;
3142: PetscBool sameObject;
3143: PetscObjectState sprev, spost;
3145: PetscCall(TSGetSolution(ts, &U));
3146: PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3147: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3148: PetscCallBack("TS callback preset", (*ts->prestep)(ts));
3149: PetscCall(TSGetSolution(ts, &U));
3150: PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3151: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3152: if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3153: }
3154: PetscFunctionReturn(PETSC_SUCCESS);
3155: }
3157: /*@C
3158: TSSetPreStage - Sets the general-purpose function
3159: called once at the beginning of each stage.
3161: Logically Collective
3163: Input Parameters:
3164: + ts - The `TS` context obtained from `TSCreate()`
3165: - func - The function
3167: Calling sequence of `func`:
3168: + ts - the `TS` context
3169: - stagetime - the stage time
3171: Level: intermediate
3173: Note:
3174: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3175: The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3176: attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3178: .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3179: @*/
3180: PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime))
3181: {
3182: PetscFunctionBegin;
3184: ts->prestage = func;
3185: PetscFunctionReturn(PETSC_SUCCESS);
3186: }
3188: /*@C
3189: TSSetPostStage - Sets the general-purpose function
3190: called once at the end of each stage.
3192: Logically Collective
3194: Input Parameters:
3195: + ts - The `TS` context obtained from `TSCreate()`
3196: - func - The function
3198: Calling sequence of `func`:
3199: + ts - the `TS` context
3200: . stagetime - the stage time
3201: . stageindex - the stage index
3202: - Y - Array of vectors (of size = total number of stages) with the stage solutions
3204: Level: intermediate
3206: Note:
3207: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3208: The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3209: attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3211: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3212: @*/
3213: PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y))
3214: {
3215: PetscFunctionBegin;
3217: ts->poststage = func;
3218: PetscFunctionReturn(PETSC_SUCCESS);
3219: }
3221: /*@C
3222: TSSetPostEvaluate - Sets the general-purpose function
3223: called at the end of each step evaluation.
3225: Logically Collective
3227: Input Parameters:
3228: + ts - The `TS` context obtained from `TSCreate()`
3229: - func - The function
3231: Calling sequence of `func`:
3232: . ts - the `TS` context
3234: Level: intermediate
3236: Note:
3237: The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback.
3238: Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be.
3239: The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`.
3240: The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`,
3241: but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below
3242: .vb
3243: ...
3244: Step()
3245: PostEvaluate()
3246: EventHandling()
3247: step_rollback ? PostEvaluate() : PostStep()
3248: ...
3249: .ve
3250: where EventHandling() may result in one of the following three outcomes
3251: .vb
3252: (1) | successful step | solution intact
3253: (2) | successful step | solution modified by `postevent()`
3254: (3) | step_rollback | solution rolled back
3255: .ve
3257: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3258: @*/
3259: PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts))
3260: {
3261: PetscFunctionBegin;
3263: ts->postevaluate = func;
3264: PetscFunctionReturn(PETSC_SUCCESS);
3265: }
3267: /*@
3268: TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()`
3270: Collective
3272: Input Parameters:
3273: + ts - The `TS` context obtained from `TSCreate()`
3274: - stagetime - The absolute time of the current stage
3276: Level: developer
3278: Note:
3279: `TSPreStage()` is typically used within time stepping implementations,
3280: most users would not generally call this routine themselves.
3282: .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3283: @*/
3284: PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
3285: {
3286: PetscFunctionBegin;
3288: if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
3289: PetscFunctionReturn(PETSC_SUCCESS);
3290: }
3292: /*@
3293: TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()`
3295: Collective
3297: Input Parameters:
3298: + ts - The `TS` context obtained from `TSCreate()`
3299: . stagetime - The absolute time of the current stage
3300: . stageindex - Stage number
3301: - Y - Array of vectors (of size = total number of stages) with the stage solutions
3303: Level: developer
3305: Note:
3306: `TSPostStage()` is typically used within time stepping implementations,
3307: most users would not generally call this routine themselves.
3309: .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3310: @*/
3311: PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec Y[])
3312: {
3313: PetscFunctionBegin;
3315: if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
3316: PetscFunctionReturn(PETSC_SUCCESS);
3317: }
3319: /*@
3320: TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()`
3322: Collective
3324: Input Parameter:
3325: . ts - The `TS` context obtained from `TSCreate()`
3327: Level: developer
3329: Note:
3330: `TSPostEvaluate()` is typically used within time stepping implementations,
3331: most users would not generally call this routine themselves.
3333: .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3334: @*/
3335: PetscErrorCode TSPostEvaluate(TS ts)
3336: {
3337: PetscFunctionBegin;
3339: if (ts->postevaluate) {
3340: Vec U;
3341: PetscObjectState sprev, spost;
3343: PetscCall(TSGetSolution(ts, &U));
3344: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3345: PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
3346: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3347: if (sprev != spost) PetscCall(TSRestartStep(ts));
3348: }
3349: PetscFunctionReturn(PETSC_SUCCESS);
3350: }
3352: /*@C
3353: TSSetPostStep - Sets the general-purpose function
3354: called once at the end of each successful time step.
3356: Logically Collective
3358: Input Parameters:
3359: + ts - The `TS` context obtained from `TSCreate()`
3360: - func - The function
3362: Calling sequence of `func`:
3363: . ts - the `TS` context
3365: Level: intermediate
3367: Note:
3368: The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the
3369: given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will
3370: contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback.
3371: The scheme of the relevant function calls in `TSSolve()` is shown below
3372: .vb
3373: ...
3374: Step()
3375: PostEvaluate()
3376: EventHandling()
3377: step_rollback ? PostEvaluate() : PostStep()
3378: ...
3379: .ve
3380: where EventHandling() may result in one of the following three outcomes
3381: .vb
3382: (1) | successful step | solution intact
3383: (2) | successful step | solution modified by `postevent()`
3384: (3) | step_rollback | solution rolled back
3385: .ve
3387: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
3388: @*/
3389: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts))
3390: {
3391: PetscFunctionBegin;
3393: ts->poststep = func;
3394: PetscFunctionReturn(PETSC_SUCCESS);
3395: }
3397: /*@
3398: TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()`
3400: Collective
3402: Input Parameter:
3403: . ts - The `TS` context obtained from `TSCreate()`
3405: Note:
3406: `TSPostStep()` is typically used within time stepping implementations,
3407: so most users would not generally call this routine themselves.
3409: Level: developer
3411: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPostStep()`
3412: @*/
3413: PetscErrorCode TSPostStep(TS ts)
3414: {
3415: PetscFunctionBegin;
3417: if (ts->poststep) {
3418: Vec U;
3419: PetscObjectId idprev;
3420: PetscBool sameObject;
3421: PetscObjectState sprev, spost;
3423: PetscCall(TSGetSolution(ts, &U));
3424: PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3425: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3426: PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
3427: PetscCall(TSGetSolution(ts, &U));
3428: PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3429: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3430: if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3431: }
3432: PetscFunctionReturn(PETSC_SUCCESS);
3433: }
3435: /*@
3436: TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3438: Collective
3440: Input Parameters:
3441: + ts - time stepping context
3442: - t - time to interpolate to
3444: Output Parameter:
3445: . U - state at given time
3447: Level: intermediate
3449: Developer Notes:
3450: `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3452: .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()`
3453: @*/
3454: PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U)
3455: {
3456: PetscFunctionBegin;
3459: PetscCheck(t >= ts->ptime_prev && t <= ts->ptime, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Requested time %g not in last time steps [%g,%g]", (double)t, (double)ts->ptime_prev, (double)ts->ptime);
3460: PetscUseTypeMethod(ts, interpolate, t, U);
3461: PetscFunctionReturn(PETSC_SUCCESS);
3462: }
3464: /*@
3465: TSStep - Steps one time step
3467: Collective
3469: Input Parameter:
3470: . ts - the `TS` context obtained from `TSCreate()`
3472: Level: developer
3474: Notes:
3475: The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine.
3477: The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may
3478: be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3480: This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the
3481: time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep.
3483: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
3484: @*/
3485: PetscErrorCode TSStep(TS ts)
3486: {
3487: static PetscBool cite = PETSC_FALSE;
3488: PetscReal ptime;
3490: PetscFunctionBegin;
3492: PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3493: " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3494: " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3495: " journal = {arXiv e-preprints},\n"
3496: " eprint = {1806.01437},\n"
3497: " archivePrefix = {arXiv},\n"
3498: " year = {2018}\n}\n",
3499: &cite));
3500: PetscCall(TSSetUp(ts));
3501: PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3502: if (ts->eval_times)
3503: ts->eval_times->worktol = 0; /* In each step of TSSolve() 'eval_times->worktol' will be meaningfully defined (later) only once:
3504: in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */
3506: PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->run_steps != PETSC_INT_MAX || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime(), TSSetMaxSteps(), or TSSetRunSteps() or use -ts_max_time <time>, -ts_max_steps <steps>, -ts_run_steps <steps>");
3507: PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_UNSPECIFIED, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSStep()");
3508: PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP || ts->adapt, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE");
3510: if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0));
3511: PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0));
3512: ts->time_step0 = ts->time_step;
3514: if (!ts->steps) ts->ptime_prev = ts->ptime;
3515: ptime = ts->ptime;
3517: ts->ptime_prev_rollback = ts->ptime_prev;
3518: ts->reason = TS_CONVERGED_ITERATING;
3520: PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
3521: PetscUseTypeMethod(ts, step);
3522: PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));
3524: if (ts->reason >= 0) {
3525: ts->ptime_prev = ptime;
3526: ts->steps++;
3527: ts->steprollback = PETSC_FALSE;
3528: ts->steprestart = PETSC_FALSE;
3529: ts->stepresize = PETSC_FALSE;
3530: }
3532: if (ts->reason < 0 && ts->errorifstepfailed) {
3533: PetscCall(TSMonitorCancel(ts));
3534: if (ts->usessnes && ts->snes) PetscCall(SNESMonitorCancel(ts->snes));
3535: PetscCheck(ts->reason != TS_DIVERGED_NONLINEAR_SOLVE, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s, increase -ts_max_snes_failures or use unlimited to attempt recovery", TSConvergedReasons[ts->reason]);
3536: SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
3537: }
3538: PetscFunctionReturn(PETSC_SUCCESS);
3539: }
3541: /*@
3542: TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3543: at the end of a time step with a given order of accuracy.
3545: Collective
3547: Input Parameters:
3548: + ts - time stepping context
3549: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
3551: Input/Output Parameter:
3552: . order - optional, desired order for the error evaluation or `PETSC_DECIDE`;
3553: on output, the actual order of the error evaluation
3555: Output Parameter:
3556: . wlte - the weighted local truncation error norm
3558: Level: advanced
3560: Note:
3561: If the timestepper cannot evaluate the error in a particular step
3562: (eg. in the first step or restart steps after event handling),
3563: this routine returns wlte=-1.0 .
3565: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3566: @*/
3567: PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
3568: {
3569: PetscFunctionBegin;
3573: if (order) PetscAssertPointer(order, 3);
3575: PetscAssertPointer(wlte, 4);
3576: PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
3577: PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
3578: PetscFunctionReturn(PETSC_SUCCESS);
3579: }
3581: /*@
3582: TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3584: Collective
3586: Input Parameters:
3587: + ts - time stepping context
3588: . order - desired order of accuracy
3589: - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available)
3591: Output Parameter:
3592: . U - state at the end of the current step
3594: Level: advanced
3596: Notes:
3597: This function cannot be called until all stages have been evaluated.
3599: 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.
3601: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`
3602: @*/
3603: PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done)
3604: {
3605: PetscFunctionBegin;
3609: PetscUseTypeMethod(ts, evaluatestep, order, U, done);
3610: PetscFunctionReturn(PETSC_SUCCESS);
3611: }
3613: /*@C
3614: TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.
3616: Not collective
3618: Input Parameter:
3619: . ts - time stepping context
3621: Output Parameter:
3622: . initCondition - The function which computes an initial condition
3624: Calling sequence of `initCondition`:
3625: + ts - The timestepping context
3626: - u - The input vector in which the initial condition is stored
3628: Level: advanced
3630: .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3631: @*/
3632: PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u))
3633: {
3634: PetscFunctionBegin;
3636: PetscAssertPointer(initCondition, 2);
3637: *initCondition = ts->ops->initcondition;
3638: PetscFunctionReturn(PETSC_SUCCESS);
3639: }
3641: /*@C
3642: TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.
3644: Logically collective
3646: Input Parameters:
3647: + ts - time stepping context
3648: - initCondition - The function which computes an initial condition
3650: Calling sequence of `initCondition`:
3651: + ts - The timestepping context
3652: - e - The input vector in which the initial condition is to be stored
3654: Level: advanced
3656: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3657: @*/
3658: PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e))
3659: {
3660: PetscFunctionBegin;
3663: ts->ops->initcondition = initCondition;
3664: PetscFunctionReturn(PETSC_SUCCESS);
3665: }
3667: /*@
3668: TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()`
3670: Collective
3672: Input Parameters:
3673: + ts - time stepping context
3674: - u - The `Vec` to store the condition in which will be used in `TSSolve()`
3676: Level: advanced
3678: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3679: @*/
3680: PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
3681: {
3682: PetscFunctionBegin;
3685: PetscTryTypeMethod(ts, initcondition, u);
3686: PetscFunctionReturn(PETSC_SUCCESS);
3687: }
3689: /*@C
3690: TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.
3692: Not collective
3694: Input Parameter:
3695: . ts - time stepping context
3697: Output Parameter:
3698: . exactError - The function which computes the solution error
3700: Calling sequence of `exactError`:
3701: + ts - The timestepping context
3702: . u - The approximate solution vector
3703: - e - The vector in which the error is stored
3705: Level: advanced
3707: .seealso: [](ch_ts), `TS`, `TSComputeExactError()`
3708: @*/
3709: PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e))
3710: {
3711: PetscFunctionBegin;
3713: PetscAssertPointer(exactError, 2);
3714: *exactError = ts->ops->exacterror;
3715: PetscFunctionReturn(PETSC_SUCCESS);
3716: }
3718: /*@C
3719: TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.
3721: Logically collective
3723: Input Parameters:
3724: + ts - time stepping context
3725: - exactError - The function which computes the solution error
3727: Calling sequence of `exactError`:
3728: + ts - The timestepping context
3729: . u - The approximate solution vector
3730: - e - The vector in which the error is stored
3732: Level: advanced
3734: .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()`
3735: @*/
3736: PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e))
3737: {
3738: PetscFunctionBegin;
3741: ts->ops->exacterror = exactError;
3742: PetscFunctionReturn(PETSC_SUCCESS);
3743: }
3745: /*@
3746: TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()`
3748: Collective
3750: Input Parameters:
3751: + ts - time stepping context
3752: . u - The approximate solution
3753: - e - The `Vec` used to store the error
3755: Level: advanced
3757: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3758: @*/
3759: PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
3760: {
3761: PetscFunctionBegin;
3765: PetscTryTypeMethod(ts, exacterror, u, e);
3766: PetscFunctionReturn(PETSC_SUCCESS);
3767: }
3769: /*@C
3770: TSSetResize - Sets the resize callbacks.
3772: Logically Collective
3774: Input Parameters:
3775: + ts - The `TS` context obtained from `TSCreate()`
3776: . rollback - Whether a resize will restart the step
3777: . setup - The setup function
3778: . transfer - The transfer function
3779: - ctx - [optional] The user-defined context
3781: Calling sequence of `setup`:
3782: + ts - the `TS` context
3783: . step - the current step
3784: . time - the current time
3785: . state - the current vector of state
3786: . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise
3787: - ctx - user defined context
3789: Calling sequence of `transfer`:
3790: + ts - the `TS` context
3791: . nv - the number of vectors to be transferred
3792: . vecsin - array of vectors to be transferred
3793: . vecsout - array of transferred vectors
3794: - ctx - user defined context
3796: Notes:
3797: The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()`
3798: depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators
3799: and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver
3800: that the size of the discrete problem has changed.
3801: In both cases, the solver will collect the needed vectors that will be
3802: transferred from the old to the new sizes using the `transfer` callback. These vectors will include the
3803: current solution vector, and other vectors needed by the specific solver used.
3804: For example, `TSBDF` uses previous solutions vectors to solve for the next time step.
3805: Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`,
3806: will be automatically reset if the sizes are changed and they must be specified again by the user
3807: inside the `transfer` function.
3808: The input and output arrays passed to `transfer` are allocated by PETSc.
3809: Vectors in `vecsout` must be created by the user.
3810: Ownership of vectors in `vecsout` is transferred to PETSc.
3812: Level: advanced
3814: .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()`
3815: @*/
3816: PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, PetscCtx ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], PetscCtx ctx), PetscCtx ctx)
3817: {
3818: PetscFunctionBegin;
3820: ts->resizerollback = rollback;
3821: ts->resizesetup = setup;
3822: ts->resizetransfer = transfer;
3823: ts->resizectx = ctx;
3824: PetscFunctionReturn(PETSC_SUCCESS);
3825: }
3827: /*
3828: TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`.
3830: Collective
3832: Input Parameters:
3833: + ts - The `TS` context obtained from `TSCreate()`
3834: - flg - If `PETSC_TRUE` each TS implementation (e.g. `TSBDF`) will register vectors to be transferred, if `PETSC_FALSE` vectors will be imported from transferred vectors.
3836: Level: developer
3838: Note:
3839: `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is
3840: used within time stepping implementations,
3841: so most users would not generally call this routine themselves.
3843: .seealso: [](ch_ts), `TS`, `TSSetResize()`
3844: @*/
3845: static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg)
3846: {
3847: PetscFunctionBegin;
3849: PetscTryTypeMethod(ts, resizeregister, flg);
3850: /* PetscTryTypeMethod(adapt, resizeregister, flg); */
3851: PetscFunctionReturn(PETSC_SUCCESS);
3852: }
3854: static PetscErrorCode TSResizeReset(TS ts)
3855: {
3856: PetscFunctionBegin;
3858: PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs));
3859: PetscFunctionReturn(PETSC_SUCCESS);
3860: }
3862: static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[])
3863: {
3864: PetscFunctionBegin;
3867: for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i]));
3868: if (ts->resizetransfer) {
3869: PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt));
3870: PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx));
3871: }
3872: for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i]));
3873: PetscFunctionReturn(PETSC_SUCCESS);
3874: }
3876: /*@C
3877: TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`.
3879: Collective
3881: Input Parameters:
3882: + ts - The `TS` context obtained from `TSCreate()`
3883: . name - A string identifying the vector
3884: - vec - The vector
3886: Level: developer
3888: Note:
3889: `TSResizeRegisterVec()` is typically used within time stepping implementations,
3890: so most users would not generally call this routine themselves.
3892: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()`
3893: @*/
3894: PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec)
3895: {
3896: PetscFunctionBegin;
3898: PetscAssertPointer(name, 2);
3900: PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec));
3901: PetscFunctionReturn(PETSC_SUCCESS);
3902: }
3904: /*@C
3905: TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`.
3907: Collective
3909: Input Parameters:
3910: + ts - The `TS` context obtained from `TSCreate()`
3911: . name - A string identifying the vector
3912: - vec - The vector
3914: Level: developer
3916: Note:
3917: `TSResizeRetrieveVec()` is typically used within time stepping implementations,
3918: so most users would not generally call this routine themselves.
3920: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()`
3921: @*/
3922: PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec)
3923: {
3924: PetscFunctionBegin;
3926: PetscAssertPointer(name, 2);
3927: PetscAssertPointer(vec, 3);
3928: PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec));
3929: PetscFunctionReturn(PETSC_SUCCESS);
3930: }
3932: static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[])
3933: {
3934: PetscInt cnt;
3935: PetscObjectList tmp;
3936: Vec *vecsin = NULL;
3937: const char **namesin = NULL;
3939: PetscFunctionBegin;
3940: for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next)
3941: if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++;
3942: if (names) PetscCall(PetscMalloc1(cnt, &namesin));
3943: if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin));
3944: for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) {
3945: if (tmp->obj && tmp->obj->classid == VEC_CLASSID) {
3946: if (vecs) vecsin[cnt] = (Vec)tmp->obj;
3947: if (names) namesin[cnt] = tmp->name;
3948: cnt++;
3949: }
3950: }
3951: if (nv) *nv = cnt;
3952: if (names) *names = namesin;
3953: if (vecs) *vecs = vecsin;
3954: PetscFunctionReturn(PETSC_SUCCESS);
3955: }
3957: /*@
3958: TSResize - Runs the user-defined transfer functions provided with `TSSetResize()`
3960: Collective
3962: Input Parameter:
3963: . ts - The `TS` context obtained from `TSCreate()`
3965: Level: developer
3967: Note:
3968: `TSResize()` is typically used within time stepping implementations,
3969: so most users would not generally call this routine themselves.
3971: .seealso: [](ch_ts), `TS`, `TSSetResize()`
3972: @*/
3973: PetscErrorCode TSResize(TS ts)
3974: {
3975: PetscInt nv = 0;
3976: const char **names = NULL;
3977: Vec *vecsin = NULL;
3978: const char *solname = "ts:vec_sol";
3980: PetscFunctionBegin;
3982: if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS);
3983: if (ts->resizesetup) {
3984: PetscCall(VecLockReadPush(ts->vec_sol));
3985: PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx));
3986: PetscCall(VecLockReadPop(ts->vec_sol));
3987: if (ts->stepresize) {
3988: if (ts->resizerollback) {
3989: PetscCall(TSRollBack(ts));
3990: ts->time_step = ts->time_step0;
3991: }
3992: PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol));
3993: PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */
3994: }
3995: }
3997: PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin));
3998: if (nv) {
3999: Vec *vecsout, vecsol;
4001: /* Reset internal objects */
4002: PetscCall(TSReset(ts));
4004: /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */
4005: PetscCall(PetscCalloc1(nv, &vecsout));
4006: PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout));
4007: for (PetscInt i = 0; i < nv; i++) {
4008: const char *name;
4009: char *oname;
4011: PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
4012: PetscCall(PetscStrallocpy(name, &oname));
4013: PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i]));
4014: if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname));
4015: PetscCall(PetscFree(oname));
4016: PetscCall(VecDestroy(&vecsout[i]));
4017: }
4018: PetscCall(PetscFree(vecsout));
4019: PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */
4021: PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol));
4022: if (vecsol) PetscCall(TSSetSolution(ts, vecsol));
4023: PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution");
4024: }
4026: PetscCall(PetscFree(names));
4027: PetscCall(PetscFree(vecsin));
4028: PetscCall(TSResizeReset(ts));
4029: PetscFunctionReturn(PETSC_SUCCESS);
4030: }
4032: /*@
4033: TSSolve - Steps the requested number of timesteps.
4035: Collective
4037: Input Parameters:
4038: + ts - the `TS` context obtained from `TSCreate()`
4039: - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used,
4040: otherwise it must contain the initial conditions and will contain the solution at the final requested time
4042: Level: beginner
4044: Notes:
4045: The final time returned by this function may be different from the time of the internally
4046: held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have
4047: stepped over the final time.
4049: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
4050: @*/
4051: PetscErrorCode TSSolve(TS ts, Vec u)
4052: {
4053: Vec solution;
4055: PetscFunctionBegin;
4059: PetscCall(TSSetExactFinalTimeDefault(ts));
4060: 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 */
4061: if (!ts->vec_sol || u == ts->vec_sol) {
4062: PetscCall(VecDuplicate(u, &solution));
4063: PetscCall(TSSetSolution(ts, solution));
4064: PetscCall(VecDestroy(&solution)); /* grant ownership */
4065: }
4066: PetscCall(VecCopy(u, ts->vec_sol));
4067: PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
4068: } else if (u) PetscCall(TSSetSolution(ts, u));
4069: PetscCall(TSSetUp(ts));
4070: PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
4072: PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->run_steps != PETSC_INT_MAX || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime(), TSSetMaxSteps(), or TSSetRunSteps() or use -ts_max_time <time>, -ts_max_steps <steps>, -ts_run_steps <steps>");
4073: PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_UNSPECIFIED, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSSolve()");
4074: PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP || ts->adapt, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE");
4075: PetscCheck(!(ts->eval_times && ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP), PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "You must use TS_EXACTFINALTIME_MATCHSTEP when using time span or evaluation times");
4077: if (ts->eval_times) {
4078: if (!ts->eval_times->sol_vecs) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
4079: for (PetscInt i = 0; i < ts->eval_times->num_time_points; i++) {
4080: PetscBool is_close = PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[i], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0);
4081: if (ts->ptime <= ts->eval_times->time_points[i] || is_close) {
4082: ts->eval_times->time_point_idx = i;
4084: PetscBool is_ptime_in_sol_times = PETSC_FALSE; // If current solution has already been saved, we should not save it again
4085: if (ts->eval_times->sol_idx > 0) is_ptime_in_sol_times = PetscIsCloseAtTol(ts->ptime, ts->eval_times->sol_times[ts->eval_times->sol_idx - 1], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0);
4086: if (is_close && !is_ptime_in_sol_times) {
4087: PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx]));
4088: ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime;
4089: ts->eval_times->sol_idx++;
4090: ts->eval_times->time_point_idx++;
4091: }
4092: break;
4093: }
4094: }
4095: }
4097: if (ts->forward_solve) PetscCall(TSForwardSetUp(ts));
4099: /* reset number of steps only when the step is not restarted. ARKIMEX
4100: restarts the step after an event. Resetting these counters in such case causes
4101: TSTrajectory to incorrectly save the output files
4102: */
4103: /* reset time step and iteration counters */
4104: if (!ts->steps) {
4105: ts->ksp_its = 0;
4106: ts->snes_its = 0;
4107: ts->num_snes_failures = 0;
4108: ts->reject = 0;
4109: ts->steprestart = PETSC_TRUE;
4110: ts->steprollback = PETSC_FALSE;
4111: ts->stepresize = PETSC_FALSE;
4112: ts->rhsjacobian.time = PETSC_MIN_REAL;
4113: }
4115: /* make sure initial time step does not overshoot final time or the next point in evaluation times */
4116: if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
4117: PetscReal maxdt;
4118: PetscReal dt = ts->time_step;
4120: if (ts->eval_times) maxdt = ts->eval_times->time_points[ts->eval_times->time_point_idx] - ts->ptime;
4121: else maxdt = ts->max_time - ts->ptime;
4122: ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
4123: }
4124: ts->reason = TS_CONVERGED_ITERATING;
4126: {
4127: PetscViewer viewer;
4128: PetscViewerFormat format;
4129: PetscBool flg;
4130: static PetscBool incall = PETSC_FALSE;
4132: if (!incall) {
4133: /* Estimate the convergence rate of the time discretization */
4134: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
4135: if (flg) {
4136: PetscConvEst conv;
4137: DM dm;
4138: PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4139: PetscInt Nf;
4140: PetscBool checkTemporal = PETSC_TRUE;
4142: incall = PETSC_TRUE;
4143: PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
4144: PetscCall(TSGetDM(ts, &dm));
4145: PetscCall(DMGetNumFields(dm, &Nf));
4146: PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
4147: PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
4148: PetscCall(PetscConvEstUseTS(conv, checkTemporal));
4149: PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
4150: PetscCall(PetscConvEstSetFromOptions(conv));
4151: PetscCall(PetscConvEstSetUp(conv));
4152: PetscCall(PetscConvEstGetConvRate(conv, alpha));
4153: PetscCall(PetscViewerPushFormat(viewer, format));
4154: PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4155: PetscCall(PetscViewerPopFormat(viewer));
4156: PetscCall(PetscViewerDestroy(&viewer));
4157: PetscCall(PetscConvEstDestroy(&conv));
4158: PetscCall(PetscFree(alpha));
4159: incall = PETSC_FALSE;
4160: }
4161: }
4162: }
4164: PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre"));
4166: if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4167: PetscUseTypeMethod(ts, solve);
4168: if (u) PetscCall(VecCopy(ts->vec_sol, u));
4169: ts->solvetime = ts->ptime;
4170: solution = ts->vec_sol;
4171: } else { /* Step the requested number of timesteps. */
4172: if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4173: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4175: if (!ts->steps) {
4176: PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4177: PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
4178: }
4180: ts->start_step = ts->steps; // records starting step
4181: while (!ts->reason) {
4182: PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4183: if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts));
4184: PetscCall(TSStep(ts));
4185: if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
4186: if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
4187: if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4188: if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4189: PetscCall(TSForwardCostIntegral(ts));
4190: if (ts->reason >= 0) ts->steps++;
4191: }
4192: if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4193: if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4194: PetscCall(TSForwardStep(ts));
4195: if (ts->reason >= 0) ts->steps++;
4196: }
4197: PetscCall(TSPostEvaluate(ts));
4198: PetscCall(TSEventHandler(ts)); /* The right-hand side may be changed due to event. Be careful with Any computation using the RHS information after this point. */
4199: if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
4200: if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts));
4201: /* check convergence */
4202: if (!ts->reason) {
4203: if ((ts->steps - ts->start_step) >= ts->run_steps) ts->reason = TS_CONVERGED_ITS;
4204: else if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4205: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4206: }
4207: if (!ts->steprollback) {
4208: PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4209: PetscCall(TSPostStep(ts));
4210: if (!ts->resizerollback) PetscCall(TSResize(ts));
4212: if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points && ts->reason >= 0) {
4213: PetscCheck(ts->eval_times->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(eval_times->worktol > 0) in TSSolve()");
4214: if (PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) {
4215: ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime;
4216: PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx]));
4217: ts->eval_times->sol_idx++;
4218: ts->eval_times->time_point_idx++;
4219: }
4220: }
4221: }
4222: }
4223: PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4225: if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4226: if (!u) u = ts->vec_sol;
4227: PetscCall(TSInterpolate(ts, ts->max_time, u));
4228: ts->solvetime = ts->max_time;
4229: solution = u;
4230: PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
4231: } else {
4232: if (u) PetscCall(VecCopy(ts->vec_sol, u));
4233: ts->solvetime = ts->ptime;
4234: solution = ts->vec_sol;
4235: }
4236: }
4238: PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
4239: PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
4240: PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
4241: if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
4242: PetscFunctionReturn(PETSC_SUCCESS);
4243: }
4245: /*@
4246: TSGetTime - Gets the time of the most recently completed step.
4248: Not Collective
4250: Input Parameter:
4251: . ts - the `TS` context obtained from `TSCreate()`
4253: Output Parameter:
4254: . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`.
4256: Level: beginner
4258: Note:
4259: When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`,
4260: `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated.
4262: .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
4263: @*/
4264: PetscErrorCode TSGetTime(TS ts, PetscReal *t)
4265: {
4266: PetscFunctionBegin;
4268: PetscAssertPointer(t, 2);
4269: *t = ts->ptime;
4270: PetscFunctionReturn(PETSC_SUCCESS);
4271: }
4273: /*@
4274: TSGetPrevTime - Gets the starting time of the previously completed step.
4276: Not Collective
4278: Input Parameter:
4279: . ts - the `TS` context obtained from `TSCreate()`
4281: Output Parameter:
4282: . t - the previous time
4284: Level: beginner
4286: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
4287: @*/
4288: PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t)
4289: {
4290: PetscFunctionBegin;
4292: PetscAssertPointer(t, 2);
4293: *t = ts->ptime_prev;
4294: PetscFunctionReturn(PETSC_SUCCESS);
4295: }
4297: /*@
4298: TSSetTime - Allows one to reset the time.
4300: Logically Collective
4302: Input Parameters:
4303: + ts - the `TS` context obtained from `TSCreate()`
4304: - t - the time
4306: Level: intermediate
4308: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()`
4309: @*/
4310: PetscErrorCode TSSetTime(TS ts, PetscReal t)
4311: {
4312: PetscFunctionBegin;
4315: ts->ptime = t;
4316: PetscFunctionReturn(PETSC_SUCCESS);
4317: }
4319: /*@
4320: TSSetOptionsPrefix - Sets the prefix used for searching for all
4321: TS options in the database.
4323: Logically Collective
4325: Input Parameters:
4326: + ts - The `TS` context
4327: - prefix - The prefix to prepend to all option names
4329: Level: advanced
4331: Note:
4332: A hyphen (-) must NOT be given at the beginning of the prefix name.
4333: The first character of all runtime options is AUTOMATICALLY the
4334: hyphen.
4336: .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()`
4337: @*/
4338: PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[])
4339: {
4340: SNES snes;
4342: PetscFunctionBegin;
4344: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
4345: PetscCall(TSGetSNES(ts, &snes));
4346: PetscCall(SNESSetOptionsPrefix(snes, prefix));
4347: PetscFunctionReturn(PETSC_SUCCESS);
4348: }
4350: /*@
4351: TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4352: TS options in the database.
4354: Logically Collective
4356: Input Parameters:
4357: + ts - The `TS` context
4358: - prefix - The prefix to prepend to all option names
4360: Level: advanced
4362: Note:
4363: A hyphen (-) must NOT be given at the beginning of the prefix name.
4364: The first character of all runtime options is AUTOMATICALLY the
4365: hyphen.
4367: .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()`
4368: @*/
4369: PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[])
4370: {
4371: SNES snes;
4373: PetscFunctionBegin;
4375: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
4376: PetscCall(TSGetSNES(ts, &snes));
4377: PetscCall(SNESAppendOptionsPrefix(snes, prefix));
4378: PetscFunctionReturn(PETSC_SUCCESS);
4379: }
4381: /*@
4382: TSGetOptionsPrefix - Sets the prefix used for searching for all
4383: `TS` options in the database.
4385: Not Collective
4387: Input Parameter:
4388: . ts - The `TS` context
4390: Output Parameter:
4391: . prefix - A pointer to the prefix string used
4393: Level: intermediate
4395: .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
4396: @*/
4397: PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
4398: {
4399: PetscFunctionBegin;
4401: PetscAssertPointer(prefix, 2);
4402: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
4403: PetscFunctionReturn(PETSC_SUCCESS);
4404: }
4406: /*@C
4407: TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4409: Not Collective, but parallel objects are returned if ts is parallel
4411: Input Parameter:
4412: . ts - The `TS` context obtained from `TSCreate()`
4414: Output Parameters:
4415: + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`)
4416: . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`)
4417: . func - Function to compute the Jacobian of the RHS (or `NULL`)
4418: - ctx - User-defined context for Jacobian evaluation routine (or `NULL`)
4420: Level: intermediate
4422: Note:
4423: You can pass in `NULL` for any return argument you do not need.
4425: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4427: @*/
4428: PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, PetscCtxRt ctx)
4429: {
4430: DM dm;
4432: PetscFunctionBegin;
4433: if (Amat || Pmat) {
4434: SNES snes;
4435: PetscCall(TSGetSNES(ts, &snes));
4436: PetscCall(SNESSetUpMatrices(snes));
4437: PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4438: }
4439: PetscCall(TSGetDM(ts, &dm));
4440: PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
4441: PetscFunctionReturn(PETSC_SUCCESS);
4442: }
4444: /*@C
4445: TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4447: Not Collective, but parallel objects are returned if ts is parallel
4449: Input Parameter:
4450: . ts - The `TS` context obtained from `TSCreate()`
4452: Output Parameters:
4453: + Amat - The (approximate) Jacobian of F(t,U,U_t)
4454: . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat`
4455: . f - The function to compute the matrices
4456: - ctx - User-defined context for Jacobian evaluation routine
4458: Level: advanced
4460: Note:
4461: You can pass in `NULL` for any return argument you do not need.
4463: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4464: @*/
4465: PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, PetscCtxRt ctx)
4466: {
4467: DM dm;
4469: PetscFunctionBegin;
4470: if (Amat || Pmat) {
4471: SNES snes;
4472: PetscCall(TSGetSNES(ts, &snes));
4473: PetscCall(SNESSetUpMatrices(snes));
4474: PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4475: }
4476: PetscCall(TSGetDM(ts, &dm));
4477: PetscCall(DMTSGetIJacobian(dm, f, ctx));
4478: PetscFunctionReturn(PETSC_SUCCESS);
4479: }
4481: #include <petsc/private/dmimpl.h>
4482: /*@
4483: TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS`
4485: Logically Collective
4487: Input Parameters:
4488: + ts - the `TS` integrator object
4489: - dm - the dm, cannot be `NULL`
4491: Level: intermediate
4493: Notes:
4494: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
4495: even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving
4496: different problems using the same function space.
4498: .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4499: @*/
4500: PetscErrorCode TSSetDM(TS ts, DM dm)
4501: {
4502: SNES snes;
4503: DMTS tsdm;
4505: PetscFunctionBegin;
4508: PetscCall(PetscObjectReference((PetscObject)dm));
4509: if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4510: if (ts->dm->dmts && !dm->dmts) {
4511: PetscCall(DMCopyDMTS(ts->dm, dm));
4512: PetscCall(DMGetDMTS(ts->dm, &tsdm));
4513: /* Grant write privileges to the replacement DM */
4514: if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4515: }
4516: PetscCall(DMDestroy(&ts->dm));
4517: }
4518: ts->dm = dm;
4520: PetscCall(TSGetSNES(ts, &snes));
4521: PetscCall(SNESSetDM(snes, dm));
4522: PetscFunctionReturn(PETSC_SUCCESS);
4523: }
4525: /*@
4526: TSGetDM - Gets the `DM` that may be used by some preconditioners
4528: Not Collective
4530: Input Parameter:
4531: . ts - the `TS`
4533: Output Parameter:
4534: . dm - the `DM`
4536: Level: intermediate
4538: .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4539: @*/
4540: PetscErrorCode TSGetDM(TS ts, DM *dm)
4541: {
4542: PetscFunctionBegin;
4544: if (!ts->dm) {
4545: PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4546: if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4547: }
4548: *dm = ts->dm;
4549: PetscFunctionReturn(PETSC_SUCCESS);
4550: }
4552: /*@
4553: SNESTSFormFunction - Function to evaluate nonlinear residual defined by an ODE solver algorithm implemented within `TS`
4555: Logically Collective
4557: Input Parameters:
4558: + snes - nonlinear solver
4559: . U - the current state at which to evaluate the residual
4560: - ctx - user context, must be a `TS`
4562: Output Parameter:
4563: . F - the nonlinear residual
4565: Level: developer
4567: Note:
4568: This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4569: It is most frequently passed to `MatFDColoringSetFunction()`.
4571: .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
4572: @*/
4573: PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, PetscCtx ctx)
4574: {
4575: TS ts = (TS)ctx;
4577: PetscFunctionBegin;
4582: PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
4583: PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
4584: PetscFunctionReturn(PETSC_SUCCESS);
4585: }
4587: /*@
4588: SNESTSFormJacobian - Function to evaluate the Jacobian defined by an ODE solver algorithm implemented within `TS`
4590: Collective
4592: Input Parameters:
4593: + snes - nonlinear solver
4594: . U - the current state at which to evaluate the residual
4595: - ctx - user context, must be a `TS`
4597: Output Parameters:
4598: + A - the Jacobian
4599: - B - the matrix used to construct the preconditioner (often the same as `A`)
4601: Level: developer
4603: Note:
4604: This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4606: .seealso: [](ch_ts), `SNESSetJacobian()`
4607: @*/
4608: PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, PetscCtx ctx)
4609: {
4610: TS ts = (TS)ctx;
4612: PetscFunctionBegin;
4618: PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
4619: PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
4620: PetscFunctionReturn(PETSC_SUCCESS);
4621: }
4623: /*@C
4624: TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only
4626: Collective
4628: Input Parameters:
4629: + ts - time stepping context
4630: . t - time at which to evaluate
4631: . U - state at which to evaluate
4632: - ctx - context
4634: Output Parameter:
4635: . F - right-hand side
4637: Level: intermediate
4639: Note:
4640: This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems.
4641: The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`.
4643: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4644: @*/
4645: PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, PetscCtx ctx)
4646: {
4647: Mat Arhs, Brhs;
4649: PetscFunctionBegin;
4650: PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4651: /* undo the damage caused by shifting */
4652: PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4653: PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4654: PetscCall(MatMult(Arhs, U, F));
4655: PetscFunctionReturn(PETSC_SUCCESS);
4656: }
4658: /*@C
4659: TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4661: Collective
4663: Input Parameters:
4664: + ts - time stepping context
4665: . t - time at which to evaluate
4666: . U - state at which to evaluate
4667: - ctx - context
4669: Output Parameters:
4670: + A - Jacobian
4671: - B - matrix used to construct the preconditioner, often the same as `A`
4673: Level: intermediate
4675: Note:
4676: This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems.
4678: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4679: @*/
4680: PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, PetscCtx ctx)
4681: {
4682: PetscFunctionBegin;
4683: PetscFunctionReturn(PETSC_SUCCESS);
4684: }
4686: /*@C
4687: TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4689: Collective
4691: Input Parameters:
4692: + ts - time stepping context
4693: . t - time at which to evaluate
4694: . U - state at which to evaluate
4695: . Udot - time derivative of state vector
4696: - ctx - context
4698: Output Parameter:
4699: . F - left hand side
4701: Level: intermediate
4703: Notes:
4704: 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
4705: user is required to write their own `TSComputeIFunction()`.
4706: This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems.
4707: The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`.
4709: Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U
4711: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4712: @*/
4713: PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, PetscCtx ctx)
4714: {
4715: Mat A, B;
4717: PetscFunctionBegin;
4718: PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4719: PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4720: PetscCall(MatMult(A, Udot, F));
4721: PetscFunctionReturn(PETSC_SUCCESS);
4722: }
4724: /*@C
4725: TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE
4727: Collective
4729: Input Parameters:
4730: + ts - time stepping context
4731: . t - time at which to evaluate
4732: . U - state at which to evaluate
4733: . Udot - time derivative of state vector
4734: . shift - shift to apply
4735: - ctx - context
4737: Output Parameters:
4738: + A - pointer to operator
4739: - B - pointer to matrix from which the preconditioner is built (often `A`)
4741: Level: advanced
4743: Notes:
4744: This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems.
4746: It is only appropriate for problems of the form
4748: $$
4749: M \dot{U} = F(U,t)
4750: $$
4752: where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only
4753: works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing
4754: an implicit operator of the form
4756: $$
4757: shift*M + J
4758: $$
4760: 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
4761: a copy of M or reassemble it when requested.
4763: .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4764: @*/
4765: PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscCtx ctx)
4766: {
4767: PetscFunctionBegin;
4768: PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4769: ts->ijacobian.shift = shift;
4770: PetscFunctionReturn(PETSC_SUCCESS);
4771: }
4773: /*@
4774: TSGetEquationType - Gets the type of the equation that `TS` is solving.
4776: Not Collective
4778: Input Parameter:
4779: . ts - the `TS` context
4781: Output Parameter:
4782: . equation_type - see `TSEquationType`
4784: Level: beginner
4786: .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
4787: @*/
4788: PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
4789: {
4790: PetscFunctionBegin;
4792: PetscAssertPointer(equation_type, 2);
4793: *equation_type = ts->equation_type;
4794: PetscFunctionReturn(PETSC_SUCCESS);
4795: }
4797: /*@
4798: TSSetEquationType - Sets the type of the equation that `TS` is solving.
4800: Not Collective
4802: Input Parameters:
4803: + ts - the `TS` context
4804: - equation_type - see `TSEquationType`
4806: Level: advanced
4808: .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
4809: @*/
4810: PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
4811: {
4812: PetscFunctionBegin;
4814: ts->equation_type = equation_type;
4815: PetscFunctionReturn(PETSC_SUCCESS);
4816: }
4818: /*@
4819: TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.
4821: Not Collective
4823: Input Parameter:
4824: . ts - the `TS` context
4826: Output Parameter:
4827: . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4828: manual pages for the individual convergence tests for complete lists
4830: Level: beginner
4832: Note:
4833: Can only be called after the call to `TSSolve()` is complete.
4835: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4836: @*/
4837: PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
4838: {
4839: PetscFunctionBegin;
4841: PetscAssertPointer(reason, 2);
4842: *reason = ts->reason;
4843: PetscFunctionReturn(PETSC_SUCCESS);
4844: }
4846: /*@
4847: TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`.
4849: Logically Collective; reason must contain common value
4851: Input Parameters:
4852: + ts - the `TS` context
4853: - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4854: manual pages for the individual convergence tests for complete lists
4856: Level: advanced
4858: Note:
4859: Can only be called while `TSSolve()` is active.
4861: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4862: @*/
4863: PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
4864: {
4865: PetscFunctionBegin;
4867: ts->reason = reason;
4868: PetscFunctionReturn(PETSC_SUCCESS);
4869: }
4871: /*@
4872: TSGetSolveTime - Gets the time after a call to `TSSolve()`
4874: Not Collective
4876: Input Parameter:
4877: . ts - the `TS` context
4879: Output Parameter:
4880: . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()`
4882: Level: beginner
4884: Note:
4885: Can only be called after the call to `TSSolve()` is complete.
4887: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4888: @*/
4889: PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
4890: {
4891: PetscFunctionBegin;
4893: PetscAssertPointer(ftime, 2);
4894: *ftime = ts->solvetime;
4895: PetscFunctionReturn(PETSC_SUCCESS);
4896: }
4898: /*@
4899: TSGetSNESIterations - Gets the total number of nonlinear iterations
4900: used by the time integrator.
4902: Not Collective
4904: Input Parameter:
4905: . ts - `TS` context
4907: Output Parameter:
4908: . nits - number of nonlinear iterations
4910: Level: intermediate
4912: Note:
4913: This counter is reset to zero for each successive call to `TSSolve()`.
4915: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
4916: @*/
4917: PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
4918: {
4919: PetscFunctionBegin;
4921: PetscAssertPointer(nits, 2);
4922: *nits = ts->snes_its;
4923: PetscFunctionReturn(PETSC_SUCCESS);
4924: }
4926: /*@
4927: TSGetKSPIterations - Gets the total number of linear iterations
4928: used by the time integrator.
4930: Not Collective
4932: Input Parameter:
4933: . ts - `TS` context
4935: Output Parameter:
4936: . lits - number of linear iterations
4938: Level: intermediate
4940: Note:
4941: This counter is reset to zero for each successive call to `TSSolve()`.
4943: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`
4944: @*/
4945: PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
4946: {
4947: PetscFunctionBegin;
4949: PetscAssertPointer(lits, 2);
4950: *lits = ts->ksp_its;
4951: PetscFunctionReturn(PETSC_SUCCESS);
4952: }
4954: /*@
4955: TSGetStepRejections - Gets the total number of rejected steps.
4957: Not Collective
4959: Input Parameter:
4960: . ts - `TS` context
4962: Output Parameter:
4963: . rejects - number of steps rejected
4965: Level: intermediate
4967: Note:
4968: This counter is reset to zero for each successive call to `TSSolve()`.
4970: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4971: @*/
4972: PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
4973: {
4974: PetscFunctionBegin;
4976: PetscAssertPointer(rejects, 2);
4977: *rejects = ts->reject;
4978: PetscFunctionReturn(PETSC_SUCCESS);
4979: }
4981: /*@
4982: TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS`
4984: Not Collective
4986: Input Parameter:
4987: . ts - `TS` context
4989: Output Parameter:
4990: . fails - number of failed nonlinear solves
4992: Level: intermediate
4994: Note:
4995: This counter is reset to zero for each successive call to `TSSolve()`.
4997: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4998: @*/
4999: PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
5000: {
5001: PetscFunctionBegin;
5003: PetscAssertPointer(fails, 2);
5004: *fails = ts->num_snes_failures;
5005: PetscFunctionReturn(PETSC_SUCCESS);
5006: }
5008: /*@
5009: TSSetMaxStepRejections - Sets the maximum number of step rejections allowed in a single time-step attempt before a time step fails in `TSSolve()` with `TS_DIVERGED_STEP_REJECTED`
5011: Not Collective
5013: Input Parameters:
5014: + ts - `TS` context
5015: - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited
5017: Options Database Key:
5018: . -ts_max_step_rejections - Maximum number of step rejections before a step fails
5020: Level: intermediate
5022: Developer Note:
5023: The options database name is incorrect.
5025: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`,
5026: `TSGetConvergedReason()`, `TSSolve()`, `TS_DIVERGED_STEP_REJECTED`
5027: @*/
5028: PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
5029: {
5030: PetscFunctionBegin;
5032: if (rejects == PETSC_UNLIMITED || rejects == -1) {
5033: ts->max_reject = PETSC_UNLIMITED;
5034: } else {
5035: PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
5036: ts->max_reject = rejects;
5037: }
5038: PetscFunctionReturn(PETSC_SUCCESS);
5039: }
5041: /*@
5042: TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves allowed before `TSSolve()` is ended with a `TSConvergedReason` of `TS_DIVERGED_NONLINEAR_SOLVE`
5044: Not Collective
5046: Input Parameters:
5047: + ts - `TS` context
5048: - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures.
5050: Options Database Key:
5051: . -ts_max_snes_failures - Maximum number of nonlinear solve failures
5053: Level: intermediate
5055: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`,
5056: `TSGetConvergedReason()`, `TS_DIVERGED_NONLINEAR_SOLVE`, `TSConvergedReason`
5057: @*/
5058: PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
5059: {
5060: PetscFunctionBegin;
5062: if (fails == PETSC_UNLIMITED || fails == -1) {
5063: ts->max_snes_failures = PETSC_UNLIMITED;
5064: } else {
5065: PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
5066: ts->max_snes_failures = fails;
5067: }
5068: PetscFunctionReturn(PETSC_SUCCESS);
5069: }
5071: /*@
5072: TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()`
5074: Not Collective
5076: Input Parameters:
5077: + ts - `TS` context
5078: - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure
5080: Options Database Key:
5081: . -ts_error_if_step_fails - Error if no step succeeds
5083: Level: intermediate
5085: .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
5086: @*/
5087: PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
5088: {
5089: PetscFunctionBegin;
5091: ts->errorifstepfailed = err;
5092: PetscFunctionReturn(PETSC_SUCCESS);
5093: }
5095: /*@
5096: TSGetAdapt - Get the adaptive controller context for the current method
5098: Collective if controller has not yet been created
5100: Input Parameter:
5101: . ts - time stepping context
5103: Output Parameter:
5104: . adapt - adaptive controller
5106: Level: intermediate
5108: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
5109: @*/
5110: PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
5111: {
5112: PetscFunctionBegin;
5114: PetscAssertPointer(adapt, 2);
5115: if (!ts->adapt) {
5116: PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
5117: PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
5118: }
5119: *adapt = ts->adapt;
5120: PetscFunctionReturn(PETSC_SUCCESS);
5121: }
5123: /*@
5124: TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller
5126: Logically Collective
5128: Input Parameters:
5129: + ts - time integration context
5130: . atol - scalar absolute tolerances
5131: . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
5132: . rtol - scalar relative tolerances
5133: - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present
5135: Options Database Keys:
5136: + -ts_rtol <rtol> - relative tolerance for local truncation error
5137: - -ts_atol <atol> - Absolute tolerance for local truncation error
5139: Level: beginner
5141: Notes:
5142: `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value
5143: or the default value from when the object's type was set.
5145: With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5146: (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5147: computed only for the differential or the algebraic part then this can be done using the vector of
5148: tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5149: differential part and infinity for the algebraic part, the LTE calculation will include only the
5150: differential variables.
5152: Fortran Note:
5153: Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.
5155: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
5156: @*/
5157: PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
5158: {
5159: PetscFunctionBegin;
5160: if (atol == (PetscReal)PETSC_DETERMINE) {
5161: ts->atol = ts->default_atol;
5162: } else if (atol != (PetscReal)PETSC_CURRENT) {
5163: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
5164: ts->atol = atol;
5165: }
5167: if (vatol) {
5168: PetscCall(PetscObjectReference((PetscObject)vatol));
5169: PetscCall(VecDestroy(&ts->vatol));
5170: ts->vatol = vatol;
5171: }
5173: if (rtol == (PetscReal)PETSC_DETERMINE) {
5174: ts->rtol = ts->default_rtol;
5175: } else if (rtol != (PetscReal)PETSC_CURRENT) {
5176: PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
5177: ts->rtol = rtol;
5178: }
5180: if (vrtol) {
5181: PetscCall(PetscObjectReference((PetscObject)vrtol));
5182: PetscCall(VecDestroy(&ts->vrtol));
5183: ts->vrtol = vrtol;
5184: }
5185: PetscFunctionReturn(PETSC_SUCCESS);
5186: }
5188: /*@
5189: TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5191: Logically Collective
5193: Input Parameter:
5194: . ts - time integration context
5196: Output Parameters:
5197: + atol - scalar absolute tolerances, `NULL` to ignore
5198: . vatol - vector of absolute tolerances, `NULL` to ignore
5199: . rtol - scalar relative tolerances, `NULL` to ignore
5200: - vrtol - vector of relative tolerances, `NULL` to ignore
5202: Level: beginner
5204: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
5205: @*/
5206: PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
5207: {
5208: PetscFunctionBegin;
5209: if (atol) *atol = ts->atol;
5210: if (vatol) *vatol = ts->vatol;
5211: if (rtol) *rtol = ts->rtol;
5212: if (vrtol) *vrtol = ts->vrtol;
5213: PetscFunctionReturn(PETSC_SUCCESS);
5214: }
5216: /*@
5217: TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5219: Collective
5221: Input Parameters:
5222: + ts - time stepping context
5223: . U - state vector, usually ts->vec_sol
5224: . Y - state vector to be compared to U
5225: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5227: Output Parameters:
5228: + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5229: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5230: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5232: Options Database Key:
5233: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5235: Level: developer
5237: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
5238: @*/
5239: PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5240: {
5241: PetscInt norma_loc, norm_loc, normr_loc;
5243: PetscFunctionBegin;
5248: PetscAssertPointer(norm, 5);
5249: PetscAssertPointer(norma, 6);
5250: PetscAssertPointer(normr, 7);
5251: PetscCall(VecErrorWeightedNorms(U, Y, NULL, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc));
5252: if (wnormtype == NORM_2) {
5253: if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5254: if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5255: if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5256: }
5257: PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5258: PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5259: PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5260: PetscFunctionReturn(PETSC_SUCCESS);
5261: }
5263: /*@
5264: TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5266: Collective
5268: Input Parameters:
5269: + ts - time stepping context
5270: . E - error vector
5271: . U - state vector, usually ts->vec_sol
5272: . Y - state vector, previous time step
5273: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5275: Output Parameters:
5276: + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5277: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5278: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5280: Options Database Key:
5281: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5283: Level: developer
5285: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
5286: @*/
5287: PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5288: {
5289: PetscInt norma_loc, norm_loc, normr_loc;
5291: PetscFunctionBegin;
5293: PetscCall(VecErrorWeightedNorms(U, Y, E, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc));
5294: if (wnormtype == NORM_2) {
5295: if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5296: if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5297: if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5298: }
5299: PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5300: PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5301: PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5302: PetscFunctionReturn(PETSC_SUCCESS);
5303: }
5305: /*@
5306: TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5308: Logically Collective
5310: Input Parameters:
5311: + ts - time stepping context
5312: - cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5314: Note:
5315: After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5317: Level: intermediate
5319: .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
5320: @*/
5321: PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
5322: {
5323: PetscFunctionBegin;
5325: ts->cfltime_local = cfltime;
5326: ts->cfltime = -1.;
5327: PetscFunctionReturn(PETSC_SUCCESS);
5328: }
5330: /*@
5331: TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5333: Collective
5335: Input Parameter:
5336: . ts - time stepping context
5338: Output Parameter:
5339: . cfltime - maximum stable time step for forward Euler
5341: Level: advanced
5343: .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
5344: @*/
5345: PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
5346: {
5347: PetscFunctionBegin;
5348: if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5349: *cfltime = ts->cfltime;
5350: PetscFunctionReturn(PETSC_SUCCESS);
5351: }
5353: /*@
5354: TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5356: Input Parameters:
5357: + ts - the `TS` context.
5358: . xl - lower bound.
5359: - xu - upper bound.
5361: Level: advanced
5363: Note:
5364: If this routine is not called then the lower and upper bounds are set to
5365: `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`.
5367: .seealso: [](ch_ts), `TS`
5368: @*/
5369: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5370: {
5371: SNES snes;
5373: PetscFunctionBegin;
5374: PetscCall(TSGetSNES(ts, &snes));
5375: PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5376: PetscFunctionReturn(PETSC_SUCCESS);
5377: }
5379: /*@
5380: TSComputeLinearStability - computes the linear stability function at a point
5382: Collective
5384: Input Parameters:
5385: + ts - the `TS` context
5386: . xr - real part of input argument
5387: - xi - imaginary part of input argument
5389: Output Parameters:
5390: + yr - real part of function value
5391: - yi - imaginary part of function value
5393: Level: developer
5395: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
5396: @*/
5397: PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
5398: {
5399: PetscFunctionBegin;
5401: PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5402: PetscFunctionReturn(PETSC_SUCCESS);
5403: }
5405: /*@
5406: TSRestartStep - Flags the solver to restart the next step
5408: Collective
5410: Input Parameter:
5411: . ts - the `TS` context obtained from `TSCreate()`
5413: Level: advanced
5415: Notes:
5416: Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5417: discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5418: vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5419: the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
5420: discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5421: discontinuous source terms).
5423: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5424: @*/
5425: PetscErrorCode TSRestartStep(TS ts)
5426: {
5427: PetscFunctionBegin;
5429: ts->steprestart = PETSC_TRUE;
5430: PetscFunctionReturn(PETSC_SUCCESS);
5431: }
5433: /*@
5434: TSRollBack - Rolls back one time step
5436: Collective
5438: Input Parameter:
5439: . ts - the `TS` context obtained from `TSCreate()`
5441: Level: advanced
5443: .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5444: @*/
5445: PetscErrorCode TSRollBack(TS ts)
5446: {
5447: PetscFunctionBegin;
5449: PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5450: PetscTryTypeMethod(ts, rollback);
5451: PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
5452: ts->time_step = ts->ptime - ts->ptime_prev;
5453: ts->ptime = ts->ptime_prev;
5454: ts->ptime_prev = ts->ptime_prev_rollback;
5455: ts->steps--;
5456: ts->steprollback = PETSC_TRUE;
5457: PetscFunctionReturn(PETSC_SUCCESS);
5458: }
5460: /*@
5461: TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step
5463: Not collective
5465: Input Parameter:
5466: . ts - the `TS` context obtained from `TSCreate()`
5468: Output Parameter:
5469: . flg - the rollback flag
5471: Level: advanced
5473: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
5474: @*/
5475: PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
5476: {
5477: PetscFunctionBegin;
5479: PetscAssertPointer(flg, 2);
5480: *flg = ts->steprollback;
5481: PetscFunctionReturn(PETSC_SUCCESS);
5482: }
5484: /*@
5485: TSGetStepResize - Get the internal flag indicating if the current step is after a resize.
5487: Not collective
5489: Input Parameter:
5490: . ts - the `TS` context obtained from `TSCreate()`
5492: Output Parameter:
5493: . flg - the resize flag
5495: Level: advanced
5497: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
5498: @*/
5499: PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
5500: {
5501: PetscFunctionBegin;
5503: PetscAssertPointer(flg, 2);
5504: *flg = ts->stepresize;
5505: PetscFunctionReturn(PETSC_SUCCESS);
5506: }
5508: /*@
5509: TSGetStages - Get the number of stages and stage values
5511: Input Parameter:
5512: . ts - the `TS` context obtained from `TSCreate()`
5514: Output Parameters:
5515: + ns - the number of stages
5516: - Y - the current stage vectors
5518: Level: advanced
5520: Note:
5521: Both `ns` and `Y` can be `NULL`.
5523: .seealso: [](ch_ts), `TS`, `TSCreate()`
5524: @*/
5525: PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
5526: {
5527: PetscFunctionBegin;
5529: if (ns) PetscAssertPointer(ns, 2);
5530: if (Y) PetscAssertPointer(Y, 3);
5531: if (!ts->ops->getstages) {
5532: if (ns) *ns = 0;
5533: if (Y) *Y = NULL;
5534: } else PetscUseTypeMethod(ts, getstages, ns, Y);
5535: PetscFunctionReturn(PETSC_SUCCESS);
5536: }
5538: /*@C
5539: TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5541: Collective
5543: Input Parameters:
5544: + ts - the `TS` context
5545: . t - current timestep
5546: . U - state vector
5547: . Udot - time derivative of state vector
5548: . shift - shift to apply, see note below
5549: - ctx - an optional user context
5551: Output Parameters:
5552: + J - Jacobian matrix (not altered in this routine)
5553: - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)
5555: Level: intermediate
5557: Notes:
5558: If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5560: dF/dU + shift*dF/dUdot
5562: Most users should not need to explicitly call this routine, as it
5563: is used internally within the nonlinear solvers.
5565: This will first try to get the coloring from the `DM`. If the `DM` type has no coloring
5566: routine, then it will try to get the coloring from the matrix. This requires that the
5567: matrix have nonzero entries precomputed.
5569: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5570: @*/
5571: PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, PetscCtx ctx)
5572: {
5573: SNES snes;
5574: MatFDColoring color;
5575: PetscBool hascolor, matcolor = PETSC_FALSE;
5577: PetscFunctionBegin;
5578: PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5579: PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5580: if (!color) {
5581: DM dm;
5582: ISColoring iscoloring;
5584: PetscCall(TSGetDM(ts, &dm));
5585: PetscCall(DMHasColoring(dm, &hascolor));
5586: if (hascolor && !matcolor) {
5587: PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5588: PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5589: PetscCall(MatFDColoringSetFunction(color, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
5590: PetscCall(MatFDColoringSetFromOptions(color));
5591: PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5592: PetscCall(ISColoringDestroy(&iscoloring));
5593: } else {
5594: MatColoring mc;
5596: PetscCall(MatColoringCreate(B, &mc));
5597: PetscCall(MatColoringSetDistance(mc, 2));
5598: PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5599: PetscCall(MatColoringSetFromOptions(mc));
5600: PetscCall(MatColoringApply(mc, &iscoloring));
5601: PetscCall(MatColoringDestroy(&mc));
5602: PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5603: PetscCall(MatFDColoringSetFunction(color, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
5604: PetscCall(MatFDColoringSetFromOptions(color));
5605: PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5606: PetscCall(ISColoringDestroy(&iscoloring));
5607: }
5608: PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5609: PetscCall(PetscObjectDereference((PetscObject)color));
5610: }
5611: PetscCall(TSGetSNES(ts, &snes));
5612: PetscCall(MatFDColoringApply(B, color, U, snes));
5613: if (J != B) {
5614: PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5615: PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5616: }
5617: PetscFunctionReturn(PETSC_SUCCESS);
5618: }
5620: /*@C
5621: TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5623: Logically collective
5625: Input Parameters:
5626: + ts - the `TS` context
5627: - func - function called within `TSFunctionDomainError()`
5629: Calling sequence of `func`:
5630: + ts - the `TS` context
5631: . time - the current time (of the stage)
5632: . state - the state to check if it is valid
5633: - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable
5635: Level: intermediate
5637: Notes:
5638: `accept` must be collectively specified.
5639: If an implicit ODE solver is being used then, in addition to providing this routine, the
5640: user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
5641: function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
5642: Use `TSGetSNES()` to obtain the `SNES` object
5644: Developer Notes:
5645: The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
5646: since one takes a function pointer and the other does not.
5648: .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5649: @*/
5650: PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
5651: {
5652: PetscFunctionBegin;
5654: ts->functiondomainerror = func;
5655: PetscFunctionReturn(PETSC_SUCCESS);
5656: }
5658: /*@
5659: TSFunctionDomainError - Checks if the current state is valid
5661: Collective
5663: Input Parameters:
5664: + ts - the `TS` context
5665: . stagetime - time of the simulation
5666: - Y - state vector to check.
5668: Output Parameter:
5669: . accept - Set to `PETSC_FALSE` if the current state vector is valid.
5671: Level: developer
5673: Note:
5674: This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
5675: to check if the current state is valid.
5677: .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
5678: @*/
5679: PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
5680: {
5681: PetscFunctionBegin;
5685: PetscAssertPointer(accept, 4);
5686: *accept = PETSC_TRUE;
5687: if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5688: PetscFunctionReturn(PETSC_SUCCESS);
5689: }
5691: /*@
5692: TSClone - This function clones a time step `TS` object.
5694: Collective
5696: Input Parameter:
5697: . tsin - The input `TS`
5699: Output Parameter:
5700: . tsout - The output `TS` (cloned)
5702: Level: developer
5704: Notes:
5705: This function is used to create a clone of a `TS` object. It is used in `TSARKIMEX` for initializing the slope for first stage explicit methods.
5706: It will likely be replaced in the future with a mechanism of switching methods on the fly.
5708: 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
5709: .vb
5710: SNES snes_dup = NULL;
5711: TSGetSNES(ts,&snes_dup);
5712: TSSetSNES(ts,snes_dup);
5713: .ve
5715: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5716: @*/
5717: PetscErrorCode TSClone(TS tsin, TS *tsout)
5718: {
5719: TS t;
5720: SNES snes_start;
5721: DM dm;
5722: TSType type;
5724: PetscFunctionBegin;
5725: PetscAssertPointer(tsin, 1);
5726: *tsout = NULL;
5728: PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
5730: /* General TS description */
5731: t->numbermonitors = 0;
5732: t->setupcalled = PETSC_FALSE;
5733: t->ksp_its = 0;
5734: t->snes_its = 0;
5735: t->nwork = 0;
5736: t->rhsjacobian.time = PETSC_MIN_REAL;
5737: t->rhsjacobian.scale = 1.;
5738: t->ijacobian.shift = 1.;
5740: PetscCall(TSGetSNES(tsin, &snes_start));
5741: PetscCall(TSSetSNES(t, snes_start));
5743: PetscCall(TSGetDM(tsin, &dm));
5744: PetscCall(TSSetDM(t, dm));
5746: t->adapt = tsin->adapt;
5747: PetscCall(PetscObjectReference((PetscObject)t->adapt));
5749: t->trajectory = tsin->trajectory;
5750: PetscCall(PetscObjectReference((PetscObject)t->trajectory));
5752: t->event = tsin->event;
5753: if (t->event) t->event->refct++;
5755: t->problem_type = tsin->problem_type;
5756: t->ptime = tsin->ptime;
5757: t->ptime_prev = tsin->ptime_prev;
5758: t->time_step = tsin->time_step;
5759: t->max_time = tsin->max_time;
5760: t->steps = tsin->steps;
5761: t->max_steps = tsin->max_steps;
5762: t->equation_type = tsin->equation_type;
5763: t->atol = tsin->atol;
5764: t->rtol = tsin->rtol;
5765: t->max_snes_failures = tsin->max_snes_failures;
5766: t->max_reject = tsin->max_reject;
5767: t->errorifstepfailed = tsin->errorifstepfailed;
5769: PetscCall(TSGetType(tsin, &type));
5770: PetscCall(TSSetType(t, type));
5772: t->vec_sol = NULL;
5774: t->cfltime = tsin->cfltime;
5775: t->cfltime_local = tsin->cfltime_local;
5776: t->exact_final_time = tsin->exact_final_time;
5778: t->ops[0] = tsin->ops[0];
5780: if (((PetscObject)tsin)->fortran_func_pointers) {
5781: PetscInt i;
5782: PetscCall(PetscMalloc((10) * sizeof(PetscFortranCallbackFn *), &((PetscObject)t)->fortran_func_pointers));
5783: for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5784: }
5785: *tsout = t;
5786: PetscFunctionReturn(PETSC_SUCCESS);
5787: }
5789: static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(PetscCtx ctx, Vec x, Vec y)
5790: {
5791: TS ts = (TS)ctx;
5793: PetscFunctionBegin;
5794: PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5795: PetscFunctionReturn(PETSC_SUCCESS);
5796: }
5798: /*@
5799: TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5801: Logically Collective
5803: Input Parameter:
5804: . ts - the time stepping routine
5806: Output Parameter:
5807: . flg - `PETSC_TRUE` if the multiply is likely correct
5809: Options Database Key:
5810: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
5812: Level: advanced
5814: Note:
5815: This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5817: .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5818: @*/
5819: PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
5820: {
5821: Mat J, B;
5822: TSRHSJacobianFn *func;
5823: void *ctx;
5825: PetscFunctionBegin;
5826: PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5827: PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5828: PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5829: PetscFunctionReturn(PETSC_SUCCESS);
5830: }
5832: /*@
5833: TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5835: Logically Collective
5837: Input Parameter:
5838: . ts - the time stepping routine
5840: Output Parameter:
5841: . flg - `PETSC_TRUE` if the multiply is likely correct
5843: Options Database Key:
5844: . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
5846: Level: advanced
5848: Notes:
5849: This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5851: .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5852: @*/
5853: PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
5854: {
5855: Mat J, B;
5856: void *ctx;
5857: TSRHSJacobianFn *func;
5859: PetscFunctionBegin;
5860: PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5861: PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5862: PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5863: PetscFunctionReturn(PETSC_SUCCESS);
5864: }
5866: /*@
5867: TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
5869: Logically Collective
5871: Input Parameters:
5872: + ts - timestepping context
5873: - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5875: Options Database Key:
5876: . -ts_use_splitrhsfunction - <true,false>
5878: Level: intermediate
5880: Note:
5881: This is only for multirate methods
5883: .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
5884: @*/
5885: PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
5886: {
5887: PetscFunctionBegin;
5889: ts->use_splitrhsfunction = use_splitrhsfunction;
5890: PetscFunctionReturn(PETSC_SUCCESS);
5891: }
5893: /*@
5894: TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
5896: Not Collective
5898: Input Parameter:
5899: . ts - timestepping context
5901: Output Parameter:
5902: . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5904: Level: intermediate
5906: .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
5907: @*/
5908: PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
5909: {
5910: PetscFunctionBegin;
5912: *use_splitrhsfunction = ts->use_splitrhsfunction;
5913: PetscFunctionReturn(PETSC_SUCCESS);
5914: }
5916: /*@
5917: TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
5919: Logically Collective
5921: Input Parameters:
5922: + ts - the time-stepper
5923: - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)
5925: Level: intermediate
5927: Note:
5928: When the relationship between the nonzero structures is known and supplied the solution process can be much faster
5930: .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
5931: @*/
5932: PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
5933: {
5934: PetscFunctionBegin;
5936: ts->axpy_pattern = str;
5937: PetscFunctionReturn(PETSC_SUCCESS);
5938: }
5940: /*@
5941: TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested
5943: Collective
5945: Input Parameters:
5946: + ts - the time-stepper
5947: . n - number of the time points
5948: - time_points - array of the time points, must be increasing
5950: Options Database Key:
5951: . -ts_eval_times <t0,...tn> - Sets the evaluation times
5953: Level: intermediate
5955: Notes:
5956: The elements in `time_points` must be all increasing. They correspond to the intermediate points to be saved.
5958: `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
5960: The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may
5961: pressure the memory system when using a large number of time points.
5963: .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()`
5964: @*/
5965: PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal time_points[])
5966: {
5967: PetscBool is_sorted;
5969: PetscFunctionBegin;
5971: if (ts->eval_times) { // Reset eval_times
5972: ts->eval_times->sol_idx = 0;
5973: ts->eval_times->time_point_idx = 0;
5974: if (n != ts->eval_times->num_time_points) {
5975: PetscCall(PetscFree(ts->eval_times->time_points));
5976: PetscCall(PetscFree(ts->eval_times->sol_times));
5977: PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
5978: } else {
5979: PetscCall(PetscArrayzero(ts->eval_times->sol_times, n));
5980: for (PetscInt i = 0; i < n; i++) PetscCall(VecZeroEntries(ts->eval_times->sol_vecs[i]));
5981: }
5982: } else { // Create/initialize eval_times
5983: TSEvaluationTimes eval_times;
5984: PetscCall(PetscNew(&eval_times));
5985: PetscCall(PetscMalloc1(n, &eval_times->time_points));
5986: PetscCall(PetscMalloc1(n, &eval_times->sol_times));
5987: eval_times->reltol = 1e-6;
5988: eval_times->abstol = 10 * PETSC_MACHINE_EPSILON;
5989: eval_times->worktol = 0;
5990: ts->eval_times = eval_times;
5991: }
5992: ts->eval_times->num_time_points = n;
5993: PetscCall(PetscSortedReal(n, time_points, &is_sorted));
5994: PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted");
5995: PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n));
5996: // Note: ts->vec_sol not guaranteed to exist, so ts->eval_times->sol_vecs allocated at TSSolve time
5997: PetscFunctionReturn(PETSC_SUCCESS);
5998: }
6000: /*@C
6001: TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()`
6003: Not Collective
6005: Input Parameter:
6006: . ts - the time-stepper
6008: Output Parameters:
6009: + n - number of the time points
6010: - time_points - array of the time points
6012: Level: beginner
6014: Note:
6015: The values obtained are valid until the `TS` object is destroyed.
6017: Both `n` and `time_points` can be `NULL`.
6019: Also used to see time points set by `TSSetTimeSpan()`.
6021: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()`
6022: @*/
6023: PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[])
6024: {
6025: PetscFunctionBegin;
6027: if (n) PetscAssertPointer(n, 2);
6028: if (time_points) PetscAssertPointer(time_points, 3);
6029: if (!ts->eval_times) {
6030: if (n) *n = 0;
6031: if (time_points) *time_points = NULL;
6032: } else {
6033: if (n) *n = ts->eval_times->num_time_points;
6034: if (time_points) *time_points = ts->eval_times->time_points;
6035: }
6036: PetscFunctionReturn(PETSC_SUCCESS);
6037: }
6039: /*@C
6040: TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified
6042: Input Parameter:
6043: . ts - the `TS` context obtained from `TSCreate()`
6045: Output Parameters:
6046: + nsol - the number of solutions
6047: . sol_times - array of solution times corresponding to the solution vectors. See note below
6048: - Sols - the solution vectors
6050: Level: intermediate
6052: Notes:
6053: Both `nsol` and `Sols` can be `NULL`.
6055: Some time points in the evaluation points may be skipped by `TS` so that `nsol` is less than the number of points specified by `TSSetEvaluationTimes()`.
6056: For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times.
6058: Also used to see view solutions requested by `TSSetTimeSpan()`.
6060: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`
6061: @*/
6062: PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec *Sols[])
6063: {
6064: PetscFunctionBegin;
6066: if (nsol) PetscAssertPointer(nsol, 2);
6067: if (sol_times) PetscAssertPointer(sol_times, 3);
6068: if (Sols) PetscAssertPointer(Sols, 4);
6069: if (!ts->eval_times) {
6070: if (nsol) *nsol = 0;
6071: if (sol_times) *sol_times = NULL;
6072: if (Sols) *Sols = NULL;
6073: } else {
6074: if (nsol) *nsol = ts->eval_times->sol_idx;
6075: if (sol_times) *sol_times = ts->eval_times->sol_times;
6076: if (Sols) *Sols = ts->eval_times->sol_vecs;
6077: }
6078: PetscFunctionReturn(PETSC_SUCCESS);
6079: }
6081: /*@
6082: TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span
6084: Collective
6086: Input Parameters:
6087: + ts - the time-stepper
6088: . n - number of the time points (>=2)
6089: - span_times - array of the time points, must be increasing. The first element and the last element are the initial time and the final time respectively.
6091: Options Database Key:
6092: . -ts_time_span <t0,...tf> - Sets the time span
6094: Level: intermediate
6096: Notes:
6097: This function is identical to `TSSetEvaluationTimes()`, except that it also sets the initial time and final time for the `ts` to the first and last `span_times` entries.
6099: The elements in `span_times` must be all increasing. They correspond to the intermediate points to be saved.
6101: `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
6103: The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may
6104: pressure the memory system when using a large number of span points.
6106: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`
6107: @*/
6108: PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal span_times[])
6109: {
6110: PetscFunctionBegin;
6112: PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
6113: PetscCall(TSSetEvaluationTimes(ts, n, span_times));
6114: PetscCall(TSSetTime(ts, span_times[0]));
6115: PetscCall(TSSetMaxTime(ts, span_times[n - 1]));
6116: PetscFunctionReturn(PETSC_SUCCESS);
6117: }
6119: /*@
6120: TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.
6122: Collective
6124: Input Parameters:
6125: + ts - the `TS` context
6126: . J - Jacobian matrix (not altered in this routine)
6127: - B - newly computed Jacobian matrix to use with preconditioner
6129: Level: intermediate
6131: Notes:
6132: This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
6133: many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
6134: and multiple fields are involved.
6136: Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
6137: structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
6138: usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
6139: `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.
6141: .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
6142: @*/
6143: PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
6144: {
6145: MatColoring mc = NULL;
6146: ISColoring iscoloring = NULL;
6147: MatFDColoring matfdcoloring = NULL;
6149: PetscFunctionBegin;
6150: /* Generate new coloring after eliminating zeros in the matrix */
6151: PetscCall(MatEliminateZeros(B, PETSC_TRUE));
6152: PetscCall(MatColoringCreate(B, &mc));
6153: PetscCall(MatColoringSetDistance(mc, 2));
6154: PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
6155: PetscCall(MatColoringSetFromOptions(mc));
6156: PetscCall(MatColoringApply(mc, &iscoloring));
6157: PetscCall(MatColoringDestroy(&mc));
6158: /* Replace the old coloring with the new one */
6159: PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
6160: PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
6161: PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
6162: PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
6163: PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
6164: PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
6165: PetscCall(ISColoringDestroy(&iscoloring));
6166: PetscFunctionReturn(PETSC_SUCCESS);
6167: }