1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscdmda.h> 3 #include <petscdmshell.h> 4 #include <petscdmplex.h> // For TSSetFromOptions() 5 #include <petscdmswarm.h> // For TSSetFromOptions() 6 #include <petscviewer.h> 7 #include <petscdraw.h> 8 #include <petscconvest.h> 9 10 /* Logging support */ 11 PetscClassId TS_CLASSID, DMTS_CLASSID; 12 PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval; 13 14 const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED", "STEPOVER", "INTERPOLATE", "MATCHSTEP", "TSExactFinalTimeOption", "TS_EXACTFINALTIME_", NULL}; 15 16 static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt, TSAdaptType default_type) 17 { 18 PetscFunctionBegin; 19 PetscValidHeaderSpecific(adapt, TSADAPT_CLASSID, 1); 20 PetscAssertPointer(default_type, 2); 21 if (!((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, default_type)); 22 PetscFunctionReturn(PETSC_SUCCESS); 23 } 24 25 /*@ 26 TSSetFromOptions - Sets various `TS` parameters from the options database 27 28 Collective 29 30 Input Parameter: 31 . ts - the `TS` context obtained from `TSCreate()` 32 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 71 72 Level: beginner 73 74 Notes: 75 See `SNESSetFromOptions()` and `KSPSetFromOptions()` for how to control the nonlinear and linear solves used by the time-stepper. 76 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` 80 81 Developer Notes: 82 We should unify all the -ts_monitor options in the way that -xxx_view has been unified 83 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]; 97 98 PetscFunctionBegin; 99 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 100 101 PetscCall(TSRegisterAll()); 102 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 103 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)); 110 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)); 133 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 145 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)); 152 153 PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 154 if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename)); 155 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; 161 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 } 176 177 PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt)); 178 if (opt) { 179 TSMonitorLGCtx ctx; 180 PetscInt howoften = 1; 181 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)); 187 188 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt)); 189 if (opt) { 190 TSMonitorLGCtx ctx; 191 PetscInt howoften = 1; 192 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; 201 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 } 207 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; 212 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; 221 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; 230 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; 240 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; 260 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; 269 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; 287 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; 300 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; 315 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; 325 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 } 330 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; 335 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 } 340 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; 348 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); 354 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; 371 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); 377 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 } 385 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; 389 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)); 396 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; 401 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 } 407 408 /* Handle specific TS options */ 409 PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject); 410 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)); 415 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)); 420 421 PetscCall(TSAdjointSetFromOptions(ts, PetscOptionsObject)); 422 423 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 424 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject)); 425 PetscOptionsEnd(); 426 427 if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory, ts)); 428 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 } 438 439 /*@ 440 TSGetTrajectory - Gets the trajectory from a `TS` if it exists 441 442 Collective 443 444 Input Parameter: 445 . ts - the `TS` context obtained from `TSCreate()` 446 447 Output Parameter: 448 . tr - the `TSTrajectory` object, if it exists 449 450 Level: advanced 451 452 Note: 453 This routine should be called after all `TS` options have been set 454 455 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()` 456 @*/ 457 PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 461 *tr = ts->trajectory; 462 PetscFunctionReturn(PETSC_SUCCESS); 463 } 464 465 /*@ 466 TSSetSaveTrajectory - Causes the `TS` to save its solutions as it iterates forward in time in a `TSTrajectory` object 467 468 Collective 469 470 Input Parameter: 471 . ts - the `TS` context obtained from `TSCreate()` 472 473 Options Database Keys: 474 + -ts_save_trajectory - saves the trajectory to a file 475 - -ts_trajectory_type type - set trajectory type 476 477 Level: intermediate 478 479 Notes: 480 This routine should be called after all `TS` options have been set 481 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 484 485 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()` 486 @*/ 487 PetscErrorCode TSSetSaveTrajectory(TS ts) 488 { 489 PetscFunctionBegin; 490 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 491 if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory)); 492 PetscFunctionReturn(PETSC_SUCCESS); 493 } 494 495 /*@ 496 TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object 497 498 Collective 499 500 Input Parameter: 501 . ts - the `TS` context obtained from `TSCreate()` 502 503 Level: intermediate 504 505 .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()` 506 @*/ 507 PetscErrorCode TSResetTrajectory(TS ts) 508 { 509 PetscFunctionBegin; 510 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 511 if (ts->trajectory) { 512 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 513 PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory)); 514 } 515 PetscFunctionReturn(PETSC_SUCCESS); 516 } 517 518 /*@ 519 TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from a `TS` 520 521 Collective 522 523 Input Parameter: 524 . ts - the `TS` context obtained from `TSCreate()` 525 526 Level: intermediate 527 528 .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()` 529 @*/ 530 PetscErrorCode TSRemoveTrajectory(TS ts) 531 { 532 PetscFunctionBegin; 533 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 534 if (ts->trajectory) PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 535 PetscFunctionReturn(PETSC_SUCCESS); 536 } 537 538 /*@ 539 TSComputeRHSJacobian - Computes the Jacobian matrix that has been 540 set with `TSSetRHSJacobian()`. 541 542 Collective 543 544 Input Parameters: 545 + ts - the `TS` context 546 . t - current timestep 547 - U - input vector 548 549 Output Parameters: 550 + A - Jacobian matrix 551 - B - optional preconditioning matrix 552 553 Level: developer 554 555 Note: 556 Most users should not need to explicitly call this routine, as it 557 is used internally within the nonlinear solvers. 558 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; 570 571 PetscFunctionBegin; 572 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 573 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 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)); 581 582 if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(PETSC_SUCCESS); 583 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 } 601 602 /*@ 603 TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS` 604 605 Collective 606 607 Input Parameters: 608 + ts - the `TS` context 609 . t - current time 610 - U - state vector 611 612 Output Parameter: 613 . y - right-hand side 614 615 Level: developer 616 617 Note: 618 Most users should not need to explicitly call this routine, as it 619 is used internally within the nonlinear solvers. 620 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; 629 630 PetscFunctionBegin; 631 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 632 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 633 PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 634 PetscCall(TSGetDM(ts, &dm)); 635 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx)); 636 PetscCall(DMTSGetIFunction(dm, &ifunction, NULL)); 637 638 PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()"); 639 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 } 650 651 /*@ 652 TSComputeSolutionFunction - Evaluates the solution function. 653 654 Collective 655 656 Input Parameters: 657 + ts - the `TS` context 658 - t - current time 659 660 Output Parameter: 661 . U - the solution 662 663 Level: developer 664 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; 672 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 675 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 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. 683 684 Collective 685 686 Input Parameters: 687 + ts - the `TS` context 688 - t - current time 689 690 Output Parameter: 691 . U - the function value 692 693 Level: developer 694 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; 702 703 PetscFunctionBegin; 704 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 705 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 706 PetscCall(TSGetDM(ts, &dm)); 707 PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx)); 708 709 if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx)); 710 PetscFunctionReturn(PETSC_SUCCESS); 711 } 712 713 PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs) 714 { 715 Mat A, B; 716 TSIJacobianFn *ijacobian; 717 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 } 761 762 /*@ 763 TSComputeIFunction - Evaluates the DAE residual written in the implicit form F(t,U,Udot)=0 764 765 Collective 766 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 773 774 Output Parameter: 775 . Y - right-hand side 776 777 Level: developer 778 779 Note: 780 Most users should not need to explicitly call this routine, as it 781 is used internally within the nonlinear solvers. 782 783 If the user did not write their equations in implicit form, this 784 function recasts them in implicit form. 785 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; 794 795 PetscFunctionBegin; 796 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 797 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 798 PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4); 799 PetscValidHeaderSpecific(Y, VEC_CLASSID, 5); 800 801 PetscCall(TSGetDM(ts, &dm)); 802 PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx)); 803 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 804 805 PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()"); 806 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; 817 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 } 830 831 /* 832 TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call `TSComputeRHSJacobian()` on it. 833 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()`. 836 837 */ 838 static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B) 839 { 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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"); 844 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 } 855 856 /*@ 857 TSComputeIJacobian - Evaluates the Jacobian of the DAE 858 859 Collective 860 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 868 869 Output Parameters: 870 + A - Jacobian matrix 871 - B - matrix from which the preconditioner is constructed; often the same as `A` 872 873 Level: developer 874 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. 882 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; 891 892 PetscFunctionBegin; 893 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 894 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 895 PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4); 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 6); 897 PetscValidHeaderSpecific(B, MAT_CLASSID, 7); 898 899 PetscCall(TSGetDM(ts, &dm)); 900 PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx)); 901 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL)); 902 903 PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()"); 904 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; 940 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; 947 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; 957 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 } 995 996 /*@C 997 TSSetRHSFunction - Sets the routine for evaluating the function, 998 where U_t = G(t,u). 999 1000 Logically Collective 1001 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`) 1007 1008 Level: beginner 1009 1010 Note: 1011 You must call this function or `TSSetIFunction()` to define your ODE. You cannot use this function when solving a DAE. 1012 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; 1020 1021 PetscFunctionBegin; 1022 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1023 if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1024 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 } 1036 1037 /*@C 1038 TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE 1039 1040 Logically Collective 1041 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`) 1047 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()` 1051 1052 Level: intermediate 1053 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. 1058 1059 For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history. 1060 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; 1066 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1069 PetscCall(TSGetDM(ts, &dm)); 1070 PetscCall(DMTSSetSolutionFunction(dm, f, ctx)); 1071 PetscFunctionReturn(PETSC_SUCCESS); 1072 } 1073 1074 /*@C 1075 TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE 1076 1077 Logically Collective 1078 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`) 1084 1085 Level: intermediate 1086 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. 1091 1092 This replaces the ODE F(u,u_t,t) = 0 the `TS` is solving with F(u,u_t,t) - func(t) = 0 1093 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. 1096 1097 For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history. 1098 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; 1105 1106 PetscFunctionBegin; 1107 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1108 PetscCall(TSGetDM(ts, &dm)); 1109 PetscCall(DMTSSetForcingFunction(dm, func, ctx)); 1110 PetscFunctionReturn(PETSC_SUCCESS); 1111 } 1112 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. 1116 1117 Logically Collective 1118 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`) 1125 1126 Level: beginner 1127 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 1130 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. 1133 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; 1142 1143 PetscFunctionBegin; 1144 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1145 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1146 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 1147 if (Amat) PetscCheckSameComm(ts, 1, Amat, 2); 1148 if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3); 1149 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 } 1167 1168 /*@C 1169 TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved. 1170 1171 Logically Collective 1172 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`) 1178 1179 Level: beginner 1180 1181 Note: 1182 The user MUST call either this routine or `TSSetRHSFunction()` to define the ODE. When solving DAEs you must use this function. 1183 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; 1192 1193 PetscFunctionBegin; 1194 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1195 if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1196 1197 PetscCall(TSGetDM(ts, &dm)); 1198 PetscCall(DMTSSetIFunction(dm, f, ctx)); 1199 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 } 1209 1210 /*@C 1211 TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it. 1212 1213 Not Collective 1214 1215 Input Parameter: 1216 . ts - the `TS` context 1217 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`) 1222 1223 Level: advanced 1224 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; 1231 1232 PetscFunctionBegin; 1233 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 1240 1241 /*@C 1242 TSGetRHSFunction - Returns the vector where the right-hand side is stored and the function/context to compute it. 1243 1244 Not Collective 1245 1246 Input Parameter: 1247 . ts - the `TS` context 1248 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`) 1253 1254 Level: advanced 1255 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; 1262 1263 PetscFunctionBegin; 1264 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 1271 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()`. 1275 1276 Logically Collective 1277 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`) 1284 1285 Level: beginner 1286 1287 Notes: 1288 The matrices `Amat` and `Pmat` are exactly the matrices that are used by `SNES` for the nonlinear solve. 1289 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. 1292 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 1299 1300 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1301 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. 1304 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. 1307 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; 1315 1316 PetscFunctionBegin; 1317 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1318 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1319 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 1320 if (Amat) PetscCheckSameComm(ts, 1, Amat, 2); 1321 if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3); 1322 1323 PetscCall(TSGetDM(ts, &dm)); 1324 PetscCall(DMTSSetIJacobian(dm, f, ctx)); 1325 1326 PetscCall(TSGetSNES(ts, &snes)); 1327 PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts)); 1328 PetscFunctionReturn(PETSC_SUCCESS); 1329 } 1330 1331 /*@ 1332 TSRHSJacobianSetReuse - restore the RHS Jacobian before calling the user-provided `TSRHSJacobianFn` function again 1333 1334 Logically Collective 1335 1336 Input Parameters: 1337 + ts - `TS` context obtained from `TSCreate()` 1338 - reuse - `PETSC_TRUE` if the RHS Jacobian 1339 1340 Level: intermediate 1341 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`. 1347 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 } 1356 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. 1359 1360 Logically Collective 1361 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`) 1367 1368 Level: beginner 1369 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; 1376 1377 PetscFunctionBegin; 1378 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1379 if (F) PetscValidHeaderSpecific(F, VEC_CLASSID, 2); 1380 PetscCall(TSSetIFunction(ts, F, NULL, NULL)); 1381 PetscCall(TSGetDM(ts, &dm)); 1382 PetscCall(DMTSSetI2Function(dm, fun, ctx)); 1383 PetscFunctionReturn(PETSC_SUCCESS); 1384 } 1385 1386 /*@C 1387 TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it. 1388 1389 Not Collective 1390 1391 Input Parameter: 1392 . ts - the `TS` context 1393 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`) 1398 1399 Level: advanced 1400 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; 1407 1408 PetscFunctionBegin; 1409 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 1416 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()`. 1420 1421 Logically Collective 1422 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`) 1429 1430 Level: beginner 1431 1432 Notes: 1433 The matrices `J` and `P` are exactly the matrices that are used by `SNES` for the nonlinear solve. 1434 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. 1439 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; 1445 1446 PetscFunctionBegin; 1447 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1448 if (J) PetscValidHeaderSpecific(J, MAT_CLASSID, 2); 1449 if (P) PetscValidHeaderSpecific(P, MAT_CLASSID, 3); 1450 PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL)); 1451 PetscCall(TSGetDM(ts, &dm)); 1452 PetscCall(DMTSSetI2Jacobian(dm, jac, ctx)); 1453 PetscFunctionReturn(PETSC_SUCCESS); 1454 } 1455 1456 /*@C 1457 TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep. 1458 1459 Not Collective, but parallel objects are returned if `TS` is parallel 1460 1461 Input Parameter: 1462 . ts - The `TS` context obtained from `TSCreate()` 1463 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 1469 1470 Level: advanced 1471 1472 Note: 1473 You can pass in `NULL` for any return argument you do not need. 1474 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; 1481 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 } 1490 1491 /*@ 1492 TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0 1493 1494 Collective 1495 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) 1502 1503 Output Parameter: 1504 . F - the residual vector 1505 1506 Level: developer 1507 1508 Note: 1509 Most users should not need to explicitly call this routine, as it 1510 is used internally within the nonlinear solvers. 1511 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; 1520 1521 PetscFunctionBegin; 1522 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1523 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1524 PetscValidHeaderSpecific(V, VEC_CLASSID, 4); 1525 PetscValidHeaderSpecific(A, VEC_CLASSID, 5); 1526 PetscValidHeaderSpecific(F, VEC_CLASSID, 6); 1527 1528 PetscCall(TSGetDM(ts, &dm)); 1529 PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx)); 1530 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 1531 1532 if (!I2Function) { 1533 PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE)); 1534 PetscFunctionReturn(PETSC_SUCCESS); 1535 } 1536 1537 PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, V, F)); 1538 1539 PetscCallBack("TS callback implicit function", I2Function(ts, t, U, V, A, F, ctx)); 1540 1541 if (rhsfunction) { 1542 Vec Frhs; 1543 1544 PetscCall(DMGetGlobalVector(dm, &Frhs)); 1545 PetscCall(TSComputeRHSFunction(ts, t, U, Frhs)); 1546 PetscCall(VecAXPY(F, -1, Frhs)); 1547 PetscCall(DMRestoreGlobalVector(dm, &Frhs)); 1548 } 1549 1550 PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F)); 1551 PetscFunctionReturn(PETSC_SUCCESS); 1552 } 1553 1554 /*@ 1555 TSComputeI2Jacobian - Evaluates the Jacobian of the DAE 1556 1557 Collective 1558 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 1567 1568 Output Parameters: 1569 + J - Jacobian matrix 1570 - P - optional preconditioning matrix 1571 1572 Level: developer 1573 1574 Notes: 1575 If F(t,U,V,A)=0 is the DAE, the required Jacobian is 1576 1577 dF/dU + shiftV*dF/dV + shiftA*dF/dA 1578 1579 Most users should not need to explicitly call this routine, as it 1580 is used internally within the nonlinear solvers. 1581 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; 1590 1591 PetscFunctionBegin; 1592 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1593 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1594 PetscValidHeaderSpecific(V, VEC_CLASSID, 4); 1595 PetscValidHeaderSpecific(A, VEC_CLASSID, 5); 1596 PetscValidHeaderSpecific(J, MAT_CLASSID, 8); 1597 PetscValidHeaderSpecific(P, MAT_CLASSID, 9); 1598 1599 PetscCall(TSGetDM(ts, &dm)); 1600 PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx)); 1601 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL)); 1602 1603 if (!I2Jacobian) { 1604 PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE)); 1605 PetscFunctionReturn(PETSC_SUCCESS); 1606 } 1607 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 } 1617 1618 PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P)); 1619 PetscFunctionReturn(PETSC_SUCCESS); 1620 } 1621 1622 /*@C 1623 TSSetTransientVariable - sets function to transform from state to transient variables 1624 1625 Logically Collective 1626 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 1631 1632 Level: advanced 1633 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 1643 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; 1649 1650 PetscFunctionBegin; 1651 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1652 PetscCall(TSGetDM(ts, &dm)); 1653 PetscCall(DMTSSetTransientVariable(dm, tvar, ctx)); 1654 PetscFunctionReturn(PETSC_SUCCESS); 1655 } 1656 1657 /*@ 1658 TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables 1659 1660 Logically Collective 1661 1662 Input Parameters: 1663 + ts - TS on which to compute 1664 - U - state vector to be transformed to transient variables 1665 1666 Output Parameter: 1667 . C - transient (conservative) variable 1668 1669 Level: developer 1670 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. 1675 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; 1682 1683 PetscFunctionBegin; 1684 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1685 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 1686 PetscCall(TSGetDM(ts, &dm)); 1687 PetscCall(DMGetDMTS(dm, &dmts)); 1688 if (dmts->ops->transientvar) { 1689 PetscValidHeaderSpecific(C, VEC_CLASSID, 3); 1690 PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx)); 1691 } 1692 PetscFunctionReturn(PETSC_SUCCESS); 1693 } 1694 1695 /*@ 1696 TSHasTransientVariable - determine whether transient variables have been set 1697 1698 Logically Collective 1699 1700 Input Parameter: 1701 . ts - `TS` on which to compute 1702 1703 Output Parameter: 1704 . has - `PETSC_TRUE` if transient variables have been set 1705 1706 Level: developer 1707 1708 .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()` 1709 @*/ 1710 PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has) 1711 { 1712 DM dm; 1713 DMTS dmts; 1714 1715 PetscFunctionBegin; 1716 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1717 PetscCall(TSGetDM(ts, &dm)); 1718 PetscCall(DMGetDMTS(dm, &dmts)); 1719 *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE; 1720 PetscFunctionReturn(PETSC_SUCCESS); 1721 } 1722 1723 /*@ 1724 TS2SetSolution - Sets the initial solution and time derivative vectors 1725 for use by the `TS` routines handling second order equations. 1726 1727 Logically Collective 1728 1729 Input Parameters: 1730 + ts - the `TS` context obtained from `TSCreate()` 1731 . u - the solution vector 1732 - v - the time derivative vector 1733 1734 Level: beginner 1735 1736 .seealso: [](ch_ts), `TS` 1737 @*/ 1738 PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v) 1739 { 1740 PetscFunctionBegin; 1741 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1742 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 1743 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 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 } 1750 1751 /*@ 1752 TS2GetSolution - Returns the solution and time derivative at the present timestep 1753 for second order equations. 1754 1755 Not Collective 1756 1757 Input Parameter: 1758 . ts - the `TS` context obtained from `TSCreate()` 1759 1760 Output Parameters: 1761 + u - the vector containing the solution 1762 - v - the vector containing the time derivative 1763 1764 Level: intermediate 1765 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. 1770 1771 .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()` 1772 @*/ 1773 PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v) 1774 { 1775 PetscFunctionBegin; 1776 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 1783 1784 /*@ 1785 TSLoad - Loads a `TS` that has been stored in binary with `TSView()`. 1786 1787 Collective 1788 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()` 1793 1794 Level: intermediate 1795 1796 Note: 1797 The type is determined by the data in the file, any type set into the `TS` before this call is ignored. 1798 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; 1808 1809 PetscFunctionBegin; 1810 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1811 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1812 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1813 PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1814 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 } 1829 1830 #include <petscdraw.h> 1831 #if defined(PETSC_HAVE_SAWS) 1832 #include <petscviewersaws.h> 1833 #endif 1834 1835 /*@ 1836 TSViewFromOptions - View a `TS` based on values in the options database 1837 1838 Collective 1839 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 1844 1845 Level: intermediate 1846 1847 .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()` 1848 @*/ 1849 PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[]) 1850 { 1851 PetscFunctionBegin; 1852 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1853 PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name)); 1854 PetscFunctionReturn(PETSC_SUCCESS); 1855 } 1856 1857 /*@ 1858 TSView - Prints the `TS` data structure. 1859 1860 Collective 1861 1862 Input Parameters: 1863 + ts - the `TS` context obtained from `TSCreate()` 1864 - viewer - visualization context 1865 1866 Options Database Key: 1867 . -ts_view - calls `TSView()` at end of `TSStep()` 1868 1869 Level: beginner 1870 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. 1878 1879 The user can open an alternative visualization context with 1880 `PetscViewerASCIIOpen()` - output to a specified file. 1881 1882 In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer). 1883 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 1894 1895 PetscFunctionBegin; 1896 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1897 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer)); 1898 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1899 PetscCheckSameComm(ts, 1, viewer, 2); 1900 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]; 1945 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; 1963 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; 1979 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]; 1984 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)); 2001 2002 PetscCall(PetscViewerASCIIPushTab(viewer)); 2003 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &isundials)); 2004 PetscCall(PetscViewerASCIIPopTab(viewer)); 2005 PetscFunctionReturn(PETSC_SUCCESS); 2006 } 2007 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()` 2011 2012 Logically Collective 2013 2014 Input Parameters: 2015 + ts - the `TS` context obtained from `TSCreate()` 2016 - ctx - user context 2017 2018 Level: intermediate 2019 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. 2024 2025 .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()` 2026 @*/ 2027 PetscErrorCode TSSetApplicationContext(TS ts, PeCtx ctx) 2028 { 2029 PetscFunctionBegin; 2030 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2031 ts->ctx = ctx; 2032 PetscFunctionReturn(PETSC_SUCCESS); 2033 } 2034 2035 /*@ 2036 TSGetApplicationContext - Gets the user-defined context for the 2037 timestepper that was set with `TSSetApplicationContext()` 2038 2039 Not Collective 2040 2041 Input Parameter: 2042 . ts - the `TS` context obtained from `TSCreate()` 2043 2044 Output Parameter: 2045 . ctx - a pointer to the user context 2046 2047 Level: intermediate 2048 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 2063 2064 The prototype for `ctx` must be 2065 .vb 2066 type(tUsertype), pointer :: ctx 2067 .ve 2068 2069 .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()` 2070 @*/ 2071 PetscErrorCode TSGetApplicationContext(TS ts, void *ctx) 2072 { 2073 PetscFunctionBegin; 2074 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2075 *(void **)ctx = ts->ctx; 2076 PetscFunctionReturn(PETSC_SUCCESS); 2077 } 2078 2079 /*@ 2080 TSGetStepNumber - Gets the number of time steps completed. 2081 2082 Not Collective 2083 2084 Input Parameter: 2085 . ts - the `TS` context obtained from `TSCreate()` 2086 2087 Output Parameter: 2088 . steps - number of steps completed so far 2089 2090 Level: intermediate 2091 2092 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()` 2093 @*/ 2094 PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps) 2095 { 2096 PetscFunctionBegin; 2097 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2098 PetscAssertPointer(steps, 2); 2099 *steps = ts->steps; 2100 PetscFunctionReturn(PETSC_SUCCESS); 2101 } 2102 2103 /*@ 2104 TSSetStepNumber - Sets the number of steps completed. 2105 2106 Logically Collective 2107 2108 Input Parameters: 2109 + ts - the `TS` context 2110 - steps - number of steps completed so far 2111 2112 Level: developer 2113 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. 2123 2124 .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()` 2125 @*/ 2126 PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps) 2127 { 2128 PetscFunctionBegin; 2129 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2130 PetscValidLogicalCollectiveInt(ts, steps, 2); 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 } 2135 2136 /*@ 2137 TSSetTimeStep - Allows one to reset the timestep at any time, 2138 useful for simple pseudo-timestepping codes. 2139 2140 Logically Collective 2141 2142 Input Parameters: 2143 + ts - the `TS` context obtained from `TSCreate()` 2144 - time_step - the size of the timestep 2145 2146 Level: intermediate 2147 2148 .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()` 2149 @*/ 2150 PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step) 2151 { 2152 PetscFunctionBegin; 2153 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2154 PetscValidLogicalCollectiveReal(ts, time_step, 2); 2155 ts->time_step = time_step; 2156 PetscFunctionReturn(PETSC_SUCCESS); 2157 } 2158 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). 2164 2165 Logically Collective 2166 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 2175 2176 Options Database Key: 2177 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime 2178 2179 Level: beginner 2180 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. 2184 2185 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()` 2186 @*/ 2187 PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt) 2188 { 2189 PetscFunctionBegin; 2190 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2191 PetscValidLogicalCollectiveEnum(ts, eftopt, 2); 2192 ts->exact_final_time = eftopt; 2193 PetscFunctionReturn(PETSC_SUCCESS); 2194 } 2195 2196 /*@ 2197 TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()` 2198 2199 Not Collective 2200 2201 Input Parameter: 2202 . ts - the `TS` context 2203 2204 Output Parameter: 2205 . eftopt - exact final time option 2206 2207 Level: beginner 2208 2209 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()` 2210 @*/ 2211 PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt) 2212 { 2213 PetscFunctionBegin; 2214 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2215 PetscAssertPointer(eftopt, 2); 2216 *eftopt = ts->exact_final_time; 2217 PetscFunctionReturn(PETSC_SUCCESS); 2218 } 2219 2220 /*@ 2221 TSGetTimeStep - Gets the current timestep size. 2222 2223 Not Collective 2224 2225 Input Parameter: 2226 . ts - the `TS` context obtained from `TSCreate()` 2227 2228 Output Parameter: 2229 . dt - the current timestep size 2230 2231 Level: intermediate 2232 2233 .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()` 2234 @*/ 2235 PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt) 2236 { 2237 PetscFunctionBegin; 2238 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2239 PetscAssertPointer(dt, 2); 2240 *dt = ts->time_step; 2241 PetscFunctionReturn(PETSC_SUCCESS); 2242 } 2243 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. 2249 2250 Not Collective, but v returned is parallel if ts is parallel 2251 2252 Input Parameter: 2253 . ts - the `TS` context obtained from `TSCreate()` 2254 2255 Output Parameter: 2256 . v - the vector containing the solution 2257 2258 Level: intermediate 2259 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. 2263 2264 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()` 2265 @*/ 2266 PetscErrorCode TSGetSolution(TS ts, Vec *v) 2267 { 2268 PetscFunctionBegin; 2269 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2270 PetscAssertPointer(v, 2); 2271 *v = ts->vec_sol; 2272 PetscFunctionReturn(PETSC_SUCCESS); 2273 } 2274 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. 2280 2281 Not Collective, but v returned is parallel if ts is parallel 2282 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). 2291 2292 Level: advanced 2293 2294 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2295 @*/ 2296 PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v) 2297 { 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2300 if (!ts->ops->getsolutioncomponents) *n = 0; 2301 else PetscUseTypeMethod(ts, getsolutioncomponents, n, v); 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@ 2306 TSGetAuxSolution - Returns an auxiliary solution at the present 2307 timestep, if available for the time integration method being used. 2308 2309 Not Collective, but v returned is parallel if ts is parallel 2310 2311 Input Parameters: 2312 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2313 - v - the vector containing the auxiliary solution 2314 2315 Level: intermediate 2316 2317 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2318 @*/ 2319 PetscErrorCode TSGetAuxSolution(TS ts, Vec *v) 2320 { 2321 PetscFunctionBegin; 2322 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2323 if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v); 2324 else PetscCall(VecZeroEntries(*v)); 2325 PetscFunctionReturn(PETSC_SUCCESS); 2326 } 2327 2328 /*@ 2329 TSGetTimeError - Returns the estimated error vector, if the chosen 2330 `TSType` has an error estimation functionality and `TSSetTimeError()` was called 2331 2332 Not Collective, but v returned is parallel if ts is parallel 2333 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). 2338 2339 Level: intermediate 2340 2341 Note: 2342 MUST call after `TSSetUp()` 2343 2344 .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()` 2345 @*/ 2346 PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v) 2347 { 2348 PetscFunctionBegin; 2349 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2350 if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v); 2351 else PetscCall(VecZeroEntries(*v)); 2352 PetscFunctionReturn(PETSC_SUCCESS); 2353 } 2354 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. 2359 2360 Not Collective, but v returned is parallel if ts is parallel 2361 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). 2365 2366 Level: intermediate 2367 2368 .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()` 2369 @*/ 2370 PetscErrorCode TSSetTimeError(TS ts, Vec v) 2371 { 2372 PetscFunctionBegin; 2373 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 2378 2379 /* ----- Routines to initialize and destroy a timestepper ---- */ 2380 /*@ 2381 TSSetProblemType - Sets the type of problem to be solved. 2382 2383 Not collective 2384 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 2393 2394 Level: beginner 2395 2396 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2397 @*/ 2398 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2399 { 2400 PetscFunctionBegin; 2401 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 2410 2411 /*@ 2412 TSGetProblemType - Gets the type of problem to be solved. 2413 2414 Not collective 2415 2416 Input Parameter: 2417 . ts - The `TS` 2418 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 2426 2427 Level: beginner 2428 2429 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2430 @*/ 2431 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2432 { 2433 PetscFunctionBegin; 2434 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2435 PetscAssertPointer(type, 2); 2436 *type = ts->problem_type; 2437 PetscFunctionReturn(PETSC_SUCCESS); 2438 } 2439 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; 2446 2447 PetscFunctionBegin; 2448 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2449 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2450 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 } 2456 2457 /*@ 2458 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2459 2460 Collective 2461 2462 Input Parameter: 2463 . ts - the `TS` context obtained from `TSCreate()` 2464 2465 Level: advanced 2466 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()`. 2473 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; 2485 2486 PetscFunctionBegin; 2487 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2488 if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 2489 2490 if (!((PetscObject)ts)->type_name) { 2491 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 2492 PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER)); 2493 } 2494 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 } 2499 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 } 2508 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 } 2514 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 } 2535 2536 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2537 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2538 2539 PetscTryTypeMethod(ts, setup); 2540 2541 PetscCall(TSSetExactFinalTimeDefault(ts)); 2542 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)); 2549 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)); 2558 2559 /* if time integration scheme has a starting method, call it */ 2560 PetscTryTypeMethod(ts, startingmethod); 2561 2562 ts->setupcalled = PETSC_TRUE; 2563 PetscFunctionReturn(PETSC_SUCCESS); 2564 } 2565 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 2568 2569 Collective 2570 2571 Input Parameter: 2572 . ts - the `TS` context obtained from `TSCreate()` 2573 2574 Level: developer 2575 2576 Notes: 2577 Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain. 2578 2579 See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration. 2580 2581 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSetResize()` 2582 @*/ 2583 PetscErrorCode TSReset(TS ts) 2584 { 2585 TS_RHSSplitLink ilink = ts->tsrhssplit, next; 2586 2587 PetscFunctionBegin; 2588 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2589 2590 PetscTryTypeMethod(ts, reset); 2591 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2592 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2593 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)); 2603 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 } 2633 2634 static PetscErrorCode TSResizeReset(TS); 2635 2636 /*@ 2637 TSDestroy - Destroys the timestepper context that was created 2638 with `TSCreate()`. 2639 2640 Collective 2641 2642 Input Parameter: 2643 . ts - the `TS` context obtained from `TSCreate()` 2644 2645 Level: beginner 2646 2647 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2648 @*/ 2649 PetscErrorCode TSDestroy(TS *ts) 2650 { 2651 PetscFunctionBegin; 2652 if (!*ts) PetscFunctionReturn(PETSC_SUCCESS); 2653 PetscValidHeaderSpecific(*ts, TS_CLASSID, 1); 2654 if (--((PetscObject)*ts)->refct > 0) { 2655 *ts = NULL; 2656 PetscFunctionReturn(PETSC_SUCCESS); 2657 } 2658 2659 PetscCall(TSReset(*ts)); 2660 PetscCall(TSAdjointReset(*ts)); 2661 if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts)); 2662 PetscCall(TSResizeReset(*ts)); 2663 2664 /* if memory was published with SAWs then destroy it */ 2665 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2666 PetscTryTypeMethod(*ts, destroy); 2667 2668 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2669 2670 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2671 PetscCall(TSEventDestroy(&(*ts)->event)); 2672 2673 PetscCall(SNESDestroy(&(*ts)->snes)); 2674 PetscCall(SNESDestroy(&(*ts)->snesrhssplit)); 2675 PetscCall(DMDestroy(&(*ts)->dm)); 2676 PetscCall(TSMonitorCancel(*ts)); 2677 PetscCall(TSAdjointMonitorCancel(*ts)); 2678 2679 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2680 PetscCall(PetscHeaderDestroy(ts)); 2681 PetscFunctionReturn(PETSC_SUCCESS); 2682 } 2683 2684 /*@ 2685 TSGetSNES - Returns the `SNES` (nonlinear solver) associated with 2686 a `TS` (timestepper) context. Valid only for nonlinear problems. 2687 2688 Not Collective, but snes is parallel if ts is parallel 2689 2690 Input Parameter: 2691 . ts - the `TS` context obtained from `TSCreate()` 2692 2693 Output Parameter: 2694 . snes - the nonlinear solver context 2695 2696 Level: beginner 2697 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. 2702 2703 `TSGetSNES()` does not work for integrators that do not use `SNES`; in 2704 this case `TSGetSNES()` returns `NULL` in `snes`. 2705 2706 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2707 @*/ 2708 PetscErrorCode TSGetSNES(TS ts, SNES *snes) 2709 { 2710 PetscFunctionBegin; 2711 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 2724 2725 /*@ 2726 TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context 2727 2728 Collective 2729 2730 Input Parameters: 2731 + ts - the `TS` context obtained from `TSCreate()` 2732 - snes - the nonlinear solver context 2733 2734 Level: developer 2735 2736 Note: 2737 Most users should have the `TS` created by calling `TSGetSNES()` 2738 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 *); 2744 2745 PetscFunctionBegin; 2746 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2747 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2748 PetscCall(PetscObjectReference((PetscObject)snes)); 2749 PetscCall(SNESDestroy(&ts->snes)); 2750 2751 ts->snes = snes; 2752 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 } 2758 2759 /*@ 2760 TSGetKSP - Returns the `KSP` (linear solver) associated with 2761 a `TS` (timestepper) context. 2762 2763 Not Collective, but `ksp` is parallel if `ts` is parallel 2764 2765 Input Parameter: 2766 . ts - the `TS` context obtained from `TSCreate()` 2767 2768 Output Parameter: 2769 . ksp - the nonlinear solver context 2770 2771 Level: beginner 2772 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. 2777 2778 `TSGetKSP()` does not work for integrators that do not use `KSP`; 2779 in this case `TSGetKSP()` returns `NULL` in `ksp`. 2780 2781 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2782 @*/ 2783 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) 2784 { 2785 SNES snes; 2786 2787 PetscFunctionBegin; 2788 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 2796 2797 /* ----------- Routines to set solver parameters ---------- */ 2798 2799 /*@ 2800 TSSetMaxSteps - Sets the maximum number of steps to use. 2801 2802 Logically Collective 2803 2804 Input Parameters: 2805 + ts - the `TS` context obtained from `TSCreate()` 2806 - maxsteps - maximum number of steps to use 2807 2808 Options Database Key: 2809 . -ts_max_steps <maxsteps> - Sets maxsteps 2810 2811 Level: intermediate 2812 2813 Note: 2814 Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set 2815 2816 The default maximum number of steps is 5,000 2817 2818 Fortran Note: 2819 Use `PETSC_DETERMINE_INTEGER` 2820 2821 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2822 @*/ 2823 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) 2824 { 2825 PetscFunctionBegin; 2826 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2827 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 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 } 2836 2837 /*@ 2838 TSGetMaxSteps - Gets the maximum number of steps to use. 2839 2840 Not Collective 2841 2842 Input Parameter: 2843 . ts - the `TS` context obtained from `TSCreate()` 2844 2845 Output Parameter: 2846 . maxsteps - maximum number of steps to use 2847 2848 Level: advanced 2849 2850 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2851 @*/ 2852 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) 2853 { 2854 PetscFunctionBegin; 2855 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2856 PetscAssertPointer(maxsteps, 2); 2857 *maxsteps = ts->max_steps; 2858 PetscFunctionReturn(PETSC_SUCCESS); 2859 } 2860 2861 /*@ 2862 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2863 2864 Logically Collective 2865 2866 Input Parameters: 2867 + ts - the `TS` context obtained from `TSCreate()` 2868 - maxtime - final time to step to 2869 2870 Options Database Key: 2871 . -ts_max_time <maxtime> - Sets maxtime 2872 2873 Level: intermediate 2874 2875 Notes: 2876 Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set 2877 2878 The default maximum time is 5.0 2879 2880 Fortran Note: 2881 Use `PETSC_DETERMINE_REAL` 2882 2883 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2884 @*/ 2885 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) 2886 { 2887 PetscFunctionBegin; 2888 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2889 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 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 } 2897 2898 /*@ 2899 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2900 2901 Not Collective 2902 2903 Input Parameter: 2904 . ts - the `TS` context obtained from `TSCreate()` 2905 2906 Output Parameter: 2907 . maxtime - final time to step to 2908 2909 Level: advanced 2910 2911 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2912 @*/ 2913 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) 2914 { 2915 PetscFunctionBegin; 2916 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2917 PetscAssertPointer(maxtime, 2); 2918 *maxtime = ts->max_time; 2919 PetscFunctionReturn(PETSC_SUCCESS); 2920 } 2921 2922 // PetscClangLinter pragma disable: -fdoc-* 2923 /*@ 2924 TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`. 2925 2926 Level: deprecated 2927 2928 @*/ 2929 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) 2930 { 2931 PetscFunctionBegin; 2932 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2933 PetscCall(TSSetTime(ts, initial_time)); 2934 PetscCall(TSSetTimeStep(ts, time_step)); 2935 PetscFunctionReturn(PETSC_SUCCESS); 2936 } 2937 2938 // PetscClangLinter pragma disable: -fdoc-* 2939 /*@ 2940 TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`. 2941 2942 Level: deprecated 2943 2944 @*/ 2945 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 2946 { 2947 PetscFunctionBegin; 2948 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 2959 2960 // PetscClangLinter pragma disable: -fdoc-* 2961 /*@ 2962 TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`. 2963 2964 Level: deprecated 2965 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 } 2974 2975 // PetscClangLinter pragma disable: -fdoc-* 2976 /*@ 2977 TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`. 2978 2979 Level: deprecated 2980 2981 @*/ 2982 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) 2983 { 2984 return TSGetStepNumber(ts, steps); 2985 } 2986 2987 // PetscClangLinter pragma disable: -fdoc-* 2988 /*@ 2989 TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`. 2990 2991 Level: deprecated 2992 2993 @*/ 2994 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) 2995 { 2996 return TSGetStepNumber(ts, steps); 2997 } 2998 2999 /*@ 3000 TSSetSolution - Sets the initial solution vector 3001 for use by the `TS` routines. 3002 3003 Logically Collective 3004 3005 Input Parameters: 3006 + ts - the `TS` context obtained from `TSCreate()` 3007 - u - the solution vector 3008 3009 Level: beginner 3010 3011 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 3012 @*/ 3013 PetscErrorCode TSSetSolution(TS ts, Vec u) 3014 { 3015 DM dm; 3016 3017 PetscFunctionBegin; 3018 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3019 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3020 PetscCall(PetscObjectReference((PetscObject)u)); 3021 PetscCall(VecDestroy(&ts->vec_sol)); 3022 ts->vec_sol = u; 3023 3024 PetscCall(TSGetDM(ts, &dm)); 3025 PetscCall(DMShellSetGlobalVector(dm, u)); 3026 PetscFunctionReturn(PETSC_SUCCESS); 3027 } 3028 3029 /*@C 3030 TSSetPreStep - Sets the general-purpose function 3031 called once at the beginning of each time step. 3032 3033 Logically Collective 3034 3035 Input Parameters: 3036 + ts - The `TS` context obtained from `TSCreate()` 3037 - func - The function 3038 3039 Calling sequence of `func`: 3040 . ts - the `TS` context 3041 3042 Level: intermediate 3043 3044 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3045 @*/ 3046 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts)) 3047 { 3048 PetscFunctionBegin; 3049 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3050 ts->prestep = func; 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@ 3055 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3056 3057 Collective 3058 3059 Input Parameter: 3060 . ts - The `TS` context obtained from `TSCreate()` 3061 3062 Level: developer 3063 3064 Note: 3065 `TSPreStep()` is typically used within time stepping implementations, 3066 so most users would not generally call this routine themselves. 3067 3068 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3069 @*/ 3070 PetscErrorCode TSPreStep(TS ts) 3071 { 3072 PetscFunctionBegin; 3073 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3074 if (ts->prestep) { 3075 Vec U; 3076 PetscObjectId idprev; 3077 PetscBool sameObject; 3078 PetscObjectState sprev, spost; 3079 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 } 3091 3092 /*@C 3093 TSSetPreStage - Sets the general-purpose function 3094 called once at the beginning of each stage. 3095 3096 Logically Collective 3097 3098 Input Parameters: 3099 + ts - The `TS` context obtained from `TSCreate()` 3100 - func - The function 3101 3102 Calling sequence of `func`: 3103 + ts - the `TS` context 3104 - stagetime - the stage time 3105 3106 Level: intermediate 3107 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()`. 3112 3113 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3114 @*/ 3115 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime)) 3116 { 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3119 ts->prestage = func; 3120 PetscFunctionReturn(PETSC_SUCCESS); 3121 } 3122 3123 /*@C 3124 TSSetPostStage - Sets the general-purpose function 3125 called once at the end of each stage. 3126 3127 Logically Collective 3128 3129 Input Parameters: 3130 + ts - The `TS` context obtained from `TSCreate()` 3131 - func - The function 3132 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 3138 3139 Level: intermediate 3140 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()`. 3145 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; 3151 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3152 ts->poststage = func; 3153 PetscFunctionReturn(PETSC_SUCCESS); 3154 } 3155 3156 /*@C 3157 TSSetPostEvaluate - Sets the general-purpose function 3158 called at the end of each step evaluation. 3159 3160 Logically Collective 3161 3162 Input Parameters: 3163 + ts - The `TS` context obtained from `TSCreate()` 3164 - func - The function 3165 3166 Calling sequence of `func`: 3167 . ts - the `TS` context 3168 3169 Level: intermediate 3170 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 3191 3192 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3193 @*/ 3194 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts)) 3195 { 3196 PetscFunctionBegin; 3197 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3198 ts->postevaluate = func; 3199 PetscFunctionReturn(PETSC_SUCCESS); 3200 } 3201 3202 /*@ 3203 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3204 3205 Collective 3206 3207 Input Parameters: 3208 + ts - The `TS` context obtained from `TSCreate()` 3209 - stagetime - The absolute time of the current stage 3210 3211 Level: developer 3212 3213 Note: 3214 `TSPreStage()` is typically used within time stepping implementations, 3215 most users would not generally call this routine themselves. 3216 3217 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3218 @*/ 3219 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3220 { 3221 PetscFunctionBegin; 3222 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3223 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3224 PetscFunctionReturn(PETSC_SUCCESS); 3225 } 3226 3227 /*@ 3228 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3229 3230 Collective 3231 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 3237 3238 Level: developer 3239 3240 Note: 3241 `TSPostStage()` is typically used within time stepping implementations, 3242 most users would not generally call this routine themselves. 3243 3244 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3245 @*/ 3246 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3247 { 3248 PetscFunctionBegin; 3249 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3250 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3251 PetscFunctionReturn(PETSC_SUCCESS); 3252 } 3253 3254 /*@ 3255 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3256 3257 Collective 3258 3259 Input Parameter: 3260 . ts - The `TS` context obtained from `TSCreate()` 3261 3262 Level: developer 3263 3264 Note: 3265 `TSPostEvaluate()` is typically used within time stepping implementations, 3266 most users would not generally call this routine themselves. 3267 3268 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3269 @*/ 3270 PetscErrorCode TSPostEvaluate(TS ts) 3271 { 3272 PetscFunctionBegin; 3273 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3274 if (ts->postevaluate) { 3275 Vec U; 3276 PetscObjectState sprev, spost; 3277 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 } 3286 3287 /*@C 3288 TSSetPostStep - Sets the general-purpose function 3289 called once at the end of each successful time step. 3290 3291 Logically Collective 3292 3293 Input Parameters: 3294 + ts - The `TS` context obtained from `TSCreate()` 3295 - func - The function 3296 3297 Calling sequence of `func`: 3298 . ts - the `TS` context 3299 3300 Level: intermediate 3301 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 3321 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; 3327 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3328 ts->poststep = func; 3329 PetscFunctionReturn(PETSC_SUCCESS); 3330 } 3331 3332 /*@ 3333 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()` 3334 3335 Collective 3336 3337 Input Parameter: 3338 . ts - The `TS` context obtained from `TSCreate()` 3339 3340 Note: 3341 `TSPostStep()` is typically used within time stepping implementations, 3342 so most users would not generally call this routine themselves. 3343 3344 Level: developer 3345 3346 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPostStep()` 3347 @*/ 3348 PetscErrorCode TSPostStep(TS ts) 3349 { 3350 PetscFunctionBegin; 3351 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3352 if (ts->poststep) { 3353 Vec U; 3354 PetscObjectId idprev; 3355 PetscBool sameObject; 3356 PetscObjectState sprev, spost; 3357 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 } 3369 3370 /*@ 3371 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3372 3373 Collective 3374 3375 Input Parameters: 3376 + ts - time stepping context 3377 - t - time to interpolate to 3378 3379 Output Parameter: 3380 . U - state at given time 3381 3382 Level: intermediate 3383 3384 Developer Notes: 3385 `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3386 3387 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()` 3388 @*/ 3389 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) 3390 { 3391 PetscFunctionBegin; 3392 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3393 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 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 } 3398 3399 /*@ 3400 TSStep - Steps one time step 3401 3402 Collective 3403 3404 Input Parameter: 3405 . ts - the `TS` context obtained from `TSCreate()` 3406 3407 Level: developer 3408 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. 3411 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. 3414 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. 3417 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; 3424 3425 PetscFunctionBegin; 3426 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 */ 3440 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"); 3444 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; 3448 3449 if (!ts->steps) ts->ptime_prev = ts->ptime; 3450 ptime = ts->ptime; 3451 3452 ts->ptime_prev_rollback = ts->ptime_prev; 3453 ts->reason = TS_CONVERGED_ITERATING; 3454 3455 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3456 PetscUseTypeMethod(ts, step); 3457 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3458 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 } 3466 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 } 3474 3475 /*@ 3476 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3477 at the end of a time step with a given order of accuracy. 3478 3479 Collective 3480 3481 Input Parameters: 3482 + ts - time stepping context 3483 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3484 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 3488 3489 Output Parameter: 3490 . wlte - the weighted local truncation error norm 3491 3492 Level: advanced 3493 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 . 3498 3499 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3500 @*/ 3501 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3502 { 3503 PetscFunctionBegin; 3504 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3505 PetscValidType(ts, 1); 3506 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3507 if (order) PetscAssertPointer(order, 3); 3508 if (order) PetscValidLogicalCollectiveInt(ts, *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 } 3514 3515 /*@ 3516 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3517 3518 Collective 3519 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) 3524 3525 Output Parameter: 3526 . U - state at the end of the current step 3527 3528 Level: advanced 3529 3530 Notes: 3531 This function cannot be called until all stages have been evaluated. 3532 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. 3534 3535 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt` 3536 @*/ 3537 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3538 { 3539 PetscFunctionBegin; 3540 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3541 PetscValidType(ts, 1); 3542 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3543 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3544 PetscFunctionReturn(PETSC_SUCCESS); 3545 } 3546 3547 /*@C 3548 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3549 3550 Not collective 3551 3552 Input Parameter: 3553 . ts - time stepping context 3554 3555 Output Parameter: 3556 . initCondition - The function which computes an initial condition 3557 3558 Calling sequence of `initCondition`: 3559 + ts - The timestepping context 3560 - u - The input vector in which the initial condition is stored 3561 3562 Level: advanced 3563 3564 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3565 @*/ 3566 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u)) 3567 { 3568 PetscFunctionBegin; 3569 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3570 PetscAssertPointer(initCondition, 2); 3571 *initCondition = ts->ops->initcondition; 3572 PetscFunctionReturn(PETSC_SUCCESS); 3573 } 3574 3575 /*@C 3576 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3577 3578 Logically collective 3579 3580 Input Parameters: 3581 + ts - time stepping context 3582 - initCondition - The function which computes an initial condition 3583 3584 Calling sequence of `initCondition`: 3585 + ts - The timestepping context 3586 - e - The input vector in which the initial condition is to be stored 3587 3588 Level: advanced 3589 3590 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3591 @*/ 3592 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e)) 3593 { 3594 PetscFunctionBegin; 3595 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3596 PetscValidFunction(initCondition, 2); 3597 ts->ops->initcondition = initCondition; 3598 PetscFunctionReturn(PETSC_SUCCESS); 3599 } 3600 3601 /*@ 3602 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3603 3604 Collective 3605 3606 Input Parameters: 3607 + ts - time stepping context 3608 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3609 3610 Level: advanced 3611 3612 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3613 @*/ 3614 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3615 { 3616 PetscFunctionBegin; 3617 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3618 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3619 PetscTryTypeMethod(ts, initcondition, u); 3620 PetscFunctionReturn(PETSC_SUCCESS); 3621 } 3622 3623 /*@C 3624 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3625 3626 Not collective 3627 3628 Input Parameter: 3629 . ts - time stepping context 3630 3631 Output Parameter: 3632 . exactError - The function which computes the solution error 3633 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 3638 3639 Level: advanced 3640 3641 .seealso: [](ch_ts), `TS`, `TSComputeExactError()` 3642 @*/ 3643 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e)) 3644 { 3645 PetscFunctionBegin; 3646 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3647 PetscAssertPointer(exactError, 2); 3648 *exactError = ts->ops->exacterror; 3649 PetscFunctionReturn(PETSC_SUCCESS); 3650 } 3651 3652 /*@C 3653 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3654 3655 Logically collective 3656 3657 Input Parameters: 3658 + ts - time stepping context 3659 - exactError - The function which computes the solution error 3660 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 3665 3666 Level: advanced 3667 3668 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3669 @*/ 3670 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e)) 3671 { 3672 PetscFunctionBegin; 3673 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3674 PetscValidFunction(exactError, 2); 3675 ts->ops->exacterror = exactError; 3676 PetscFunctionReturn(PETSC_SUCCESS); 3677 } 3678 3679 /*@ 3680 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3681 3682 Collective 3683 3684 Input Parameters: 3685 + ts - time stepping context 3686 . u - The approximate solution 3687 - e - The `Vec` used to store the error 3688 3689 Level: advanced 3690 3691 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3692 @*/ 3693 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3694 { 3695 PetscFunctionBegin; 3696 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3697 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3698 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3699 PetscTryTypeMethod(ts, exacterror, u, e); 3700 PetscFunctionReturn(PETSC_SUCCESS); 3701 } 3702 3703 /*@C 3704 TSSetResize - Sets the resize callbacks. 3705 3706 Logically Collective 3707 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 3714 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 3722 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 3729 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. 3745 3746 Level: advanced 3747 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; 3753 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3754 ts->resizerollback = rollback; 3755 ts->resizesetup = setup; 3756 ts->resizetransfer = transfer; 3757 ts->resizectx = ctx; 3758 PetscFunctionReturn(PETSC_SUCCESS); 3759 } 3760 3761 /* 3762 TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`. 3763 3764 Collective 3765 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. 3769 3770 Level: developer 3771 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. 3776 3777 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3778 @*/ 3779 static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg) 3780 { 3781 PetscFunctionBegin; 3782 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3783 PetscTryTypeMethod(ts, resizeregister, flg); 3784 /* PetscTryTypeMethod(adapt, resizeregister, flg); */ 3785 PetscFunctionReturn(PETSC_SUCCESS); 3786 } 3787 3788 static PetscErrorCode TSResizeReset(TS ts) 3789 { 3790 PetscFunctionBegin; 3791 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3792 PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs)); 3793 PetscFunctionReturn(PETSC_SUCCESS); 3794 } 3795 3796 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[]) 3797 { 3798 PetscFunctionBegin; 3799 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3800 PetscValidLogicalCollectiveInt(ts, cnt, 2); 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 } 3809 3810 /*@C 3811 TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`. 3812 3813 Collective 3814 3815 Input Parameters: 3816 + ts - The `TS` context obtained from `TSCreate()` 3817 . name - A string identifying the vector 3818 - vec - The vector 3819 3820 Level: developer 3821 3822 Note: 3823 `TSResizeRegisterVec()` is typically used within time stepping implementations, 3824 so most users would not generally call this routine themselves. 3825 3826 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()` 3827 @*/ 3828 PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec) 3829 { 3830 PetscFunctionBegin; 3831 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3832 PetscAssertPointer(name, 2); 3833 if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3); 3834 PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec)); 3835 PetscFunctionReturn(PETSC_SUCCESS); 3836 } 3837 3838 /*@C 3839 TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`. 3840 3841 Collective 3842 3843 Input Parameters: 3844 + ts - The `TS` context obtained from `TSCreate()` 3845 . name - A string identifying the vector 3846 - vec - The vector 3847 3848 Level: developer 3849 3850 Note: 3851 `TSResizeRetrieveVec()` is typically used within time stepping implementations, 3852 so most users would not generally call this routine themselves. 3853 3854 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()` 3855 @*/ 3856 PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec) 3857 { 3858 PetscFunctionBegin; 3859 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3860 PetscAssertPointer(name, 2); 3861 PetscAssertPointer(vec, 3); 3862 PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec)); 3863 PetscFunctionReturn(PETSC_SUCCESS); 3864 } 3865 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; 3872 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 } 3890 3891 /*@ 3892 TSResize - Runs the user-defined transfer functions provided with `TSSetResize()` 3893 3894 Collective 3895 3896 Input Parameter: 3897 . ts - The `TS` context obtained from `TSCreate()` 3898 3899 Level: developer 3900 3901 Note: 3902 `TSResize()` is typically used within time stepping implementations, 3903 so most users would not generally call this routine themselves. 3904 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"; 3913 3914 PetscFunctionBegin; 3915 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 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 } 3930 3931 PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin)); 3932 if (nv) { 3933 Vec *vecsout, vecsol; 3934 3935 /* Reset internal objects */ 3936 PetscCall(TSReset(ts)); 3937 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; 3944 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 */ 3954 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 } 3959 3960 PetscCall(PetscFree(names)); 3961 PetscCall(PetscFree(vecsin)); 3962 PetscCall(TSResizeReset(ts)); 3963 PetscFunctionReturn(PETSC_SUCCESS); 3964 } 3965 3966 /*@ 3967 TSSolve - Steps the requested number of timesteps. 3968 3969 Collective 3970 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 3975 3976 Level: beginner 3977 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. 3982 3983 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3984 @*/ 3985 PetscErrorCode TSSolve(TS ts, Vec u) 3986 { 3987 Vec solution; 3988 3989 PetscFunctionBegin; 3990 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3991 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3992 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)); 4005 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"); 4010 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 } 4026 4027 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 4028 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 } 4044 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; 4049 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; 4055 4056 { 4057 PetscViewer viewer; 4058 PetscViewerFormat format; 4059 PetscBool flg; 4060 static PetscBool incall = PETSC_FALSE; 4061 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; 4071 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 } 4093 4094 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 4095 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; 4104 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 } 4109 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)); 4139 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)); 4152 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 } 4165 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 } 4172 4173 /*@ 4174 TSGetTime - Gets the time of the most recently completed step. 4175 4176 Not Collective 4177 4178 Input Parameter: 4179 . ts - the `TS` context obtained from `TSCreate()` 4180 4181 Output Parameter: 4182 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 4183 4184 Level: beginner 4185 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. 4189 4190 .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 4191 @*/ 4192 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 4193 { 4194 PetscFunctionBegin; 4195 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4196 PetscAssertPointer(t, 2); 4197 *t = ts->ptime; 4198 PetscFunctionReturn(PETSC_SUCCESS); 4199 } 4200 4201 /*@ 4202 TSGetPrevTime - Gets the starting time of the previously completed step. 4203 4204 Not Collective 4205 4206 Input Parameter: 4207 . ts - the `TS` context obtained from `TSCreate()` 4208 4209 Output Parameter: 4210 . t - the previous time 4211 4212 Level: beginner 4213 4214 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4215 @*/ 4216 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 4217 { 4218 PetscFunctionBegin; 4219 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4220 PetscAssertPointer(t, 2); 4221 *t = ts->ptime_prev; 4222 PetscFunctionReturn(PETSC_SUCCESS); 4223 } 4224 4225 /*@ 4226 TSSetTime - Allows one to reset the time. 4227 4228 Logically Collective 4229 4230 Input Parameters: 4231 + ts - the `TS` context obtained from `TSCreate()` 4232 - t - the time 4233 4234 Level: intermediate 4235 4236 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 4237 @*/ 4238 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4239 { 4240 PetscFunctionBegin; 4241 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4242 PetscValidLogicalCollectiveReal(ts, t, 2); 4243 ts->ptime = t; 4244 PetscFunctionReturn(PETSC_SUCCESS); 4245 } 4246 4247 /*@ 4248 TSSetOptionsPrefix - Sets the prefix used for searching for all 4249 TS options in the database. 4250 4251 Logically Collective 4252 4253 Input Parameters: 4254 + ts - The `TS` context 4255 - prefix - The prefix to prepend to all option names 4256 4257 Level: advanced 4258 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. 4263 4264 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 4265 @*/ 4266 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 4267 { 4268 SNES snes; 4269 4270 PetscFunctionBegin; 4271 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4272 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 4273 PetscCall(TSGetSNES(ts, &snes)); 4274 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 4275 PetscFunctionReturn(PETSC_SUCCESS); 4276 } 4277 4278 /*@ 4279 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4280 TS options in the database. 4281 4282 Logically Collective 4283 4284 Input Parameters: 4285 + ts - The `TS` context 4286 - prefix - The prefix to prepend to all option names 4287 4288 Level: advanced 4289 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. 4294 4295 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 4296 @*/ 4297 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 4298 { 4299 SNES snes; 4300 4301 PetscFunctionBegin; 4302 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4303 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 4304 PetscCall(TSGetSNES(ts, &snes)); 4305 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 4306 PetscFunctionReturn(PETSC_SUCCESS); 4307 } 4308 4309 /*@ 4310 TSGetOptionsPrefix - Sets the prefix used for searching for all 4311 `TS` options in the database. 4312 4313 Not Collective 4314 4315 Input Parameter: 4316 . ts - The `TS` context 4317 4318 Output Parameter: 4319 . prefix - A pointer to the prefix string used 4320 4321 Level: intermediate 4322 4323 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4324 @*/ 4325 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4326 { 4327 PetscFunctionBegin; 4328 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4329 PetscAssertPointer(prefix, 2); 4330 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4331 PetscFunctionReturn(PETSC_SUCCESS); 4332 } 4333 4334 /*@C 4335 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4336 4337 Not Collective, but parallel objects are returned if ts is parallel 4338 4339 Input Parameter: 4340 . ts - The `TS` context obtained from `TSCreate()` 4341 4342 Output Parameters: 4343 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4344 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4345 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4346 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4347 4348 Level: intermediate 4349 4350 Note: 4351 You can pass in `NULL` for any return argument you do not need. 4352 4353 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4354 4355 @*/ 4356 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx) 4357 { 4358 DM dm; 4359 4360 PetscFunctionBegin; 4361 if (Amat || Pmat) { 4362 SNES snes; 4363 PetscCall(TSGetSNES(ts, &snes)); 4364 PetscCall(SNESSetUpMatrices(snes)); 4365 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4366 } 4367 PetscCall(TSGetDM(ts, &dm)); 4368 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4369 PetscFunctionReturn(PETSC_SUCCESS); 4370 } 4371 4372 /*@C 4373 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4374 4375 Not Collective, but parallel objects are returned if ts is parallel 4376 4377 Input Parameter: 4378 . ts - The `TS` context obtained from `TSCreate()` 4379 4380 Output Parameters: 4381 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4382 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4383 . f - The function to compute the matrices 4384 - ctx - User-defined context for Jacobian evaluation routine 4385 4386 Level: advanced 4387 4388 Note: 4389 You can pass in `NULL` for any return argument you do not need. 4390 4391 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4392 @*/ 4393 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx) 4394 { 4395 DM dm; 4396 4397 PetscFunctionBegin; 4398 if (Amat || Pmat) { 4399 SNES snes; 4400 PetscCall(TSGetSNES(ts, &snes)); 4401 PetscCall(SNESSetUpMatrices(snes)); 4402 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4403 } 4404 PetscCall(TSGetDM(ts, &dm)); 4405 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4406 PetscFunctionReturn(PETSC_SUCCESS); 4407 } 4408 4409 #include <petsc/private/dmimpl.h> 4410 /*@ 4411 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4412 4413 Logically Collective 4414 4415 Input Parameters: 4416 + ts - the `TS` integrator object 4417 - dm - the dm, cannot be `NULL` 4418 4419 Level: intermediate 4420 4421 Notes: 4422 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4423 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4424 different problems using the same function space. 4425 4426 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4427 @*/ 4428 PetscErrorCode TSSetDM(TS ts, DM dm) 4429 { 4430 SNES snes; 4431 DMTS tsdm; 4432 4433 PetscFunctionBegin; 4434 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4435 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4436 PetscCall(PetscObjectReference((PetscObject)dm)); 4437 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4438 if (ts->dm->dmts && !dm->dmts) { 4439 PetscCall(DMCopyDMTS(ts->dm, dm)); 4440 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4441 /* Grant write privileges to the replacement DM */ 4442 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4443 } 4444 PetscCall(DMDestroy(&ts->dm)); 4445 } 4446 ts->dm = dm; 4447 4448 PetscCall(TSGetSNES(ts, &snes)); 4449 PetscCall(SNESSetDM(snes, dm)); 4450 PetscFunctionReturn(PETSC_SUCCESS); 4451 } 4452 4453 /*@ 4454 TSGetDM - Gets the `DM` that may be used by some preconditioners 4455 4456 Not Collective 4457 4458 Input Parameter: 4459 . ts - the `TS` 4460 4461 Output Parameter: 4462 . dm - the `DM` 4463 4464 Level: intermediate 4465 4466 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4467 @*/ 4468 PetscErrorCode TSGetDM(TS ts, DM *dm) 4469 { 4470 PetscFunctionBegin; 4471 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4472 if (!ts->dm) { 4473 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4474 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4475 } 4476 *dm = ts->dm; 4477 PetscFunctionReturn(PETSC_SUCCESS); 4478 } 4479 4480 /*@ 4481 SNESTSFormFunction - Function to evaluate nonlinear residual 4482 4483 Logically Collective 4484 4485 Input Parameters: 4486 + snes - nonlinear solver 4487 . U - the current state at which to evaluate the residual 4488 - ctx - user context, must be a TS 4489 4490 Output Parameter: 4491 . F - the nonlinear residual 4492 4493 Level: advanced 4494 4495 Note: 4496 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4497 It is most frequently passed to `MatFDColoringSetFunction()`. 4498 4499 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4500 @*/ 4501 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4502 { 4503 TS ts = (TS)ctx; 4504 4505 PetscFunctionBegin; 4506 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4507 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4508 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4509 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4510 PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name); 4511 PetscCall((*ts->ops->snesfunction)(snes, U, F, ts)); 4512 PetscFunctionReturn(PETSC_SUCCESS); 4513 } 4514 4515 /*@ 4516 SNESTSFormJacobian - Function to evaluate the Jacobian 4517 4518 Collective 4519 4520 Input Parameters: 4521 + snes - nonlinear solver 4522 . U - the current state at which to evaluate the residual 4523 - ctx - user context, must be a `TS` 4524 4525 Output Parameters: 4526 + A - the Jacobian 4527 - B - the preconditioning matrix (may be the same as A) 4528 4529 Level: developer 4530 4531 Note: 4532 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4533 4534 .seealso: [](ch_ts), `SNESSetJacobian()` 4535 @*/ 4536 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4537 { 4538 TS ts = (TS)ctx; 4539 4540 PetscFunctionBegin; 4541 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4542 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4543 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4544 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4545 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4546 PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name); 4547 PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts)); 4548 PetscFunctionReturn(PETSC_SUCCESS); 4549 } 4550 4551 /*@C 4552 TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only 4553 4554 Collective 4555 4556 Input Parameters: 4557 + ts - time stepping context 4558 . t - time at which to evaluate 4559 . U - state at which to evaluate 4560 - ctx - context 4561 4562 Output Parameter: 4563 . F - right-hand side 4564 4565 Level: intermediate 4566 4567 Note: 4568 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems. 4569 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4570 4571 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4572 @*/ 4573 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4574 { 4575 Mat Arhs, Brhs; 4576 4577 PetscFunctionBegin; 4578 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4579 /* undo the damage caused by shifting */ 4580 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4581 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4582 PetscCall(MatMult(Arhs, U, F)); 4583 PetscFunctionReturn(PETSC_SUCCESS); 4584 } 4585 4586 /*@C 4587 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4588 4589 Collective 4590 4591 Input Parameters: 4592 + ts - time stepping context 4593 . t - time at which to evaluate 4594 . U - state at which to evaluate 4595 - ctx - context 4596 4597 Output Parameters: 4598 + A - pointer to operator 4599 - B - pointer to preconditioning matrix 4600 4601 Level: intermediate 4602 4603 Note: 4604 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4605 4606 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4607 @*/ 4608 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4609 { 4610 PetscFunctionBegin; 4611 PetscFunctionReturn(PETSC_SUCCESS); 4612 } 4613 4614 /*@C 4615 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4616 4617 Collective 4618 4619 Input Parameters: 4620 + ts - time stepping context 4621 . t - time at which to evaluate 4622 . U - state at which to evaluate 4623 . Udot - time derivative of state vector 4624 - ctx - context 4625 4626 Output Parameter: 4627 . F - left hand side 4628 4629 Level: intermediate 4630 4631 Notes: 4632 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 4633 user is required to write their own `TSComputeIFunction()`. 4634 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4635 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4636 4637 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4638 4639 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4640 @*/ 4641 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4642 { 4643 Mat A, B; 4644 4645 PetscFunctionBegin; 4646 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4647 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4648 PetscCall(MatMult(A, Udot, F)); 4649 PetscFunctionReturn(PETSC_SUCCESS); 4650 } 4651 4652 /*@C 4653 TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE 4654 4655 Collective 4656 4657 Input Parameters: 4658 + ts - time stepping context 4659 . t - time at which to evaluate 4660 . U - state at which to evaluate 4661 . Udot - time derivative of state vector 4662 . shift - shift to apply 4663 - ctx - context 4664 4665 Output Parameters: 4666 + A - pointer to operator 4667 - B - pointer to matrix from which the preconditioner is built (often `A`) 4668 4669 Level: advanced 4670 4671 Notes: 4672 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4673 4674 It is only appropriate for problems of the form 4675 4676 $$ 4677 M \dot{U} = F(U,t) 4678 $$ 4679 4680 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4681 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4682 an implicit operator of the form 4683 4684 $$ 4685 shift*M + J 4686 $$ 4687 4688 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 4689 a copy of M or reassemble it when requested. 4690 4691 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4692 @*/ 4693 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4694 { 4695 PetscFunctionBegin; 4696 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4697 ts->ijacobian.shift = shift; 4698 PetscFunctionReturn(PETSC_SUCCESS); 4699 } 4700 4701 /*@ 4702 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4703 4704 Not Collective 4705 4706 Input Parameter: 4707 . ts - the `TS` context 4708 4709 Output Parameter: 4710 . equation_type - see `TSEquationType` 4711 4712 Level: beginner 4713 4714 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4715 @*/ 4716 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4717 { 4718 PetscFunctionBegin; 4719 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4720 PetscAssertPointer(equation_type, 2); 4721 *equation_type = ts->equation_type; 4722 PetscFunctionReturn(PETSC_SUCCESS); 4723 } 4724 4725 /*@ 4726 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4727 4728 Not Collective 4729 4730 Input Parameters: 4731 + ts - the `TS` context 4732 - equation_type - see `TSEquationType` 4733 4734 Level: advanced 4735 4736 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4737 @*/ 4738 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4739 { 4740 PetscFunctionBegin; 4741 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4742 ts->equation_type = equation_type; 4743 PetscFunctionReturn(PETSC_SUCCESS); 4744 } 4745 4746 /*@ 4747 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4748 4749 Not Collective 4750 4751 Input Parameter: 4752 . ts - the `TS` context 4753 4754 Output Parameter: 4755 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4756 manual pages for the individual convergence tests for complete lists 4757 4758 Level: beginner 4759 4760 Note: 4761 Can only be called after the call to `TSSolve()` is complete. 4762 4763 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4764 @*/ 4765 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4766 { 4767 PetscFunctionBegin; 4768 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4769 PetscAssertPointer(reason, 2); 4770 *reason = ts->reason; 4771 PetscFunctionReturn(PETSC_SUCCESS); 4772 } 4773 4774 /*@ 4775 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4776 4777 Logically Collective; reason must contain common value 4778 4779 Input Parameters: 4780 + ts - the `TS` context 4781 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4782 manual pages for the individual convergence tests for complete lists 4783 4784 Level: advanced 4785 4786 Note: 4787 Can only be called while `TSSolve()` is active. 4788 4789 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4790 @*/ 4791 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4792 { 4793 PetscFunctionBegin; 4794 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4795 ts->reason = reason; 4796 PetscFunctionReturn(PETSC_SUCCESS); 4797 } 4798 4799 /*@ 4800 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4801 4802 Not Collective 4803 4804 Input Parameter: 4805 . ts - the `TS` context 4806 4807 Output Parameter: 4808 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4809 4810 Level: beginner 4811 4812 Note: 4813 Can only be called after the call to `TSSolve()` is complete. 4814 4815 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4816 @*/ 4817 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4818 { 4819 PetscFunctionBegin; 4820 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4821 PetscAssertPointer(ftime, 2); 4822 *ftime = ts->solvetime; 4823 PetscFunctionReturn(PETSC_SUCCESS); 4824 } 4825 4826 /*@ 4827 TSGetSNESIterations - Gets the total number of nonlinear iterations 4828 used by the time integrator. 4829 4830 Not Collective 4831 4832 Input Parameter: 4833 . ts - `TS` context 4834 4835 Output Parameter: 4836 . nits - number of nonlinear iterations 4837 4838 Level: intermediate 4839 4840 Note: 4841 This counter is reset to zero for each successive call to `TSSolve()`. 4842 4843 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4844 @*/ 4845 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4846 { 4847 PetscFunctionBegin; 4848 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4849 PetscAssertPointer(nits, 2); 4850 *nits = ts->snes_its; 4851 PetscFunctionReturn(PETSC_SUCCESS); 4852 } 4853 4854 /*@ 4855 TSGetKSPIterations - Gets the total number of linear iterations 4856 used by the time integrator. 4857 4858 Not Collective 4859 4860 Input Parameter: 4861 . ts - `TS` context 4862 4863 Output Parameter: 4864 . lits - number of linear iterations 4865 4866 Level: intermediate 4867 4868 Note: 4869 This counter is reset to zero for each successive call to `TSSolve()`. 4870 4871 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()` 4872 @*/ 4873 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4874 { 4875 PetscFunctionBegin; 4876 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4877 PetscAssertPointer(lits, 2); 4878 *lits = ts->ksp_its; 4879 PetscFunctionReturn(PETSC_SUCCESS); 4880 } 4881 4882 /*@ 4883 TSGetStepRejections - Gets the total number of rejected steps. 4884 4885 Not Collective 4886 4887 Input Parameter: 4888 . ts - `TS` context 4889 4890 Output Parameter: 4891 . rejects - number of steps rejected 4892 4893 Level: intermediate 4894 4895 Note: 4896 This counter is reset to zero for each successive call to `TSSolve()`. 4897 4898 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4899 @*/ 4900 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4901 { 4902 PetscFunctionBegin; 4903 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4904 PetscAssertPointer(rejects, 2); 4905 *rejects = ts->reject; 4906 PetscFunctionReturn(PETSC_SUCCESS); 4907 } 4908 4909 /*@ 4910 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4911 4912 Not Collective 4913 4914 Input Parameter: 4915 . ts - `TS` context 4916 4917 Output Parameter: 4918 . fails - number of failed nonlinear solves 4919 4920 Level: intermediate 4921 4922 Note: 4923 This counter is reset to zero for each successive call to `TSSolve()`. 4924 4925 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4926 @*/ 4927 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4928 { 4929 PetscFunctionBegin; 4930 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4931 PetscAssertPointer(fails, 2); 4932 *fails = ts->num_snes_failures; 4933 PetscFunctionReturn(PETSC_SUCCESS); 4934 } 4935 4936 /*@ 4937 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4938 4939 Not Collective 4940 4941 Input Parameters: 4942 + ts - `TS` context 4943 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited 4944 4945 Options Database Key: 4946 . -ts_max_reject - Maximum number of step rejections before a step fails 4947 4948 Level: intermediate 4949 4950 Developer Note: 4951 The options database name is incorrect. 4952 4953 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4954 @*/ 4955 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4956 { 4957 PetscFunctionBegin; 4958 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4959 if (rejects == PETSC_UNLIMITED || rejects == -1) { 4960 ts->max_reject = PETSC_UNLIMITED; 4961 } else { 4962 PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections"); 4963 ts->max_reject = rejects; 4964 } 4965 PetscFunctionReturn(PETSC_SUCCESS); 4966 } 4967 4968 /*@ 4969 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4970 4971 Not Collective 4972 4973 Input Parameters: 4974 + ts - `TS` context 4975 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures. 4976 4977 Options Database Key: 4978 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4979 4980 Level: intermediate 4981 4982 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4983 @*/ 4984 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4985 { 4986 PetscFunctionBegin; 4987 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4988 if (fails == PETSC_UNLIMITED || fails == -1) { 4989 ts->max_snes_failures = PETSC_UNLIMITED; 4990 } else { 4991 PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 4992 ts->max_snes_failures = fails; 4993 } 4994 PetscFunctionReturn(PETSC_SUCCESS); 4995 } 4996 4997 /*@ 4998 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 4999 5000 Not Collective 5001 5002 Input Parameters: 5003 + ts - `TS` context 5004 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 5005 5006 Options Database Key: 5007 . -ts_error_if_step_fails - Error if no step succeeds 5008 5009 Level: intermediate 5010 5011 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()` 5012 @*/ 5013 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 5014 { 5015 PetscFunctionBegin; 5016 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5017 ts->errorifstepfailed = err; 5018 PetscFunctionReturn(PETSC_SUCCESS); 5019 } 5020 5021 /*@ 5022 TSGetAdapt - Get the adaptive controller context for the current method 5023 5024 Collective if controller has not yet been created 5025 5026 Input Parameter: 5027 . ts - time stepping context 5028 5029 Output Parameter: 5030 . adapt - adaptive controller 5031 5032 Level: intermediate 5033 5034 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 5035 @*/ 5036 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 5037 { 5038 PetscFunctionBegin; 5039 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5040 PetscAssertPointer(adapt, 2); 5041 if (!ts->adapt) { 5042 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 5043 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 5044 } 5045 *adapt = ts->adapt; 5046 PetscFunctionReturn(PETSC_SUCCESS); 5047 } 5048 5049 /*@ 5050 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 5051 5052 Logically Collective 5053 5054 Input Parameters: 5055 + ts - time integration context 5056 . atol - scalar absolute tolerances 5057 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present 5058 . rtol - scalar relative tolerances 5059 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present 5060 5061 Options Database Keys: 5062 + -ts_rtol <rtol> - relative tolerance for local truncation error 5063 - -ts_atol <atol> - Absolute tolerance for local truncation error 5064 5065 Level: beginner 5066 5067 Notes: 5068 `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value 5069 or the default value from when the object's type was set. 5070 5071 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5072 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5073 computed only for the differential or the algebraic part then this can be done using the vector of 5074 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5075 differential part and infinity for the algebraic part, the LTE calculation will include only the 5076 differential variables. 5077 5078 Fortran Note: 5079 Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`. 5080 5081 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5082 @*/ 5083 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5084 { 5085 PetscFunctionBegin; 5086 if (atol == (PetscReal)PETSC_DETERMINE) { 5087 ts->atol = ts->default_atol; 5088 } else if (atol != (PetscReal)PETSC_CURRENT) { 5089 PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol); 5090 ts->atol = atol; 5091 } 5092 5093 if (vatol) { 5094 PetscCall(PetscObjectReference((PetscObject)vatol)); 5095 PetscCall(VecDestroy(&ts->vatol)); 5096 ts->vatol = vatol; 5097 } 5098 5099 if (rtol == (PetscReal)PETSC_DETERMINE) { 5100 ts->rtol = ts->default_rtol; 5101 } else if (rtol != (PetscReal)PETSC_CURRENT) { 5102 PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol); 5103 ts->rtol = rtol; 5104 } 5105 5106 if (vrtol) { 5107 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5108 PetscCall(VecDestroy(&ts->vrtol)); 5109 ts->vrtol = vrtol; 5110 } 5111 PetscFunctionReturn(PETSC_SUCCESS); 5112 } 5113 5114 /*@ 5115 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5116 5117 Logically Collective 5118 5119 Input Parameter: 5120 . ts - time integration context 5121 5122 Output Parameters: 5123 + atol - scalar absolute tolerances, `NULL` to ignore 5124 . vatol - vector of absolute tolerances, `NULL` to ignore 5125 . rtol - scalar relative tolerances, `NULL` to ignore 5126 - vrtol - vector of relative tolerances, `NULL` to ignore 5127 5128 Level: beginner 5129 5130 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5131 @*/ 5132 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5133 { 5134 PetscFunctionBegin; 5135 if (atol) *atol = ts->atol; 5136 if (vatol) *vatol = ts->vatol; 5137 if (rtol) *rtol = ts->rtol; 5138 if (vrtol) *vrtol = ts->vrtol; 5139 PetscFunctionReturn(PETSC_SUCCESS); 5140 } 5141 5142 /*@ 5143 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5144 5145 Collective 5146 5147 Input Parameters: 5148 + ts - time stepping context 5149 . U - state vector, usually ts->vec_sol 5150 . Y - state vector to be compared to U 5151 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5152 5153 Output Parameters: 5154 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5155 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5156 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5157 5158 Options Database Key: 5159 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5160 5161 Level: developer 5162 5163 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5164 @*/ 5165 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5166 { 5167 PetscInt norma_loc, norm_loc, normr_loc; 5168 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5171 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)); 5172 if (wnormtype == NORM_2) { 5173 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5174 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5175 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5176 } 5177 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5178 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5179 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5180 PetscFunctionReturn(PETSC_SUCCESS); 5181 } 5182 5183 /*@ 5184 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5185 5186 Collective 5187 5188 Input Parameters: 5189 + ts - time stepping context 5190 . E - error vector 5191 . U - state vector, usually ts->vec_sol 5192 . Y - state vector, previous time step 5193 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5194 5195 Output Parameters: 5196 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5197 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5198 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5199 5200 Options Database Key: 5201 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5202 5203 Level: developer 5204 5205 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5206 @*/ 5207 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5208 { 5209 PetscInt norma_loc, norm_loc, normr_loc; 5210 5211 PetscFunctionBegin; 5212 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5213 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)); 5214 if (wnormtype == NORM_2) { 5215 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5216 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5217 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5218 } 5219 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5220 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5221 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5222 PetscFunctionReturn(PETSC_SUCCESS); 5223 } 5224 5225 /*@ 5226 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5227 5228 Logically Collective 5229 5230 Input Parameters: 5231 + ts - time stepping context 5232 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5233 5234 Note: 5235 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5236 5237 Level: intermediate 5238 5239 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5240 @*/ 5241 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5242 { 5243 PetscFunctionBegin; 5244 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5245 ts->cfltime_local = cfltime; 5246 ts->cfltime = -1.; 5247 PetscFunctionReturn(PETSC_SUCCESS); 5248 } 5249 5250 /*@ 5251 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5252 5253 Collective 5254 5255 Input Parameter: 5256 . ts - time stepping context 5257 5258 Output Parameter: 5259 . cfltime - maximum stable time step for forward Euler 5260 5261 Level: advanced 5262 5263 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5264 @*/ 5265 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5266 { 5267 PetscFunctionBegin; 5268 if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5269 *cfltime = ts->cfltime; 5270 PetscFunctionReturn(PETSC_SUCCESS); 5271 } 5272 5273 /*@ 5274 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5275 5276 Input Parameters: 5277 + ts - the `TS` context. 5278 . xl - lower bound. 5279 - xu - upper bound. 5280 5281 Level: advanced 5282 5283 Note: 5284 If this routine is not called then the lower and upper bounds are set to 5285 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5286 5287 .seealso: [](ch_ts), `TS` 5288 @*/ 5289 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5290 { 5291 SNES snes; 5292 5293 PetscFunctionBegin; 5294 PetscCall(TSGetSNES(ts, &snes)); 5295 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5296 PetscFunctionReturn(PETSC_SUCCESS); 5297 } 5298 5299 /*@ 5300 TSComputeLinearStability - computes the linear stability function at a point 5301 5302 Collective 5303 5304 Input Parameters: 5305 + ts - the `TS` context 5306 . xr - real part of input argument 5307 - xi - imaginary part of input argument 5308 5309 Output Parameters: 5310 + yr - real part of function value 5311 - yi - imaginary part of function value 5312 5313 Level: developer 5314 5315 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5316 @*/ 5317 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5318 { 5319 PetscFunctionBegin; 5320 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5321 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5322 PetscFunctionReturn(PETSC_SUCCESS); 5323 } 5324 5325 /*@ 5326 TSRestartStep - Flags the solver to restart the next step 5327 5328 Collective 5329 5330 Input Parameter: 5331 . ts - the `TS` context obtained from `TSCreate()` 5332 5333 Level: advanced 5334 5335 Notes: 5336 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5337 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5338 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5339 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5340 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5341 discontinuous source terms). 5342 5343 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5344 @*/ 5345 PetscErrorCode TSRestartStep(TS ts) 5346 { 5347 PetscFunctionBegin; 5348 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5349 ts->steprestart = PETSC_TRUE; 5350 PetscFunctionReturn(PETSC_SUCCESS); 5351 } 5352 5353 /*@ 5354 TSRollBack - Rolls back one time step 5355 5356 Collective 5357 5358 Input Parameter: 5359 . ts - the `TS` context obtained from `TSCreate()` 5360 5361 Level: advanced 5362 5363 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5364 @*/ 5365 PetscErrorCode TSRollBack(TS ts) 5366 { 5367 PetscFunctionBegin; 5368 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5369 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5370 PetscTryTypeMethod(ts, rollback); 5371 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 5372 ts->time_step = ts->ptime - ts->ptime_prev; 5373 ts->ptime = ts->ptime_prev; 5374 ts->ptime_prev = ts->ptime_prev_rollback; 5375 ts->steps--; 5376 ts->steprollback = PETSC_TRUE; 5377 PetscFunctionReturn(PETSC_SUCCESS); 5378 } 5379 5380 /*@ 5381 TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step 5382 5383 Not collective 5384 5385 Input Parameter: 5386 . ts - the `TS` context obtained from `TSCreate()` 5387 5388 Output Parameter: 5389 . flg - the rollback flag 5390 5391 Level: advanced 5392 5393 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()` 5394 @*/ 5395 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg) 5396 { 5397 PetscFunctionBegin; 5398 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5399 PetscAssertPointer(flg, 2); 5400 *flg = ts->steprollback; 5401 PetscFunctionReturn(PETSC_SUCCESS); 5402 } 5403 5404 /*@ 5405 TSGetStepResize - Get the internal flag indicating if the current step is after a resize. 5406 5407 Not collective 5408 5409 Input Parameter: 5410 . ts - the `TS` context obtained from `TSCreate()` 5411 5412 Output Parameter: 5413 . flg - the resize flag 5414 5415 Level: advanced 5416 5417 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()` 5418 @*/ 5419 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg) 5420 { 5421 PetscFunctionBegin; 5422 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5423 PetscAssertPointer(flg, 2); 5424 *flg = ts->stepresize; 5425 PetscFunctionReturn(PETSC_SUCCESS); 5426 } 5427 5428 /*@ 5429 TSGetStages - Get the number of stages and stage values 5430 5431 Input Parameter: 5432 . ts - the `TS` context obtained from `TSCreate()` 5433 5434 Output Parameters: 5435 + ns - the number of stages 5436 - Y - the current stage vectors 5437 5438 Level: advanced 5439 5440 Note: 5441 Both `ns` and `Y` can be `NULL`. 5442 5443 .seealso: [](ch_ts), `TS`, `TSCreate()` 5444 @*/ 5445 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5446 { 5447 PetscFunctionBegin; 5448 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5449 if (ns) PetscAssertPointer(ns, 2); 5450 if (Y) PetscAssertPointer(Y, 3); 5451 if (!ts->ops->getstages) { 5452 if (ns) *ns = 0; 5453 if (Y) *Y = NULL; 5454 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5455 PetscFunctionReturn(PETSC_SUCCESS); 5456 } 5457 5458 /*@C 5459 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5460 5461 Collective 5462 5463 Input Parameters: 5464 + ts - the `TS` context 5465 . t - current timestep 5466 . U - state vector 5467 . Udot - time derivative of state vector 5468 . shift - shift to apply, see note below 5469 - ctx - an optional user context 5470 5471 Output Parameters: 5472 + J - Jacobian matrix (not altered in this routine) 5473 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5474 5475 Level: intermediate 5476 5477 Notes: 5478 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5479 5480 dF/dU + shift*dF/dUdot 5481 5482 Most users should not need to explicitly call this routine, as it 5483 is used internally within the nonlinear solvers. 5484 5485 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5486 routine, then it will try to get the coloring from the matrix. This requires that the 5487 matrix have nonzero entries precomputed. 5488 5489 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5490 @*/ 5491 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5492 { 5493 SNES snes; 5494 MatFDColoring color; 5495 PetscBool hascolor, matcolor = PETSC_FALSE; 5496 5497 PetscFunctionBegin; 5498 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5499 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5500 if (!color) { 5501 DM dm; 5502 ISColoring iscoloring; 5503 5504 PetscCall(TSGetDM(ts, &dm)); 5505 PetscCall(DMHasColoring(dm, &hascolor)); 5506 if (hascolor && !matcolor) { 5507 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5508 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5509 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5510 PetscCall(MatFDColoringSetFromOptions(color)); 5511 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5512 PetscCall(ISColoringDestroy(&iscoloring)); 5513 } else { 5514 MatColoring mc; 5515 5516 PetscCall(MatColoringCreate(B, &mc)); 5517 PetscCall(MatColoringSetDistance(mc, 2)); 5518 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5519 PetscCall(MatColoringSetFromOptions(mc)); 5520 PetscCall(MatColoringApply(mc, &iscoloring)); 5521 PetscCall(MatColoringDestroy(&mc)); 5522 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5523 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5524 PetscCall(MatFDColoringSetFromOptions(color)); 5525 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5526 PetscCall(ISColoringDestroy(&iscoloring)); 5527 } 5528 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5529 PetscCall(PetscObjectDereference((PetscObject)color)); 5530 } 5531 PetscCall(TSGetSNES(ts, &snes)); 5532 PetscCall(MatFDColoringApply(B, color, U, snes)); 5533 if (J != B) { 5534 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5535 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5536 } 5537 PetscFunctionReturn(PETSC_SUCCESS); 5538 } 5539 5540 /*@C 5541 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5542 5543 Input Parameters: 5544 + ts - the `TS` context 5545 - func - function called within `TSFunctionDomainError()` 5546 5547 Calling sequence of `func`: 5548 + ts - the `TS` context 5549 . time - the current time (of the stage) 5550 . state - the state to check if it is valid 5551 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable 5552 5553 Level: intermediate 5554 5555 Notes: 5556 If an implicit ODE solver is being used then, in addition to providing this routine, the 5557 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5558 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5559 Use `TSGetSNES()` to obtain the `SNES` object 5560 5561 Developer Notes: 5562 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5563 since one takes a function pointer and the other does not. 5564 5565 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5566 @*/ 5567 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept)) 5568 { 5569 PetscFunctionBegin; 5570 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5571 ts->functiondomainerror = func; 5572 PetscFunctionReturn(PETSC_SUCCESS); 5573 } 5574 5575 /*@ 5576 TSFunctionDomainError - Checks if the current state is valid 5577 5578 Input Parameters: 5579 + ts - the `TS` context 5580 . stagetime - time of the simulation 5581 - Y - state vector to check. 5582 5583 Output Parameter: 5584 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5585 5586 Level: developer 5587 5588 Note: 5589 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5590 to check if the current state is valid. 5591 5592 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5593 @*/ 5594 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5595 { 5596 PetscFunctionBegin; 5597 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5598 *accept = PETSC_TRUE; 5599 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5600 PetscFunctionReturn(PETSC_SUCCESS); 5601 } 5602 5603 /*@ 5604 TSClone - This function clones a time step `TS` object. 5605 5606 Collective 5607 5608 Input Parameter: 5609 . tsin - The input `TS` 5610 5611 Output Parameter: 5612 . tsout - The output `TS` (cloned) 5613 5614 Level: developer 5615 5616 Notes: 5617 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. 5618 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5619 5620 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 5621 .vb 5622 SNES snes_dup = NULL; 5623 TSGetSNES(ts,&snes_dup); 5624 TSSetSNES(ts,snes_dup); 5625 .ve 5626 5627 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5628 @*/ 5629 PetscErrorCode TSClone(TS tsin, TS *tsout) 5630 { 5631 TS t; 5632 SNES snes_start; 5633 DM dm; 5634 TSType type; 5635 5636 PetscFunctionBegin; 5637 PetscAssertPointer(tsin, 1); 5638 *tsout = NULL; 5639 5640 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5641 5642 /* General TS description */ 5643 t->numbermonitors = 0; 5644 t->monitorFrequency = 1; 5645 t->setupcalled = 0; 5646 t->ksp_its = 0; 5647 t->snes_its = 0; 5648 t->nwork = 0; 5649 t->rhsjacobian.time = PETSC_MIN_REAL; 5650 t->rhsjacobian.scale = 1.; 5651 t->ijacobian.shift = 1.; 5652 5653 PetscCall(TSGetSNES(tsin, &snes_start)); 5654 PetscCall(TSSetSNES(t, snes_start)); 5655 5656 PetscCall(TSGetDM(tsin, &dm)); 5657 PetscCall(TSSetDM(t, dm)); 5658 5659 t->adapt = tsin->adapt; 5660 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5661 5662 t->trajectory = tsin->trajectory; 5663 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5664 5665 t->event = tsin->event; 5666 if (t->event) t->event->refct++; 5667 5668 t->problem_type = tsin->problem_type; 5669 t->ptime = tsin->ptime; 5670 t->ptime_prev = tsin->ptime_prev; 5671 t->time_step = tsin->time_step; 5672 t->max_time = tsin->max_time; 5673 t->steps = tsin->steps; 5674 t->max_steps = tsin->max_steps; 5675 t->equation_type = tsin->equation_type; 5676 t->atol = tsin->atol; 5677 t->rtol = tsin->rtol; 5678 t->max_snes_failures = tsin->max_snes_failures; 5679 t->max_reject = tsin->max_reject; 5680 t->errorifstepfailed = tsin->errorifstepfailed; 5681 5682 PetscCall(TSGetType(tsin, &type)); 5683 PetscCall(TSSetType(t, type)); 5684 5685 t->vec_sol = NULL; 5686 5687 t->cfltime = tsin->cfltime; 5688 t->cfltime_local = tsin->cfltime_local; 5689 t->exact_final_time = tsin->exact_final_time; 5690 5691 t->ops[0] = tsin->ops[0]; 5692 5693 if (((PetscObject)tsin)->fortran_func_pointers) { 5694 PetscInt i; 5695 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5696 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5697 } 5698 *tsout = t; 5699 PetscFunctionReturn(PETSC_SUCCESS); 5700 } 5701 5702 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5703 { 5704 TS ts = (TS)ctx; 5705 5706 PetscFunctionBegin; 5707 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5708 PetscFunctionReturn(PETSC_SUCCESS); 5709 } 5710 5711 /*@ 5712 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5713 5714 Logically Collective 5715 5716 Input Parameter: 5717 . ts - the time stepping routine 5718 5719 Output Parameter: 5720 . flg - `PETSC_TRUE` if the multiply is likely correct 5721 5722 Options Database Key: 5723 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5724 5725 Level: advanced 5726 5727 Note: 5728 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5729 5730 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5731 @*/ 5732 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5733 { 5734 Mat J, B; 5735 TSRHSJacobianFn *func; 5736 void *ctx; 5737 5738 PetscFunctionBegin; 5739 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5740 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5741 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5742 PetscFunctionReturn(PETSC_SUCCESS); 5743 } 5744 5745 /*@ 5746 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5747 5748 Logically Collective 5749 5750 Input Parameter: 5751 . ts - the time stepping routine 5752 5753 Output Parameter: 5754 . flg - `PETSC_TRUE` if the multiply is likely correct 5755 5756 Options Database Key: 5757 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5758 5759 Level: advanced 5760 5761 Notes: 5762 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5763 5764 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5765 @*/ 5766 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5767 { 5768 Mat J, B; 5769 void *ctx; 5770 TSRHSJacobianFn *func; 5771 5772 PetscFunctionBegin; 5773 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5774 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5775 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5776 PetscFunctionReturn(PETSC_SUCCESS); 5777 } 5778 5779 /*@ 5780 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5781 5782 Logically Collective 5783 5784 Input Parameters: 5785 + ts - timestepping context 5786 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5787 5788 Options Database Key: 5789 . -ts_use_splitrhsfunction - <true,false> 5790 5791 Level: intermediate 5792 5793 Note: 5794 This is only for multirate methods 5795 5796 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5797 @*/ 5798 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5799 { 5800 PetscFunctionBegin; 5801 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5802 ts->use_splitrhsfunction = use_splitrhsfunction; 5803 PetscFunctionReturn(PETSC_SUCCESS); 5804 } 5805 5806 /*@ 5807 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5808 5809 Not Collective 5810 5811 Input Parameter: 5812 . ts - timestepping context 5813 5814 Output Parameter: 5815 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5816 5817 Level: intermediate 5818 5819 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5820 @*/ 5821 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5822 { 5823 PetscFunctionBegin; 5824 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5825 *use_splitrhsfunction = ts->use_splitrhsfunction; 5826 PetscFunctionReturn(PETSC_SUCCESS); 5827 } 5828 5829 /*@ 5830 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5831 5832 Logically Collective 5833 5834 Input Parameters: 5835 + ts - the time-stepper 5836 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5837 5838 Level: intermediate 5839 5840 Note: 5841 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5842 5843 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5844 @*/ 5845 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5846 { 5847 PetscFunctionBegin; 5848 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5849 ts->axpy_pattern = str; 5850 PetscFunctionReturn(PETSC_SUCCESS); 5851 } 5852 5853 /*@ 5854 TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested 5855 5856 Collective 5857 5858 Input Parameters: 5859 + ts - the time-stepper 5860 . n - number of the time points 5861 - time_points - array of the time points 5862 5863 Options Database Key: 5864 . -ts_eval_times <t0,...tn> - Sets the evaluation times 5865 5866 Level: intermediate 5867 5868 Notes: 5869 The elements in `time_points` must be all increasing. They correspond to the intermediate points for time integration. 5870 5871 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5872 5873 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may 5874 pressure the memory system when using a large number of time points. 5875 5876 .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()` 5877 @*/ 5878 PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal *time_points) 5879 { 5880 PetscBool is_sorted; 5881 5882 PetscFunctionBegin; 5883 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5884 if (ts->eval_times && n != ts->eval_times->num_time_points) { 5885 PetscCall(PetscFree(ts->eval_times->time_points)); 5886 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 5887 PetscCall(PetscMalloc1(n, &ts->eval_times->time_points)); 5888 } 5889 if (!ts->eval_times) { 5890 TSEvaluationTimes eval_times; 5891 PetscCall(PetscNew(&eval_times)); 5892 PetscCall(PetscMalloc1(n, &eval_times->time_points)); 5893 eval_times->reltol = 1e-6; 5894 eval_times->abstol = 10 * PETSC_MACHINE_EPSILON; 5895 eval_times->worktol = 0; 5896 ts->eval_times = eval_times; 5897 } 5898 ts->eval_times->num_time_points = n; 5899 PetscCall(PetscSortedReal(n, time_points, &is_sorted)); 5900 PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted"); 5901 PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n)); 5902 PetscFunctionReturn(PETSC_SUCCESS); 5903 } 5904 5905 /*@C 5906 TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()` 5907 5908 Not Collective 5909 5910 Input Parameter: 5911 . ts - the time-stepper 5912 5913 Output Parameters: 5914 + n - number of the time points 5915 - time_points - array of the time points 5916 5917 Level: beginner 5918 5919 Note: 5920 The values obtained are valid until the `TS` object is destroyed. 5921 5922 Both `n` and `time_points` can be `NULL`. 5923 5924 Also used to see time points set by `TSSetTimeSpan()`. 5925 5926 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()` 5927 @*/ 5928 PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[]) 5929 { 5930 PetscFunctionBegin; 5931 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5932 if (n) PetscAssertPointer(n, 2); 5933 if (time_points) PetscAssertPointer(time_points, 3); 5934 if (!ts->eval_times) { 5935 if (n) *n = 0; 5936 if (time_points) *time_points = NULL; 5937 } else { 5938 if (n) *n = ts->eval_times->num_time_points; 5939 if (time_points) *time_points = ts->eval_times->time_points; 5940 } 5941 PetscFunctionReturn(PETSC_SUCCESS); 5942 } 5943 5944 /*@C 5945 TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified 5946 5947 Input Parameter: 5948 . ts - the `TS` context obtained from `TSCreate()` 5949 5950 Output Parameters: 5951 + nsol - the number of solutions 5952 . sol_times - array of solution times corresponding to the solution vectors. See note below 5953 - Sols - the solution vectors 5954 5955 Level: intermediate 5956 5957 Notes: 5958 Both `nsol` and `Sols` can be `NULL`. 5959 5960 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()`. 5961 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times. 5962 5963 Also used to see view solutions requested by `TSSetTimeSpan()`. 5964 5965 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()` 5966 @*/ 5967 PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec **Sols) 5968 { 5969 PetscFunctionBegin; 5970 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5971 if (nsol) PetscAssertPointer(nsol, 2); 5972 if (sol_times) PetscAssertPointer(sol_times, 3); 5973 if (Sols) PetscAssertPointer(Sols, 4); 5974 if (!ts->eval_times) { 5975 if (nsol) *nsol = 0; 5976 if (sol_times) *sol_times = NULL; 5977 if (Sols) *Sols = NULL; 5978 } else { 5979 if (nsol) *nsol = ts->eval_times->sol_ctr; 5980 if (sol_times) *sol_times = ts->eval_times->sol_times; 5981 if (Sols) *Sols = ts->eval_times->sol_vecs; 5982 } 5983 PetscFunctionReturn(PETSC_SUCCESS); 5984 } 5985 5986 /*@ 5987 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 5988 5989 Collective 5990 5991 Input Parameters: 5992 + ts - the time-stepper 5993 . n - number of the time points (>=2) 5994 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5995 5996 Options Database Key: 5997 . -ts_time_span <t0,...tf> - Sets the time span 5998 5999 Level: intermediate 6000 6001 Notes: 6002 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. 6003 6004 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 6005 6006 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 6007 6008 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may 6009 pressure the memory system when using a large number of span points. 6010 6011 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()` 6012 @*/ 6013 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 6014 { 6015 PetscFunctionBegin; 6016 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6017 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 6018 PetscCall(TSSetEvaluationTimes(ts, n, span_times)); 6019 PetscCall(TSSetTime(ts, span_times[0])); 6020 PetscCall(TSSetMaxTime(ts, span_times[n - 1])); 6021 PetscFunctionReturn(PETSC_SUCCESS); 6022 } 6023 6024 /*@ 6025 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 6026 6027 Collective 6028 6029 Input Parameters: 6030 + ts - the `TS` context 6031 . J - Jacobian matrix (not altered in this routine) 6032 - B - newly computed Jacobian matrix to use with preconditioner 6033 6034 Level: intermediate 6035 6036 Notes: 6037 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 6038 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 6039 and multiple fields are involved. 6040 6041 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 6042 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 6043 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 6044 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 6045 6046 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 6047 @*/ 6048 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 6049 { 6050 MatColoring mc = NULL; 6051 ISColoring iscoloring = NULL; 6052 MatFDColoring matfdcoloring = NULL; 6053 6054 PetscFunctionBegin; 6055 /* Generate new coloring after eliminating zeros in the matrix */ 6056 PetscCall(MatEliminateZeros(B, PETSC_TRUE)); 6057 PetscCall(MatColoringCreate(B, &mc)); 6058 PetscCall(MatColoringSetDistance(mc, 2)); 6059 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 6060 PetscCall(MatColoringSetFromOptions(mc)); 6061 PetscCall(MatColoringApply(mc, &iscoloring)); 6062 PetscCall(MatColoringDestroy(&mc)); 6063 /* Replace the old coloring with the new one */ 6064 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 6065 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 6066 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 6067 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 6068 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 6069 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 6070 PetscCall(ISColoringDestroy(&iscoloring)); 6071 PetscFunctionReturn(PETSC_SUCCESS); 6072 } 6073