Date: 2025-03-29T05:58:49+00:00

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 number of time-steps to take
     40: . -ts_init_time <time>                                               - initial time to start computation
     41: . -ts_final_time <time>                                              - final time to compute to (deprecated: use `-ts_max_time`)
     42: . -ts_dt <dt>                                                        - initial time step
     43: . -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
     44: . -ts_max_snes_failures <maxfailures>                                - Maximum number of nonlinear solve failures allowed
     45: . -ts_max_reject <maxrejects>                                        - Maximum number of step rejections before step fails
     46: . -ts_error_if_step_fails <true,false>                               - Error if no step succeeds
     47: . -ts_rtol <rtol>                                                    - relative tolerance for local truncation error
     48: . -ts_atol <atol>                                                    - Absolute tolerance for local truncation error
     49: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view               - test the Jacobian at each iteration against finite difference with RHS function
     50: . -ts_rhs_jacobian_test_mult_transpose                               - test the Jacobian at each iteration against finite difference with RHS function
     51: . -ts_adjoint_solve <yes,no>                                         - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
     52: . -ts_fd_color                                                       - Use finite differences with coloring to compute IJacobian
     53: . -ts_monitor                                                        - print information at each timestep
     54: . -ts_monitor_cancel                                                 - Cancel all monitors
     55: . -ts_monitor_lg_solution                                            - Monitor solution graphically
     56: . -ts_monitor_lg_error                                               - Monitor error graphically
     57: . -ts_monitor_error                                                  - Monitors norm of error
     58: . -ts_monitor_lg_timestep                                            - Monitor timestep size graphically
     59: . -ts_monitor_lg_timestep_log                                        - Monitor log timestep size graphically
     60: . -ts_monitor_lg_snes_iterations                                     - Monitor number nonlinear iterations for each timestep graphically
     61: . -ts_monitor_lg_ksp_iterations                                      - Monitor number nonlinear iterations for each timestep graphically
     62: . -ts_monitor_sp_eig                                                 - Monitor eigenvalues of linearized operator graphically
     63: . -ts_monitor_draw_solution                                          - Monitor solution graphically
     64: . -ts_monitor_draw_solution_phase  <xleft,yleft,xright,yright>       - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
     65: . -ts_monitor_draw_error                                             - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
     66: . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
     67: . -ts_monitor_solution_interval <interval>                           - output once every interval (default=1) time steps. Use -1 to only output at the end of the simulation
     68: . -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)
     69: . -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
     70: - -ts_monitor_envelope                                               - determine maximum and minimum value of each component of the solution over the solution time

     72:   Level: beginner

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

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

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

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

     98:   PetscFunctionBegin;

    101:   PetscCall(TSRegisterAll());
    102:   PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));

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

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

    134:   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult", "Test the RHS Jacobian for consistency with RHS at each solve ", "None", ts->testjacobian, &ts->testjacobian, NULL));
    135:   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));
    136:   PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction", "Use the split RHS function for multirate solvers ", "TSSetUseSplitRHSFunction", ts->use_splitrhsfunction, &ts->use_splitrhsfunction, NULL));
    137: #if defined(PETSC_HAVE_SAWS)
    138:   {
    139:     PetscBool set;
    140:     flg = PETSC_FALSE;
    141:     PetscCall(PetscOptionsBool("-ts_saws_block", "Block for SAWs memory snooper at end of TSSolve", "PetscObjectSAWsBlock", ((PetscObject)ts)->amspublishblock, &flg, &set));
    142:     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts, flg));
    143:   }
    144: #endif

    146:   /* Monitor options */
    147:   PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL));
    148:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor", "Monitor time and timestep size", "TSMonitorDefault", TSMonitorDefault, NULL));
    149:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_extreme", "Monitor extreme values of the solution", "TSMonitorExtreme", TSMonitorExtreme, NULL));
    150:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_solution", "View the solution at each timestep", "TSMonitorSolution", TSMonitorSolution, NULL));
    151:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_dmswarm_monitor_moments", "Monitor moments of particle distribution", "TSDMSwarmMonitorMoments", TSDMSwarmMonitorMoments, NULL));

    153:   PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
    154:   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename));

    156:   PetscCall(PetscOptionsName("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", &opt));
    157:   if (opt) {
    158:     PetscInt  howoften = 1;
    159:     DM        dm;
    160:     PetscBool net;

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

    177:   PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt));
    178:   if (opt) {
    179:     TSMonitorLGCtx ctx;
    180:     PetscInt       howoften = 1;

    182:     PetscCall(PetscOptionsInt("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", howoften, &howoften, NULL));
    183:     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
    184:     PetscCall(TSMonitorSet(ts, TSMonitorLGError, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
    185:   }
    186:   PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_error", "View the error at each timestep", "TSMonitorError", TSMonitorError, NULL));

    188:   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt));
    189:   if (opt) {
    190:     TSMonitorLGCtx ctx;
    191:     PetscInt       howoften = 1;

    193:     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
    194:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
    195:     PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
    196:   }
    197:   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", &opt));
    198:   if (opt) {
    199:     TSMonitorLGCtx ctx;
    200:     PetscInt       howoften = 1;

    202:     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL));
    203:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
    204:     PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
    205:     ctx->semilogy = PETSC_TRUE;
    206:   }

    208:   PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", &opt));
    209:   if (opt) {
    210:     TSMonitorLGCtx ctx;
    211:     PetscInt       howoften = 1;

    213:     PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", howoften, &howoften, NULL));
    214:     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx));
    215:     PetscCall(TSMonitorSet(ts, TSMonitorLGSNESIterations, ctx, (PetscCtxDestroyFn *)TSMonitorLGCtxDestroy));
    216:   }
    217:   PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", &opt));
    218:   if (opt) {
    219:     TSMonitorLGCtx ctx;
    220:     PetscInt       howoften = 1;

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

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

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

    261:     for (PetscInt i = 0; i < ts->numbermonitors; ++i)
    262:       if (ts->monitor[i] == TSMonitorHGSwarmSolution) {
    263:         create = PETSC_FALSE;
    264:         break;
    265:       }
    266:     if (create) {
    267:       DM       sw, dm;
    268:       PetscInt Nc, Nb;

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

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

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

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

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

    331:   opt = PETSC_FALSE;
    332:   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));
    333:   if (flg) {
    334:     TSMonitorVTKCtx ctx;

    336:     PetscCall(TSMonitorSolutionVTKCtxCreate(monfilename, &ctx));
    337:     PetscCall(PetscOptionsInt("-ts_monitor_solution_vtk_interval", "Save every interval time step (-1 for last step only)", NULL, ctx->interval, &ctx->interval, NULL));
    338:     PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, void *))TSMonitorSolutionVTK, ctx, (PetscCtxDestroyFn *)TSMonitorSolutionVTKDestroy));
    339:   }

    341:   PetscCall(PetscOptionsString("-ts_monitor_dmda_ray", "Display a ray of the solution", "None", "y=0", dir, sizeof(dir), &flg));
    342:   if (flg) {
    343:     TSMonitorDMDARayCtx *rayctx;
    344:     int                  ray = 0;
    345:     DMDirection          ddir;
    346:     DM                   da;
    347:     PetscMPIInt          rank;

    349:     PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
    350:     if (dir[0] == 'x') ddir = DM_X;
    351:     else if (dir[0] == 'y') ddir = DM_Y;
    352:     else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir);
    353:     sscanf(dir + 2, "%d", &ray);

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

    372:     PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
    373:     if (dir[0] == 'x') ddir = DM_X;
    374:     else if (dir[0] == 'y') ddir = DM_Y;
    375:     else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
    376:     sscanf(dir + 2, "%d", &ray);

    378:     PetscCall(PetscInfo(ts, "Displaying LG DMDA ray %c = %d\n", dir[0], ray));
    379:     PetscCall(PetscNew(&rayctx));
    380:     PetscCall(TSGetDM(ts, &da));
    381:     PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
    382:     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &rayctx->lgctx));
    383:     PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
    384:   }

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

    390:     PetscCall(TSMonitorEnvelopeCtxCreate(ts, &ctx));
    391:     PetscCall(TSMonitorSet(ts, TSMonitorEnvelope, ctx, (PetscCtxDestroyFn *)TSMonitorEnvelopeCtxDestroy));
    392:   }
    393:   flg = PETSC_FALSE;
    394:   PetscCall(PetscOptionsBool("-ts_monitor_cancel", "Remove all monitors", "TSMonitorCancel", flg, &flg, &opt));
    395:   if (opt && flg) PetscCall(TSMonitorCancel(ts));

    397:   flg = PETSC_FALSE;
    398:   PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeIJacobianDefaultColor", flg, &flg, NULL));
    399:   if (flg) {
    400:     DM dm;

    402:     PetscCall(TSGetDM(ts, &dm));
    403:     PetscCall(DMTSUnsetIJacobianContext_Internal(dm));
    404:     PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
    405:     PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
    406:   }

    408:   /* Handle specific TS options */
    409:   PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject);

    411:   /* Handle TSAdapt options */
    412:   PetscCall(TSGetAdapt(ts, &ts->adapt));
    413:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
    414:   PetscCall(TSAdaptSetFromOptions(ts->adapt, PetscOptionsObject));

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

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

    423:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    424:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject));
    425:   PetscOptionsEnd();

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

    429:   /* why do we have to do this here and not during TSSetUp? */
    430:   PetscCall(TSGetSNES(ts, &ts->snes));
    431:   if (ts->problem_type == TS_LINEAR) {
    432:     PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &flg, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
    433:     if (!flg) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
    434:   }
    435:   PetscCall(SNESSetFromOptions(ts->snes));
    436:   PetscFunctionReturn(PETSC_SUCCESS);
    437: }

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

    442:   Collective

    444:   Input Parameter:
    445: . ts - the `TS` context obtained from `TSCreate()`

    447:   Output Parameter:
    448: . tr - the `TSTrajectory` object, if it exists

    450:   Level: advanced

    452:   Note:
    453:   This routine should be called after all `TS` options have been set

    455: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()`
    456: @*/
    457: PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr)
    458: {
    459:   PetscFunctionBegin;
    461:   *tr = ts->trajectory;
    462:   PetscFunctionReturn(PETSC_SUCCESS);
    463: }

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

    468:   Collective

    470:   Input Parameter:
    471: . ts - the `TS` context obtained from `TSCreate()`

    473:   Options Database Keys:
    474: + -ts_save_trajectory      - saves the trajectory to a file
    475: - -ts_trajectory_type type - set trajectory type

    477:   Level: intermediate

    479:   Notes:
    480:   This routine should be called after all `TS` options have been set

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

    485: .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`
    486: @*/
    487: PetscErrorCode TSSetSaveTrajectory(TS ts)
    488: {
    489:   PetscFunctionBegin;
    491:   if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
    492:   PetscFunctionReturn(PETSC_SUCCESS);
    493: }

    495: /*@
    496:   TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object

    498:   Collective

    500:   Input Parameter:
    501: . ts - the `TS` context obtained from `TSCreate()`

    503:   Level: intermediate

    505: .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()`
    506: @*/
    507: PetscErrorCode TSResetTrajectory(TS ts)
    508: {
    509:   PetscFunctionBegin;
    511:   if (ts->trajectory) {
    512:     PetscCall(TSTrajectoryDestroy(&ts->trajectory));
    513:     PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory));
    514:   }
    515:   PetscFunctionReturn(PETSC_SUCCESS);
    516: }

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

    521:   Collective

    523:   Input Parameter:
    524: . ts - the `TS` context obtained from `TSCreate()`

    526:   Level: intermediate

    528: .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()`
    529: @*/
    530: PetscErrorCode TSRemoveTrajectory(TS ts)
    531: {
    532:   PetscFunctionBegin;
    534:   if (ts->trajectory) PetscCall(TSTrajectoryDestroy(&ts->trajectory));
    535:   PetscFunctionReturn(PETSC_SUCCESS);
    536: }

    538: /*@
    539:   TSComputeRHSJacobian - Computes the Jacobian matrix that has been
    540:   set with `TSSetRHSJacobian()`.

    542:   Collective

    544:   Input Parameters:
    545: + ts - the `TS` context
    546: . t  - current timestep
    547: - U  - input vector

    549:   Output Parameters:
    550: + A - Jacobian matrix
    551: - B - optional preconditioning matrix

    553:   Level: developer

    555:   Note:
    556:   Most users should not need to explicitly call this routine, as it
    557:   is used internally within the nonlinear solvers.

    559: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `KSPSetOperators()`
    560: @*/
    561: PetscErrorCode TSComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B)
    562: {
    563:   PetscObjectState Ustate;
    564:   PetscObjectId    Uid;
    565:   DM               dm;
    566:   DMTS             tsdm;
    567:   TSRHSJacobianFn *rhsjacobianfunc;
    568:   void            *ctx;
    569:   TSRHSFunctionFn *rhsfunction;

    571:   PetscFunctionBegin;
    574:   PetscCheckSameComm(ts, 1, U, 3);
    575:   PetscCall(TSGetDM(ts, &dm));
    576:   PetscCall(DMGetDMTS(dm, &tsdm));
    577:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));
    578:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobianfunc, &ctx));
    579:   PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate));
    580:   PetscCall(PetscObjectGetId((PetscObject)U, &Uid));

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

    584:   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);
    585:   if (rhsjacobianfunc) {
    586:     PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B));
    587:     PetscCallBack("TS callback Jacobian", (*rhsjacobianfunc)(ts, t, U, A, B, ctx));
    588:     ts->rhsjacs++;
    589:     PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B));
    590:   } else {
    591:     PetscCall(MatZeroEntries(A));
    592:     if (B && A != B) PetscCall(MatZeroEntries(B));
    593:   }
    594:   ts->rhsjacobian.time  = t;
    595:   ts->rhsjacobian.shift = 0;
    596:   ts->rhsjacobian.scale = 1.;
    597:   PetscCall(PetscObjectGetId((PetscObject)U, &ts->rhsjacobian.Xid));
    598:   PetscCall(PetscObjectStateGet((PetscObject)U, &ts->rhsjacobian.Xstate));
    599:   PetscFunctionReturn(PETSC_SUCCESS);
    600: }

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

    605:   Collective

    607:   Input Parameters:
    608: + ts - the `TS` context
    609: . t  - current time
    610: - U  - state vector

    612:   Output Parameter:
    613: . y - right-hand side

    615:   Level: developer

    617:   Note:
    618:   Most users should not need to explicitly call this routine, as it
    619:   is used internally within the nonlinear solvers.

    621: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
    622: @*/
    623: PetscErrorCode TSComputeRHSFunction(TS ts, PetscReal t, Vec U, Vec y)
    624: {
    625:   TSRHSFunctionFn *rhsfunction;
    626:   TSIFunctionFn   *ifunction;
    627:   void            *ctx;
    628:   DM               dm;

    630:   PetscFunctionBegin;
    634:   PetscCall(TSGetDM(ts, &dm));
    635:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx));
    636:   PetscCall(DMTSGetIFunction(dm, &ifunction, NULL));

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

    640:   if (rhsfunction) {
    641:     PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, y, 0));
    642:     PetscCall(VecLockReadPush(U));
    643:     PetscCallBack("TS callback right-hand-side", (*rhsfunction)(ts, t, U, y, ctx));
    644:     PetscCall(VecLockReadPop(U));
    645:     ts->rhsfuncs++;
    646:     PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, y, 0));
    647:   } else PetscCall(VecZeroEntries(y));
    648:   PetscFunctionReturn(PETSC_SUCCESS);
    649: }

    651: /*@
    652:   TSComputeSolutionFunction - Evaluates the solution function.

    654:   Collective

    656:   Input Parameters:
    657: + ts - the `TS` context
    658: - t  - current time

    660:   Output Parameter:
    661: . U - the solution

    663:   Level: developer

    665: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
    666: @*/
    667: PetscErrorCode TSComputeSolutionFunction(TS ts, PetscReal t, Vec U)
    668: {
    669:   TSSolutionFn *solutionfunction;
    670:   void         *ctx;
    671:   DM            dm;

    673:   PetscFunctionBegin;
    676:   PetscCall(TSGetDM(ts, &dm));
    677:   PetscCall(DMTSGetSolutionFunction(dm, &solutionfunction, &ctx));
    678:   if (solutionfunction) PetscCallBack("TS callback solution", (*solutionfunction)(ts, t, U, ctx));
    679:   PetscFunctionReturn(PETSC_SUCCESS);
    680: }
    681: /*@
    682:   TSComputeForcingFunction - Evaluates the forcing function.

    684:   Collective

    686:   Input Parameters:
    687: + ts - the `TS` context
    688: - t  - current time

    690:   Output Parameter:
    691: . U - the function value

    693:   Level: developer

    695: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()`
    696: @*/
    697: PetscErrorCode TSComputeForcingFunction(TS ts, PetscReal t, Vec U)
    698: {
    699:   void        *ctx;
    700:   DM           dm;
    701:   TSForcingFn *forcing;

    703:   PetscFunctionBegin;
    706:   PetscCall(TSGetDM(ts, &dm));
    707:   PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx));

    709:   if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx));
    710:   PetscFunctionReturn(PETSC_SUCCESS);
    711: }

    713: PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs)
    714: {
    715:   Mat            A, B;
    716:   TSIJacobianFn *ijacobian;

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

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

    765:   Collective

    767:   Input Parameters:
    768: + ts   - the `TS` context
    769: . t    - current time
    770: . U    - state vector
    771: . Udot - time derivative of state vector
    772: - imex - flag indicates if the method is `TSARKIMEX` so that the RHSFunction should be kept separate

    774:   Output Parameter:
    775: . Y - right-hand side

    777:   Level: developer

    779:   Note:
    780:   Most users should not need to explicitly call this routine, as it
    781:   is used internally within the nonlinear solvers.

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

    786: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSComputeRHSFunction()`
    787: @*/
    788: PetscErrorCode TSComputeIFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec Y, PetscBool imex)
    789: {
    790:   TSIFunctionFn   *ifunction;
    791:   TSRHSFunctionFn *rhsfunction;
    792:   void            *ctx;
    793:   DM               dm;

    795:   PetscFunctionBegin;

    801:   PetscCall(TSGetDM(ts, &dm));
    802:   PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx));
    803:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));

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

    807:   PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, Udot, Y));
    808:   if (ifunction) {
    809:     PetscCallBack("TS callback implicit function", (*ifunction)(ts, t, U, Udot, Y, ctx));
    810:     ts->ifuncs++;
    811:   }
    812:   if (imex) {
    813:     if (!ifunction) PetscCall(VecCopy(Udot, Y));
    814:   } else if (rhsfunction) {
    815:     if (ifunction) {
    816:       Vec Frhs;

    818:       PetscCall(DMGetGlobalVector(dm, &Frhs));
    819:       PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
    820:       PetscCall(VecAXPY(Y, -1, Frhs));
    821:       PetscCall(DMRestoreGlobalVector(dm, &Frhs));
    822:     } else {
    823:       PetscCall(TSComputeRHSFunction(ts, t, U, Y));
    824:       PetscCall(VecAYPX(Y, -1, Udot));
    825:     }
    826:   }
    827:   PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, Udot, Y));
    828:   PetscFunctionReturn(PETSC_SUCCESS);
    829: }

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

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

    837: */
    838: static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B)
    839: {
    840:   PetscFunctionBegin;
    842:   PetscCheck(A == ts->Arhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Amat");
    843:   PetscCheck(B == ts->Brhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Bmat");

    845:   if (ts->rhsjacobian.shift) PetscCall(MatShift(A, -ts->rhsjacobian.shift));
    846:   if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(A, -1));
    847:   if (B && B == ts->Brhs && A != B) {
    848:     if (ts->rhsjacobian.shift) PetscCall(MatShift(B, -ts->rhsjacobian.shift));
    849:     if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(B, -1));
    850:   }
    851:   ts->rhsjacobian.shift = 0;
    852:   ts->rhsjacobian.scale = 1.;
    853:   PetscFunctionReturn(PETSC_SUCCESS);
    854: }

    856: /*@
    857:   TSComputeIJacobian - Evaluates the Jacobian of the DAE

    859:   Collective

    861:   Input Parameters:
    862: + ts    - the `TS` context
    863: . t     - current timestep
    864: . U     - state vector
    865: . Udot  - time derivative of state vector
    866: . shift - shift to apply, see note below
    867: - imex  - flag indicates if the method is `TSARKIMEX` so that the RHSJacobian should be kept separate

    869:   Output Parameters:
    870: + A - Jacobian matrix
    871: - B - matrix from which the preconditioner is constructed; often the same as `A`

    873:   Level: developer

    875:   Notes:
    876:   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
    877: .vb
    878:    dF/dU + shift*dF/dUdot
    879: .ve
    880:   Most users should not need to explicitly call this routine, as it
    881:   is used internally within the nonlinear solvers.

    883: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`
    884: @*/
    885: PetscErrorCode TSComputeIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex)
    886: {
    887:   TSIJacobianFn   *ijacobian;
    888:   TSRHSJacobianFn *rhsjacobian;
    889:   DM               dm;
    890:   void            *ctx;

    892:   PetscFunctionBegin;

    899:   PetscCall(TSGetDM(ts, &dm));
    900:   PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx));
    901:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));

    903:   PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()");

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

    941:     /* RHSJacobian needs to be converted to part of IJacobian if exists */
    942:     if (rhsjacobian) PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
    943:     if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */
    944:       PetscObjectState Ustate;
    945:       PetscObjectId    Uid;
    946:       TSRHSFunctionFn *rhsfunction;

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

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

    996: /*@C
    997:   TSSetRHSFunction - Sets the routine for evaluating the function,
    998:   where U_t = G(t,u).

    1000:   Logically Collective

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

    1008:   Level: beginner

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

    1013: .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
    1014: @*/
    1015: PetscErrorCode TSSetRHSFunction(TS ts, Vec r, TSRHSFunctionFn *f, void *ctx)
    1016: {
    1017:   SNES snes;
    1018:   Vec  ralloc = NULL;
    1019:   DM   dm;

    1021:   PetscFunctionBegin;

    1025:   PetscCall(TSGetDM(ts, &dm));
    1026:   PetscCall(DMTSSetRHSFunction(dm, f, ctx));
    1027:   PetscCall(TSGetSNES(ts, &snes));
    1028:   if (!r && !ts->dm && ts->vec_sol) {
    1029:     PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
    1030:     r = ralloc;
    1031:   }
    1032:   PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
    1033:   PetscCall(VecDestroy(&ralloc));
    1034:   PetscFunctionReturn(PETSC_SUCCESS);
    1035: }

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

    1040:   Logically Collective

    1042:   Input Parameters:
    1043: + ts  - the `TS` context obtained from `TSCreate()`
    1044: . f   - routine for evaluating the solution
    1045: - ctx - [optional] user-defined context for private data for the
    1046:           function evaluation routine (may be `NULL`)

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

    1052:   Level: intermediate

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

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

    1061: .seealso: [](ch_ts), `TS`, `TSSolutionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()`
    1062: @*/
    1063: PetscErrorCode TSSetSolutionFunction(TS ts, TSSolutionFn *f, void *ctx)
    1064: {
    1065:   DM dm;

    1067:   PetscFunctionBegin;
    1069:   PetscCall(TSGetDM(ts, &dm));
    1070:   PetscCall(DMTSSetSolutionFunction(dm, f, ctx));
    1071:   PetscFunctionReturn(PETSC_SUCCESS);
    1072: }

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

    1077:   Logically Collective

    1079:   Input Parameters:
    1080: + ts   - the `TS` context obtained from `TSCreate()`
    1081: . func - routine for evaluating the forcing function
    1082: - ctx  - [optional] user-defined context for private data for the function evaluation routine
    1083:          (may be `NULL`)

    1085:   Level: intermediate

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

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

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

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

    1099: .seealso: [](ch_ts), `TS`, `TSForcingFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`,
    1100: `TSComputeSolutionFunction()`, `TSSetSolutionFunction()`
    1101: @*/
    1102: PetscErrorCode TSSetForcingFunction(TS ts, TSForcingFn *func, void *ctx)
    1103: {
    1104:   DM dm;

    1106:   PetscFunctionBegin;
    1108:   PetscCall(TSGetDM(ts, &dm));
    1109:   PetscCall(DMTSSetForcingFunction(dm, func, ctx));
    1110:   PetscFunctionReturn(PETSC_SUCCESS);
    1111: }

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

    1117:   Logically Collective

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

    1126:   Level: beginner

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

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

    1134: .seealso: [](ch_ts), `TS`, `TSRHSJacobianFn`, `SNESComputeJacobianDefaultColor()`,
    1135: `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()`, `TSRHSFunctionFn`, `TSIFunctionFn`
    1136: @*/
    1137: PetscErrorCode TSSetRHSJacobian(TS ts, Mat Amat, Mat Pmat, TSRHSJacobianFn *f, void *ctx)
    1138: {
    1139:   SNES           snes;
    1140:   DM             dm;
    1141:   TSIJacobianFn *ijacobian;

    1143:   PetscFunctionBegin;
    1147:   if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
    1148:   if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);

    1150:   PetscCall(TSGetDM(ts, &dm));
    1151:   PetscCall(DMTSSetRHSJacobian(dm, f, ctx));
    1152:   PetscCall(DMTSGetIJacobian(dm, &ijacobian, NULL));
    1153:   PetscCall(TSGetSNES(ts, &snes));
    1154:   if (!ijacobian) PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
    1155:   if (Amat) {
    1156:     PetscCall(PetscObjectReference((PetscObject)Amat));
    1157:     PetscCall(MatDestroy(&ts->Arhs));
    1158:     ts->Arhs = Amat;
    1159:   }
    1160:   if (Pmat) {
    1161:     PetscCall(PetscObjectReference((PetscObject)Pmat));
    1162:     PetscCall(MatDestroy(&ts->Brhs));
    1163:     ts->Brhs = Pmat;
    1164:   }
    1165:   PetscFunctionReturn(PETSC_SUCCESS);
    1166: }

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

    1171:   Logically Collective

    1173:   Input Parameters:
    1174: + ts  - the `TS` context obtained from `TSCreate()`
    1175: . r   - vector to hold the residual (or `NULL` to have it created internally)
    1176: . f   - the function evaluation routine
    1177: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)

    1179:   Level: beginner

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

    1184: .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `TSSetRHSJacobian()`, `TSSetRHSFunction()`,
    1185: `TSSetIJacobian()`
    1186: @*/
    1187: PetscErrorCode TSSetIFunction(TS ts, Vec r, TSIFunctionFn *f, void *ctx)
    1188: {
    1189:   SNES snes;
    1190:   Vec  ralloc = NULL;
    1191:   DM   dm;

    1193:   PetscFunctionBegin;

    1197:   PetscCall(TSGetDM(ts, &dm));
    1198:   PetscCall(DMTSSetIFunction(dm, f, ctx));

    1200:   PetscCall(TSGetSNES(ts, &snes));
    1201:   if (!r && !ts->dm && ts->vec_sol) {
    1202:     PetscCall(VecDuplicate(ts->vec_sol, &ralloc));
    1203:     r = ralloc;
    1204:   }
    1205:   PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts));
    1206:   PetscCall(VecDestroy(&ralloc));
    1207:   PetscFunctionReturn(PETSC_SUCCESS);
    1208: }

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

    1213:   Not Collective

    1215:   Input Parameter:
    1216: . ts - the `TS` context

    1218:   Output Parameters:
    1219: + r    - vector to hold residual (or `NULL`)
    1220: . func - the function to compute residual (or `NULL`)
    1221: - ctx  - the function context (or `NULL`)

    1223:   Level: advanced

    1225: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`
    1226: @*/
    1227: PetscErrorCode TSGetIFunction(TS ts, Vec *r, TSIFunctionFn **func, void **ctx)
    1228: {
    1229:   SNES snes;
    1230:   DM   dm;

    1232:   PetscFunctionBegin;
    1234:   PetscCall(TSGetSNES(ts, &snes));
    1235:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
    1236:   PetscCall(TSGetDM(ts, &dm));
    1237:   PetscCall(DMTSGetIFunction(dm, func, ctx));
    1238:   PetscFunctionReturn(PETSC_SUCCESS);
    1239: }

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

    1244:   Not Collective

    1246:   Input Parameter:
    1247: . ts - the `TS` context

    1249:   Output Parameters:
    1250: + r    - vector to hold computed right-hand side (or `NULL`)
    1251: . func - the function to compute right-hand side (or `NULL`)
    1252: - ctx  - the function context (or `NULL`)

    1254:   Level: advanced

    1256: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `SNESGetFunction()`
    1257: @*/
    1258: PetscErrorCode TSGetRHSFunction(TS ts, Vec *r, TSRHSFunctionFn **func, void **ctx)
    1259: {
    1260:   SNES snes;
    1261:   DM   dm;

    1263:   PetscFunctionBegin;
    1265:   PetscCall(TSGetSNES(ts, &snes));
    1266:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
    1267:   PetscCall(TSGetDM(ts, &dm));
    1268:   PetscCall(DMTSGetRHSFunction(dm, func, ctx));
    1269:   PetscFunctionReturn(PETSC_SUCCESS);
    1270: }

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

    1276:   Logically Collective

    1278:   Input Parameters:
    1279: + ts   - the `TS` context obtained from `TSCreate()`
    1280: . Amat - (approximate) matrix to store Jacobian entries computed by `f`
    1281: . Pmat - matrix used to compute preconditioner (usually the same as `Amat`)
    1282: . f    - the Jacobian evaluation routine
    1283: - ctx  - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)

    1285:   Level: beginner

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

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

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

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

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

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

    1308: .seealso: [](ch_ts), `TS`, `TSIJacobianFn`, `TSSetIFunction()`, `TSSetRHSJacobian()`,
    1309: `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()`
    1310: @*/
    1311: PetscErrorCode TSSetIJacobian(TS ts, Mat Amat, Mat Pmat, TSIJacobianFn *f, void *ctx)
    1312: {
    1313:   SNES snes;
    1314:   DM   dm;

    1316:   PetscFunctionBegin;
    1320:   if (Amat) PetscCheckSameComm(ts, 1, Amat, 2);
    1321:   if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3);

    1323:   PetscCall(TSGetDM(ts, &dm));
    1324:   PetscCall(DMTSSetIJacobian(dm, f, ctx));

    1326:   PetscCall(TSGetSNES(ts, &snes));
    1327:   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts));
    1328:   PetscFunctionReturn(PETSC_SUCCESS);
    1329: }

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

    1334:   Logically Collective

    1336:   Input Parameters:
    1337: + ts    - `TS` context obtained from `TSCreate()`
    1338: - reuse - `PETSC_TRUE` if the RHS Jacobian

    1340:   Level: intermediate

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

    1348: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
    1349: @*/
    1350: PetscErrorCode TSRHSJacobianSetReuse(TS ts, PetscBool reuse)
    1351: {
    1352:   PetscFunctionBegin;
    1353:   ts->rhsjacobian.reuse = reuse;
    1354:   PetscFunctionReturn(PETSC_SUCCESS);
    1355: }

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

    1360:   Logically Collective

    1362:   Input Parameters:
    1363: + ts  - the `TS` context obtained from `TSCreate()`
    1364: . F   - vector to hold the residual (or `NULL` to have it created internally)
    1365: . fun - the function evaluation routine
    1366: - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`)

    1368:   Level: beginner

    1370: .seealso: [](ch_ts), `TS`, `TSI2FunctionFn`, `TSSetI2Jacobian()`, `TSSetIFunction()`,
    1371: `TSCreate()`, `TSSetRHSFunction()`
    1372: @*/
    1373: PetscErrorCode TSSetI2Function(TS ts, Vec F, TSI2FunctionFn *fun, void *ctx)
    1374: {
    1375:   DM dm;

    1377:   PetscFunctionBegin;
    1380:   PetscCall(TSSetIFunction(ts, F, NULL, NULL));
    1381:   PetscCall(TSGetDM(ts, &dm));
    1382:   PetscCall(DMTSSetI2Function(dm, fun, ctx));
    1383:   PetscFunctionReturn(PETSC_SUCCESS);
    1384: }

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

    1389:   Not Collective

    1391:   Input Parameter:
    1392: . ts - the `TS` context

    1394:   Output Parameters:
    1395: + r   - vector to hold residual (or `NULL`)
    1396: . fun - the function to compute residual (or `NULL`)
    1397: - ctx - the function context (or `NULL`)

    1399:   Level: advanced

    1401: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()`
    1402: @*/
    1403: PetscErrorCode TSGetI2Function(TS ts, Vec *r, TSI2FunctionFn **fun, void **ctx)
    1404: {
    1405:   SNES snes;
    1406:   DM   dm;

    1408:   PetscFunctionBegin;
    1410:   PetscCall(TSGetSNES(ts, &snes));
    1411:   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
    1412:   PetscCall(TSGetDM(ts, &dm));
    1413:   PetscCall(DMTSGetI2Function(dm, fun, ctx));
    1414:   PetscFunctionReturn(PETSC_SUCCESS);
    1415: }

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

    1421:   Logically Collective

    1423:   Input Parameters:
    1424: + ts  - the `TS` context obtained from `TSCreate()`
    1425: . J   - matrix to hold the Jacobian values
    1426: . P   - matrix for constructing the preconditioner (may be same as `J`)
    1427: . jac - the Jacobian evaluation routine, see `TSI2JacobianFn` for the calling sequence
    1428: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`)

    1430:   Level: beginner

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

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

    1440: .seealso: [](ch_ts), `TS`, `TSI2JacobianFn`, `TSSetI2Function()`, `TSGetI2Jacobian()`
    1441: @*/
    1442: PetscErrorCode TSSetI2Jacobian(TS ts, Mat J, Mat P, TSI2JacobianFn *jac, void *ctx)
    1443: {
    1444:   DM dm;

    1446:   PetscFunctionBegin;
    1450:   PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL));
    1451:   PetscCall(TSGetDM(ts, &dm));
    1452:   PetscCall(DMTSSetI2Jacobian(dm, jac, ctx));
    1453:   PetscFunctionReturn(PETSC_SUCCESS);
    1454: }

    1456: /*@C
    1457:   TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.

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

    1461:   Input Parameter:
    1462: . ts - The `TS` context obtained from `TSCreate()`

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

    1470:   Level: advanced

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

    1475: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()`
    1476: @*/
    1477: PetscErrorCode TSGetI2Jacobian(TS ts, Mat *J, Mat *P, TSI2JacobianFn **jac, void **ctx)
    1478: {
    1479:   SNES snes;
    1480:   DM   dm;

    1482:   PetscFunctionBegin;
    1483:   PetscCall(TSGetSNES(ts, &snes));
    1484:   PetscCall(SNESSetUpMatrices(snes));
    1485:   PetscCall(SNESGetJacobian(snes, J, P, NULL, NULL));
    1486:   PetscCall(TSGetDM(ts, &dm));
    1487:   PetscCall(DMTSGetI2Jacobian(dm, jac, ctx));
    1488:   PetscFunctionReturn(PETSC_SUCCESS);
    1489: }

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

    1494:   Collective

    1496:   Input Parameters:
    1497: + ts - the `TS` context
    1498: . t  - current time
    1499: . U  - state vector
    1500: . V  - time derivative of state vector (U_t)
    1501: - A  - second time derivative of state vector (U_tt)

    1503:   Output Parameter:
    1504: . F - the residual vector

    1506:   Level: developer

    1508:   Note:
    1509:   Most users should not need to explicitly call this routine, as it
    1510:   is used internally within the nonlinear solvers.

    1512: .seealso: [](ch_ts), `TS`, `TSSetI2Function()`, `TSGetI2Function()`
    1513: @*/
    1514: PetscErrorCode TSComputeI2Function(TS ts, PetscReal t, Vec U, Vec V, Vec A, Vec F)
    1515: {
    1516:   DM               dm;
    1517:   TSI2FunctionFn  *I2Function;
    1518:   void            *ctx;
    1519:   TSRHSFunctionFn *rhsfunction;

    1521:   PetscFunctionBegin;

    1528:   PetscCall(TSGetDM(ts, &dm));
    1529:   PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx));
    1530:   PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL));

    1532:   if (!I2Function) {
    1533:     PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE));
    1534:     PetscFunctionReturn(PETSC_SUCCESS);
    1535:   }

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

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

    1541:   if (rhsfunction) {
    1542:     Vec Frhs;

    1544:     PetscCall(DMGetGlobalVector(dm, &Frhs));
    1545:     PetscCall(TSComputeRHSFunction(ts, t, U, Frhs));
    1546:     PetscCall(VecAXPY(F, -1, Frhs));
    1547:     PetscCall(DMRestoreGlobalVector(dm, &Frhs));
    1548:   }

    1550:   PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F));
    1551:   PetscFunctionReturn(PETSC_SUCCESS);
    1552: }

    1554: /*@
    1555:   TSComputeI2Jacobian - Evaluates the Jacobian of the DAE

    1557:   Collective

    1559:   Input Parameters:
    1560: + ts     - the `TS` context
    1561: . t      - current timestep
    1562: . U      - state vector
    1563: . V      - time derivative of state vector
    1564: . A      - second time derivative of state vector
    1565: . shiftV - shift to apply, see note below
    1566: - shiftA - shift to apply, see note below

    1568:   Output Parameters:
    1569: + J - Jacobian matrix
    1570: - P - optional preconditioning matrix

    1572:   Level: developer

    1574:   Notes:
    1575:   If F(t,U,V,A)=0 is the DAE, the required Jacobian is

    1577:   dF/dU + shiftV*dF/dV + shiftA*dF/dA

    1579:   Most users should not need to explicitly call this routine, as it
    1580:   is used internally within the nonlinear solvers.

    1582: .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()`
    1583: @*/
    1584: PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P)
    1585: {
    1586:   DM               dm;
    1587:   TSI2JacobianFn  *I2Jacobian;
    1588:   void            *ctx;
    1589:   TSRHSJacobianFn *rhsjacobian;

    1591:   PetscFunctionBegin;

    1599:   PetscCall(TSGetDM(ts, &dm));
    1600:   PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx));
    1601:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL));

    1603:   if (!I2Jacobian) {
    1604:     PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE));
    1605:     PetscFunctionReturn(PETSC_SUCCESS);
    1606:   }

    1608:   PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P));
    1609:   PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx));
    1610:   if (rhsjacobian) {
    1611:     Mat Jrhs, Prhs;
    1612:     PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs));
    1613:     PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs));
    1614:     PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern));
    1615:     if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern));
    1616:   }

    1618:   PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P));
    1619:   PetscFunctionReturn(PETSC_SUCCESS);
    1620: }

    1622: /*@C
    1623:   TSSetTransientVariable - sets function to transform from state to transient variables

    1625:   Logically Collective

    1627:   Input Parameters:
    1628: + ts   - time stepping context on which to change the transient variable
    1629: . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
    1630: - ctx  - a context for tvar

    1632:   Level: advanced

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

    1644: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()`
    1645: @*/
    1646: PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, void *ctx)
    1647: {
    1648:   DM dm;

    1650:   PetscFunctionBegin;
    1652:   PetscCall(TSGetDM(ts, &dm));
    1653:   PetscCall(DMTSSetTransientVariable(dm, tvar, ctx));
    1654:   PetscFunctionReturn(PETSC_SUCCESS);
    1655: }

    1657: /*@
    1658:   TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables

    1660:   Logically Collective

    1662:   Input Parameters:
    1663: + ts - TS on which to compute
    1664: - U  - state vector to be transformed to transient variables

    1666:   Output Parameter:
    1667: . C - transient (conservative) variable

    1669:   Level: developer

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

    1676: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()`
    1677: @*/
    1678: PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C)
    1679: {
    1680:   DM   dm;
    1681:   DMTS dmts;

    1683:   PetscFunctionBegin;
    1686:   PetscCall(TSGetDM(ts, &dm));
    1687:   PetscCall(DMGetDMTS(dm, &dmts));
    1688:   if (dmts->ops->transientvar) {
    1690:     PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx));
    1691:   }
    1692:   PetscFunctionReturn(PETSC_SUCCESS);
    1693: }

    1695: /*@
    1696:   TSHasTransientVariable - determine whether transient variables have been set

    1698:   Logically Collective

    1700:   Input Parameter:
    1701: . ts - `TS` on which to compute

    1703:   Output Parameter:
    1704: . has - `PETSC_TRUE` if transient variables have been set

    1706:   Level: developer

    1708: .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()`
    1709: @*/
    1710: PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has)
    1711: {
    1712:   DM   dm;
    1713:   DMTS dmts;

    1715:   PetscFunctionBegin;
    1717:   PetscCall(TSGetDM(ts, &dm));
    1718:   PetscCall(DMGetDMTS(dm, &dmts));
    1719:   *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE;
    1720:   PetscFunctionReturn(PETSC_SUCCESS);
    1721: }

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

    1727:   Logically Collective

    1729:   Input Parameters:
    1730: + ts - the `TS` context obtained from `TSCreate()`
    1731: . u  - the solution vector
    1732: - v  - the time derivative vector

    1734:   Level: beginner

    1736: .seealso: [](ch_ts), `TS`
    1737: @*/
    1738: PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v)
    1739: {
    1740:   PetscFunctionBegin;
    1744:   PetscCall(TSSetSolution(ts, u));
    1745:   PetscCall(PetscObjectReference((PetscObject)v));
    1746:   PetscCall(VecDestroy(&ts->vec_dot));
    1747:   ts->vec_dot = v;
    1748:   PetscFunctionReturn(PETSC_SUCCESS);
    1749: }

    1751: /*@
    1752:   TS2GetSolution - Returns the solution and time derivative at the present timestep
    1753:   for second order equations.

    1755:   Not Collective

    1757:   Input Parameter:
    1758: . ts - the `TS` context obtained from `TSCreate()`

    1760:   Output Parameters:
    1761: + u - the vector containing the solution
    1762: - v - the vector containing the time derivative

    1764:   Level: intermediate

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

    1771: .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()`
    1772: @*/
    1773: PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v)
    1774: {
    1775:   PetscFunctionBegin;
    1777:   if (u) PetscAssertPointer(u, 2);
    1778:   if (v) PetscAssertPointer(v, 3);
    1779:   if (u) *u = ts->vec_sol;
    1780:   if (v) *v = ts->vec_dot;
    1781:   PetscFunctionReturn(PETSC_SUCCESS);
    1782: }

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

    1787:   Collective

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

    1794:   Level: intermediate

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

    1799: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()`
    1800: @*/
    1801: PetscErrorCode TSLoad(TS ts, PetscViewer viewer)
    1802: {
    1803:   PetscBool isbinary;
    1804:   PetscInt  classid;
    1805:   char      type[256];
    1806:   DMTS      sdm;
    1807:   DM        dm;

    1809:   PetscFunctionBegin;
    1812:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
    1813:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");

    1815:   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
    1816:   PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file");
    1817:   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
    1818:   PetscCall(TSSetType(ts, type));
    1819:   PetscTryTypeMethod(ts, load, viewer);
    1820:   PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm));
    1821:   PetscCall(DMLoad(dm, viewer));
    1822:   PetscCall(TSSetDM(ts, dm));
    1823:   PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
    1824:   PetscCall(VecLoad(ts->vec_sol, viewer));
    1825:   PetscCall(DMGetDMTS(ts->dm, &sdm));
    1826:   PetscCall(DMTSLoad(sdm, viewer));
    1827:   PetscFunctionReturn(PETSC_SUCCESS);
    1828: }

    1830: #include <petscdraw.h>
    1831: #if defined(PETSC_HAVE_SAWS)
    1832: #include <petscviewersaws.h>
    1833: #endif

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

    1838:   Collective

    1840:   Input Parameters:
    1841: + ts   - the `TS` context
    1842: . obj  - Optional object that provides the prefix for the options database keys
    1843: - name - command line option string to be passed by user

    1845:   Level: intermediate

    1847: .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()`
    1848: @*/
    1849: PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[])
    1850: {
    1851:   PetscFunctionBegin;
    1853:   PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name));
    1854:   PetscFunctionReturn(PETSC_SUCCESS);
    1855: }

    1857: /*@
    1858:   TSView - Prints the `TS` data structure.

    1860:   Collective

    1862:   Input Parameters:
    1863: + ts     - the `TS` context obtained from `TSCreate()`
    1864: - viewer - visualization context

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

    1869:   Level: beginner

    1871:   Notes:
    1872:   The available visualization contexts include
    1873: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
    1874: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
    1875:   output where only the first processor opens
    1876:   the file.  All other processors send their
    1877:   data to the first processor to print.

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

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

    1884: .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()`
    1885: @*/
    1886: PetscErrorCode TSView(TS ts, PetscViewer viewer)
    1887: {
    1888:   TSType    type;
    1889:   PetscBool iascii, isstring, isundials, isbinary, isdraw;
    1890:   DMTS      sdm;
    1891: #if defined(PETSC_HAVE_SAWS)
    1892:   PetscBool issaws;
    1893: #endif

    1895:   PetscFunctionBegin;
    1897:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer));
    1899:   PetscCheckSameComm(ts, 1, viewer, 2);

    1901:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    1902:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
    1903:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
    1904:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
    1905: #if defined(PETSC_HAVE_SAWS)
    1906:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
    1907: #endif
    1908:   if (iascii) {
    1909:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer));
    1910:     if (ts->ops->view) {
    1911:       PetscCall(PetscViewerASCIIPushTab(viewer));
    1912:       PetscUseTypeMethod(ts, view, viewer);
    1913:       PetscCall(PetscViewerASCIIPopTab(viewer));
    1914:     }
    1915:     if (ts->max_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum steps=%" PetscInt_FMT "\n", ts->max_steps));
    1916:     if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum time=%g\n", (double)ts->max_time));
    1917:     if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs));
    1918:     if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs));
    1919:     if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs));
    1920:     if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs));
    1921:     if (ts->usessnes) {
    1922:       PetscBool lin;
    1923:       if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its));
    1924:       PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its));
    1925:       PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, ""));
    1926:       PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures));
    1927:     }
    1928:     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of rejected steps=%" PetscInt_FMT "\n", ts->reject));
    1929:     if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, "  using vector of relative error tolerances, "));
    1930:     else PetscCall(PetscViewerASCIIPrintf(viewer, "  using relative error tolerance of %g, ", (double)ts->rtol));
    1931:     if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, "  using vector of absolute error tolerances\n"));
    1932:     else PetscCall(PetscViewerASCIIPrintf(viewer, "  using absolute error tolerance of %g\n", (double)ts->atol));
    1933:     PetscCall(PetscViewerASCIIPushTab(viewer));
    1934:     PetscCall(TSAdaptView(ts->adapt, viewer));
    1935:     PetscCall(PetscViewerASCIIPopTab(viewer));
    1936:   } else if (isstring) {
    1937:     PetscCall(TSGetType(ts, &type));
    1938:     PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type));
    1939:     PetscTryTypeMethod(ts, view, viewer);
    1940:   } else if (isbinary) {
    1941:     PetscInt    classid = TS_FILE_CLASSID;
    1942:     MPI_Comm    comm;
    1943:     PetscMPIInt rank;
    1944:     char        type[256];

    1946:     PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
    1947:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
    1948:     if (rank == 0) {
    1949:       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
    1950:       PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256));
    1951:       PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
    1952:     }
    1953:     PetscTryTypeMethod(ts, view, viewer);
    1954:     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
    1955:     PetscCall(DMView(ts->dm, viewer));
    1956:     PetscCall(VecView(ts->vec_sol, viewer));
    1957:     PetscCall(DMGetDMTS(ts->dm, &sdm));
    1958:     PetscCall(DMTSView(sdm, viewer));
    1959:   } else if (isdraw) {
    1960:     PetscDraw draw;
    1961:     char      str[36];
    1962:     PetscReal x, y, bottom, h;

    1964:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
    1965:     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
    1966:     PetscCall(PetscStrncpy(str, "TS: ", sizeof(str)));
    1967:     PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str)));
    1968:     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h));
    1969:     bottom = y - h;
    1970:     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
    1971:     PetscTryTypeMethod(ts, view, viewer);
    1972:     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer));
    1973:     if (ts->snes) PetscCall(SNESView(ts->snes, viewer));
    1974:     PetscCall(PetscDrawPopCurrentPoint(draw));
    1975: #if defined(PETSC_HAVE_SAWS)
    1976:   } else if (issaws) {
    1977:     PetscMPIInt rank;
    1978:     const char *name;

    1980:     PetscCall(PetscObjectGetName((PetscObject)ts, &name));
    1981:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
    1982:     if (!((PetscObject)ts)->amsmem && rank == 0) {
    1983:       char dir[1024];

    1985:       PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer));
    1986:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name));
    1987:       PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT));
    1988:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name));
    1989:       PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE));
    1990:     }
    1991:     PetscTryTypeMethod(ts, view, viewer);
    1992: #endif
    1993:   }
    1994:   if (ts->snes && ts->usessnes) {
    1995:     PetscCall(PetscViewerASCIIPushTab(viewer));
    1996:     PetscCall(SNESView(ts->snes, viewer));
    1997:     PetscCall(PetscViewerASCIIPopTab(viewer));
    1998:   }
    1999:   PetscCall(DMGetDMTS(ts->dm, &sdm));
    2000:   PetscCall(DMTSView(sdm, viewer));

    2002:   PetscCall(PetscViewerASCIIPushTab(viewer));
    2003:   PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &isundials));
    2004:   PetscCall(PetscViewerASCIIPopTab(viewer));
    2005:   PetscFunctionReturn(PETSC_SUCCESS);
    2006: }

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

    2012:   Logically Collective

    2014:   Input Parameters:
    2015: + ts  - the `TS` context obtained from `TSCreate()`
    2016: - ctx - user context

    2018:   Level: intermediate

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

    2025: .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()`
    2026: @*/
    2027: PetscErrorCode TSSetApplicationContext(TS ts, PeCtx ctx)
    2028: {
    2029:   PetscFunctionBegin;
    2031:   ts->ctx = ctx;
    2032:   PetscFunctionReturn(PETSC_SUCCESS);
    2033: }

    2035: /*@
    2036:   TSGetApplicationContext - Gets the user-defined context for the
    2037:   timestepper that was set with `TSSetApplicationContext()`

    2039:   Not Collective

    2041:   Input Parameter:
    2042: . ts - the `TS` context obtained from `TSCreate()`

    2044:   Output Parameter:
    2045: . ctx - a pointer to the user context

    2047:   Level: intermediate

    2049:   Fortran Notes:
    2050:   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
    2051:   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
    2052: .vb
    2053:   Interface TSGetApplicationContext
    2054:     Subroutine TSGetApplicationContext(ts,ctx,ierr)
    2055:   #include <petsc/finclude/petscts.h>
    2056:       use petscts
    2057:       TS ts
    2058:       type(tUsertype), pointer :: ctx
    2059:       PetscErrorCode ierr
    2060:     End Subroutine
    2061:   End Interface TSGetApplicationContext
    2062: .ve

    2064:   The prototpye for `ctx` must be
    2065: .vb
    2066:   type(tUsertype), pointer :: ctx
    2067: .ve

    2069: .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()`
    2070: @*/
    2071: PetscErrorCode TSGetApplicationContext(TS ts, void *ctx)
    2072: {
    2073:   PetscFunctionBegin;
    2075:   *(void **)ctx = ts->ctx;
    2076:   PetscFunctionReturn(PETSC_SUCCESS);
    2077: }

    2079: /*@
    2080:   TSGetStepNumber - Gets the number of time steps completed.

    2082:   Not Collective

    2084:   Input Parameter:
    2085: . ts - the `TS` context obtained from `TSCreate()`

    2087:   Output Parameter:
    2088: . steps - number of steps completed so far

    2090:   Level: intermediate

    2092: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`
    2093: @*/
    2094: PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps)
    2095: {
    2096:   PetscFunctionBegin;
    2098:   PetscAssertPointer(steps, 2);
    2099:   *steps = ts->steps;
    2100:   PetscFunctionReturn(PETSC_SUCCESS);
    2101: }

    2103: /*@
    2104:   TSSetStepNumber - Sets the number of steps completed.

    2106:   Logically Collective

    2108:   Input Parameters:
    2109: + ts    - the `TS` context
    2110: - steps - number of steps completed so far

    2112:   Level: developer

    2114:   Note:
    2115:   For most uses of the `TS` solvers the user need not explicitly call
    2116:   `TSSetStepNumber()`, as the step counter is appropriately updated in
    2117:   `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to
    2118:   reinitialize timestepping by setting the step counter to zero (and time
    2119:   to the initial time) to solve a similar problem with different initial
    2120:   conditions or parameters. Other possible use case is to continue
    2121:   timestepping from a previously interrupted run in such a way that `TS`
    2122:   monitors will be called with a initial nonzero step counter.

    2124: .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()`
    2125: @*/
    2126: PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps)
    2127: {
    2128:   PetscFunctionBegin;
    2131:   PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative");
    2132:   ts->steps = steps;
    2133:   PetscFunctionReturn(PETSC_SUCCESS);
    2134: }

    2136: /*@
    2137:   TSSetTimeStep - Allows one to reset the timestep at any time,
    2138:   useful for simple pseudo-timestepping codes.

    2140:   Logically Collective

    2142:   Input Parameters:
    2143: + ts        - the `TS` context obtained from `TSCreate()`
    2144: - time_step - the size of the timestep

    2146:   Level: intermediate

    2148: .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()`
    2149: @*/
    2150: PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step)
    2151: {
    2152:   PetscFunctionBegin;
    2155:   ts->time_step = time_step;
    2156:   PetscFunctionReturn(PETSC_SUCCESS);
    2157: }

    2159: /*@
    2160:   TSSetExactFinalTime - Determines whether to adapt the final time step to
    2161:   match the exact final time, to interpolate the solution to the exact final time,
    2162:   or to just return at the final time `TS` computed (which may be slightly larger
    2163:   than the requested final time).

    2165:   Logically Collective

    2167:   Input Parameters:
    2168: + ts     - the time-step context
    2169: - eftopt - exact final time option
    2170: .vb
    2171:   TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded, just use it
    2172:   TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded
    2173:   TS_EXACTFINALTIME_MATCHSTEP   - Adapt final time step to ensure the computed final time exactly equals the requested final time
    2174: .ve

    2176:   Options Database Key:
    2177: . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime

    2179:   Level: beginner

    2181:   Note:
    2182:   If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time
    2183:   then the final time you selected.

    2185: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()`
    2186: @*/
    2187: PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt)
    2188: {
    2189:   PetscFunctionBegin;
    2192:   ts->exact_final_time = eftopt;
    2193:   PetscFunctionReturn(PETSC_SUCCESS);
    2194: }

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

    2199:   Not Collective

    2201:   Input Parameter:
    2202: . ts - the `TS` context

    2204:   Output Parameter:
    2205: . eftopt - exact final time option

    2207:   Level: beginner

    2209: .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()`
    2210: @*/
    2211: PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt)
    2212: {
    2213:   PetscFunctionBegin;
    2215:   PetscAssertPointer(eftopt, 2);
    2216:   *eftopt = ts->exact_final_time;
    2217:   PetscFunctionReturn(PETSC_SUCCESS);
    2218: }

    2220: /*@
    2221:   TSGetTimeStep - Gets the current timestep size.

    2223:   Not Collective

    2225:   Input Parameter:
    2226: . ts - the `TS` context obtained from `TSCreate()`

    2228:   Output Parameter:
    2229: . dt - the current timestep size

    2231:   Level: intermediate

    2233: .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()`
    2234: @*/
    2235: PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt)
    2236: {
    2237:   PetscFunctionBegin;
    2239:   PetscAssertPointer(dt, 2);
    2240:   *dt = ts->time_step;
    2241:   PetscFunctionReturn(PETSC_SUCCESS);
    2242: }

    2244: /*@
    2245:   TSGetSolution - Returns the solution at the present timestep. It
    2246:   is valid to call this routine inside the function that you are evaluating
    2247:   in order to move to the new timestep. This vector not changed until
    2248:   the solution at the next timestep has been calculated.

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

    2252:   Input Parameter:
    2253: . ts - the `TS` context obtained from `TSCreate()`

    2255:   Output Parameter:
    2256: . v - the vector containing the solution

    2258:   Level: intermediate

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

    2264: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()`
    2265: @*/
    2266: PetscErrorCode TSGetSolution(TS ts, Vec *v)
    2267: {
    2268:   PetscFunctionBegin;
    2270:   PetscAssertPointer(v, 2);
    2271:   *v = ts->vec_sol;
    2272:   PetscFunctionReturn(PETSC_SUCCESS);
    2273: }

    2275: /*@
    2276:   TSGetSolutionComponents - Returns any solution components at the present
    2277:   timestep, if available for the time integration method being used.
    2278:   Solution components are quantities that share the same size and
    2279:   structure as the solution vector.

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

    2283:   Input Parameters:
    2284: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
    2285: . n  - If v is `NULL`, then the number of solution components is
    2286:        returned through n, else the n-th solution component is
    2287:        returned in v.
    2288: - v  - the vector containing the n-th solution component
    2289:        (may be `NULL` to use this function to find out
    2290:         the number of solutions components).

    2292:   Level: advanced

    2294: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
    2295: @*/
    2296: PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v)
    2297: {
    2298:   PetscFunctionBegin;
    2300:   if (!ts->ops->getsolutioncomponents) *n = 0;
    2301:   else PetscUseTypeMethod(ts, getsolutioncomponents, n, v);
    2302:   PetscFunctionReturn(PETSC_SUCCESS);
    2303: }

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

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

    2311:   Input Parameters:
    2312: + ts - the `TS` context obtained from `TSCreate()` (input parameter).
    2313: - v  - the vector containing the auxiliary solution

    2315:   Level: intermediate

    2317: .seealso: [](ch_ts), `TS`, `TSGetSolution()`
    2318: @*/
    2319: PetscErrorCode TSGetAuxSolution(TS ts, Vec *v)
    2320: {
    2321:   PetscFunctionBegin;
    2323:   if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v);
    2324:   else PetscCall(VecZeroEntries(*v));
    2325:   PetscFunctionReturn(PETSC_SUCCESS);
    2326: }

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

    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  - current estimate (n=0) or previous one (n=-1)
    2337: - v  - the vector containing the error (same size as the solution).

    2339:   Level: intermediate

    2341:   Note:
    2342:   MUST call after `TSSetUp()`

    2344: .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()`
    2345: @*/
    2346: PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v)
    2347: {
    2348:   PetscFunctionBegin;
    2350:   if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v);
    2351:   else PetscCall(VecZeroEntries(*v));
    2352:   PetscFunctionReturn(PETSC_SUCCESS);
    2353: }

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

    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 error (same size as the solution).

    2366:   Level: intermediate

    2368: .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()`
    2369: @*/
    2370: PetscErrorCode TSSetTimeError(TS ts, Vec v)
    2371: {
    2372:   PetscFunctionBegin;
    2374:   PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first");
    2375:   PetscTryTypeMethod(ts, settimeerror, v);
    2376:   PetscFunctionReturn(PETSC_SUCCESS);
    2377: }

    2379: /* ----- Routines to initialize and destroy a timestepper ---- */
    2380: /*@
    2381:   TSSetProblemType - Sets the type of problem to be solved.

    2383:   Not collective

    2385:   Input Parameters:
    2386: + ts   - The `TS`
    2387: - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
    2388: .vb
    2389:          U_t - A U = 0      (linear)
    2390:          U_t - A(t) U = 0   (linear)
    2391:          F(t,U,U_t) = 0     (nonlinear)
    2392: .ve

    2394:   Level: beginner

    2396: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
    2397: @*/
    2398: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
    2399: {
    2400:   PetscFunctionBegin;
    2402:   ts->problem_type = type;
    2403:   if (type == TS_LINEAR) {
    2404:     SNES snes;
    2405:     PetscCall(TSGetSNES(ts, &snes));
    2406:     PetscCall(SNESSetType(snes, SNESKSPONLY));
    2407:   }
    2408:   PetscFunctionReturn(PETSC_SUCCESS);
    2409: }

    2411: /*@
    2412:   TSGetProblemType - Gets the type of problem to be solved.

    2414:   Not collective

    2416:   Input Parameter:
    2417: . ts - The `TS`

    2419:   Output Parameter:
    2420: . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
    2421: .vb
    2422:          M U_t = A U
    2423:          M(t) U_t = A(t) U
    2424:          F(t,U,U_t)
    2425: .ve

    2427:   Level: beginner

    2429: .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
    2430: @*/
    2431: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
    2432: {
    2433:   PetscFunctionBegin;
    2435:   PetscAssertPointer(type, 2);
    2436:   *type = ts->problem_type;
    2437:   PetscFunctionReturn(PETSC_SUCCESS);
    2438: }

    2440: /*
    2441:     Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
    2442: */
    2443: static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
    2444: {
    2445:   PetscBool isnone;

    2447:   PetscFunctionBegin;
    2448:   PetscCall(TSGetAdapt(ts, &ts->adapt));
    2449:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));

    2451:   PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone));
    2452:   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
    2453:   else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
    2454:   PetscFunctionReturn(PETSC_SUCCESS);
    2455: }

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

    2460:   Collective

    2462:   Input Parameter:
    2463: . ts - the `TS` context obtained from `TSCreate()`

    2465:   Level: advanced

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

    2474: .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()`
    2475: @*/
    2476: PetscErrorCode TSSetUp(TS ts)
    2477: {
    2478:   DM dm;
    2479:   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
    2480:   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
    2481:   TSIFunctionFn   *ifun;
    2482:   TSIJacobianFn   *ijac;
    2483:   TSI2JacobianFn  *i2jac;
    2484:   TSRHSJacobianFn *rhsjac;

    2486:   PetscFunctionBegin;
    2488:   if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);

    2490:   if (!((PetscObject)ts)->type_name) {
    2491:     PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
    2492:     PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER));
    2493:   }

    2495:   if (!ts->vec_sol) {
    2496:     PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first");
    2497:     PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
    2498:   }

    2500:   if (ts->eval_times) {
    2501:     if (!ts->eval_times->sol_vecs) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
    2502:     if (!ts->eval_times->sol_times) PetscCall(PetscMalloc1(ts->eval_times->num_time_points, &ts->eval_times->sol_times));
    2503:   }
    2504:   if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
    2505:     PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
    2506:     ts->Jacp = ts->Jacprhs;
    2507:   }

    2509:   if (ts->quadraturets) {
    2510:     PetscCall(TSSetUp(ts->quadraturets));
    2511:     PetscCall(VecDestroy(&ts->vec_costintegrand));
    2512:     PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand));
    2513:   }

    2515:   PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL));
    2516:   if (rhsjac == TSComputeRHSJacobianConstant) {
    2517:     Mat  Amat, Pmat;
    2518:     SNES snes;
    2519:     PetscCall(TSGetSNES(ts, &snes));
    2520:     PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL));
    2521:     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
    2522:      * have displaced the RHS matrix */
    2523:     if (Amat && Amat == ts->Arhs) {
    2524:       /* 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 */
    2525:       PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat));
    2526:       PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL));
    2527:       PetscCall(MatDestroy(&Amat));
    2528:     }
    2529:     if (Pmat && Pmat == ts->Brhs) {
    2530:       PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat));
    2531:       PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL));
    2532:       PetscCall(MatDestroy(&Pmat));
    2533:     }
    2534:   }

    2536:   PetscCall(TSGetAdapt(ts, &ts->adapt));
    2537:   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));

    2539:   PetscTryTypeMethod(ts, setup);

    2541:   PetscCall(TSSetExactFinalTimeDefault(ts));

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

    2550:   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
    2551:      Otherwise, the SNES will use coloring internally to form the Jacobian.
    2552:    */
    2553:   PetscCall(DMSNESGetJacobian(dm, &jac, NULL));
    2554:   PetscCall(DMTSGetIJacobian(dm, &ijac, NULL));
    2555:   PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL));
    2556:   PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL));
    2557:   if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts));

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

    2562:   ts->setupcalled = PETSC_TRUE;
    2563:   PetscFunctionReturn(PETSC_SUCCESS);
    2564: }

    2566: /*@
    2567:   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

    2569:   Collective

    2571:   Input Parameter:
    2572: . ts - the `TS` context obtained from `TSCreate()`

    2574:   Level: developer

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

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

    2581: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetup()`, `TSDestroy()`, `TSSetResize()`
    2582: @*/
    2583: PetscErrorCode TSReset(TS ts)
    2584: {
    2585:   TS_RHSSplitLink ilink = ts->tsrhssplit, next;

    2587:   PetscFunctionBegin;

    2590:   PetscTryTypeMethod(ts, reset);
    2591:   if (ts->snes) PetscCall(SNESReset(ts->snes));
    2592:   if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));

    2594:   PetscCall(MatDestroy(&ts->Arhs));
    2595:   PetscCall(MatDestroy(&ts->Brhs));
    2596:   PetscCall(VecDestroy(&ts->Frhs));
    2597:   PetscCall(VecDestroy(&ts->vec_sol));
    2598:   PetscCall(VecDestroy(&ts->vec_sol0));
    2599:   PetscCall(VecDestroy(&ts->vec_dot));
    2600:   PetscCall(VecDestroy(&ts->vatol));
    2601:   PetscCall(VecDestroy(&ts->vrtol));
    2602:   PetscCall(VecDestroyVecs(ts->nwork, &ts->work));

    2604:   PetscCall(MatDestroy(&ts->Jacprhs));
    2605:   PetscCall(MatDestroy(&ts->Jacp));
    2606:   if (ts->forward_solve) PetscCall(TSForwardReset(ts));
    2607:   if (ts->quadraturets) {
    2608:     PetscCall(TSReset(ts->quadraturets));
    2609:     PetscCall(VecDestroy(&ts->vec_costintegrand));
    2610:   }
    2611:   while (ilink) {
    2612:     next = ilink->next;
    2613:     PetscCall(TSDestroy(&ilink->ts));
    2614:     PetscCall(PetscFree(ilink->splitname));
    2615:     PetscCall(ISDestroy(&ilink->is));
    2616:     PetscCall(PetscFree(ilink));
    2617:     ilink = next;
    2618:   }
    2619:   ts->tsrhssplit     = NULL;
    2620:   ts->num_rhs_splits = 0;
    2621:   if (ts->eval_times) {
    2622:     PetscCall(PetscFree(ts->eval_times->time_points));
    2623:     PetscCall(PetscFree(ts->eval_times->sol_times));
    2624:     PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
    2625:     PetscCall(PetscFree(ts->eval_times));
    2626:   }
    2627:   ts->rhsjacobian.time  = PETSC_MIN_REAL;
    2628:   ts->rhsjacobian.scale = 1.0;
    2629:   ts->ijacobian.shift   = 1.0;
    2630:   ts->setupcalled       = PETSC_FALSE;
    2631:   PetscFunctionReturn(PETSC_SUCCESS);
    2632: }

    2634: static PetscErrorCode TSResizeReset(TS);

    2636: /*@
    2637:   TSDestroy - Destroys the timestepper context that was created
    2638:   with `TSCreate()`.

    2640:   Collective

    2642:   Input Parameter:
    2643: . ts - the `TS` context obtained from `TSCreate()`

    2645:   Level: beginner

    2647: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
    2648: @*/
    2649: PetscErrorCode TSDestroy(TS *ts)
    2650: {
    2651:   PetscFunctionBegin;
    2652:   if (!*ts) PetscFunctionReturn(PETSC_SUCCESS);
    2654:   if (--((PetscObject)*ts)->refct > 0) {
    2655:     *ts = NULL;
    2656:     PetscFunctionReturn(PETSC_SUCCESS);
    2657:   }

    2659:   PetscCall(TSReset(*ts));
    2660:   PetscCall(TSAdjointReset(*ts));
    2661:   if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts));
    2662:   PetscCall(TSResizeReset(*ts));

    2664:   /* if memory was published with SAWs then destroy it */
    2665:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
    2666:   PetscTryTypeMethod(*ts, destroy);

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

    2670:   PetscCall(TSAdaptDestroy(&(*ts)->adapt));
    2671:   PetscCall(TSEventDestroy(&(*ts)->event));

    2673:   PetscCall(SNESDestroy(&(*ts)->snes));
    2674:   PetscCall(SNESDestroy(&(*ts)->snesrhssplit));
    2675:   PetscCall(DMDestroy(&(*ts)->dm));
    2676:   PetscCall(TSMonitorCancel(*ts));
    2677:   PetscCall(TSAdjointMonitorCancel(*ts));

    2679:   PetscCall(TSDestroy(&(*ts)->quadraturets));
    2680:   PetscCall(PetscHeaderDestroy(ts));
    2681:   PetscFunctionReturn(PETSC_SUCCESS);
    2682: }

    2684: /*@
    2685:   TSGetSNES - Returns the `SNES` (nonlinear solver) associated with
    2686:   a `TS` (timestepper) context. Valid only for nonlinear problems.

    2688:   Not Collective, but snes is parallel if ts is parallel

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

    2693:   Output Parameter:
    2694: . snes - the nonlinear solver context

    2696:   Level: beginner

    2698:   Notes:
    2699:   The user can then directly manipulate the `SNES` context to set various
    2700:   options, etc.  Likewise, the user can then extract and manipulate the
    2701:   `KSP`, and `PC` contexts as well.

    2703:   `TSGetSNES()` does not work for integrators that do not use `SNES`; in
    2704:   this case `TSGetSNES()` returns `NULL` in `snes`.

    2706: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
    2707: @*/
    2708: PetscErrorCode TSGetSNES(TS ts, SNES *snes)
    2709: {
    2710:   PetscFunctionBegin;
    2712:   PetscAssertPointer(snes, 2);
    2713:   if (!ts->snes) {
    2714:     PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes));
    2715:     PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options));
    2716:     PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
    2717:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
    2718:     if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
    2719:     if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
    2720:   }
    2721:   *snes = ts->snes;
    2722:   PetscFunctionReturn(PETSC_SUCCESS);
    2723: }

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

    2728:   Collective

    2730:   Input Parameters:
    2731: + ts   - the `TS` context obtained from `TSCreate()`
    2732: - snes - the nonlinear solver context

    2734:   Level: developer

    2736:   Note:
    2737:   Most users should have the `TS` created by calling `TSGetSNES()`

    2739: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
    2740: @*/
    2741: PetscErrorCode TSSetSNES(TS ts, SNES snes)
    2742: {
    2743:   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);

    2745:   PetscFunctionBegin;
    2748:   PetscCall(PetscObjectReference((PetscObject)snes));
    2749:   PetscCall(SNESDestroy(&ts->snes));

    2751:   ts->snes = snes;

    2753:   PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
    2754:   PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
    2755:   if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
    2756:   PetscFunctionReturn(PETSC_SUCCESS);
    2757: }

    2759: /*@
    2760:   TSGetKSP - Returns the `KSP` (linear solver) associated with
    2761:   a `TS` (timestepper) context.

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

    2765:   Input Parameter:
    2766: . ts - the `TS` context obtained from `TSCreate()`

    2768:   Output Parameter:
    2769: . ksp - the nonlinear solver context

    2771:   Level: beginner

    2773:   Notes:
    2774:   The user can then directly manipulate the `KSP` context to set various
    2775:   options, etc.  Likewise, the user can then extract and manipulate the
    2776:   `PC` context as well.

    2778:   `TSGetKSP()` does not work for integrators that do not use `KSP`;
    2779:   in this case `TSGetKSP()` returns `NULL` in `ksp`.

    2781: .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
    2782: @*/
    2783: PetscErrorCode TSGetKSP(TS ts, KSP *ksp)
    2784: {
    2785:   SNES snes;

    2787:   PetscFunctionBegin;
    2789:   PetscAssertPointer(ksp, 2);
    2790:   PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
    2791:   PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()");
    2792:   PetscCall(TSGetSNES(ts, &snes));
    2793:   PetscCall(SNESGetKSP(snes, ksp));
    2794:   PetscFunctionReturn(PETSC_SUCCESS);
    2795: }

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

    2799: /*@
    2800:   TSSetMaxSteps - Sets the maximum number of steps to use.

    2802:   Logically Collective

    2804:   Input Parameters:
    2805: + ts       - the `TS` context obtained from `TSCreate()`
    2806: - maxsteps - maximum number of steps to use

    2808:   Options Database Key:
    2809: . -ts_max_steps <maxsteps> - Sets maxsteps

    2811:   Level: intermediate

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

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

    2818:   Fortran Note:
    2819:   Use `PETSC_DETERMINE_INTEGER`

    2821: .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
    2822: @*/
    2823: PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps)
    2824: {
    2825:   PetscFunctionBegin;
    2828:   if (maxsteps == PETSC_DETERMINE) {
    2829:     ts->max_steps = ts->default_max_steps;
    2830:   } else {
    2831:     PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
    2832:     ts->max_steps = maxsteps;
    2833:   }
    2834:   PetscFunctionReturn(PETSC_SUCCESS);
    2835: }

    2837: /*@
    2838:   TSGetMaxSteps - Gets the maximum number of steps to use.

    2840:   Not Collective

    2842:   Input Parameter:
    2843: . ts - the `TS` context obtained from `TSCreate()`

    2845:   Output Parameter:
    2846: . maxsteps - maximum number of steps to use

    2848:   Level: advanced

    2850: .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
    2851: @*/
    2852: PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps)
    2853: {
    2854:   PetscFunctionBegin;
    2856:   PetscAssertPointer(maxsteps, 2);
    2857:   *maxsteps = ts->max_steps;
    2858:   PetscFunctionReturn(PETSC_SUCCESS);
    2859: }

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

    2864:   Logically Collective

    2866:   Input Parameters:
    2867: + ts      - the `TS` context obtained from `TSCreate()`
    2868: - maxtime - final time to step to

    2870:   Options Database Key:
    2871: . -ts_max_time <maxtime> - Sets maxtime

    2873:   Level: intermediate

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

    2878:   The default maximum time is 5.0

    2880:   Fortran Note:
    2881:   Use `PETSC_DETERMINE_REAL`

    2883: .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
    2884: @*/
    2885: PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime)
    2886: {
    2887:   PetscFunctionBegin;
    2890:   if (maxtime == PETSC_DETERMINE) {
    2891:     ts->max_time = ts->default_max_time;
    2892:   } else {
    2893:     ts->max_time = maxtime;
    2894:   }
    2895:   PetscFunctionReturn(PETSC_SUCCESS);
    2896: }

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

    2901:   Not Collective

    2903:   Input Parameter:
    2904: . ts - the `TS` context obtained from `TSCreate()`

    2906:   Output Parameter:
    2907: . maxtime - final time to step to

    2909:   Level: advanced

    2911: .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
    2912: @*/
    2913: PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime)
    2914: {
    2915:   PetscFunctionBegin;
    2917:   PetscAssertPointer(maxtime, 2);
    2918:   *maxtime = ts->max_time;
    2919:   PetscFunctionReturn(PETSC_SUCCESS);
    2920: }

    2922: // PetscClangLinter pragma disable: -fdoc-*
    2923: /*@
    2924:   TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`.

    2926:   Level: deprecated

    2928: @*/
    2929: PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step)
    2930: {
    2931:   PetscFunctionBegin;
    2933:   PetscCall(TSSetTime(ts, initial_time));
    2934:   PetscCall(TSSetTimeStep(ts, time_step));
    2935:   PetscFunctionReturn(PETSC_SUCCESS);
    2936: }

    2938: // PetscClangLinter pragma disable: -fdoc-*
    2939: /*@
    2940:   TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`.

    2942:   Level: deprecated

    2944: @*/
    2945: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
    2946: {
    2947:   PetscFunctionBegin;
    2949:   if (maxsteps) {
    2950:     PetscAssertPointer(maxsteps, 2);
    2951:     *maxsteps = ts->max_steps;
    2952:   }
    2953:   if (maxtime) {
    2954:     PetscAssertPointer(maxtime, 3);
    2955:     *maxtime = ts->max_time;
    2956:   }
    2957:   PetscFunctionReturn(PETSC_SUCCESS);
    2958: }

    2960: // PetscClangLinter pragma disable: -fdoc-*
    2961: /*@
    2962:   TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`.

    2964:   Level: deprecated

    2966: @*/
    2967: PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime)
    2968: {
    2969:   PetscFunctionBegin;
    2970:   if (maxsteps != PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps));
    2971:   if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime));
    2972:   PetscFunctionReturn(PETSC_SUCCESS);
    2973: }

    2975: // PetscClangLinter pragma disable: -fdoc-*
    2976: /*@
    2977:   TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`.

    2979:   Level: deprecated

    2981: @*/
    2982: PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps)
    2983: {
    2984:   return TSGetStepNumber(ts, steps);
    2985: }

    2987: // PetscClangLinter pragma disable: -fdoc-*
    2988: /*@
    2989:   TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`.

    2991:   Level: deprecated

    2993: @*/
    2994: PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps)
    2995: {
    2996:   return TSGetStepNumber(ts, steps);
    2997: }

    2999: /*@
    3000:   TSSetSolution - Sets the initial solution vector
    3001:   for use by the `TS` routines.

    3003:   Logically Collective

    3005:   Input Parameters:
    3006: + ts - the `TS` context obtained from `TSCreate()`
    3007: - u  - the solution vector

    3009:   Level: beginner

    3011: .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
    3012: @*/
    3013: PetscErrorCode TSSetSolution(TS ts, Vec u)
    3014: {
    3015:   DM dm;

    3017:   PetscFunctionBegin;
    3020:   PetscCall(PetscObjectReference((PetscObject)u));
    3021:   PetscCall(VecDestroy(&ts->vec_sol));
    3022:   ts->vec_sol = u;

    3024:   PetscCall(TSGetDM(ts, &dm));
    3025:   PetscCall(DMShellSetGlobalVector(dm, u));
    3026:   PetscFunctionReturn(PETSC_SUCCESS);
    3027: }

    3029: /*@C
    3030:   TSSetPreStep - Sets the general-purpose function
    3031:   called once at the beginning of each time step.

    3033:   Logically Collective

    3035:   Input Parameters:
    3036: + ts   - The `TS` context obtained from `TSCreate()`
    3037: - func - The function

    3039:   Calling sequence of `func`:
    3040: . ts - the `TS` context

    3042:   Level: intermediate

    3044: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
    3045: @*/
    3046: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts))
    3047: {
    3048:   PetscFunctionBegin;
    3050:   ts->prestep = func;
    3051:   PetscFunctionReturn(PETSC_SUCCESS);
    3052: }

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

    3057:   Collective

    3059:   Input Parameter:
    3060: . ts - The `TS` context obtained from `TSCreate()`

    3062:   Level: developer

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

    3068: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
    3069: @*/
    3070: PetscErrorCode TSPreStep(TS ts)
    3071: {
    3072:   PetscFunctionBegin;
    3074:   if (ts->prestep) {
    3075:     Vec              U;
    3076:     PetscObjectId    idprev;
    3077:     PetscBool        sameObject;
    3078:     PetscObjectState sprev, spost;

    3080:     PetscCall(TSGetSolution(ts, &U));
    3081:     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
    3082:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
    3083:     PetscCallBack("TS callback preset", (*ts->prestep)(ts));
    3084:     PetscCall(TSGetSolution(ts, &U));
    3085:     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
    3086:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
    3087:     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
    3088:   }
    3089:   PetscFunctionReturn(PETSC_SUCCESS);
    3090: }

    3092: /*@C
    3093:   TSSetPreStage - Sets the general-purpose function
    3094:   called once at the beginning of each stage.

    3096:   Logically Collective

    3098:   Input Parameters:
    3099: + ts   - The `TS` context obtained from `TSCreate()`
    3100: - func - The function

    3102:   Calling sequence of `func`:
    3103: + ts        - the `TS` context
    3104: - stagetime - the stage time

    3106:   Level: intermediate

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

    3113: .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
    3114: @*/
    3115: PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime))
    3116: {
    3117:   PetscFunctionBegin;
    3119:   ts->prestage = func;
    3120:   PetscFunctionReturn(PETSC_SUCCESS);
    3121: }

    3123: /*@C
    3124:   TSSetPostStage - Sets the general-purpose function
    3125:   called once at the end of each stage.

    3127:   Logically Collective

    3129:   Input Parameters:
    3130: + ts   - The `TS` context obtained from `TSCreate()`
    3131: - func - The function

    3133:   Calling sequence of `func`:
    3134: + ts         - the `TS` context
    3135: . stagetime  - the stage time
    3136: . stageindex - the stage index
    3137: - Y          - Array of vectors (of size = total number of stages) with the stage solutions

    3139:   Level: intermediate

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

    3146: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
    3147: @*/
    3148: PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y))
    3149: {
    3150:   PetscFunctionBegin;
    3152:   ts->poststage = func;
    3153:   PetscFunctionReturn(PETSC_SUCCESS);
    3154: }

    3156: /*@C
    3157:   TSSetPostEvaluate - Sets the general-purpose function
    3158:   called at the end of each step evaluation.

    3160:   Logically Collective

    3162:   Input Parameters:
    3163: + ts   - The `TS` context obtained from `TSCreate()`
    3164: - func - The function

    3166:   Calling sequence of `func`:
    3167: . ts - the `TS` context

    3169:   Level: intermediate

    3171:   Note:
    3172:   The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback.
    3173:   Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be.
    3174:   The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`.
    3175:   The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`,
    3176:   but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below
    3177: .vb
    3178:   ...
    3179:   Step()
    3180:   PostEvaluate()
    3181:   EventHandling()
    3182:   step_rollback ? PostEvaluate() : PostStep()
    3183:   ...
    3184: .ve
    3185:   where EventHandling() may result in one of the following three outcomes
    3186: .vb
    3187:   (1) | successful step | solution intact
    3188:   (2) | successful step | solution modified by `postevent()`
    3189:   (3) | step_rollback   | solution rolled back
    3190: .ve

    3192: .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
    3193: @*/
    3194: PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts))
    3195: {
    3196:   PetscFunctionBegin;
    3198:   ts->postevaluate = func;
    3199:   PetscFunctionReturn(PETSC_SUCCESS);
    3200: }

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

    3205:   Collective

    3207:   Input Parameters:
    3208: + ts        - The `TS` context obtained from `TSCreate()`
    3209: - stagetime - The absolute time of the current stage

    3211:   Level: developer

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

    3217: .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
    3218: @*/
    3219: PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
    3220: {
    3221:   PetscFunctionBegin;
    3223:   if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
    3224:   PetscFunctionReturn(PETSC_SUCCESS);
    3225: }

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

    3230:   Collective

    3232:   Input Parameters:
    3233: + ts         - The `TS` context obtained from `TSCreate()`
    3234: . stagetime  - The absolute time of the current stage
    3235: . stageindex - Stage number
    3236: - Y          - Array of vectors (of size = total number of stages) with the stage solutions

    3238:   Level: developer

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

    3244: .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
    3245: @*/
    3246: PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
    3247: {
    3248:   PetscFunctionBegin;
    3250:   if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
    3251:   PetscFunctionReturn(PETSC_SUCCESS);
    3252: }

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

    3257:   Collective

    3259:   Input Parameter:
    3260: . ts - The `TS` context obtained from `TSCreate()`

    3262:   Level: developer

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

    3268: .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
    3269: @*/
    3270: PetscErrorCode TSPostEvaluate(TS ts)
    3271: {
    3272:   PetscFunctionBegin;
    3274:   if (ts->postevaluate) {
    3275:     Vec              U;
    3276:     PetscObjectState sprev, spost;

    3278:     PetscCall(TSGetSolution(ts, &U));
    3279:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
    3280:     PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
    3281:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
    3282:     if (sprev != spost) PetscCall(TSRestartStep(ts));
    3283:   }
    3284:   PetscFunctionReturn(PETSC_SUCCESS);
    3285: }

    3287: /*@C
    3288:   TSSetPostStep - Sets the general-purpose function
    3289:   called once at the end of each successful time step.

    3291:   Logically Collective

    3293:   Input Parameters:
    3294: + ts   - The `TS` context obtained from `TSCreate()`
    3295: - func - The function

    3297:   Calling sequence of `func`:
    3298: . ts - the `TS` context

    3300:   Level: intermediate

    3302:   Note:
    3303:   The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the
    3304:   given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will
    3305:   contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback.
    3306:   The scheme of the relevant function calls in `TSSolve()` is shown below
    3307: .vb
    3308:   ...
    3309:   Step()
    3310:   PostEvaluate()
    3311:   EventHandling()
    3312:   step_rollback ? PostEvaluate() : PostStep()
    3313:   ...
    3314: .ve
    3315:   where EventHandling() may result in one of the following three outcomes
    3316: .vb
    3317:   (1) | successful step | solution intact
    3318:   (2) | successful step | solution modified by `postevent()`
    3319:   (3) | step_rollback   | solution rolled back
    3320: .ve

    3322: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
    3323: @*/
    3324: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts))
    3325: {
    3326:   PetscFunctionBegin;
    3328:   ts->poststep = func;
    3329:   PetscFunctionReturn(PETSC_SUCCESS);
    3330: }

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

    3335:   Collective

    3337:   Input Parameter:
    3338: . ts - The `TS` context obtained from `TSCreate()`

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

    3344:   Level: developer

    3346: .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPotsStep()`
    3347: @*/
    3348: PetscErrorCode TSPostStep(TS ts)
    3349: {
    3350:   PetscFunctionBegin;
    3352:   if (ts->poststep) {
    3353:     Vec              U;
    3354:     PetscObjectId    idprev;
    3355:     PetscBool        sameObject;
    3356:     PetscObjectState sprev, spost;

    3358:     PetscCall(TSGetSolution(ts, &U));
    3359:     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
    3360:     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
    3361:     PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
    3362:     PetscCall(TSGetSolution(ts, &U));
    3363:     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
    3364:     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
    3365:     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
    3366:   }
    3367:   PetscFunctionReturn(PETSC_SUCCESS);
    3368: }

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

    3373:   Collective

    3375:   Input Parameters:
    3376: + ts - time stepping context
    3377: - t  - time to interpolate to

    3379:   Output Parameter:
    3380: . U - state at given time

    3382:   Level: intermediate

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

    3387: .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()`
    3388: @*/
    3389: PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U)
    3390: {
    3391:   PetscFunctionBegin;
    3394:   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);
    3395:   PetscUseTypeMethod(ts, interpolate, t, U);
    3396:   PetscFunctionReturn(PETSC_SUCCESS);
    3397: }

    3399: /*@
    3400:   TSStep - Steps one time step

    3402:   Collective

    3404:   Input Parameter:
    3405: . ts - the `TS` context obtained from `TSCreate()`

    3407:   Level: developer

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

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

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

    3418: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
    3419: @*/
    3420: PetscErrorCode TSStep(TS ts)
    3421: {
    3422:   static PetscBool cite = PETSC_FALSE;
    3423:   PetscReal        ptime;

    3425:   PetscFunctionBegin;
    3427:   PetscCall(PetscCitationsRegister("@article{tspaper,\n"
    3428:                                    "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
    3429:                                    "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
    3430:                                    "  journal       = {arXiv e-preprints},\n"
    3431:                                    "  eprint        = {1806.01437},\n"
    3432:                                    "  archivePrefix = {arXiv},\n"
    3433:                                    "  year          = {2018}\n}\n",
    3434:                                    &cite));
    3435:   PetscCall(TSSetUp(ts));
    3436:   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
    3437:   if (ts->eval_times)
    3438:     ts->eval_times->worktol = 0; /* In each step of TSSolve() 'eval_times->worktol' will be meaningfully defined (later) only once:
    3439:                                                    in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */

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

    3445:   if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0));
    3446:   PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0));
    3447:   ts->time_step0 = ts->time_step;

    3449:   if (!ts->steps) ts->ptime_prev = ts->ptime;
    3450:   ptime = ts->ptime;

    3452:   ts->ptime_prev_rollback = ts->ptime_prev;
    3453:   ts->reason              = TS_CONVERGED_ITERATING;

    3455:   PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
    3456:   PetscUseTypeMethod(ts, step);
    3457:   PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));

    3459:   if (ts->reason >= 0) {
    3460:     ts->ptime_prev = ptime;
    3461:     ts->steps++;
    3462:     ts->steprollback = PETSC_FALSE;
    3463:     ts->steprestart  = PETSC_FALSE;
    3464:     ts->stepresize   = PETSC_FALSE;
    3465:   }

    3467:   if (ts->reason < 0 && ts->errorifstepfailed) {
    3468:     PetscCall(TSMonitorCancel(ts));
    3469:     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]);
    3470:     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
    3471:   }
    3472:   PetscFunctionReturn(PETSC_SUCCESS);
    3473: }

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

    3479:   Collective

    3481:   Input Parameters:
    3482: + ts        - time stepping context
    3483: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

    3485:   Input/Output Parameter:
    3486: . order - optional, desired order for the error evaluation or `PETSC_DECIDE`;
    3487:            on output, the actual order of the error evaluation

    3489:   Output Parameter:
    3490: . wlte - the weighted local truncation error norm

    3492:   Level: advanced

    3494:   Note:
    3495:   If the timestepper cannot evaluate the error in a particular step
    3496:   (eg. in the first step or restart steps after event handling),
    3497:   this routine returns wlte=-1.0 .

    3499: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
    3500: @*/
    3501: PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
    3502: {
    3503:   PetscFunctionBegin;
    3507:   if (order) PetscAssertPointer(order, 3);
    3509:   PetscAssertPointer(wlte, 4);
    3510:   PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
    3511:   PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
    3512:   PetscFunctionReturn(PETSC_SUCCESS);
    3513: }

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

    3518:   Collective

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

    3525:   Output Parameter:
    3526: . U - state at the end of the current step

    3528:   Level: advanced

    3530:   Notes:
    3531:   This function cannot be called until all stages have been evaluated.

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

    3535: .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`
    3536: @*/
    3537: PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done)
    3538: {
    3539:   PetscFunctionBegin;
    3543:   PetscUseTypeMethod(ts, evaluatestep, order, U, done);
    3544:   PetscFunctionReturn(PETSC_SUCCESS);
    3545: }

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

    3550:   Not collective

    3552:   Input Parameter:
    3553: . ts - time stepping context

    3555:   Output Parameter:
    3556: . initCondition - The function which computes an initial condition

    3558:   Calling sequence of `initCondition`:
    3559: + ts - The timestepping context
    3560: - u  - The input vector in which the initial condition is stored

    3562:   Level: advanced

    3564: .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
    3565: @*/
    3566: PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u))
    3567: {
    3568:   PetscFunctionBegin;
    3570:   PetscAssertPointer(initCondition, 2);
    3571:   *initCondition = ts->ops->initcondition;
    3572:   PetscFunctionReturn(PETSC_SUCCESS);
    3573: }

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

    3578:   Logically collective

    3580:   Input Parameters:
    3581: + ts            - time stepping context
    3582: - initCondition - The function which computes an initial condition

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

    3588:   Level: advanced

    3590: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
    3591: @*/
    3592: PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e))
    3593: {
    3594:   PetscFunctionBegin;
    3597:   ts->ops->initcondition = initCondition;
    3598:   PetscFunctionReturn(PETSC_SUCCESS);
    3599: }

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

    3604:   Collective

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

    3610:   Level: advanced

    3612: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
    3613: @*/
    3614: PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
    3615: {
    3616:   PetscFunctionBegin;
    3619:   PetscTryTypeMethod(ts, initcondition, u);
    3620:   PetscFunctionReturn(PETSC_SUCCESS);
    3621: }

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

    3626:   Not collective

    3628:   Input Parameter:
    3629: . ts - time stepping context

    3631:   Output Parameter:
    3632: . exactError - The function which computes the solution error

    3634:   Calling sequence of `exactError`:
    3635: + ts - The timestepping context
    3636: . u  - The approximate solution vector
    3637: - e  - The vector in which the error is stored

    3639:   Level: advanced

    3641: .seealso: [](ch_ts), `TS`, `TSComputeExactError()`
    3642: @*/
    3643: PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e))
    3644: {
    3645:   PetscFunctionBegin;
    3647:   PetscAssertPointer(exactError, 2);
    3648:   *exactError = ts->ops->exacterror;
    3649:   PetscFunctionReturn(PETSC_SUCCESS);
    3650: }

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

    3655:   Logically collective

    3657:   Input Parameters:
    3658: + ts         - time stepping context
    3659: - exactError - The function which computes the solution error

    3661:   Calling sequence of `exactError`:
    3662: + ts - The timestepping context
    3663: . u  - The approximate solution vector
    3664: - e  - The  vector in which the error is stored

    3666:   Level: advanced

    3668: .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()`
    3669: @*/
    3670: PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e))
    3671: {
    3672:   PetscFunctionBegin;
    3675:   ts->ops->exacterror = exactError;
    3676:   PetscFunctionReturn(PETSC_SUCCESS);
    3677: }

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

    3682:   Collective

    3684:   Input Parameters:
    3685: + ts - time stepping context
    3686: . u  - The approximate solution
    3687: - e  - The `Vec` used to store the error

    3689:   Level: advanced

    3691: .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
    3692: @*/
    3693: PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
    3694: {
    3695:   PetscFunctionBegin;
    3699:   PetscTryTypeMethod(ts, exacterror, u, e);
    3700:   PetscFunctionReturn(PETSC_SUCCESS);
    3701: }

    3703: /*@C
    3704:   TSSetResize - Sets the resize callbacks.

    3706:   Logically Collective

    3708:   Input Parameters:
    3709: + ts       - The `TS` context obtained from `TSCreate()`
    3710: . rollback - Whether a resize will restart the step
    3711: . setup    - The setup function
    3712: . transfer - The transfer function
    3713: - ctx      - [optional] The user-defined context

    3715:   Calling sequence of `setup`:
    3716: + ts     - the `TS` context
    3717: . step   - the current step
    3718: . time   - the current time
    3719: . state  - the current vector of state
    3720: . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise
    3721: - ctx    - user defined context

    3723:   Calling sequence of `transfer`:
    3724: + ts      - the `TS` context
    3725: . nv      - the number of vectors to be transferred
    3726: . vecsin  - array of vectors to be transferred
    3727: . vecsout - array of transferred vectors
    3728: - ctx     - user defined context

    3730:   Notes:
    3731:   The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()`
    3732:   depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators
    3733:   and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver
    3734:   that the size of the discrete problem has changed.
    3735:   In both cases, the solver will collect the needed vectors that will be
    3736:   transferred from the old to the new sizes using the `transfer` callback. These vectors will include the
    3737:   current solution vector, and other vectors needed by the specific solver used.
    3738:   For example, `TSBDF` uses previous solutions vectors to solve for the next time step.
    3739:   Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`,
    3740:   will be automatically reset if the sizes are changed and they must be specified again by the user
    3741:   inside the `transfer` function.
    3742:   The input and output arrays passed to `transfer` are allocated by PETSc.
    3743:   Vectors in `vecsout` must be created by the user.
    3744:   Ownership of vectors in `vecsout` is transferred to PETSc.

    3746:   Level: advanced

    3748: .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()`
    3749: @*/
    3750: PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, void *ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *ctx), void *ctx)
    3751: {
    3752:   PetscFunctionBegin;
    3754:   ts->resizerollback = rollback;
    3755:   ts->resizesetup    = setup;
    3756:   ts->resizetransfer = transfer;
    3757:   ts->resizectx      = ctx;
    3758:   PetscFunctionReturn(PETSC_SUCCESS);
    3759: }

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

    3764:   Collective

    3766:   Input Parameters:
    3767: + ts   - The `TS` context obtained from `TSCreate()`
    3768: - 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.

    3770:   Level: developer

    3772:   Note:
    3773:   `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is
    3774:    used within time stepping implementations,
    3775:    so most users would not generally call this routine themselves.

    3777: .seealso: [](ch_ts), `TS`, `TSSetResize()`
    3778: @*/
    3779: static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg)
    3780: {
    3781:   PetscFunctionBegin;
    3783:   PetscTryTypeMethod(ts, resizeregister, flg);
    3784:   /* PetscTryTypeMethod(adapt, resizeregister, flg); */
    3785:   PetscFunctionReturn(PETSC_SUCCESS);
    3786: }

    3788: static PetscErrorCode TSResizeReset(TS ts)
    3789: {
    3790:   PetscFunctionBegin;
    3792:   PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs));
    3793:   PetscFunctionReturn(PETSC_SUCCESS);
    3794: }

    3796: static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[])
    3797: {
    3798:   PetscFunctionBegin;
    3801:   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i]));
    3802:   if (ts->resizetransfer) {
    3803:     PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt));
    3804:     PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx));
    3805:   }
    3806:   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i]));
    3807:   PetscFunctionReturn(PETSC_SUCCESS);
    3808: }

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

    3813:   Collective

    3815:   Input Parameters:
    3816: + ts   - The `TS` context obtained from `TSCreate()`
    3817: . name - A string identifying the vector
    3818: - vec  - The vector

    3820:   Level: developer

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

    3826: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()`
    3827: @*/
    3828: PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec)
    3829: {
    3830:   PetscFunctionBegin;
    3832:   PetscAssertPointer(name, 2);
    3834:   PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec));
    3835:   PetscFunctionReturn(PETSC_SUCCESS);
    3836: }

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

    3841:   Collective

    3843:   Input Parameters:
    3844: + ts   - The `TS` context obtained from `TSCreate()`
    3845: . name - A string identifying the vector
    3846: - vec  - The vector

    3848:   Level: developer

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

    3854: .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()`
    3855: @*/
    3856: PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec)
    3857: {
    3858:   PetscFunctionBegin;
    3860:   PetscAssertPointer(name, 2);
    3861:   PetscAssertPointer(vec, 3);
    3862:   PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec));
    3863:   PetscFunctionReturn(PETSC_SUCCESS);
    3864: }

    3866: static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[])
    3867: {
    3868:   PetscInt        cnt;
    3869:   PetscObjectList tmp;
    3870:   Vec            *vecsin  = NULL;
    3871:   const char    **namesin = NULL;

    3873:   PetscFunctionBegin;
    3874:   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next)
    3875:     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++;
    3876:   if (names) PetscCall(PetscMalloc1(cnt, &namesin));
    3877:   if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin));
    3878:   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) {
    3879:     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) {
    3880:       if (vecs) vecsin[cnt] = (Vec)tmp->obj;
    3881:       if (names) namesin[cnt] = tmp->name;
    3882:       cnt++;
    3883:     }
    3884:   }
    3885:   if (nv) *nv = cnt;
    3886:   if (names) *names = namesin;
    3887:   if (vecs) *vecs = vecsin;
    3888:   PetscFunctionReturn(PETSC_SUCCESS);
    3889: }

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

    3894:   Collective

    3896:   Input Parameter:
    3897: . ts - The `TS` context obtained from `TSCreate()`

    3899:   Level: developer

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

    3905: .seealso: [](ch_ts), `TS`, `TSSetResize()`
    3906: @*/
    3907: PetscErrorCode TSResize(TS ts)
    3908: {
    3909:   PetscInt     nv      = 0;
    3910:   const char **names   = NULL;
    3911:   Vec         *vecsin  = NULL;
    3912:   const char  *solname = "ts:vec_sol";

    3914:   PetscFunctionBegin;
    3916:   if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS);
    3917:   if (ts->resizesetup) {
    3918:     PetscCall(VecLockReadPush(ts->vec_sol));
    3919:     PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx));
    3920:     PetscCall(VecLockReadPop(ts->vec_sol));
    3921:     if (ts->stepresize) {
    3922:       if (ts->resizerollback) {
    3923:         PetscCall(TSRollBack(ts));
    3924:         ts->time_step = ts->time_step0;
    3925:       }
    3926:       PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol));
    3927:       PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */
    3928:     }
    3929:   }

    3931:   PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin));
    3932:   if (nv) {
    3933:     Vec *vecsout, vecsol;

    3935:     /* Reset internal objects */
    3936:     PetscCall(TSReset(ts));

    3938:     /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */
    3939:     PetscCall(PetscCalloc1(nv, &vecsout));
    3940:     PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout));
    3941:     for (PetscInt i = 0; i < nv; i++) {
    3942:       const char *name;
    3943:       char       *oname;

    3945:       PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
    3946:       PetscCall(PetscStrallocpy(name, &oname));
    3947:       PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i]));
    3948:       if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname));
    3949:       PetscCall(PetscFree(oname));
    3950:       PetscCall(VecDestroy(&vecsout[i]));
    3951:     }
    3952:     PetscCall(PetscFree(vecsout));
    3953:     PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */

    3955:     PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol));
    3956:     if (vecsol) PetscCall(TSSetSolution(ts, vecsol));
    3957:     PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution");
    3958:   }

    3960:   PetscCall(PetscFree(names));
    3961:   PetscCall(PetscFree(vecsin));
    3962:   PetscCall(TSResizeReset(ts));
    3963:   PetscFunctionReturn(PETSC_SUCCESS);
    3964: }

    3966: /*@
    3967:   TSSolve - Steps the requested number of timesteps.

    3969:   Collective

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

    3976:   Level: beginner

    3978:   Notes:
    3979:   The final time returned by this function may be different from the time of the internally
    3980:   held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have
    3981:   stepped over the final time.

    3983: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
    3984: @*/
    3985: PetscErrorCode TSSolve(TS ts, Vec u)
    3986: {
    3987:   Vec solution;

    3989:   PetscFunctionBegin;

    3993:   PetscCall(TSSetExactFinalTimeDefault(ts));
    3994:   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 */
    3995:     if (!ts->vec_sol || u == ts->vec_sol) {
    3996:       PetscCall(VecDuplicate(u, &solution));
    3997:       PetscCall(TSSetSolution(ts, solution));
    3998:       PetscCall(VecDestroy(&solution)); /* grant ownership */
    3999:     }
    4000:     PetscCall(VecCopy(u, ts->vec_sol));
    4001:     PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
    4002:   } else if (u) PetscCall(TSSetSolution(ts, u));
    4003:   PetscCall(TSSetUp(ts));
    4004:   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));

    4006:   PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_INT_MAX, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>");
    4007:   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()");
    4008:   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");
    4009:   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");

    4011:   if (ts->eval_times) {
    4012:     for (PetscInt i = 0; i < ts->eval_times->num_time_points; i++) {
    4013:       PetscBool is_close = PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[i], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0);
    4014:       if (ts->ptime <= ts->eval_times->time_points[i] || is_close) {
    4015:         ts->eval_times->time_point_idx = i;
    4016:         if (is_close) { /* starting point in evaluation times */
    4017:           PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_ctr]));
    4018:           ts->eval_times->sol_times[ts->eval_times->sol_ctr] = ts->ptime;
    4019:           ts->eval_times->sol_ctr++;
    4020:           ts->eval_times->time_point_idx++;
    4021:         }
    4022:         break;
    4023:       }
    4024:     }
    4025:   }

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

    4029:   /* reset number of steps only when the step is not restarted. ARKIMEX
    4030:      restarts the step after an event. Resetting these counters in such case causes
    4031:      TSTrajectory to incorrectly save the output files
    4032:   */
    4033:   /* reset time step and iteration counters */
    4034:   if (!ts->steps) {
    4035:     ts->ksp_its           = 0;
    4036:     ts->snes_its          = 0;
    4037:     ts->num_snes_failures = 0;
    4038:     ts->reject            = 0;
    4039:     ts->steprestart       = PETSC_TRUE;
    4040:     ts->steprollback      = PETSC_FALSE;
    4041:     ts->stepresize        = PETSC_FALSE;
    4042:     ts->rhsjacobian.time  = PETSC_MIN_REAL;
    4043:   }

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

    4050:     if (ts->eval_times) maxdt = ts->eval_times->time_points[ts->eval_times->time_point_idx] - ts->ptime;
    4051:     else maxdt = ts->max_time - ts->ptime;
    4052:     ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
    4053:   }
    4054:   ts->reason = TS_CONVERGED_ITERATING;

    4056:   {
    4057:     PetscViewer       viewer;
    4058:     PetscViewerFormat format;
    4059:     PetscBool         flg;
    4060:     static PetscBool  incall = PETSC_FALSE;

    4062:     if (!incall) {
    4063:       /* Estimate the convergence rate of the time discretization */
    4064:       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
    4065:       if (flg) {
    4066:         PetscConvEst conv;
    4067:         DM           dm;
    4068:         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
    4069:         PetscInt     Nf;
    4070:         PetscBool    checkTemporal = PETSC_TRUE;

    4072:         incall = PETSC_TRUE;
    4073:         PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
    4074:         PetscCall(TSGetDM(ts, &dm));
    4075:         PetscCall(DMGetNumFields(dm, &Nf));
    4076:         PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
    4077:         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
    4078:         PetscCall(PetscConvEstUseTS(conv, checkTemporal));
    4079:         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
    4080:         PetscCall(PetscConvEstSetFromOptions(conv));
    4081:         PetscCall(PetscConvEstSetUp(conv));
    4082:         PetscCall(PetscConvEstGetConvRate(conv, alpha));
    4083:         PetscCall(PetscViewerPushFormat(viewer, format));
    4084:         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
    4085:         PetscCall(PetscViewerPopFormat(viewer));
    4086:         PetscCall(PetscViewerDestroy(&viewer));
    4087:         PetscCall(PetscConvEstDestroy(&conv));
    4088:         PetscCall(PetscFree(alpha));
    4089:         incall = PETSC_FALSE;
    4090:       }
    4091:     }
    4092:   }

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

    4096:   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
    4097:     PetscUseTypeMethod(ts, solve);
    4098:     if (u) PetscCall(VecCopy(ts->vec_sol, u));
    4099:     ts->solvetime = ts->ptime;
    4100:     solution      = ts->vec_sol;
    4101:   } else { /* Step the requested number of timesteps. */
    4102:     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
    4103:     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;

    4105:     if (!ts->steps) {
    4106:       PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
    4107:       PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
    4108:     }

    4110:     while (!ts->reason) {
    4111:       PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
    4112:       if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts));
    4113:       PetscCall(TSStep(ts));
    4114:       if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
    4115:       if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
    4116:       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
    4117:         if (ts->reason >= 0) ts->steps--;            /* Revert the step number changed by TSStep() */
    4118:         PetscCall(TSForwardCostIntegral(ts));
    4119:         if (ts->reason >= 0) ts->steps++;
    4120:       }
    4121:       if (ts->forward_solve) {            /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
    4122:         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
    4123:         PetscCall(TSForwardStep(ts));
    4124:         if (ts->reason >= 0) ts->steps++;
    4125:       }
    4126:       PetscCall(TSPostEvaluate(ts));
    4127:       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. */
    4128:       if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
    4129:       if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts));
    4130:       /* check convergence */
    4131:       if (!ts->reason) {
    4132:         if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
    4133:         else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
    4134:       }
    4135:       if (!ts->steprollback) {
    4136:         PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
    4137:         PetscCall(TSPostStep(ts));
    4138:         if (!ts->resizerollback) PetscCall(TSResize(ts));

    4140:         if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points && ts->reason >= 0) {
    4141:           PetscCheck(ts->eval_times->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(eval_times->worktol > 0) in TSSolve()");
    4142:           if (PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) {
    4143:             ts->eval_times->sol_times[ts->eval_times->sol_ctr] = ts->ptime;
    4144:             PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_ctr]));
    4145:             ts->eval_times->sol_ctr++;
    4146:             ts->eval_times->time_point_idx++;
    4147:           }
    4148:         }
    4149:       }
    4150:     }
    4151:     PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));

    4153:     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
    4154:       if (!u) u = ts->vec_sol;
    4155:       PetscCall(TSInterpolate(ts, ts->max_time, u));
    4156:       ts->solvetime = ts->max_time;
    4157:       solution      = u;
    4158:       PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
    4159:     } else {
    4160:       if (u) PetscCall(VecCopy(ts->vec_sol, u));
    4161:       ts->solvetime = ts->ptime;
    4162:       solution      = ts->vec_sol;
    4163:     }
    4164:   }

    4166:   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
    4167:   PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
    4168:   PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
    4169:   if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
    4170:   PetscFunctionReturn(PETSC_SUCCESS);
    4171: }

    4173: /*@
    4174:   TSGetTime - Gets the time of the most recently completed step.

    4176:   Not Collective

    4178:   Input Parameter:
    4179: . ts - the `TS` context obtained from `TSCreate()`

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

    4184:   Level: beginner

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

    4190: .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
    4191: @*/
    4192: PetscErrorCode TSGetTime(TS ts, PetscReal *t)
    4193: {
    4194:   PetscFunctionBegin;
    4196:   PetscAssertPointer(t, 2);
    4197:   *t = ts->ptime;
    4198:   PetscFunctionReturn(PETSC_SUCCESS);
    4199: }

    4201: /*@
    4202:   TSGetPrevTime - Gets the starting time of the previously completed step.

    4204:   Not Collective

    4206:   Input Parameter:
    4207: . ts - the `TS` context obtained from `TSCreate()`

    4209:   Output Parameter:
    4210: . t - the previous time

    4212:   Level: beginner

    4214: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
    4215: @*/
    4216: PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t)
    4217: {
    4218:   PetscFunctionBegin;
    4220:   PetscAssertPointer(t, 2);
    4221:   *t = ts->ptime_prev;
    4222:   PetscFunctionReturn(PETSC_SUCCESS);
    4223: }

    4225: /*@
    4226:   TSSetTime - Allows one to reset the time.

    4228:   Logically Collective

    4230:   Input Parameters:
    4231: + ts - the `TS` context obtained from `TSCreate()`
    4232: - t  - the time

    4234:   Level: intermediate

    4236: .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()`
    4237: @*/
    4238: PetscErrorCode TSSetTime(TS ts, PetscReal t)
    4239: {
    4240:   PetscFunctionBegin;
    4243:   ts->ptime = t;
    4244:   PetscFunctionReturn(PETSC_SUCCESS);
    4245: }

    4247: /*@
    4248:   TSSetOptionsPrefix - Sets the prefix used for searching for all
    4249:   TS options in the database.

    4251:   Logically Collective

    4253:   Input Parameters:
    4254: + ts     - The `TS` context
    4255: - prefix - The prefix to prepend to all option names

    4257:   Level: advanced

    4259:   Note:
    4260:   A hyphen (-) must NOT be given at the beginning of the prefix name.
    4261:   The first character of all runtime options is AUTOMATICALLY the
    4262:   hyphen.

    4264: .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()`
    4265: @*/
    4266: PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[])
    4267: {
    4268:   SNES snes;

    4270:   PetscFunctionBegin;
    4272:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
    4273:   PetscCall(TSGetSNES(ts, &snes));
    4274:   PetscCall(SNESSetOptionsPrefix(snes, prefix));
    4275:   PetscFunctionReturn(PETSC_SUCCESS);
    4276: }

    4278: /*@
    4279:   TSAppendOptionsPrefix - Appends to the prefix used for searching for all
    4280:   TS options in the database.

    4282:   Logically Collective

    4284:   Input Parameters:
    4285: + ts     - The `TS` context
    4286: - prefix - The prefix to prepend to all option names

    4288:   Level: advanced

    4290:   Note:
    4291:   A hyphen (-) must NOT be given at the beginning of the prefix name.
    4292:   The first character of all runtime options is AUTOMATICALLY the
    4293:   hyphen.

    4295: .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()`
    4296: @*/
    4297: PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[])
    4298: {
    4299:   SNES snes;

    4301:   PetscFunctionBegin;
    4303:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
    4304:   PetscCall(TSGetSNES(ts, &snes));
    4305:   PetscCall(SNESAppendOptionsPrefix(snes, prefix));
    4306:   PetscFunctionReturn(PETSC_SUCCESS);
    4307: }

    4309: /*@
    4310:   TSGetOptionsPrefix - Sets the prefix used for searching for all
    4311:   `TS` options in the database.

    4313:   Not Collective

    4315:   Input Parameter:
    4316: . ts - The `TS` context

    4318:   Output Parameter:
    4319: . prefix - A pointer to the prefix string used

    4321:   Level: intermediate

    4323:   Fortran Notes:
    4324:   The user should pass in a string 'prefix' of
    4325:   sufficient length to hold the prefix.

    4327: .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
    4328: @*/
    4329: PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
    4330: {
    4331:   PetscFunctionBegin;
    4333:   PetscAssertPointer(prefix, 2);
    4334:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
    4335:   PetscFunctionReturn(PETSC_SUCCESS);
    4336: }

    4338: /*@C
    4339:   TSGetRHSJacobian - Returns the Jacobian J at the present timestep.

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

    4343:   Input Parameter:
    4344: . ts - The `TS` context obtained from `TSCreate()`

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

    4352:   Level: intermediate

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

    4357: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`

    4359: @*/
    4360: PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx)
    4361: {
    4362:   DM dm;

    4364:   PetscFunctionBegin;
    4365:   if (Amat || Pmat) {
    4366:     SNES snes;
    4367:     PetscCall(TSGetSNES(ts, &snes));
    4368:     PetscCall(SNESSetUpMatrices(snes));
    4369:     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
    4370:   }
    4371:   PetscCall(TSGetDM(ts, &dm));
    4372:   PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
    4373:   PetscFunctionReturn(PETSC_SUCCESS);
    4374: }

    4376: /*@C
    4377:   TSGetIJacobian - Returns the implicit Jacobian at the present timestep.

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

    4381:   Input Parameter:
    4382: . ts - The `TS` context obtained from `TSCreate()`

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

    4390:   Level: advanced

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

    4395: .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
    4396: @*/
    4397: PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx)
    4398: {
    4399:   DM dm;

    4401:   PetscFunctionBegin;
    4402:   if (Amat || Pmat) {
    4403:     SNES snes;
    4404:     PetscCall(TSGetSNES(ts, &snes));
    4405:     PetscCall(SNESSetUpMatrices(snes));
    4406:     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
    4407:   }
    4408:   PetscCall(TSGetDM(ts, &dm));
    4409:   PetscCall(DMTSGetIJacobian(dm, f, ctx));
    4410:   PetscFunctionReturn(PETSC_SUCCESS);
    4411: }

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

    4417:   Logically Collective

    4419:   Input Parameters:
    4420: + ts - the `TS` integrator object
    4421: - dm - the dm, cannot be `NULL`

    4423:   Level: intermediate

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

    4430: .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
    4431: @*/
    4432: PetscErrorCode TSSetDM(TS ts, DM dm)
    4433: {
    4434:   SNES snes;
    4435:   DMTS tsdm;

    4437:   PetscFunctionBegin;
    4440:   PetscCall(PetscObjectReference((PetscObject)dm));
    4441:   if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
    4442:     if (ts->dm->dmts && !dm->dmts) {
    4443:       PetscCall(DMCopyDMTS(ts->dm, dm));
    4444:       PetscCall(DMGetDMTS(ts->dm, &tsdm));
    4445:       /* Grant write privileges to the replacement DM */
    4446:       if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
    4447:     }
    4448:     PetscCall(DMDestroy(&ts->dm));
    4449:   }
    4450:   ts->dm = dm;

    4452:   PetscCall(TSGetSNES(ts, &snes));
    4453:   PetscCall(SNESSetDM(snes, dm));
    4454:   PetscFunctionReturn(PETSC_SUCCESS);
    4455: }

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

    4460:   Not Collective

    4462:   Input Parameter:
    4463: . ts - the `TS`

    4465:   Output Parameter:
    4466: . dm - the `DM`

    4468:   Level: intermediate

    4470: .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
    4471: @*/
    4472: PetscErrorCode TSGetDM(TS ts, DM *dm)
    4473: {
    4474:   PetscFunctionBegin;
    4476:   if (!ts->dm) {
    4477:     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
    4478:     if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
    4479:   }
    4480:   *dm = ts->dm;
    4481:   PetscFunctionReturn(PETSC_SUCCESS);
    4482: }

    4484: /*@
    4485:   SNESTSFormFunction - Function to evaluate nonlinear residual

    4487:   Logically Collective

    4489:   Input Parameters:
    4490: + snes - nonlinear solver
    4491: . U    - the current state at which to evaluate the residual
    4492: - ctx  - user context, must be a TS

    4494:   Output Parameter:
    4495: . F - the nonlinear residual

    4497:   Level: advanced

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

    4503: .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
    4504: @*/
    4505: PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx)
    4506: {
    4507:   TS ts = (TS)ctx;

    4509:   PetscFunctionBegin;
    4514:   PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
    4515:   PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
    4516:   PetscFunctionReturn(PETSC_SUCCESS);
    4517: }

    4519: /*@
    4520:   SNESTSFormJacobian - Function to evaluate the Jacobian

    4522:   Collective

    4524:   Input Parameters:
    4525: + snes - nonlinear solver
    4526: . U    - the current state at which to evaluate the residual
    4527: - ctx  - user context, must be a `TS`

    4529:   Output Parameters:
    4530: + A - the Jacobian
    4531: - B - the preconditioning matrix (may be the same as A)

    4533:   Level: developer

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

    4538: .seealso: [](ch_ts), `SNESSetJacobian()`
    4539: @*/
    4540: PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx)
    4541: {
    4542:   TS ts = (TS)ctx;

    4544:   PetscFunctionBegin;
    4550:   PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
    4551:   PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
    4552:   PetscFunctionReturn(PETSC_SUCCESS);
    4553: }

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

    4558:   Collective

    4560:   Input Parameters:
    4561: + ts  - time stepping context
    4562: . t   - time at which to evaluate
    4563: . U   - state at which to evaluate
    4564: - ctx - context

    4566:   Output Parameter:
    4567: . F - right-hand side

    4569:   Level: intermediate

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

    4575: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
    4576: @*/
    4577: PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx)
    4578: {
    4579:   Mat Arhs, Brhs;

    4581:   PetscFunctionBegin;
    4582:   PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
    4583:   /* undo the damage caused by shifting */
    4584:   PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
    4585:   PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
    4586:   PetscCall(MatMult(Arhs, U, F));
    4587:   PetscFunctionReturn(PETSC_SUCCESS);
    4588: }

    4590: /*@C
    4591:   TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.

    4593:   Collective

    4595:   Input Parameters:
    4596: + ts  - time stepping context
    4597: . t   - time at which to evaluate
    4598: . U   - state at which to evaluate
    4599: - ctx - context

    4601:   Output Parameters:
    4602: + A - pointer to operator
    4603: - B - pointer to preconditioning matrix

    4605:   Level: intermediate

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

    4610: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
    4611: @*/
    4612: PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx)
    4613: {
    4614:   PetscFunctionBegin;
    4615:   PetscFunctionReturn(PETSC_SUCCESS);
    4616: }

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

    4621:   Collective

    4623:   Input Parameters:
    4624: + ts   - time stepping context
    4625: . t    - time at which to evaluate
    4626: . U    - state at which to evaluate
    4627: . Udot - time derivative of state vector
    4628: - ctx  - context

    4630:   Output Parameter:
    4631: . F - left hand side

    4633:   Level: intermediate

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

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

    4643: .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
    4644: @*/
    4645: PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx)
    4646: {
    4647:   Mat A, B;

    4649:   PetscFunctionBegin;
    4650:   PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
    4651:   PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
    4652:   PetscCall(MatMult(A, Udot, F));
    4653:   PetscFunctionReturn(PETSC_SUCCESS);
    4654: }

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

    4659:   Collective

    4661:   Input Parameters:
    4662: + ts    - time stepping context
    4663: . t     - time at which to evaluate
    4664: . U     - state at which to evaluate
    4665: . Udot  - time derivative of state vector
    4666: . shift - shift to apply
    4667: - ctx   - context

    4669:   Output Parameters:
    4670: + A - pointer to operator
    4671: - B - pointer to matrix from which the preconditioner is built (often `A`)

    4673:   Level: advanced

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

    4678:   It is only appropriate for problems of the form

    4680:   $$
    4681:   M \dot{U} = F(U,t)
    4682:   $$

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

    4688:   $$
    4689:   shift*M + J
    4690:   $$

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

    4695: .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
    4696: @*/
    4697: PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx)
    4698: {
    4699:   PetscFunctionBegin;
    4700:   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
    4701:   ts->ijacobian.shift = shift;
    4702:   PetscFunctionReturn(PETSC_SUCCESS);
    4703: }

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

    4708:   Not Collective

    4710:   Input Parameter:
    4711: . ts - the `TS` context

    4713:   Output Parameter:
    4714: . equation_type - see `TSEquationType`

    4716:   Level: beginner

    4718: .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
    4719: @*/
    4720: PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
    4721: {
    4722:   PetscFunctionBegin;
    4724:   PetscAssertPointer(equation_type, 2);
    4725:   *equation_type = ts->equation_type;
    4726:   PetscFunctionReturn(PETSC_SUCCESS);
    4727: }

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

    4732:   Not Collective

    4734:   Input Parameters:
    4735: + ts            - the `TS` context
    4736: - equation_type - see `TSEquationType`

    4738:   Level: advanced

    4740: .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
    4741: @*/
    4742: PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
    4743: {
    4744:   PetscFunctionBegin;
    4746:   ts->equation_type = equation_type;
    4747:   PetscFunctionReturn(PETSC_SUCCESS);
    4748: }

    4750: /*@
    4751:   TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.

    4753:   Not Collective

    4755:   Input Parameter:
    4756: . ts - the `TS` context

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

    4762:   Level: beginner

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

    4767: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
    4768: @*/
    4769: PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
    4770: {
    4771:   PetscFunctionBegin;
    4773:   PetscAssertPointer(reason, 2);
    4774:   *reason = ts->reason;
    4775:   PetscFunctionReturn(PETSC_SUCCESS);
    4776: }

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

    4781:   Logically Collective; reason must contain common value

    4783:   Input Parameters:
    4784: + ts     - the `TS` context
    4785: - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
    4786:             manual pages for the individual convergence tests for complete lists

    4788:   Level: advanced

    4790:   Note:
    4791:   Can only be called while `TSSolve()` is active.

    4793: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
    4794: @*/
    4795: PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
    4796: {
    4797:   PetscFunctionBegin;
    4799:   ts->reason = reason;
    4800:   PetscFunctionReturn(PETSC_SUCCESS);
    4801: }

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

    4806:   Not Collective

    4808:   Input Parameter:
    4809: . ts - the `TS` context

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

    4814:   Level: beginner

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

    4819: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
    4820: @*/
    4821: PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
    4822: {
    4823:   PetscFunctionBegin;
    4825:   PetscAssertPointer(ftime, 2);
    4826:   *ftime = ts->solvetime;
    4827:   PetscFunctionReturn(PETSC_SUCCESS);
    4828: }

    4830: /*@
    4831:   TSGetSNESIterations - Gets the total number of nonlinear iterations
    4832:   used by the time integrator.

    4834:   Not Collective

    4836:   Input Parameter:
    4837: . ts - `TS` context

    4839:   Output Parameter:
    4840: . nits - number of nonlinear iterations

    4842:   Level: intermediate

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

    4847: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
    4848: @*/
    4849: PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
    4850: {
    4851:   PetscFunctionBegin;
    4853:   PetscAssertPointer(nits, 2);
    4854:   *nits = ts->snes_its;
    4855:   PetscFunctionReturn(PETSC_SUCCESS);
    4856: }

    4858: /*@
    4859:   TSGetKSPIterations - Gets the total number of linear iterations
    4860:   used by the time integrator.

    4862:   Not Collective

    4864:   Input Parameter:
    4865: . ts - `TS` context

    4867:   Output Parameter:
    4868: . lits - number of linear iterations

    4870:   Level: intermediate

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

    4875: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()`
    4876: @*/
    4877: PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
    4878: {
    4879:   PetscFunctionBegin;
    4881:   PetscAssertPointer(lits, 2);
    4882:   *lits = ts->ksp_its;
    4883:   PetscFunctionReturn(PETSC_SUCCESS);
    4884: }

    4886: /*@
    4887:   TSGetStepRejections - Gets the total number of rejected steps.

    4889:   Not Collective

    4891:   Input Parameter:
    4892: . ts - `TS` context

    4894:   Output Parameter:
    4895: . rejects - number of steps rejected

    4897:   Level: intermediate

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

    4902: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
    4903: @*/
    4904: PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
    4905: {
    4906:   PetscFunctionBegin;
    4908:   PetscAssertPointer(rejects, 2);
    4909:   *rejects = ts->reject;
    4910:   PetscFunctionReturn(PETSC_SUCCESS);
    4911: }

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

    4916:   Not Collective

    4918:   Input Parameter:
    4919: . ts - `TS` context

    4921:   Output Parameter:
    4922: . fails - number of failed nonlinear solves

    4924:   Level: intermediate

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

    4929: .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
    4930: @*/
    4931: PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
    4932: {
    4933:   PetscFunctionBegin;
    4935:   PetscAssertPointer(fails, 2);
    4936:   *fails = ts->num_snes_failures;
    4937:   PetscFunctionReturn(PETSC_SUCCESS);
    4938: }

    4940: /*@
    4941:   TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails

    4943:   Not Collective

    4945:   Input Parameters:
    4946: + ts      - `TS` context
    4947: - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited

    4949:   Options Database Key:
    4950: . -ts_max_reject - Maximum number of step rejections before a step fails

    4952:   Level: intermediate

    4954:   Developer Note:
    4955:   The options database name is incorrect.

    4957: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
    4958: @*/
    4959: PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
    4960: {
    4961:   PetscFunctionBegin;
    4963:   if (rejects == PETSC_UNLIMITED || rejects == -1) {
    4964:     ts->max_reject = PETSC_UNLIMITED;
    4965:   } else {
    4966:     PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
    4967:     ts->max_reject = rejects;
    4968:   }
    4969:   PetscFunctionReturn(PETSC_SUCCESS);
    4970: }

    4972: /*@
    4973:   TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves

    4975:   Not Collective

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

    4981:   Options Database Key:
    4982: . -ts_max_snes_failures - Maximum number of nonlinear solve failures

    4984:   Level: intermediate

    4986: .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
    4987: @*/
    4988: PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
    4989: {
    4990:   PetscFunctionBegin;
    4992:   if (fails == PETSC_UNLIMITED || fails == -1) {
    4993:     ts->max_snes_failures = PETSC_UNLIMITED;
    4994:   } else {
    4995:     PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
    4996:     ts->max_snes_failures = fails;
    4997:   }
    4998:   PetscFunctionReturn(PETSC_SUCCESS);
    4999: }

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

    5004:   Not Collective

    5006:   Input Parameters:
    5007: + ts  - `TS` context
    5008: - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure

    5010:   Options Database Key:
    5011: . -ts_error_if_step_fails - Error if no step succeeds

    5013:   Level: intermediate

    5015: .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
    5016: @*/
    5017: PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
    5018: {
    5019:   PetscFunctionBegin;
    5021:   ts->errorifstepfailed = err;
    5022:   PetscFunctionReturn(PETSC_SUCCESS);
    5023: }

    5025: /*@
    5026:   TSGetAdapt - Get the adaptive controller context for the current method

    5028:   Collective if controller has not yet been created

    5030:   Input Parameter:
    5031: . ts - time stepping context

    5033:   Output Parameter:
    5034: . adapt - adaptive controller

    5036:   Level: intermediate

    5038: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
    5039: @*/
    5040: PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
    5041: {
    5042:   PetscFunctionBegin;
    5044:   PetscAssertPointer(adapt, 2);
    5045:   if (!ts->adapt) {
    5046:     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
    5047:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
    5048:   }
    5049:   *adapt = ts->adapt;
    5050:   PetscFunctionReturn(PETSC_SUCCESS);
    5051: }

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

    5056:   Logically Collective

    5058:   Input Parameters:
    5059: + ts    - time integration context
    5060: . atol  - scalar absolute tolerances
    5061: . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
    5062: . rtol  - scalar relative tolerances
    5063: - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present

    5065:   Options Database Keys:
    5066: + -ts_rtol <rtol> - relative tolerance for local truncation error
    5067: - -ts_atol <atol> - Absolute tolerance for local truncation error

    5069:   Level: beginner

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

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

    5082:   Fortran Note:
    5083:   Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.

    5085: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
    5086: @*/
    5087: PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
    5088: {
    5089:   PetscFunctionBegin;
    5090:   if (atol == (PetscReal)PETSC_DETERMINE) {
    5091:     ts->atol = ts->default_atol;
    5092:   } else if (atol != (PetscReal)PETSC_CURRENT) {
    5093:     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
    5094:     ts->atol = atol;
    5095:   }

    5097:   if (vatol) {
    5098:     PetscCall(PetscObjectReference((PetscObject)vatol));
    5099:     PetscCall(VecDestroy(&ts->vatol));
    5100:     ts->vatol = vatol;
    5101:   }

    5103:   if (rtol == (PetscReal)PETSC_DETERMINE) {
    5104:     ts->rtol = ts->default_rtol;
    5105:   } else if (rtol != (PetscReal)PETSC_CURRENT) {
    5106:     PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
    5107:     ts->rtol = rtol;
    5108:   }

    5110:   if (vrtol) {
    5111:     PetscCall(PetscObjectReference((PetscObject)vrtol));
    5112:     PetscCall(VecDestroy(&ts->vrtol));
    5113:     ts->vrtol = vrtol;
    5114:   }
    5115:   PetscFunctionReturn(PETSC_SUCCESS);
    5116: }

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

    5121:   Logically Collective

    5123:   Input Parameter:
    5124: . ts - time integration context

    5126:   Output Parameters:
    5127: + atol  - scalar absolute tolerances, `NULL` to ignore
    5128: . vatol - vector of absolute tolerances, `NULL` to ignore
    5129: . rtol  - scalar relative tolerances, `NULL` to ignore
    5130: - vrtol - vector of relative tolerances, `NULL` to ignore

    5132:   Level: beginner

    5134: .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
    5135: @*/
    5136: PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
    5137: {
    5138:   PetscFunctionBegin;
    5139:   if (atol) *atol = ts->atol;
    5140:   if (vatol) *vatol = ts->vatol;
    5141:   if (rtol) *rtol = ts->rtol;
    5142:   if (vrtol) *vrtol = ts->vrtol;
    5143:   PetscFunctionReturn(PETSC_SUCCESS);
    5144: }

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

    5149:   Collective

    5151:   Input Parameters:
    5152: + ts        - time stepping context
    5153: . U         - state vector, usually ts->vec_sol
    5154: . Y         - state vector to be compared to U
    5155: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

    5157:   Output Parameters:
    5158: + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
    5159: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
    5160: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user

    5162:   Options Database Key:
    5163: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY

    5165:   Level: developer

    5167: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
    5168: @*/
    5169: PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
    5170: {
    5171:   PetscInt norma_loc, norm_loc, normr_loc;

    5173:   PetscFunctionBegin;
    5175:   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));
    5176:   if (wnormtype == NORM_2) {
    5177:     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
    5178:     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
    5179:     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
    5180:   }
    5181:   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
    5182:   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
    5183:   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
    5184:   PetscFunctionReturn(PETSC_SUCCESS);
    5185: }

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

    5190:   Collective

    5192:   Input Parameters:
    5193: + ts        - time stepping context
    5194: . E         - error vector
    5195: . U         - state vector, usually ts->vec_sol
    5196: . Y         - state vector, previous time step
    5197: - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`

    5199:   Output Parameters:
    5200: + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
    5201: . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
    5202: - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user

    5204:   Options Database Key:
    5205: . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY

    5207:   Level: developer

    5209: .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
    5210: @*/
    5211: PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
    5212: {
    5213:   PetscInt norma_loc, norm_loc, normr_loc;

    5215:   PetscFunctionBegin;
    5217:   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));
    5218:   if (wnormtype == NORM_2) {
    5219:     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
    5220:     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
    5221:     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
    5222:   }
    5223:   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
    5224:   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
    5225:   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
    5226:   PetscFunctionReturn(PETSC_SUCCESS);
    5227: }

    5229: /*@
    5230:   TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler

    5232:   Logically Collective

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

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

    5241:   Level: intermediate

    5243: .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
    5244: @*/
    5245: PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
    5246: {
    5247:   PetscFunctionBegin;
    5249:   ts->cfltime_local = cfltime;
    5250:   ts->cfltime       = -1.;
    5251:   PetscFunctionReturn(PETSC_SUCCESS);
    5252: }

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

    5257:   Collective

    5259:   Input Parameter:
    5260: . ts - time stepping context

    5262:   Output Parameter:
    5263: . cfltime - maximum stable time step for forward Euler

    5265:   Level: advanced

    5267: .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
    5268: @*/
    5269: PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
    5270: {
    5271:   PetscFunctionBegin;
    5272:   if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
    5273:   *cfltime = ts->cfltime;
    5274:   PetscFunctionReturn(PETSC_SUCCESS);
    5275: }

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

    5280:   Input Parameters:
    5281: + ts - the `TS` context.
    5282: . xl - lower bound.
    5283: - xu - upper bound.

    5285:   Level: advanced

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

    5291: .seealso: [](ch_ts), `TS`
    5292: @*/
    5293: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
    5294: {
    5295:   SNES snes;

    5297:   PetscFunctionBegin;
    5298:   PetscCall(TSGetSNES(ts, &snes));
    5299:   PetscCall(SNESVISetVariableBounds(snes, xl, xu));
    5300:   PetscFunctionReturn(PETSC_SUCCESS);
    5301: }

    5303: /*@
    5304:   TSComputeLinearStability - computes the linear stability function at a point

    5306:   Collective

    5308:   Input Parameters:
    5309: + ts - the `TS` context
    5310: . xr - real part of input argument
    5311: - xi - imaginary part of input argument

    5313:   Output Parameters:
    5314: + yr - real part of function value
    5315: - yi - imaginary part of function value

    5317:   Level: developer

    5319: .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
    5320: @*/
    5321: PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
    5322: {
    5323:   PetscFunctionBegin;
    5325:   PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
    5326:   PetscFunctionReturn(PETSC_SUCCESS);
    5327: }

    5329: /*@
    5330:   TSRestartStep - Flags the solver to restart the next step

    5332:   Collective

    5334:   Input Parameter:
    5335: . ts - the `TS` context obtained from `TSCreate()`

    5337:   Level: advanced

    5339:   Notes:
    5340:   Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
    5341:   discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
    5342:   vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
    5343:   the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
    5344:   discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
    5345:   discontinuous source terms).

    5347: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
    5348: @*/
    5349: PetscErrorCode TSRestartStep(TS ts)
    5350: {
    5351:   PetscFunctionBegin;
    5353:   ts->steprestart = PETSC_TRUE;
    5354:   PetscFunctionReturn(PETSC_SUCCESS);
    5355: }

    5357: /*@
    5358:   TSRollBack - Rolls back one time step

    5360:   Collective

    5362:   Input Parameter:
    5363: . ts - the `TS` context obtained from `TSCreate()`

    5365:   Level: advanced

    5367: .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
    5368: @*/
    5369: PetscErrorCode TSRollBack(TS ts)
    5370: {
    5371:   PetscFunctionBegin;
    5373:   PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
    5374:   PetscTryTypeMethod(ts, rollback);
    5375:   PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
    5376:   ts->time_step  = ts->ptime - ts->ptime_prev;
    5377:   ts->ptime      = ts->ptime_prev;
    5378:   ts->ptime_prev = ts->ptime_prev_rollback;
    5379:   ts->steps--;
    5380:   ts->steprollback = PETSC_TRUE;
    5381:   PetscFunctionReturn(PETSC_SUCCESS);
    5382: }

    5384: /*@
    5385:   TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step

    5387:   Not collective

    5389:   Input Parameter:
    5390: . ts - the `TS` context obtained from `TSCreate()`

    5392:   Output Parameter:
    5393: . flg - the rollback flag

    5395:   Level: advanced

    5397: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
    5398: @*/
    5399: PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
    5400: {
    5401:   PetscFunctionBegin;
    5403:   PetscAssertPointer(flg, 2);
    5404:   *flg = ts->steprollback;
    5405:   PetscFunctionReturn(PETSC_SUCCESS);
    5406: }

    5408: /*@
    5409:   TSGetStepResize - Get the internal flag indicating if the current step is after a resize.

    5411:   Not collective

    5413:   Input Parameter:
    5414: . ts - the `TS` context obtained from `TSCreate()`

    5416:   Output Parameter:
    5417: . flg - the resize flag

    5419:   Level: advanced

    5421: .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
    5422: @*/
    5423: PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
    5424: {
    5425:   PetscFunctionBegin;
    5427:   PetscAssertPointer(flg, 2);
    5428:   *flg = ts->stepresize;
    5429:   PetscFunctionReturn(PETSC_SUCCESS);
    5430: }

    5432: /*@
    5433:   TSGetStages - Get the number of stages and stage values

    5435:   Input Parameter:
    5436: . ts - the `TS` context obtained from `TSCreate()`

    5438:   Output Parameters:
    5439: + ns - the number of stages
    5440: - Y  - the current stage vectors

    5442:   Level: advanced

    5444:   Note:
    5445:   Both `ns` and `Y` can be `NULL`.

    5447: .seealso: [](ch_ts), `TS`, `TSCreate()`
    5448: @*/
    5449: PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
    5450: {
    5451:   PetscFunctionBegin;
    5453:   if (ns) PetscAssertPointer(ns, 2);
    5454:   if (Y) PetscAssertPointer(Y, 3);
    5455:   if (!ts->ops->getstages) {
    5456:     if (ns) *ns = 0;
    5457:     if (Y) *Y = NULL;
    5458:   } else PetscUseTypeMethod(ts, getstages, ns, Y);
    5459:   PetscFunctionReturn(PETSC_SUCCESS);
    5460: }

    5462: /*@C
    5463:   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.

    5465:   Collective

    5467:   Input Parameters:
    5468: + ts    - the `TS` context
    5469: . t     - current timestep
    5470: . U     - state vector
    5471: . Udot  - time derivative of state vector
    5472: . shift - shift to apply, see note below
    5473: - ctx   - an optional user context

    5475:   Output Parameters:
    5476: + J - Jacobian matrix (not altered in this routine)
    5477: - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)

    5479:   Level: intermediate

    5481:   Notes:
    5482:   If F(t,U,Udot)=0 is the DAE, the required Jacobian is

    5484:   dF/dU + shift*dF/dUdot

    5486:   Most users should not need to explicitly call this routine, as it
    5487:   is used internally within the nonlinear solvers.

    5489:   This will first try to get the coloring from the `DM`.  If the `DM` type has no coloring
    5490:   routine, then it will try to get the coloring from the matrix.  This requires that the
    5491:   matrix have nonzero entries precomputed.

    5493: .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
    5494: @*/
    5495: PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx)
    5496: {
    5497:   SNES          snes;
    5498:   MatFDColoring color;
    5499:   PetscBool     hascolor, matcolor = PETSC_FALSE;

    5501:   PetscFunctionBegin;
    5502:   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
    5503:   PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
    5504:   if (!color) {
    5505:     DM         dm;
    5506:     ISColoring iscoloring;

    5508:     PetscCall(TSGetDM(ts, &dm));
    5509:     PetscCall(DMHasColoring(dm, &hascolor));
    5510:     if (hascolor && !matcolor) {
    5511:       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
    5512:       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
    5513:       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
    5514:       PetscCall(MatFDColoringSetFromOptions(color));
    5515:       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
    5516:       PetscCall(ISColoringDestroy(&iscoloring));
    5517:     } else {
    5518:       MatColoring mc;

    5520:       PetscCall(MatColoringCreate(B, &mc));
    5521:       PetscCall(MatColoringSetDistance(mc, 2));
    5522:       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
    5523:       PetscCall(MatColoringSetFromOptions(mc));
    5524:       PetscCall(MatColoringApply(mc, &iscoloring));
    5525:       PetscCall(MatColoringDestroy(&mc));
    5526:       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
    5527:       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
    5528:       PetscCall(MatFDColoringSetFromOptions(color));
    5529:       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
    5530:       PetscCall(ISColoringDestroy(&iscoloring));
    5531:     }
    5532:     PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
    5533:     PetscCall(PetscObjectDereference((PetscObject)color));
    5534:   }
    5535:   PetscCall(TSGetSNES(ts, &snes));
    5536:   PetscCall(MatFDColoringApply(B, color, U, snes));
    5537:   if (J != B) {
    5538:     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
    5539:     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
    5540:   }
    5541:   PetscFunctionReturn(PETSC_SUCCESS);
    5542: }

    5544: /*@C
    5545:   TSSetFunctionDomainError - Set a function that tests if the current state vector is valid

    5547:   Input Parameters:
    5548: + ts   - the `TS` context
    5549: - func - function called within `TSFunctionDomainError()`

    5551:   Calling sequence of `func`:
    5552: + ts     - the `TS` context
    5553: . time   - the current time (of the stage)
    5554: . state  - the state to check if it is valid
    5555: - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable

    5557:   Level: intermediate

    5559:   Notes:
    5560:   If an implicit ODE solver is being used then, in addition to providing this routine, the
    5561:   user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
    5562:   function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
    5563:   Use `TSGetSNES()` to obtain the `SNES` object

    5565:   Developer Notes:
    5566:   The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
    5567:   since one takes a function pointer and the other does not.

    5569: .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
    5570: @*/
    5571: PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
    5572: {
    5573:   PetscFunctionBegin;
    5575:   ts->functiondomainerror = func;
    5576:   PetscFunctionReturn(PETSC_SUCCESS);
    5577: }

    5579: /*@
    5580:   TSFunctionDomainError - Checks if the current state is valid

    5582:   Input Parameters:
    5583: + ts        - the `TS` context
    5584: . stagetime - time of the simulation
    5585: - Y         - state vector to check.

    5587:   Output Parameter:
    5588: . accept - Set to `PETSC_FALSE` if the current state vector is valid.

    5590:   Level: developer

    5592:   Note:
    5593:   This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
    5594:   to check if the current state is valid.

    5596: .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
    5597: @*/
    5598: PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
    5599: {
    5600:   PetscFunctionBegin;
    5602:   *accept = PETSC_TRUE;
    5603:   if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
    5604:   PetscFunctionReturn(PETSC_SUCCESS);
    5605: }

    5607: /*@
    5608:   TSClone - This function clones a time step `TS` object.

    5610:   Collective

    5612:   Input Parameter:
    5613: . tsin - The input `TS`

    5615:   Output Parameter:
    5616: . tsout - The output `TS` (cloned)

    5618:   Level: developer

    5620:   Notes:
    5621:   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.
    5622:   It will likely be replaced in the future with a mechanism of switching methods on the fly.

    5624:   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
    5625: .vb
    5626:  SNES snes_dup = NULL;
    5627:  TSGetSNES(ts,&snes_dup);
    5628:  TSSetSNES(ts,snes_dup);
    5629: .ve

    5631: .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
    5632: @*/
    5633: PetscErrorCode TSClone(TS tsin, TS *tsout)
    5634: {
    5635:   TS     t;
    5636:   SNES   snes_start;
    5637:   DM     dm;
    5638:   TSType type;

    5640:   PetscFunctionBegin;
    5641:   PetscAssertPointer(tsin, 1);
    5642:   *tsout = NULL;

    5644:   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));

    5646:   /* General TS description */
    5647:   t->numbermonitors    = 0;
    5648:   t->monitorFrequency  = 1;
    5649:   t->setupcalled       = 0;
    5650:   t->ksp_its           = 0;
    5651:   t->snes_its          = 0;
    5652:   t->nwork             = 0;
    5653:   t->rhsjacobian.time  = PETSC_MIN_REAL;
    5654:   t->rhsjacobian.scale = 1.;
    5655:   t->ijacobian.shift   = 1.;

    5657:   PetscCall(TSGetSNES(tsin, &snes_start));
    5658:   PetscCall(TSSetSNES(t, snes_start));

    5660:   PetscCall(TSGetDM(tsin, &dm));
    5661:   PetscCall(TSSetDM(t, dm));

    5663:   t->adapt = tsin->adapt;
    5664:   PetscCall(PetscObjectReference((PetscObject)t->adapt));

    5666:   t->trajectory = tsin->trajectory;
    5667:   PetscCall(PetscObjectReference((PetscObject)t->trajectory));

    5669:   t->event = tsin->event;
    5670:   if (t->event) t->event->refct++;

    5672:   t->problem_type      = tsin->problem_type;
    5673:   t->ptime             = tsin->ptime;
    5674:   t->ptime_prev        = tsin->ptime_prev;
    5675:   t->time_step         = tsin->time_step;
    5676:   t->max_time          = tsin->max_time;
    5677:   t->steps             = tsin->steps;
    5678:   t->max_steps         = tsin->max_steps;
    5679:   t->equation_type     = tsin->equation_type;
    5680:   t->atol              = tsin->atol;
    5681:   t->rtol              = tsin->rtol;
    5682:   t->max_snes_failures = tsin->max_snes_failures;
    5683:   t->max_reject        = tsin->max_reject;
    5684:   t->errorifstepfailed = tsin->errorifstepfailed;

    5686:   PetscCall(TSGetType(tsin, &type));
    5687:   PetscCall(TSSetType(t, type));

    5689:   t->vec_sol = NULL;

    5691:   t->cfltime          = tsin->cfltime;
    5692:   t->cfltime_local    = tsin->cfltime_local;
    5693:   t->exact_final_time = tsin->exact_final_time;

    5695:   t->ops[0] = tsin->ops[0];

    5697:   if (((PetscObject)tsin)->fortran_func_pointers) {
    5698:     PetscInt i;
    5699:     PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers));
    5700:     for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
    5701:   }
    5702:   *tsout = t;
    5703:   PetscFunctionReturn(PETSC_SUCCESS);
    5704: }

    5706: static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y)
    5707: {
    5708:   TS ts = (TS)ctx;

    5710:   PetscFunctionBegin;
    5711:   PetscCall(TSComputeRHSFunction(ts, 0, x, y));
    5712:   PetscFunctionReturn(PETSC_SUCCESS);
    5713: }

    5715: /*@
    5716:   TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.

    5718:   Logically Collective

    5720:   Input Parameter:
    5721: . ts - the time stepping routine

    5723:   Output Parameter:
    5724: . flg - `PETSC_TRUE` if the multiply is likely correct

    5726:   Options Database Key:
    5727: . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator

    5729:   Level: advanced

    5731:   Note:
    5732:   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian

    5734: .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
    5735: @*/
    5736: PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
    5737: {
    5738:   Mat              J, B;
    5739:   TSRHSJacobianFn *func;
    5740:   void            *ctx;

    5742:   PetscFunctionBegin;
    5743:   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
    5744:   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
    5745:   PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
    5746:   PetscFunctionReturn(PETSC_SUCCESS);
    5747: }

    5749: /*@
    5750:   TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.

    5752:   Logically Collective

    5754:   Input Parameter:
    5755: . ts - the time stepping routine

    5757:   Output Parameter:
    5758: . flg - `PETSC_TRUE` if the multiply is likely correct

    5760:   Options Database Key:
    5761: . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator

    5763:   Level: advanced

    5765:   Notes:
    5766:   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian

    5768: .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
    5769: @*/
    5770: PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
    5771: {
    5772:   Mat              J, B;
    5773:   void            *ctx;
    5774:   TSRHSJacobianFn *func;

    5776:   PetscFunctionBegin;
    5777:   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
    5778:   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
    5779:   PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
    5780:   PetscFunctionReturn(PETSC_SUCCESS);
    5781: }

    5783: /*@
    5784:   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.

    5786:   Logically Collective

    5788:   Input Parameters:
    5789: + ts                   - timestepping context
    5790: - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used

    5792:   Options Database Key:
    5793: . -ts_use_splitrhsfunction - <true,false>

    5795:   Level: intermediate

    5797:   Note:
    5798:   This is only for multirate methods

    5800: .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
    5801: @*/
    5802: PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
    5803: {
    5804:   PetscFunctionBegin;
    5806:   ts->use_splitrhsfunction = use_splitrhsfunction;
    5807:   PetscFunctionReturn(PETSC_SUCCESS);
    5808: }

    5810: /*@
    5811:   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.

    5813:   Not Collective

    5815:   Input Parameter:
    5816: . ts - timestepping context

    5818:   Output Parameter:
    5819: . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used

    5821:   Level: intermediate

    5823: .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
    5824: @*/
    5825: PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
    5826: {
    5827:   PetscFunctionBegin;
    5829:   *use_splitrhsfunction = ts->use_splitrhsfunction;
    5830:   PetscFunctionReturn(PETSC_SUCCESS);
    5831: }

    5833: /*@
    5834:   TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.

    5836:   Logically  Collective

    5838:   Input Parameters:
    5839: + ts  - the time-stepper
    5840: - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)

    5842:   Level: intermediate

    5844:   Note:
    5845:   When the relationship between the nonzero structures is known and supplied the solution process can be much faster

    5847: .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
    5848:  @*/
    5849: PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
    5850: {
    5851:   PetscFunctionBegin;
    5853:   ts->axpy_pattern = str;
    5854:   PetscFunctionReturn(PETSC_SUCCESS);
    5855: }

    5857: /*@
    5858:   TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested

    5860:   Collective

    5862:   Input Parameters:
    5863: + ts          - the time-stepper
    5864: . n           - number of the time points
    5865: - time_points - array of the time points

    5867:   Options Database Key:
    5868: . -ts_eval_times <t0,...tn> - Sets the evaluation times

    5870:   Level: intermediate

    5872:   Notes:
    5873:   The elements in `time_points` must be all increasing. They correspond to the intermediate points for time integration.

    5875:   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.

    5877:   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may
    5878:   pressure the memory system when using a large number of time points.

    5880: .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()`
    5881:  @*/
    5882: PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal *time_points)
    5883: {
    5884:   PetscBool is_sorted;

    5886:   PetscFunctionBegin;
    5888:   if (ts->eval_times && n != ts->eval_times->num_time_points) {
    5889:     PetscCall(PetscFree(ts->eval_times->time_points));
    5890:     PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
    5891:     PetscCall(PetscMalloc1(n, &ts->eval_times->time_points));
    5892:   }
    5893:   if (!ts->eval_times) {
    5894:     TSEvaluationTimes eval_times;
    5895:     PetscCall(PetscNew(&eval_times));
    5896:     PetscCall(PetscMalloc1(n, &eval_times->time_points));
    5897:     eval_times->reltol  = 1e-6;
    5898:     eval_times->abstol  = 10 * PETSC_MACHINE_EPSILON;
    5899:     eval_times->worktol = 0;
    5900:     ts->eval_times      = eval_times;
    5901:   }
    5902:   ts->eval_times->num_time_points = n;
    5903:   PetscCall(PetscSortedReal(n, time_points, &is_sorted));
    5904:   PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted");
    5905:   PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n));
    5906:   PetscFunctionReturn(PETSC_SUCCESS);
    5907: }

    5909: /*@C
    5910:   TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()`

    5912:   Not Collective

    5914:   Input Parameter:
    5915: . ts - the time-stepper

    5917:   Output Parameters:
    5918: + n           - number of the time points
    5919: - time_points - array of the time points

    5921:   Level: beginner

    5923:   Note:
    5924:   The values obtained are valid until the `TS` object is destroyed.

    5926:   Both `n` and `time_points` can be `NULL`.

    5928:   Also used to see time points set by `TSSetTimeSpan()`.

    5930: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()`
    5931:  @*/
    5932: PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[])
    5933: {
    5934:   PetscFunctionBegin;
    5936:   if (n) PetscAssertPointer(n, 2);
    5937:   if (time_points) PetscAssertPointer(time_points, 3);
    5938:   if (!ts->eval_times) {
    5939:     if (n) *n = 0;
    5940:     if (time_points) *time_points = NULL;
    5941:   } else {
    5942:     if (n) *n = ts->eval_times->num_time_points;
    5943:     if (time_points) *time_points = ts->eval_times->time_points;
    5944:   }
    5945:   PetscFunctionReturn(PETSC_SUCCESS);
    5946: }

    5948: /*@C
    5949:   TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified

    5951:   Input Parameter:
    5952: . ts - the `TS` context obtained from `TSCreate()`

    5954:   Output Parameters:
    5955: + nsol      - the number of solutions
    5956: . sol_times - array of solution times corresponding to the solution vectors. See note below
    5957: - Sols      - the solution vectors

    5959:   Level: intermediate

    5961:   Notes:
    5962:   Both `nsol` and `Sols` can be `NULL`.

    5964:   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()`.
    5965:   For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times.

    5967:   Also used to see view solutions requested by `TSSetTimeSpan()`.

    5969: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`
    5970: @*/
    5971: PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec **Sols)
    5972: {
    5973:   PetscFunctionBegin;
    5975:   if (nsol) PetscAssertPointer(nsol, 2);
    5976:   if (sol_times) PetscAssertPointer(sol_times, 3);
    5977:   if (Sols) PetscAssertPointer(Sols, 4);
    5978:   if (!ts->eval_times) {
    5979:     if (nsol) *nsol = 0;
    5980:     if (sol_times) *sol_times = NULL;
    5981:     if (Sols) *Sols = NULL;
    5982:   } else {
    5983:     if (nsol) *nsol = ts->eval_times->sol_ctr;
    5984:     if (sol_times) *sol_times = ts->eval_times->sol_times;
    5985:     if (Sols) *Sols = ts->eval_times->sol_vecs;
    5986:   }
    5987:   PetscFunctionReturn(PETSC_SUCCESS);
    5988: }

    5990: /*@
    5991:   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span

    5993:   Collective

    5995:   Input Parameters:
    5996: + ts         - the time-stepper
    5997: . n          - number of the time points (>=2)
    5998: - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.

    6000:   Options Database Key:
    6001: . -ts_time_span <t0,...tf> - Sets the time span

    6003:   Level: intermediate

    6005:   Notes:
    6006:   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.

    6008:   The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.

    6010:   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.

    6012:   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may
    6013:   pressure the memory system when using a large number of span points.

    6015: .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`
    6016:  @*/
    6017: PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times)
    6018: {
    6019:   PetscFunctionBegin;
    6021:   PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
    6022:   PetscCall(TSSetEvaluationTimes(ts, n, span_times));
    6023:   PetscCall(TSSetTime(ts, span_times[0]));
    6024:   PetscCall(TSSetMaxTime(ts, span_times[n - 1]));
    6025:   PetscFunctionReturn(PETSC_SUCCESS);
    6026: }

    6028: /*@
    6029:   TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.

    6031:   Collective

    6033:   Input Parameters:
    6034: + ts - the `TS` context
    6035: . J  - Jacobian matrix (not altered in this routine)
    6036: - B  - newly computed Jacobian matrix to use with preconditioner

    6038:   Level: intermediate

    6040:   Notes:
    6041:   This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
    6042:   many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
    6043:   and multiple fields are involved.

    6045:   Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
    6046:   structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
    6047:   usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
    6048:   `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.

    6050: .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
    6051: @*/
    6052: PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
    6053: {
    6054:   MatColoring   mc            = NULL;
    6055:   ISColoring    iscoloring    = NULL;
    6056:   MatFDColoring matfdcoloring = NULL;

    6058:   PetscFunctionBegin;
    6059:   /* Generate new coloring after eliminating zeros in the matrix */
    6060:   PetscCall(MatEliminateZeros(B, PETSC_TRUE));
    6061:   PetscCall(MatColoringCreate(B, &mc));
    6062:   PetscCall(MatColoringSetDistance(mc, 2));
    6063:   PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
    6064:   PetscCall(MatColoringSetFromOptions(mc));
    6065:   PetscCall(MatColoringApply(mc, &iscoloring));
    6066:   PetscCall(MatColoringDestroy(&mc));
    6067:   /* Replace the old coloring with the new one */
    6068:   PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
    6069:   PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
    6070:   PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
    6071:   PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
    6072:   PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
    6073:   PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
    6074:   PetscCall(ISColoringDestroy(&iscoloring));
    6075:   PetscFunctionReturn(PETSC_SUCCESS);
    6076: }