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
38: . -ts_max_steps <steps> - maximum number of time-steps to take
39: . -ts_init_time <time> - initial time to start computation
40: . -ts_final_time <time> - final time to compute to (deprecated: use `-ts_max_time`)
41: . -ts_dt <dt> - initial time step
42: . -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
43: . -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed
44: . -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails
45: . -ts_error_if_step_fails <true,false> - Error if no step succeeds
46: . -ts_rtol <rtol> - relative tolerance for local truncation error
47: . -ts_atol <atol> - Absolute tolerance for local truncation error
48: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function
49: . -ts_rhs_jacobian_test_mult_transpose - test the Jacobian at each iteration against finite difference with RHS function
50: . -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
51: . -ts_fd_color - Use finite differences with coloring to compute IJacobian
52: . -ts_monitor - print information at each timestep
53: . -ts_monitor_cancel - Cancel all monitors
54: . -ts_monitor_lg_solution - Monitor solution graphically
55: . -ts_monitor_lg_error - Monitor error graphically
56: . -ts_monitor_error - Monitors norm of error
57: . -ts_monitor_lg_timestep - Monitor timestep size graphically
58: . -ts_monitor_lg_timestep_log - Monitor log timestep size graphically
59: . -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
60: . -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
61: . -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
62: . -ts_monitor_draw_solution - Monitor solution graphically
63: . -ts_monitor_draw_solution_phase <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
64: . -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
65: . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
66: . -ts_monitor_solution_interval <interval> - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
67: . -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)
68: . -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
69: - -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
71: Level: beginner
73: Notes:
74: See `SNESSetFromOptions()` and `KSPSetFromOptions()` for how to control the nonlinear and linear solves used by the time-stepper.
76: Certain `SNES` options get reset for each new nonlinear solver, for example `-snes_lag_jacobian its` and `-snes_lag_preconditioner its`, in order
77: to retain them over the multiple nonlinear solves that `TS` uses you must also provide `-snes_lag_jacobian_persists true` and
78: `-snes_lag_preconditioner_persists true`
80: Developer Notes:
81: We should unify all the -ts_monitor options in the way that -xxx_view has been unified
83: .seealso: [](ch_ts), `TS`, `TSGetType()`
84: @*/
85: PetscErrorCode TSSetFromOptions(TS ts)
86: {
87: PetscBool opt, flg, tflg;
88: char monfilename[PETSC_MAX_PATH_LEN];
89: PetscReal time_step, tspan[100];
90: PetscInt nt = PETSC_STATIC_ARRAY_LENGTH(tspan);
91: TSExactFinalTimeOption eftopt;
92: char dir[16];
93: TSIFunctionFn *ifun;
94: const char *defaultType;
95: char typeName[256];
97: PetscFunctionBegin;
100: PetscCall(TSRegisterAll());
101: PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
103: PetscObjectOptionsBegin((PetscObject)ts);
104: if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
105: else defaultType = ifun ? TSBEULER : TSEULER;
106: PetscCall(PetscOptionsFList("-ts_type", "TS method", "TSSetType", TSList, defaultType, typeName, 256, &opt));
107: if (opt) PetscCall(TSSetType(ts, typeName));
108: else PetscCall(TSSetType(ts, defaultType));
110: /* Handle generic TS options */
111: PetscCall(PetscOptionsDeprecated("-ts_final_time", "-ts_max_time", "3.10", NULL));
112: PetscCall(PetscOptionsReal("-ts_max_time", "Maximum time to run to", "TSSetMaxTime", ts->max_time, &ts->max_time, NULL));
113: PetscCall(PetscOptionsRealArray("-ts_time_span", "Time span", "TSSetTimeSpan", tspan, &nt, &flg));
114: if (flg) PetscCall(TSSetTimeSpan(ts, nt, tspan));
115: PetscCall(PetscOptionsInt("-ts_max_steps", "Maximum number of time steps", "TSSetMaxSteps", ts->max_steps, &ts->max_steps, NULL));
116: PetscCall(PetscOptionsReal("-ts_init_time", "Initial time", "TSSetTime", ts->ptime, &ts->ptime, NULL));
117: PetscCall(PetscOptionsReal("-ts_dt", "Initial time step", "TSSetTimeStep", ts->time_step, &time_step, &flg));
118: if (flg) PetscCall(TSSetTimeStep(ts, time_step));
119: PetscCall(PetscOptionsEnum("-ts_exact_final_time", "Option for handling of final time step", "TSSetExactFinalTime", TSExactFinalTimeOptions, (PetscEnum)ts->exact_final_time, (PetscEnum *)&eftopt, &flg));
120: if (flg) PetscCall(TSSetExactFinalTime(ts, eftopt));
121: PetscCall(PetscOptionsInt("-ts_max_snes_failures", "Maximum number of nonlinear solve failures", "TSSetMaxSNESFailures", ts->max_snes_failures, &ts->max_snes_failures, &flg));
122: if (flg) PetscCall(TSSetMaxSNESFailures(ts, ts->max_snes_failures));
123: PetscCall(PetscOptionsInt("-ts_max_reject", "Maximum number of step rejections before step fails", "TSSetMaxStepRejections", ts->max_reject, &ts->max_reject, &flg));
124: if (flg) PetscCall(TSSetMaxStepRejections(ts, ts->max_reject));
125: PetscCall(PetscOptionsBool("-ts_error_if_step_fails", "Error if no step succeeds", "TSSetErrorIfStepFails", ts->errorifstepfailed, &ts->errorifstepfailed, NULL));
126: PetscCall(PetscOptionsBoundedReal("-ts_rtol", "Relative tolerance for local truncation error", "TSSetTolerances", ts->rtol, &ts->rtol, NULL, 0));
127: PetscCall(PetscOptionsBoundedReal("-ts_atol", "Absolute tolerance for local truncation error", "TSSetTolerances", ts->atol, &ts->atol, NULL, 0));
129: PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult", "Test the RHS Jacobian for consistency with RHS at each solve ", "None", ts->testjacobian, &ts->testjacobian, NULL));
130: 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));
131: PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction", "Use the split RHS function for multirate solvers ", "TSSetUseSplitRHSFunction", ts->use_splitrhsfunction, &ts->use_splitrhsfunction, NULL));
132: #if defined(PETSC_HAVE_SAWS)
133: {
134: PetscBool set;
135: flg = PETSC_FALSE;
136: PetscCall(PetscOptionsBool("-ts_saws_block", "Block for SAWs memory snooper at end of TSSolve", "PetscObjectSAWsBlock", ((PetscObject)ts)->amspublishblock, &flg, &set));
137: if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts, flg));
138: }
139: #endif
141: /* Monitor options */
142: PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL));
143: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor", "Monitor time and timestep size", "TSMonitorDefault", TSMonitorDefault, NULL));
144: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_extreme", "Monitor extreme values of the solution", "TSMonitorExtreme", TSMonitorExtreme, NULL));
145: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_solution", "View the solution at each timestep", "TSMonitorSolution", TSMonitorSolution, NULL));
146: PetscCall(TSMonitorSetFromOptions(ts, "-ts_dmswarm_monitor_moments", "Monitor moments of particle distribution", "TSDMSwarmMonitorMoments", TSDMSwarmMonitorMoments, NULL));
148: PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
149: if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename));
151: PetscCall(PetscOptionsName("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", &opt));
152: if (opt) {
153: PetscInt howoften = 1;
154: DM dm;
155: PetscBool net;
157: PetscCall(PetscOptionsInt("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", howoften, &howoften, NULL));
158: PetscCall(TSGetDM(ts, &dm));
159: PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMNETWORK, &net));
160: if (net) {
161: TSMonitorLGCtxNetwork ctx;
162: PetscCall(TSMonitorLGCtxNetworkCreate(ts, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &ctx));
163: PetscCall(TSMonitorSet(ts, TSMonitorLGCtxNetworkSolution, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxNetworkDestroy));
164: PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy", "Plot the solution with a semi-log axis", "", ctx->semilogy, &ctx->semilogy, NULL));
165: } else {
166: TSMonitorLGCtx ctx;
167: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
168: PetscCall(TSMonitorSet(ts, TSMonitorLGSolution, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
169: }
170: }
172: PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt));
173: if (opt) {
174: TSMonitorLGCtx ctx;
175: PetscInt howoften = 1;
177: PetscCall(PetscOptionsInt("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", howoften, &howoften, NULL));
178: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
179: PetscCall(TSMonitorSet(ts, TSMonitorLGError, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
180: }
181: PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_error", "View the error at each timestep", "TSMonitorError", TSMonitorError, NULL));
183: PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt));
184: if (opt) {
185: TSMonitorLGCtx ctx;
186: PetscInt howoften = 1;
188: PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
189: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
190: PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
191: }
192: PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", &opt));
193: if (opt) {
194: TSMonitorLGCtx ctx;
195: PetscInt howoften = 1;
197: PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
198: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
199: PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
200: ctx->semilogy = PETSC_TRUE;
201: }
203: PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", &opt));
204: if (opt) {
205: TSMonitorLGCtx ctx;
206: PetscInt howoften = 1;
208: PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", howoften, &howoften, NULL));
209: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
210: PetscCall(TSMonitorSet(ts, TSMonitorLGSNESIterations, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
211: }
212: PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", &opt));
213: if (opt) {
214: TSMonitorLGCtx ctx;
215: PetscInt howoften = 1;
217: PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", howoften, &howoften, NULL));
218: PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
219: PetscCall(TSMonitorSet(ts, TSMonitorLGKSPIterations, ctx, (PetscErrorCode (*)(void **))TSMonitorLGCtxDestroy));
220: }
221: PetscCall(PetscOptionsName("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", &opt));
222: if (opt) {
223: TSMonitorSPEigCtx ctx;
224: PetscInt howoften = 1;
226: PetscCall(PetscOptionsInt("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", howoften, &howoften, NULL));
227: PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
228: PetscCall(TSMonitorSet(ts, TSMonitorSPEig, ctx, (PetscErrorCode (*)(void **))TSMonitorSPEigCtxDestroy));
229: }
230: PetscCall(PetscOptionsName("-ts_monitor_sp_swarm", "Display particle phase space from the DMSwarm", "TSMonitorSPSwarm", &opt));
231: if (opt) {
232: TSMonitorSPCtx ctx;
233: PetscInt howoften = 1, retain = 0;
234: PetscBool phase = PETSC_TRUE, create = PETSC_TRUE, multispecies = PETSC_FALSE;
236: for (PetscInt i = 0; i < ts->numbermonitors; ++i)
237: if (ts->monitor[i] == TSMonitorSPSwarmSolution) {
238: create = PETSC_FALSE;
239: break;
240: }
241: if (create) {
242: PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm", "Display particles phase space from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL));
243: PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL));
244: PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL));
245: PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_multi_species", "Color particles by particle species", "TSMonitorSPSwarm", multispecies, &multispecies, NULL));
246: PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, multispecies, &ctx));
247: PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void **))TSMonitorSPCtxDestroy));
248: }
249: }
250: PetscCall(PetscOptionsName("-ts_monitor_hg_swarm", "Display particle histogram from the DMSwarm", "TSMonitorHGSwarm", &opt));
251: if (opt) {
252: TSMonitorHGCtx ctx;
253: PetscInt howoften = 1, Ns = 1;
254: PetscBool velocity = PETSC_FALSE, create = PETSC_TRUE;
256: for (PetscInt i = 0; i < ts->numbermonitors; ++i)
257: if (ts->monitor[i] == TSMonitorHGSwarmSolution) {
258: create = PETSC_FALSE;
259: break;
260: }
261: if (create) {
262: DM sw, dm;
263: PetscInt Nc, Nb;
265: PetscCall(TSGetDM(ts, &sw));
266: PetscCall(DMSwarmGetCellDM(sw, &dm));
267: PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &Nc));
268: Nb = PetscMin(20, PetscMax(10, Nc));
269: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm", "Display particles histogram from the DMSwarm", "TSMonitorHGSwarm", howoften, &howoften, NULL));
270: PetscCall(PetscOptionsBool("-ts_monitor_hg_swarm_velocity", "Plot in velocity space rather than coordinate space", "TSMonitorHGSwarm", velocity, &velocity, NULL));
271: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_species", "Number of species to histogram", "TSMonitorHGSwarm", Ns, &Ns, NULL));
272: PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_bins", "Number of histogram bins", "TSMonitorHGSwarm", Nb, &Nb, NULL));
273: PetscCall(TSMonitorHGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, Ns, Nb, velocity, &ctx));
274: PetscCall(TSMonitorSet(ts, TSMonitorHGSwarmSolution, ctx, (PetscErrorCode (*)(void **))TSMonitorHGCtxDestroy));
275: }
276: }
277: opt = PETSC_FALSE;
278: PetscCall(PetscOptionsName("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", &opt));
279: if (opt) {
280: TSMonitorDrawCtx ctx;
281: PetscInt howoften = 1;
283: PetscCall(PetscOptionsInt("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", howoften, &howoften, NULL));
284: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Computed Solution", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
285: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolution, ctx, (PetscErrorCode (*)(void **))TSMonitorDrawCtxDestroy));
286: }
287: opt = PETSC_FALSE;
288: PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", &opt));
289: if (opt) {
290: TSMonitorDrawCtx ctx;
291: PetscReal bounds[4];
292: PetscInt n = 4;
293: PetscDraw draw;
294: PetscDrawAxis axis;
296: PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", bounds, &n, NULL));
297: PetscCheck(n == 4, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Must provide bounding box of phase field");
298: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, 1, &ctx));
299: PetscCall(PetscViewerDrawGetDraw(ctx->viewer, 0, &draw));
300: PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer, 0, &axis));
301: PetscCall(PetscDrawAxisSetLimits(axis, bounds[0], bounds[2], bounds[1], bounds[3]));
302: PetscCall(PetscDrawAxisSetLabels(axis, "Phase Diagram", "Variable 1", "Variable 2"));
303: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionPhase, ctx, (PetscErrorCode (*)(void **))TSMonitorDrawCtxDestroy));
304: }
305: opt = PETSC_FALSE;
306: PetscCall(PetscOptionsName("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", &opt));
307: if (opt) {
308: TSMonitorDrawCtx ctx;
309: PetscInt howoften = 1;
311: PetscCall(PetscOptionsInt("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", howoften, &howoften, NULL));
312: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Error", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
313: PetscCall(TSMonitorSet(ts, TSMonitorDrawError, ctx, (PetscErrorCode (*)(void **))TSMonitorDrawCtxDestroy));
314: }
315: opt = PETSC_FALSE;
316: PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", &opt));
317: if (opt) {
318: TSMonitorDrawCtx ctx;
319: PetscInt howoften = 1;
321: PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", howoften, &howoften, NULL));
322: PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Solution provided by user function", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
323: PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionFunction, ctx, (PetscErrorCode (*)(void **))TSMonitorDrawCtxDestroy));
324: }
326: opt = PETSC_FALSE;
327: 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));
328: if (flg) {
329: TSMonitorVTKCtx ctx;
331: PetscCall(TSMonitorSolutionVTKCtxCreate(monfilename, &ctx));
332: PetscCall(PetscOptionsInt("-ts_monitor_solution_vtk_interval", "Save every interval time step (-1 for last step only)", NULL, ctx->interval, &ctx->interval, NULL));
333: PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, void *))TSMonitorSolutionVTK, ctx, (PetscErrorCode (*)(void **))TSMonitorSolutionVTKDestroy));
334: }
336: PetscCall(PetscOptionsString("-ts_monitor_dmda_ray", "Display a ray of the solution", "None", "y=0", dir, sizeof(dir), &flg));
337: if (flg) {
338: TSMonitorDMDARayCtx *rayctx;
339: int ray = 0;
340: DMDirection ddir;
341: DM da;
342: PetscMPIInt rank;
344: PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
345: if (dir[0] == 'x') ddir = DM_X;
346: else if (dir[0] == 'y') ddir = DM_Y;
347: else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
348: sscanf(dir + 2, "%d", &ray);
350: PetscCall(PetscInfo((PetscObject)ts, "Displaying DMDA ray %c = %d\n", dir[0], ray));
351: PetscCall(PetscNew(&rayctx));
352: PetscCall(TSGetDM(ts, &da));
353: PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
354: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts), &rank));
355: if (rank == 0) PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, NULL, NULL, 0, 0, 600, 300, &rayctx->viewer));
356: rayctx->lgctx = NULL;
357: PetscCall(TSMonitorSet(ts, TSMonitorDMDARay, rayctx, TSMonitorDMDARayDestroy));
358: }
359: PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray", "Display a ray of the solution", "None", "x=0", dir, sizeof(dir), &flg));
360: if (flg) {
361: TSMonitorDMDARayCtx *rayctx;
362: int ray = 0;
363: DMDirection ddir;
364: DM da;
365: PetscInt howoften = 1;
367: PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
368: if (dir[0] == 'x') ddir = DM_X;
369: else if (dir[0] == 'y') ddir = DM_Y;
370: else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
371: sscanf(dir + 2, "%d", &ray);
373: PetscCall(PetscInfo((PetscObject)ts, "Displaying LG DMDA ray %c = %d\n", dir[0], ray));
374: PetscCall(PetscNew(&rayctx));
375: PetscCall(TSGetDM(ts, &da));
376: PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
377: PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &rayctx->lgctx));
378: PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
379: }
381: PetscCall(PetscOptionsName("-ts_monitor_envelope", "Monitor maximum and minimum value of each component of the solution", "TSMonitorEnvelope", &opt));
382: if (opt) {
383: TSMonitorEnvelopeCtx ctx;
385: PetscCall(TSMonitorEnvelopeCtxCreate(ts, &ctx));
386: PetscCall(TSMonitorSet(ts, TSMonitorEnvelope, ctx, (PetscErrorCode (*)(void **))TSMonitorEnvelopeCtxDestroy));
387: }
388: flg = PETSC_FALSE;
389: PetscCall(PetscOptionsBool("-ts_monitor_cancel", "Remove all monitors", "TSMonitorCancel", flg, &flg, &opt));
390: if (opt && flg) PetscCall(TSMonitorCancel(ts));
392: flg = PETSC_FALSE;
393: PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeIJacobianDefaultColor", flg, &flg, NULL));
394: if (flg) {
395: DM dm;
397: PetscCall(TSGetDM(ts, &dm));
398: PetscCall(DMTSUnsetIJacobianContext_Internal(dm));
399: PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
400: PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
401: }
403: /* Handle specific TS options */
404: PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject);
406: /* Handle TSAdapt options */
407: PetscCall(TSGetAdapt(ts, &ts->adapt));
408: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
409: PetscCall(TSAdaptSetFromOptions(ts->adapt, PetscOptionsObject));
411: /* TS trajectory must be set after TS, since it may use some TS options above */
412: tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
413: PetscCall(PetscOptionsBool("-ts_save_trajectory", "Save the solution at each timestep", "TSSetSaveTrajectory", tflg, &tflg, NULL));
414: if (tflg) PetscCall(TSSetSaveTrajectory(ts));
416: PetscCall(TSAdjointSetFromOptions(ts, PetscOptionsObject));
418: /* process any options handlers added with PetscObjectAddOptionsHandler() */
419: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject));
420: PetscOptionsEnd();
422: if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory, ts));
424: /* why do we have to do this here and not during TSSetUp? */
425: PetscCall(TSGetSNES(ts, &ts->snes));
426: if (ts->problem_type == TS_LINEAR) {
427: PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &flg, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
428: if (!flg) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
429: }
430: PetscCall(SNESSetFromOptions(ts->snes));
431: PetscFunctionReturn(PETSC_SUCCESS);
432: }
434: /*@
435: TSGetTrajectory - Gets the trajectory from a `TS` if it exists
437: Collective
439: Input Parameter:
440: . ts - the `TS` context obtained from `TSCreate()`
442: Output Parameter:
443: . tr - the `TSTrajectory` object, if it exists
445: Level: advanced
447: Note:
448: This routine should be called after all `TS` options have been set
450: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()`
451: @*/
452: PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr)
453: {
454: PetscFunctionBegin;
456: *tr = ts->trajectory;
457: PetscFunctionReturn(PETSC_SUCCESS);
458: }
460: /*@
461: TSSetSaveTrajectory - Causes the `TS` to save its solutions as it iterates forward in time in a `TSTrajectory` object
463: Collective
465: Input Parameter:
466: . ts - the `TS` context obtained from `TSCreate()`
468: Options Database Keys:
469: + -ts_save_trajectory - saves the trajectory to a file
470: - -ts_trajectory_type type - set trajectory type
472: Level: intermediate
474: Notes:
475: This routine should be called after all `TS` options have been set
477: The `TSTRAJECTORYVISUALIZATION` files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
478: MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
480: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`
481: @*/
482: PetscErrorCode TSSetSaveTrajectory(TS ts)
483: {
484: PetscFunctionBegin;
486: if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
487: PetscFunctionReturn(PETSC_SUCCESS);
488: }
490: /*@
491: TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object
493: Collective
495: Input Parameter:
496: . ts - the `TS` context obtained from `TSCreate()`
498: Level: intermediate
500: .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()`
501: @*/
502: PetscErrorCode TSResetTrajectory(TS ts)
503: {
504: PetscFunctionBegin;
506: if (ts->trajectory) {
507: PetscCall(TSTrajectoryDestroy(&ts->trajectory));
508: PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
509: }
510: PetscFunctionReturn(PETSC_SUCCESS);
511: }
513: /*@
514: TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from a `TS`
516: Collective
518: Input Parameter:
519: . ts - the `TS` context obtained from `TSCreate()`
521: Level: intermediate
523: .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()`
524: @*/
525: PetscErrorCode TSRemoveTrajectory(TS ts)
526: {
527: PetscFunctionBegin;
529: if (ts->trajectory) PetscCall(TSTrajectoryDestroy(&ts->trajectory));
530: PetscFunctionReturn(PETSC_SUCCESS);
531: }
533: /*@
534: TSComputeRHSJacobian - Computes the Jacobian matrix that has been
535: set with `TSSetRHSJacobian()`.
537: Collective
539: Input Parameters:
540: + ts - the `TS` context
541: . t - current timestep
542: - U - input vector
544: Output Parameters:
545: + A - Jacobian matrix
546: - B - optional preconditioning matrix
548: Level: developer
550: Note:
551: Most users should not need to explicitly call this routine, as it
552: is used internally within the nonlinear solvers.
554: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `KSPSetOperators()`
555: @*/
556: PetscErrorCode TSComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B)
557: {
558: PetscObjectState Ustate;
559: PetscObjectId Uid;
560: DM dm;
561: DMTS tsdm;
562: TSRHSJacobianFn *rhsjacobianfunc;
563: void *ctx;
564: TSRHSFunctionFn *rhsfunction;
566: PetscFunctionBegin;
569: PetscCheckSameComm(ts, 1, U, 3);
570: PetscCall(TSGetDM(ts, &dm));
571: PetscCall(DMGetDMTS(dm, &tsdm));
572: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
573: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobianfunc, &ctx));
574: PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
575: PetscCall(PetscObjectGetId((PetscObject)U, &Uid));
577: if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(PETSC_SUCCESS);
579: 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);
580: if (rhsjacobianfunc) {
581: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
582: PetscCallBack("TS callback Jacobian", (*rhsjacobianfunc)(ts, t, U, A, B, ctx));
583: ts->rhsjacs++;
584: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
585: } else {
586: PetscCall(MatZeroEntries(A));
587: if (B && A != B) PetscCall(MatZeroEntries(B));
588: }
589: ts->rhsjacobian.time = t;
590: ts->rhsjacobian.shift = 0;
591: ts->rhsjacobian.scale = 1.;
592: PetscCall(PetscObjectGetId((PetscObject)U, &ts->rhsjacobian.Xid));
593: PetscCall(PetscObjectStateGet((PetscObject)U, &ts->rhsjacobian.Xstate));
594: PetscFunctionReturn(PETSC_SUCCESS);
595: }
597: /*@
598: TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS`
600: Collective
602: Input Parameters:
603: + ts - the `TS` context
604: . t - current time
605: - U - state vector
607: Output Parameter:
608: . y - right-hand side
610: Level: developer
612: Note:
613: Most users should not need to explicitly call this routine, as it
614: is used internally within the nonlinear solvers.
616: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
617: @*/
618: PetscErrorCode TSComputeRHSFunction(TS ts, PetscReal t, Vec U, Vec y)
619: {
620: TSRHSFunctionFn *rhsfunction;
621: TSIFunctionFn *ifunction;
622: void *ctx;
623: DM dm;
625: PetscFunctionBegin;
629: PetscCall(TSGetDM(ts, &dm));
630: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx));
631: PetscCall(DMTSGetIFunction(dm, &ifunction, NULL));
633: PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");
635: if (rhsfunction) {
636: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, y, 0));
637: PetscCall(VecLockReadPush(U));
638: PetscCallBack("TS callback right-hand-side", (*rhsfunction)(ts, t, U, y, ctx));
639: PetscCall(VecLockReadPop(U));
640: ts->rhsfuncs++;
641: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, y, 0));
642: } else PetscCall(VecZeroEntries(y));
643: PetscFunctionReturn(PETSC_SUCCESS);
644: }
646: /*@
647: TSComputeSolutionFunction - Evaluates the solution function.
649: Collective
651: Input Parameters:
652: + ts - the `TS` context
653: - t - current time
655: Output Parameter:
656: . U - the solution
658: Level: developer
660: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
661: @*/
662: PetscErrorCode TSComputeSolutionFunction(TS ts, PetscReal t, Vec U)
663: {
664: TSSolutionFn *solutionfunction;
665: void *ctx;
666: DM dm;
668: PetscFunctionBegin;
671: PetscCall(TSGetDM(ts, &dm));
672: PetscCall(DMTSGetSolutionFunction(dm, &solutionfunction, &ctx));
673: if (solutionfunction) PetscCallBack("TS callback solution", (*solutionfunction)(ts, t, U, ctx));
674: PetscFunctionReturn(PETSC_SUCCESS);
675: }
676: /*@
677: TSComputeForcingFunction - Evaluates the forcing function.
679: Collective
681: Input Parameters:
682: + ts - the `TS` context
683: - t - current time
685: Output Parameter:
686: . U - the function value
688: Level: developer
690: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
691: @*/
692: PetscErrorCode TSComputeForcingFunction(TS ts, PetscReal t, Vec U)
693: {
694: void *ctx;
695: DM dm;
696: TSForcingFn *forcing;
698: PetscFunctionBegin;
701: PetscCall(TSGetDM(ts, &dm));
702: PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx));
704: if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx));
705: PetscFunctionReturn(PETSC_SUCCESS);
706: }
708: PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs)
709: {
710: Mat A, B;
711: TSIJacobianFn *ijacobian;
713: PetscFunctionBegin;
714: if (Arhs) *Arhs = NULL;
715: if (Brhs) *Brhs = NULL;
716: PetscCall(TSGetIJacobian(ts, &A, &B, &ijacobian, NULL));
717: if (Arhs) {
718: if (!ts->Arhs) {
719: if (ijacobian) {
720: PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &ts->Arhs));
721: PetscCall(TSSetMatStructure(ts, SAME_NONZERO_PATTERN));
722: } else {
723: ts->Arhs = A;
724: PetscCall(PetscObjectReference((PetscObject)A));
725: }
726: } else {
727: PetscBool flg;
728: PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
729: /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */
730: if (flg && !ijacobian && ts->Arhs == ts->Brhs) {
731: PetscCall(PetscObjectDereference((PetscObject)ts->Arhs));
732: ts->Arhs = A;
733: PetscCall(PetscObjectReference((PetscObject)A));
734: }
735: }
736: *Arhs = ts->Arhs;
737: }
738: if (Brhs) {
739: if (!ts->Brhs) {
740: if (A != B) {
741: if (ijacobian) {
742: PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &ts->Brhs));
743: } else {
744: ts->Brhs = B;
745: PetscCall(PetscObjectReference((PetscObject)B));
746: }
747: } else {
748: PetscCall(PetscObjectReference((PetscObject)ts->Arhs));
749: ts->Brhs = ts->Arhs;
750: }
751: }
752: *Brhs = ts->Brhs;
753: }
754: PetscFunctionReturn(PETSC_SUCCESS);
755: }
757: /*@
758: TSComputeIFunction - Evaluates the DAE residual written in the implicit form F(t,U,Udot)=0
760: Collective
762: Input Parameters:
763: + ts - the `TS` context
764: . t - current time
765: . U - state vector
766: . Udot - time derivative of state vector
767: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSFunction should be kept separate
769: Output Parameter:
770: . Y - right-hand side
772: Level: developer
774: Note:
775: Most users should not need to explicitly call this routine, as it
776: is used internally within the nonlinear solvers.
778: If the user did not write their equations in implicit form, this
779: function recasts them in implicit form.
781: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSComputeRHSFunction()`
782: @*/
783: PetscErrorCode TSComputeIFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec Y, PetscBool imex)
784: {
785: TSIFunctionFn *ifunction;
786: TSRHSFunctionFn *rhsfunction;
787: void *ctx;
788: DM dm;
790: PetscFunctionBegin;
796: PetscCall(TSGetDM(ts, &dm));
797: PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx));
798: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
800: PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");
802: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, Udot, Y));
803: if (ifunction) {
804: PetscCallBack("TS callback implicit function", (*ifunction)(ts, t, U, Udot, Y, ctx));
805: ts->ifuncs++;
806: }
807: if (imex) {
808: if (!ifunction) PetscCall(VecCopy(Udot, Y));
809: } else if (rhsfunction) {
810: if (ifunction) {
811: Vec Frhs;
813: PetscCall(DMGetGlobalVector(dm, &Frhs));
814: PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
815: PetscCall(VecAXPY(Y, -1, Frhs));
816: PetscCall(DMRestoreGlobalVector(dm, &Frhs));
817: } else {
818: PetscCall(TSComputeRHSFunction(ts, t, U, Y));
819: PetscCall(VecAYPX(Y, -1, Udot));
820: }
821: }
822: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, Udot, Y));
823: PetscFunctionReturn(PETSC_SUCCESS);
824: }
826: /*
827: TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call `TSComputeRHSJacobian()` on it.
829: Note:
830: This routine is needed when one switches from `TSComputeIJacobian()` to `TSComputeRHSJacobian()` because the Jacobian matrix may be shifted or scaled in `TSComputeIJacobian()`.
832: */
833: static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B)
834: {
835: PetscFunctionBegin;
837: PetscCheck(A == ts->Arhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Amat");
838: PetscCheck(B == ts->Brhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Bmat");
840: if (ts->rhsjacobian.shift) PetscCall(MatShift(A, -ts->rhsjacobian.shift));
841: if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(A, -1));
842: if (B && B == ts->Brhs && A != B) {
843: if (ts->rhsjacobian.shift) PetscCall(MatShift(B, -ts->rhsjacobian.shift));
844: if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(B, -1));
845: }
846: ts->rhsjacobian.shift = 0;
847: ts->rhsjacobian.scale = 1.;
848: PetscFunctionReturn(PETSC_SUCCESS);
849: }
851: /*@
852: TSComputeIJacobian - Evaluates the Jacobian of the DAE
854: Collective
856: Input Parameters:
857: + ts - the `TS` context
858: . t - current timestep
859: . U - state vector
860: . Udot - time derivative of state vector
861: . shift - shift to apply, see note below
862: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSJacobian should be kept separate
864: Output Parameters:
865: + A - Jacobian matrix
866: - B - matrix from which the preconditioner is constructed; often the same as `A`
868: Level: developer
870: Notes:
871: If F(t,U,Udot)=0 is the DAE, the required Jacobian is
872: .vb
873: dF/dU + shift*dF/dUdot
874: .ve
875: Most users should not need to explicitly call this routine, as it
876: is used internally within the nonlinear solvers.
878: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`
879: @*/
880: PetscErrorCode TSComputeIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex)
881: {
882: TSIJacobianFn *ijacobian;
883: TSRHSJacobianFn *rhsjacobian;
884: DM dm;
885: void *ctx;
887: PetscFunctionBegin;
894: PetscCall(TSGetDM(ts, &dm));
895: PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx));
896: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));
898: PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
900: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
901: if (ijacobian) {
902: PetscCallBack("TS callback implicit Jacobian", (*ijacobian)(ts, t, U, Udot, shift, A, B, ctx));
903: ts->ijacs++;
904: }
905: if (imex) {
906: if (!ijacobian) { /* system was written as Udot = G(t,U) */
907: PetscBool assembled;
908: if (rhsjacobian) {
909: Mat Arhs = NULL;
910: PetscCall(TSGetRHSMats_Private(ts, &Arhs, NULL));
911: if (A == Arhs) {
912: 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 */
913: ts->rhsjacobian.time = PETSC_MIN_REAL;
914: }
915: }
916: PetscCall(MatZeroEntries(A));
917: PetscCall(MatAssembled(A, &assembled));
918: if (!assembled) {
919: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
920: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
921: }
922: PetscCall(MatShift(A, shift));
923: if (A != B) {
924: PetscCall(MatZeroEntries(B));
925: PetscCall(MatAssembled(B, &assembled));
926: if (!assembled) {
927: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
928: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
929: }
930: PetscCall(MatShift(B, shift));
931: }
932: }
933: } else {
934: Mat Arhs = NULL, Brhs = NULL;
936: /* RHSJacobian needs to be converted to part of IJacobian if exists */
937: if (rhsjacobian) PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
938: if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */
939: PetscObjectState Ustate;
940: PetscObjectId Uid;
941: TSRHSFunctionFn *rhsfunction;
943: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
944: PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
945: PetscCall(PetscObjectGetId((PetscObject)U, &Uid));
946: if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) &&
947: ts->rhsjacobian.scale == -1.) { /* No need to recompute RHSJacobian */
948: PetscCall(MatShift(A, shift - ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */
949: if (A != B) PetscCall(MatShift(B, shift - ts->rhsjacobian.shift));
950: } else {
951: PetscBool flg;
953: if (ts->rhsjacobian.reuse) { /* Undo the damage */
954: /* MatScale has a short path for this case.
955: However, this code path is taken the first time TSComputeRHSJacobian is called
956: and the matrices have not been assembled yet */
957: PetscCall(TSRecoverRHSJacobian(ts, A, B));
958: }
959: PetscCall(TSComputeRHSJacobian(ts, t, U, A, B));
960: PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
961: /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */
962: if (!flg) {
963: PetscCall(MatScale(A, -1));
964: PetscCall(MatShift(A, shift));
965: }
966: if (A != B) {
967: PetscCall(MatScale(B, -1));
968: PetscCall(MatShift(B, shift));
969: }
970: }
971: ts->rhsjacobian.scale = -1;
972: ts->rhsjacobian.shift = shift;
973: } else if (Arhs) { /* Both IJacobian and RHSJacobian */
974: if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */
975: PetscCall(MatZeroEntries(A));
976: PetscCall(MatShift(A, shift));
977: if (A != B) {
978: PetscCall(MatZeroEntries(B));
979: PetscCall(MatShift(B, shift));
980: }
981: }
982: PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
983: PetscCall(MatAXPY(A, -1, Arhs, ts->axpy_pattern));
984: if (A != B) PetscCall(MatAXPY(B, -1, Brhs, ts->axpy_pattern));
985: }
986: }
987: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
988: PetscFunctionReturn(PETSC_SUCCESS);
989: }
991: /*@C
992: TSSetRHSFunction - Sets the routine for evaluating the function,
993: where U_t = G(t,u).
995: Logically Collective
997: Input Parameters:
998: + ts - the `TS` context obtained from `TSCreate()`
999: . r - vector to put the computed right-hand side (or `NULL` to have it created)
1000: . f - routine for evaluating the right-hand-side function
1001: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
1003: Level: beginner
1005: Note:
1006: You must call this function or `TSSetIFunction()` to define your ODE. You cannot use this function when solving a DAE.
1008: .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1009: @*/
1010: PetscErrorCode TSSetRHSFunction(TS ts, Vec r, TSRHSFunctionFn *f, void *ctx)
1011: {
1012: SNES snes;
1013: Vec ralloc = NULL;
1014: DM dm;
1016: PetscFunctionBegin;
1020: PetscCall(TSGetDM(ts, &dm));
1021: PetscCall(DMTSSetRHSFunction(dm, f, ctx));
1022: PetscCall(TSGetSNES(ts, &snes));
1023: if (!r && !ts->dm && ts->vec_sol) {
1024: PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1025: r = ralloc;
1026: }
1027: PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1028: PetscCall(VecDestroy(&ralloc));
1029: PetscFunctionReturn(PETSC_SUCCESS);
1030: }
1032: /*@C
1033: TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
1035: Logically Collective
1037: Input Parameters:
1038: + ts - the `TS` context obtained from `TSCreate()`
1039: . f - routine for evaluating the solution
1040: - ctx - [optional] user-defined context for private data for the
1041: function evaluation routine (may be `NULL`)
1043: Options Database Keys:
1044: + -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided `TSSetSolutionFunction()`
1045: - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
1047: Level: intermediate
1049: Notes:
1050: This routine is used for testing accuracy of time integration schemes when you already know the solution.
1051: If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
1052: create closed-form solutions with non-physical forcing terms.
1054: For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.
1056: .seealso: [](ch_ts), `TS`, `TSSolutionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()`
1057: @*/
1058: PetscErrorCode TSSetSolutionFunction(TS ts, TSSolutionFn *f, void *ctx)
1059: {
1060: DM dm;
1062: PetscFunctionBegin;
1064: PetscCall(TSGetDM(ts, &dm));
1065: PetscCall(DMTSSetSolutionFunction(dm, f, ctx));
1066: PetscFunctionReturn(PETSC_SUCCESS);
1067: }
1069: /*@C
1070: TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
1072: Logically Collective
1074: Input Parameters:
1075: + ts - the `TS` context obtained from `TSCreate()`
1076: . func - routine for evaluating the forcing function
1077: - ctx - [optional] user-defined context for private data for the function evaluation routine
1078: (may be `NULL`)
1080: Level: intermediate
1082: Notes:
1083: This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
1084: create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the
1085: definition of the problem you are solving and hence possibly introducing bugs.
1087: This replaces the ODE F(u,u_t,t) = 0 the `TS` is solving with F(u,u_t,t) - func(t) = 0
1089: This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the
1090: parameters can be passed in the ctx variable.
1092: For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.
1094: .seealso: [](ch_ts), `TS`, `TSForcingFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`,
1095: `TSComputeSolutionFunction()`, `TSSetSolutionFunction()`
1096: @*/
1097: PetscErrorCode TSSetForcingFunction(TS ts, TSForcingFn *func, void *ctx)
1098: {
1099: DM dm;
1101: PetscFunctionBegin;
1103: PetscCall(TSGetDM(ts, &dm));
1104: PetscCall(DMTSSetForcingFunction(dm, func, ctx));
1105: PetscFunctionReturn(PETSC_SUCCESS);
1106: }
1108: /*@C
1109: TSSetRHSJacobian - Sets the function to compute the Jacobian of G,
1110: where U_t = G(U,t), as well as the location to store the matrix.
1112: Logically Collective
1114: Input Parameters:
1115: + ts - the `TS` context obtained from `TSCreate()`
1116: . Amat - (approximate) location to store Jacobian matrix entries computed by `f`
1117: . Pmat - matrix from which preconditioner is to be constructed (usually the same as `Amat`)
1118: . f - the Jacobian evaluation routine
1119: - ctx - [optional] user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1121: Level: beginner
1123: Notes:
1124: You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1126: The `TS` solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f()`
1127: You should not assume the values are the same in the next call to f() as you set them in the previous call.
1129: .seealso: [](ch_ts), `TS`, `TSRHSJacobianFn`, `SNESComputeJacobianDefaultColor()`,
1130: `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()`, `TSRHSFunctionFn`, `TSIFunctionFn`
1131: @*/
1132: PetscErrorCode TSSetRHSJacobian(TS ts, Mat Amat, Mat Pmat, TSRHSJacobianFn *f, void *ctx)
1133: {
1134: SNES snes;
1135: DM dm;
1136: TSIJacobianFn *ijacobian;
1138: PetscFunctionBegin;
1142: if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1143: if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);
1145: PetscCall(TSGetDM(ts, &dm));
1146: PetscCall(DMTSSetRHSJacobian(dm, f, ctx));
1147: PetscCall(DMTSGetIJacobian(dm, &ijacobian, NULL));
1148: PetscCall(TSGetSNES(ts, &snes));
1149: if (!ijacobian) PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1150: if (Amat) {
1151: PetscCall(PetscObjectReference((PetscObject)Amat));
1152: PetscCall(MatDestroy(&ts->Arhs));
1153: ts->Arhs = Amat;
1154: }
1155: if (Pmat) {
1156: PetscCall(PetscObjectReference((PetscObject)Pmat));
1157: PetscCall(MatDestroy(&ts->Brhs));
1158: ts->Brhs = Pmat;
1159: }
1160: PetscFunctionReturn(PETSC_SUCCESS);
1161: }
1163: /*@C
1164: TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
1166: Logically Collective
1168: Input Parameters:
1169: + ts - the `TS` context obtained from `TSCreate()`
1170: . r - vector to hold the residual (or `NULL` to have it created internally)
1171: . f - the function evaluation routine
1172: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)
1174: Level: beginner
1176: Note:
1177: The user MUST call either this routine or `TSSetRHSFunction()` to define the ODE. When solving DAEs you must use this function.
1179: .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `TSSetRHSJacobian()`, `TSSetRHSFunction()`,
1180: `TSSetIJacobian()`
1181: @*/
1182: PetscErrorCode TSSetIFunction(TS ts, Vec r, TSIFunctionFn *f, void *ctx)
1183: {
1184: SNES snes;
1185: Vec ralloc = NULL;
1186: DM dm;
1188: PetscFunctionBegin;
1192: PetscCall(TSGetDM(ts, &dm));
1193: PetscCall(DMTSSetIFunction(dm, f, ctx));
1195: PetscCall(TSGetSNES(ts, &snes));
1196: if (!r && !ts->dm && ts->vec_sol) {
1197: PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1198: r = ralloc;
1199: }
1200: PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1201: PetscCall(VecDestroy(&ralloc));
1202: PetscFunctionReturn(PETSC_SUCCESS);
1203: }
1205: /*@C
1206: TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it.
1208: Not Collective
1210: Input Parameter:
1211: . ts - the `TS` context
1213: Output Parameters:
1214: + r - vector to hold residual (or `NULL`)
1215: . func - the function to compute residual (or `NULL`)
1216: - ctx - the function context (or `NULL`)
1218: Level: advanced
1220: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`
1221: @*/
1222: PetscErrorCode TSGetIFunction(TS ts, Vec *r, TSIFunctionFn **func, void **ctx)
1223: {
1224: SNES snes;
1225: DM dm;
1227: PetscFunctionBegin;
1229: PetscCall(TSGetSNES(ts, &snes));
1230: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1231: PetscCall(TSGetDM(ts, &dm));
1232: PetscCall(DMTSGetIFunction(dm, func, ctx));
1233: PetscFunctionReturn(PETSC_SUCCESS);
1234: }
1236: /*@C
1237: TSGetRHSFunction - Returns the vector where the right-hand side is stored and the function/context to compute it.
1239: Not Collective
1241: Input Parameter:
1242: . ts - the `TS` context
1244: Output Parameters:
1245: + r - vector to hold computed right-hand side (or `NULL`)
1246: . func - the function to compute right-hand side (or `NULL`)
1247: - ctx - the function context (or `NULL`)
1249: Level: advanced
1251: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `SNESGetFunction()`
1252: @*/
1253: PetscErrorCode TSGetRHSFunction(TS ts, Vec *r, TSRHSFunctionFn **func, void **ctx)
1254: {
1255: SNES snes;
1256: DM dm;
1258: PetscFunctionBegin;
1260: PetscCall(TSGetSNES(ts, &snes));
1261: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1262: PetscCall(TSGetDM(ts, &dm));
1263: PetscCall(DMTSGetRHSFunction(dm, func, ctx));
1264: PetscFunctionReturn(PETSC_SUCCESS);
1265: }
1267: /*@C
1268: TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1269: provided with `TSSetIFunction()`.
1271: Logically Collective
1273: Input Parameters:
1274: + ts - the `TS` context obtained from `TSCreate()`
1275: . Amat - (approximate) matrix to store Jacobian entries computed by `f`
1276: . Pmat - matrix used to compute preconditioner (usually the same as `Amat`)
1277: . f - the Jacobian evaluation routine
1278: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1280: Level: beginner
1282: Notes:
1283: The matrices `Amat` and `Pmat` are exactly the matrices that are used by `SNES` for the nonlinear solve.
1285: If you know the operator Amat has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
1286: space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
1288: The matrix dF/dU + a*dF/dU_t you provide turns out to be
1289: the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1290: The time integrator internally approximates U_t by W+a*U where the positive "shift"
1291: a and vector W depend on the integration method, step size, and past states. For example with
1292: the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1293: W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1295: You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1297: The TS solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f`
1298: You should not assume the values are the same in the next call to `f` as you set them in the previous call.
1300: In case `TSSetRHSJacobian()` is also used in conjunction with a fully-implicit solver,
1301: multilevel linear solvers, e.g. `PCMG`, will likely not work due to the way `TS` handles rhs matrices.
1303: .seealso: [](ch_ts), `TS`, `TSIJacobianFn`, `TSSetIFunction()`, `TSSetRHSJacobian()`,
1304: `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()`
1305: @*/
1306: PetscErrorCode TSSetIJacobian(TS ts, Mat Amat, Mat Pmat, TSIJacobianFn *f, void *ctx)
1307: {
1308: SNES snes;
1309: DM dm;
1311: PetscFunctionBegin;
1315: if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1316: if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);
1318: PetscCall(TSGetDM(ts, &dm));
1319: PetscCall(DMTSSetIJacobian(dm, f, ctx));
1321: PetscCall(TSGetSNES(ts, &snes));
1322: PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1323: PetscFunctionReturn(PETSC_SUCCESS);
1324: }
1326: /*@
1327: TSRHSJacobianSetReuse - restore the RHS Jacobian before calling the user-provided `TSRHSJacobianFn` function again
1329: Logically Collective
1331: Input Parameters:
1332: + ts - `TS` context obtained from `TSCreate()`
1333: - reuse - `PETSC_TRUE` if the RHS Jacobian
1335: Level: intermediate
1337: Notes:
1338: Without this flag, `TS` will change the sign and shift the RHS Jacobian for a
1339: finite-time-step implicit solve, in which case the user function will need to recompute the
1340: entire Jacobian. The `reuse `flag must be set if the evaluation function assumes that the
1341: matrix entries have not been changed by the `TS`.
1343: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
1344: @*/
1345: PetscErrorCode TSRHSJacobianSetReuse(TS ts, PetscBool reuse)
1346: {
1347: PetscFunctionBegin;
1348: ts->rhsjacobian.reuse = reuse;
1349: PetscFunctionReturn(PETSC_SUCCESS);
1350: }
1352: /*@C
1353: TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved.
1355: Logically Collective
1357: Input Parameters:
1358: + ts - the `TS` context obtained from `TSCreate()`
1359: . F - vector to hold the residual (or `NULL` to have it created internally)
1360: . fun - the function evaluation routine
1361: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)
1363: Level: beginner
1365: .seealso: [](ch_ts), `TS`, `TSI2FunctionFn`, `TSSetI2Jacobian()`, `TSSetIFunction()`,
1366: `TSCreate()`, `TSSetRHSFunction()`
1367: @*/
1368: PetscErrorCode TSSetI2Function(TS ts, Vec F, TSI2FunctionFn *fun, void *ctx)
1369: {
1370: DM dm;
1372: PetscFunctionBegin;
1375: PetscCall(TSSetIFunction(ts, F, NULL, NULL));
1376: PetscCall(TSGetDM(ts, &dm));
1377: PetscCall(DMTSSetI2Function(dm, fun, ctx));
1378: PetscFunctionReturn(PETSC_SUCCESS);
1379: }
1381: /*@C
1382: TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it.
1384: Not Collective
1386: Input Parameter:
1387: . ts - the `TS` context
1389: Output Parameters:
1390: + r - vector to hold residual (or `NULL`)
1391: . fun - the function to compute residual (or `NULL`)
1392: - ctx - the function context (or `NULL`)
1394: Level: advanced
1396: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()`
1397: @*/
1398: PetscErrorCode TSGetI2Function(TS ts, Vec *r, TSI2FunctionFn **fun, void **ctx)
1399: {
1400: SNES snes;
1401: DM dm;
1403: PetscFunctionBegin;
1405: PetscCall(TSGetSNES(ts, &snes));
1406: PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1407: PetscCall(TSGetDM(ts, &dm));
1408: PetscCall(DMTSGetI2Function(dm, fun, ctx));
1409: PetscFunctionReturn(PETSC_SUCCESS);
1410: }
1412: /*@C
1413: TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t + a*dF/dU_tt
1414: where F(t,U,U_t,U_tt) is the function you provided with `TSSetI2Function()`.
1416: Logically Collective
1418: Input Parameters:
1419: + ts - the `TS` context obtained from `TSCreate()`
1420: . J - matrix to hold the Jacobian values
1421: . P - matrix for constructing the preconditioner (may be same as `J`)
1422: . jac - the Jacobian evaluation routine, see `TSI2JacobianFn` for the calling sequence
1423: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)
1425: Level: beginner
1427: Notes:
1428: The matrices `J` and `P` are exactly the matrices that are used by `SNES` for the nonlinear solve.
1430: The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be
1431: 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.
1432: The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U where the positive "shift"
1433: parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states.
1435: .seealso: [](ch_ts), `TS`, `TSI2JacobianFn`, `TSSetI2Function()`, `TSGetI2Jacobian()`
1436: @*/
1437: PetscErrorCode TSSetI2Jacobian(TS ts, Mat J, Mat P, TSI2JacobianFn *jac, void *ctx)
1438: {
1439: DM dm;
1441: PetscFunctionBegin;
1445: PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL));
1446: PetscCall(TSGetDM(ts, &dm));
1447: PetscCall(DMTSSetI2Jacobian(dm, jac, ctx));
1448: PetscFunctionReturn(PETSC_SUCCESS);
1449: }
1451: /*@C
1452: TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.
1454: Not Collective, but parallel objects are returned if `TS` is parallel
1456: Input Parameter:
1457: . ts - The `TS` context obtained from `TSCreate()`
1459: Output Parameters:
1460: + J - The (approximate) Jacobian of F(t,U,U_t,U_tt)
1461: . P - The matrix from which the preconditioner is constructed, often the same as `J`
1462: . jac - The function to compute the Jacobian matrices
1463: - ctx - User-defined context for Jacobian evaluation routine
1465: Level: advanced
1467: Note:
1468: You can pass in `NULL` for any return argument you do not need.
1470: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()`
1471: @*/
1472: PetscErrorCode TSGetI2Jacobian(TS ts, Mat *J, Mat *P, TSI2JacobianFn **jac, void **ctx)
1473: {
1474: SNES snes;
1475: DM dm;
1477: PetscFunctionBegin;
1478: PetscCall(TSGetSNES(ts, &snes));
1479: PetscCall(SNESSetUpMatrices(snes));
1480: PetscCall(SNESGetJacobian(snes, J, P, NULL, NULL));
1481: PetscCall(TSGetDM(ts, &dm));
1482: PetscCall(DMTSGetI2Jacobian(dm, jac, ctx));
1483: PetscFunctionReturn(PETSC_SUCCESS);
1484: }
1486: /*@
1487: TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0
1489: Collective
1491: Input Parameters:
1492: + ts - the `TS` context
1493: . t - current time
1494: . U - state vector
1495: . V - time derivative of state vector (U_t)
1496: - A - second time derivative of state vector (U_tt)
1498: Output Parameter:
1499: . F - the residual vector
1501: Level: developer
1503: Note:
1504: Most users should not need to explicitly call this routine, as it
1505: is used internally within the nonlinear solvers.
1507: .seealso: [](ch_ts), `TS`, `TSSetI2Function()`, `TSGetI2Function()`
1508: @*/
1509: PetscErrorCode TSComputeI2Function(TS ts, PetscReal t, Vec U, Vec V, Vec A, Vec F)
1510: {
1511: DM dm;
1512: TSI2FunctionFn *I2Function;
1513: void *ctx;
1514: TSRHSFunctionFn *rhsfunction;
1516: PetscFunctionBegin;
1523: PetscCall(TSGetDM(ts, &dm));
1524: PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx));
1525: PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
1527: if (!I2Function) {
1528: PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE));
1529: PetscFunctionReturn(PETSC_SUCCESS);
1530: }
1532: PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, V, F));
1534: PetscCallBack("TS callback implicit function", I2Function(ts, t, U, V, A, F, ctx));
1536: if (rhsfunction) {
1537: Vec Frhs;
1539: PetscCall(DMGetGlobalVector(dm, &Frhs));
1540: PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
1541: PetscCall(VecAXPY(F, -1, Frhs));
1542: PetscCall(DMRestoreGlobalVector(dm, &Frhs));
1543: }
1545: PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F));
1546: PetscFunctionReturn(PETSC_SUCCESS);
1547: }
1549: /*@
1550: TSComputeI2Jacobian - Evaluates the Jacobian of the DAE
1552: Collective
1554: Input Parameters:
1555: + ts - the `TS` context
1556: . t - current timestep
1557: . U - state vector
1558: . V - time derivative of state vector
1559: . A - second time derivative of state vector
1560: . shiftV - shift to apply, see note below
1561: - shiftA - shift to apply, see note below
1563: Output Parameters:
1564: + J - Jacobian matrix
1565: - P - optional preconditioning matrix
1567: Level: developer
1569: Notes:
1570: If F(t,U,V,A)=0 is the DAE, the required Jacobian is
1572: dF/dU + shiftV*dF/dV + shiftA*dF/dA
1574: Most users should not need to explicitly call this routine, as it
1575: is used internally within the nonlinear solvers.
1577: .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()`
1578: @*/
1579: PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P)
1580: {
1581: DM dm;
1582: TSI2JacobianFn *I2Jacobian;
1583: void *ctx;
1584: TSRHSJacobianFn *rhsjacobian;
1586: PetscFunctionBegin;
1594: PetscCall(TSGetDM(ts, &dm));
1595: PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx));
1596: PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));
1598: if (!I2Jacobian) {
1599: PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE));
1600: PetscFunctionReturn(PETSC_SUCCESS);
1601: }
1603: PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P));
1604: PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx));
1605: if (rhsjacobian) {
1606: Mat Jrhs, Prhs;
1607: PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs));
1608: PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs));
1609: PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern));
1610: if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern));
1611: }
1613: PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P));
1614: PetscFunctionReturn(PETSC_SUCCESS);
1615: }
1617: /*@C
1618: TSSetTransientVariable - sets function to transform from state to transient variables
1620: Logically Collective
1622: Input Parameters:
1623: + ts - time stepping context on which to change the transient variable
1624: . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
1625: - ctx - a context for tvar
1627: Level: advanced
1629: Notes:
1630: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
1631: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
1632: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
1633: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
1634: evaluated via the chain rule, as in
1635: .vb
1636: dF/dP + shift * dF/dCdot dC/dP.
1637: .ve
1639: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()`
1640: @*/
1641: PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, void *ctx)
1642: {
1643: DM dm;
1645: PetscFunctionBegin;
1647: PetscCall(TSGetDM(ts, &dm));
1648: PetscCall(DMTSSetTransientVariable(dm, tvar, ctx));
1649: PetscFunctionReturn(PETSC_SUCCESS);
1650: }
1652: /*@
1653: TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables
1655: Logically Collective
1657: Input Parameters:
1658: + ts - TS on which to compute
1659: - U - state vector to be transformed to transient variables
1661: Output Parameter:
1662: . C - transient (conservative) variable
1664: Level: developer
1666: Developer Notes:
1667: If `DMTSSetTransientVariable()` has not been called, then C is not modified in this routine and C = `NULL` is allowed.
1668: This makes it safe to call without a guard. One can use `TSHasTransientVariable()` to check if transient variables are
1669: being used.
1671: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()`
1672: @*/
1673: PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C)
1674: {
1675: DM dm;
1676: DMTS dmts;
1678: PetscFunctionBegin;
1681: PetscCall(TSGetDM(ts, &dm));
1682: PetscCall(DMGetDMTS(dm, &dmts));
1683: if (dmts->ops->transientvar) {
1685: PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx));
1686: }
1687: PetscFunctionReturn(PETSC_SUCCESS);
1688: }
1690: /*@
1691: TSHasTransientVariable - determine whether transient variables have been set
1693: Logically Collective
1695: Input Parameter:
1696: . ts - `TS` on which to compute
1698: Output Parameter:
1699: . has - `PETSC_TRUE` if transient variables have been set
1701: Level: developer
1703: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()`
1704: @*/
1705: PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has)
1706: {
1707: DM dm;
1708: DMTS dmts;
1710: PetscFunctionBegin;
1712: PetscCall(TSGetDM(ts, &dm));
1713: PetscCall(DMGetDMTS(dm, &dmts));
1714: *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE;
1715: PetscFunctionReturn(PETSC_SUCCESS);
1716: }
1718: /*@
1719: TS2SetSolution - Sets the initial solution and time derivative vectors
1720: for use by the `TS` routines handling second order equations.
1722: Logically Collective
1724: Input Parameters:
1725: + ts - the `TS` context obtained from `TSCreate()`
1726: . u - the solution vector
1727: - v - the time derivative vector
1729: Level: beginner
1731: .seealso: [](ch_ts), `TS`
1732: @*/
1733: PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v)
1734: {
1735: PetscFunctionBegin;
1739: PetscCall(TSSetSolution(ts, u));
1740: PetscCall(PetscObjectReference((PetscObject)v));
1741: PetscCall(VecDestroy(&ts->vec_dot));
1742: ts->vec_dot = v;
1743: PetscFunctionReturn(PETSC_SUCCESS);
1744: }
1746: /*@
1747: TS2GetSolution - Returns the solution and time derivative at the present timestep
1748: for second order equations.
1750: Not Collective
1752: Input Parameter:
1753: . ts - the `TS` context obtained from `TSCreate()`
1755: Output Parameters:
1756: + u - the vector containing the solution
1757: - v - the vector containing the time derivative
1759: Level: intermediate
1761: Notes:
1762: It is valid to call this routine inside the function
1763: that you are evaluating in order to move to the new timestep. This vector not
1764: changed until the solution at the next timestep has been calculated.
1766: .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()`
1767: @*/
1768: PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v)
1769: {
1770: PetscFunctionBegin;
1772: if (u) PetscAssertPointer(u, 2);
1773: if (v) PetscAssertPointer(v, 3);
1774: if (u) *u = ts->vec_sol;
1775: if (v) *v = ts->vec_dot;
1776: PetscFunctionReturn(PETSC_SUCCESS);
1777: }
1779: /*@
1780: TSLoad - Loads a `TS` that has been stored in binary with `TSView()`.
1782: Collective
1784: Input Parameters:
1785: + ts - the newly loaded `TS`, this needs to have been created with `TSCreate()` or
1786: some related function before a call to `TSLoad()`.
1787: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
1789: Level: intermediate
1791: Note:
1792: The type is determined by the data in the file, any type set into the `TS` before this call is ignored.
1794: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()`
1795: @*/
1796: PetscErrorCode TSLoad(TS ts, PetscViewer viewer)
1797: {
1798: PetscBool isbinary;
1799: PetscInt classid;
1800: char type[256];
1801: DMTS sdm;
1802: DM dm;
1804: PetscFunctionBegin;
1807: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1808: PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1810: PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
1811: PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file");
1812: PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
1813: PetscCall(TSSetType(ts, type));
1814: PetscTryTypeMethod(ts, load, viewer);
1815: PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm));
1816: PetscCall(DMLoad(dm, viewer));
1817: PetscCall(TSSetDM(ts, dm));
1818: PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
1819: PetscCall(VecLoad(ts->vec_sol, viewer));
1820: PetscCall(DMGetDMTS(ts->dm, &sdm));
1821: PetscCall(DMTSLoad(sdm, viewer));
1822: PetscFunctionReturn(PETSC_SUCCESS);
1823: }
1825: #include <petscdraw.h>
1826: #if defined(PETSC_HAVE_SAWS)
1827: #include <petscviewersaws.h>
1828: #endif
1830: /*@
1831: TSViewFromOptions - View a `TS` based on values in the options database
1833: Collective
1835: Input Parameters:
1836: + ts - the `TS` context
1837: . obj - Optional object that provides the prefix for the options database keys
1838: - name - command line option string to be passed by user
1840: Level: intermediate
1842: .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()`
1843: @*/
1844: PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[])
1845: {
1846: PetscFunctionBegin;
1848: PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name));
1849: PetscFunctionReturn(PETSC_SUCCESS);
1850: }
1852: /*@
1853: TSView - Prints the `TS` data structure.
1855: Collective
1857: Input Parameters:
1858: + ts - the `TS` context obtained from `TSCreate()`
1859: - viewer - visualization context
1861: Options Database Key:
1862: . -ts_view - calls `TSView()` at end of `TSStep()`
1864: Level: beginner
1866: Notes:
1867: The available visualization contexts include
1868: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1869: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1870: output where only the first processor opens
1871: the file. All other processors send their
1872: data to the first processor to print.
1874: The user can open an alternative visualization context with
1875: `PetscViewerASCIIOpen()` - output to a specified file.
1877: In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer).
1879: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()`
1880: @*/
1881: PetscErrorCode TSView(TS ts, PetscViewer viewer)
1882: {
1883: TSType type;
1884: PetscBool iascii, isstring, isundials, isbinary, isdraw;
1885: DMTS sdm;
1886: #if defined(PETSC_HAVE_SAWS)
1887: PetscBool issaws;
1888: #endif
1890: PetscFunctionBegin;
1892: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer));
1894: PetscCheckSameComm(ts, 1, viewer, 2);
1896: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1897: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1898: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1899: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1900: #if defined(PETSC_HAVE_SAWS)
1901: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1902: #endif
1903: if (iascii) {
1904: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer));
1905: if (ts->ops->view) {
1906: PetscCall(PetscViewerASCIIPushTab(viewer));
1907: PetscUseTypeMethod(ts, view, viewer);
1908: PetscCall(PetscViewerASCIIPopTab(viewer));
1909: }
1910: if (ts->max_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum steps=%" PetscInt_FMT "\n", ts->max_steps));
1911: if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum time=%g\n", (double)ts->max_time));
1912: if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs));
1913: if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs));
1914: if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs));
1915: if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs));
1916: if (ts->usessnes) {
1917: PetscBool lin;
1918: if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its));
1919: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its));
1920: PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
1921: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures));
1922: }
1923: PetscCall(PetscViewerASCIIPrintf(viewer, " total number of rejected steps=%" PetscInt_FMT "\n", ts->reject));
1924: if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of relative error tolerances, "));
1925: else PetscCall(PetscViewerASCIIPrintf(viewer, " using relative error tolerance of %g, ", (double)ts->rtol));
1926: if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of absolute error tolerances\n"));
1927: else PetscCall(PetscViewerASCIIPrintf(viewer, " using absolute error tolerance of %g\n", (double)ts->atol));
1928: PetscCall(PetscViewerASCIIPushTab(viewer));
1929: PetscCall(TSAdaptView(ts->adapt, viewer));
1930: PetscCall(PetscViewerASCIIPopTab(viewer));
1931: } else if (isstring) {
1932: PetscCall(TSGetType(ts, &type));
1933: PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type));
1934: PetscTryTypeMethod(ts, view, viewer);
1935: } else if (isbinary) {
1936: PetscInt classid = TS_FILE_CLASSID;
1937: MPI_Comm comm;
1938: PetscMPIInt rank;
1939: char type[256];
1941: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1942: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1943: if (rank == 0) {
1944: PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
1945: PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256));
1946: PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
1947: }
1948: PetscTryTypeMethod(ts, view, viewer);
1949: if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
1950: PetscCall(DMView(ts->dm, viewer));
1951: PetscCall(VecView(ts->vec_sol, viewer));
1952: PetscCall(DMGetDMTS(ts->dm, &sdm));
1953: PetscCall(DMTSView(sdm, viewer));
1954: } else if (isdraw) {
1955: PetscDraw draw;
1956: char str[36];
1957: PetscReal x, y, bottom, h;
1959: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1960: PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
1961: PetscCall(PetscStrncpy(str, "TS: ", sizeof(str)));
1962: PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str)));
1963: PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h));
1964: bottom = y - h;
1965: PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
1966: PetscTryTypeMethod(ts, view, viewer);
1967: if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
1968: if (ts->snes) PetscCall(SNESView(ts->snes, viewer));
1969: PetscCall(PetscDrawPopCurrentPoint(draw));
1970: #if defined(PETSC_HAVE_SAWS)
1971: } else if (issaws) {
1972: PetscMPIInt rank;
1973: const char *name;
1975: PetscCall(PetscObjectGetName((PetscObject)ts, &name));
1976: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1977: if (!((PetscObject)ts)->amsmem && rank == 0) {
1978: char dir[1024];
1980: PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer));
1981: PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name));
1982: PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT));
1983: PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name));
1984: PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE));
1985: }
1986: PetscTryTypeMethod(ts, view, viewer);
1987: #endif
1988: }
1989: if (ts->snes && ts->usessnes) {
1990: PetscCall(PetscViewerASCIIPushTab(viewer));
1991: PetscCall(SNESView(ts->snes, viewer));
1992: PetscCall(PetscViewerASCIIPopTab(viewer));
1993: }
1994: PetscCall(DMGetDMTS(ts->dm, &sdm));
1995: PetscCall(DMTSView(sdm, viewer));
1997: PetscCall(PetscViewerASCIIPushTab(viewer));
1998: PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &isundials));
1999: PetscCall(PetscViewerASCIIPopTab(viewer));
2000: PetscFunctionReturn(PETSC_SUCCESS);
2001: }
2003: /*@
2004: TSSetApplicationContext - Sets an optional user-defined context for
2005: the timesteppers.
2007: Logically Collective
2009: Input Parameters:
2010: + ts - the `TS` context obtained from `TSCreate()`
2011: - usrP - user context
2013: Level: intermediate
2015: Fortran Notes:
2016: You must write a Fortran interface definition for this
2017: function that tells Fortran the Fortran derived data type that you are passing in as the `ctx` argument.
2019: .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()`
2020: @*/
2021: PetscErrorCode TSSetApplicationContext(TS ts, void *usrP)
2022: {
2023: PetscFunctionBegin;
2025: ts->user = usrP;
2026: PetscFunctionReturn(PETSC_SUCCESS);
2027: }
2029: /*@
2030: TSGetApplicationContext - Gets the user-defined context for the
2031: timestepper that was set with `TSSetApplicationContext()`
2033: Not Collective
2035: Input Parameter:
2036: . ts - the `TS` context obtained from `TSCreate()`
2038: Output Parameter:
2039: . usrP - user context
2041: Level: intermediate
2043: Fortran Notes:
2044: You must write a Fortran interface definition for this
2045: function that tells Fortran the Fortran derived data type that you are passing in as the `ctx` argument.
2047: .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()`
2048: @*/
2049: PetscErrorCode TSGetApplicationContext(TS ts, void *usrP)
2050: {
2051: PetscFunctionBegin;
2053: *(void **)usrP = ts->user;
2054: PetscFunctionReturn(PETSC_SUCCESS);
2055: }
2057: /*@
2058: TSGetStepNumber - Gets the number of time steps completed.
2060: Not Collective
2062: Input Parameter:
2063: . ts - the `TS` context obtained from `TSCreate()`
2065: Output Parameter:
2066: . steps - number of steps completed so far
2068: Level: intermediate
2070: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`
2071: @*/
2072: PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps)
2073: {
2074: PetscFunctionBegin;
2076: PetscAssertPointer(steps, 2);
2077: *steps = ts->steps;
2078: PetscFunctionReturn(PETSC_SUCCESS);
2079: }
2081: /*@
2082: TSSetStepNumber - Sets the number of steps completed.
2084: Logically Collective
2086: Input Parameters:
2087: + ts - the `TS` context
2088: - steps - number of steps completed so far
2090: Level: developer
2092: Note:
2093: For most uses of the `TS` solvers the user need not explicitly call
2094: `TSSetStepNumber()`, as the step counter is appropriately updated in
2095: `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to
2096: reinitialize timestepping by setting the step counter to zero (and time
2097: to the initial time) to solve a similar problem with different initial
2098: conditions or parameters. Other possible use case is to continue
2099: timestepping from a previously interrupted run in such a way that `TS`
2100: monitors will be called with a initial nonzero step counter.
2102: .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()`
2103: @*/
2104: PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps)
2105: {
2106: PetscFunctionBegin;
2109: PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative");
2110: ts->steps = steps;
2111: PetscFunctionReturn(PETSC_SUCCESS);
2112: }
2114: /*@
2115: TSSetTimeStep - Allows one to reset the timestep at any time,
2116: useful for simple pseudo-timestepping codes.
2118: Logically Collective
2120: Input Parameters:
2121: + ts - the `TS` context obtained from `TSCreate()`
2122: - time_step - the size of the timestep
2124: Level: intermediate
2126: .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()`
2127: @*/
2128: PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step)
2129: {
2130: PetscFunctionBegin;
2133: ts->time_step = time_step;
2134: PetscFunctionReturn(PETSC_SUCCESS);
2135: }
2137: /*@
2138: TSSetExactFinalTime - Determines whether to adapt the final time step to
2139: match the exact final time, to interpolate the solution to the exact final time,
2140: or to just return at the final time `TS` computed (which may be slightly larger
2141: than the requested final time).
2143: Logically Collective
2145: Input Parameters:
2146: + ts - the time-step context
2147: - eftopt - exact final time option
2148: .vb
2149: TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded, just use it
2150: TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded
2151: TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to ensure the computed final time exactly equals the requested final time
2152: .ve
2154: Options Database Key:
2155: . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime
2157: Level: beginner
2159: Note:
2160: If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time
2161: then the final time you selected.
2163: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()`
2164: @*/
2165: PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt)
2166: {
2167: PetscFunctionBegin;
2170: ts->exact_final_time = eftopt;
2171: PetscFunctionReturn(PETSC_SUCCESS);
2172: }
2174: /*@
2175: TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()`
2177: Not Collective
2179: Input Parameter:
2180: . ts - the `TS` context
2182: Output Parameter:
2183: . eftopt - exact final time option
2185: Level: beginner
2187: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()`
2188: @*/
2189: PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt)
2190: {
2191: PetscFunctionBegin;
2193: PetscAssertPointer(eftopt, 2);
2194: *eftopt = ts->exact_final_time;
2195: PetscFunctionReturn(PETSC_SUCCESS);
2196: }
2198: /*@
2199: TSGetTimeStep - Gets the current timestep size.
2201: Not Collective
2203: Input Parameter:
2204: . ts - the `TS` context obtained from `TSCreate()`
2206: Output Parameter:
2207: . dt - the current timestep size
2209: Level: intermediate
2211: .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()`
2212: @*/
2213: PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt)
2214: {
2215: PetscFunctionBegin;
2217: PetscAssertPointer(dt, 2);
2218: *dt = ts->time_step;
2219: PetscFunctionReturn(PETSC_SUCCESS);
2220: }
2222: /*@
2223: TSGetSolution - Returns the solution at the present timestep. It
2224: is valid to call this routine inside the function that you are evaluating
2225: in order to move to the new timestep. This vector not changed until
2226: the solution at the next timestep has been calculated.
2228: Not Collective, but v returned is parallel if ts is parallel
2230: Input Parameter:
2231: . ts - the `TS` context obtained from `TSCreate()`
2233: Output Parameter:
2234: . v - the vector containing the solution
2236: Level: intermediate
2238: Note:
2239: If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested
2240: final time. It returns the solution at the next timestep.
2242: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()`
2243: @*/
2244: PetscErrorCode TSGetSolution(TS ts, Vec *v)
2245: {
2246: PetscFunctionBegin;
2248: PetscAssertPointer(v, 2);
2249: *v = ts->vec_sol;
2250: PetscFunctionReturn(PETSC_SUCCESS);
2251: }
2253: /*@
2254: TSGetSolutionComponents - Returns any solution components at the present
2255: timestep, if available for the time integration method being used.
2256: Solution components are quantities that share the same size and
2257: structure as the solution vector.
2259: Not Collective, but v returned is parallel if ts is parallel
2261: Input Parameters:
2262: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2263: . n - If v is `NULL`, then the number of solution components is
2264: returned through n, else the n-th solution component is
2265: returned in v.
2266: - v - the vector containing the n-th solution component
2267: (may be `NULL` to use this function to find out
2268: the number of solutions components).
2270: Level: advanced
2272: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2273: @*/
2274: PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v)
2275: {
2276: PetscFunctionBegin;
2278: if (!ts->ops->getsolutioncomponents) *n = 0;
2279: else PetscUseTypeMethod(ts, getsolutioncomponents, n, v);
2280: PetscFunctionReturn(PETSC_SUCCESS);
2281: }
2283: /*@
2284: TSGetAuxSolution - Returns an auxiliary solution at the present
2285: timestep, if available for the time integration method being used.
2287: Not Collective, but v returned is parallel if ts is parallel
2289: Input Parameters:
2290: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2291: - v - the vector containing the auxiliary solution
2293: Level: intermediate
2295: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2296: @*/
2297: PetscErrorCode TSGetAuxSolution(TS ts, Vec *v)
2298: {
2299: PetscFunctionBegin;
2301: if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v);
2302: else PetscCall(VecZeroEntries(*v));
2303: PetscFunctionReturn(PETSC_SUCCESS);
2304: }
2306: /*@
2307: TSGetTimeError - Returns the estimated error vector, if the chosen
2308: `TSType` has an error estimation functionality and `TSSetTimeError()` was called
2310: Not Collective, but v returned is parallel if ts is parallel
2312: Input Parameters:
2313: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2314: . n - current estimate (n=0) or previous one (n=-1)
2315: - v - the vector containing the error (same size as the solution).
2317: Level: intermediate
2319: Note:
2320: MUST call after `TSSetUp()`
2322: .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()`
2323: @*/
2324: PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v)
2325: {
2326: PetscFunctionBegin;
2328: if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v);
2329: else PetscCall(VecZeroEntries(*v));
2330: PetscFunctionReturn(PETSC_SUCCESS);
2331: }
2333: /*@
2334: TSSetTimeError - Sets the estimated error vector, if the chosen
2335: `TSType` has an error estimation functionality. This can be used
2336: to restart such a time integrator with a given error vector.
2338: Not Collective, but v returned is parallel if ts is parallel
2340: Input Parameters:
2341: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2342: - v - the vector containing the error (same size as the solution).
2344: Level: intermediate
2346: .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()`
2347: @*/
2348: PetscErrorCode TSSetTimeError(TS ts, Vec v)
2349: {
2350: PetscFunctionBegin;
2352: PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first");
2353: PetscTryTypeMethod(ts, settimeerror, v);
2354: PetscFunctionReturn(PETSC_SUCCESS);
2355: }
2357: /* ----- Routines to initialize and destroy a timestepper ---- */
2358: /*@
2359: TSSetProblemType - Sets the type of problem to be solved.
2361: Not collective
2363: Input Parameters:
2364: + ts - The `TS`
2365: - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2366: .vb
2367: U_t - A U = 0 (linear)
2368: U_t - A(t) U = 0 (linear)
2369: F(t,U,U_t) = 0 (nonlinear)
2370: .ve
2372: Level: beginner
2374: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2375: @*/
2376: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
2377: {
2378: PetscFunctionBegin;
2380: ts->problem_type = type;
2381: if (type == TS_LINEAR) {
2382: SNES snes;
2383: PetscCall(TSGetSNES(ts, &snes));
2384: PetscCall(SNESSetType(snes, SNESKSPONLY));
2385: }
2386: PetscFunctionReturn(PETSC_SUCCESS);
2387: }
2389: /*@
2390: TSGetProblemType - Gets the type of problem to be solved.
2392: Not collective
2394: Input Parameter:
2395: . ts - The `TS`
2397: Output Parameter:
2398: . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2399: .vb
2400: M U_t = A U
2401: M(t) U_t = A(t) U
2402: F(t,U,U_t)
2403: .ve
2405: Level: beginner
2407: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2408: @*/
2409: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
2410: {
2411: PetscFunctionBegin;
2413: PetscAssertPointer(type, 2);
2414: *type = ts->problem_type;
2415: PetscFunctionReturn(PETSC_SUCCESS);
2416: }
2418: /*
2419: Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
2420: */
2421: static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
2422: {
2423: PetscBool isnone;
2425: PetscFunctionBegin;
2426: PetscCall(TSGetAdapt(ts, &ts->adapt));
2427: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2429: PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone));
2430: if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2431: else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
2432: PetscFunctionReturn(PETSC_SUCCESS);
2433: }
2435: /*@
2436: TSSetUp - Sets up the internal data structures for the later use of a timestepper.
2438: Collective
2440: Input Parameter:
2441: . ts - the `TS` context obtained from `TSCreate()`
2443: Level: advanced
2445: Note:
2446: For basic use of the `TS` solvers the user need not explicitly call
2447: `TSSetUp()`, since these actions will automatically occur during
2448: the call to `TSStep()` or `TSSolve()`. However, if one wishes to control this
2449: phase separately, `TSSetUp()` should be called after `TSCreate()`
2450: and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`.
2452: .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()`
2453: @*/
2454: PetscErrorCode TSSetUp(TS ts)
2455: {
2456: DM dm;
2457: PetscErrorCode (*func)(SNES, Vec, Vec, void *);
2458: PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
2459: TSIFunctionFn *ifun;
2460: TSIJacobianFn *ijac;
2461: TSI2JacobianFn *i2jac;
2462: TSRHSJacobianFn *rhsjac;
2464: PetscFunctionBegin;
2466: if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
2468: if (!((PetscObject)ts)->type_name) {
2469: PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
2470: PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER));
2471: }
2473: if (!ts->vec_sol) {
2474: PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first");
2475: PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
2476: }
2478: if (ts->tspan) {
2479: if (!ts->tspan->vecs_sol) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->tspan->num_span_times, &ts->tspan->vecs_sol));
2480: }
2481: if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
2482: PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
2483: ts->Jacp = ts->Jacprhs;
2484: }
2486: if (ts->quadraturets) {
2487: PetscCall(TSSetUp(ts->quadraturets));
2488: PetscCall(VecDestroy(&ts->vec_costintegrand));
2489: PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand));
2490: }
2492: PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL));
2493: if (rhsjac == TSComputeRHSJacobianConstant) {
2494: Mat Amat, Pmat;
2495: SNES snes;
2496: PetscCall(TSGetSNES(ts, &snes));
2497: PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL));
2498: /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2499: * have displaced the RHS matrix */
2500: if (Amat && Amat == ts->Arhs) {
2501: /* 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 */
2502: PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat));
2503: PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL));
2504: PetscCall(MatDestroy(&Amat));
2505: }
2506: if (Pmat && Pmat == ts->Brhs) {
2507: PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat));
2508: PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL));
2509: PetscCall(MatDestroy(&Pmat));
2510: }
2511: }
2513: PetscCall(TSGetAdapt(ts, &ts->adapt));
2514: PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2516: PetscTryTypeMethod(ts, setup);
2518: PetscCall(TSSetExactFinalTimeDefault(ts));
2520: /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2521: to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2522: */
2523: PetscCall(TSGetDM(ts, &dm));
2524: PetscCall(DMSNESGetFunction(dm, &func, NULL));
2525: if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts));
2527: /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2528: Otherwise, the SNES will use coloring internally to form the Jacobian.
2529: */
2530: PetscCall(DMSNESGetJacobian(dm, &jac, NULL));
2531: PetscCall(DMTSGetIJacobian(dm, &ijac, NULL));
2532: PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL));
2533: PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL));
2534: if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts));
2536: /* if time integration scheme has a starting method, call it */
2537: PetscTryTypeMethod(ts, startingmethod);
2539: ts->setupcalled = PETSC_TRUE;
2540: PetscFunctionReturn(PETSC_SUCCESS);
2541: }
2543: /*@
2544: 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
2546: Collective
2548: Input Parameter:
2549: . ts - the `TS` context obtained from `TSCreate()`
2551: Level: developer
2553: Notes:
2554: Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain.
2556: See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration.
2558: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetup()`, `TSDestroy()`, `TSSetResize()`
2559: @*/
2560: PetscErrorCode TSReset(TS ts)
2561: {
2562: TS_RHSSplitLink ilink = ts->tsrhssplit, next;
2564: PetscFunctionBegin;
2567: PetscTryTypeMethod(ts, reset);
2568: if (ts->snes) PetscCall(SNESReset(ts->snes));
2569: if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));
2571: PetscCall(MatDestroy(&ts->Arhs));
2572: PetscCall(MatDestroy(&ts->Brhs));
2573: PetscCall(VecDestroy(&ts->Frhs));
2574: PetscCall(VecDestroy(&ts->vec_sol));
2575: PetscCall(VecDestroy(&ts->vec_sol0));
2576: PetscCall(VecDestroy(&ts->vec_dot));
2577: PetscCall(VecDestroy(&ts->vatol));
2578: PetscCall(VecDestroy(&ts->vrtol));
2579: PetscCall(VecDestroyVecs(ts->nwork, &ts->work));
2581: PetscCall(MatDestroy(&ts->Jacprhs));
2582: PetscCall(MatDestroy(&ts->Jacp));
2583: if (ts->forward_solve) PetscCall(TSForwardReset(ts));
2584: if (ts->quadraturets) {
2585: PetscCall(TSReset(ts->quadraturets));
2586: PetscCall(VecDestroy(&ts->vec_costintegrand));
2587: }
2588: while (ilink) {
2589: next = ilink->next;
2590: PetscCall(TSDestroy(&ilink->ts));
2591: PetscCall(PetscFree(ilink->splitname));
2592: PetscCall(ISDestroy(&ilink->is));
2593: PetscCall(PetscFree(ilink));
2594: ilink = next;
2595: }
2596: ts->tsrhssplit = NULL;
2597: ts->num_rhs_splits = 0;
2598: if (ts->tspan) {
2599: PetscCall(PetscFree(ts->tspan->span_times));
2600: PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol));
2601: PetscCall(PetscFree(ts->tspan));
2602: }
2603: ts->rhsjacobian.time = PETSC_MIN_REAL;
2604: ts->rhsjacobian.scale = 1.0;
2605: ts->ijacobian.shift = 1.0;
2606: ts->setupcalled = PETSC_FALSE;
2607: PetscFunctionReturn(PETSC_SUCCESS);
2608: }
2610: static PetscErrorCode TSResizeReset(TS);
2612: /*@
2613: TSDestroy - Destroys the timestepper context that was created
2614: with `TSCreate()`.
2616: Collective
2618: Input Parameter:
2619: . ts - the `TS` context obtained from `TSCreate()`
2621: Level: beginner
2623: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2624: @*/
2625: PetscErrorCode TSDestroy(TS *ts)
2626: {
2627: PetscFunctionBegin;
2628: if (!*ts) PetscFunctionReturn(PETSC_SUCCESS);
2630: if (--((PetscObject)*ts)->refct > 0) {
2631: *ts = NULL;
2632: PetscFunctionReturn(PETSC_SUCCESS);
2633: }
2635: PetscCall(TSReset(*ts));
2636: PetscCall(TSAdjointReset(*ts));
2637: if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts));
2638: PetscCall(TSResizeReset(*ts));
2640: /* if memory was published with SAWs then destroy it */
2641: PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
2642: PetscTryTypeMethod(*ts, destroy);
2644: PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory));
2646: PetscCall(TSAdaptDestroy(&(*ts)->adapt));
2647: PetscCall(TSEventDestroy(&(*ts)->event));
2649: PetscCall(SNESDestroy(&(*ts)->snes));
2650: PetscCall(SNESDestroy(&(*ts)->snesrhssplit));
2651: PetscCall(DMDestroy(&(*ts)->dm));
2652: PetscCall(TSMonitorCancel(*ts));
2653: PetscCall(TSAdjointMonitorCancel(*ts));
2655: PetscCall(TSDestroy(&(*ts)->quadraturets));
2656: PetscCall(PetscHeaderDestroy(ts));
2657: PetscFunctionReturn(PETSC_SUCCESS);
2658: }
2660: /*@
2661: TSGetSNES - Returns the `SNES` (nonlinear solver) associated with
2662: a `TS` (timestepper) context. Valid only for nonlinear problems.
2664: Not Collective, but snes is parallel if ts is parallel
2666: Input Parameter:
2667: . ts - the `TS` context obtained from `TSCreate()`
2669: Output Parameter:
2670: . snes - the nonlinear solver context
2672: Level: beginner
2674: Notes:
2675: The user can then directly manipulate the `SNES` context to set various
2676: options, etc. Likewise, the user can then extract and manipulate the
2677: `KSP`, and `PC` contexts as well.
2679: `TSGetSNES()` does not work for integrators that do not use `SNES`; in
2680: this case `TSGetSNES()` returns `NULL` in `snes`.
2682: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2683: @*/
2684: PetscErrorCode TSGetSNES(TS ts, SNES *snes)
2685: {
2686: PetscFunctionBegin;
2688: PetscAssertPointer(snes, 2);
2689: if (!ts->snes) {
2690: PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes));
2691: PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options));
2692: PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2693: PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
2694: if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
2695: if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
2696: }
2697: *snes = ts->snes;
2698: PetscFunctionReturn(PETSC_SUCCESS);
2699: }
2701: /*@
2702: TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context
2704: Collective
2706: Input Parameters:
2707: + ts - the `TS` context obtained from `TSCreate()`
2708: - snes - the nonlinear solver context
2710: Level: developer
2712: Note:
2713: Most users should have the `TS` created by calling `TSGetSNES()`
2715: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2716: @*/
2717: PetscErrorCode TSSetSNES(TS ts, SNES snes)
2718: {
2719: PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
2721: PetscFunctionBegin;
2724: PetscCall(PetscObjectReference((PetscObject)snes));
2725: PetscCall(SNESDestroy(&ts->snes));
2727: ts->snes = snes;
2729: PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2730: PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
2731: if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
2732: PetscFunctionReturn(PETSC_SUCCESS);
2733: }
2735: /*@
2736: TSGetKSP - Returns the `KSP` (linear solver) associated with
2737: a `TS` (timestepper) context.
2739: Not Collective, but `ksp` is parallel if `ts` is parallel
2741: Input Parameter:
2742: . ts - the `TS` context obtained from `TSCreate()`
2744: Output Parameter:
2745: . ksp - the nonlinear solver context
2747: Level: beginner
2749: Notes:
2750: The user can then directly manipulate the `KSP` context to set various
2751: options, etc. Likewise, the user can then extract and manipulate the
2752: `PC` context as well.
2754: `TSGetKSP()` does not work for integrators that do not use `KSP`;
2755: in this case `TSGetKSP()` returns `NULL` in `ksp`.
2757: .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2758: @*/
2759: PetscErrorCode TSGetKSP(TS ts, KSP *ksp)
2760: {
2761: SNES snes;
2763: PetscFunctionBegin;
2765: PetscAssertPointer(ksp, 2);
2766: PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
2767: PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()");
2768: PetscCall(TSGetSNES(ts, &snes));
2769: PetscCall(SNESGetKSP(snes, ksp));
2770: PetscFunctionReturn(PETSC_SUCCESS);
2771: }
2773: /* ----------- Routines to set solver parameters ---------- */
2775: /*@
2776: TSSetMaxSteps - Sets the maximum number of steps to use.
2778: Logically Collective
2780: Input Parameters:
2781: + ts - the `TS` context obtained from `TSCreate()`
2782: - maxsteps - maximum number of steps to use
2784: Options Database Key:
2785: . -ts_max_steps <maxsteps> - Sets maxsteps
2787: Level: intermediate
2789: Note:
2790: Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set
2792: The default maximum number of steps is 5,000
2794: Fortran Note:
2795: Use `PETSC_DETERMINE_INTEGER`
2797: .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
2798: @*/
2799: PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps)
2800: {
2801: PetscFunctionBegin;
2804: if (maxsteps == PETSC_DETERMINE) {
2805: ts->max_steps = ts->default_max_steps;
2806: } else {
2807: PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
2808: ts->max_steps = maxsteps;
2809: }
2810: PetscFunctionReturn(PETSC_SUCCESS);
2811: }
2813: /*@
2814: TSGetMaxSteps - Gets the maximum number of steps to use.
2816: Not Collective
2818: Input Parameter:
2819: . ts - the `TS` context obtained from `TSCreate()`
2821: Output Parameter:
2822: . maxsteps - maximum number of steps to use
2824: Level: advanced
2826: .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
2827: @*/
2828: PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps)
2829: {
2830: PetscFunctionBegin;
2832: PetscAssertPointer(maxsteps, 2);
2833: *maxsteps = ts->max_steps;
2834: PetscFunctionReturn(PETSC_SUCCESS);
2835: }
2837: /*@
2838: TSSetMaxTime - Sets the maximum (or final) time for timestepping.
2840: Logically Collective
2842: Input Parameters:
2843: + ts - the `TS` context obtained from `TSCreate()`
2844: - maxtime - final time to step to
2846: Options Database Key:
2847: . -ts_max_time <maxtime> - Sets maxtime
2849: Level: intermediate
2851: Notes:
2852: Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set
2854: The default maximum time is 5.0
2856: Fortran Note:
2857: Use `PETSC_DETERMINE_REAL`
2859: .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
2860: @*/
2861: PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime)
2862: {
2863: PetscFunctionBegin;
2866: if (maxtime == PETSC_DETERMINE) {
2867: ts->max_time = ts->default_max_time;
2868: } else {
2869: ts->max_time = maxtime;
2870: }
2871: PetscFunctionReturn(PETSC_SUCCESS);
2872: }
2874: /*@
2875: TSGetMaxTime - Gets the maximum (or final) time for timestepping.
2877: Not Collective
2879: Input Parameter:
2880: . ts - the `TS` context obtained from `TSCreate()`
2882: Output Parameter:
2883: . maxtime - final time to step to
2885: Level: advanced
2887: .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
2888: @*/
2889: PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime)
2890: {
2891: PetscFunctionBegin;
2893: PetscAssertPointer(maxtime, 2);
2894: *maxtime = ts->max_time;
2895: PetscFunctionReturn(PETSC_SUCCESS);
2896: }
2898: // PetscClangLinter pragma disable: -fdoc-*
2899: /*@
2900: TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`.
2902: Level: deprecated
2904: @*/
2905: PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step)
2906: {
2907: PetscFunctionBegin;
2909: PetscCall(TSSetTime(ts, initial_time));
2910: PetscCall(TSSetTimeStep(ts, time_step));
2911: PetscFunctionReturn(PETSC_SUCCESS);
2912: }
2914: // PetscClangLinter pragma disable: -fdoc-*
2915: /*@
2916: TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`.
2918: Level: deprecated
2920: @*/
2921: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2922: {
2923: PetscFunctionBegin;
2925: if (maxsteps) {
2926: PetscAssertPointer(maxsteps, 2);
2927: *maxsteps = ts->max_steps;
2928: }
2929: if (maxtime) {
2930: PetscAssertPointer(maxtime, 3);
2931: *maxtime = ts->max_time;
2932: }
2933: PetscFunctionReturn(PETSC_SUCCESS);
2934: }
2936: // PetscClangLinter pragma disable: -fdoc-*
2937: /*@
2938: TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`.
2940: Level: deprecated
2942: @*/
2943: PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime)
2944: {
2945: PetscFunctionBegin;
2946: if (maxsteps != (PetscInt)PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps));
2947: if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime));
2948: PetscFunctionReturn(PETSC_SUCCESS);
2949: }
2951: // PetscClangLinter pragma disable: -fdoc-*
2952: /*@
2953: TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`.
2955: Level: deprecated
2957: @*/
2958: PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps)
2959: {
2960: return TSGetStepNumber(ts, steps);
2961: }
2963: // PetscClangLinter pragma disable: -fdoc-*
2964: /*@
2965: TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`.
2967: Level: deprecated
2969: @*/
2970: PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps)
2971: {
2972: return TSGetStepNumber(ts, steps);
2973: }
2975: /*@
2976: TSSetSolution - Sets the initial solution vector
2977: for use by the `TS` routines.
2979: Logically Collective
2981: Input Parameters:
2982: + ts - the `TS` context obtained from `TSCreate()`
2983: - u - the solution vector
2985: Level: beginner
2987: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
2988: @*/
2989: PetscErrorCode TSSetSolution(TS ts, Vec u)
2990: {
2991: DM dm;
2993: PetscFunctionBegin;
2996: PetscCall(PetscObjectReference((PetscObject)u));
2997: PetscCall(VecDestroy(&ts->vec_sol));
2998: ts->vec_sol = u;
3000: PetscCall(TSGetDM(ts, &dm));
3001: PetscCall(DMShellSetGlobalVector(dm, u));
3002: PetscFunctionReturn(PETSC_SUCCESS);
3003: }
3005: /*@C
3006: TSSetPreStep - Sets the general-purpose function
3007: called once at the beginning of each time step.
3009: Logically Collective
3011: Input Parameters:
3012: + ts - The `TS` context obtained from `TSCreate()`
3013: - func - The function
3015: Calling sequence of `func`:
3016: . ts - the `TS` context
3018: Level: intermediate
3020: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
3021: @*/
3022: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts))
3023: {
3024: PetscFunctionBegin;
3026: ts->prestep = func;
3027: PetscFunctionReturn(PETSC_SUCCESS);
3028: }
3030: /*@
3031: TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()`
3033: Collective
3035: Input Parameter:
3036: . ts - The `TS` context obtained from `TSCreate()`
3038: Level: developer
3040: Note:
3041: `TSPreStep()` is typically used within time stepping implementations,
3042: so most users would not generally call this routine themselves.
3044: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
3045: @*/
3046: PetscErrorCode TSPreStep(TS ts)
3047: {
3048: PetscFunctionBegin;
3050: if (ts->prestep) {
3051: Vec U;
3052: PetscObjectId idprev;
3053: PetscBool sameObject;
3054: PetscObjectState sprev, spost;
3056: PetscCall(TSGetSolution(ts, &U));
3057: PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3058: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3059: PetscCallBack("TS callback preset", (*ts->prestep)(ts));
3060: PetscCall(TSGetSolution(ts, &U));
3061: PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3062: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3063: if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3064: }
3065: PetscFunctionReturn(PETSC_SUCCESS);
3066: }
3068: /*@C
3069: TSSetPreStage - Sets the general-purpose function
3070: called once at the beginning of each stage.
3072: Logically Collective
3074: Input Parameters:
3075: + ts - The `TS` context obtained from `TSCreate()`
3076: - func - The function
3078: Calling sequence of `func`:
3079: + ts - the `TS` context
3080: - stagetime - the stage time
3082: Level: intermediate
3084: Note:
3085: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3086: The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3087: attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3089: .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3090: @*/
3091: PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime))
3092: {
3093: PetscFunctionBegin;
3095: ts->prestage = func;
3096: PetscFunctionReturn(PETSC_SUCCESS);
3097: }
3099: /*@C
3100: TSSetPostStage - Sets the general-purpose function
3101: called once at the end of each stage.
3103: Logically Collective
3105: Input Parameters:
3106: + ts - The `TS` context obtained from `TSCreate()`
3107: - func - The function
3109: Calling sequence of `func`:
3110: + ts - the `TS` context
3111: . stagetime - the stage time
3112: . stageindex - the stage index
3113: - Y - Array of vectors (of size = total number of stages) with the stage solutions
3115: Level: intermediate
3117: Note:
3118: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3119: The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3120: attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3122: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3123: @*/
3124: PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y))
3125: {
3126: PetscFunctionBegin;
3128: ts->poststage = func;
3129: PetscFunctionReturn(PETSC_SUCCESS);
3130: }
3132: /*@C
3133: TSSetPostEvaluate - Sets the general-purpose function
3134: called at the end of each step evaluation.
3136: Logically Collective
3138: Input Parameters:
3139: + ts - The `TS` context obtained from `TSCreate()`
3140: - func - The function
3142: Calling sequence of `func`:
3143: . ts - the `TS` context
3145: Level: intermediate
3147: Note:
3148: The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback.
3149: Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be.
3150: The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`.
3151: The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`,
3152: but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below
3153: .vb
3154: ...
3155: Step()
3156: PostEvaluate()
3157: EventHandling()
3158: step_rollback ? PostEvaluate() : PostStep()
3159: ...
3160: .ve
3161: where EventHandling() may result in one of the following three outcomes
3162: .vb
3163: (1) | successful step | solution intact
3164: (2) | successful step | solution modified by `postevent()`
3165: (3) | step_rollback | solution rolled back
3166: .ve
3168: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3169: @*/
3170: PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts))
3171: {
3172: PetscFunctionBegin;
3174: ts->postevaluate = func;
3175: PetscFunctionReturn(PETSC_SUCCESS);
3176: }
3178: /*@
3179: TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()`
3181: Collective
3183: Input Parameters:
3184: + ts - The `TS` context obtained from `TSCreate()`
3185: - stagetime - The absolute time of the current stage
3187: Level: developer
3189: Note:
3190: `TSPreStage()` is typically used within time stepping implementations,
3191: most users would not generally call this routine themselves.
3193: .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3194: @*/
3195: PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
3196: {
3197: PetscFunctionBegin;
3199: if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
3200: PetscFunctionReturn(PETSC_SUCCESS);
3201: }
3203: /*@
3204: TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()`
3206: Collective
3208: Input Parameters:
3209: + ts - The `TS` context obtained from `TSCreate()`
3210: . stagetime - The absolute time of the current stage
3211: . stageindex - Stage number
3212: - Y - Array of vectors (of size = total number of stages) with the stage solutions
3214: Level: developer
3216: Note:
3217: `TSPostStage()` is typically used within time stepping implementations,
3218: most users would not generally call this routine themselves.
3220: .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3221: @*/
3222: PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3223: {
3224: PetscFunctionBegin;
3226: if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
3227: PetscFunctionReturn(PETSC_SUCCESS);
3228: }
3230: /*@
3231: TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()`
3233: Collective
3235: Input Parameter:
3236: . ts - The `TS` context obtained from `TSCreate()`
3238: Level: developer
3240: Note:
3241: `TSPostEvaluate()` is typically used within time stepping implementations,
3242: most users would not generally call this routine themselves.
3244: .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3245: @*/
3246: PetscErrorCode TSPostEvaluate(TS ts)
3247: {
3248: PetscFunctionBegin;
3250: if (ts->postevaluate) {
3251: Vec U;
3252: PetscObjectState sprev, spost;
3254: PetscCall(TSGetSolution(ts, &U));
3255: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3256: PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
3257: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3258: if (sprev != spost) PetscCall(TSRestartStep(ts));
3259: }
3260: PetscFunctionReturn(PETSC_SUCCESS);
3261: }
3263: /*@C
3264: TSSetPostStep - Sets the general-purpose function
3265: called once at the end of each successful time step.
3267: Logically Collective
3269: Input Parameters:
3270: + ts - The `TS` context obtained from `TSCreate()`
3271: - func - The function
3273: Calling sequence of `func`:
3274: . ts - the `TS` context
3276: Level: intermediate
3278: Note:
3279: The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the
3280: given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will
3281: contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback.
3282: The scheme of the relevant function calls in `TSSolve()` is shown below
3283: .vb
3284: ...
3285: Step()
3286: PostEvaluate()
3287: EventHandling()
3288: step_rollback ? PostEvaluate() : PostStep()
3289: ...
3290: .ve
3291: where EventHandling() may result in one of the following three outcomes
3292: .vb
3293: (1) | successful step | solution intact
3294: (2) | successful step | solution modified by `postevent()`
3295: (3) | step_rollback | solution rolled back
3296: .ve
3298: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
3299: @*/
3300: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts))
3301: {
3302: PetscFunctionBegin;
3304: ts->poststep = func;
3305: PetscFunctionReturn(PETSC_SUCCESS);
3306: }
3308: /*@
3309: TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()`
3311: Collective
3313: Input Parameter:
3314: . ts - The `TS` context obtained from `TSCreate()`
3316: Note:
3317: `TSPostStep()` is typically used within time stepping implementations,
3318: so most users would not generally call this routine themselves.
3320: Level: developer
3322: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPotsStep()`
3323: @*/
3324: PetscErrorCode TSPostStep(TS ts)
3325: {
3326: PetscFunctionBegin;
3328: if (ts->poststep) {
3329: Vec U;
3330: PetscObjectId idprev;
3331: PetscBool sameObject;
3332: PetscObjectState sprev, spost;
3334: PetscCall(TSGetSolution(ts, &U));
3335: PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3336: PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3337: PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
3338: PetscCall(TSGetSolution(ts, &U));
3339: PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3340: PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3341: if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3342: }
3343: PetscFunctionReturn(PETSC_SUCCESS);
3344: }
3346: /*@
3347: TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3349: Collective
3351: Input Parameters:
3352: + ts - time stepping context
3353: - t - time to interpolate to
3355: Output Parameter:
3356: . U - state at given time
3358: Level: intermediate
3360: Developer Notes:
3361: `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3363: .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()`
3364: @*/
3365: PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U)
3366: {
3367: PetscFunctionBegin;
3370: 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);
3371: PetscUseTypeMethod(ts, interpolate, t, U);
3372: PetscFunctionReturn(PETSC_SUCCESS);
3373: }
3375: /*@
3376: TSStep - Steps one time step
3378: Collective
3380: Input Parameter:
3381: . ts - the `TS` context obtained from `TSCreate()`
3383: Level: developer
3385: Notes:
3386: The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine.
3388: The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may
3389: be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3391: This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the
3392: time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep.
3394: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
3395: @*/
3396: PetscErrorCode TSStep(TS ts)
3397: {
3398: static PetscBool cite = PETSC_FALSE;
3399: PetscReal ptime;
3401: PetscFunctionBegin;
3403: PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3404: " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3405: " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3406: " journal = {arXiv e-preprints},\n"
3407: " eprint = {1806.01437},\n"
3408: " archivePrefix = {arXiv},\n"
3409: " year = {2018}\n}\n",
3410: &cite));
3411: PetscCall(TSSetUp(ts));
3412: PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3413: if (ts->tspan)
3414: ts->tspan->worktol = 0; /* In each step of TSSolve() 'tspan->worktol' will be meaningfully defined (later) only once:
3415: in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */
3417: PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>");
3418: 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()");
3419: 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");
3421: if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0));
3422: PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0));
3423: ts->time_step0 = ts->time_step;
3425: if (!ts->steps) ts->ptime_prev = ts->ptime;
3426: ptime = ts->ptime;
3428: ts->ptime_prev_rollback = ts->ptime_prev;
3429: ts->reason = TS_CONVERGED_ITERATING;
3431: PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
3432: PetscUseTypeMethod(ts, step);
3433: PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));
3435: if (ts->reason >= 0) {
3436: ts->ptime_prev = ptime;
3437: ts->steps++;
3438: ts->steprollback = PETSC_FALSE;
3439: ts->steprestart = PETSC_FALSE;
3440: ts->stepresize = PETSC_FALSE;
3441: }
3443: if (ts->reason < 0 && ts->errorifstepfailed) {
3444: PetscCall(TSMonitorCancel(ts));
3445: 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]);
3446: SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
3447: }
3448: PetscFunctionReturn(PETSC_SUCCESS);
3449: }
3451: /*@
3452: TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3453: at the end of a time step with a given order of accuracy.
3455: Collective
3457: Input Parameters:
3458: + ts - time stepping context
3459: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
3461: Input/Output Parameter:
3462: . order - optional, desired order for the error evaluation or `PETSC_DECIDE`;
3463: on output, the actual order of the error evaluation
3465: Output Parameter:
3466: . wlte - the weighted local truncation error norm
3468: Level: advanced
3470: Note:
3471: If the timestepper cannot evaluate the error in a particular step
3472: (eg. in the first step or restart steps after event handling),
3473: this routine returns wlte=-1.0 .
3475: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3476: @*/
3477: PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
3478: {
3479: PetscFunctionBegin;
3483: if (order) PetscAssertPointer(order, 3);
3485: PetscAssertPointer(wlte, 4);
3486: PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
3487: PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
3488: PetscFunctionReturn(PETSC_SUCCESS);
3489: }
3491: /*@
3492: TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3494: Collective
3496: Input Parameters:
3497: + ts - time stepping context
3498: . order - desired order of accuracy
3499: - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available)
3501: Output Parameter:
3502: . U - state at the end of the current step
3504: Level: advanced
3506: Notes:
3507: This function cannot be called until all stages have been evaluated.
3509: 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.
3511: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`
3512: @*/
3513: PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done)
3514: {
3515: PetscFunctionBegin;
3519: PetscUseTypeMethod(ts, evaluatestep, order, U, done);
3520: PetscFunctionReturn(PETSC_SUCCESS);
3521: }
3523: /*@C
3524: TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.
3526: Not collective
3528: Input Parameter:
3529: . ts - time stepping context
3531: Output Parameter:
3532: . initCondition - The function which computes an initial condition
3534: Calling sequence of `initCondition`:
3535: + ts - The timestepping context
3536: - u - The input vector in which the initial condition is stored
3538: Level: advanced
3540: .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3541: @*/
3542: PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u))
3543: {
3544: PetscFunctionBegin;
3546: PetscAssertPointer(initCondition, 2);
3547: *initCondition = ts->ops->initcondition;
3548: PetscFunctionReturn(PETSC_SUCCESS);
3549: }
3551: /*@C
3552: TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.
3554: Logically collective
3556: Input Parameters:
3557: + ts - time stepping context
3558: - initCondition - The function which computes an initial condition
3560: Calling sequence of `initCondition`:
3561: + ts - The timestepping context
3562: - e - The input vector in which the initial condition is to be stored
3564: Level: advanced
3566: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3567: @*/
3568: PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e))
3569: {
3570: PetscFunctionBegin;
3573: ts->ops->initcondition = initCondition;
3574: PetscFunctionReturn(PETSC_SUCCESS);
3575: }
3577: /*@
3578: TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()`
3580: Collective
3582: Input Parameters:
3583: + ts - time stepping context
3584: - u - The `Vec` to store the condition in which will be used in `TSSolve()`
3586: Level: advanced
3588: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3589: @*/
3590: PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
3591: {
3592: PetscFunctionBegin;
3595: PetscTryTypeMethod(ts, initcondition, u);
3596: PetscFunctionReturn(PETSC_SUCCESS);
3597: }
3599: /*@C
3600: TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.
3602: Not collective
3604: Input Parameter:
3605: . ts - time stepping context
3607: Output Parameter:
3608: . exactError - The function which computes the solution error
3610: Calling sequence of `exactError`:
3611: + ts - The timestepping context
3612: . u - The approximate solution vector
3613: - e - The vector in which the error is stored
3615: Level: advanced
3617: .seealso: [](ch_ts), `TS`, `TSComputeExactError()`
3618: @*/
3619: PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e))
3620: {
3621: PetscFunctionBegin;
3623: PetscAssertPointer(exactError, 2);
3624: *exactError = ts->ops->exacterror;
3625: PetscFunctionReturn(PETSC_SUCCESS);
3626: }
3628: /*@C
3629: TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.
3631: Logically collective
3633: Input Parameters:
3634: + ts - time stepping context
3635: - exactError - The function which computes the solution error
3637: Calling sequence of `exactError`:
3638: + ts - The timestepping context
3639: . u - The approximate solution vector
3640: - e - The vector in which the error is stored
3642: Level: advanced
3644: .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()`
3645: @*/
3646: PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e))
3647: {
3648: PetscFunctionBegin;
3651: ts->ops->exacterror = exactError;
3652: PetscFunctionReturn(PETSC_SUCCESS);
3653: }
3655: /*@
3656: TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()`
3658: Collective
3660: Input Parameters:
3661: + ts - time stepping context
3662: . u - The approximate solution
3663: - e - The `Vec` used to store the error
3665: Level: advanced
3667: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3668: @*/
3669: PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
3670: {
3671: PetscFunctionBegin;
3675: PetscTryTypeMethod(ts, exacterror, u, e);
3676: PetscFunctionReturn(PETSC_SUCCESS);
3677: }
3679: /*@C
3680: TSSetResize - Sets the resize callbacks.
3682: Logically Collective
3684: Input Parameters:
3685: + ts - The `TS` context obtained from `TSCreate()`
3686: . rollback - Whether a resize will restart the step
3687: . setup - The setup function
3688: . transfer - The transfer function
3689: - ctx - [optional] The user-defined context
3691: Calling sequence of `setup`:
3692: + ts - the `TS` context
3693: . step - the current step
3694: . time - the current time
3695: . state - the current vector of state
3696: . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise
3697: - ctx - user defined context
3699: Calling sequence of `transfer`:
3700: + ts - the `TS` context
3701: . nv - the number of vectors to be transferred
3702: . vecsin - array of vectors to be transferred
3703: . vecsout - array of transferred vectors
3704: - ctx - user defined context
3706: Notes:
3707: The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()`
3708: depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators
3709: and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver
3710: that the size of the discrete problem has changed.
3711: In both cases, the solver will collect the needed vectors that will be
3712: transferred from the old to the new sizes using the `transfer` callback. These vectors will include the
3713: current solution vector, and other vectors needed by the specific solver used.
3714: For example, `TSBDF` uses previous solutions vectors to solve for the next time step.
3715: Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`,
3716: will be automatically reset if the sizes are changed and they must be specified again by the user
3717: inside the `transfer` function.
3718: The input and output arrays passed to `transfer` are allocated by PETSc.
3719: Vectors in `vecsout` must be created by the user.
3720: Ownership of vectors in `vecsout` is transferred to PETSc.
3722: Level: advanced
3724: .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()`
3725: @*/
3726: PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, void *ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *ctx), void *ctx)
3727: {
3728: PetscFunctionBegin;
3730: ts->resizerollback = rollback;
3731: ts->resizesetup = setup;
3732: ts->resizetransfer = transfer;
3733: ts->resizectx = ctx;
3734: PetscFunctionReturn(PETSC_SUCCESS);
3735: }
3737: /*
3738: TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`.
3740: Collective
3742: Input Parameters:
3743: + ts - The `TS` context obtained from `TSCreate()`
3744: - 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.
3746: Level: developer
3748: Note:
3749: `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is
3750: used within time stepping implementations,
3751: so most users would not generally call this routine themselves.
3753: .seealso: [](ch_ts), `TS`, `TSSetResize()`
3754: @*/
3755: static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg)
3756: {
3757: PetscFunctionBegin;
3759: PetscTryTypeMethod(ts, resizeregister, flg);
3760: /* PetscTryTypeMethod(adapt, resizeregister, flg); */
3761: PetscFunctionReturn(PETSC_SUCCESS);
3762: }
3764: static PetscErrorCode TSResizeReset(TS ts)
3765: {
3766: PetscFunctionBegin;
3768: PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs));
3769: PetscFunctionReturn(PETSC_SUCCESS);
3770: }
3772: static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[])
3773: {
3774: PetscFunctionBegin;
3777: for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i]));
3778: if (ts->resizetransfer) {
3779: PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt));
3780: PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx));
3781: }
3782: for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i]));
3783: PetscFunctionReturn(PETSC_SUCCESS);
3784: }
3786: /*@C
3787: TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`.
3789: Collective
3791: Input Parameters:
3792: + ts - The `TS` context obtained from `TSCreate()`
3793: . name - A string identifying the vector
3794: - vec - The vector
3796: Level: developer
3798: Note:
3799: `TSResizeRegisterVec()` is typically used within time stepping implementations,
3800: so most users would not generally call this routine themselves.
3802: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()`
3803: @*/
3804: PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec)
3805: {
3806: PetscFunctionBegin;
3808: PetscAssertPointer(name, 2);
3810: PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec));
3811: PetscFunctionReturn(PETSC_SUCCESS);
3812: }
3814: /*@C
3815: TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`.
3817: Collective
3819: Input Parameters:
3820: + ts - The `TS` context obtained from `TSCreate()`
3821: . name - A string identifying the vector
3822: - vec - The vector
3824: Level: developer
3826: Note:
3827: `TSResizeRetrieveVec()` is typically used within time stepping implementations,
3828: so most users would not generally call this routine themselves.
3830: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()`
3831: @*/
3832: PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec)
3833: {
3834: PetscFunctionBegin;
3836: PetscAssertPointer(name, 2);
3837: PetscAssertPointer(vec, 3);
3838: PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec));
3839: PetscFunctionReturn(PETSC_SUCCESS);
3840: }
3842: static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[])
3843: {
3844: PetscInt cnt;
3845: PetscObjectList tmp;
3846: Vec *vecsin = NULL;
3847: const char **namesin = NULL;
3849: PetscFunctionBegin;
3850: for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next)
3851: if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++;
3852: if (names) PetscCall(PetscMalloc1(cnt, &namesin));
3853: if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin));
3854: for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) {
3855: if (tmp->obj && tmp->obj->classid == VEC_CLASSID) {
3856: if (vecs) vecsin[cnt] = (Vec)tmp->obj;
3857: if (names) namesin[cnt] = tmp->name;
3858: cnt++;
3859: }
3860: }
3861: if (nv) *nv = cnt;
3862: if (names) *names = namesin;
3863: if (vecs) *vecs = vecsin;
3864: PetscFunctionReturn(PETSC_SUCCESS);
3865: }
3867: /*@
3868: TSResize - Runs the user-defined transfer functions provided with `TSSetResize()`
3870: Collective
3872: Input Parameter:
3873: . ts - The `TS` context obtained from `TSCreate()`
3875: Level: developer
3877: Note:
3878: `TSResize()` is typically used within time stepping implementations,
3879: so most users would not generally call this routine themselves.
3881: .seealso: [](ch_ts), `TS`, `TSSetResize()`
3882: @*/
3883: PetscErrorCode TSResize(TS ts)
3884: {
3885: PetscInt nv = 0;
3886: const char **names = NULL;
3887: Vec *vecsin = NULL;
3888: const char *solname = "ts:vec_sol";
3890: PetscFunctionBegin;
3892: if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS);
3893: if (ts->resizesetup) {
3894: PetscCall(VecLockReadPush(ts->vec_sol));
3895: PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx));
3896: PetscCall(VecLockReadPop(ts->vec_sol));
3897: if (ts->stepresize) {
3898: if (ts->resizerollback) {
3899: PetscCall(TSRollBack(ts));
3900: ts->time_step = ts->time_step0;
3901: }
3902: PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol));
3903: PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */
3904: }
3905: }
3907: PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin));
3908: if (nv) {
3909: Vec *vecsout, vecsol;
3911: /* Reset internal objects */
3912: PetscCall(TSReset(ts));
3914: /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */
3915: PetscCall(PetscCalloc1(nv, &vecsout));
3916: PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout));
3917: for (PetscInt i = 0; i < nv; i++) {
3918: const char *name;
3919: char *oname;
3921: PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
3922: PetscCall(PetscStrallocpy(name, &oname));
3923: PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i]));
3924: if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname));
3925: PetscCall(PetscFree(oname));
3926: PetscCall(VecDestroy(&vecsout[i]));
3927: }
3928: PetscCall(PetscFree(vecsout));
3929: PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */
3931: PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol));
3932: if (vecsol) PetscCall(TSSetSolution(ts, vecsol));
3933: PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution");
3934: }
3936: PetscCall(PetscFree(names));
3937: PetscCall(PetscFree(vecsin));
3938: PetscCall(TSResizeReset(ts));
3939: PetscFunctionReturn(PETSC_SUCCESS);
3940: }
3942: /*@
3943: TSSolve - Steps the requested number of timesteps.
3945: Collective
3947: Input Parameters:
3948: + ts - the `TS` context obtained from `TSCreate()`
3949: - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used,
3950: otherwise it must contain the initial conditions and will contain the solution at the final requested time
3952: Level: beginner
3954: Notes:
3955: The final time returned by this function may be different from the time of the internally
3956: held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have
3957: stepped over the final time.
3959: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
3960: @*/
3961: PetscErrorCode TSSolve(TS ts, Vec u)
3962: {
3963: Vec solution;
3965: PetscFunctionBegin;
3969: PetscCall(TSSetExactFinalTimeDefault(ts));
3970: 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 */
3971: if (!ts->vec_sol || u == ts->vec_sol) {
3972: PetscCall(VecDuplicate(u, &solution));
3973: PetscCall(TSSetSolution(ts, solution));
3974: PetscCall(VecDestroy(&solution)); /* grant ownership */
3975: }
3976: PetscCall(VecCopy(u, ts->vec_sol));
3977: PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3978: } else if (u) PetscCall(TSSetSolution(ts, u));
3979: PetscCall(TSSetUp(ts));
3980: PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3982: PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>");
3983: 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()");
3984: 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");
3985: PetscCheck(!(ts->tspan && ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP), PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "You must use TS_EXACTFINALTIME_MATCHSTEP when using time span");
3987: if (ts->tspan && PetscIsCloseAtTol(ts->ptime, ts->tspan->span_times[0], ts->tspan->reltol * ts->time_step + ts->tspan->abstol, 0)) { /* starting point in time span */
3988: PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0]));
3989: ts->tspan->spanctr = 1;
3990: }
3992: if (ts->forward_solve) PetscCall(TSForwardSetUp(ts));
3994: /* reset number of steps only when the step is not restarted. ARKIMEX
3995: restarts the step after an event. Resetting these counters in such case causes
3996: TSTrajectory to incorrectly save the output files
3997: */
3998: /* reset time step and iteration counters */
3999: if (!ts->steps) {
4000: ts->ksp_its = 0;
4001: ts->snes_its = 0;
4002: ts->num_snes_failures = 0;
4003: ts->reject = 0;
4004: ts->steprestart = PETSC_TRUE;
4005: ts->steprollback = PETSC_FALSE;
4006: ts->stepresize = PETSC_FALSE;
4007: ts->rhsjacobian.time = PETSC_MIN_REAL;
4008: }
4010: /* make sure initial time step does not overshoot final time or the next point in tspan */
4011: if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
4012: PetscReal maxdt;
4013: PetscReal dt = ts->time_step;
4015: if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime;
4016: else maxdt = ts->max_time - ts->ptime;
4017: ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
4018: }
4019: ts->reason = TS_CONVERGED_ITERATING;
4021: {
4022: PetscViewer viewer;
4023: PetscViewerFormat format;
4024: PetscBool flg;
4025: static PetscBool incall = PETSC_FALSE;
4027: if (!incall) {
4028: /* Estimate the convergence rate of the time discretization */
4029: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
4030: if (flg) {
4031: PetscConvEst conv;
4032: DM dm;
4033: PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4034: PetscInt Nf;
4035: PetscBool checkTemporal = PETSC_TRUE;
4037: incall = PETSC_TRUE;
4038: PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
4039: PetscCall(TSGetDM(ts, &dm));
4040: PetscCall(DMGetNumFields(dm, &Nf));
4041: PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
4042: PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
4043: PetscCall(PetscConvEstUseTS(conv, checkTemporal));
4044: PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
4045: PetscCall(PetscConvEstSetFromOptions(conv));
4046: PetscCall(PetscConvEstSetUp(conv));
4047: PetscCall(PetscConvEstGetConvRate(conv, alpha));
4048: PetscCall(PetscViewerPushFormat(viewer, format));
4049: PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4050: PetscCall(PetscViewerPopFormat(viewer));
4051: PetscCall(PetscViewerDestroy(&viewer));
4052: PetscCall(PetscConvEstDestroy(&conv));
4053: PetscCall(PetscFree(alpha));
4054: incall = PETSC_FALSE;
4055: }
4056: }
4057: }
4059: PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre"));
4061: if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4062: PetscUseTypeMethod(ts, solve);
4063: if (u) PetscCall(VecCopy(ts->vec_sol, u));
4064: ts->solvetime = ts->ptime;
4065: solution = ts->vec_sol;
4066: } else { /* Step the requested number of timesteps. */
4067: if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4068: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4070: if (!ts->steps) {
4071: PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4072: PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
4073: }
4075: while (!ts->reason) {
4076: PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4077: if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts));
4078: PetscCall(TSStep(ts));
4079: if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
4080: if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
4081: if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4082: if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4083: PetscCall(TSForwardCostIntegral(ts));
4084: if (ts->reason >= 0) ts->steps++;
4085: }
4086: if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4087: if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4088: PetscCall(TSForwardStep(ts));
4089: if (ts->reason >= 0) ts->steps++;
4090: }
4091: PetscCall(TSPostEvaluate(ts));
4092: 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. */
4093: if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
4094: if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts));
4095: /* check convergence */
4096: if (!ts->reason) {
4097: if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4098: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4099: }
4100: if (!ts->steprollback) {
4101: PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4102: PetscCall(TSPostStep(ts));
4103: if (!ts->resizerollback) PetscCall(TSResize(ts));
4105: if (ts->tspan && ts->tspan->spanctr < ts->tspan->num_span_times) {
4106: PetscCheck(ts->tspan->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(tspan->worktol > 0) in TSSolve()");
4107: if (PetscIsCloseAtTol(ts->ptime, ts->tspan->span_times[ts->tspan->spanctr], ts->tspan->worktol, 0)) PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[ts->tspan->spanctr++]));
4108: }
4109: }
4110: }
4111: PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4113: if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4114: if (!u) u = ts->vec_sol;
4115: PetscCall(TSInterpolate(ts, ts->max_time, u));
4116: ts->solvetime = ts->max_time;
4117: solution = u;
4118: PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
4119: } else {
4120: if (u) PetscCall(VecCopy(ts->vec_sol, u));
4121: ts->solvetime = ts->ptime;
4122: solution = ts->vec_sol;
4123: }
4124: }
4126: PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
4127: PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
4128: PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
4129: if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
4130: PetscFunctionReturn(PETSC_SUCCESS);
4131: }
4133: /*@
4134: TSGetTime - Gets the time of the most recently completed step.
4136: Not Collective
4138: Input Parameter:
4139: . ts - the `TS` context obtained from `TSCreate()`
4141: Output Parameter:
4142: . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`.
4144: Level: beginner
4146: Note:
4147: When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`,
4148: `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated.
4150: .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
4151: @*/
4152: PetscErrorCode TSGetTime(TS ts, PetscReal *t)
4153: {
4154: PetscFunctionBegin;
4156: PetscAssertPointer(t, 2);
4157: *t = ts->ptime;
4158: PetscFunctionReturn(PETSC_SUCCESS);
4159: }
4161: /*@
4162: TSGetPrevTime - Gets the starting time of the previously completed step.
4164: Not Collective
4166: Input Parameter:
4167: . ts - the `TS` context obtained from `TSCreate()`
4169: Output Parameter:
4170: . t - the previous time
4172: Level: beginner
4174: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
4175: @*/
4176: PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t)
4177: {
4178: PetscFunctionBegin;
4180: PetscAssertPointer(t, 2);
4181: *t = ts->ptime_prev;
4182: PetscFunctionReturn(PETSC_SUCCESS);
4183: }
4185: /*@
4186: TSSetTime - Allows one to reset the time.
4188: Logically Collective
4190: Input Parameters:
4191: + ts - the `TS` context obtained from `TSCreate()`
4192: - t - the time
4194: Level: intermediate
4196: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()`
4197: @*/
4198: PetscErrorCode TSSetTime(TS ts, PetscReal t)
4199: {
4200: PetscFunctionBegin;
4203: ts->ptime = t;
4204: PetscFunctionReturn(PETSC_SUCCESS);
4205: }
4207: /*@
4208: TSSetOptionsPrefix - Sets the prefix used for searching for all
4209: TS options in the database.
4211: Logically Collective
4213: Input Parameters:
4214: + ts - The `TS` context
4215: - prefix - The prefix to prepend to all option names
4217: Level: advanced
4219: Note:
4220: A hyphen (-) must NOT be given at the beginning of the prefix name.
4221: The first character of all runtime options is AUTOMATICALLY the
4222: hyphen.
4224: .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()`
4225: @*/
4226: PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[])
4227: {
4228: SNES snes;
4230: PetscFunctionBegin;
4232: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
4233: PetscCall(TSGetSNES(ts, &snes));
4234: PetscCall(SNESSetOptionsPrefix(snes, prefix));
4235: PetscFunctionReturn(PETSC_SUCCESS);
4236: }
4238: /*@
4239: TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4240: TS options in the database.
4242: Logically Collective
4244: Input Parameters:
4245: + ts - The `TS` context
4246: - prefix - The prefix to prepend to all option names
4248: Level: advanced
4250: Note:
4251: A hyphen (-) must NOT be given at the beginning of the prefix name.
4252: The first character of all runtime options is AUTOMATICALLY the
4253: hyphen.
4255: .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()`
4256: @*/
4257: PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[])
4258: {
4259: SNES snes;
4261: PetscFunctionBegin;
4263: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
4264: PetscCall(TSGetSNES(ts, &snes));
4265: PetscCall(SNESAppendOptionsPrefix(snes, prefix));
4266: PetscFunctionReturn(PETSC_SUCCESS);
4267: }
4269: /*@
4270: TSGetOptionsPrefix - Sets the prefix used for searching for all
4271: `TS` options in the database.
4273: Not Collective
4275: Input Parameter:
4276: . ts - The `TS` context
4278: Output Parameter:
4279: . prefix - A pointer to the prefix string used
4281: Level: intermediate
4283: Fortran Notes:
4284: The user should pass in a string 'prefix' of
4285: sufficient length to hold the prefix.
4287: .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
4288: @*/
4289: PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
4290: {
4291: PetscFunctionBegin;
4293: PetscAssertPointer(prefix, 2);
4294: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
4295: PetscFunctionReturn(PETSC_SUCCESS);
4296: }
4298: /*@C
4299: TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4301: Not Collective, but parallel objects are returned if ts is parallel
4303: Input Parameter:
4304: . ts - The `TS` context obtained from `TSCreate()`
4306: Output Parameters:
4307: + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`)
4308: . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`)
4309: . func - Function to compute the Jacobian of the RHS (or `NULL`)
4310: - ctx - User-defined context for Jacobian evaluation routine (or `NULL`)
4312: Level: intermediate
4314: Note:
4315: You can pass in `NULL` for any return argument you do not need.
4317: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4319: @*/
4320: PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx)
4321: {
4322: DM dm;
4324: PetscFunctionBegin;
4325: if (Amat || Pmat) {
4326: SNES snes;
4327: PetscCall(TSGetSNES(ts, &snes));
4328: PetscCall(SNESSetUpMatrices(snes));
4329: PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4330: }
4331: PetscCall(TSGetDM(ts, &dm));
4332: PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
4333: PetscFunctionReturn(PETSC_SUCCESS);
4334: }
4336: /*@C
4337: TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4339: Not Collective, but parallel objects are returned if ts is parallel
4341: Input Parameter:
4342: . ts - The `TS` context obtained from `TSCreate()`
4344: Output Parameters:
4345: + Amat - The (approximate) Jacobian of F(t,U,U_t)
4346: . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat`
4347: . f - The function to compute the matrices
4348: - ctx - User-defined context for Jacobian evaluation routine
4350: Level: advanced
4352: Note:
4353: You can pass in `NULL` for any return argument you do not need.
4355: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4356: @*/
4357: PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx)
4358: {
4359: DM dm;
4361: PetscFunctionBegin;
4362: if (Amat || Pmat) {
4363: SNES snes;
4364: PetscCall(TSGetSNES(ts, &snes));
4365: PetscCall(SNESSetUpMatrices(snes));
4366: PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4367: }
4368: PetscCall(TSGetDM(ts, &dm));
4369: PetscCall(DMTSGetIJacobian(dm, f, ctx));
4370: PetscFunctionReturn(PETSC_SUCCESS);
4371: }
4373: #include <petsc/private/dmimpl.h>
4374: /*@
4375: TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS`
4377: Logically Collective
4379: Input Parameters:
4380: + ts - the `TS` integrator object
4381: - dm - the dm, cannot be `NULL`
4383: Level: intermediate
4385: Notes:
4386: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
4387: even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving
4388: different problems using the same function space.
4390: .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4391: @*/
4392: PetscErrorCode TSSetDM(TS ts, DM dm)
4393: {
4394: SNES snes;
4395: DMTS tsdm;
4397: PetscFunctionBegin;
4400: PetscCall(PetscObjectReference((PetscObject)dm));
4401: if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4402: if (ts->dm->dmts && !dm->dmts) {
4403: PetscCall(DMCopyDMTS(ts->dm, dm));
4404: PetscCall(DMGetDMTS(ts->dm, &tsdm));
4405: /* Grant write privileges to the replacement DM */
4406: if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4407: }
4408: PetscCall(DMDestroy(&ts->dm));
4409: }
4410: ts->dm = dm;
4412: PetscCall(TSGetSNES(ts, &snes));
4413: PetscCall(SNESSetDM(snes, dm));
4414: PetscFunctionReturn(PETSC_SUCCESS);
4415: }
4417: /*@
4418: TSGetDM - Gets the `DM` that may be used by some preconditioners
4420: Not Collective
4422: Input Parameter:
4423: . ts - the `TS`
4425: Output Parameter:
4426: . dm - the `DM`
4428: Level: intermediate
4430: .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4431: @*/
4432: PetscErrorCode TSGetDM(TS ts, DM *dm)
4433: {
4434: PetscFunctionBegin;
4436: if (!ts->dm) {
4437: PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4438: if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4439: }
4440: *dm = ts->dm;
4441: PetscFunctionReturn(PETSC_SUCCESS);
4442: }
4444: /*@
4445: SNESTSFormFunction - Function to evaluate nonlinear residual
4447: Logically Collective
4449: Input Parameters:
4450: + snes - nonlinear solver
4451: . U - the current state at which to evaluate the residual
4452: - ctx - user context, must be a TS
4454: Output Parameter:
4455: . F - the nonlinear residual
4457: Level: advanced
4459: Note:
4460: This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4461: It is most frequently passed to `MatFDColoringSetFunction()`.
4463: .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
4464: @*/
4465: PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx)
4466: {
4467: TS ts = (TS)ctx;
4469: PetscFunctionBegin;
4474: PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
4475: PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
4476: PetscFunctionReturn(PETSC_SUCCESS);
4477: }
4479: /*@
4480: SNESTSFormJacobian - Function to evaluate the Jacobian
4482: Collective
4484: Input Parameters:
4485: + snes - nonlinear solver
4486: . U - the current state at which to evaluate the residual
4487: - ctx - user context, must be a `TS`
4489: Output Parameters:
4490: + A - the Jacobian
4491: - B - the preconditioning matrix (may be the same as A)
4493: Level: developer
4495: Note:
4496: This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4498: .seealso: [](ch_ts), `SNESSetJacobian()`
4499: @*/
4500: PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx)
4501: {
4502: TS ts = (TS)ctx;
4504: PetscFunctionBegin;
4510: PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
4511: PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
4512: PetscFunctionReturn(PETSC_SUCCESS);
4513: }
4515: /*@C
4516: TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only
4518: Collective
4520: Input Parameters:
4521: + ts - time stepping context
4522: . t - time at which to evaluate
4523: . U - state at which to evaluate
4524: - ctx - context
4526: Output Parameter:
4527: . F - right-hand side
4529: Level: intermediate
4531: Note:
4532: This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems.
4533: The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`.
4535: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4536: @*/
4537: PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx)
4538: {
4539: Mat Arhs, Brhs;
4541: PetscFunctionBegin;
4542: PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4543: /* undo the damage caused by shifting */
4544: PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4545: PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4546: PetscCall(MatMult(Arhs, U, F));
4547: PetscFunctionReturn(PETSC_SUCCESS);
4548: }
4550: /*@C
4551: TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4553: Collective
4555: Input Parameters:
4556: + ts - time stepping context
4557: . t - time at which to evaluate
4558: . U - state at which to evaluate
4559: - ctx - context
4561: Output Parameters:
4562: + A - pointer to operator
4563: - B - pointer to preconditioning matrix
4565: Level: intermediate
4567: Note:
4568: This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems.
4570: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4571: @*/
4572: PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx)
4573: {
4574: PetscFunctionBegin;
4575: PetscFunctionReturn(PETSC_SUCCESS);
4576: }
4578: /*@C
4579: TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4581: Collective
4583: Input Parameters:
4584: + ts - time stepping context
4585: . t - time at which to evaluate
4586: . U - state at which to evaluate
4587: . Udot - time derivative of state vector
4588: - ctx - context
4590: Output Parameter:
4591: . F - left hand side
4593: Level: intermediate
4595: Notes:
4596: 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
4597: user is required to write their own `TSComputeIFunction()`.
4598: This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems.
4599: The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`.
4601: Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U
4603: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4604: @*/
4605: PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx)
4606: {
4607: Mat A, B;
4609: PetscFunctionBegin;
4610: PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4611: PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4612: PetscCall(MatMult(A, Udot, F));
4613: PetscFunctionReturn(PETSC_SUCCESS);
4614: }
4616: /*@C
4617: TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE
4619: Collective
4621: Input Parameters:
4622: + ts - time stepping context
4623: . t - time at which to evaluate
4624: . U - state at which to evaluate
4625: . Udot - time derivative of state vector
4626: . shift - shift to apply
4627: - ctx - context
4629: Output Parameters:
4630: + A - pointer to operator
4631: - B - pointer to matrix from which the preconditioner is built (often `A`)
4633: Level: advanced
4635: Notes:
4636: This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems.
4638: It is only appropriate for problems of the form
4640: $$
4641: M \dot{U} = F(U,t)
4642: $$
4644: where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only
4645: works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing
4646: an implicit operator of the form
4648: $$
4649: shift*M + J
4650: $$
4652: 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
4653: a copy of M or reassemble it when requested.
4655: .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4656: @*/
4657: PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx)
4658: {
4659: PetscFunctionBegin;
4660: PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4661: ts->ijacobian.shift = shift;
4662: PetscFunctionReturn(PETSC_SUCCESS);
4663: }
4665: /*@
4666: TSGetEquationType - Gets the type of the equation that `TS` is solving.
4668: Not Collective
4670: Input Parameter:
4671: . ts - the `TS` context
4673: Output Parameter:
4674: . equation_type - see `TSEquationType`
4676: Level: beginner
4678: .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
4679: @*/
4680: PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
4681: {
4682: PetscFunctionBegin;
4684: PetscAssertPointer(equation_type, 2);
4685: *equation_type = ts->equation_type;
4686: PetscFunctionReturn(PETSC_SUCCESS);
4687: }
4689: /*@
4690: TSSetEquationType - Sets the type of the equation that `TS` is solving.
4692: Not Collective
4694: Input Parameters:
4695: + ts - the `TS` context
4696: - equation_type - see `TSEquationType`
4698: Level: advanced
4700: .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
4701: @*/
4702: PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
4703: {
4704: PetscFunctionBegin;
4706: ts->equation_type = equation_type;
4707: PetscFunctionReturn(PETSC_SUCCESS);
4708: }
4710: /*@
4711: TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.
4713: Not Collective
4715: Input Parameter:
4716: . ts - the `TS` context
4718: Output Parameter:
4719: . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4720: manual pages for the individual convergence tests for complete lists
4722: Level: beginner
4724: Note:
4725: Can only be called after the call to `TSSolve()` is complete.
4727: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4728: @*/
4729: PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
4730: {
4731: PetscFunctionBegin;
4733: PetscAssertPointer(reason, 2);
4734: *reason = ts->reason;
4735: PetscFunctionReturn(PETSC_SUCCESS);
4736: }
4738: /*@
4739: TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`.
4741: Logically Collective; reason must contain common value
4743: Input Parameters:
4744: + ts - the `TS` context
4745: - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4746: manual pages for the individual convergence tests for complete lists
4748: Level: advanced
4750: Note:
4751: Can only be called while `TSSolve()` is active.
4753: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4754: @*/
4755: PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
4756: {
4757: PetscFunctionBegin;
4759: ts->reason = reason;
4760: PetscFunctionReturn(PETSC_SUCCESS);
4761: }
4763: /*@
4764: TSGetSolveTime - Gets the time after a call to `TSSolve()`
4766: Not Collective
4768: Input Parameter:
4769: . ts - the `TS` context
4771: Output Parameter:
4772: . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()`
4774: Level: beginner
4776: Note:
4777: Can only be called after the call to `TSSolve()` is complete.
4779: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4780: @*/
4781: PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
4782: {
4783: PetscFunctionBegin;
4785: PetscAssertPointer(ftime, 2);
4786: *ftime = ts->solvetime;
4787: PetscFunctionReturn(PETSC_SUCCESS);
4788: }
4790: /*@
4791: TSGetSNESIterations - Gets the total number of nonlinear iterations
4792: used by the time integrator.
4794: Not Collective
4796: Input Parameter:
4797: . ts - `TS` context
4799: Output Parameter:
4800: . nits - number of nonlinear iterations
4802: Level: intermediate
4804: Note:
4805: This counter is reset to zero for each successive call to `TSSolve()`.
4807: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
4808: @*/
4809: PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
4810: {
4811: PetscFunctionBegin;
4813: PetscAssertPointer(nits, 2);
4814: *nits = ts->snes_its;
4815: PetscFunctionReturn(PETSC_SUCCESS);
4816: }
4818: /*@
4819: TSGetKSPIterations - Gets the total number of linear iterations
4820: used by the time integrator.
4822: Not Collective
4824: Input Parameter:
4825: . ts - `TS` context
4827: Output Parameter:
4828: . lits - number of linear iterations
4830: Level: intermediate
4832: Note:
4833: This counter is reset to zero for each successive call to `TSSolve()`.
4835: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()`
4836: @*/
4837: PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
4838: {
4839: PetscFunctionBegin;
4841: PetscAssertPointer(lits, 2);
4842: *lits = ts->ksp_its;
4843: PetscFunctionReturn(PETSC_SUCCESS);
4844: }
4846: /*@
4847: TSGetStepRejections - Gets the total number of rejected steps.
4849: Not Collective
4851: Input Parameter:
4852: . ts - `TS` context
4854: Output Parameter:
4855: . rejects - number of steps rejected
4857: Level: intermediate
4859: Note:
4860: This counter is reset to zero for each successive call to `TSSolve()`.
4862: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4863: @*/
4864: PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
4865: {
4866: PetscFunctionBegin;
4868: PetscAssertPointer(rejects, 2);
4869: *rejects = ts->reject;
4870: PetscFunctionReturn(PETSC_SUCCESS);
4871: }
4873: /*@
4874: TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS`
4876: Not Collective
4878: Input Parameter:
4879: . ts - `TS` context
4881: Output Parameter:
4882: . fails - number of failed nonlinear solves
4884: Level: intermediate
4886: Note:
4887: This counter is reset to zero for each successive call to `TSSolve()`.
4889: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4890: @*/
4891: PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
4892: {
4893: PetscFunctionBegin;
4895: PetscAssertPointer(fails, 2);
4896: *fails = ts->num_snes_failures;
4897: PetscFunctionReturn(PETSC_SUCCESS);
4898: }
4900: /*@
4901: TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails
4903: Not Collective
4905: Input Parameters:
4906: + ts - `TS` context
4907: - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited
4909: Options Database Key:
4910: . -ts_max_reject - Maximum number of step rejections before a step fails
4912: Level: intermediate
4914: Developer Note:
4915: The options database name is incorrect.
4917: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4918: @*/
4919: PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
4920: {
4921: PetscFunctionBegin;
4923: if (rejects == PETSC_UNLIMITED || rejects == -1) {
4924: ts->max_reject = PETSC_UNLIMITED;
4925: } else {
4926: PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
4927: ts->max_reject = rejects;
4928: }
4929: PetscFunctionReturn(PETSC_SUCCESS);
4930: }
4932: /*@
4933: TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves
4935: Not Collective
4937: Input Parameters:
4938: + ts - `TS` context
4939: - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures.
4941: Options Database Key:
4942: . -ts_max_snes_failures - Maximum number of nonlinear solve failures
4944: Level: intermediate
4946: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
4947: @*/
4948: PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
4949: {
4950: PetscFunctionBegin;
4952: if (fails == PETSC_UNLIMITED || fails == -1) {
4953: ts->max_snes_failures = PETSC_UNLIMITED;
4954: } else {
4955: PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
4956: ts->max_snes_failures = fails;
4957: }
4958: PetscFunctionReturn(PETSC_SUCCESS);
4959: }
4961: /*@
4962: TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()`
4964: Not Collective
4966: Input Parameters:
4967: + ts - `TS` context
4968: - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure
4970: Options Database Key:
4971: . -ts_error_if_step_fails - Error if no step succeeds
4973: Level: intermediate
4975: .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
4976: @*/
4977: PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
4978: {
4979: PetscFunctionBegin;
4981: ts->errorifstepfailed = err;
4982: PetscFunctionReturn(PETSC_SUCCESS);
4983: }
4985: /*@
4986: TSGetAdapt - Get the adaptive controller context for the current method
4988: Collective if controller has not yet been created
4990: Input Parameter:
4991: . ts - time stepping context
4993: Output Parameter:
4994: . adapt - adaptive controller
4996: Level: intermediate
4998: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
4999: @*/
5000: PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
5001: {
5002: PetscFunctionBegin;
5004: PetscAssertPointer(adapt, 2);
5005: if (!ts->adapt) {
5006: PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
5007: PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
5008: }
5009: *adapt = ts->adapt;
5010: PetscFunctionReturn(PETSC_SUCCESS);
5011: }
5013: /*@
5014: TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller
5016: Logically Collective
5018: Input Parameters:
5019: + ts - time integration context
5020: . atol - scalar absolute tolerances
5021: . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
5022: . rtol - scalar relative tolerances
5023: - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present
5025: Options Database Keys:
5026: + -ts_rtol <rtol> - relative tolerance for local truncation error
5027: - -ts_atol <atol> - Absolute tolerance for local truncation error
5029: Level: beginner
5031: Notes:
5032: `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value
5033: or the default value from when the object's type was set.
5035: With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5036: (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5037: computed only for the differential or the algebraic part then this can be done using the vector of
5038: tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5039: differential part and infinity for the algebraic part, the LTE calculation will include only the
5040: differential variables.
5042: Fortran Note:
5043: Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.
5045: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
5046: @*/
5047: PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
5048: {
5049: PetscFunctionBegin;
5050: if (atol == (PetscReal)PETSC_DETERMINE) {
5051: ts->atol = ts->default_atol;
5052: } else if (atol != (PetscReal)PETSC_CURRENT) {
5053: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
5054: ts->atol = atol;
5055: }
5057: if (vatol) {
5058: PetscCall(PetscObjectReference((PetscObject)vatol));
5059: PetscCall(VecDestroy(&ts->vatol));
5060: ts->vatol = vatol;
5061: }
5063: if (rtol == (PetscReal)PETSC_DETERMINE) {
5064: ts->rtol = ts->default_rtol;
5065: } else if (rtol != (PetscReal)PETSC_CURRENT) {
5066: PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
5067: ts->rtol = rtol;
5068: }
5070: if (vrtol) {
5071: PetscCall(PetscObjectReference((PetscObject)vrtol));
5072: PetscCall(VecDestroy(&ts->vrtol));
5073: ts->vrtol = vrtol;
5074: }
5075: PetscFunctionReturn(PETSC_SUCCESS);
5076: }
5078: /*@
5079: TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5081: Logically Collective
5083: Input Parameter:
5084: . ts - time integration context
5086: Output Parameters:
5087: + atol - scalar absolute tolerances, `NULL` to ignore
5088: . vatol - vector of absolute tolerances, `NULL` to ignore
5089: . rtol - scalar relative tolerances, `NULL` to ignore
5090: - vrtol - vector of relative tolerances, `NULL` to ignore
5092: Level: beginner
5094: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
5095: @*/
5096: PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
5097: {
5098: PetscFunctionBegin;
5099: if (atol) *atol = ts->atol;
5100: if (vatol) *vatol = ts->vatol;
5101: if (rtol) *rtol = ts->rtol;
5102: if (vrtol) *vrtol = ts->vrtol;
5103: PetscFunctionReturn(PETSC_SUCCESS);
5104: }
5106: /*@
5107: TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5109: Collective
5111: Input Parameters:
5112: + ts - time stepping context
5113: . U - state vector, usually ts->vec_sol
5114: . Y - state vector to be compared to U
5115: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5117: Output Parameters:
5118: + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5119: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5120: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5122: Options Database Key:
5123: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5125: Level: developer
5127: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
5128: @*/
5129: PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5130: {
5131: PetscInt norma_loc, norm_loc, normr_loc;
5133: PetscFunctionBegin;
5135: 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));
5136: if (wnormtype == NORM_2) {
5137: if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5138: if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5139: if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5140: }
5141: PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5142: PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5143: PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5144: PetscFunctionReturn(PETSC_SUCCESS);
5145: }
5147: /*@
5148: TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5150: Collective
5152: Input Parameters:
5153: + ts - time stepping context
5154: . E - error vector
5155: . U - state vector, usually ts->vec_sol
5156: . Y - state vector, previous time step
5157: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5159: Output Parameters:
5160: + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5161: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5162: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5164: Options Database Key:
5165: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5167: Level: developer
5169: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
5170: @*/
5171: PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5172: {
5173: PetscInt norma_loc, norm_loc, normr_loc;
5175: PetscFunctionBegin;
5177: 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));
5178: if (wnormtype == NORM_2) {
5179: if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5180: if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5181: if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5182: }
5183: PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5184: PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5185: PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5186: PetscFunctionReturn(PETSC_SUCCESS);
5187: }
5189: /*@
5190: TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5192: Logically Collective
5194: Input Parameters:
5195: + ts - time stepping context
5196: - cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5198: Note:
5199: After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5201: Level: intermediate
5203: .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
5204: @*/
5205: PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
5206: {
5207: PetscFunctionBegin;
5209: ts->cfltime_local = cfltime;
5210: ts->cfltime = -1.;
5211: PetscFunctionReturn(PETSC_SUCCESS);
5212: }
5214: /*@
5215: TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5217: Collective
5219: Input Parameter:
5220: . ts - time stepping context
5222: Output Parameter:
5223: . cfltime - maximum stable time step for forward Euler
5225: Level: advanced
5227: .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
5228: @*/
5229: PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
5230: {
5231: PetscFunctionBegin;
5232: if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5233: *cfltime = ts->cfltime;
5234: PetscFunctionReturn(PETSC_SUCCESS);
5235: }
5237: /*@
5238: TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5240: Input Parameters:
5241: + ts - the `TS` context.
5242: . xl - lower bound.
5243: - xu - upper bound.
5245: Level: advanced
5247: Note:
5248: If this routine is not called then the lower and upper bounds are set to
5249: `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`.
5251: .seealso: [](ch_ts), `TS`
5252: @*/
5253: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5254: {
5255: SNES snes;
5257: PetscFunctionBegin;
5258: PetscCall(TSGetSNES(ts, &snes));
5259: PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5260: PetscFunctionReturn(PETSC_SUCCESS);
5261: }
5263: /*@
5264: TSComputeLinearStability - computes the linear stability function at a point
5266: Collective
5268: Input Parameters:
5269: + ts - the `TS` context
5270: . xr - real part of input argument
5271: - xi - imaginary part of input argument
5273: Output Parameters:
5274: + yr - real part of function value
5275: - yi - imaginary part of function value
5277: Level: developer
5279: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
5280: @*/
5281: PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
5282: {
5283: PetscFunctionBegin;
5285: PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5286: PetscFunctionReturn(PETSC_SUCCESS);
5287: }
5289: /*@
5290: TSRestartStep - Flags the solver to restart the next step
5292: Collective
5294: Input Parameter:
5295: . ts - the `TS` context obtained from `TSCreate()`
5297: Level: advanced
5299: Notes:
5300: Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5301: discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5302: vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5303: the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
5304: discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5305: discontinuous source terms).
5307: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5308: @*/
5309: PetscErrorCode TSRestartStep(TS ts)
5310: {
5311: PetscFunctionBegin;
5313: ts->steprestart = PETSC_TRUE;
5314: PetscFunctionReturn(PETSC_SUCCESS);
5315: }
5317: /*@
5318: TSRollBack - Rolls back one time step
5320: Collective
5322: Input Parameter:
5323: . ts - the `TS` context obtained from `TSCreate()`
5325: Level: advanced
5327: .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5328: @*/
5329: PetscErrorCode TSRollBack(TS ts)
5330: {
5331: PetscFunctionBegin;
5333: PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5334: PetscTryTypeMethod(ts, rollback);
5335: PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
5336: ts->time_step = ts->ptime - ts->ptime_prev;
5337: ts->ptime = ts->ptime_prev;
5338: ts->ptime_prev = ts->ptime_prev_rollback;
5339: ts->steps--;
5340: ts->steprollback = PETSC_TRUE;
5341: PetscFunctionReturn(PETSC_SUCCESS);
5342: }
5344: /*@
5345: TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step
5347: Not collective
5349: Input Parameter:
5350: . ts - the `TS` context obtained from `TSCreate()`
5352: Output Parameter:
5353: . flg - the rollback flag
5355: Level: advanced
5357: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
5358: @*/
5359: PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
5360: {
5361: PetscFunctionBegin;
5363: PetscAssertPointer(flg, 2);
5364: *flg = ts->steprollback;
5365: PetscFunctionReturn(PETSC_SUCCESS);
5366: }
5368: /*@
5369: TSGetStepResize - Get the internal flag indicating if the current step is after a resize.
5371: Not collective
5373: Input Parameter:
5374: . ts - the `TS` context obtained from `TSCreate()`
5376: Output Parameter:
5377: . flg - the resize flag
5379: Level: advanced
5381: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
5382: @*/
5383: PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
5384: {
5385: PetscFunctionBegin;
5387: PetscAssertPointer(flg, 2);
5388: *flg = ts->stepresize;
5389: PetscFunctionReturn(PETSC_SUCCESS);
5390: }
5392: /*@
5393: TSGetStages - Get the number of stages and stage values
5395: Input Parameter:
5396: . ts - the `TS` context obtained from `TSCreate()`
5398: Output Parameters:
5399: + ns - the number of stages
5400: - Y - the current stage vectors
5402: Level: advanced
5404: Note:
5405: Both `ns` and `Y` can be `NULL`.
5407: .seealso: [](ch_ts), `TS`, `TSCreate()`
5408: @*/
5409: PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
5410: {
5411: PetscFunctionBegin;
5413: if (ns) PetscAssertPointer(ns, 2);
5414: if (Y) PetscAssertPointer(Y, 3);
5415: if (!ts->ops->getstages) {
5416: if (ns) *ns = 0;
5417: if (Y) *Y = NULL;
5418: } else PetscUseTypeMethod(ts, getstages, ns, Y);
5419: PetscFunctionReturn(PETSC_SUCCESS);
5420: }
5422: /*@C
5423: TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5425: Collective
5427: Input Parameters:
5428: + ts - the `TS` context
5429: . t - current timestep
5430: . U - state vector
5431: . Udot - time derivative of state vector
5432: . shift - shift to apply, see note below
5433: - ctx - an optional user context
5435: Output Parameters:
5436: + J - Jacobian matrix (not altered in this routine)
5437: - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)
5439: Level: intermediate
5441: Notes:
5442: If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5444: dF/dU + shift*dF/dUdot
5446: Most users should not need to explicitly call this routine, as it
5447: is used internally within the nonlinear solvers.
5449: This will first try to get the coloring from the `DM`. If the `DM` type has no coloring
5450: routine, then it will try to get the coloring from the matrix. This requires that the
5451: matrix have nonzero entries precomputed.
5453: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5454: @*/
5455: PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx)
5456: {
5457: SNES snes;
5458: MatFDColoring color;
5459: PetscBool hascolor, matcolor = PETSC_FALSE;
5461: PetscFunctionBegin;
5462: PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5463: PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5464: if (!color) {
5465: DM dm;
5466: ISColoring iscoloring;
5468: PetscCall(TSGetDM(ts, &dm));
5469: PetscCall(DMHasColoring(dm, &hascolor));
5470: if (hascolor && !matcolor) {
5471: PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5472: PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5473: PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5474: PetscCall(MatFDColoringSetFromOptions(color));
5475: PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5476: PetscCall(ISColoringDestroy(&iscoloring));
5477: } else {
5478: MatColoring mc;
5480: PetscCall(MatColoringCreate(B, &mc));
5481: PetscCall(MatColoringSetDistance(mc, 2));
5482: PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5483: PetscCall(MatColoringSetFromOptions(mc));
5484: PetscCall(MatColoringApply(mc, &iscoloring));
5485: PetscCall(MatColoringDestroy(&mc));
5486: PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5487: PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5488: PetscCall(MatFDColoringSetFromOptions(color));
5489: PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5490: PetscCall(ISColoringDestroy(&iscoloring));
5491: }
5492: PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5493: PetscCall(PetscObjectDereference((PetscObject)color));
5494: }
5495: PetscCall(TSGetSNES(ts, &snes));
5496: PetscCall(MatFDColoringApply(B, color, U, snes));
5497: if (J != B) {
5498: PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5499: PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5500: }
5501: PetscFunctionReturn(PETSC_SUCCESS);
5502: }
5504: /*@C
5505: TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5507: Input Parameters:
5508: + ts - the `TS` context
5509: - func - function called within `TSFunctionDomainError()`
5511: Calling sequence of `func`:
5512: + ts - the `TS` context
5513: . time - the current time (of the stage)
5514: . state - the state to check if it is valid
5515: - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable
5517: Level: intermediate
5519: Notes:
5520: If an implicit ODE solver is being used then, in addition to providing this routine, the
5521: user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
5522: function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
5523: Use `TSGetSNES()` to obtain the `SNES` object
5525: Developer Notes:
5526: The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
5527: since one takes a function pointer and the other does not.
5529: .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5530: @*/
5531: PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
5532: {
5533: PetscFunctionBegin;
5535: ts->functiondomainerror = func;
5536: PetscFunctionReturn(PETSC_SUCCESS);
5537: }
5539: /*@
5540: TSFunctionDomainError - Checks if the current state is valid
5542: Input Parameters:
5543: + ts - the `TS` context
5544: . stagetime - time of the simulation
5545: - Y - state vector to check.
5547: Output Parameter:
5548: . accept - Set to `PETSC_FALSE` if the current state vector is valid.
5550: Level: developer
5552: Note:
5553: This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
5554: to check if the current state is valid.
5556: .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
5557: @*/
5558: PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
5559: {
5560: PetscFunctionBegin;
5562: *accept = PETSC_TRUE;
5563: if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5564: PetscFunctionReturn(PETSC_SUCCESS);
5565: }
5567: /*@
5568: TSClone - This function clones a time step `TS` object.
5570: Collective
5572: Input Parameter:
5573: . tsin - The input `TS`
5575: Output Parameter:
5576: . tsout - The output `TS` (cloned)
5578: Level: developer
5580: Notes:
5581: 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.
5582: It will likely be replaced in the future with a mechanism of switching methods on the fly.
5584: 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
5585: .vb
5586: SNES snes_dup = NULL;
5587: TSGetSNES(ts,&snes_dup);
5588: TSSetSNES(ts,snes_dup);
5589: .ve
5591: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5592: @*/
5593: PetscErrorCode TSClone(TS tsin, TS *tsout)
5594: {
5595: TS t;
5596: SNES snes_start;
5597: DM dm;
5598: TSType type;
5600: PetscFunctionBegin;
5601: PetscAssertPointer(tsin, 1);
5602: *tsout = NULL;
5604: PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
5606: /* General TS description */
5607: t->numbermonitors = 0;
5608: t->monitorFrequency = 1;
5609: t->setupcalled = 0;
5610: t->ksp_its = 0;
5611: t->snes_its = 0;
5612: t->nwork = 0;
5613: t->rhsjacobian.time = PETSC_MIN_REAL;
5614: t->rhsjacobian.scale = 1.;
5615: t->ijacobian.shift = 1.;
5617: PetscCall(TSGetSNES(tsin, &snes_start));
5618: PetscCall(TSSetSNES(t, snes_start));
5620: PetscCall(TSGetDM(tsin, &dm));
5621: PetscCall(TSSetDM(t, dm));
5623: t->adapt = tsin->adapt;
5624: PetscCall(PetscObjectReference((PetscObject)t->adapt));
5626: t->trajectory = tsin->trajectory;
5627: PetscCall(PetscObjectReference((PetscObject)t->trajectory));
5629: t->event = tsin->event;
5630: if (t->event) t->event->refct++;
5632: t->problem_type = tsin->problem_type;
5633: t->ptime = tsin->ptime;
5634: t->ptime_prev = tsin->ptime_prev;
5635: t->time_step = tsin->time_step;
5636: t->max_time = tsin->max_time;
5637: t->steps = tsin->steps;
5638: t->max_steps = tsin->max_steps;
5639: t->equation_type = tsin->equation_type;
5640: t->atol = tsin->atol;
5641: t->rtol = tsin->rtol;
5642: t->max_snes_failures = tsin->max_snes_failures;
5643: t->max_reject = tsin->max_reject;
5644: t->errorifstepfailed = tsin->errorifstepfailed;
5646: PetscCall(TSGetType(tsin, &type));
5647: PetscCall(TSSetType(t, type));
5649: t->vec_sol = NULL;
5651: t->cfltime = tsin->cfltime;
5652: t->cfltime_local = tsin->cfltime_local;
5653: t->exact_final_time = tsin->exact_final_time;
5655: t->ops[0] = tsin->ops[0];
5657: if (((PetscObject)tsin)->fortran_func_pointers) {
5658: PetscInt i;
5659: PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers));
5660: for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5661: }
5662: *tsout = t;
5663: PetscFunctionReturn(PETSC_SUCCESS);
5664: }
5666: static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y)
5667: {
5668: TS ts = (TS)ctx;
5670: PetscFunctionBegin;
5671: PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5672: PetscFunctionReturn(PETSC_SUCCESS);
5673: }
5675: /*@
5676: TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5678: Logically Collective
5680: Input Parameter:
5681: . ts - the time stepping routine
5683: Output Parameter:
5684: . flg - `PETSC_TRUE` if the multiply is likely correct
5686: Options Database Key:
5687: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
5689: Level: advanced
5691: Note:
5692: This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5694: .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5695: @*/
5696: PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
5697: {
5698: Mat J, B;
5699: TSRHSJacobianFn *func;
5700: void *ctx;
5702: PetscFunctionBegin;
5703: PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5704: PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5705: PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5706: PetscFunctionReturn(PETSC_SUCCESS);
5707: }
5709: /*@
5710: TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5712: Logically Collective
5714: Input Parameter:
5715: . ts - the time stepping routine
5717: Output Parameter:
5718: . flg - `PETSC_TRUE` if the multiply is likely correct
5720: Options Database Key:
5721: . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
5723: Level: advanced
5725: Notes:
5726: This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5728: .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5729: @*/
5730: PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
5731: {
5732: Mat J, B;
5733: void *ctx;
5734: TSRHSJacobianFn *func;
5736: PetscFunctionBegin;
5737: PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5738: PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5739: PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5740: PetscFunctionReturn(PETSC_SUCCESS);
5741: }
5743: /*@
5744: TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
5746: Logically Collective
5748: Input Parameters:
5749: + ts - timestepping context
5750: - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5752: Options Database Key:
5753: . -ts_use_splitrhsfunction - <true,false>
5755: Level: intermediate
5757: Note:
5758: This is only for multirate methods
5760: .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
5761: @*/
5762: PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
5763: {
5764: PetscFunctionBegin;
5766: ts->use_splitrhsfunction = use_splitrhsfunction;
5767: PetscFunctionReturn(PETSC_SUCCESS);
5768: }
5770: /*@
5771: TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
5773: Not Collective
5775: Input Parameter:
5776: . ts - timestepping context
5778: Output Parameter:
5779: . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5781: Level: intermediate
5783: .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
5784: @*/
5785: PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
5786: {
5787: PetscFunctionBegin;
5789: *use_splitrhsfunction = ts->use_splitrhsfunction;
5790: PetscFunctionReturn(PETSC_SUCCESS);
5791: }
5793: /*@
5794: TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
5796: Logically Collective
5798: Input Parameters:
5799: + ts - the time-stepper
5800: - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)
5802: Level: intermediate
5804: Note:
5805: When the relationship between the nonzero structures is known and supplied the solution process can be much faster
5807: .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
5808: @*/
5809: PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
5810: {
5811: PetscFunctionBegin;
5813: ts->axpy_pattern = str;
5814: PetscFunctionReturn(PETSC_SUCCESS);
5815: }
5817: /*@
5818: TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span
5820: Collective
5822: Input Parameters:
5823: + ts - the time-stepper
5824: . n - number of the time points (>=2)
5825: - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5827: Options Database Key:
5828: . -ts_time_span <t0,...tf> - Sets the time span
5830: Level: intermediate
5832: Notes:
5833: The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.
5834: `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
5835: The intermediate solutions are saved in a vector array that can be accessed with `TSGetTimeSpanSolutions()`. Thus using time span may
5836: pressure the memory system when using a large number of span points.
5838: .seealso: [](ch_ts), `TS`, `TSGetTimeSpan()`, `TSGetTimeSpanSolutions()`
5839: @*/
5840: PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times)
5841: {
5842: PetscFunctionBegin;
5844: PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
5845: if (ts->tspan && n != ts->tspan->num_span_times) {
5846: PetscCall(PetscFree(ts->tspan->span_times));
5847: PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol));
5848: PetscCall(PetscMalloc1(n, &ts->tspan->span_times));
5849: }
5850: if (!ts->tspan) {
5851: TSTimeSpan tspan;
5852: PetscCall(PetscNew(&tspan));
5853: PetscCall(PetscMalloc1(n, &tspan->span_times));
5854: tspan->reltol = 1e-6;
5855: tspan->abstol = 10 * PETSC_MACHINE_EPSILON;
5856: tspan->worktol = 0;
5857: ts->tspan = tspan;
5858: }
5859: ts->tspan->num_span_times = n;
5860: PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n));
5861: PetscCall(TSSetTime(ts, ts->tspan->span_times[0]));
5862: PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1]));
5863: PetscFunctionReturn(PETSC_SUCCESS);
5864: }
5866: /*@C
5867: TSGetTimeSpan - gets the time span set with `TSSetTimeSpan()`
5869: Not Collective
5871: Input Parameter:
5872: . ts - the time-stepper
5874: Output Parameters:
5875: + n - number of the time points (>=2)
5876: - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5878: Level: beginner
5880: Note:
5881: The values obtained are valid until the `TS` object is destroyed.
5883: Both `n` and `span_times` can be `NULL`.
5885: .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`, `TSGetTimeSpanSolutions()`
5886: @*/
5887: PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal *span_times[])
5888: {
5889: PetscFunctionBegin;
5891: if (n) PetscAssertPointer(n, 2);
5892: if (span_times) PetscAssertPointer(span_times, 3);
5893: if (!ts->tspan) {
5894: if (n) *n = 0;
5895: if (span_times) *span_times = NULL;
5896: } else {
5897: if (n) *n = ts->tspan->num_span_times;
5898: if (span_times) *span_times = ts->tspan->span_times;
5899: }
5900: PetscFunctionReturn(PETSC_SUCCESS);
5901: }
5903: /*@
5904: TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span.
5906: Input Parameter:
5907: . ts - the `TS` context obtained from `TSCreate()`
5909: Output Parameters:
5910: + nsol - the number of solutions
5911: - Sols - the solution vectors
5913: Level: intermediate
5915: Notes:
5916: Both `nsol` and `Sols` can be `NULL`.
5918: Some time points in the time span may be skipped by `TS` so that `nsol` is less than the number of points specified by `TSSetTimeSpan()`.
5919: For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain points in the span.
5921: .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`
5922: @*/
5923: PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols)
5924: {
5925: PetscFunctionBegin;
5927: if (nsol) PetscAssertPointer(nsol, 2);
5928: if (Sols) PetscAssertPointer(Sols, 3);
5929: if (!ts->tspan) {
5930: if (nsol) *nsol = 0;
5931: if (Sols) *Sols = NULL;
5932: } else {
5933: if (nsol) *nsol = ts->tspan->spanctr;
5934: if (Sols) *Sols = ts->tspan->vecs_sol;
5935: }
5936: PetscFunctionReturn(PETSC_SUCCESS);
5937: }
5939: /*@
5940: TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.
5942: Collective
5944: Input Parameters:
5945: + ts - the `TS` context
5946: . J - Jacobian matrix (not altered in this routine)
5947: - B - newly computed Jacobian matrix to use with preconditioner
5949: Level: intermediate
5951: Notes:
5952: This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
5953: many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
5954: and multiple fields are involved.
5956: Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
5957: structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
5958: usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
5959: `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.
5961: .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5962: @*/
5963: PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
5964: {
5965: MatColoring mc = NULL;
5966: ISColoring iscoloring = NULL;
5967: MatFDColoring matfdcoloring = NULL;
5969: PetscFunctionBegin;
5970: /* Generate new coloring after eliminating zeros in the matrix */
5971: PetscCall(MatEliminateZeros(B, PETSC_TRUE));
5972: PetscCall(MatColoringCreate(B, &mc));
5973: PetscCall(MatColoringSetDistance(mc, 2));
5974: PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5975: PetscCall(MatColoringSetFromOptions(mc));
5976: PetscCall(MatColoringApply(mc, &iscoloring));
5977: PetscCall(MatColoringDestroy(&mc));
5978: /* Replace the old coloring with the new one */
5979: PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
5980: PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5981: PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
5982: PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
5983: PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
5984: PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
5985: PetscCall(ISColoringDestroy(&iscoloring));
5986: PetscFunctionReturn(PETSC_SUCCESS);
5987: }