Actual source code: ts.c

  1: #include <petsc/private/tsimpl.h>
  2: #include <petscdmda.h>
  3: #include <petscdmshell.h>
  4: #include <petscdmplex.h>
  5: #include <petscdmswarm.h>
  6: #include <petscviewer.h>
  7: #include <petscdraw.h>
  8: #include <petscconvest.h>

 10: /* Logging support */
 11: PetscClassId  TS_CLASSID, DMTS_CLASSID;
 12: PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;

 14: const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED", "STEPOVER", "INTERPOLATE", "MATCHSTEP", "TSExactFinalTimeOption", "TS_EXACTFINALTIME_", NULL};

 16: static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt, TSAdaptType default_type)
 17: {
 18:   PetscFunctionBegin;
 20:   PetscAssertPointer(default_type, 2);
 21:   if (!((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, default_type));
 22:   PetscFunctionReturn(PETSC_SUCCESS);
 23: }

 25: /*@
 26:   TSSetFromOptions - Sets various `TS` parameters from the options database

 28:   Collective

 30:   Input Parameter:
 31: . ts - the `TS` context obtained from `TSCreate()`

 33:   Options Database Keys:
 34: + -ts_type type                                                      - EULER, BEULER, SUNDIALS, PSEUDO, CN, RK, THETA, ALPHA, GLLE,  SSP, GLEE, BSYMP, IRK, see `TSType`
 35: . -ts_save_trajectory                                                - checkpoint the solution at each time-step
 36: . -ts_max_time time                                                  - maximum time to compute to
 37: . -ts_time_span t0,...,tf                                            - sets the time span, solutions are computed and stored for each indicated time, init_time and max_time are set
 38: . -ts_eval_times t0,...,tn                                           - time points where solutions are computed and stored for each indicated time
 39: . -ts_max_steps steps                                                - maximum time-step number to execute until (possibly with nonzero starting value)
 40: . -ts_run_steps steps                                                - maximum number of time steps for `TSSolve()` to take on each call
 41: . -ts_init_time time                                                 - initial time to start computation
 42: . -ts_final_time time                                                - final time to compute to (deprecated: use `-ts_max_time`)
 43: . -ts_time_step dt                                                   - initial time step (only a suggestion, the actual initial time step used differ)
 44: . -ts_exact_final_time (stepover,interpolate,matchstep)              - whether to stop at the exact given final time and how to compute the solution at that time
 45: . -ts_max_snes_failures maxfailures                                  - Maximum number of nonlinear solve failures allowed
 46: . -ts_max_step_rejections maxrejects                                 - Maximum number of step rejections before step fails
 47: . -ts_error_if_step_fails (true|false)                               - Error if no step succeeds
 48: . -ts_rtol rtol                                                      - relative tolerance for local truncation error
 49: . -ts_atol atol                                                      - Absolute tolerance for local truncation error
 50: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view               - test the Jacobian at each iteration against finite difference with RHS function
 51: . -ts_rhs_jacobian_test_mult_transpose                               - test the Jacobian at each iteration against finite difference with RHS function
 52: . -ts_adjoint_solve (true|false)                                     - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
 53: . -ts_fd_color                                                       - Use finite differences with coloring to compute IJacobian
 54: . -ts_monitor                                                        - print information at each timestep
 55: . -ts_monitor_cancel                                                 - Cancel all monitors
 56: . -ts_monitor_wall_clock_time                                        - Monitor wall-clock time, KSP iterations, and SNES iterations per step
 57: . -ts_monitor_lg_solution                                            - Monitor solution graphically
 58: . -ts_monitor_lg_error                                               - Monitor error graphically
 59: . -ts_monitor_error                                                  - Monitors norm of error
 60: . -ts_monitor_lg_timestep                                            - Monitor timestep size graphically
 61: . -ts_monitor_lg_timestep_log                                        - Monitor log timestep size graphically
 62: . -ts_monitor_lg_snes_iterations                                     - Monitor number nonlinear iterations for each timestep graphically
 63: . -ts_monitor_lg_ksp_iterations                                      - Monitor number nonlinear iterations for each timestep graphically
 64: . -ts_monitor_sp_eig                                                 - Monitor eigenvalues of linearized operator graphically
 65: . -ts_monitor_draw_solution                                          - Monitor solution graphically
 66: . -ts_monitor_draw_solution_phase  xleft,yleft,xright,yright         - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
 67: . -ts_monitor_draw_error                                             - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
 68: . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
 69: . -ts_monitor_solution_interval interval                             - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
 70: . -ts_monitor_solution_skip_initial                                  - skip writing of initial condition
 71: . -ts_monitor_solution_vtk filename.vts,filename.vtu                 - Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts (filename-%%03" PetscInt_FMT ".vtu)
 72: . -ts_monitor_solution_vtk_interval interval                         - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
 73: - -ts_monitor_envelope                                               - determine maximum and minimum value of each component of the solution over the solution time

 75:   Level: beginner

 77:   Notes:
 78:   See `SNESSetFromOptions()` and `KSPSetFromOptions()` for how to control the nonlinear and linear solves used by the time-stepper.

 80:   Certain `SNES` options get reset for each new nonlinear solver, for example `-snes_lag_jacobian its` and `-snes_lag_preconditioner its`, in order
 81:   to retain them over the multiple nonlinear solves that `TS` uses you must also provide `-snes_lag_jacobian_persists true` and
 82:   `-snes_lag_preconditioner_persists true`

 84:   Developer Notes:
 85:   We should unify all the -ts_monitor options in the way that -xxx_view has been unified

 87: .seealso: [](ch_ts), `TS`, `TSGetType()`
 88: @*/
 89: PetscErrorCode TSSetFromOptions(TS ts)
 90: {
 91:   PetscBool              opt, flg, tflg;
 92:   char                   monfilename[PETSC_MAX_PATH_LEN];
 93:   PetscReal              time_step, eval_times[100] = {0};
 94:   PetscInt               num_eval_times = PETSC_STATIC_ARRAY_LENGTH(eval_times);
 95:   TSExactFinalTimeOption eftopt;
 96:   char                   dir[16];
 97:   TSIFunctionFn         *ifun;
 98:   const char            *defaultType;
 99:   char                   typeName[256];

101:   PetscFunctionBegin;

104:   PetscCall(TSRegisterAll());
105:   PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));

107:   PetscObjectOptionsBegin((PetscObject)ts);
108:   if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
109:   else defaultType = ifun ? TSBEULER : TSEULER;
110:   PetscCall(PetscOptionsFList("-ts_type", "TS method", "TSSetType", TSList, defaultType, typeName, 256, &opt));
111:   if (opt) PetscCall(TSSetType(ts, typeName));
112:   else PetscCall(TSSetType(ts, defaultType));

114:   /* Handle generic TS options */
115:   PetscCall(PetscOptionsDeprecated("-ts_final_time", "-ts_max_time", "3.10", NULL));
116:   PetscCall(PetscOptionsReal("-ts_max_time", "Maximum time to run to", "TSSetMaxTime", ts->max_time, &ts->max_time, NULL));
117:   PetscCall(PetscOptionsRealArray("-ts_time_span", "Time span", "TSSetTimeSpan", eval_times, &num_eval_times, &flg));
118:   if (flg) PetscCall(TSSetTimeSpan(ts, num_eval_times, eval_times));
119:   num_eval_times = PETSC_STATIC_ARRAY_LENGTH(eval_times);
120:   PetscCall(PetscOptionsRealArray("-ts_eval_times", "Evaluation time points", "TSSetEvaluationTimes", eval_times, &num_eval_times, &opt));
121:   PetscCheck(flg != opt || (!flg && !opt), PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "May not provide -ts_time_span and -ts_eval_times simultaneously");
122:   if (opt) PetscCall(TSSetEvaluationTimes(ts, num_eval_times, eval_times));
123:   PetscCall(PetscOptionsInt("-ts_max_steps", "Maximum time step number to execute to (possibly with non-zero starting value)", "TSSetMaxSteps", ts->max_steps, &ts->max_steps, NULL));
124:   PetscCall(PetscOptionsInt("-ts_run_steps", "Maximum number of time steps to take on each call to TSSolve()", "TSSetRunSteps", ts->run_steps, &ts->run_steps, NULL));
125:   PetscCall(PetscOptionsReal("-ts_init_time", "Initial time", "TSSetTime", ts->ptime, &ts->ptime, NULL));
126:   PetscCall(PetscOptionsDeprecated("-ts_dt", "-ts_time_step", "3.25", NULL));
127:   PetscCall(PetscOptionsReal("-ts_time_step", "Initial time step", "TSSetTimeStep", ts->time_step, &time_step, &flg));
128:   if (flg) PetscCall(TSSetTimeStep(ts, time_step));
129:   PetscCall(PetscOptionsEnum("-ts_exact_final_time", "Option for handling of final time step", "TSSetExactFinalTime", TSExactFinalTimeOptions, (PetscEnum)ts->exact_final_time, (PetscEnum *)&eftopt, &flg));
130:   if (flg) PetscCall(TSSetExactFinalTime(ts, eftopt));
131:   PetscCall(PetscOptionsInt("-ts_max_snes_failures", "Maximum number of nonlinear solve failures", "TSSetMaxSNESFailures", ts->max_snes_failures, &ts->max_snes_failures, &flg));
132:   if (flg) PetscCall(TSSetMaxSNESFailures(ts, ts->max_snes_failures));
133:   PetscCall(PetscOptionsDeprecated("-ts_max_reject", "-ts_max_step_rejections", "3.25", NULL));
134:   PetscCall(PetscOptionsInt("-ts_max_step_rejections", "Maximum number of step rejections before step fails", "TSSetMaxStepRejections", ts->max_reject, &ts->max_reject, &flg));
135:   if (flg) PetscCall(TSSetMaxStepRejections(ts, ts->max_reject));
136:   PetscCall(PetscOptionsBool("-ts_error_if_step_fails", "Error if no step succeeds", "TSSetErrorIfStepFails", ts->errorifstepfailed, &ts->errorifstepfailed, NULL));
137:   PetscCall(PetscOptionsBoundedReal("-ts_rtol", "Relative tolerance for local truncation error", "TSSetTolerances", ts->rtol, &ts->rtol, NULL, 0));
138:   PetscCall(PetscOptionsBoundedReal("-ts_atol", "Absolute tolerance for local truncation error", "TSSetTolerances", ts->atol, &ts->atol, NULL, 0));

140:   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult", "Test the RHS Jacobian for consistency with RHS at each solve ", "None", ts->testjacobian, &ts->testjacobian, NULL));
141:   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult_transpose", "Test the RHS Jacobian transpose for consistency with RHS at each solve ", "None", ts->testjacobiantranspose, &ts->testjacobiantranspose, NULL));
142:   PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction", "Use the split RHS function for multirate solvers ", "TSSetUseSplitRHSFunction", ts->use_splitrhsfunction, &ts->use_splitrhsfunction, NULL));
143: #if defined(PETSC_HAVE_SAWS)
144:   {
145:     PetscBool set;
146:     flg = PETSC_FALSE;
147:     PetscCall(PetscOptionsBool("-ts_saws_block", "Block for SAWs memory snooper at end of TSSolve", "PetscObjectSAWsBlock", ((PetscObject)ts)->amspublishblock, &flg, &set));
148:     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts, flg));
149:   }
150: #endif

152:   /* Monitor options */
153:   PetscCall(PetscOptionsDeprecated("-ts_monitor_frequency", "-ts_dmswarm_monitor_moments_interval", "3.24", "Retired in favor of monitor-specific intervals (ts_dmswarm_monitor_moments was the only monitor to use ts_monitor_frequency)"));
154:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor", "Monitor time and timestep size", "TSMonitorDefault", TSMonitorDefault, NULL));
155:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_wall_clock_time", "Monitor wall-clock time, KSP iterations, and SNES iterations per step", "TSMonitorWallClockTime", TSMonitorWallClockTime, TSMonitorWallClockTimeSetUp));
156:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_extreme", "Monitor extreme values of the solution", "TSMonitorExtreme", TSMonitorExtreme, NULL));
157:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_solution", "View the solution at each timestep", "TSMonitorSolution", TSMonitorSolution, TSMonitorSolutionSetup));
158:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_dmswarm_monitor_moments", "Monitor moments of particle distribution", "TSDMSwarmMonitorMoments", TSDMSwarmMonitorMoments, NULL));
159:   PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
160:   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename));

162:   PetscCall(PetscOptionsName("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", &opt));
163:   if (opt) {
164:     PetscInt  howoften = 1;
165:     DM        dm;
166:     PetscBool net;

168:     PetscCall(PetscOptionsInt("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", howoften, &howoften, NULL));
169:     PetscCall(TSGetDM(ts, &dm));
170:     PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMNETWORK, &net));
171:     if (net) {
172:       TSMonitorLGCtxNetwork ctx;
173:       PetscCall(TSMonitorLGCtxNetworkCreate(ts, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &ctx));
174:       PetscCall(TSMonitorSet(ts, TSMonitorLGCtxNetworkSolution, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxNetworkDestroy));
175:       PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy", "Plot the solution with a semi-log axis", "", ctx->semilogy, &ctx->semilogy, NULL));
176:     } else {
177:       TSMonitorLGCtx ctx;
178:       PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
179:       PetscCall(TSMonitorSet(ts, TSMonitorLGSolution, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
180:     }
181:   }

183:   PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt));
184:   if (opt) {
185:     TSMonitorLGCtx ctx;
186:     PetscInt       howoften = 1;

188:     PetscCall(PetscOptionsInt("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", howoften, &howoften, NULL));
189:     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
190:     PetscCall(TSMonitorSet(ts, TSMonitorLGError, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
191:   }
192:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_error", "View the error at each timestep", "TSMonitorError", TSMonitorError, NULL));

194:   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt));
195:   if (opt) {
196:     TSMonitorLGCtx ctx;
197:     PetscInt       howoften = 1;

199:     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
200:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
201:     PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
202:   }
203:   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", &opt));
204:   if (opt) {
205:     TSMonitorLGCtx ctx;
206:     PetscInt       howoften = 1;

208:     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
209:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
210:     PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
211:     ctx->semilogy = PETSC_TRUE;
212:   }

214:   PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", &opt));
215:   if (opt) {
216:     TSMonitorLGCtx ctx;
217:     PetscInt       howoften = 1;

219:     PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", howoften, &howoften, NULL));
220:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
221:     PetscCall(TSMonitorSet(ts, TSMonitorLGSNESIterations, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
222:   }
223:   PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", &opt));
224:   if (opt) {
225:     TSMonitorLGCtx ctx;
226:     PetscInt       howoften = 1;

228:     PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", howoften, &howoften, NULL));
229:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
230:     PetscCall(TSMonitorSet(ts, TSMonitorLGKSPIterations, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
231:   }
232:   PetscCall(PetscOptionsName("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", &opt));
233:   if (opt) {
234:     TSMonitorSPEigCtx ctx;
235:     PetscInt          howoften = 1;

237:     PetscCall(PetscOptionsInt("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", howoften, &howoften, NULL));
238:     PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
239:     PetscCall(TSMonitorSet(ts, TSMonitorSPEig, ctx, (PetscCtxDestroyFn *)TSMonitorSPEigCtxDestroy));
240:   }
241:   PetscCall(PetscOptionsName("-ts_monitor_sp_swarm", "Display particle phase space from the DMSwarm", "TSMonitorSPSwarm", &opt));
242:   if (opt) {
243:     TSMonitorSPCtx ctx;
244:     PetscInt       howoften = 1, retain = 0;
245:     PetscBool      phase = PETSC_TRUE, create = PETSC_TRUE, multispecies = PETSC_FALSE;

247:     for (PetscInt i = 0; i < ts->numbermonitors; ++i)
248:       if (ts->monitor[i] == TSMonitorSPSwarmSolution) {
249:         create = PETSC_FALSE;
250:         break;
251:       }
252:     if (create) {
253:       PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm", "Display particles phase space from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL));
254:       PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL));
255:       PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL));
256:       PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_multi_species", "Color particles by particle species", "TSMonitorSPSwarm", multispecies, &multispecies, NULL));
257:       PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, multispecies, &ctx));
258:       PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscCtxDestroyFn *)TSMonitorSPCtxDestroy));
259:     }
260:   }
261:   PetscCall(PetscOptionsName("-ts_monitor_hg_swarm", "Display particle histogram from the DMSwarm", "TSMonitorHGSwarm", &opt));
262:   if (opt) {
263:     TSMonitorHGCtx ctx;
264:     PetscInt       howoften = 1, Ns = 1;
265:     PetscBool      velocity = PETSC_FALSE, create = PETSC_TRUE;

267:     for (PetscInt i = 0; i < ts->numbermonitors; ++i)
268:       if (ts->monitor[i] == TSMonitorHGSwarmSolution) {
269:         create = PETSC_FALSE;
270:         break;
271:       }
272:     if (create) {
273:       DM       sw, dm;
274:       PetscInt Nc, Nb;

276:       PetscCall(TSGetDM(ts, &sw));
277:       PetscCall(DMSwarmGetCellDM(sw, &dm));
278:       PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &Nc));
279:       Nb = PetscMin(20, PetscMax(10, Nc));
280:       PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm", "Display particles histogram from the DMSwarm", "TSMonitorHGSwarm", howoften, &howoften, NULL));
281:       PetscCall(PetscOptionsBool("-ts_monitor_hg_swarm_velocity", "Plot in velocity space rather than coordinate space", "TSMonitorHGSwarm", velocity, &velocity, NULL));
282:       PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_species", "Number of species to histogram", "TSMonitorHGSwarm", Ns, &Ns, NULL));
283:       PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_bins", "Number of histogram bins", "TSMonitorHGSwarm", Nb, &Nb, NULL));
284:       PetscCall(TSMonitorHGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, Ns, Nb, velocity, &ctx));
285:       PetscCall(TSMonitorSet(ts, TSMonitorHGSwarmSolution, ctx, (PetscCtxDestroyFn *)TSMonitorHGCtxDestroy));
286:     }
287:   }
288:   opt = PETSC_FALSE;
289:   PetscCall(PetscOptionsName("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", &opt));
290:   if (opt) {
291:     TSMonitorDrawCtx ctx;
292:     PetscInt         howoften = 1;

294:     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", howoften, &howoften, NULL));
295:     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Computed Solution", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
296:     PetscCall(TSMonitorSet(ts, TSMonitorDrawSolution, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
297:   }
298:   opt = PETSC_FALSE;
299:   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", &opt));
300:   if (opt) {
301:     TSMonitorDrawCtx ctx;
302:     PetscReal        bounds[4];
303:     PetscInt         n = 4;
304:     PetscDraw        draw;
305:     PetscDrawAxis    axis;

307:     PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", bounds, &n, NULL));
308:     PetscCheck(n == 4, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Must provide bounding box of phase field");
309:     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, 1, &ctx));
310:     PetscCall(PetscViewerDrawGetDraw(ctx->viewer, 0, &draw));
311:     PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer, 0, &axis));
312:     PetscCall(PetscDrawAxisSetLimits(axis, bounds[0], bounds[2], bounds[1], bounds[3]));
313:     PetscCall(PetscDrawAxisSetLabels(axis, "Phase Diagram", "Variable 1", "Variable 2"));
314:     PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionPhase, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
315:   }
316:   opt = PETSC_FALSE;
317:   PetscCall(PetscOptionsName("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", &opt));
318:   if (opt) {
319:     TSMonitorDrawCtx ctx;
320:     PetscInt         howoften = 1;

322:     PetscCall(PetscOptionsInt("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", howoften, &howoften, NULL));
323:     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Error", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
324:     PetscCall(TSMonitorSet(ts, TSMonitorDrawError, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
325:   }
326:   opt = PETSC_FALSE;
327:   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", &opt));
328:   if (opt) {
329:     TSMonitorDrawCtx ctx;
330:     PetscInt         howoften = 1;

332:     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", howoften, &howoften, NULL));
333:     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Solution provided by user function", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
334:     PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionFunction, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
335:   }

337:   opt = PETSC_FALSE;
338:   PetscCall(PetscOptionsString("-ts_monitor_solution_vtk", "Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts", "TSMonitorSolutionVTK", NULL, monfilename, sizeof(monfilename), &flg));
339:   if (flg) {
340:     TSMonitorVTKCtx ctx;

342:     PetscCall(TSMonitorSolutionVTKCtxCreate(monfilename, &ctx));
343:     PetscCall(PetscOptionsInt("-ts_monitor_solution_vtk_interval", "Save every interval time step (-1 for last step only)", NULL, ctx->interval, &ctx->interval, NULL));
344:     PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscCtx))TSMonitorSolutionVTK, ctx, (PetscCtxDestroyFn *)TSMonitorSolutionVTKDestroy));
345:   }

347:   PetscCall(PetscOptionsString("-ts_monitor_dmda_ray", "Display a ray of the solution", "None", "y=0", dir, sizeof(dir), &flg));
348:   if (flg) {
349:     TSMonitorDMDARayCtx *rayctx;
350:     int                  ray = 0;
351:     DMDirection          ddir;
352:     DM                   da;
353:     PetscMPIInt          rank;

355:     PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
356:     if (dir[0] == 'x') ddir = DM_X;
357:     else if (dir[0] == 'y') ddir = DM_Y;
358:     else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
359:     sscanf(dir + 2, "%d", &ray);

361:     PetscCall(PetscInfo(ts, "Displaying DMDA ray %c = %d\n", dir[0], ray));
362:     PetscCall(PetscNew(&rayctx));
363:     PetscCall(TSGetDM(ts, &da));
364:     PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
365:     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts), &rank));
366:     if (rank == 0) PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, NULL, NULL, 0, 0, 600, 300, &rayctx->viewer));
367:     rayctx->lgctx = NULL;
368:     PetscCall(TSMonitorSet(ts, TSMonitorDMDARay, rayctx, TSMonitorDMDARayDestroy));
369:   }
370:   PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray", "Display a ray of the solution", "None", "x=0", dir, sizeof(dir), &flg));
371:   if (flg) {
372:     TSMonitorDMDARayCtx *rayctx;
373:     int                  ray = 0;
374:     DMDirection          ddir;
375:     DM                   da;
376:     PetscInt             howoften = 1;

378:     PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
379:     if (dir[0] == 'x') ddir = DM_X;
380:     else if (dir[0] == 'y') ddir = DM_Y;
381:     else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
382:     sscanf(dir + 2, "%d", &ray);

384:     PetscCall(PetscInfo(ts, "Displaying LG DMDA ray %c = %d\n", dir[0], ray));
385:     PetscCall(PetscNew(&rayctx));
386:     PetscCall(TSGetDM(ts, &da));
387:     PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
388:     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &rayctx->lgctx));
389:     PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
390:   }

392:   PetscCall(PetscOptionsName("-ts_monitor_envelope", "Monitor maximum and minimum value of each component of the solution", "TSMonitorEnvelope", &opt));
393:   if (opt) {
394:     TSMonitorEnvelopeCtx ctx;

396:     PetscCall(TSMonitorEnvelopeCtxCreate(ts, &ctx));
397:     PetscCall(TSMonitorSet(ts, TSMonitorEnvelope, ctx, (PetscCtxDestroyFn *)TSMonitorEnvelopeCtxDestroy));
398:   }
399:   flg = PETSC_FALSE;
400:   PetscCall(PetscOptionsBool("-ts_monitor_cancel", "Remove all monitors", "TSMonitorCancel", flg, &flg, &opt));
401:   if (opt && flg) PetscCall(TSMonitorCancel(ts));

403:   flg = PETSC_FALSE;
404:   PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeIJacobianDefaultColor", flg, &flg, NULL));
405:   if (flg) {
406:     DM dm;

408:     PetscCall(TSGetDM(ts, &dm));
409:     PetscCall(DMTSUnsetIJacobianContext_Internal(dm));
410:     PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
411:     PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
412:   }

414:   /* Handle specific TS options */
415:   PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject);

417:   /* Handle TSAdapt options */
418:   PetscCall(TSGetAdapt(ts, &ts->adapt));
419:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
420:   PetscCall(TSAdaptSetFromOptions(ts->adapt, PetscOptionsObject));

422:   /* TS trajectory must be set after TS, since it may use some TS options above */
423:   tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
424:   PetscCall(PetscOptionsBool("-ts_save_trajectory", "Save the solution at each timestep", "TSSetSaveTrajectory", tflg, &tflg, NULL));
425:   if (tflg) PetscCall(TSSetSaveTrajectory(ts));

427:   PetscCall(TSAdjointSetFromOptions(ts, PetscOptionsObject));

429:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
430:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject));
431:   PetscOptionsEnd();

433:   if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory, ts));

435:   /* why do we have to do this here and not during TSSetUp? */
436:   PetscCall(TSGetSNES(ts, &ts->snes));
437:   if (ts->problem_type == TS_LINEAR) {
438:     PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &flg, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
439:     if (!flg) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
440:   }
441:   PetscCall(SNESSetFromOptions(ts->snes));
442:   PetscFunctionReturn(PETSC_SUCCESS);
443: }

445: /*@
446:   TSGetTrajectory - Gets the trajectory from a `TS` if it exists

448:   Collective

450:   Input Parameter:
451: . ts - the `TS` context obtained from `TSCreate()`

453:   Output Parameter:
454: . tr - the `TSTrajectory` object, if it exists

456:   Level: advanced

458:   Note:
459:   This routine should be called after all `TS` options have been set

461: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()`
462: @*/
463: PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr)
464: {
465:   PetscFunctionBegin;
467:   *tr = ts->trajectory;
468:   PetscFunctionReturn(PETSC_SUCCESS);
469: }

471: /*@
472:   TSSetSaveTrajectory - Causes the `TS` to save its solutions as it iterates forward in time in a `TSTrajectory` object

474:   Collective

476:   Input Parameter:
477: . ts - the `TS` context obtained from `TSCreate()`

479:   Options Database Keys:
480: + -ts_save_trajectory                                         - saves the trajectory to a file
481: - -ts_trajectory_type (basic|singlefile|memory|visualization) - set trajectory type

483:   Level: intermediate

485:   Notes:
486:   This routine should be called after all `TS` options have been set

488:   The `TSTRAJECTORYVISUALIZATION` files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
489:   MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m

491: .seealso: [](ch_ts), `TS`, `TSTrajectoryType`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`
492: @*/
493: PetscErrorCode TSSetSaveTrajectory(TS ts)
494: {
495:   PetscFunctionBegin;
497:   if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
498:   PetscFunctionReturn(PETSC_SUCCESS);
499: }

501: /*@
502:   TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object

504:   Collective

506:   Input Parameter:
507: . ts - the `TS` context obtained from `TSCreate()`

509:   Level: intermediate

511: .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()`
512: @*/
513: PetscErrorCode TSResetTrajectory(TS ts)
514: {
515:   PetscFunctionBegin;
517:   if (ts->trajectory) {
518:     PetscCall(TSTrajectoryDestroy(&ts->trajectory));
519:     PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
520:   }
521:   PetscFunctionReturn(PETSC_SUCCESS);
522: }

524: /*@
525:   TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from a `TS`

527:   Collective

529:   Input Parameter:
530: . ts - the `TS` context obtained from `TSCreate()`

532:   Level: intermediate

534: .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()`
535: @*/
536: PetscErrorCode TSRemoveTrajectory(TS ts)
537: {
538:   PetscFunctionBegin;
540:   PetscCall(TSTrajectoryDestroy(&ts->trajectory));
541:   PetscFunctionReturn(PETSC_SUCCESS);
542: }

544: /*@
545:   TSComputeRHSJacobian - Computes the Jacobian matrix that has been
546:   set with `TSSetRHSJacobian()`.

548:   Collective

550:   Input Parameters:
551: + ts - the `TS` context
552: . t  - current timestep
553: - U  - input vector

555:   Output Parameters:
556: + A - Jacobian matrix
557: - B - optional matrix used to compute the preconditioner, often the same as `A`

559:   Level: developer

561:   Note:
562:   Most users should not need to explicitly call this routine, as it
563:   is used internally within the ODE integrators.

565: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `KSPSetOperators()`
566: @*/
567: PetscErrorCode TSComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B)
568: {
569:   PetscObjectState Ustate;
570:   PetscObjectId    Uid;
571:   DM               dm;
572:   DMTS             tsdm;
573:   TSRHSJacobianFn *rhsjacobianfunc;
574:   void            *ctx;
575:   TSRHSFunctionFn *rhsfunction;

577:   PetscFunctionBegin;
580:   PetscCheckSameComm(ts, 1, U, 3);
581:   PetscCall(TSGetDM(ts, &dm));
582:   PetscCall(DMGetDMTS(dm, &tsdm));
583:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
584:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobianfunc, &ctx));
585:   PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
586:   PetscCall(PetscObjectGetId((PetscObject)U, &Uid));

588:   if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(PETSC_SUCCESS);

590:   PetscCheck(ts->rhsjacobian.shift == 0.0 || !ts->rhsjacobian.reuse, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Should not call TSComputeRHSJacobian() on a shifted matrix (shift=%lf) when RHSJacobian is reusable.", (double)ts->rhsjacobian.shift);
591:   if (rhsjacobianfunc) {
592:     PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
593:     PetscCallBack("TS callback Jacobian", (*rhsjacobianfunc)(ts, t, U, A, B, ctx));
594:     ts->rhsjacs++;
595:     PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
596:   } else {
597:     PetscCall(MatZeroEntries(A));
598:     if (B && A != B) PetscCall(MatZeroEntries(B));
599:   }
600:   ts->rhsjacobian.time  = t;
601:   ts->rhsjacobian.shift = 0;
602:   ts->rhsjacobian.scale = 1.;
603:   PetscCall(PetscObjectGetId((PetscObject)U, &ts->rhsjacobian.Xid));
604:   PetscCall(PetscObjectStateGet((PetscObject)U, &ts->rhsjacobian.Xstate));
605:   PetscFunctionReturn(PETSC_SUCCESS);
606: }

608: /*@
609:   TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS`

611:   Collective

613:   Input Parameters:
614: + ts - the `TS` context
615: . t  - current time
616: - U  - state vector

618:   Output Parameter:
619: . y - right-hand side

621:   Level: developer

623:   Note:
624:   Most users should not need to explicitly call this routine, as it
625:   is used internally within the nonlinear solvers.

627: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
628: @*/
629: PetscErrorCode TSComputeRHSFunction(TS ts, PetscReal t, Vec U, Vec y)
630: {
631:   TSRHSFunctionFn *rhsfunction;
632:   TSIFunctionFn   *ifunction;
633:   void            *ctx;
634:   DM               dm;

636:   PetscFunctionBegin;
640:   PetscCall(TSGetDM(ts, &dm));
641:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx));
642:   PetscCall(DMTSGetIFunction(dm, &ifunction, NULL));

644:   PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");

646:   if (rhsfunction) {
647:     PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, y, 0));
648:     PetscCall(VecLockReadPush(U));
649:     PetscCallBack("TS callback right-hand-side", (*rhsfunction)(ts, t, U, y, ctx));
650:     PetscCall(VecLockReadPop(U));
651:     ts->rhsfuncs++;
652:     PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, y, 0));
653:   } else PetscCall(VecZeroEntries(y));
654:   PetscFunctionReturn(PETSC_SUCCESS);
655: }

657: /*@
658:   TSComputeSolutionFunction - Evaluates the solution function.

660:   Collective

662:   Input Parameters:
663: + ts - the `TS` context
664: - t  - current time

666:   Output Parameter:
667: . U - the solution

669:   Level: developer

671: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
672: @*/
673: PetscErrorCode TSComputeSolutionFunction(TS ts, PetscReal t, Vec U)
674: {
675:   TSSolutionFn *solutionfunction;
676:   void         *ctx;
677:   DM            dm;

679:   PetscFunctionBegin;
682:   PetscCall(TSGetDM(ts, &dm));
683:   PetscCall(DMTSGetSolutionFunction(dm, &solutionfunction, &ctx));
684:   if (solutionfunction) PetscCallBack("TS callback solution", (*solutionfunction)(ts, t, U, ctx));
685:   PetscFunctionReturn(PETSC_SUCCESS);
686: }
687: /*@
688:   TSComputeForcingFunction - Evaluates the forcing function.

690:   Collective

692:   Input Parameters:
693: + ts - the `TS` context
694: - t  - current time

696:   Output Parameter:
697: . U - the function value

699:   Level: developer

701: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
702: @*/
703: PetscErrorCode TSComputeForcingFunction(TS ts, PetscReal t, Vec U)
704: {
705:   void        *ctx;
706:   DM           dm;
707:   TSForcingFn *forcing;

709:   PetscFunctionBegin;
712:   PetscCall(TSGetDM(ts, &dm));
713:   PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx));

715:   if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx));
716:   PetscFunctionReturn(PETSC_SUCCESS);
717: }

719: PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs)
720: {
721:   Mat            A, B;
722:   TSIJacobianFn *ijacobian;

724:   PetscFunctionBegin;
725:   if (Arhs) *Arhs = NULL;
726:   if (Brhs) *Brhs = NULL;
727:   PetscCall(TSGetIJacobian(ts, &A, &B, &ijacobian, NULL));
728:   if (Arhs) {
729:     if (!ts->Arhs) {
730:       if (ijacobian) {
731:         PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &ts->Arhs));
732:         PetscCall(TSSetMatStructure(ts, SAME_NONZERO_PATTERN));
733:       } else {
734:         ts->Arhs = A;
735:         PetscCall(PetscObjectReference((PetscObject)A));
736:       }
737:     } else {
738:       PetscBool flg;
739:       PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
740:       /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */
741:       if (flg && !ijacobian && ts->Arhs == ts->Brhs) {
742:         PetscCall(PetscObjectDereference((PetscObject)ts->Arhs));
743:         ts->Arhs = A;
744:         PetscCall(PetscObjectReference((PetscObject)A));
745:       }
746:     }
747:     *Arhs = ts->Arhs;
748:   }
749:   if (Brhs) {
750:     if (!ts->Brhs) {
751:       if (A != B) {
752:         if (ijacobian) {
753:           PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &ts->Brhs));
754:         } else {
755:           ts->Brhs = B;
756:           PetscCall(PetscObjectReference((PetscObject)B));
757:         }
758:       } else {
759:         PetscCall(PetscObjectReference((PetscObject)ts->Arhs));
760:         ts->Brhs = ts->Arhs;
761:       }
762:     }
763:     *Brhs = ts->Brhs;
764:   }
765:   PetscFunctionReturn(PETSC_SUCCESS);
766: }

768: /*@
769:   TSComputeIFunction - Evaluates the DAE residual written in the implicit form F(t,U,Udot)=0

771:   Collective

773:   Input Parameters:
774: + ts   - the `TS` context
775: . t    - current time
776: . U    - state vector
777: . Udot - time derivative of state vector
778: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSFunction should be kept separate

780:   Output Parameter:
781: . Y - right-hand side

783:   Level: developer

785:   Note:
786:   Most users should not need to explicitly call this routine, as it
787:   is used internally within the nonlinear solvers.

789:   If the user did not write their equations in implicit form, this
790:   function recasts them in implicit form.

792: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSComputeRHSFunction()`
793: @*/
794: PetscErrorCode TSComputeIFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec Y, PetscBool imex)
795: {
796:   TSIFunctionFn   *ifunction;
797:   TSRHSFunctionFn *rhsfunction;
798:   void            *ctx;
799:   DM               dm;

801:   PetscFunctionBegin;

807:   PetscCall(TSGetDM(ts, &dm));
808:   PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx));
809:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));

811:   PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()");

813:   PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, Udot, Y));
814:   if (ifunction) {
815:     PetscCallBack("TS callback implicit function", (*ifunction)(ts, t, U, Udot, Y, ctx));
816:     ts->ifuncs++;
817:   }
818:   if (imex) {
819:     if (!ifunction) PetscCall(VecCopy(Udot, Y));
820:   } else if (rhsfunction) {
821:     if (ifunction) {
822:       Vec Frhs;

824:       PetscCall(DMGetGlobalVector(dm, &Frhs));
825:       PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
826:       PetscCall(VecAXPY(Y, -1, Frhs));
827:       PetscCall(DMRestoreGlobalVector(dm, &Frhs));
828:     } else {
829:       PetscCall(TSComputeRHSFunction(ts, t, U, Y));
830:       PetscCall(VecAYPX(Y, -1, Udot));
831:     }
832:   }
833:   PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, Udot, Y));
834:   PetscFunctionReturn(PETSC_SUCCESS);
835: }

837: /*
838:    TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call `TSComputeRHSJacobian()` on it.

840:    Note:
841:    This routine is needed when one switches from `TSComputeIJacobian()` to `TSComputeRHSJacobian()` because the Jacobian matrix may be shifted or scaled in `TSComputeIJacobian()`.

843: */
844: static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B)
845: {
846:   PetscFunctionBegin;
848:   PetscCheck(A == ts->Arhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Amat");
849:   PetscCheck(B == ts->Brhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Bmat");

851:   if (ts->rhsjacobian.shift) PetscCall(MatShift(A, -ts->rhsjacobian.shift));
852:   if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(A, -1));
853:   if (B && B == ts->Brhs && A != B) {
854:     if (ts->rhsjacobian.shift) PetscCall(MatShift(B, -ts->rhsjacobian.shift));
855:     if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(B, -1));
856:   }
857:   ts->rhsjacobian.shift = 0;
858:   ts->rhsjacobian.scale = 1.;
859:   PetscFunctionReturn(PETSC_SUCCESS);
860: }

862: /*
863:   TSComputeIJacobian_Internal - Evaluates the Jacobian of the DAE

865:   Collective

867:   Input Parameters:
868: + ts          - the `TS` context
869: . ijacobian   - function to compute LHS Jacobian
870: . rhsjacobian - function to compute RHS Jacobian
871: . ctx         - user context for Jacobian functions
872: . t           - current timestep
873: . U           - state vector
874: . Udot        - time derivative of state vector
875: . shift       - shift to apply, see note below
876: - imex        - flag indicates if the method is `TSARKIMEX` so that the RHSJacobian should be kept separate

878:   Output Parameters:
879: + A - Jacobian matrix
880: - B - matrix from which the preconditioner is constructed; often the same as `A`

882:   Level: developer

884:   Notes:
885:   This function exists so that a user can assemble the Jacobian pieces with functions not stores in the `DMTS`. This was necessary in `TSDISCGRAD` since two different representations of the formulation can be stored.

887:   If $ F(t,U,\dot{U})=0 $ is the DAE, the required Jacobian is
888: .vb
889:    dF/dU + shift*dF/dUdot
890: .ve

892: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`
893: */
894: PetscErrorCode TSComputeIJacobian_Internal(TS ts, TSIJacobianFn *ijacobian, TSRHSJacobianFn *rhsjacobian, void *ctx, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex)
895: {
896:   PetscFunctionBegin;
897:   PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()");

899:   PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
900:   if (ijacobian) {
901:     PetscCallBack("TS callback implicit Jacobian", (*ijacobian)(ts, t, U, Udot, shift, A, B, ctx));
902:     ts->ijacs++;
903:   }
904:   if (imex) {
905:     if (!ijacobian) { /* system was written as Udot = G(t,U) */
906:       PetscBool assembled;
907:       if (rhsjacobian) {
908:         Mat Arhs = NULL;
909:         PetscCall(TSGetRHSMats_Private(ts, &Arhs, NULL));
910:         if (A == Arhs) {
911:           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 */
912:           ts->rhsjacobian.time = PETSC_MIN_REAL;
913:         }
914:       }
915:       PetscCall(MatZeroEntries(A));
916:       PetscCall(MatAssembled(A, &assembled));
917:       if (!assembled) {
918:         PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
919:         PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
920:       }
921:       PetscCall(MatShift(A, shift));
922:       if (A != B) {
923:         PetscCall(MatZeroEntries(B));
924:         PetscCall(MatAssembled(B, &assembled));
925:         if (!assembled) {
926:           PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
927:           PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
928:         }
929:         PetscCall(MatShift(B, shift));
930:       }
931:     }
932:   } else {
933:     Mat Arhs = NULL, Brhs = NULL;

935:     /* RHSJacobian needs to be converted to part of IJacobian if exists */
936:     if (rhsjacobian) PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
937:     if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */
938:       DM               dm;
939:       PetscObjectState Ustate;
940:       PetscObjectId    Uid;
941:       TSRHSFunctionFn *rhsfunction;

943:       PetscCall(TSGetDM(ts, &dm));
944:       PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
945:       PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
946:       PetscCall(PetscObjectGetId((PetscObject)U, &Uid));
947:       if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) &&
948:           ts->rhsjacobian.scale == -1.) {                      /* No need to recompute RHSJacobian */
949:         PetscCall(MatShift(A, shift - ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */
950:         if (A != B) PetscCall(MatShift(B, shift - ts->rhsjacobian.shift));
951:       } else {
952:         PetscBool flg;

954:         if (ts->rhsjacobian.reuse) { /* Undo the damage */
955:           /* MatScale has a short path for this case.
956:              However, this code path is taken the first time TSComputeRHSJacobian is called
957:              and the matrices have not been assembled yet */
958:           PetscCall(TSRecoverRHSJacobian(ts, A, B));
959:         }
960:         PetscCall(TSComputeRHSJacobian(ts, t, U, A, B));
961:         PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg));
962:         /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */
963:         if (!flg) {
964:           PetscCall(MatScale(A, -1));
965:           PetscCall(MatShift(A, shift));
966:         }
967:         if (A != B) {
968:           PetscCall(MatScale(B, -1));
969:           PetscCall(MatShift(B, shift));
970:         }
971:       }
972:       ts->rhsjacobian.scale = -1;
973:       ts->rhsjacobian.shift = shift;
974:     } else if (Arhs) {  /* Both IJacobian and RHSJacobian */
975:       if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */
976:         PetscCall(MatZeroEntries(A));
977:         PetscCall(MatShift(A, shift));
978:         if (A != B) {
979:           PetscCall(MatZeroEntries(B));
980:           PetscCall(MatShift(B, shift));
981:         }
982:       }
983:       PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
984:       PetscCall(MatAXPY(A, -1, Arhs, ts->axpy_pattern));
985:       if (A != B) PetscCall(MatAXPY(B, -1, Brhs, ts->axpy_pattern));
986:     }
987:   }
988:   PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
989:   PetscFunctionReturn(PETSC_SUCCESS);
990: }

992: /*@
993:   TSComputeIJacobian - Evaluates the Jacobian of the DAE

995:   Collective

997:   Input Parameters:
998: + ts    - the `TS` context
999: . t     - current timestep
1000: . U     - state vector
1001: . Udot  - time derivative of state vector
1002: . shift - shift to apply, see note below
1003: - imex  - flag indicates if the method is `TSARKIMEX` so that the RHSJacobian should be kept separate

1005:   Output Parameters:
1006: + A - Jacobian matrix
1007: - B - matrix from which the preconditioner is constructed; often the same as `A`

1009:   Level: developer

1011:   Notes:
1012:   If $ F(t,U,\dot{U})=0 $ is the DAE, the required Jacobian is
1013: .vb
1014:    dF/dU + shift*dF/dUdot
1015: .ve
1016:   Most users should not need to explicitly call this routine, as it
1017:   is used internally within the nonlinear solvers.

1019: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`
1020: @*/
1021: PetscErrorCode TSComputeIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex)
1022: {
1023:   TSIJacobianFn   *ijacobian;
1024:   TSRHSJacobianFn *rhsjacobian;
1025:   DM               dm;
1026:   void            *ctx;

1028:   PetscFunctionBegin;

1035:   PetscCall(TSGetDM(ts, &dm));
1036:   PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx));
1037:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));
1038:   PetscCall(TSComputeIJacobian_Internal(ts, ijacobian, rhsjacobian, ctx, t, U, Udot, shift, A, B, imex));
1039:   PetscFunctionReturn(PETSC_SUCCESS);
1040: }

1042: /*@C
1043:   TSSetRHSFunction - Sets the routine for evaluating the function,
1044:   where U_t = G(t,u).

1046:   Logically Collective

1048:   Input Parameters:
1049: + ts  - the `TS` context obtained from `TSCreate()`
1050: . r   - vector to put the computed right-hand side (or `NULL` to have it created)
1051: . f   - routine for evaluating the right-hand-side function
1052: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)

1054:   Level: beginner

1056:   Note:
1057:   You must call this function or `TSSetIFunction()` to define your ODE. You cannot use this function when solving a DAE.

1059: .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1060: @*/
1061: PetscErrorCode TSSetRHSFunction(TS ts, Vec r, TSRHSFunctionFn *f, PetscCtx ctx)
1062: {
1063:   SNES snes;
1064:   Vec  ralloc = NULL;
1065:   DM   dm;

1067:   PetscFunctionBegin;

1071:   PetscCall(TSGetDM(ts, &dm));
1072:   PetscCall(DMTSSetRHSFunction(dm, f, ctx));
1073:   PetscCall(TSGetSNES(ts, &snes));
1074:   if (!r && !ts->dm && ts->vec_sol) {
1075:     PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1076:     r = ralloc;
1077:   }
1078:   PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1079:   PetscCall(VecDestroy(&ralloc));
1080:   PetscFunctionReturn(PETSC_SUCCESS);
1081: }

1083: /*@C
1084:   TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE

1086:   Logically Collective

1088:   Input Parameters:
1089: + ts  - the `TS` context obtained from `TSCreate()`
1090: . f   - routine for evaluating the solution
1091: - ctx - [optional] user-defined context for private data for the
1092:           function evaluation routine (may be `NULL`)

1094:   Options Database Keys:
1095: + -ts_monitor_lg_error   - create a graphical monitor of error history, requires user to have provided `TSSetSolutionFunction()`
1096: - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`

1098:   Level: intermediate

1100:   Notes:
1101:   This routine is used for testing accuracy of time integration schemes when you already know the solution.
1102:   If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
1103:   create closed-form solutions with non-physical forcing terms.

1105:   For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.

1107: .seealso: [](ch_ts), `TS`, `TSSolutionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()`
1108: @*/
1109: PetscErrorCode TSSetSolutionFunction(TS ts, TSSolutionFn *f, PetscCtx ctx)
1110: {
1111:   DM dm;

1113:   PetscFunctionBegin;
1115:   PetscCall(TSGetDM(ts, &dm));
1116:   PetscCall(DMTSSetSolutionFunction(dm, f, ctx));
1117:   PetscFunctionReturn(PETSC_SUCCESS);
1118: }

1120: /*@C
1121:   TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE

1123:   Logically Collective

1125:   Input Parameters:
1126: + ts   - the `TS` context obtained from `TSCreate()`
1127: . func - routine for evaluating the forcing function
1128: - ctx  - [optional] user-defined context for private data for the function evaluation routine
1129:          (may be `NULL`)

1131:   Level: intermediate

1133:   Notes:
1134:   This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
1135:   create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the
1136:   definition of the problem you are solving and hence possibly introducing bugs.

1138:   This replaces the ODE F(u,u_t,t) = 0 the `TS` is solving with F(u,u_t,t) - func(t) = 0

1140:   This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the
1141:   parameters can be passed in the ctx variable.

1143:   For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history.

1145: .seealso: [](ch_ts), `TS`, `TSForcingFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`,
1146: `TSComputeSolutionFunction()`, `TSSetSolutionFunction()`
1147: @*/
1148: PetscErrorCode TSSetForcingFunction(TS ts, TSForcingFn *func, PetscCtx ctx)
1149: {
1150:   DM dm;

1152:   PetscFunctionBegin;
1154:   PetscCall(TSGetDM(ts, &dm));
1155:   PetscCall(DMTSSetForcingFunction(dm, func, ctx));
1156:   PetscFunctionReturn(PETSC_SUCCESS);
1157: }

1159: /*@C
1160:   TSSetRHSJacobian - Sets the function to compute the Jacobian of G,
1161:   where U_t = G(U,t), as well as the location to store the matrix.

1163:   Logically Collective

1165:   Input Parameters:
1166: + ts   - the `TS` context obtained from `TSCreate()`
1167: . Amat - (approximate) location to store Jacobian matrix entries computed by `f`
1168: . Pmat - matrix from which preconditioner is to be constructed (usually the same as `Amat`)
1169: . f    - the Jacobian evaluation routine
1170: - ctx  - [optional] user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)

1172:   Level: beginner

1174:   Notes:
1175:   You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value

1177:   The `TS` solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f()`
1178:   You should not assume the values are the same in the next call to f() as you set them in the previous call.

1180: .seealso: [](ch_ts), `TS`, `TSRHSJacobianFn`, `SNESComputeJacobianDefaultColor()`,
1181: `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()`, `TSRHSFunctionFn`, `TSIFunctionFn`
1182: @*/
1183: PetscErrorCode TSSetRHSJacobian(TS ts, Mat Amat, Mat Pmat, TSRHSJacobianFn *f, PetscCtx ctx)
1184: {
1185:   SNES           snes;
1186:   DM             dm;
1187:   TSIJacobianFn *ijacobian;

1189:   PetscFunctionBegin;
1193:   if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1194:   if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);

1196:   PetscCall(TSGetDM(ts, &dm));
1197:   PetscCall(DMTSSetRHSJacobian(dm, f, ctx));
1198:   PetscCall(DMTSGetIJacobian(dm, &ijacobian, NULL));
1199:   PetscCall(TSGetSNES(ts, &snes));
1200:   if (!ijacobian) PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1201:   if (Amat) {
1202:     PetscCall(PetscObjectReference((PetscObject)Amat));
1203:     PetscCall(MatDestroy(&ts->Arhs));
1204:     ts->Arhs = Amat;
1205:   }
1206:   if (Pmat) {
1207:     PetscCall(PetscObjectReference((PetscObject)Pmat));
1208:     PetscCall(MatDestroy(&ts->Brhs));
1209:     ts->Brhs = Pmat;
1210:   }
1211:   PetscFunctionReturn(PETSC_SUCCESS);
1212: }

1214: /*@C
1215:   TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.

1217:   Logically Collective

1219:   Input Parameters:
1220: + ts  - the `TS` context obtained from `TSCreate()`
1221: . r   - vector to hold the residual (or `NULL` to have it created internally)
1222: . f   - the function evaluation routine
1223: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)

1225:   Level: beginner

1227:   Note:
1228:   The user MUST call either this routine or `TSSetRHSFunction()` to define the ODE.  When solving DAEs you must use this function.

1230: .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `TSSetRHSJacobian()`, `TSSetRHSFunction()`,
1231: `TSSetIJacobian()`
1232: @*/
1233: PetscErrorCode TSSetIFunction(TS ts, Vec r, TSIFunctionFn *f, PetscCtx ctx)
1234: {
1235:   SNES snes;
1236:   Vec  ralloc = NULL;
1237:   DM   dm;

1239:   PetscFunctionBegin;

1243:   PetscCall(TSGetDM(ts, &dm));
1244:   PetscCall(DMTSSetIFunction(dm, f, ctx));

1246:   PetscCall(TSGetSNES(ts, &snes));
1247:   if (!r && !ts->dm && ts->vec_sol) {
1248:     PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
1249:     r = ralloc;
1250:   }
1251:   PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
1252:   PetscCall(VecDestroy(&ralloc));
1253:   PetscFunctionReturn(PETSC_SUCCESS);
1254: }

1256: /*@C
1257:   TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it.

1259:   Not Collective

1261:   Input Parameter:
1262: . ts - the `TS` context

1264:   Output Parameters:
1265: + r    - vector to hold residual (or `NULL`)
1266: . func - the function to compute residual (or `NULL`)
1267: - ctx  - the function context (or `NULL`)

1269:   Level: advanced

1271: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`
1272: @*/
1273: PetscErrorCode TSGetIFunction(TS ts, Vec *r, TSIFunctionFn **func, PetscCtxRt ctx)
1274: {
1275:   SNES snes;
1276:   DM   dm;

1278:   PetscFunctionBegin;
1280:   PetscCall(TSGetSNES(ts, &snes));
1281:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1282:   PetscCall(TSGetDM(ts, &dm));
1283:   PetscCall(DMTSGetIFunction(dm, func, ctx));
1284:   PetscFunctionReturn(PETSC_SUCCESS);
1285: }

1287: /*@C
1288:   TSGetRHSFunction - Returns the vector where the right-hand side is stored and the function/context to compute it.

1290:   Not Collective

1292:   Input Parameter:
1293: . ts - the `TS` context

1295:   Output Parameters:
1296: + r    - vector to hold computed right-hand side (or `NULL`)
1297: . func - the function to compute right-hand side (or `NULL`)
1298: - ctx  - the function context (or `NULL`)

1300:   Level: advanced

1302: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `SNESGetFunction()`
1303: @*/
1304: PetscErrorCode TSGetRHSFunction(TS ts, Vec *r, TSRHSFunctionFn **func, PetscCtxRt ctx)
1305: {
1306:   SNES snes;
1307:   DM   dm;

1309:   PetscFunctionBegin;
1311:   PetscCall(TSGetSNES(ts, &snes));
1312:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1313:   PetscCall(TSGetDM(ts, &dm));
1314:   PetscCall(DMTSGetRHSFunction(dm, func, ctx));
1315:   PetscFunctionReturn(PETSC_SUCCESS);
1316: }

1318: /*@C
1319:   TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1320:   provided with `TSSetIFunction()`.

1322:   Logically Collective

1324:   Input Parameters:
1325: + ts   - the `TS` context obtained from `TSCreate()`
1326: . Amat - (approximate) matrix to store Jacobian entries computed by `f`
1327: . Pmat - matrix used to compute preconditioner (usually the same as `Amat`)
1328: . f    - the Jacobian evaluation routine
1329: - ctx  - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)

1331:   Level: beginner

1333:   Notes:
1334:   The matrices `Amat` and `Pmat` are exactly the matrices that are used by `SNES` for the nonlinear solve.

1336:   If you know the operator Amat has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
1337:   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.

1339:   The matrix dF/dU + a*dF/dU_t you provide turns out to be
1340:   the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1341:   The time integrator internally approximates U_t by W+a*U where the positive "shift"
1342:   a and vector W depend on the integration method, step size, and past states. For example with
1343:   the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1344:   W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt

1346:   You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value

1348:   The TS solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f`
1349:   You should not assume the values are the same in the next call to `f` as you set them in the previous call.

1351:   In case `TSSetRHSJacobian()` is also used in conjunction with a fully-implicit solver,
1352:   multilevel linear solvers, e.g. `PCMG`, will likely not work due to the way `TS` handles rhs matrices.

1354: .seealso: [](ch_ts), `TS`, `TSIJacobianFn`, `TSSetIFunction()`, `TSSetRHSJacobian()`,
1355: `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()`
1356: @*/
1357: PetscErrorCode TSSetIJacobian(TS ts, Mat Amat, Mat Pmat, TSIJacobianFn *f, PetscCtx ctx)
1358: {
1359:   SNES snes;
1360:   DM   dm;

1362:   PetscFunctionBegin;
1366:   if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
1367:   if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);

1369:   PetscCall(TSGetDM(ts, &dm));
1370:   PetscCall(DMTSSetIJacobian(dm, f, ctx));

1372:   PetscCall(TSGetSNES(ts, &snes));
1373:   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
1374:   PetscFunctionReturn(PETSC_SUCCESS);
1375: }

1377: /*@
1378:   TSRHSJacobianSetReuse - restore the RHS Jacobian before calling the user-provided `TSRHSJacobianFn` function again

1380:   Logically Collective

1382:   Input Parameters:
1383: + ts    - `TS` context obtained from `TSCreate()`
1384: - reuse - `PETSC_TRUE` if the RHS Jacobian

1386:   Level: intermediate

1388:   Notes:
1389:   Without this flag, `TS` will change the sign and shift the RHS Jacobian for a
1390:   finite-time-step implicit solve, in which case the user function will need to recompute the
1391:   entire Jacobian.  The `reuse `flag must be set if the evaluation function assumes that the
1392:   matrix entries have not been changed by the `TS`.

1394: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
1395: @*/
1396: PetscErrorCode TSRHSJacobianSetReuse(TS ts, PetscBool reuse)
1397: {
1398:   PetscFunctionBegin;
1399:   ts->rhsjacobian.reuse = reuse;
1400:   PetscFunctionReturn(PETSC_SUCCESS);
1401: }

1403: /*@C
1404:   TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved.

1406:   Logically Collective

1408:   Input Parameters:
1409: + ts  - the `TS` context obtained from `TSCreate()`
1410: . F   - vector to hold the residual (or `NULL` to have it created internally)
1411: . fun - the function evaluation routine
1412: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)

1414:   Level: beginner

1416: .seealso: [](ch_ts), `TS`, `TSI2FunctionFn`, `TSSetI2Jacobian()`, `TSSetIFunction()`,
1417: `TSCreate()`, `TSSetRHSFunction()`
1418: @*/
1419: PetscErrorCode TSSetI2Function(TS ts, Vec F, TSI2FunctionFn *fun, PetscCtx ctx)
1420: {
1421:   DM dm;

1423:   PetscFunctionBegin;
1426:   PetscCall(TSSetIFunction(ts, F, NULL, NULL));
1427:   PetscCall(TSGetDM(ts, &dm));
1428:   PetscCall(DMTSSetI2Function(dm, fun, ctx));
1429:   PetscFunctionReturn(PETSC_SUCCESS);
1430: }

1432: /*@C
1433:   TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it.

1435:   Not Collective

1437:   Input Parameter:
1438: . ts - the `TS` context

1440:   Output Parameters:
1441: + r   - vector to hold residual (or `NULL`)
1442: . fun - the function to compute residual (or `NULL`)
1443: - ctx - the function context (or `NULL`)

1445:   Level: advanced

1447: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()`
1448: @*/
1449: PetscErrorCode TSGetI2Function(TS ts, Vec *r, TSI2FunctionFn **fun, PetscCtxRt ctx)
1450: {
1451:   SNES snes;
1452:   DM   dm;

1454:   PetscFunctionBegin;
1456:   PetscCall(TSGetSNES(ts, &snes));
1457:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
1458:   PetscCall(TSGetDM(ts, &dm));
1459:   PetscCall(DMTSGetI2Function(dm, fun, ctx));
1460:   PetscFunctionReturn(PETSC_SUCCESS);
1461: }

1463: /*@C
1464:   TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t  + a*dF/dU_tt
1465:   where F(t,U,U_t,U_tt) is the function you provided with `TSSetI2Function()`.

1467:   Logically Collective

1469:   Input Parameters:
1470: + ts  - the `TS` context obtained from `TSCreate()`
1471: . J   - matrix to hold the Jacobian values
1472: . P   - matrix for constructing the preconditioner (may be same as `J`)
1473: . jac - the Jacobian evaluation routine, see `TSI2JacobianFn` for the calling sequence
1474: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)

1476:   Level: beginner

1478:   Notes:
1479:   The matrices `J` and `P` are exactly the matrices that are used by `SNES` for the nonlinear solve.

1481:   The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be
1482:   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.
1483:   The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U  where the positive "shift"
1484:   parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states.

1486: .seealso: [](ch_ts), `TS`, `TSI2JacobianFn`, `TSSetI2Function()`, `TSGetI2Jacobian()`
1487: @*/
1488: PetscErrorCode TSSetI2Jacobian(TS ts, Mat J, Mat P, TSI2JacobianFn *jac, PetscCtx ctx)
1489: {
1490:   DM dm;

1492:   PetscFunctionBegin;
1496:   PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL));
1497:   PetscCall(TSGetDM(ts, &dm));
1498:   PetscCall(DMTSSetI2Jacobian(dm, jac, ctx));
1499:   PetscFunctionReturn(PETSC_SUCCESS);
1500: }

1502: /*@C
1503:   TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.

1505:   Not Collective, but parallel objects are returned if `TS` is parallel

1507:   Input Parameter:
1508: . ts - The `TS` context obtained from `TSCreate()`

1510:   Output Parameters:
1511: + J   - The (approximate) Jacobian of F(t,U,U_t,U_tt)
1512: . P   - The matrix from which the preconditioner is constructed, often the same as `J`
1513: . jac - The function to compute the Jacobian matrices
1514: - ctx - User-defined context for Jacobian evaluation routine

1516:   Level: advanced

1518:   Note:
1519:   You can pass in `NULL` for any return argument you do not need.

1521: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()`
1522: @*/
1523: PetscErrorCode TSGetI2Jacobian(TS ts, Mat *J, Mat *P, TSI2JacobianFn **jac, PetscCtxRt ctx)
1524: {
1525:   SNES snes;
1526:   DM   dm;

1528:   PetscFunctionBegin;
1529:   PetscCall(TSGetSNES(ts, &snes));
1530:   PetscCall(SNESSetUpMatrices(snes));
1531:   PetscCall(SNESGetJacobian(snes, J, P, NULL, NULL));
1532:   PetscCall(TSGetDM(ts, &dm));
1533:   PetscCall(DMTSGetI2Jacobian(dm, jac, ctx));
1534:   PetscFunctionReturn(PETSC_SUCCESS);
1535: }

1537: /*@
1538:   TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0

1540:   Collective

1542:   Input Parameters:
1543: + ts - the `TS` context
1544: . t  - current time
1545: . U  - state vector
1546: . V  - time derivative of state vector (U_t)
1547: - A  - second time derivative of state vector (U_tt)

1549:   Output Parameter:
1550: . F - the residual vector

1552:   Level: developer

1554:   Note:
1555:   Most users should not need to explicitly call this routine, as it
1556:   is used internally within the nonlinear solvers.

1558: .seealso: [](ch_ts), `TS`, `TSSetI2Function()`, `TSGetI2Function()`
1559: @*/
1560: PetscErrorCode TSComputeI2Function(TS ts, PetscReal t, Vec U, Vec V, Vec A, Vec F)
1561: {
1562:   DM               dm;
1563:   TSI2FunctionFn  *I2Function;
1564:   void            *ctx;
1565:   TSRHSFunctionFn *rhsfunction;

1567:   PetscFunctionBegin;

1574:   PetscCall(TSGetDM(ts, &dm));
1575:   PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx));
1576:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));

1578:   if (!I2Function) {
1579:     PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE));
1580:     PetscFunctionReturn(PETSC_SUCCESS);
1581:   }

1583:   PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, V, F));

1585:   PetscCallBack("TS callback implicit function", I2Function(ts, t, U, V, A, F, ctx));

1587:   if (rhsfunction) {
1588:     Vec Frhs;

1590:     PetscCall(DMGetGlobalVector(dm, &Frhs));
1591:     PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
1592:     PetscCall(VecAXPY(F, -1, Frhs));
1593:     PetscCall(DMRestoreGlobalVector(dm, &Frhs));
1594:   }

1596:   PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F));
1597:   PetscFunctionReturn(PETSC_SUCCESS);
1598: }

1600: /*@
1601:   TSComputeI2Jacobian - Evaluates the Jacobian of the DAE

1603:   Collective

1605:   Input Parameters:
1606: + ts     - the `TS` context
1607: . t      - current timestep
1608: . U      - state vector
1609: . V      - time derivative of state vector
1610: . A      - second time derivative of state vector
1611: . shiftV - shift to apply, see note below
1612: - shiftA - shift to apply, see note below

1614:   Output Parameters:
1615: + J - Jacobian matrix
1616: - P - optional matrix used to construct the preconditioner

1618:   Level: developer

1620:   Notes:
1621:   If $F(t,U,V,A) = 0$ is the DAE, the required Jacobian is

1623: $$
1624:   dF/dU + shiftV*dF/dV + shiftA*dF/dA
1625: $$

1627:   Most users should not need to explicitly call this routine, as it
1628:   is used internally within the ODE integrators.

1630: .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()`
1631: @*/
1632: PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P)
1633: {
1634:   DM               dm;
1635:   TSI2JacobianFn  *I2Jacobian;
1636:   void            *ctx;
1637:   TSRHSJacobianFn *rhsjacobian;

1639:   PetscFunctionBegin;

1647:   PetscCall(TSGetDM(ts, &dm));
1648:   PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx));
1649:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));

1651:   if (!I2Jacobian) {
1652:     PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE));
1653:     PetscFunctionReturn(PETSC_SUCCESS);
1654:   }

1656:   PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P));
1657:   PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx));
1658:   if (rhsjacobian) {
1659:     Mat Jrhs, Prhs;
1660:     PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs));
1661:     PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs));
1662:     PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern));
1663:     if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern));
1664:   }

1666:   PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P));
1667:   PetscFunctionReturn(PETSC_SUCCESS);
1668: }

1670: /*@C
1671:   TSSetTransientVariable - sets function to transform from state to transient variables

1673:   Logically Collective

1675:   Input Parameters:
1676: + ts   - time stepping context on which to change the transient variable
1677: . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
1678: - ctx  - a context for tvar

1680:   Level: advanced

1682:   Notes:
1683:   This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
1684:   can be conservative.  In this context, primitive variables P are used to model the state (e.g., because they lead to
1685:   well-conditioned formulations even in limiting cases such as low-Mach or zero porosity).  The transient variable is
1686:   C(P), specified by calling this function.  An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
1687:   evaluated via the chain rule, as in
1688: .vb
1689:      dF/dP + shift * dF/dCdot dC/dP.
1690: .ve

1692: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()`
1693: @*/
1694: PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, PetscCtx ctx)
1695: {
1696:   DM dm;

1698:   PetscFunctionBegin;
1700:   PetscCall(TSGetDM(ts, &dm));
1701:   PetscCall(DMTSSetTransientVariable(dm, tvar, ctx));
1702:   PetscFunctionReturn(PETSC_SUCCESS);
1703: }

1705: /*@
1706:   TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables

1708:   Logically Collective

1710:   Input Parameters:
1711: + ts - TS on which to compute
1712: - U  - state vector to be transformed to transient variables

1714:   Output Parameter:
1715: . C - transient (conservative) variable

1717:   Level: developer

1719:   Developer Notes:
1720:   If `DMTSSetTransientVariable()` has not been called, then C is not modified in this routine and C = `NULL` is allowed.
1721:   This makes it safe to call without a guard.  One can use `TSHasTransientVariable()` to check if transient variables are
1722:   being used.

1724: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()`
1725: @*/
1726: PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C)
1727: {
1728:   DM   dm;
1729:   DMTS dmts;

1731:   PetscFunctionBegin;
1734:   PetscCall(TSGetDM(ts, &dm));
1735:   PetscCall(DMGetDMTS(dm, &dmts));
1736:   if (dmts->ops->transientvar) {
1738:     PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx));
1739:   }
1740:   PetscFunctionReturn(PETSC_SUCCESS);
1741: }

1743: /*@
1744:   TSHasTransientVariable - determine whether transient variables have been set

1746:   Logically Collective

1748:   Input Parameter:
1749: . ts - `TS` on which to compute

1751:   Output Parameter:
1752: . has - `PETSC_TRUE` if transient variables have been set

1754:   Level: developer

1756: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()`
1757: @*/
1758: PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has)
1759: {
1760:   DM   dm;
1761:   DMTS dmts;

1763:   PetscFunctionBegin;
1765:   PetscCall(TSGetDM(ts, &dm));
1766:   PetscCall(DMGetDMTS(dm, &dmts));
1767:   *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE;
1768:   PetscFunctionReturn(PETSC_SUCCESS);
1769: }

1771: /*@
1772:   TS2SetSolution - Sets the initial solution and time derivative vectors
1773:   for use by the `TS` routines handling second order equations.

1775:   Logically Collective

1777:   Input Parameters:
1778: + ts - the `TS` context obtained from `TSCreate()`
1779: . u  - the solution vector
1780: - v  - the time derivative vector

1782:   Level: beginner

1784: .seealso: [](ch_ts), `TS`
1785: @*/
1786: PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v)
1787: {
1788:   PetscFunctionBegin;
1792:   PetscCall(TSSetSolution(ts, u));
1793:   PetscCall(PetscObjectReference((PetscObject)v));
1794:   PetscCall(VecDestroy(&ts->vec_dot));
1795:   ts->vec_dot = v;
1796:   PetscFunctionReturn(PETSC_SUCCESS);
1797: }

1799: /*@
1800:   TS2GetSolution - Returns the solution and time derivative at the present timestep
1801:   for second order equations.

1803:   Not Collective

1805:   Input Parameter:
1806: . ts - the `TS` context obtained from `TSCreate()`

1808:   Output Parameters:
1809: + u - the vector containing the solution
1810: - v - the vector containing the time derivative

1812:   Level: intermediate

1814:   Notes:
1815:   It is valid to call this routine inside the function
1816:   that you are evaluating in order to move to the new timestep. This vector not
1817:   changed until the solution at the next timestep has been calculated.

1819: .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()`
1820: @*/
1821: PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v)
1822: {
1823:   PetscFunctionBegin;
1825:   if (u) PetscAssertPointer(u, 2);
1826:   if (v) PetscAssertPointer(v, 3);
1827:   if (u) *u = ts->vec_sol;
1828:   if (v) *v = ts->vec_dot;
1829:   PetscFunctionReturn(PETSC_SUCCESS);
1830: }

1832: /*@
1833:   TSLoad - Loads a `TS` that has been stored in binary  with `TSView()`.

1835:   Collective

1837:   Input Parameters:
1838: + ts     - the newly loaded `TS`, this needs to have been created with `TSCreate()` or
1839:            some related function before a call to `TSLoad()`.
1840: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`

1842:   Level: intermediate

1844:   Note:
1845:   The type is determined by the data in the file, any type set into the `TS` before this call is ignored.

1847: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()`
1848: @*/
1849: PetscErrorCode TSLoad(TS ts, PetscViewer viewer)
1850: {
1851:   PetscBool isbinary;
1852:   PetscInt  classid;
1853:   char      type[256];
1854:   DMTS      sdm;
1855:   DM        dm;

1857:   PetscFunctionBegin;
1860:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1861:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");

1863:   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
1864:   PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file");
1865:   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
1866:   PetscCall(TSSetType(ts, type));
1867:   PetscTryTypeMethod(ts, load, viewer);
1868:   PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm));
1869:   PetscCall(DMLoad(dm, viewer));
1870:   PetscCall(TSSetDM(ts, dm));
1871:   PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
1872:   PetscCall(VecLoad(ts->vec_sol, viewer));
1873:   PetscCall(DMGetDMTS(ts->dm, &sdm));
1874:   PetscCall(DMTSLoad(sdm, viewer));
1875:   PetscFunctionReturn(PETSC_SUCCESS);
1876: }

1878: #include <petscdraw.h>
1879: #if defined(PETSC_HAVE_SAWS)
1880: #include <petscviewersaws.h>
1881: #endif

1883: /*@
1884:   TSViewFromOptions - View a `TS` based on values in the options database

1886:   Collective

1888:   Input Parameters:
1889: + ts   - the `TS` context
1890: . obj  - Optional object that provides the prefix for the options database keys
1891: - name - command line option string to be passed by user

1893:   Options Database Key:
1894: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments

1896:   Level: intermediate

1898: .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()`
1899: @*/
1900: PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[])
1901: {
1902:   PetscFunctionBegin;
1904:   PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name));
1905:   PetscFunctionReturn(PETSC_SUCCESS);
1906: }

1908: /*@
1909:   TSView - Prints the `TS` data structure.

1911:   Collective

1913:   Input Parameters:
1914: + ts     - the `TS` context obtained from `TSCreate()`
1915: - viewer - visualization context

1917:   Options Database Key:
1918: . -ts_view - calls `TSView()` at end of `TSStep()`

1920:   Level: beginner

1922:   Notes:
1923:   The available visualization contexts include
1924: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1925: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1926:   output where only the first processor opens
1927:   the file.  All other processors send their
1928:   data to the first processor to print.

1930:   The user can open an alternative visualization context with
1931:   `PetscViewerASCIIOpen()` - output to a specified file.

1933:   In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer).

1935:   The "initial time step" displayed is the default time step from `TSCreate()` or that set with `TSSetTimeStep()` or `-ts_time_step`

1937: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()`
1938: @*/
1939: PetscErrorCode TSView(TS ts, PetscViewer viewer)
1940: {
1941:   TSType    type;
1942:   PetscBool isascii, isstring, issundials, isbinary, isdraw;
1943:   DMTS      sdm;
1944: #if defined(PETSC_HAVE_SAWS)
1945:   PetscBool issaws;
1946: #endif

1948:   PetscFunctionBegin;
1950:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer));
1952:   PetscCheckSameComm(ts, 1, viewer, 2);

1954:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1955:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1956:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1957:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1958: #if defined(PETSC_HAVE_SAWS)
1959:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1960: #endif
1961:   if (isascii) {
1962:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer));
1963:     if (ts->ops->view) {
1964:       PetscCall(PetscViewerASCIIPushTab(viewer));
1965:       PetscUseTypeMethod(ts, view, viewer);
1966:       PetscCall(PetscViewerASCIIPopTab(viewer));
1967:     }
1968:     PetscCall(PetscViewerASCIIPrintf(viewer, "  initial time step=%g\n", (double)ts->initial_time_step));
1969:     if (ts->max_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum steps=%" PetscInt_FMT "\n", ts->max_steps));
1970:     if (ts->run_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, "  run steps=%" PetscInt_FMT "\n", ts->run_steps));
1971:     if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum time=%g\n", (double)ts->max_time));
1972:     if (ts->max_reject != PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum number of step rejections=%" PetscInt_FMT "\n", ts->max_reject));
1973:     if (ts->max_snes_failures != PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum number of SNES failures allowed=%" PetscInt_FMT "\n", ts->max_snes_failures));
1974:     if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs));
1975:     if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs));
1976:     if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs));
1977:     if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs));
1978:     if (ts->usessnes) {
1979:       PetscBool lin;
1980:       if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its));
1981:       PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its));
1982:       PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
1983:       PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures));
1984:     }
1985:     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of rejected steps=%" PetscInt_FMT "\n", ts->reject));
1986:     if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, "  using vector of relative error tolerances, "));
1987:     else PetscCall(PetscViewerASCIIPrintf(viewer, "  using relative error tolerance of %g, ", (double)ts->rtol));
1988:     if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, "using vector of absolute error tolerances\n"));
1989:     else PetscCall(PetscViewerASCIIPrintf(viewer, "using absolute error tolerance of %g\n", (double)ts->atol));
1990:     PetscCall(PetscViewerASCIIPushTab(viewer));
1991:     PetscCall(TSAdaptView(ts->adapt, viewer));
1992:     PetscCall(PetscViewerASCIIPopTab(viewer));
1993:   } else if (isstring) {
1994:     PetscCall(TSGetType(ts, &type));
1995:     PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type));
1996:     PetscTryTypeMethod(ts, view, viewer);
1997:   } else if (isbinary) {
1998:     PetscInt    classid = TS_FILE_CLASSID;
1999:     MPI_Comm    comm;
2000:     PetscMPIInt rank;
2001:     char        type[256];

2003:     PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
2004:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
2005:     if (rank == 0) {
2006:       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
2007:       PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256));
2008:       PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
2009:     }
2010:     PetscTryTypeMethod(ts, view, viewer);
2011:     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
2012:     PetscCall(DMView(ts->dm, viewer));
2013:     PetscCall(VecView(ts->vec_sol, viewer));
2014:     PetscCall(DMGetDMTS(ts->dm, &sdm));
2015:     PetscCall(DMTSView(sdm, viewer));
2016:   } else if (isdraw) {
2017:     PetscDraw draw;
2018:     char      str[36];
2019:     PetscReal x, y, bottom, h;

2021:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2022:     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
2023:     PetscCall(PetscStrncpy(str, "TS: ", sizeof(str)));
2024:     PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str)));
2025:     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h));
2026:     bottom = y - h;
2027:     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
2028:     PetscTryTypeMethod(ts, view, viewer);
2029:     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
2030:     if (ts->snes) PetscCall(SNESView(ts->snes, viewer));
2031:     PetscCall(PetscDrawPopCurrentPoint(draw));
2032: #if defined(PETSC_HAVE_SAWS)
2033:   } else if (issaws) {
2034:     PetscMPIInt rank;
2035:     const char *name;

2037:     PetscCall(PetscObjectGetName((PetscObject)ts, &name));
2038:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
2039:     if (!((PetscObject)ts)->amsmem && rank == 0) {
2040:       char dir[1024];

2042:       PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer));
2043:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name));
2044:       PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT));
2045:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name));
2046:       PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE));
2047:     }
2048:     PetscTryTypeMethod(ts, view, viewer);
2049: #endif
2050:   }
2051:   if (ts->snes && ts->usessnes) {
2052:     PetscCall(PetscViewerASCIIPushTab(viewer));
2053:     PetscCall(SNESView(ts->snes, viewer));
2054:     PetscCall(PetscViewerASCIIPopTab(viewer));
2055:   }
2056:   PetscCall(DMGetDMTS(ts->dm, &sdm));
2057:   PetscCall(DMTSView(sdm, viewer));

2059:   PetscCall(PetscViewerASCIIPushTab(viewer));
2060:   PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &issundials));
2061:   PetscCall(PetscViewerASCIIPopTab(viewer));
2062:   PetscFunctionReturn(PETSC_SUCCESS);
2063: }

2065: /*@
2066:   TSSetApplicationContext - Sets an optional user-defined context for the timesteppers that may be accessed, for example inside the user provided
2067:   `TS` callbacks with `TSGetApplicationContext()`

2069:   Logically Collective

2071:   Input Parameters:
2072: + ts  - the `TS` context obtained from `TSCreate()`
2073: - ctx - user context

2075:   Level: intermediate

2077:   Fortran Note:
2078:   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2079:   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TSGetApplicationContext()` for
2080:   an example.

2082: .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()`
2083: @*/
2084: PetscErrorCode TSSetApplicationContext(TS ts, PetscCtx ctx)
2085: {
2086:   PetscFunctionBegin;
2088:   ts->ctx = ctx;
2089:   PetscFunctionReturn(PETSC_SUCCESS);
2090: }

2092: /*@
2093:   TSGetApplicationContext - Gets the user-defined context for the
2094:   timestepper that was set with `TSSetApplicationContext()`

2096:   Not Collective

2098:   Input Parameter:
2099: . ts - the `TS` context obtained from `TSCreate()`

2101:   Output Parameter:
2102: . ctx - a pointer to the user context

2104:   Level: intermediate

2106:   Fortran Notes:
2107:   This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with
2108: .vb
2109:   type(tUsertype), pointer :: ctx
2110: .ve

2112: .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()`
2113: @*/
2114: PetscErrorCode TSGetApplicationContext(TS ts, PetscCtxRt ctx)
2115: {
2116:   PetscFunctionBegin;
2118:   *(void **)ctx = ts->ctx;
2119:   PetscFunctionReturn(PETSC_SUCCESS);
2120: }

2122: /*@
2123:   TSGetStepNumber - Gets the number of time steps completed.

2125:   Not Collective

2127:   Input Parameter:
2128: . ts - the `TS` context obtained from `TSCreate()`

2130:   Output Parameter:
2131: . steps - number of steps completed so far

2133:   Level: intermediate

2135: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`
2136: @*/
2137: PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps)
2138: {
2139:   PetscFunctionBegin;
2141:   PetscAssertPointer(steps, 2);
2142:   *steps = ts->steps;
2143:   PetscFunctionReturn(PETSC_SUCCESS);
2144: }

2146: /*@
2147:   TSSetStepNumber - Sets the number of steps completed.

2149:   Logically Collective

2151:   Input Parameters:
2152: + ts    - the `TS` context
2153: - steps - number of steps completed so far

2155:   Level: developer

2157:   Note:
2158:   For most uses of the `TS` solvers the user need not explicitly call
2159:   `TSSetStepNumber()`, as the step counter is appropriately updated in
2160:   `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to
2161:   reinitialize timestepping by setting the step counter to zero (and time
2162:   to the initial time) to solve a similar problem with different initial
2163:   conditions or parameters. Other possible use case is to continue
2164:   timestepping from a previously interrupted run in such a way that `TS`
2165:   monitors will be called with a initial nonzero step counter.

2167: .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()`
2168: @*/
2169: PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps)
2170: {
2171:   PetscFunctionBegin;
2174:   PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative");
2175:   ts->steps = steps;
2176:   PetscFunctionReturn(PETSC_SUCCESS);
2177: }

2179: /*@
2180:   TSSetTimeStep - Allows one to reset the timestep at any time.

2182:   Logically Collective

2184:   Input Parameters:
2185: + ts        - the `TS` context obtained from `TSCreate()`
2186: - time_step - the size of the timestep

2188:   Options Database Key:
2189: . -ts_time_step dt - provide the initial time step

2191:   Level: intermediate

2193:   Notes:
2194:   This is only a suggestion, the actual initial time step used may differ

2196:   If this is called after `TSSetUp()`, it will not change the initial time step value printed by `TSView()`

2198: .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()`
2199: @*/
2200: PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step)
2201: {
2202:   PetscFunctionBegin;
2205:   ts->time_step = time_step;
2206:   if (ts->setupcalled == PETSC_FALSE) ts->initial_time_step = time_step;
2207:   PetscFunctionReturn(PETSC_SUCCESS);
2208: }

2210: /*@
2211:   TSSetExactFinalTime - Determines whether to adapt the final time step to
2212:   match the exact final time, to interpolate the solution to the exact final time,
2213:   or to just return at the final time `TS` computed (which may be slightly larger
2214:   than the requested final time).

2216:   Logically Collective

2218:   Input Parameters:
2219: + ts     - the time-step context
2220: - eftopt - exact final time option
2221: .vb
2222:   TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded, just use it
2223:   TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded
2224:   TS_EXACTFINALTIME_MATCHSTEP   - Adapt final time step to ensure the computed final time exactly equals the requested final time
2225: .ve

2227:   Options Database Key:
2228: . -ts_exact_final_time stepover,interpolate,matchstep - select the final step approach at runtime

2230:   Level: beginner

2232:   Note:
2233:   If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time
2234:   then the final time you selected.

2236: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()`
2237: @*/
2238: PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt)
2239: {
2240:   PetscFunctionBegin;
2243:   ts->exact_final_time = eftopt;
2244:   PetscFunctionReturn(PETSC_SUCCESS);
2245: }

2247: /*@
2248:   TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()`

2250:   Not Collective

2252:   Input Parameter:
2253: . ts - the `TS` context

2255:   Output Parameter:
2256: . eftopt - exact final time option

2258:   Level: beginner

2260: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()`
2261: @*/
2262: PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt)
2263: {
2264:   PetscFunctionBegin;
2266:   PetscAssertPointer(eftopt, 2);
2267:   *eftopt = ts->exact_final_time;
2268:   PetscFunctionReturn(PETSC_SUCCESS);
2269: }

2271: /*@
2272:   TSGetTimeStep - Gets the current timestep size.

2274:   Not Collective

2276:   Input Parameter:
2277: . ts - the `TS` context obtained from `TSCreate()`

2279:   Output Parameter:
2280: . dt - the current timestep size

2282:   Level: intermediate

2284: .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()`
2285: @*/
2286: PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt)
2287: {
2288:   PetscFunctionBegin;
2290:   PetscAssertPointer(dt, 2);
2291:   *dt = ts->time_step;
2292:   PetscFunctionReturn(PETSC_SUCCESS);
2293: }

2295: /*@
2296:   TSGetSolution - Returns the solution at the present timestep. It
2297:   is valid to call this routine inside the function that you are evaluating
2298:   in order to move to the new timestep. This vector not changed until
2299:   the solution at the next timestep has been calculated.

2301:   Not Collective, but v returned is parallel if ts is parallel

2303:   Input Parameter:
2304: . ts - the `TS` context obtained from `TSCreate()`

2306:   Output Parameter:
2307: . v - the vector containing the solution

2309:   Level: intermediate

2311:   Note:
2312:   If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested
2313:   final time. It returns the solution at the next timestep.

2315: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()`
2316: @*/
2317: PetscErrorCode TSGetSolution(TS ts, Vec *v)
2318: {
2319:   PetscFunctionBegin;
2321:   PetscAssertPointer(v, 2);
2322:   *v = ts->vec_sol;
2323:   PetscFunctionReturn(PETSC_SUCCESS);
2324: }

2326: /*@
2327:   TSGetSolutionComponents - Returns any solution components at the present
2328:   timestep, if available for the time integration method being used.
2329:   Solution components are quantities that share the same size and
2330:   structure as the solution vector.

2332:   Not Collective, but v returned is parallel if ts is parallel

2334:   Input Parameters:
2335: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2336: . n  - If v is `NULL`, then the number of solution components is
2337:        returned through n, else the n-th solution component is
2338:        returned in v.
2339: - v  - the vector containing the n-th solution component
2340:        (may be `NULL` to use this function to find out
2341:         the number of solutions components).

2343:   Level: advanced

2345: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2346: @*/
2347: PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v)
2348: {
2349:   PetscFunctionBegin;
2351:   if (!ts->ops->getsolutioncomponents) *n = 0;
2352:   else PetscUseTypeMethod(ts, getsolutioncomponents, n, v);
2353:   PetscFunctionReturn(PETSC_SUCCESS);
2354: }

2356: /*@
2357:   TSGetAuxSolution - Returns an auxiliary solution at the present
2358:   timestep, if available for the time integration method being used.

2360:   Not Collective, but v returned is parallel if ts is parallel

2362:   Input Parameters:
2363: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2364: - v  - the vector containing the auxiliary solution

2366:   Level: intermediate

2368: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2369: @*/
2370: PetscErrorCode TSGetAuxSolution(TS ts, Vec *v)
2371: {
2372:   PetscFunctionBegin;
2374:   if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v);
2375:   else PetscCall(VecZeroEntries(*v));
2376:   PetscFunctionReturn(PETSC_SUCCESS);
2377: }

2379: /*@
2380:   TSGetTimeError - Returns the estimated error vector, if the chosen
2381:   `TSType` has an error estimation functionality and `TSSetTimeError()` was called

2383:   Not Collective, but v returned is parallel if ts is parallel

2385:   Input Parameters:
2386: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2387: . n  - current estimate (n=0) or previous one (n=-1)
2388: - v  - the vector containing the error (same size as the solution).

2390:   Level: intermediate

2392:   Note:
2393:   MUST call after `TSSetUp()`

2395: .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()`
2396: @*/
2397: PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v)
2398: {
2399:   PetscFunctionBegin;
2401:   if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v);
2402:   else PetscCall(VecZeroEntries(*v));
2403:   PetscFunctionReturn(PETSC_SUCCESS);
2404: }

2406: /*@
2407:   TSSetTimeError - Sets the estimated error vector, if the chosen
2408:   `TSType` has an error estimation functionality. This can be used
2409:   to restart such a time integrator with a given error vector.

2411:   Not Collective, but v returned is parallel if ts is parallel

2413:   Input Parameters:
2414: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2415: - v  - the vector containing the error (same size as the solution).

2417:   Level: intermediate

2419: .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()`
2420: @*/
2421: PetscErrorCode TSSetTimeError(TS ts, Vec v)
2422: {
2423:   PetscFunctionBegin;
2425:   PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first");
2426:   PetscTryTypeMethod(ts, settimeerror, v);
2427:   PetscFunctionReturn(PETSC_SUCCESS);
2428: }

2430: /* ----- Routines to initialize and destroy a timestepper ---- */
2431: /*@
2432:   TSSetProblemType - Sets the type of problem to be solved.

2434:   Not collective

2436:   Input Parameters:
2437: + ts   - The `TS`
2438: - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2439: .vb
2440:          U_t - A U = 0      (linear)
2441:          U_t - A(t) U = 0   (linear)
2442:          F(t,U,U_t) = 0     (nonlinear)
2443: .ve

2445:   Level: beginner

2447: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2448: @*/
2449: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
2450: {
2451:   PetscFunctionBegin;
2453:   ts->problem_type = type;
2454:   if (type == TS_LINEAR) {
2455:     SNES snes;
2456:     PetscCall(TSGetSNES(ts, &snes));
2457:     PetscCall(SNESSetType(snes, SNESKSPONLY));
2458:   }
2459:   PetscFunctionReturn(PETSC_SUCCESS);
2460: }

2462: /*@
2463:   TSGetProblemType - Gets the type of problem to be solved.

2465:   Not collective

2467:   Input Parameter:
2468: . ts - The `TS`

2470:   Output Parameter:
2471: . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2472: .vb
2473:          M U_t = A U
2474:          M(t) U_t = A(t) U
2475:          F(t,U,U_t)
2476: .ve

2478:   Level: beginner

2480: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2481: @*/
2482: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
2483: {
2484:   PetscFunctionBegin;
2486:   PetscAssertPointer(type, 2);
2487:   *type = ts->problem_type;
2488:   PetscFunctionReturn(PETSC_SUCCESS);
2489: }

2491: /*
2492:     Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
2493: */
2494: static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
2495: {
2496:   PetscBool isnone;

2498:   PetscFunctionBegin;
2499:   PetscCall(TSGetAdapt(ts, &ts->adapt));
2500:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));

2502:   PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone));
2503:   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2504:   else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
2505:   PetscFunctionReturn(PETSC_SUCCESS);
2506: }

2508: /*@
2509:   TSSetUp - Sets up the internal data structures for the later use of a timestepper.

2511:   Collective

2513:   Input Parameter:
2514: . ts - the `TS` context obtained from `TSCreate()`

2516:   Level: advanced

2518:   Note:
2519:   For basic use of the `TS` solvers the user need not explicitly call
2520:   `TSSetUp()`, since these actions will automatically occur during
2521:   the call to `TSStep()` or `TSSolve()`.  However, if one wishes to control this
2522:   phase separately, `TSSetUp()` should be called after `TSCreate()`
2523:   and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`.

2525: .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()`
2526: @*/
2527: PetscErrorCode TSSetUp(TS ts)
2528: {
2529:   DM dm;
2530:   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
2531:   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
2532:   TSIFunctionFn   *ifun;
2533:   TSIJacobianFn   *ijac;
2534:   TSI2JacobianFn  *i2jac;
2535:   TSRHSJacobianFn *rhsjac;

2537:   PetscFunctionBegin;
2539:   if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);

2541:   if (!((PetscObject)ts)->type_name) {
2542:     PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
2543:     PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER));
2544:   }

2546:   if (!ts->vec_sol) {
2547:     PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first");
2548:     PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
2549:   }

2551:   if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
2552:     PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
2553:     ts->Jacp = ts->Jacprhs;
2554:   }

2556:   if (ts->quadraturets) {
2557:     PetscCall(TSSetUp(ts->quadraturets));
2558:     PetscCall(VecDestroy(&ts->vec_costintegrand));
2559:     PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand));
2560:   }

2562:   PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL));
2563:   if (rhsjac == TSComputeRHSJacobianConstant) {
2564:     Mat  Amat, Pmat;
2565:     SNES snes;
2566:     PetscCall(TSGetSNES(ts, &snes));
2567:     PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL));
2568:     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2569:      * have displaced the RHS matrix */
2570:     if (Amat && Amat == ts->Arhs) {
2571:       /* 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 */
2572:       PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat));
2573:       PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL));
2574:       PetscCall(MatDestroy(&Amat));
2575:     }
2576:     if (Pmat && Pmat == ts->Brhs) {
2577:       PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat));
2578:       PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL));
2579:       PetscCall(MatDestroy(&Pmat));
2580:     }
2581:   }

2583:   PetscCall(TSGetAdapt(ts, &ts->adapt));
2584:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));

2586:   PetscTryTypeMethod(ts, setup);

2588:   PetscCall(TSSetExactFinalTimeDefault(ts));

2590:   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2591:      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2592:    */
2593:   PetscCall(TSGetDM(ts, &dm));
2594:   PetscCall(DMSNESGetFunction(dm, &func, NULL));
2595:   if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts));

2597:   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2598:      Otherwise, the SNES will use coloring internally to form the Jacobian.
2599:    */
2600:   PetscCall(DMSNESGetJacobian(dm, &jac, NULL));
2601:   PetscCall(DMTSGetIJacobian(dm, &ijac, NULL));
2602:   PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL));
2603:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL));
2604:   if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts));

2606:   /* if time integration scheme has a starting method, call it */
2607:   PetscTryTypeMethod(ts, startingmethod);

2609:   ts->setupcalled = PETSC_TRUE;
2610:   PetscFunctionReturn(PETSC_SUCCESS);
2611: }

2613: /*@
2614:   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

2616:   Collective

2618:   Input Parameter:
2619: . ts - the `TS` context obtained from `TSCreate()`

2621:   Level: developer

2623:   Notes:
2624:   Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain.

2626:   See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration.

2628: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSetResize()`
2629: @*/
2630: PetscErrorCode TSReset(TS ts)
2631: {
2632:   TS_RHSSplitLink ilink = ts->tsrhssplit, next;

2634:   PetscFunctionBegin;

2637:   PetscTryTypeMethod(ts, reset);
2638:   if (ts->snes) PetscCall(SNESReset(ts->snes));
2639:   if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));

2641:   PetscCall(MatDestroy(&ts->Arhs));
2642:   PetscCall(MatDestroy(&ts->Brhs));
2643:   PetscCall(VecDestroy(&ts->Frhs));
2644:   PetscCall(VecDestroy(&ts->vec_sol));
2645:   PetscCall(VecDestroy(&ts->vec_sol0));
2646:   PetscCall(VecDestroy(&ts->vec_dot));
2647:   PetscCall(VecDestroy(&ts->vatol));
2648:   PetscCall(VecDestroy(&ts->vrtol));
2649:   PetscCall(VecDestroyVecs(ts->nwork, &ts->work));

2651:   PetscCall(MatDestroy(&ts->Jacprhs));
2652:   PetscCall(MatDestroy(&ts->Jacp));
2653:   if (ts->forward_solve) PetscCall(TSForwardReset(ts));
2654:   if (ts->quadraturets) {
2655:     PetscCall(TSReset(ts->quadraturets));
2656:     PetscCall(VecDestroy(&ts->vec_costintegrand));
2657:   }
2658:   while (ilink) {
2659:     next = ilink->next;
2660:     PetscCall(TSDestroy(&ilink->ts));
2661:     PetscCall(PetscFree(ilink->splitname));
2662:     PetscCall(ISDestroy(&ilink->is));
2663:     PetscCall(PetscFree(ilink));
2664:     ilink = next;
2665:   }
2666:   ts->tsrhssplit     = NULL;
2667:   ts->num_rhs_splits = 0;
2668:   if (ts->eval_times) {
2669:     PetscCall(PetscFree(ts->eval_times->time_points));
2670:     PetscCall(PetscFree(ts->eval_times->sol_times));
2671:     PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
2672:     PetscCall(PetscFree(ts->eval_times));
2673:   }
2674:   ts->rhsjacobian.time  = PETSC_MIN_REAL;
2675:   ts->rhsjacobian.scale = 1.0;
2676:   ts->ijacobian.shift   = 1.0;
2677:   ts->setupcalled       = PETSC_FALSE;
2678:   PetscFunctionReturn(PETSC_SUCCESS);
2679: }

2681: static PetscErrorCode TSResizeReset(TS);

2683: /*@
2684:   TSDestroy - Destroys the timestepper context that was created
2685:   with `TSCreate()`.

2687:   Collective

2689:   Input Parameter:
2690: . ts - the `TS` context obtained from `TSCreate()`

2692:   Level: beginner

2694: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2695: @*/
2696: PetscErrorCode TSDestroy(TS *ts)
2697: {
2698:   PetscFunctionBegin;
2699:   if (!*ts) PetscFunctionReturn(PETSC_SUCCESS);
2701:   if (--((PetscObject)*ts)->refct > 0) {
2702:     *ts = NULL;
2703:     PetscFunctionReturn(PETSC_SUCCESS);
2704:   }

2706:   PetscCall(TSReset(*ts));
2707:   PetscCall(TSAdjointReset(*ts));
2708:   if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts));
2709:   PetscCall(TSResizeReset(*ts));

2711:   /* if memory was published with SAWs then destroy it */
2712:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
2713:   PetscTryTypeMethod(*ts, destroy);

2715:   PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory));

2717:   PetscCall(TSAdaptDestroy(&(*ts)->adapt));
2718:   PetscCall(TSEventDestroy(&(*ts)->event));

2720:   PetscCall(SNESDestroy(&(*ts)->snes));
2721:   PetscCall(SNESDestroy(&(*ts)->snesrhssplit));
2722:   PetscCall(DMDestroy(&(*ts)->dm));
2723:   PetscCall(TSMonitorCancel(*ts));
2724:   PetscCall(TSAdjointMonitorCancel(*ts));

2726:   PetscCall(TSDestroy(&(*ts)->quadraturets));
2727:   PetscCall(PetscHeaderDestroy(ts));
2728:   PetscFunctionReturn(PETSC_SUCCESS);
2729: }

2731: /*@
2732:   TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context

2734:   Collective

2736:   Input Parameters:
2737: + ts   - the `TS` context obtained from `TSCreate()`
2738: - snes - the nonlinear solver context

2740:   Level: developer

2742:   Note:
2743:   Most users should obtain the `SNES` by calling `TSGetSNES()` rather than setting it with this function.

2745: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetKSP()`, `TSIsImplicit()`, `TSGetSNES()`
2746:  @*/
2747: PetscErrorCode TSSetSNES(TS ts, SNES snes)
2748: {
2749:   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);

2751:   PetscFunctionBegin;
2754:   PetscCall(PetscObjectReference((PetscObject)snes));
2755:   PetscCall(SNESDestroy(&ts->snes));
2756:   ts->snes = snes;
2757:   PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2758:   PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
2759:   if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
2760:   PetscFunctionReturn(PETSC_SUCCESS);
2761: }

2763: /*@
2764:   TSGetSNES - Returns the `SNES` (nonlinear solver) associated with
2765:   a `TS` (timestepper) context.

2767:   Not Collective, but `snes` is parallel if `ts` is parallel

2769:   Input Parameter:
2770: . ts - the `TS` context obtained from `TSCreate()`

2772:   Output Parameter:
2773: . snes - the nonlinear solver context

2775:   Level: beginner

2777:   Notes:
2778:   The user can then directly manipulate the `SNES` context to set various
2779:   options, etc.  Likewise, the user can then extract and manipulate the
2780:   `KSP`, and `PC` contexts as well.

2782:   For linear problems, use `TSGetKSP()`.

2784:   For integrators that do not use `SNES` (that is, explicit methods),
2785:   the `snes` exists but is not used. Use `TSIsImplicit()` to determine if the
2786:   method is implicit and uses `snes`.

2788:   Developer Note:
2789:   `TS` manages the life-cycle of the `SNES` object for all `TSType` for the life-time of the `TS` object,
2790:   even explicit methods that do not use `SNES`. This is so that `SNES` options are retained between changes to the `TSType` with `TSSetType()`.

2792: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetKSP()`, `TSIsImplicit()`
2793: @*/
2794: PetscErrorCode TSGetSNES(TS ts, SNES *snes)
2795: {
2796:   PetscFunctionBegin;
2798:   PetscAssertPointer(snes, 2);
2799:   if (!ts->snes) {
2800:     PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes));
2801:     PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options));
2802:     PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2803:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
2804:     if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
2805:     if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
2806:   }
2807:   *snes = ts->snes;
2808:   PetscFunctionReturn(PETSC_SUCCESS);
2809: }

2811: /*@
2812:   TSIsImplicit - Indicates if a `TS` represents an implicit integrator that uses `SNES`

2814:   Not Collective

2816:   Input Parameter:
2817: . ts - the `TS` context obtained from `TSCreate()`

2819:   Output Parameter:
2820: . isimplicit - if the integrator is implicit and uses either `SNES` or `KSP`

2822:   Level: beginner

2824:   Note:
2825:   For integrators that do not use `SNES` (that is, explicit methods), `snes` exists but is not used.

2827: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetKSP()`, `TSGetSNES()`
2828: @*/
2829: PetscErrorCode TSIsImplicit(TS ts, PetscBool *isimplicit)
2830: {
2831:   PetscFunctionBegin;
2833:   PetscAssertPointer(isimplicit, 2);
2834:   *isimplicit = ts->usessnes;
2835:   PetscFunctionReturn(PETSC_SUCCESS);
2836: }

2838: /*@
2839:   TSGetKSP - Returns the `KSP` (linear solver) associated with
2840:   a `TS` (timestepper) context.

2842:   Not Collective, but `ksp` is parallel if `ts` is parallel

2844:   Input Parameter:
2845: . ts - the `TS` context obtained from `TSCreate()`

2847:   Output Parameter:
2848: . ksp - the nonlinear solver context

2850:   Level: beginner

2852:   Notes:
2853:   The user can then directly manipulate the `KSP` context to set various
2854:   options, etc.  Likewise, the user can then extract and manipulate the
2855:   `PC` context as well.

2857:   For nonlinear problems (`TS_NONLINEAR`), use `TSGetSNES()` followed by `SNESGetKSP()`.

2859:   For integrators that do not use `KSP` (that is, explicit methods),
2860:   `TSGetKSP()` returns a `ksp` that is not used. Use `TSIsImplicit()` to determine if
2861:   the `ksp` is actually used.

2863: .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`, `TSIsImplicit()`
2864: @*/
2865: PetscErrorCode TSGetKSP(TS ts, KSP *ksp)
2866: {
2867:   SNES snes;

2869:   PetscFunctionBegin;
2871:   PetscAssertPointer(ksp, 2);
2872:   PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
2873:   PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "For linear problems only; use TSGetSNES() then SNESGetKSP()");
2874:   PetscCall(TSGetSNES(ts, &snes));
2875:   PetscCall(SNESGetKSP(snes, ksp));
2876:   PetscFunctionReturn(PETSC_SUCCESS);
2877: }

2879: /* ----------- Routines to set solver parameters ---------- */

2881: /*@
2882:   TSSetMaxSteps - Sets the maximum number of steps to use.

2884:   Logically Collective

2886:   Input Parameters:
2887: + ts       - the `TS` context obtained from `TSCreate()`
2888: - maxsteps - maximum number of steps to use

2890:   Options Database Key:
2891: . -ts_max_steps maxsteps - Sets maxsteps

2893:   Level: intermediate

2895:   Note:
2896:   Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set

2898:   The default maximum number of steps is 5,000

2900:   Fortran Note:
2901:   Use `PETSC_DETERMINE_INTEGER`

2903: .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
2904: @*/
2905: PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps)
2906: {
2907:   PetscFunctionBegin;
2910:   if (maxsteps == PETSC_DETERMINE) {
2911:     ts->max_steps = ts->default_max_steps;
2912:   } else {
2913:     PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
2914:     ts->max_steps = maxsteps;
2915:   }
2916:   PetscFunctionReturn(PETSC_SUCCESS);
2917: }

2919: /*@
2920:   TSGetMaxSteps - Gets the maximum number of steps to use.

2922:   Not Collective

2924:   Input Parameter:
2925: . ts - the `TS` context obtained from `TSCreate()`

2927:   Output Parameter:
2928: . maxsteps - maximum number of steps to use

2930:   Level: advanced

2932: .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
2933: @*/
2934: PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps)
2935: {
2936:   PetscFunctionBegin;
2938:   PetscAssertPointer(maxsteps, 2);
2939:   *maxsteps = ts->max_steps;
2940:   PetscFunctionReturn(PETSC_SUCCESS);
2941: }

2943: /*@
2944:   TSSetRunSteps - Sets the maximum number of steps to take in each call to `TSSolve()`.

2946:   If the step count when `TSSolve()` is `start_step`, this will stop the simulation once `current_step - start_step >= run_steps`.
2947:   Comparatively, `TSSetMaxSteps()` will stop if `current_step >= max_steps`.
2948:   The simulation will stop when either condition is reached.

2950:   Logically Collective

2952:   Input Parameters:
2953: + ts       - the `TS` context obtained from `TSCreate()`
2954: - runsteps - maximum number of steps to take in each call to `TSSolve()`;

2956:   Options Database Key:
2957: . -ts_run_steps runsteps - Sets runsteps

2959:   Level: intermediate

2961:   Note:
2962:   The default is `PETSC_UNLIMITED`

2964: .seealso: [](ch_ts), `TS`, `TSGetRunSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`, `TSSetMaxSteps()`
2965: @*/
2966: PetscErrorCode TSSetRunSteps(TS ts, PetscInt runsteps)
2967: {
2968:   PetscFunctionBegin;
2971:   if (runsteps == PETSC_DETERMINE) {
2972:     ts->run_steps = PETSC_UNLIMITED;
2973:   } else {
2974:     PetscCheck(runsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Max number of steps to take in each call to TSSolve must be non-negative");
2975:     ts->run_steps = runsteps;
2976:   }
2977:   PetscFunctionReturn(PETSC_SUCCESS);
2978: }

2980: /*@
2981:   TSGetRunSteps - Gets the maximum number of steps to take in each call to `TSSolve()`.

2983:   Not Collective

2985:   Input Parameter:
2986: . ts - the `TS` context obtained from `TSCreate()`

2988:   Output Parameter:
2989: . runsteps - maximum number of steps to take in each call to `TSSolve`.

2991:   Level: advanced

2993: .seealso: [](ch_ts), `TS`, `TSSetRunSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`, `TSGetMaxSteps()`
2994: @*/
2995: PetscErrorCode TSGetRunSteps(TS ts, PetscInt *runsteps)
2996: {
2997:   PetscFunctionBegin;
2999:   PetscAssertPointer(runsteps, 2);
3000:   *runsteps = ts->run_steps;
3001:   PetscFunctionReturn(PETSC_SUCCESS);
3002: }

3004: /*@
3005:   TSSetMaxTime - Sets the maximum (or final) time for timestepping.

3007:   Logically Collective

3009:   Input Parameters:
3010: + ts      - the `TS` context obtained from `TSCreate()`
3011: - maxtime - final time to step to

3013:   Options Database Key:
3014: . -ts_max_time maxtime - Sets maxtime

3016:   Level: intermediate

3018:   Notes:
3019:   Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set

3021:   The default maximum time is 5.0

3023:   Fortran Note:
3024:   Use `PETSC_DETERMINE_REAL`

3026: .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
3027: @*/
3028: PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime)
3029: {
3030:   PetscFunctionBegin;
3033:   if (maxtime == PETSC_DETERMINE) {
3034:     ts->max_time = ts->default_max_time;
3035:   } else {
3036:     ts->max_time = maxtime;
3037:   }
3038:   PetscFunctionReturn(PETSC_SUCCESS);
3039: }

3041: /*@
3042:   TSGetMaxTime - Gets the maximum (or final) time for timestepping.

3044:   Not Collective

3046:   Input Parameter:
3047: . ts - the `TS` context obtained from `TSCreate()`

3049:   Output Parameter:
3050: . maxtime - final time to step to

3052:   Level: advanced

3054: .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
3055: @*/
3056: PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime)
3057: {
3058:   PetscFunctionBegin;
3060:   PetscAssertPointer(maxtime, 2);
3061:   *maxtime = ts->max_time;
3062:   PetscFunctionReturn(PETSC_SUCCESS);
3063: }

3065: // PetscClangLinter pragma disable: -fdoc-*
3066: /*@
3067:   TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`.

3069:   Level: deprecated

3071: @*/
3072: PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step)
3073: {
3074:   PetscFunctionBegin;
3076:   PetscCall(TSSetTime(ts, initial_time));
3077:   PetscCall(TSSetTimeStep(ts, time_step));
3078:   PetscFunctionReturn(PETSC_SUCCESS);
3079: }

3081: // PetscClangLinter pragma disable: -fdoc-*
3082: /*@
3083:   TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`.

3085:   Level: deprecated

3087: @*/
3088: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
3089: {
3090:   PetscFunctionBegin;
3092:   if (maxsteps) {
3093:     PetscAssertPointer(maxsteps, 2);
3094:     *maxsteps = ts->max_steps;
3095:   }
3096:   if (maxtime) {
3097:     PetscAssertPointer(maxtime, 3);
3098:     *maxtime = ts->max_time;
3099:   }
3100:   PetscFunctionReturn(PETSC_SUCCESS);
3101: }

3103: // PetscClangLinter pragma disable: -fdoc-*
3104: /*@
3105:   TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`.

3107:   Level: deprecated

3109: @*/
3110: PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime)
3111: {
3112:   PetscFunctionBegin;
3113:   if (maxsteps != PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps));
3114:   if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime));
3115:   PetscFunctionReturn(PETSC_SUCCESS);
3116: }

3118: // PetscClangLinter pragma disable: -fdoc-*
3119: /*@
3120:   TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`.

3122:   Level: deprecated

3124: @*/
3125: PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps)
3126: {
3127:   return TSGetStepNumber(ts, steps);
3128: }

3130: // PetscClangLinter pragma disable: -fdoc-*
3131: /*@
3132:   TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`.

3134:   Level: deprecated

3136: @*/
3137: PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps)
3138: {
3139:   return TSGetStepNumber(ts, steps);
3140: }

3142: /*@
3143:   TSSetSolution - Sets the initial solution vector
3144:   for use by the `TS` routines.

3146:   Logically Collective

3148:   Input Parameters:
3149: + ts - the `TS` context obtained from `TSCreate()`
3150: - u  - the solution vector

3152:   Level: beginner

3154: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
3155: @*/
3156: PetscErrorCode TSSetSolution(TS ts, Vec u)
3157: {
3158:   DM dm;

3160:   PetscFunctionBegin;
3163:   PetscCall(PetscObjectReference((PetscObject)u));
3164:   PetscCall(VecDestroy(&ts->vec_sol));
3165:   ts->vec_sol = u;

3167:   PetscCall(TSGetDM(ts, &dm));
3168:   PetscCall(DMShellSetGlobalVector(dm, u));
3169:   PetscFunctionReturn(PETSC_SUCCESS);
3170: }

3172: /*@C
3173:   TSSetPreStep - Sets the general-purpose function
3174:   called once at the beginning of each time step.

3176:   Logically Collective

3178:   Input Parameters:
3179: + ts   - The `TS` context obtained from `TSCreate()`
3180: - func - The function

3182:   Calling sequence of `func`:
3183: . ts - the `TS` context

3185:   Level: intermediate

3187: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
3188: @*/
3189: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts))
3190: {
3191:   PetscFunctionBegin;
3193:   ts->prestep = func;
3194:   PetscFunctionReturn(PETSC_SUCCESS);
3195: }

3197: /*@
3198:   TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()`

3200:   Collective

3202:   Input Parameter:
3203: . ts - The `TS` context obtained from `TSCreate()`

3205:   Level: developer

3207:   Note:
3208:   `TSPreStep()` is typically used within time stepping implementations,
3209:   so most users would not generally call this routine themselves.

3211: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
3212: @*/
3213: PetscErrorCode TSPreStep(TS ts)
3214: {
3215:   PetscFunctionBegin;
3217:   if (ts->prestep) {
3218:     Vec              U;
3219:     PetscObjectId    idprev;
3220:     PetscBool        sameObject;
3221:     PetscObjectState sprev, spost;

3223:     PetscCall(TSGetSolution(ts, &U));
3224:     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3225:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3226:     PetscCallBack("TS callback preset", (*ts->prestep)(ts));
3227:     PetscCall(TSGetSolution(ts, &U));
3228:     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3229:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3230:     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3231:   }
3232:   PetscFunctionReturn(PETSC_SUCCESS);
3233: }

3235: /*@C
3236:   TSSetPreStage - Sets the general-purpose function
3237:   called once at the beginning of each stage.

3239:   Logically Collective

3241:   Input Parameters:
3242: + ts   - The `TS` context obtained from `TSCreate()`
3243: - func - The function

3245:   Calling sequence of `func`:
3246: + ts        - the `TS` context
3247: - stagetime - the stage time

3249:   Level: intermediate

3251:   Note:
3252:   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3253:   The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3254:   attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.

3256: .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3257: @*/
3258: PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime))
3259: {
3260:   PetscFunctionBegin;
3262:   ts->prestage = func;
3263:   PetscFunctionReturn(PETSC_SUCCESS);
3264: }

3266: /*@C
3267:   TSSetPostStage - Sets the general-purpose function
3268:   called once at the end of each stage.

3270:   Logically Collective

3272:   Input Parameters:
3273: + ts   - The `TS` context obtained from `TSCreate()`
3274: - func - The function

3276:   Calling sequence of `func`:
3277: + ts         - the `TS` context
3278: . stagetime  - the stage time
3279: . stageindex - the stage index
3280: - Y          - Array of vectors (of size = total number of stages) with the stage solutions

3282:   Level: intermediate

3284:   Note:
3285:   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3286:   The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3287:   attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.

3289: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3290: @*/
3291: PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y))
3292: {
3293:   PetscFunctionBegin;
3295:   ts->poststage = func;
3296:   PetscFunctionReturn(PETSC_SUCCESS);
3297: }

3299: /*@C
3300:   TSSetPostEvaluate - Sets the general-purpose function
3301:   called at the end of each step evaluation.

3303:   Logically Collective

3305:   Input Parameters:
3306: + ts   - The `TS` context obtained from `TSCreate()`
3307: - func - The function

3309:   Calling sequence of `func`:
3310: . ts - the `TS` context

3312:   Level: intermediate

3314:   Note:
3315:   The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback.
3316:   Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be.
3317:   The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`.
3318:   The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`,
3319:   but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below
3320: .vb
3321:   ...
3322:   Step()
3323:   PostEvaluate()
3324:   EventHandling()
3325:   step_rollback ? PostEvaluate() : PostStep()
3326:   ...
3327: .ve
3328:   where EventHandling() may result in one of the following three outcomes
3329: .vb
3330:   (1) | successful step | solution intact
3331:   (2) | successful step | solution modified by `postevent()`
3332:   (3) | step_rollback   | solution rolled back
3333: .ve

3335: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3336: @*/
3337: PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts))
3338: {
3339:   PetscFunctionBegin;
3341:   ts->postevaluate = func;
3342:   PetscFunctionReturn(PETSC_SUCCESS);
3343: }

3345: /*@
3346:   TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()`

3348:   Collective

3350:   Input Parameters:
3351: + ts        - The `TS` context obtained from `TSCreate()`
3352: - stagetime - The absolute time of the current stage

3354:   Level: developer

3356:   Note:
3357:   `TSPreStage()` is typically used within time stepping implementations,
3358:   most users would not generally call this routine themselves.

3360: .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3361: @*/
3362: PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
3363: {
3364:   PetscFunctionBegin;
3366:   if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
3367:   PetscFunctionReturn(PETSC_SUCCESS);
3368: }

3370: /*@
3371:   TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()`

3373:   Collective

3375:   Input Parameters:
3376: + ts         - The `TS` context obtained from `TSCreate()`
3377: . stagetime  - The absolute time of the current stage
3378: . stageindex - Stage number
3379: - Y          - Array of vectors (of size = total number of stages) with the stage solutions

3381:   Level: developer

3383:   Note:
3384:   `TSPostStage()` is typically used within time stepping implementations,
3385:   most users would not generally call this routine themselves.

3387: .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3388: @*/
3389: PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec Y[])
3390: {
3391:   PetscFunctionBegin;
3393:   if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
3394:   PetscFunctionReturn(PETSC_SUCCESS);
3395: }

3397: /*@
3398:   TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()`

3400:   Collective

3402:   Input Parameter:
3403: . ts - The `TS` context obtained from `TSCreate()`

3405:   Level: developer

3407:   Note:
3408:   `TSPostEvaluate()` is typically used within time stepping implementations,
3409:   most users would not generally call this routine themselves.

3411: .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3412: @*/
3413: PetscErrorCode TSPostEvaluate(TS ts)
3414: {
3415:   PetscFunctionBegin;
3417:   if (ts->postevaluate) {
3418:     Vec              U;
3419:     PetscObjectState sprev, spost;

3421:     PetscCall(TSGetSolution(ts, &U));
3422:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3423:     PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
3424:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3425:     if (sprev != spost) PetscCall(TSRestartStep(ts));
3426:   }
3427:   PetscFunctionReturn(PETSC_SUCCESS);
3428: }

3430: /*@C
3431:   TSSetPostStep - Sets the general-purpose function
3432:   called once at the end of each successful time step.

3434:   Logically Collective

3436:   Input Parameters:
3437: + ts   - The `TS` context obtained from `TSCreate()`
3438: - func - The function

3440:   Calling sequence of `func`:
3441: . ts - the `TS` context

3443:   Level: intermediate

3445:   Note:
3446:   The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the
3447:   given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will
3448:   contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback.
3449:   The scheme of the relevant function calls in `TSSolve()` is shown below
3450: .vb
3451:   ...
3452:   Step()
3453:   PostEvaluate()
3454:   EventHandling()
3455:   step_rollback ? PostEvaluate() : PostStep()
3456:   ...
3457: .ve
3458:   where EventHandling() may result in one of the following three outcomes
3459: .vb
3460:   (1) | successful step | solution intact
3461:   (2) | successful step | solution modified by `postevent()`
3462:   (3) | step_rollback   | solution rolled back
3463: .ve

3465: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
3466: @*/
3467: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts))
3468: {
3469:   PetscFunctionBegin;
3471:   ts->poststep = func;
3472:   PetscFunctionReturn(PETSC_SUCCESS);
3473: }

3475: /*@
3476:   TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()`

3478:   Collective

3480:   Input Parameter:
3481: . ts - The `TS` context obtained from `TSCreate()`

3483:   Note:
3484:   `TSPostStep()` is typically used within time stepping implementations,
3485:   so most users would not generally call this routine themselves.

3487:   Level: developer

3489: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPostStep()`
3490: @*/
3491: PetscErrorCode TSPostStep(TS ts)
3492: {
3493:   PetscFunctionBegin;
3495:   if (ts->poststep) {
3496:     Vec              U;
3497:     PetscObjectId    idprev;
3498:     PetscBool        sameObject;
3499:     PetscObjectState sprev, spost;

3501:     PetscCall(TSGetSolution(ts, &U));
3502:     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3503:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3504:     PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
3505:     PetscCall(TSGetSolution(ts, &U));
3506:     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3507:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3508:     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3509:   }
3510:   PetscFunctionReturn(PETSC_SUCCESS);
3511: }

3513: /*@
3514:   TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval

3516:   Collective

3518:   Input Parameters:
3519: + ts - time stepping context
3520: - t  - time to interpolate to

3522:   Output Parameter:
3523: . U - state at given time

3525:   Level: intermediate

3527:   Developer Notes:
3528:   `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.

3530: .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()`
3531: @*/
3532: PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U)
3533: {
3534:   PetscFunctionBegin;
3537:   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);
3538:   PetscUseTypeMethod(ts, interpolate, t, U);
3539:   PetscFunctionReturn(PETSC_SUCCESS);
3540: }

3542: /*@
3543:   TSStep - Steps one time step

3545:   Collective

3547:   Input Parameter:
3548: . ts - the `TS` context obtained from `TSCreate()`

3550:   Level: developer

3552:   Notes:
3553:   The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine.

3555:   The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may
3556:   be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.

3558:   This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the
3559:   time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep.

3561: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
3562: @*/
3563: PetscErrorCode TSStep(TS ts)
3564: {
3565:   static PetscBool cite = PETSC_FALSE;
3566:   PetscReal        ptime;

3568:   PetscFunctionBegin;
3570:   PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3571:                                    "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3572:                                    "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3573:                                    "  journal       = {arXiv e-preprints},\n"
3574:                                    "  eprint        = {1806.01437},\n"
3575:                                    "  archivePrefix = {arXiv},\n"
3576:                                    "  year          = {2018}\n}\n",
3577:                                    &cite));
3578:   PetscCall(TSSetUp(ts));
3579:   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3580:   if (ts->eval_times)
3581:     ts->eval_times->worktol = 0; /* In each step of TSSolve() 'eval_times->worktol' will be meaningfully defined (later) only once:
3582:                                                    in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */

3584:   PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->run_steps != PETSC_INT_MAX || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime(), TSSetMaxSteps(), or TSSetRunSteps() or use -ts_max_time <time>, -ts_max_steps <steps>, -ts_run_steps <steps>");
3585:   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()");
3586:   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");

3588:   if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0));
3589:   PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0));
3590:   ts->time_step0 = ts->time_step;

3592:   if (!ts->steps) ts->ptime_prev = ts->ptime;
3593:   ptime = ts->ptime;

3595:   ts->ptime_prev_rollback = ts->ptime_prev;
3596:   ts->reason              = TS_CONVERGED_ITERATING;

3598:   PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
3599:   PetscUseTypeMethod(ts, step);
3600:   PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));

3602:   if (ts->reason >= 0) {
3603:     ts->ptime_prev = ptime;
3604:     ts->steps++;
3605:     ts->steprollback = PETSC_FALSE;
3606:     ts->steprestart  = PETSC_FALSE;
3607:     ts->stepresize   = PETSC_FALSE;
3608:   }

3610:   if (ts->reason < 0 && ts->errorifstepfailed) {
3611:     PetscCall(TSMonitorCancel(ts));
3612:     if (ts->usessnes && ts->snes) PetscCall(SNESMonitorCancel(ts->snes));
3613:     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]);
3614:     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
3615:   }
3616:   PetscFunctionReturn(PETSC_SUCCESS);
3617: }

3619: /*@
3620:   TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3621:   at the end of a time step with a given order of accuracy.

3623:   Collective

3625:   Input Parameters:
3626: + ts        - time stepping context
3627: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

3629:   Input/Output Parameter:
3630: . order - optional, desired order for the error evaluation or `PETSC_DECIDE`;
3631:            on output, the actual order of the error evaluation

3633:   Output Parameter:
3634: . wlte - the weighted local truncation error norm

3636:   Level: advanced

3638:   Note:
3639:   If the timestepper cannot evaluate the error in a particular step
3640:   (eg. in the first step or restart steps after event handling),
3641:   this routine returns wlte=-1.0 .

3643: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3644: @*/
3645: PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
3646: {
3647:   PetscFunctionBegin;
3651:   if (order) PetscAssertPointer(order, 3);
3653:   PetscAssertPointer(wlte, 4);
3654:   PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
3655:   PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
3656:   PetscFunctionReturn(PETSC_SUCCESS);
3657: }

3659: /*@
3660:   TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.

3662:   Collective

3664:   Input Parameters:
3665: + ts    - time stepping context
3666: . order - desired order of accuracy
3667: - done  - whether the step was evaluated at this order (pass `NULL` to generate an error if not available)

3669:   Output Parameter:
3670: . U - state at the end of the current step

3672:   Level: advanced

3674:   Notes:
3675:   This function cannot be called until all stages have been evaluated.

3677:   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.

3679: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`
3680: @*/
3681: PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done)
3682: {
3683:   PetscFunctionBegin;
3687:   PetscUseTypeMethod(ts, evaluatestep, order, U, done);
3688:   PetscFunctionReturn(PETSC_SUCCESS);
3689: }

3691: /*@C
3692:   TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.

3694:   Not collective

3696:   Input Parameter:
3697: . ts - time stepping context

3699:   Output Parameter:
3700: . initCondition - The function which computes an initial condition

3702:   Calling sequence of `initCondition`:
3703: + ts - The timestepping context
3704: - u  - The input vector in which the initial condition is stored

3706:   Level: advanced

3708: .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3709: @*/
3710: PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u))
3711: {
3712:   PetscFunctionBegin;
3714:   PetscAssertPointer(initCondition, 2);
3715:   *initCondition = ts->ops->initcondition;
3716:   PetscFunctionReturn(PETSC_SUCCESS);
3717: }

3719: /*@C
3720:   TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.

3722:   Logically collective

3724:   Input Parameters:
3725: + ts            - time stepping context
3726: - initCondition - The function which computes an initial condition

3728:   Calling sequence of `initCondition`:
3729: + ts - The timestepping context
3730: - e  - The input vector in which the initial condition is to be stored

3732:   Level: advanced

3734: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3735: @*/
3736: PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e))
3737: {
3738:   PetscFunctionBegin;
3741:   ts->ops->initcondition = initCondition;
3742:   PetscFunctionReturn(PETSC_SUCCESS);
3743: }

3745: /*@
3746:   TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()`

3748:   Collective

3750:   Input Parameters:
3751: + ts - time stepping context
3752: - u  - The `Vec` to store the condition in which will be used in `TSSolve()`

3754:   Level: advanced

3756: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3757: @*/
3758: PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
3759: {
3760:   PetscFunctionBegin;
3763:   PetscTryTypeMethod(ts, initcondition, u);
3764:   PetscFunctionReturn(PETSC_SUCCESS);
3765: }

3767: /*@C
3768:   TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.

3770:   Not collective

3772:   Input Parameter:
3773: . ts - time stepping context

3775:   Output Parameter:
3776: . exactError - The function which computes the solution error

3778:   Calling sequence of `exactError`:
3779: + ts - The timestepping context
3780: . u  - The approximate solution vector
3781: - e  - The vector in which the error is stored

3783:   Level: advanced

3785: .seealso: [](ch_ts), `TS`, `TSComputeExactError()`
3786: @*/
3787: PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e))
3788: {
3789:   PetscFunctionBegin;
3791:   PetscAssertPointer(exactError, 2);
3792:   *exactError = ts->ops->exacterror;
3793:   PetscFunctionReturn(PETSC_SUCCESS);
3794: }

3796: /*@C
3797:   TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.

3799:   Logically collective

3801:   Input Parameters:
3802: + ts         - time stepping context
3803: - exactError - The function which computes the solution error

3805:   Calling sequence of `exactError`:
3806: + ts - The timestepping context
3807: . u  - The approximate solution vector
3808: - e  - The  vector in which the error is stored

3810:   Level: advanced

3812: .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()`
3813: @*/
3814: PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e))
3815: {
3816:   PetscFunctionBegin;
3819:   ts->ops->exacterror = exactError;
3820:   PetscFunctionReturn(PETSC_SUCCESS);
3821: }

3823: /*@
3824:   TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()`

3826:   Collective

3828:   Input Parameters:
3829: + ts - time stepping context
3830: . u  - The approximate solution
3831: - e  - The `Vec` used to store the error

3833:   Level: advanced

3835: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3836: @*/
3837: PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
3838: {
3839:   PetscFunctionBegin;
3843:   PetscTryTypeMethod(ts, exacterror, u, e);
3844:   PetscFunctionReturn(PETSC_SUCCESS);
3845: }

3847: /*@C
3848:   TSSetResize - Sets the resize callbacks.

3850:   Logically Collective

3852:   Input Parameters:
3853: + ts       - The `TS` context obtained from `TSCreate()`
3854: . rollback - Whether a resize will restart the step
3855: . setup    - The setup function
3856: . transfer - The transfer function
3857: - ctx      - [optional] The user-defined context

3859:   Calling sequence of `setup`:
3860: + ts     - the `TS` context
3861: . step   - the current step
3862: . time   - the current time
3863: . state  - the current vector of state
3864: . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise
3865: - ctx    - user defined context

3867:   Calling sequence of `transfer`:
3868: + ts      - the `TS` context
3869: . nv      - the number of vectors to be transferred
3870: . vecsin  - array of vectors to be transferred
3871: . vecsout - array of transferred vectors
3872: - ctx     - user defined context

3874:   Notes:
3875:   The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()`
3876:   depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators
3877:   and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver
3878:   that the size of the discrete problem has changed.
3879:   In both cases, the solver will collect the needed vectors that will be
3880:   transferred from the old to the new sizes using the `transfer` callback. These vectors will include the
3881:   current solution vector, and other vectors needed by the specific solver used.
3882:   For example, `TSBDF` uses previous solutions vectors to solve for the next time step.
3883:   Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`,
3884:   will be automatically reset if the sizes are changed and they must be specified again by the user
3885:   inside the `transfer` function.
3886:   The input and output arrays passed to `transfer` are allocated by PETSc.
3887:   Vectors in `vecsout` must be created by the user.
3888:   Ownership of vectors in `vecsout` is transferred to PETSc.

3890:   Level: advanced

3892: .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()`
3893: @*/
3894: PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, PetscCtx ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], PetscCtx ctx), PetscCtx ctx)
3895: {
3896:   PetscFunctionBegin;
3898:   ts->resizerollback = rollback;
3899:   ts->resizesetup    = setup;
3900:   ts->resizetransfer = transfer;
3901:   ts->resizectx      = ctx;
3902:   PetscFunctionReturn(PETSC_SUCCESS);
3903: }

3905: /*
3906:   TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`.

3908:   Collective

3910:   Input Parameters:
3911: + ts   - The `TS` context obtained from `TSCreate()`
3912: - 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.

3914:   Level: developer

3916:   Note:
3917:   `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is
3918:    used within time stepping implementations,
3919:    so most users would not generally call this routine themselves.

3921: .seealso: [](ch_ts), `TS`, `TSSetResize()`
3922: @*/
3923: static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg)
3924: {
3925:   PetscFunctionBegin;
3927:   PetscTryTypeMethod(ts, resizeregister, flg);
3928:   /* PetscTryTypeMethod(adapt, resizeregister, flg); */
3929:   PetscFunctionReturn(PETSC_SUCCESS);
3930: }

3932: static PetscErrorCode TSResizeReset(TS ts)
3933: {
3934:   PetscFunctionBegin;
3936:   PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs));
3937:   PetscFunctionReturn(PETSC_SUCCESS);
3938: }

3940: static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[])
3941: {
3942:   PetscFunctionBegin;
3945:   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i]));
3946:   if (ts->resizetransfer) {
3947:     PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt));
3948:     PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx));
3949:   }
3950:   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i]));
3951:   PetscFunctionReturn(PETSC_SUCCESS);
3952: }

3954: /*@C
3955:   TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`.

3957:   Collective

3959:   Input Parameters:
3960: + ts   - The `TS` context obtained from `TSCreate()`
3961: . name - A string identifying the vector
3962: - vec  - The vector

3964:   Level: developer

3966:   Note:
3967:   `TSResizeRegisterVec()` is typically used within time stepping implementations,
3968:   so most users would not generally call this routine themselves.

3970: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()`
3971: @*/
3972: PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec)
3973: {
3974:   PetscFunctionBegin;
3976:   PetscAssertPointer(name, 2);
3978:   PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec));
3979:   PetscFunctionReturn(PETSC_SUCCESS);
3980: }

3982: /*@C
3983:   TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`.

3985:   Collective

3987:   Input Parameters:
3988: + ts   - The `TS` context obtained from `TSCreate()`
3989: . name - A string identifying the vector
3990: - vec  - The vector

3992:   Level: developer

3994:   Note:
3995:   `TSResizeRetrieveVec()` is typically used within time stepping implementations,
3996:   so most users would not generally call this routine themselves.

3998: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()`
3999: @*/
4000: PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec)
4001: {
4002:   PetscFunctionBegin;
4004:   PetscAssertPointer(name, 2);
4005:   PetscAssertPointer(vec, 3);
4006:   PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec));
4007:   PetscFunctionReturn(PETSC_SUCCESS);
4008: }

4010: static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[])
4011: {
4012:   PetscInt        cnt;
4013:   PetscObjectList tmp;
4014:   Vec            *vecsin  = NULL;
4015:   const char    **namesin = NULL;

4017:   PetscFunctionBegin;
4018:   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next)
4019:     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++;
4020:   if (names) PetscCall(PetscMalloc1(cnt, &namesin));
4021:   if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin));
4022:   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) {
4023:     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) {
4024:       if (vecs) vecsin[cnt] = (Vec)tmp->obj;
4025:       if (names) namesin[cnt] = tmp->name;
4026:       cnt++;
4027:     }
4028:   }
4029:   if (nv) *nv = cnt;
4030:   if (names) *names = namesin;
4031:   if (vecs) *vecs = vecsin;
4032:   PetscFunctionReturn(PETSC_SUCCESS);
4033: }

4035: /*@
4036:   TSResize - Runs the user-defined transfer functions provided with `TSSetResize()`

4038:   Collective

4040:   Input Parameter:
4041: . ts - The `TS` context obtained from `TSCreate()`

4043:   Level: developer

4045:   Note:
4046:   `TSResize()` is typically used within time stepping implementations,
4047:   so most users would not generally call this routine themselves.

4049: .seealso: [](ch_ts), `TS`, `TSSetResize()`
4050: @*/
4051: PetscErrorCode TSResize(TS ts)
4052: {
4053:   PetscInt     nv      = 0;
4054:   const char **names   = NULL;
4055:   Vec         *vecsin  = NULL;
4056:   const char  *solname = "ts:vec_sol";

4058:   PetscFunctionBegin;
4060:   if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS);
4061:   if (ts->resizesetup) {
4062:     PetscCall(VecLockReadPush(ts->vec_sol));
4063:     PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx));
4064:     PetscCall(VecLockReadPop(ts->vec_sol));
4065:     if (ts->stepresize) {
4066:       if (ts->resizerollback) {
4067:         PetscCall(TSRollBack(ts));
4068:         ts->time_step = ts->time_step0;
4069:       }
4070:       PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol));
4071:       PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */
4072:     }
4073:   }

4075:   PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin));
4076:   if (nv) {
4077:     Vec *vecsout, vecsol;

4079:     /* Reset internal objects */
4080:     PetscCall(TSReset(ts));

4082:     /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */
4083:     PetscCall(PetscCalloc1(nv, &vecsout));
4084:     PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout));
4085:     for (PetscInt i = 0; i < nv; i++) {
4086:       const char *name;
4087:       char       *oname;

4089:       PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
4090:       PetscCall(PetscStrallocpy(name, &oname));
4091:       PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i]));
4092:       if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname));
4093:       PetscCall(PetscFree(oname));
4094:       PetscCall(VecDestroy(&vecsout[i]));
4095:     }
4096:     PetscCall(PetscFree(vecsout));
4097:     PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */

4099:     PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol));
4100:     if (vecsol) PetscCall(TSSetSolution(ts, vecsol));
4101:     PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution");
4102:   }

4104:   PetscCall(PetscFree(names));
4105:   PetscCall(PetscFree(vecsin));
4106:   PetscCall(TSResizeReset(ts));
4107:   PetscFunctionReturn(PETSC_SUCCESS);
4108: }

4110: /*@
4111:   TSSolve - Steps the requested number of timesteps.

4113:   Collective

4115:   Input Parameters:
4116: + ts - the `TS` context obtained from `TSCreate()`
4117: - u  - the solution vector  (can be `NULL` if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used,
4118:        otherwise it must contain the initial conditions and will contain the solution at the final requested time

4120:   Level: beginner

4122:   Note:
4123:   The final time returned by this function may be different from the time of the internally
4124:   held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have
4125:   stepped over the final time.

4127: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
4128: @*/
4129: PetscErrorCode TSSolve(TS ts, Vec u)
4130: {
4131:   Vec solution;

4133:   PetscFunctionBegin;

4137:   PetscCall(TSSetExactFinalTimeDefault(ts));
4138:   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 */
4139:     if (!ts->vec_sol || u == ts->vec_sol) {
4140:       PetscCall(VecDuplicate(u, &solution));
4141:       PetscCall(TSSetSolution(ts, solution));
4142:       PetscCall(VecDestroy(&solution)); /* grant ownership */
4143:     }
4144:     PetscCall(VecCopy(u, ts->vec_sol));
4145:     PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
4146:   } else if (u) PetscCall(TSSetSolution(ts, u));
4147:   PetscCall(TSSetUp(ts));
4148:   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));

4150:   PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->run_steps != PETSC_INT_MAX || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime(), TSSetMaxSteps(), or TSSetRunSteps() or use -ts_max_time <time>, -ts_max_steps <steps>, -ts_run_steps <steps>");
4151:   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()");
4152:   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");
4153:   PetscCheck(!(ts->eval_times && ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP), PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "You must use TS_EXACTFINALTIME_MATCHSTEP when using time span or evaluation times");

4155:   if (ts->eval_times) {
4156:     if (!ts->eval_times->sol_vecs) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
4157:     for (PetscInt i = 0; i < ts->eval_times->num_time_points; i++) {
4158:       PetscBool is_close = PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[i], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0);
4159:       if (ts->ptime <= ts->eval_times->time_points[i] || is_close) {
4160:         ts->eval_times->time_point_idx = i;

4162:         PetscBool is_ptime_in_sol_times = PETSC_FALSE; // If current solution has already been saved, we should not save it again
4163:         if (ts->eval_times->sol_idx > 0) is_ptime_in_sol_times = PetscIsCloseAtTol(ts->ptime, ts->eval_times->sol_times[ts->eval_times->sol_idx - 1], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0);
4164:         if (is_close && !is_ptime_in_sol_times) {
4165:           PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx]));
4166:           ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime;
4167:           ts->eval_times->sol_idx++;
4168:           ts->eval_times->time_point_idx++;
4169:         }
4170:         break;
4171:       }
4172:     }
4173:   }

4175:   if (ts->forward_solve) PetscCall(TSForwardSetUp(ts));

4177:   /* reset number of steps only when the step is not restarted. ARKIMEX
4178:      restarts the step after an event. Resetting these counters in such case causes
4179:      TSTrajectory to incorrectly save the output files
4180:   */
4181:   /* reset time step and iteration counters */
4182:   if (!ts->steps) {
4183:     ts->ksp_its           = 0;
4184:     ts->snes_its          = 0;
4185:     ts->num_snes_failures = 0;
4186:     ts->reject            = 0;
4187:     ts->steprestart       = PETSC_TRUE;
4188:     ts->steprollback      = PETSC_FALSE;
4189:     ts->stepresize        = PETSC_FALSE;
4190:     ts->rhsjacobian.time  = PETSC_MIN_REAL;
4191:   }

4193:   /* make sure initial time step does not overshoot final time or the next point in evaluation times */
4194:   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
4195:     PetscReal maxdt;
4196:     PetscReal dt = ts->time_step;

4198:     if (ts->eval_times) maxdt = ts->eval_times->time_points[ts->eval_times->time_point_idx] - ts->ptime;
4199:     else maxdt = ts->max_time - ts->ptime;
4200:     ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
4201:   }
4202:   ts->reason = TS_CONVERGED_ITERATING;

4204:   {
4205:     PetscViewer       viewer;
4206:     PetscViewerFormat format;
4207:     PetscBool         flg;
4208:     static PetscBool  incall = PETSC_FALSE;

4210:     if (!incall) {
4211:       /* Estimate the convergence rate of the time discretization */
4212:       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
4213:       if (flg) {
4214:         PetscConvEst conv;
4215:         DM           dm;
4216:         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4217:         PetscInt     Nf;
4218:         PetscBool    checkTemporal = PETSC_TRUE;

4220:         incall = PETSC_TRUE;
4221:         PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
4222:         PetscCall(TSGetDM(ts, &dm));
4223:         PetscCall(DMGetNumFields(dm, &Nf));
4224:         PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
4225:         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
4226:         PetscCall(PetscConvEstUseTS(conv, checkTemporal));
4227:         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
4228:         PetscCall(PetscConvEstSetFromOptions(conv));
4229:         PetscCall(PetscConvEstSetUp(conv));
4230:         PetscCall(PetscConvEstGetConvRate(conv, alpha));
4231:         PetscCall(PetscViewerPushFormat(viewer, format));
4232:         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4233:         PetscCall(PetscViewerPopFormat(viewer));
4234:         PetscCall(PetscViewerDestroy(&viewer));
4235:         PetscCall(PetscConvEstDestroy(&conv));
4236:         PetscCall(PetscFree(alpha));
4237:         incall = PETSC_FALSE;
4238:       }
4239:     }
4240:   }

4242:   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre"));

4244:   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4245:     PetscUseTypeMethod(ts, solve);
4246:     if (u) PetscCall(VecCopy(ts->vec_sol, u));
4247:     ts->solvetime = ts->ptime;
4248:     solution      = ts->vec_sol;
4249:   } else { /* Step the requested number of timesteps. */
4250:     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4251:     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;

4253:     if (!ts->steps) {
4254:       PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4255:       PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
4256:     }

4258:     ts->start_step = ts->steps; // records starting step
4259:     while (!ts->reason) {
4260:       PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4261:       if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts));
4262:       PetscCall(TSStep(ts));
4263:       if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
4264:       if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
4265:       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4266:         if (ts->reason >= 0) ts->steps--;            /* Revert the step number changed by TSStep() */
4267:         PetscCall(TSForwardCostIntegral(ts));
4268:         if (ts->reason >= 0) ts->steps++;
4269:       }
4270:       if (ts->forward_solve) {            /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4271:         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4272:         PetscCall(TSForwardStep(ts));
4273:         if (ts->reason >= 0) ts->steps++;
4274:       }
4275:       PetscCall(TSPostEvaluate(ts));
4276:       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. */
4277:       if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
4278:       if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts));
4279:       /* check convergence */
4280:       if (!ts->reason) {
4281:         if ((ts->steps - ts->start_step) >= ts->run_steps) ts->reason = TS_CONVERGED_ITS;
4282:         else if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4283:         else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4284:       }
4285:       if (!ts->steprollback) {
4286:         PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4287:         PetscCall(TSPostStep(ts));
4288:         if (!ts->resizerollback) PetscCall(TSResize(ts));

4290:         if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points && ts->reason >= 0) {
4291:           PetscCheck(ts->eval_times->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(eval_times->worktol > 0) in TSSolve()");
4292:           if (PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) {
4293:             ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime;
4294:             PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx]));
4295:             ts->eval_times->sol_idx++;
4296:             ts->eval_times->time_point_idx++;
4297:           }
4298:         }
4299:       }
4300:     }
4301:     PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));

4303:     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4304:       if (!u) u = ts->vec_sol;
4305:       PetscCall(TSInterpolate(ts, ts->max_time, u));
4306:       ts->solvetime = ts->max_time;
4307:       solution      = u;
4308:       PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
4309:     } else {
4310:       if (u) PetscCall(VecCopy(ts->vec_sol, u));
4311:       ts->solvetime = ts->ptime;
4312:       solution      = ts->vec_sol;
4313:     }
4314:   }

4316:   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
4317:   PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
4318:   PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
4319:   if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
4320:   PetscFunctionReturn(PETSC_SUCCESS);
4321: }

4323: /*@
4324:   TSGetTime - Gets the time of the most recently completed step.

4326:   Not Collective

4328:   Input Parameter:
4329: . ts - the `TS` context obtained from `TSCreate()`

4331:   Output Parameter:
4332: . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`.

4334:   Level: beginner

4336:   Note:
4337:   When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`,
4338:   `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated.

4340: .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
4341: @*/
4342: PetscErrorCode TSGetTime(TS ts, PetscReal *t)
4343: {
4344:   PetscFunctionBegin;
4346:   PetscAssertPointer(t, 2);
4347:   *t = ts->ptime;
4348:   PetscFunctionReturn(PETSC_SUCCESS);
4349: }

4351: /*@
4352:   TSGetPrevTime - Gets the starting time of the previously completed step.

4354:   Not Collective

4356:   Input Parameter:
4357: . ts - the `TS` context obtained from `TSCreate()`

4359:   Output Parameter:
4360: . t - the previous time

4362:   Level: beginner

4364: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
4365: @*/
4366: PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t)
4367: {
4368:   PetscFunctionBegin;
4370:   PetscAssertPointer(t, 2);
4371:   *t = ts->ptime_prev;
4372:   PetscFunctionReturn(PETSC_SUCCESS);
4373: }

4375: /*@
4376:   TSSetTime - Allows one to reset the time.

4378:   Logically Collective

4380:   Input Parameters:
4381: + ts - the `TS` context obtained from `TSCreate()`
4382: - t  - the time

4384:   Level: intermediate

4386: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()`
4387: @*/
4388: PetscErrorCode TSSetTime(TS ts, PetscReal t)
4389: {
4390:   PetscFunctionBegin;
4393:   ts->ptime = t;
4394:   PetscFunctionReturn(PETSC_SUCCESS);
4395: }

4397: /*@
4398:   TSSetOptionsPrefix - Sets the prefix used for searching for all
4399:   TS options in the database.

4401:   Logically Collective

4403:   Input Parameters:
4404: + ts     - The `TS` context
4405: - prefix - The prefix to prepend to all option names

4407:   Level: advanced

4409:   Note:
4410:   A hyphen (-) must NOT be given at the beginning of the prefix name.
4411:   The first character of all runtime options is AUTOMATICALLY the
4412:   hyphen.

4414: .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()`
4415: @*/
4416: PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[])
4417: {
4418:   SNES snes;

4420:   PetscFunctionBegin;
4422:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
4423:   PetscCall(TSGetSNES(ts, &snes));
4424:   PetscCall(SNESSetOptionsPrefix(snes, prefix));
4425:   PetscFunctionReturn(PETSC_SUCCESS);
4426: }

4428: /*@
4429:   TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4430:   TS options in the database.

4432:   Logically Collective

4434:   Input Parameters:
4435: + ts     - The `TS` context
4436: - prefix - The prefix to prepend to all option names

4438:   Level: advanced

4440:   Note:
4441:   A hyphen (-) must NOT be given at the beginning of the prefix name.
4442:   The first character of all runtime options is AUTOMATICALLY the
4443:   hyphen.

4445: .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()`
4446: @*/
4447: PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[])
4448: {
4449:   SNES snes;

4451:   PetscFunctionBegin;
4453:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
4454:   PetscCall(TSGetSNES(ts, &snes));
4455:   PetscCall(SNESAppendOptionsPrefix(snes, prefix));
4456:   PetscFunctionReturn(PETSC_SUCCESS);
4457: }

4459: /*@
4460:   TSGetOptionsPrefix - Sets the prefix used for searching for all
4461:   `TS` options in the database.

4463:   Not Collective

4465:   Input Parameter:
4466: . ts - The `TS` context

4468:   Output Parameter:
4469: . prefix - A pointer to the prefix string used

4471:   Level: intermediate

4473: .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
4474: @*/
4475: PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
4476: {
4477:   PetscFunctionBegin;
4479:   PetscAssertPointer(prefix, 2);
4480:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
4481:   PetscFunctionReturn(PETSC_SUCCESS);
4482: }

4484: /*@C
4485:   TSGetRHSJacobian - Returns the Jacobian J at the present timestep.

4487:   Not Collective, but parallel objects are returned if ts is parallel

4489:   Input Parameter:
4490: . ts - The `TS` context obtained from `TSCreate()`

4492:   Output Parameters:
4493: + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or `NULL`)
4494: . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat`  (or `NULL`)
4495: . func - Function to compute the Jacobian of the RHS  (or `NULL`)
4496: - ctx  - User-defined context for Jacobian evaluation routine  (or `NULL`)

4498:   Level: intermediate

4500:   Note:
4501:   You can pass in `NULL` for any return argument you do not need.

4503: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4504: @*/
4505: PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, PetscCtxRt ctx)
4506: {
4507:   DM dm;

4509:   PetscFunctionBegin;
4510:   if (Amat || Pmat) {
4511:     SNES snes;
4512:     PetscCall(TSGetSNES(ts, &snes));
4513:     PetscCall(SNESSetUpMatrices(snes));
4514:     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4515:   }
4516:   PetscCall(TSGetDM(ts, &dm));
4517:   PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
4518:   PetscFunctionReturn(PETSC_SUCCESS);
4519: }

4521: /*@C
4522:   TSGetIJacobian - Returns the implicit Jacobian at the present timestep.

4524:   Not Collective, but parallel objects are returned if ts is parallel

4526:   Input Parameter:
4527: . ts - The `TS` context obtained from `TSCreate()`

4529:   Output Parameters:
4530: + Amat - The (approximate) Jacobian of F(t,U,U_t)
4531: . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat`
4532: . f    - The function to compute the matrices
4533: - ctx  - User-defined context for Jacobian evaluation routine

4535:   Level: advanced

4537:   Note:
4538:   You can pass in `NULL` for any return argument you do not need.

4540: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4541: @*/
4542: PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, PetscCtxRt ctx)
4543: {
4544:   DM dm;

4546:   PetscFunctionBegin;
4547:   if (Amat || Pmat) {
4548:     SNES snes;
4549:     PetscCall(TSGetSNES(ts, &snes));
4550:     PetscCall(SNESSetUpMatrices(snes));
4551:     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4552:   }
4553:   PetscCall(TSGetDM(ts, &dm));
4554:   PetscCall(DMTSGetIJacobian(dm, f, ctx));
4555:   PetscFunctionReturn(PETSC_SUCCESS);
4556: }

4558: #include <petsc/private/dmimpl.h>
4559: /*@
4560:   TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS`

4562:   Logically Collective

4564:   Input Parameters:
4565: + ts - the `TS` integrator object
4566: - dm - the dm, cannot be `NULL`

4568:   Level: intermediate

4570:   Notes:
4571:   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
4572:   even when not using interfaces like `DMTSSetIFunction()`.  Use `DMClone()` to get a distinct `DM` when solving
4573:   different problems using the same function space.

4575: .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4576: @*/
4577: PetscErrorCode TSSetDM(TS ts, DM dm)
4578: {
4579:   SNES snes;
4580:   DMTS tsdm;

4582:   PetscFunctionBegin;
4585:   PetscCall(PetscObjectReference((PetscObject)dm));
4586:   if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4587:     if (ts->dm->dmts && !dm->dmts) {
4588:       PetscCall(DMCopyDMTS(ts->dm, dm));
4589:       PetscCall(DMGetDMTS(ts->dm, &tsdm));
4590:       /* Grant write privileges to the replacement DM */
4591:       if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4592:     }
4593:     PetscCall(DMDestroy(&ts->dm));
4594:   }
4595:   ts->dm = dm;

4597:   PetscCall(TSGetSNES(ts, &snes));
4598:   PetscCall(SNESSetDM(snes, dm));
4599:   PetscFunctionReturn(PETSC_SUCCESS);
4600: }

4602: /*@
4603:   TSGetDM - Gets the `DM` that may be used by some preconditioners

4605:   Not Collective

4607:   Input Parameter:
4608: . ts - the `TS`

4610:   Output Parameter:
4611: . dm - the `DM`

4613:   Level: intermediate

4615: .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4616: @*/
4617: PetscErrorCode TSGetDM(TS ts, DM *dm)
4618: {
4619:   PetscFunctionBegin;
4621:   if (!ts->dm) {
4622:     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4623:     if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4624:   }
4625:   *dm = ts->dm;
4626:   PetscFunctionReturn(PETSC_SUCCESS);
4627: }

4629: /*@
4630:   SNESTSFormFunction - Function to evaluate nonlinear residual defined by an ODE solver algorithm implemented within `TS`

4632:   Logically Collective

4634:   Input Parameters:
4635: + snes - nonlinear solver
4636: . U    - the current state at which to evaluate the residual
4637: - ctx  - user context, must be a `TS`

4639:   Output Parameter:
4640: . F - the nonlinear residual

4642:   Level: developer

4644:   Note:
4645:   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4646:   It is most frequently passed to `MatFDColoringSetFunction()`.

4648: .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
4649: @*/
4650: PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, PetscCtx ctx)
4651: {
4652:   TS ts = (TS)ctx;

4654:   PetscFunctionBegin;
4659:   PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
4660:   PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
4661:   PetscFunctionReturn(PETSC_SUCCESS);
4662: }

4664: /*@
4665:   SNESTSFormJacobian - Function to evaluate the Jacobian defined by an ODE solver algorithm implemented within `TS`

4667:   Collective

4669:   Input Parameters:
4670: + snes - nonlinear solver
4671: . U    - the current state at which to evaluate the residual
4672: - ctx  - user context, must be a `TS`

4674:   Output Parameters:
4675: + A - the Jacobian
4676: - B - the matrix used to construct the preconditioner (often the same as `A`)

4678:   Level: developer

4680:   Note:
4681:   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.

4683: .seealso: [](ch_ts), `SNESSetJacobian()`
4684: @*/
4685: PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, PetscCtx ctx)
4686: {
4687:   TS ts = (TS)ctx;

4689:   PetscFunctionBegin;
4695:   PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
4696:   PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
4697:   PetscFunctionReturn(PETSC_SUCCESS);
4698: }

4700: /*@C
4701:   TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only

4703:   Collective

4705:   Input Parameters:
4706: + ts  - time stepping context
4707: . t   - time at which to evaluate
4708: . U   - state at which to evaluate
4709: - ctx - context

4711:   Output Parameter:
4712: . F - right-hand side

4714:   Level: intermediate

4716:   Note:
4717:   This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems.
4718:   The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`.

4720: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4721: @*/
4722: PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, PetscCtx ctx)
4723: {
4724:   Mat Arhs, Brhs;

4726:   PetscFunctionBegin;
4727:   PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4728:   /* undo the damage caused by shifting */
4729:   PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4730:   PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4731:   PetscCall(MatMult(Arhs, U, F));
4732:   PetscFunctionReturn(PETSC_SUCCESS);
4733: }

4735: /*@C
4736:   TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.

4738:   Collective

4740:   Input Parameters:
4741: + ts  - time stepping context
4742: . t   - time at which to evaluate
4743: . U   - state at which to evaluate
4744: - ctx - context

4746:   Output Parameters:
4747: + A - Jacobian
4748: - B - matrix used to construct the preconditioner, often the same as `A`

4750:   Level: intermediate

4752:   Note:
4753:   This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems.

4755: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4756: @*/
4757: PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, PetscCtx ctx)
4758: {
4759:   PetscFunctionBegin;
4760:   PetscFunctionReturn(PETSC_SUCCESS);
4761: }

4763: /*@C
4764:   TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only

4766:   Collective

4768:   Input Parameters:
4769: + ts   - time stepping context
4770: . t    - time at which to evaluate
4771: . U    - state at which to evaluate
4772: . Udot - time derivative of state vector
4773: - ctx  - context

4775:   Output Parameter:
4776: . F - left hand side

4778:   Level: intermediate

4780:   Notes:
4781:   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
4782:   user is required to write their own `TSComputeIFunction()`.
4783:   This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems.
4784:   The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`.

4786:   Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U

4788: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4789: @*/
4790: PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, PetscCtx ctx)
4791: {
4792:   Mat A, B;

4794:   PetscFunctionBegin;
4795:   PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4796:   PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4797:   PetscCall(MatMult(A, Udot, F));
4798:   PetscFunctionReturn(PETSC_SUCCESS);
4799: }

4801: /*@C
4802:   TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE

4804:   Collective

4806:   Input Parameters:
4807: + ts    - time stepping context
4808: . t     - time at which to evaluate
4809: . U     - state at which to evaluate
4810: . Udot  - time derivative of state vector
4811: . shift - shift to apply
4812: - ctx   - context

4814:   Output Parameters:
4815: + A - pointer to operator
4816: - B - pointer to matrix from which the preconditioner is built (often `A`)

4818:   Level: advanced

4820:   Notes:
4821:   This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems.

4823:   It is only appropriate for problems of the form

4825:   $$
4826:   M \dot{U} = F(U,t)
4827:   $$

4829:   where M is constant and F is non-stiff.  The user must pass M to `TSSetIJacobian()`.  The current implementation only
4830:   works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing
4831:   an implicit operator of the form

4833:   $$
4834:   shift*M + J
4835:   $$

4837:   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
4838:   a copy of M or reassemble it when requested.

4840: .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4841: @*/
4842: PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscCtx ctx)
4843: {
4844:   PetscFunctionBegin;
4845:   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4846:   ts->ijacobian.shift = shift;
4847:   PetscFunctionReturn(PETSC_SUCCESS);
4848: }

4850: /*@
4851:   TSGetEquationType - Gets the type of the equation that `TS` is solving.

4853:   Not Collective

4855:   Input Parameter:
4856: . ts - the `TS` context

4858:   Output Parameter:
4859: . equation_type - see `TSEquationType`

4861:   Level: beginner

4863: .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
4864: @*/
4865: PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
4866: {
4867:   PetscFunctionBegin;
4869:   PetscAssertPointer(equation_type, 2);
4870:   *equation_type = ts->equation_type;
4871:   PetscFunctionReturn(PETSC_SUCCESS);
4872: }

4874: /*@
4875:   TSSetEquationType - Sets the type of the equation that `TS` is solving.

4877:   Not Collective

4879:   Input Parameters:
4880: + ts            - the `TS` context
4881: - equation_type - see `TSEquationType`

4883:   Level: advanced

4885: .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
4886: @*/
4887: PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
4888: {
4889:   PetscFunctionBegin;
4891:   ts->equation_type = equation_type;
4892:   PetscFunctionReturn(PETSC_SUCCESS);
4893: }

4895: /*@
4896:   TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.

4898:   Not Collective

4900:   Input Parameter:
4901: . ts - the `TS` context

4903:   Output Parameter:
4904: . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4905:             manual pages for the individual convergence tests for complete lists

4907:   Level: beginner

4909:   Note:
4910:   Can only be called after the call to `TSSolve()` is complete.

4912: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4913: @*/
4914: PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
4915: {
4916:   PetscFunctionBegin;
4918:   PetscAssertPointer(reason, 2);
4919:   *reason = ts->reason;
4920:   PetscFunctionReturn(PETSC_SUCCESS);
4921: }

4923: /*@
4924:   TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`.

4926:   Logically Collective; reason must contain common value

4928:   Input Parameters:
4929: + ts     - the `TS` context
4930: - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4931:             manual pages for the individual convergence tests for complete lists

4933:   Level: advanced

4935:   Note:
4936:   Can only be called while `TSSolve()` is active.

4938: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4939: @*/
4940: PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
4941: {
4942:   PetscFunctionBegin;
4944:   ts->reason = reason;
4945:   PetscFunctionReturn(PETSC_SUCCESS);
4946: }

4948: /*@
4949:   TSGetSolveTime - Gets the time after a call to `TSSolve()`

4951:   Not Collective

4953:   Input Parameter:
4954: . ts - the `TS` context

4956:   Output Parameter:
4957: . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()`

4959:   Level: beginner

4961:   Note:
4962:   Can only be called after the call to `TSSolve()` is complete.

4964: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4965: @*/
4966: PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
4967: {
4968:   PetscFunctionBegin;
4970:   PetscAssertPointer(ftime, 2);
4971:   *ftime = ts->solvetime;
4972:   PetscFunctionReturn(PETSC_SUCCESS);
4973: }

4975: /*@
4976:   TSGetSNESIterations - Gets the total number of nonlinear iterations
4977:   used by the time integrator.

4979:   Not Collective

4981:   Input Parameter:
4982: . ts - `TS` context

4984:   Output Parameter:
4985: . nits - number of nonlinear iterations

4987:   Level: intermediate

4989:   Note:
4990:   This counter is reset to zero for each successive call to `TSSolve()`.

4992: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
4993: @*/
4994: PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
4995: {
4996:   PetscFunctionBegin;
4998:   PetscAssertPointer(nits, 2);
4999:   *nits = ts->snes_its;
5000:   PetscFunctionReturn(PETSC_SUCCESS);
5001: }

5003: /*@
5004:   TSGetKSPIterations - Gets the total number of linear iterations
5005:   used by the time integrator.

5007:   Not Collective

5009:   Input Parameter:
5010: . ts - `TS` context

5012:   Output Parameter:
5013: . lits - number of linear iterations

5015:   Level: intermediate

5017:   Note:
5018:   This counter is reset to zero for each successive call to `TSSolve()`.

5020: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`
5021: @*/
5022: PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
5023: {
5024:   PetscFunctionBegin;
5026:   PetscAssertPointer(lits, 2);
5027:   *lits = ts->ksp_its;
5028:   PetscFunctionReturn(PETSC_SUCCESS);
5029: }

5031: /*@
5032:   TSGetStepRejections - Gets the total number of rejected steps.

5034:   Not Collective

5036:   Input Parameter:
5037: . ts - `TS` context

5039:   Output Parameter:
5040: . rejects - number of steps rejected

5042:   Level: intermediate

5044:   Note:
5045:   This counter is reset to zero for each successive call to `TSSolve()`.

5047: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
5048: @*/
5049: PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
5050: {
5051:   PetscFunctionBegin;
5053:   PetscAssertPointer(rejects, 2);
5054:   *rejects = ts->reject;
5055:   PetscFunctionReturn(PETSC_SUCCESS);
5056: }

5058: /*@
5059:   TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS`

5061:   Not Collective

5063:   Input Parameter:
5064: . ts - `TS` context

5066:   Output Parameter:
5067: . fails - number of failed nonlinear solves

5069:   Level: intermediate

5071:   Note:
5072:   This counter is reset to zero for each successive call to `TSSolve()`.

5074: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
5075: @*/
5076: PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
5077: {
5078:   PetscFunctionBegin;
5080:   PetscAssertPointer(fails, 2);
5081:   *fails = ts->num_snes_failures;
5082:   PetscFunctionReturn(PETSC_SUCCESS);
5083: }

5085: /*@
5086:   TSSetMaxStepRejections - Sets the maximum number of step rejections allowed in a single time-step attempt before a time step fails in `TSSolve()` with `TS_DIVERGED_STEP_REJECTED`

5088:   Not Collective

5090:   Input Parameters:
5091: + ts      - `TS` context
5092: - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited

5094:   Options Database Key:
5095: . -ts_max_step_rejections - Maximum number of step rejections before a step fails

5097:   Level: intermediate

5099:   Developer Note:
5100:   The options database name is incorrect.

5102: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`,
5103:           `TSGetConvergedReason()`, `TSSolve()`, `TS_DIVERGED_STEP_REJECTED`
5104: @*/
5105: PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
5106: {
5107:   PetscFunctionBegin;
5109:   if (rejects == PETSC_UNLIMITED || rejects == -1) {
5110:     ts->max_reject = PETSC_UNLIMITED;
5111:   } else {
5112:     PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
5113:     ts->max_reject = rejects;
5114:   }
5115:   PetscFunctionReturn(PETSC_SUCCESS);
5116: }

5118: /*@
5119:   TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves allowed before `TSSolve()` is ended with a `TSConvergedReason` of `TS_DIVERGED_NONLINEAR_SOLVE`

5121:   Not Collective

5123:   Input Parameters:
5124: + ts    - `TS` context
5125: - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures.

5127:   Options Database Key:
5128: . -ts_max_snes_failures - Maximum number of nonlinear solve failures

5130:   Level: intermediate

5132: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`,
5133:           `TSGetConvergedReason()`, `TS_DIVERGED_NONLINEAR_SOLVE`, `TSConvergedReason`
5134: @*/
5135: PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
5136: {
5137:   PetscFunctionBegin;
5139:   if (fails == PETSC_UNLIMITED || fails == -1) {
5140:     ts->max_snes_failures = PETSC_UNLIMITED;
5141:   } else {
5142:     PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
5143:     ts->max_snes_failures = fails;
5144:   }
5145:   PetscFunctionReturn(PETSC_SUCCESS);
5146: }

5148: /*@
5149:   TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()`

5151:   Not Collective

5153:   Input Parameters:
5154: + ts  - `TS` context
5155: - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure

5157:   Options Database Key:
5158: . -ts_error_if_step_fails - Error if no step succeeds

5160:   Level: intermediate

5162: .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
5163: @*/
5164: PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
5165: {
5166:   PetscFunctionBegin;
5168:   ts->errorifstepfailed = err;
5169:   PetscFunctionReturn(PETSC_SUCCESS);
5170: }

5172: /*@
5173:   TSGetAdapt - Get the adaptive controller context for the current method

5175:   Collective if controller has not yet been created

5177:   Input Parameter:
5178: . ts - time stepping context

5180:   Output Parameter:
5181: . adapt - adaptive controller

5183:   Level: intermediate

5185: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
5186: @*/
5187: PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
5188: {
5189:   PetscFunctionBegin;
5191:   PetscAssertPointer(adapt, 2);
5192:   if (!ts->adapt) {
5193:     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
5194:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
5195:   }
5196:   *adapt = ts->adapt;
5197:   PetscFunctionReturn(PETSC_SUCCESS);
5198: }

5200: /*@
5201:   TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller

5203:   Logically Collective

5205:   Input Parameters:
5206: + ts    - time integration context
5207: . atol  - scalar absolute tolerances
5208: . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
5209: . rtol  - scalar relative tolerances
5210: - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present

5212:   Options Database Keys:
5213: + -ts_rtol rtol - relative tolerance for local truncation error
5214: - -ts_atol atol - Absolute tolerance for local truncation error

5216:   Level: beginner

5218:   Notes:
5219:   `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value
5220:   or the default value from when the object's type was set.

5222:   With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5223:   (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5224:   computed only for the differential or the algebraic part then this can be done using the vector of
5225:   tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5226:   differential part and infinity for the algebraic part, the LTE calculation will include only the
5227:   differential variables.

5229:   Fortran Note:
5230:   Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.

5232: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
5233: @*/
5234: PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
5235: {
5236:   PetscFunctionBegin;
5237:   if (atol == (PetscReal)PETSC_DETERMINE) {
5238:     ts->atol = ts->default_atol;
5239:   } else if (atol != (PetscReal)PETSC_CURRENT) {
5240:     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
5241:     ts->atol = atol;
5242:   }

5244:   if (vatol) {
5245:     PetscCall(PetscObjectReference((PetscObject)vatol));
5246:     PetscCall(VecDestroy(&ts->vatol));
5247:     ts->vatol = vatol;
5248:   }

5250:   if (rtol == (PetscReal)PETSC_DETERMINE) {
5251:     ts->rtol = ts->default_rtol;
5252:   } else if (rtol != (PetscReal)PETSC_CURRENT) {
5253:     PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
5254:     ts->rtol = rtol;
5255:   }

5257:   if (vrtol) {
5258:     PetscCall(PetscObjectReference((PetscObject)vrtol));
5259:     PetscCall(VecDestroy(&ts->vrtol));
5260:     ts->vrtol = vrtol;
5261:   }
5262:   PetscFunctionReturn(PETSC_SUCCESS);
5263: }

5265: /*@
5266:   TSGetTolerances - Get tolerances for local truncation error when using adaptive controller

5268:   Logically Collective

5270:   Input Parameter:
5271: . ts - time integration context

5273:   Output Parameters:
5274: + atol  - scalar absolute tolerances, `NULL` to ignore
5275: . vatol - vector of absolute tolerances, `NULL` to ignore
5276: . rtol  - scalar relative tolerances, `NULL` to ignore
5277: - vrtol - vector of relative tolerances, `NULL` to ignore

5279:   Level: beginner

5281: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
5282: @*/
5283: PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
5284: {
5285:   PetscFunctionBegin;
5286:   if (atol) *atol = ts->atol;
5287:   if (vatol) *vatol = ts->vatol;
5288:   if (rtol) *rtol = ts->rtol;
5289:   if (vrtol) *vrtol = ts->vrtol;
5290:   PetscFunctionReturn(PETSC_SUCCESS);
5291: }

5293: /*@
5294:   TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances

5296:   Collective

5298:   Input Parameters:
5299: + ts        - time stepping context
5300: . U         - state vector, usually ts->vec_sol
5301: . Y         - state vector to be compared to U
5302: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

5304:   Output Parameters:
5305: + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5306: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5307: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user

5309:   Options Database Key:
5310: . -ts_adapt_wnormtype wnormtype - 2, INFINITY

5312:   Level: developer

5314: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
5315: @*/
5316: PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5317: {
5318:   PetscInt norma_loc, norm_loc, normr_loc;

5320:   PetscFunctionBegin;
5325:   PetscAssertPointer(norm, 5);
5326:   PetscAssertPointer(norma, 6);
5327:   PetscAssertPointer(normr, 7);
5328:   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));
5329:   if (wnormtype == NORM_2) {
5330:     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5331:     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5332:     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5333:   }
5334:   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5335:   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5336:   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5337:   PetscFunctionReturn(PETSC_SUCCESS);
5338: }

5340: /*@
5341:   TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances

5343:   Collective

5345:   Input Parameters:
5346: + ts        - time stepping context
5347: . E         - error vector
5348: . U         - state vector, usually ts->vec_sol
5349: . Y         - state vector, previous time step
5350: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

5352:   Output Parameters:
5353: + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5354: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5355: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user

5357:   Options Database Key:
5358: . -ts_adapt_wnormtype wnormtype - 2, INFINITY

5360:   Level: developer

5362: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
5363: @*/
5364: PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5365: {
5366:   PetscInt norma_loc, norm_loc, normr_loc;

5368:   PetscFunctionBegin;
5370:   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));
5371:   if (wnormtype == NORM_2) {
5372:     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5373:     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5374:     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5375:   }
5376:   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5377:   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5378:   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5379:   PetscFunctionReturn(PETSC_SUCCESS);
5380: }

5382: /*@
5383:   TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler

5385:   Logically Collective

5387:   Input Parameters:
5388: + ts      - time stepping context
5389: - cfltime - maximum stable time step if using forward Euler (value can be different on each process)

5391:   Note:
5392:   After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()

5394:   Level: intermediate

5396: .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
5397: @*/
5398: PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
5399: {
5400:   PetscFunctionBegin;
5402:   ts->cfltime_local = cfltime;
5403:   ts->cfltime       = -1.;
5404:   PetscFunctionReturn(PETSC_SUCCESS);
5405: }

5407: /*@
5408:   TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler

5410:   Collective

5412:   Input Parameter:
5413: . ts - time stepping context

5415:   Output Parameter:
5416: . cfltime - maximum stable time step for forward Euler

5418:   Level: advanced

5420: .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
5421: @*/
5422: PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
5423: {
5424:   PetscFunctionBegin;
5425:   if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5426:   *cfltime = ts->cfltime;
5427:   PetscFunctionReturn(PETSC_SUCCESS);
5428: }

5430: /*@
5431:   TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu

5433:   Input Parameters:
5434: + ts - the `TS` context.
5435: . xl - lower bound.
5436: - xu - upper bound.

5438:   Level: advanced

5440:   Note:
5441:   If this routine is not called then the lower and upper bounds are set to
5442:   `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`.

5444: .seealso: [](ch_ts), `TS`
5445: @*/
5446: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5447: {
5448:   SNES snes;

5450:   PetscFunctionBegin;
5451:   PetscCall(TSGetSNES(ts, &snes));
5452:   PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5453:   PetscFunctionReturn(PETSC_SUCCESS);
5454: }

5456: /*@
5457:   TSComputeLinearStability - computes the linear stability function at a point

5459:   Collective

5461:   Input Parameters:
5462: + ts - the `TS` context
5463: . xr - real part of input argument
5464: - xi - imaginary part of input argument

5466:   Output Parameters:
5467: + yr - real part of function value
5468: - yi - imaginary part of function value

5470:   Level: developer

5472: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
5473: @*/
5474: PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
5475: {
5476:   PetscFunctionBegin;
5478:   PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5479:   PetscFunctionReturn(PETSC_SUCCESS);
5480: }

5482: /*@
5483:   TSRestartStep - Flags the solver to restart the next step

5485:   Collective

5487:   Input Parameter:
5488: . ts - the `TS` context obtained from `TSCreate()`

5490:   Level: advanced

5492:   Notes:
5493:   Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5494:   discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5495:   vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5496:   the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
5497:   discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5498:   discontinuous source terms).

5500: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5501: @*/
5502: PetscErrorCode TSRestartStep(TS ts)
5503: {
5504:   PetscFunctionBegin;
5506:   ts->steprestart = PETSC_TRUE;
5507:   PetscFunctionReturn(PETSC_SUCCESS);
5508: }

5510: /*@
5511:   TSRollBack - Rolls back one time step

5513:   Collective

5515:   Input Parameter:
5516: . ts - the `TS` context obtained from `TSCreate()`

5518:   Level: advanced

5520: .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5521: @*/
5522: PetscErrorCode TSRollBack(TS ts)
5523: {
5524:   PetscFunctionBegin;
5526:   PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5527:   PetscTryTypeMethod(ts, rollback);
5528:   PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
5529:   ts->time_step  = ts->ptime - ts->ptime_prev;
5530:   ts->ptime      = ts->ptime_prev;
5531:   ts->ptime_prev = ts->ptime_prev_rollback;
5532:   ts->steps--;
5533:   ts->steprollback = PETSC_TRUE;
5534:   PetscFunctionReturn(PETSC_SUCCESS);
5535: }

5537: /*@
5538:   TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step

5540:   Not collective

5542:   Input Parameter:
5543: . ts - the `TS` context obtained from `TSCreate()`

5545:   Output Parameter:
5546: . flg - the rollback flag

5548:   Level: advanced

5550: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
5551: @*/
5552: PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
5553: {
5554:   PetscFunctionBegin;
5556:   PetscAssertPointer(flg, 2);
5557:   *flg = ts->steprollback;
5558:   PetscFunctionReturn(PETSC_SUCCESS);
5559: }

5561: /*@
5562:   TSGetStepResize - Get the internal flag indicating if the current step is after a resize.

5564:   Not collective

5566:   Input Parameter:
5567: . ts - the `TS` context obtained from `TSCreate()`

5569:   Output Parameter:
5570: . flg - the resize flag

5572:   Level: advanced

5574: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
5575: @*/
5576: PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
5577: {
5578:   PetscFunctionBegin;
5580:   PetscAssertPointer(flg, 2);
5581:   *flg = ts->stepresize;
5582:   PetscFunctionReturn(PETSC_SUCCESS);
5583: }

5585: /*@
5586:   TSGetStages - Get the number of stages and stage values

5588:   Input Parameter:
5589: . ts - the `TS` context obtained from `TSCreate()`

5591:   Output Parameters:
5592: + ns - the number of stages
5593: - Y  - the current stage vectors

5595:   Level: advanced

5597:   Note:
5598:   Both `ns` and `Y` can be `NULL`.

5600: .seealso: [](ch_ts), `TS`, `TSCreate()`
5601: @*/
5602: PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
5603: {
5604:   PetscFunctionBegin;
5606:   if (ns) PetscAssertPointer(ns, 2);
5607:   if (Y) PetscAssertPointer(Y, 3);
5608:   if (!ts->ops->getstages) {
5609:     if (ns) *ns = 0;
5610:     if (Y) *Y = NULL;
5611:   } else PetscUseTypeMethod(ts, getstages, ns, Y);
5612:   PetscFunctionReturn(PETSC_SUCCESS);
5613: }

5615: /*@C
5616:   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.

5618:   Collective

5620:   Input Parameters:
5621: + ts    - the `TS` context
5622: . t     - current timestep
5623: . U     - state vector
5624: . Udot  - time derivative of state vector
5625: . shift - shift to apply, see note below
5626: - ctx   - an optional user context

5628:   Output Parameters:
5629: + J - Jacobian matrix (not altered in this routine)
5630: - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)

5632:   Level: intermediate

5634:   Notes:
5635:   If F(t,U,Udot)=0 is the DAE, the required Jacobian is

5637:   dF/dU + shift*dF/dUdot

5639:   Most users should not need to explicitly call this routine, as it
5640:   is used internally within the nonlinear solvers.

5642:   This will first try to get the coloring from the `DM`.  If the `DM` type has no coloring
5643:   routine, then it will try to get the coloring from the matrix.  This requires that the
5644:   matrix have nonzero entries precomputed.

5646: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5647: @*/
5648: PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, PetscCtx ctx)
5649: {
5650:   SNES          snes;
5651:   MatFDColoring color;
5652:   PetscBool     hascolor, matcolor = PETSC_FALSE;

5654:   PetscFunctionBegin;
5655:   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5656:   PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5657:   if (!color) {
5658:     DM         dm;
5659:     ISColoring iscoloring;

5661:     PetscCall(TSGetDM(ts, &dm));
5662:     PetscCall(DMHasColoring(dm, &hascolor));
5663:     if (hascolor && !matcolor) {
5664:       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5665:       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5666:       PetscCall(MatFDColoringSetFunction(color, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
5667:       PetscCall(MatFDColoringSetFromOptions(color));
5668:       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5669:       PetscCall(ISColoringDestroy(&iscoloring));
5670:     } else {
5671:       MatColoring mc;

5673:       PetscCall(MatColoringCreate(B, &mc));
5674:       PetscCall(MatColoringSetDistance(mc, 2));
5675:       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5676:       PetscCall(MatColoringSetFromOptions(mc));
5677:       PetscCall(MatColoringApply(mc, &iscoloring));
5678:       PetscCall(MatColoringDestroy(&mc));
5679:       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5680:       PetscCall(MatFDColoringSetFunction(color, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
5681:       PetscCall(MatFDColoringSetFromOptions(color));
5682:       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5683:       PetscCall(ISColoringDestroy(&iscoloring));
5684:     }
5685:     PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5686:     PetscCall(PetscObjectDereference((PetscObject)color));
5687:   }
5688:   PetscCall(TSGetSNES(ts, &snes));
5689:   PetscCall(MatFDColoringApply(B, color, U, snes));
5690:   if (J != B) {
5691:     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5692:     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5693:   }
5694:   PetscFunctionReturn(PETSC_SUCCESS);
5695: }

5697: /*@C
5698:   TSSetFunctionDomainError - Set a function that tests if the current state vector is valid

5700:   Logically collective

5702:   Input Parameters:
5703: + ts   - the `TS` context
5704: - func - function called within `TSFunctionDomainError()`

5706:   Calling sequence of `func`:
5707: + ts     - the `TS` context
5708: . time   - the current time (of the stage)
5709: . state  - the state to check if it is valid
5710: - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable

5712:   Level: intermediate

5714:   Notes:
5715:   `accept` must be collectively specified.
5716:   If an implicit ODE solver is being used then, in addition to providing this routine, the
5717:   user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
5718:   function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
5719:   Use `TSGetSNES()` to obtain the `SNES` object

5721:   Developer Notes:
5722:   The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
5723:   since one takes a function pointer and the other does not.

5725: .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5726: @*/
5727: PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
5728: {
5729:   PetscFunctionBegin;
5731:   ts->functiondomainerror = func;
5732:   PetscFunctionReturn(PETSC_SUCCESS);
5733: }

5735: /*@
5736:   TSFunctionDomainError - Checks if the current state is valid

5738:   Collective

5740:   Input Parameters:
5741: + ts        - the `TS` context
5742: . stagetime - time of the simulation
5743: - Y         - state vector to check.

5745:   Output Parameter:
5746: . accept - Set to `PETSC_FALSE` if the current state vector is valid.

5748:   Level: developer

5750:   Note:
5751:   This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
5752:   to check if the current state is valid.

5754: .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
5755: @*/
5756: PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
5757: {
5758:   PetscFunctionBegin;
5762:   PetscAssertPointer(accept, 4);
5763:   *accept = PETSC_TRUE;
5764:   if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5765:   PetscFunctionReturn(PETSC_SUCCESS);
5766: }

5768: /*@
5769:   TSClone - This function clones a time step `TS` object.

5771:   Collective

5773:   Input Parameter:
5774: . tsin - The input `TS`

5776:   Output Parameter:
5777: . tsout - The output `TS` (cloned)

5779:   Level: developer

5781:   Notes:
5782:   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.
5783:   It will likely be replaced in the future with a mechanism of switching methods on the fly.

5785:   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
5786: .vb
5787:  SNES snes_dup = NULL;
5788:  TSGetSNES(ts,&snes_dup);
5789:  TSSetSNES(ts,snes_dup);
5790: .ve

5792: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5793: @*/
5794: PetscErrorCode TSClone(TS tsin, TS *tsout)
5795: {
5796:   TS     t;
5797:   SNES   snes_start;
5798:   DM     dm;
5799:   TSType type;

5801:   PetscFunctionBegin;
5802:   PetscAssertPointer(tsin, 1);
5803:   *tsout = NULL;

5805:   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));

5807:   /* General TS description */
5808:   t->numbermonitors    = 0;
5809:   t->setupcalled       = PETSC_FALSE;
5810:   t->ksp_its           = 0;
5811:   t->snes_its          = 0;
5812:   t->nwork             = 0;
5813:   t->rhsjacobian.time  = PETSC_MIN_REAL;
5814:   t->rhsjacobian.scale = 1.;
5815:   t->ijacobian.shift   = 1.;

5817:   PetscCall(TSGetSNES(tsin, &snes_start));
5818:   PetscCall(TSSetSNES(t, snes_start));

5820:   PetscCall(TSGetDM(tsin, &dm));
5821:   PetscCall(TSSetDM(t, dm));

5823:   t->adapt = tsin->adapt;
5824:   PetscCall(PetscObjectReference((PetscObject)t->adapt));

5826:   t->trajectory = tsin->trajectory;
5827:   PetscCall(PetscObjectReference((PetscObject)t->trajectory));

5829:   t->event = tsin->event;
5830:   if (t->event) t->event->refct++;

5832:   t->problem_type      = tsin->problem_type;
5833:   t->ptime             = tsin->ptime;
5834:   t->ptime_prev        = tsin->ptime_prev;
5835:   t->time_step         = tsin->time_step;
5836:   t->max_time          = tsin->max_time;
5837:   t->steps             = tsin->steps;
5838:   t->max_steps         = tsin->max_steps;
5839:   t->equation_type     = tsin->equation_type;
5840:   t->atol              = tsin->atol;
5841:   t->rtol              = tsin->rtol;
5842:   t->max_snes_failures = tsin->max_snes_failures;
5843:   t->max_reject        = tsin->max_reject;
5844:   t->errorifstepfailed = tsin->errorifstepfailed;

5846:   PetscCall(TSGetType(tsin, &type));
5847:   PetscCall(TSSetType(t, type));

5849:   t->vec_sol = NULL;

5851:   t->cfltime          = tsin->cfltime;
5852:   t->cfltime_local    = tsin->cfltime_local;
5853:   t->exact_final_time = tsin->exact_final_time;

5855:   t->ops[0] = tsin->ops[0];

5857:   if (((PetscObject)tsin)->fortran_func_pointers) {
5858:     PetscCall(PetscMalloc((10) * sizeof(PetscFortranCallbackFn *), &((PetscObject)t)->fortran_func_pointers));
5859:     for (PetscInt i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5860:   }
5861:   *tsout = t;
5862:   PetscFunctionReturn(PETSC_SUCCESS);
5863: }

5865: static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(PetscCtx ctx, Vec x, Vec y)
5866: {
5867:   TS ts = (TS)ctx;

5869:   PetscFunctionBegin;
5870:   PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5871:   PetscFunctionReturn(PETSC_SUCCESS);
5872: }

5874: /*@
5875:   TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.

5877:   Logically Collective

5879:   Input Parameter:
5880: . ts - the time stepping routine

5882:   Output Parameter:
5883: . flg - `PETSC_TRUE` if the multiply is likely correct

5885:   Options Database Key:
5886: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator

5888:   Level: advanced

5890:   Note:
5891:   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian

5893: .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5894: @*/
5895: PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
5896: {
5897:   Mat              J, B;
5898:   TSRHSJacobianFn *func;
5899:   void            *ctx;

5901:   PetscFunctionBegin;
5902:   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5903:   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5904:   PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5905:   PetscFunctionReturn(PETSC_SUCCESS);
5906: }

5908: /*@
5909:   TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.

5911:   Logically Collective

5913:   Input Parameter:
5914: . ts - the time stepping routine

5916:   Output Parameter:
5917: . flg - `PETSC_TRUE` if the multiply is likely correct

5919:   Options Database Key:
5920: . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator

5922:   Level: advanced

5924:   Notes:
5925:   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian

5927: .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5928: @*/
5929: PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
5930: {
5931:   Mat              J, B;
5932:   void            *ctx;
5933:   TSRHSJacobianFn *func;

5935:   PetscFunctionBegin;
5936:   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5937:   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5938:   PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5939:   PetscFunctionReturn(PETSC_SUCCESS);
5940: }

5942: /*@
5943:   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.

5945:   Logically Collective

5947:   Input Parameters:
5948: + ts                   - timestepping context
5949: - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used

5951:   Options Database Key:
5952: . -ts_use_splitrhsfunction (true|false) - use the split RHS function for multirate solvers

5954:   Level: intermediate

5956:   Note:
5957:   This is only for multirate methods

5959: .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
5960: @*/
5961: PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
5962: {
5963:   PetscFunctionBegin;
5965:   ts->use_splitrhsfunction = use_splitrhsfunction;
5966:   PetscFunctionReturn(PETSC_SUCCESS);
5967: }

5969: /*@
5970:   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.

5972:   Not Collective

5974:   Input Parameter:
5975: . ts - timestepping context

5977:   Output Parameter:
5978: . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used

5980:   Level: intermediate

5982: .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
5983: @*/
5984: PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
5985: {
5986:   PetscFunctionBegin;
5988:   *use_splitrhsfunction = ts->use_splitrhsfunction;
5989:   PetscFunctionReturn(PETSC_SUCCESS);
5990: }

5992: /*@
5993:   TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.

5995:   Logically  Collective

5997:   Input Parameters:
5998: + ts  - the time-stepper
5999: - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)

6001:   Level: intermediate

6003:   Note:
6004:   When the relationship between the nonzero structures is known and supplied the solution process can be much faster

6006: .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
6007:  @*/
6008: PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
6009: {
6010:   PetscFunctionBegin;
6012:   ts->axpy_pattern = str;
6013:   PetscFunctionReturn(PETSC_SUCCESS);
6014: }

6016: /*@
6017:   TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested

6019:   Collective

6021:   Input Parameters:
6022: + ts          - the time-stepper
6023: . n           - number of the time points
6024: - time_points - array of the time points, must be increasing

6026:   Options Database Key:
6027: . -ts_eval_times t0,...,tn - Sets the evaluation times

6029:   Level: intermediate

6031:   Notes:
6032:   The elements in `time_points` must be all increasing. They correspond to the intermediate points to be saved.

6034:   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.

6036:   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may
6037:   pressure the memory system when using a large number of time points.

6039: .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()`
6040:  @*/
6041: PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal time_points[])
6042: {
6043:   PetscBool is_sorted;

6045:   PetscFunctionBegin;
6047:   if (ts->eval_times) { // Reset eval_times
6048:     ts->eval_times->sol_idx        = 0;
6049:     ts->eval_times->time_point_idx = 0;
6050:     if (n != ts->eval_times->num_time_points) {
6051:       PetscCall(PetscFree(ts->eval_times->time_points));
6052:       PetscCall(PetscFree(ts->eval_times->sol_times));
6053:       PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
6054:     } else {
6055:       PetscCall(PetscArrayzero(ts->eval_times->sol_times, n));
6056:       for (PetscInt i = 0; i < n; i++) PetscCall(VecZeroEntries(ts->eval_times->sol_vecs[i]));
6057:     }
6058:   } else { // Create/initialize eval_times
6059:     TSEvaluationTimes eval_times;
6060:     PetscCall(PetscNew(&eval_times));
6061:     PetscCall(PetscMalloc1(n, &eval_times->time_points));
6062:     PetscCall(PetscMalloc1(n, &eval_times->sol_times));
6063:     eval_times->reltol  = 1e-6;
6064:     eval_times->abstol  = 10 * PETSC_MACHINE_EPSILON;
6065:     eval_times->worktol = 0;
6066:     ts->eval_times      = eval_times;
6067:   }
6068:   ts->eval_times->num_time_points = n;
6069:   PetscCall(PetscSortedReal(n, time_points, &is_sorted));
6070:   PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted");
6071:   PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n));
6072:   // Note: ts->vec_sol not guaranteed to exist, so ts->eval_times->sol_vecs allocated at TSSolve time
6073:   PetscFunctionReturn(PETSC_SUCCESS);
6074: }

6076: /*@C
6077:   TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()`

6079:   Not Collective

6081:   Input Parameter:
6082: . ts - the time-stepper

6084:   Output Parameters:
6085: + n           - number of the time points
6086: - time_points - array of the time points

6088:   Level: beginner

6090:   Note:
6091:   The values obtained are valid until the `TS` object is destroyed.

6093:   Both `n` and `time_points` can be `NULL`.

6095:   Also used to see time points set by `TSSetTimeSpan()`.

6097: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()`
6098:  @*/
6099: PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[])
6100: {
6101:   PetscFunctionBegin;
6103:   if (n) PetscAssertPointer(n, 2);
6104:   if (time_points) PetscAssertPointer(time_points, 3);
6105:   if (!ts->eval_times) {
6106:     if (n) *n = 0;
6107:     if (time_points) *time_points = NULL;
6108:   } else {
6109:     if (n) *n = ts->eval_times->num_time_points;
6110:     if (time_points) *time_points = ts->eval_times->time_points;
6111:   }
6112:   PetscFunctionReturn(PETSC_SUCCESS);
6113: }

6115: /*@C
6116:   TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified

6118:   Input Parameter:
6119: . ts - the `TS` context obtained from `TSCreate()`

6121:   Output Parameters:
6122: + nsol      - the number of solutions
6123: . sol_times - array of solution times corresponding to the solution vectors. See note below
6124: - Sols      - the solution vectors

6126:   Level: intermediate

6128:   Notes:
6129:   Both `nsol` and `Sols` can be `NULL`.

6131:   Some time points in the evaluation points may be skipped by `TS` so that `nsol` is less than the number of points specified by `TSSetEvaluationTimes()`.
6132:   For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times.

6134:   Also used to see view solutions requested by `TSSetTimeSpan()`.

6136: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`
6137: @*/
6138: PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec *Sols[])
6139: {
6140:   PetscFunctionBegin;
6142:   if (nsol) PetscAssertPointer(nsol, 2);
6143:   if (sol_times) PetscAssertPointer(sol_times, 3);
6144:   if (Sols) PetscAssertPointer(Sols, 4);
6145:   if (!ts->eval_times) {
6146:     if (nsol) *nsol = 0;
6147:     if (sol_times) *sol_times = NULL;
6148:     if (Sols) *Sols = NULL;
6149:   } else {
6150:     if (nsol) *nsol = ts->eval_times->sol_idx;
6151:     if (sol_times) *sol_times = ts->eval_times->sol_times;
6152:     if (Sols) *Sols = ts->eval_times->sol_vecs;
6153:   }
6154:   PetscFunctionReturn(PETSC_SUCCESS);
6155: }

6157: /*@
6158:   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span

6160:   Collective

6162:   Input Parameters:
6163: + ts         - the time-stepper
6164: . n          - number of the time points (>=2)
6165: - span_times - array of the time points, must be increasing. The first element and the last element are the initial time and the final time respectively.

6167:   Options Database Key:
6168: . -ts_time_span t0,...,tf - Sets the time span

6170:   Level: intermediate

6172:   Notes:
6173:   This function is identical to `TSSetEvaluationTimes()`, except that it also sets the initial time and final time for the `ts` to the first and last `span_times` entries.

6175:   The elements in `span_times` must be all increasing. They correspond to the intermediate points to be saved.

6177:   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.

6179:   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may
6180:   pressure the memory system when using a large number of span points.

6182: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`
6183:  @*/
6184: PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal span_times[])
6185: {
6186:   PetscFunctionBegin;
6188:   PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
6189:   PetscCall(TSSetEvaluationTimes(ts, n, span_times));
6190:   PetscCall(TSSetTime(ts, span_times[0]));
6191:   PetscCall(TSSetMaxTime(ts, span_times[n - 1]));
6192:   PetscFunctionReturn(PETSC_SUCCESS);
6193: }

6195: /*@
6196:   TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.

6198:   Collective

6200:   Input Parameters:
6201: + ts - the `TS` context
6202: . J  - Jacobian matrix (not altered in this routine)
6203: - B  - newly computed Jacobian matrix to use with preconditioner

6205:   Level: intermediate

6207:   Notes:
6208:   This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
6209:   many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
6210:   and multiple fields are involved.

6212:   Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
6213:   structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
6214:   usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
6215:   `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.

6217: .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
6218: @*/
6219: PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
6220: {
6221:   MatColoring   mc            = NULL;
6222:   ISColoring    iscoloring    = NULL;
6223:   MatFDColoring matfdcoloring = NULL;

6225:   PetscFunctionBegin;
6226:   /* Generate new coloring after eliminating zeros in the matrix */
6227:   PetscCall(MatEliminateZeros(B, PETSC_TRUE));
6228:   PetscCall(MatColoringCreate(B, &mc));
6229:   PetscCall(MatColoringSetDistance(mc, 2));
6230:   PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
6231:   PetscCall(MatColoringSetFromOptions(mc));
6232:   PetscCall(MatColoringApply(mc, &iscoloring));
6233:   PetscCall(MatColoringDestroy(&mc));
6234:   /* Replace the old coloring with the new one */
6235:   PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
6236:   PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts));
6237:   PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
6238:   PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
6239:   PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
6240:   PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
6241:   PetscCall(ISColoringDestroy(&iscoloring));
6242:   PetscFunctionReturn(PETSC_SUCCESS);
6243: }