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 prototpye 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()`, `TSSetPotsStep()` 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 Fortran Notes: 4324 The user should pass in a string 'prefix' of 4325 sufficient length to hold the prefix. 4326 4327 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4328 @*/ 4329 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4330 { 4331 PetscFunctionBegin; 4332 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4333 PetscAssertPointer(prefix, 2); 4334 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } 4337 4338 /*@C 4339 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4340 4341 Not Collective, but parallel objects are returned if ts is parallel 4342 4343 Input Parameter: 4344 . ts - The `TS` context obtained from `TSCreate()` 4345 4346 Output Parameters: 4347 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4348 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4349 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4350 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4351 4352 Level: intermediate 4353 4354 Note: 4355 You can pass in `NULL` for any return argument you do not need. 4356 4357 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4358 4359 @*/ 4360 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx) 4361 { 4362 DM dm; 4363 4364 PetscFunctionBegin; 4365 if (Amat || Pmat) { 4366 SNES snes; 4367 PetscCall(TSGetSNES(ts, &snes)); 4368 PetscCall(SNESSetUpMatrices(snes)); 4369 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4370 } 4371 PetscCall(TSGetDM(ts, &dm)); 4372 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4373 PetscFunctionReturn(PETSC_SUCCESS); 4374 } 4375 4376 /*@C 4377 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4378 4379 Not Collective, but parallel objects are returned if ts is parallel 4380 4381 Input Parameter: 4382 . ts - The `TS` context obtained from `TSCreate()` 4383 4384 Output Parameters: 4385 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4386 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4387 . f - The function to compute the matrices 4388 - ctx - User-defined context for Jacobian evaluation routine 4389 4390 Level: advanced 4391 4392 Note: 4393 You can pass in `NULL` for any return argument you do not need. 4394 4395 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4396 @*/ 4397 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx) 4398 { 4399 DM dm; 4400 4401 PetscFunctionBegin; 4402 if (Amat || Pmat) { 4403 SNES snes; 4404 PetscCall(TSGetSNES(ts, &snes)); 4405 PetscCall(SNESSetUpMatrices(snes)); 4406 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4407 } 4408 PetscCall(TSGetDM(ts, &dm)); 4409 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4410 PetscFunctionReturn(PETSC_SUCCESS); 4411 } 4412 4413 #include <petsc/private/dmimpl.h> 4414 /*@ 4415 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4416 4417 Logically Collective 4418 4419 Input Parameters: 4420 + ts - the `TS` integrator object 4421 - dm - the dm, cannot be `NULL` 4422 4423 Level: intermediate 4424 4425 Notes: 4426 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4427 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4428 different problems using the same function space. 4429 4430 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4431 @*/ 4432 PetscErrorCode TSSetDM(TS ts, DM dm) 4433 { 4434 SNES snes; 4435 DMTS tsdm; 4436 4437 PetscFunctionBegin; 4438 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4439 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4440 PetscCall(PetscObjectReference((PetscObject)dm)); 4441 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4442 if (ts->dm->dmts && !dm->dmts) { 4443 PetscCall(DMCopyDMTS(ts->dm, dm)); 4444 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4445 /* Grant write privileges to the replacement DM */ 4446 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4447 } 4448 PetscCall(DMDestroy(&ts->dm)); 4449 } 4450 ts->dm = dm; 4451 4452 PetscCall(TSGetSNES(ts, &snes)); 4453 PetscCall(SNESSetDM(snes, dm)); 4454 PetscFunctionReturn(PETSC_SUCCESS); 4455 } 4456 4457 /*@ 4458 TSGetDM - Gets the `DM` that may be used by some preconditioners 4459 4460 Not Collective 4461 4462 Input Parameter: 4463 . ts - the `TS` 4464 4465 Output Parameter: 4466 . dm - the `DM` 4467 4468 Level: intermediate 4469 4470 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4471 @*/ 4472 PetscErrorCode TSGetDM(TS ts, DM *dm) 4473 { 4474 PetscFunctionBegin; 4475 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4476 if (!ts->dm) { 4477 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4478 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4479 } 4480 *dm = ts->dm; 4481 PetscFunctionReturn(PETSC_SUCCESS); 4482 } 4483 4484 /*@ 4485 SNESTSFormFunction - Function to evaluate nonlinear residual 4486 4487 Logically Collective 4488 4489 Input Parameters: 4490 + snes - nonlinear solver 4491 . U - the current state at which to evaluate the residual 4492 - ctx - user context, must be a TS 4493 4494 Output Parameter: 4495 . F - the nonlinear residual 4496 4497 Level: advanced 4498 4499 Note: 4500 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4501 It is most frequently passed to `MatFDColoringSetFunction()`. 4502 4503 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4504 @*/ 4505 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4506 { 4507 TS ts = (TS)ctx; 4508 4509 PetscFunctionBegin; 4510 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4511 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4512 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4513 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4514 PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name); 4515 PetscCall((*ts->ops->snesfunction)(snes, U, F, ts)); 4516 PetscFunctionReturn(PETSC_SUCCESS); 4517 } 4518 4519 /*@ 4520 SNESTSFormJacobian - Function to evaluate the Jacobian 4521 4522 Collective 4523 4524 Input Parameters: 4525 + snes - nonlinear solver 4526 . U - the current state at which to evaluate the residual 4527 - ctx - user context, must be a `TS` 4528 4529 Output Parameters: 4530 + A - the Jacobian 4531 - B - the preconditioning matrix (may be the same as A) 4532 4533 Level: developer 4534 4535 Note: 4536 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4537 4538 .seealso: [](ch_ts), `SNESSetJacobian()` 4539 @*/ 4540 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4541 { 4542 TS ts = (TS)ctx; 4543 4544 PetscFunctionBegin; 4545 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4546 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4547 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4548 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4549 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4550 PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name); 4551 PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts)); 4552 PetscFunctionReturn(PETSC_SUCCESS); 4553 } 4554 4555 /*@C 4556 TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only 4557 4558 Collective 4559 4560 Input Parameters: 4561 + ts - time stepping context 4562 . t - time at which to evaluate 4563 . U - state at which to evaluate 4564 - ctx - context 4565 4566 Output Parameter: 4567 . F - right-hand side 4568 4569 Level: intermediate 4570 4571 Note: 4572 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems. 4573 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4574 4575 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4576 @*/ 4577 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4578 { 4579 Mat Arhs, Brhs; 4580 4581 PetscFunctionBegin; 4582 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4583 /* undo the damage caused by shifting */ 4584 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4585 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4586 PetscCall(MatMult(Arhs, U, F)); 4587 PetscFunctionReturn(PETSC_SUCCESS); 4588 } 4589 4590 /*@C 4591 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4592 4593 Collective 4594 4595 Input Parameters: 4596 + ts - time stepping context 4597 . t - time at which to evaluate 4598 . U - state at which to evaluate 4599 - ctx - context 4600 4601 Output Parameters: 4602 + A - pointer to operator 4603 - B - pointer to preconditioning matrix 4604 4605 Level: intermediate 4606 4607 Note: 4608 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4609 4610 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4611 @*/ 4612 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4613 { 4614 PetscFunctionBegin; 4615 PetscFunctionReturn(PETSC_SUCCESS); 4616 } 4617 4618 /*@C 4619 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4620 4621 Collective 4622 4623 Input Parameters: 4624 + ts - time stepping context 4625 . t - time at which to evaluate 4626 . U - state at which to evaluate 4627 . Udot - time derivative of state vector 4628 - ctx - context 4629 4630 Output Parameter: 4631 . F - left hand side 4632 4633 Level: intermediate 4634 4635 Notes: 4636 The assumption here is that the left hand side is of the form A*Udot (and not A*Udot + B*U). For other cases, the 4637 user is required to write their own `TSComputeIFunction()`. 4638 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4639 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4640 4641 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4642 4643 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4644 @*/ 4645 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4646 { 4647 Mat A, B; 4648 4649 PetscFunctionBegin; 4650 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4651 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4652 PetscCall(MatMult(A, Udot, F)); 4653 PetscFunctionReturn(PETSC_SUCCESS); 4654 } 4655 4656 /*@C 4657 TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE 4658 4659 Collective 4660 4661 Input Parameters: 4662 + ts - time stepping context 4663 . t - time at which to evaluate 4664 . U - state at which to evaluate 4665 . Udot - time derivative of state vector 4666 . shift - shift to apply 4667 - ctx - context 4668 4669 Output Parameters: 4670 + A - pointer to operator 4671 - B - pointer to matrix from which the preconditioner is built (often `A`) 4672 4673 Level: advanced 4674 4675 Notes: 4676 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4677 4678 It is only appropriate for problems of the form 4679 4680 $$ 4681 M \dot{U} = F(U,t) 4682 $$ 4683 4684 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4685 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4686 an implicit operator of the form 4687 4688 $$ 4689 shift*M + J 4690 $$ 4691 4692 where J is the Jacobian of -F(U). Support may be added in a future version of PETSc, but for now, the user must store 4693 a copy of M or reassemble it when requested. 4694 4695 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4696 @*/ 4697 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4698 { 4699 PetscFunctionBegin; 4700 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4701 ts->ijacobian.shift = shift; 4702 PetscFunctionReturn(PETSC_SUCCESS); 4703 } 4704 4705 /*@ 4706 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4707 4708 Not Collective 4709 4710 Input Parameter: 4711 . ts - the `TS` context 4712 4713 Output Parameter: 4714 . equation_type - see `TSEquationType` 4715 4716 Level: beginner 4717 4718 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4719 @*/ 4720 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4721 { 4722 PetscFunctionBegin; 4723 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4724 PetscAssertPointer(equation_type, 2); 4725 *equation_type = ts->equation_type; 4726 PetscFunctionReturn(PETSC_SUCCESS); 4727 } 4728 4729 /*@ 4730 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4731 4732 Not Collective 4733 4734 Input Parameters: 4735 + ts - the `TS` context 4736 - equation_type - see `TSEquationType` 4737 4738 Level: advanced 4739 4740 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4741 @*/ 4742 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4743 { 4744 PetscFunctionBegin; 4745 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4746 ts->equation_type = equation_type; 4747 PetscFunctionReturn(PETSC_SUCCESS); 4748 } 4749 4750 /*@ 4751 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4752 4753 Not Collective 4754 4755 Input Parameter: 4756 . ts - the `TS` context 4757 4758 Output Parameter: 4759 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4760 manual pages for the individual convergence tests for complete lists 4761 4762 Level: beginner 4763 4764 Note: 4765 Can only be called after the call to `TSSolve()` is complete. 4766 4767 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4768 @*/ 4769 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4770 { 4771 PetscFunctionBegin; 4772 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4773 PetscAssertPointer(reason, 2); 4774 *reason = ts->reason; 4775 PetscFunctionReturn(PETSC_SUCCESS); 4776 } 4777 4778 /*@ 4779 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4780 4781 Logically Collective; reason must contain common value 4782 4783 Input Parameters: 4784 + ts - the `TS` context 4785 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4786 manual pages for the individual convergence tests for complete lists 4787 4788 Level: advanced 4789 4790 Note: 4791 Can only be called while `TSSolve()` is active. 4792 4793 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4794 @*/ 4795 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4796 { 4797 PetscFunctionBegin; 4798 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4799 ts->reason = reason; 4800 PetscFunctionReturn(PETSC_SUCCESS); 4801 } 4802 4803 /*@ 4804 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4805 4806 Not Collective 4807 4808 Input Parameter: 4809 . ts - the `TS` context 4810 4811 Output Parameter: 4812 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4813 4814 Level: beginner 4815 4816 Note: 4817 Can only be called after the call to `TSSolve()` is complete. 4818 4819 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4820 @*/ 4821 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4822 { 4823 PetscFunctionBegin; 4824 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4825 PetscAssertPointer(ftime, 2); 4826 *ftime = ts->solvetime; 4827 PetscFunctionReturn(PETSC_SUCCESS); 4828 } 4829 4830 /*@ 4831 TSGetSNESIterations - Gets the total number of nonlinear iterations 4832 used by the time integrator. 4833 4834 Not Collective 4835 4836 Input Parameter: 4837 . ts - `TS` context 4838 4839 Output Parameter: 4840 . nits - number of nonlinear iterations 4841 4842 Level: intermediate 4843 4844 Note: 4845 This counter is reset to zero for each successive call to `TSSolve()`. 4846 4847 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4848 @*/ 4849 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4850 { 4851 PetscFunctionBegin; 4852 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4853 PetscAssertPointer(nits, 2); 4854 *nits = ts->snes_its; 4855 PetscFunctionReturn(PETSC_SUCCESS); 4856 } 4857 4858 /*@ 4859 TSGetKSPIterations - Gets the total number of linear iterations 4860 used by the time integrator. 4861 4862 Not Collective 4863 4864 Input Parameter: 4865 . ts - `TS` context 4866 4867 Output Parameter: 4868 . lits - number of linear iterations 4869 4870 Level: intermediate 4871 4872 Note: 4873 This counter is reset to zero for each successive call to `TSSolve()`. 4874 4875 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4876 @*/ 4877 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4878 { 4879 PetscFunctionBegin; 4880 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4881 PetscAssertPointer(lits, 2); 4882 *lits = ts->ksp_its; 4883 PetscFunctionReturn(PETSC_SUCCESS); 4884 } 4885 4886 /*@ 4887 TSGetStepRejections - Gets the total number of rejected steps. 4888 4889 Not Collective 4890 4891 Input Parameter: 4892 . ts - `TS` context 4893 4894 Output Parameter: 4895 . rejects - number of steps rejected 4896 4897 Level: intermediate 4898 4899 Note: 4900 This counter is reset to zero for each successive call to `TSSolve()`. 4901 4902 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4903 @*/ 4904 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4905 { 4906 PetscFunctionBegin; 4907 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4908 PetscAssertPointer(rejects, 2); 4909 *rejects = ts->reject; 4910 PetscFunctionReturn(PETSC_SUCCESS); 4911 } 4912 4913 /*@ 4914 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4915 4916 Not Collective 4917 4918 Input Parameter: 4919 . ts - `TS` context 4920 4921 Output Parameter: 4922 . fails - number of failed nonlinear solves 4923 4924 Level: intermediate 4925 4926 Note: 4927 This counter is reset to zero for each successive call to `TSSolve()`. 4928 4929 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4930 @*/ 4931 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4932 { 4933 PetscFunctionBegin; 4934 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4935 PetscAssertPointer(fails, 2); 4936 *fails = ts->num_snes_failures; 4937 PetscFunctionReturn(PETSC_SUCCESS); 4938 } 4939 4940 /*@ 4941 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4942 4943 Not Collective 4944 4945 Input Parameters: 4946 + ts - `TS` context 4947 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited 4948 4949 Options Database Key: 4950 . -ts_max_reject - Maximum number of step rejections before a step fails 4951 4952 Level: intermediate 4953 4954 Developer Note: 4955 The options database name is incorrect. 4956 4957 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4958 @*/ 4959 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4960 { 4961 PetscFunctionBegin; 4962 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4963 if (rejects == PETSC_UNLIMITED || rejects == -1) { 4964 ts->max_reject = PETSC_UNLIMITED; 4965 } else { 4966 PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections"); 4967 ts->max_reject = rejects; 4968 } 4969 PetscFunctionReturn(PETSC_SUCCESS); 4970 } 4971 4972 /*@ 4973 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4974 4975 Not Collective 4976 4977 Input Parameters: 4978 + ts - `TS` context 4979 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures. 4980 4981 Options Database Key: 4982 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4983 4984 Level: intermediate 4985 4986 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4987 @*/ 4988 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4989 { 4990 PetscFunctionBegin; 4991 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4992 if (fails == PETSC_UNLIMITED || fails == -1) { 4993 ts->max_snes_failures = PETSC_UNLIMITED; 4994 } else { 4995 PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 4996 ts->max_snes_failures = fails; 4997 } 4998 PetscFunctionReturn(PETSC_SUCCESS); 4999 } 5000 5001 /*@ 5002 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 5003 5004 Not Collective 5005 5006 Input Parameters: 5007 + ts - `TS` context 5008 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 5009 5010 Options Database Key: 5011 . -ts_error_if_step_fails - Error if no step succeeds 5012 5013 Level: intermediate 5014 5015 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()` 5016 @*/ 5017 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 5018 { 5019 PetscFunctionBegin; 5020 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5021 ts->errorifstepfailed = err; 5022 PetscFunctionReturn(PETSC_SUCCESS); 5023 } 5024 5025 /*@ 5026 TSGetAdapt - Get the adaptive controller context for the current method 5027 5028 Collective if controller has not yet been created 5029 5030 Input Parameter: 5031 . ts - time stepping context 5032 5033 Output Parameter: 5034 . adapt - adaptive controller 5035 5036 Level: intermediate 5037 5038 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 5039 @*/ 5040 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 5041 { 5042 PetscFunctionBegin; 5043 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5044 PetscAssertPointer(adapt, 2); 5045 if (!ts->adapt) { 5046 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 5047 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 5048 } 5049 *adapt = ts->adapt; 5050 PetscFunctionReturn(PETSC_SUCCESS); 5051 } 5052 5053 /*@ 5054 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 5055 5056 Logically Collective 5057 5058 Input Parameters: 5059 + ts - time integration context 5060 . atol - scalar absolute tolerances 5061 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present 5062 . rtol - scalar relative tolerances 5063 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present 5064 5065 Options Database Keys: 5066 + -ts_rtol <rtol> - relative tolerance for local truncation error 5067 - -ts_atol <atol> - Absolute tolerance for local truncation error 5068 5069 Level: beginner 5070 5071 Notes: 5072 `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value 5073 or the default value from when the object's type was set. 5074 5075 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5076 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5077 computed only for the differential or the algebraic part then this can be done using the vector of 5078 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5079 differential part and infinity for the algebraic part, the LTE calculation will include only the 5080 differential variables. 5081 5082 Fortran Note: 5083 Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`. 5084 5085 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5086 @*/ 5087 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5088 { 5089 PetscFunctionBegin; 5090 if (atol == (PetscReal)PETSC_DETERMINE) { 5091 ts->atol = ts->default_atol; 5092 } else if (atol != (PetscReal)PETSC_CURRENT) { 5093 PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol); 5094 ts->atol = atol; 5095 } 5096 5097 if (vatol) { 5098 PetscCall(PetscObjectReference((PetscObject)vatol)); 5099 PetscCall(VecDestroy(&ts->vatol)); 5100 ts->vatol = vatol; 5101 } 5102 5103 if (rtol == (PetscReal)PETSC_DETERMINE) { 5104 ts->rtol = ts->default_rtol; 5105 } else if (rtol != (PetscReal)PETSC_CURRENT) { 5106 PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol); 5107 ts->rtol = rtol; 5108 } 5109 5110 if (vrtol) { 5111 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5112 PetscCall(VecDestroy(&ts->vrtol)); 5113 ts->vrtol = vrtol; 5114 } 5115 PetscFunctionReturn(PETSC_SUCCESS); 5116 } 5117 5118 /*@ 5119 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5120 5121 Logically Collective 5122 5123 Input Parameter: 5124 . ts - time integration context 5125 5126 Output Parameters: 5127 + atol - scalar absolute tolerances, `NULL` to ignore 5128 . vatol - vector of absolute tolerances, `NULL` to ignore 5129 . rtol - scalar relative tolerances, `NULL` to ignore 5130 - vrtol - vector of relative tolerances, `NULL` to ignore 5131 5132 Level: beginner 5133 5134 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5135 @*/ 5136 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5137 { 5138 PetscFunctionBegin; 5139 if (atol) *atol = ts->atol; 5140 if (vatol) *vatol = ts->vatol; 5141 if (rtol) *rtol = ts->rtol; 5142 if (vrtol) *vrtol = ts->vrtol; 5143 PetscFunctionReturn(PETSC_SUCCESS); 5144 } 5145 5146 /*@ 5147 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5148 5149 Collective 5150 5151 Input Parameters: 5152 + ts - time stepping context 5153 . U - state vector, usually ts->vec_sol 5154 . Y - state vector to be compared to U 5155 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5156 5157 Output Parameters: 5158 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5159 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5160 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5161 5162 Options Database Key: 5163 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5164 5165 Level: developer 5166 5167 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5168 @*/ 5169 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5170 { 5171 PetscInt norma_loc, norm_loc, normr_loc; 5172 5173 PetscFunctionBegin; 5174 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5175 PetscCall(VecErrorWeightedNorms(U, Y, NULL, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc)); 5176 if (wnormtype == NORM_2) { 5177 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5178 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5179 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5180 } 5181 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5182 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5183 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5184 PetscFunctionReturn(PETSC_SUCCESS); 5185 } 5186 5187 /*@ 5188 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5189 5190 Collective 5191 5192 Input Parameters: 5193 + ts - time stepping context 5194 . E - error vector 5195 . U - state vector, usually ts->vec_sol 5196 . Y - state vector, previous time step 5197 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5198 5199 Output Parameters: 5200 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5201 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5202 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5203 5204 Options Database Key: 5205 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5206 5207 Level: developer 5208 5209 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5210 @*/ 5211 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5212 { 5213 PetscInt norma_loc, norm_loc, normr_loc; 5214 5215 PetscFunctionBegin; 5216 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5217 PetscCall(VecErrorWeightedNorms(U, Y, E, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc)); 5218 if (wnormtype == NORM_2) { 5219 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5220 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5221 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5222 } 5223 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5224 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5225 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5226 PetscFunctionReturn(PETSC_SUCCESS); 5227 } 5228 5229 /*@ 5230 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5231 5232 Logically Collective 5233 5234 Input Parameters: 5235 + ts - time stepping context 5236 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5237 5238 Note: 5239 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5240 5241 Level: intermediate 5242 5243 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5244 @*/ 5245 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5246 { 5247 PetscFunctionBegin; 5248 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5249 ts->cfltime_local = cfltime; 5250 ts->cfltime = -1.; 5251 PetscFunctionReturn(PETSC_SUCCESS); 5252 } 5253 5254 /*@ 5255 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5256 5257 Collective 5258 5259 Input Parameter: 5260 . ts - time stepping context 5261 5262 Output Parameter: 5263 . cfltime - maximum stable time step for forward Euler 5264 5265 Level: advanced 5266 5267 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5268 @*/ 5269 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5270 { 5271 PetscFunctionBegin; 5272 if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5273 *cfltime = ts->cfltime; 5274 PetscFunctionReturn(PETSC_SUCCESS); 5275 } 5276 5277 /*@ 5278 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5279 5280 Input Parameters: 5281 + ts - the `TS` context. 5282 . xl - lower bound. 5283 - xu - upper bound. 5284 5285 Level: advanced 5286 5287 Note: 5288 If this routine is not called then the lower and upper bounds are set to 5289 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5290 5291 .seealso: [](ch_ts), `TS` 5292 @*/ 5293 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5294 { 5295 SNES snes; 5296 5297 PetscFunctionBegin; 5298 PetscCall(TSGetSNES(ts, &snes)); 5299 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5300 PetscFunctionReturn(PETSC_SUCCESS); 5301 } 5302 5303 /*@ 5304 TSComputeLinearStability - computes the linear stability function at a point 5305 5306 Collective 5307 5308 Input Parameters: 5309 + ts - the `TS` context 5310 . xr - real part of input argument 5311 - xi - imaginary part of input argument 5312 5313 Output Parameters: 5314 + yr - real part of function value 5315 - yi - imaginary part of function value 5316 5317 Level: developer 5318 5319 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5320 @*/ 5321 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5322 { 5323 PetscFunctionBegin; 5324 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5325 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 /*@ 5330 TSRestartStep - Flags the solver to restart the next step 5331 5332 Collective 5333 5334 Input Parameter: 5335 . ts - the `TS` context obtained from `TSCreate()` 5336 5337 Level: advanced 5338 5339 Notes: 5340 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5341 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5342 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5343 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5344 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5345 discontinuous source terms). 5346 5347 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5348 @*/ 5349 PetscErrorCode TSRestartStep(TS ts) 5350 { 5351 PetscFunctionBegin; 5352 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5353 ts->steprestart = PETSC_TRUE; 5354 PetscFunctionReturn(PETSC_SUCCESS); 5355 } 5356 5357 /*@ 5358 TSRollBack - Rolls back one time step 5359 5360 Collective 5361 5362 Input Parameter: 5363 . ts - the `TS` context obtained from `TSCreate()` 5364 5365 Level: advanced 5366 5367 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5368 @*/ 5369 PetscErrorCode TSRollBack(TS ts) 5370 { 5371 PetscFunctionBegin; 5372 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5373 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5374 PetscTryTypeMethod(ts, rollback); 5375 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 5376 ts->time_step = ts->ptime - ts->ptime_prev; 5377 ts->ptime = ts->ptime_prev; 5378 ts->ptime_prev = ts->ptime_prev_rollback; 5379 ts->steps--; 5380 ts->steprollback = PETSC_TRUE; 5381 PetscFunctionReturn(PETSC_SUCCESS); 5382 } 5383 5384 /*@ 5385 TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step 5386 5387 Not collective 5388 5389 Input Parameter: 5390 . ts - the `TS` context obtained from `TSCreate()` 5391 5392 Output Parameter: 5393 . flg - the rollback flag 5394 5395 Level: advanced 5396 5397 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()` 5398 @*/ 5399 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg) 5400 { 5401 PetscFunctionBegin; 5402 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5403 PetscAssertPointer(flg, 2); 5404 *flg = ts->steprollback; 5405 PetscFunctionReturn(PETSC_SUCCESS); 5406 } 5407 5408 /*@ 5409 TSGetStepResize - Get the internal flag indicating if the current step is after a resize. 5410 5411 Not collective 5412 5413 Input Parameter: 5414 . ts - the `TS` context obtained from `TSCreate()` 5415 5416 Output Parameter: 5417 . flg - the resize flag 5418 5419 Level: advanced 5420 5421 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()` 5422 @*/ 5423 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg) 5424 { 5425 PetscFunctionBegin; 5426 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5427 PetscAssertPointer(flg, 2); 5428 *flg = ts->stepresize; 5429 PetscFunctionReturn(PETSC_SUCCESS); 5430 } 5431 5432 /*@ 5433 TSGetStages - Get the number of stages and stage values 5434 5435 Input Parameter: 5436 . ts - the `TS` context obtained from `TSCreate()` 5437 5438 Output Parameters: 5439 + ns - the number of stages 5440 - Y - the current stage vectors 5441 5442 Level: advanced 5443 5444 Note: 5445 Both `ns` and `Y` can be `NULL`. 5446 5447 .seealso: [](ch_ts), `TS`, `TSCreate()` 5448 @*/ 5449 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5450 { 5451 PetscFunctionBegin; 5452 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5453 if (ns) PetscAssertPointer(ns, 2); 5454 if (Y) PetscAssertPointer(Y, 3); 5455 if (!ts->ops->getstages) { 5456 if (ns) *ns = 0; 5457 if (Y) *Y = NULL; 5458 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5459 PetscFunctionReturn(PETSC_SUCCESS); 5460 } 5461 5462 /*@C 5463 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5464 5465 Collective 5466 5467 Input Parameters: 5468 + ts - the `TS` context 5469 . t - current timestep 5470 . U - state vector 5471 . Udot - time derivative of state vector 5472 . shift - shift to apply, see note below 5473 - ctx - an optional user context 5474 5475 Output Parameters: 5476 + J - Jacobian matrix (not altered in this routine) 5477 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5478 5479 Level: intermediate 5480 5481 Notes: 5482 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5483 5484 dF/dU + shift*dF/dUdot 5485 5486 Most users should not need to explicitly call this routine, as it 5487 is used internally within the nonlinear solvers. 5488 5489 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5490 routine, then it will try to get the coloring from the matrix. This requires that the 5491 matrix have nonzero entries precomputed. 5492 5493 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5494 @*/ 5495 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5496 { 5497 SNES snes; 5498 MatFDColoring color; 5499 PetscBool hascolor, matcolor = PETSC_FALSE; 5500 5501 PetscFunctionBegin; 5502 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5503 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5504 if (!color) { 5505 DM dm; 5506 ISColoring iscoloring; 5507 5508 PetscCall(TSGetDM(ts, &dm)); 5509 PetscCall(DMHasColoring(dm, &hascolor)); 5510 if (hascolor && !matcolor) { 5511 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5512 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5513 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5514 PetscCall(MatFDColoringSetFromOptions(color)); 5515 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5516 PetscCall(ISColoringDestroy(&iscoloring)); 5517 } else { 5518 MatColoring mc; 5519 5520 PetscCall(MatColoringCreate(B, &mc)); 5521 PetscCall(MatColoringSetDistance(mc, 2)); 5522 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5523 PetscCall(MatColoringSetFromOptions(mc)); 5524 PetscCall(MatColoringApply(mc, &iscoloring)); 5525 PetscCall(MatColoringDestroy(&mc)); 5526 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5527 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5528 PetscCall(MatFDColoringSetFromOptions(color)); 5529 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5530 PetscCall(ISColoringDestroy(&iscoloring)); 5531 } 5532 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5533 PetscCall(PetscObjectDereference((PetscObject)color)); 5534 } 5535 PetscCall(TSGetSNES(ts, &snes)); 5536 PetscCall(MatFDColoringApply(B, color, U, snes)); 5537 if (J != B) { 5538 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5539 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5540 } 5541 PetscFunctionReturn(PETSC_SUCCESS); 5542 } 5543 5544 /*@C 5545 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5546 5547 Input Parameters: 5548 + ts - the `TS` context 5549 - func - function called within `TSFunctionDomainError()` 5550 5551 Calling sequence of `func`: 5552 + ts - the `TS` context 5553 . time - the current time (of the stage) 5554 . state - the state to check if it is valid 5555 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable 5556 5557 Level: intermediate 5558 5559 Notes: 5560 If an implicit ODE solver is being used then, in addition to providing this routine, the 5561 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5562 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5563 Use `TSGetSNES()` to obtain the `SNES` object 5564 5565 Developer Notes: 5566 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5567 since one takes a function pointer and the other does not. 5568 5569 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5570 @*/ 5571 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept)) 5572 { 5573 PetscFunctionBegin; 5574 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5575 ts->functiondomainerror = func; 5576 PetscFunctionReturn(PETSC_SUCCESS); 5577 } 5578 5579 /*@ 5580 TSFunctionDomainError - Checks if the current state is valid 5581 5582 Input Parameters: 5583 + ts - the `TS` context 5584 . stagetime - time of the simulation 5585 - Y - state vector to check. 5586 5587 Output Parameter: 5588 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5589 5590 Level: developer 5591 5592 Note: 5593 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5594 to check if the current state is valid. 5595 5596 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5597 @*/ 5598 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5599 { 5600 PetscFunctionBegin; 5601 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5602 *accept = PETSC_TRUE; 5603 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5604 PetscFunctionReturn(PETSC_SUCCESS); 5605 } 5606 5607 /*@ 5608 TSClone - This function clones a time step `TS` object. 5609 5610 Collective 5611 5612 Input Parameter: 5613 . tsin - The input `TS` 5614 5615 Output Parameter: 5616 . tsout - The output `TS` (cloned) 5617 5618 Level: developer 5619 5620 Notes: 5621 This function is used to create a clone of a `TS` object. It is used in `TSARKIMEX` for initializing the slope for first stage explicit methods. 5622 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5623 5624 When using `TSDestroy()` on a clone the user has to first reset the correct `TS` reference in the embedded `SNES` object: e.g., by running 5625 .vb 5626 SNES snes_dup = NULL; 5627 TSGetSNES(ts,&snes_dup); 5628 TSSetSNES(ts,snes_dup); 5629 .ve 5630 5631 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5632 @*/ 5633 PetscErrorCode TSClone(TS tsin, TS *tsout) 5634 { 5635 TS t; 5636 SNES snes_start; 5637 DM dm; 5638 TSType type; 5639 5640 PetscFunctionBegin; 5641 PetscAssertPointer(tsin, 1); 5642 *tsout = NULL; 5643 5644 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5645 5646 /* General TS description */ 5647 t->numbermonitors = 0; 5648 t->monitorFrequency = 1; 5649 t->setupcalled = 0; 5650 t->ksp_its = 0; 5651 t->snes_its = 0; 5652 t->nwork = 0; 5653 t->rhsjacobian.time = PETSC_MIN_REAL; 5654 t->rhsjacobian.scale = 1.; 5655 t->ijacobian.shift = 1.; 5656 5657 PetscCall(TSGetSNES(tsin, &snes_start)); 5658 PetscCall(TSSetSNES(t, snes_start)); 5659 5660 PetscCall(TSGetDM(tsin, &dm)); 5661 PetscCall(TSSetDM(t, dm)); 5662 5663 t->adapt = tsin->adapt; 5664 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5665 5666 t->trajectory = tsin->trajectory; 5667 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5668 5669 t->event = tsin->event; 5670 if (t->event) t->event->refct++; 5671 5672 t->problem_type = tsin->problem_type; 5673 t->ptime = tsin->ptime; 5674 t->ptime_prev = tsin->ptime_prev; 5675 t->time_step = tsin->time_step; 5676 t->max_time = tsin->max_time; 5677 t->steps = tsin->steps; 5678 t->max_steps = tsin->max_steps; 5679 t->equation_type = tsin->equation_type; 5680 t->atol = tsin->atol; 5681 t->rtol = tsin->rtol; 5682 t->max_snes_failures = tsin->max_snes_failures; 5683 t->max_reject = tsin->max_reject; 5684 t->errorifstepfailed = tsin->errorifstepfailed; 5685 5686 PetscCall(TSGetType(tsin, &type)); 5687 PetscCall(TSSetType(t, type)); 5688 5689 t->vec_sol = NULL; 5690 5691 t->cfltime = tsin->cfltime; 5692 t->cfltime_local = tsin->cfltime_local; 5693 t->exact_final_time = tsin->exact_final_time; 5694 5695 t->ops[0] = tsin->ops[0]; 5696 5697 if (((PetscObject)tsin)->fortran_func_pointers) { 5698 PetscInt i; 5699 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5700 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5701 } 5702 *tsout = t; 5703 PetscFunctionReturn(PETSC_SUCCESS); 5704 } 5705 5706 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5707 { 5708 TS ts = (TS)ctx; 5709 5710 PetscFunctionBegin; 5711 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5712 PetscFunctionReturn(PETSC_SUCCESS); 5713 } 5714 5715 /*@ 5716 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5717 5718 Logically Collective 5719 5720 Input Parameter: 5721 . ts - the time stepping routine 5722 5723 Output Parameter: 5724 . flg - `PETSC_TRUE` if the multiply is likely correct 5725 5726 Options Database Key: 5727 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5728 5729 Level: advanced 5730 5731 Note: 5732 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5733 5734 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5735 @*/ 5736 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5737 { 5738 Mat J, B; 5739 TSRHSJacobianFn *func; 5740 void *ctx; 5741 5742 PetscFunctionBegin; 5743 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5744 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5745 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5746 PetscFunctionReturn(PETSC_SUCCESS); 5747 } 5748 5749 /*@ 5750 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5751 5752 Logically Collective 5753 5754 Input Parameter: 5755 . ts - the time stepping routine 5756 5757 Output Parameter: 5758 . flg - `PETSC_TRUE` if the multiply is likely correct 5759 5760 Options Database Key: 5761 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5762 5763 Level: advanced 5764 5765 Notes: 5766 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5767 5768 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5769 @*/ 5770 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5771 { 5772 Mat J, B; 5773 void *ctx; 5774 TSRHSJacobianFn *func; 5775 5776 PetscFunctionBegin; 5777 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5778 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5779 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5780 PetscFunctionReturn(PETSC_SUCCESS); 5781 } 5782 5783 /*@ 5784 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5785 5786 Logically Collective 5787 5788 Input Parameters: 5789 + ts - timestepping context 5790 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5791 5792 Options Database Key: 5793 . -ts_use_splitrhsfunction - <true,false> 5794 5795 Level: intermediate 5796 5797 Note: 5798 This is only for multirate methods 5799 5800 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5801 @*/ 5802 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5803 { 5804 PetscFunctionBegin; 5805 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5806 ts->use_splitrhsfunction = use_splitrhsfunction; 5807 PetscFunctionReturn(PETSC_SUCCESS); 5808 } 5809 5810 /*@ 5811 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5812 5813 Not Collective 5814 5815 Input Parameter: 5816 . ts - timestepping context 5817 5818 Output Parameter: 5819 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5820 5821 Level: intermediate 5822 5823 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5824 @*/ 5825 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5826 { 5827 PetscFunctionBegin; 5828 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5829 *use_splitrhsfunction = ts->use_splitrhsfunction; 5830 PetscFunctionReturn(PETSC_SUCCESS); 5831 } 5832 5833 /*@ 5834 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5835 5836 Logically Collective 5837 5838 Input Parameters: 5839 + ts - the time-stepper 5840 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5841 5842 Level: intermediate 5843 5844 Note: 5845 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5846 5847 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5848 @*/ 5849 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5850 { 5851 PetscFunctionBegin; 5852 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5853 ts->axpy_pattern = str; 5854 PetscFunctionReturn(PETSC_SUCCESS); 5855 } 5856 5857 /*@ 5858 TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested 5859 5860 Collective 5861 5862 Input Parameters: 5863 + ts - the time-stepper 5864 . n - number of the time points 5865 - time_points - array of the time points 5866 5867 Options Database Key: 5868 . -ts_eval_times <t0,...tn> - Sets the evaluation times 5869 5870 Level: intermediate 5871 5872 Notes: 5873 The elements in `time_points` must be all increasing. They correspond to the intermediate points for time integration. 5874 5875 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5876 5877 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may 5878 pressure the memory system when using a large number of time points. 5879 5880 .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()` 5881 @*/ 5882 PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal *time_points) 5883 { 5884 PetscBool is_sorted; 5885 5886 PetscFunctionBegin; 5887 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5888 if (ts->eval_times && n != ts->eval_times->num_time_points) { 5889 PetscCall(PetscFree(ts->eval_times->time_points)); 5890 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 5891 PetscCall(PetscMalloc1(n, &ts->eval_times->time_points)); 5892 } 5893 if (!ts->eval_times) { 5894 TSEvaluationTimes eval_times; 5895 PetscCall(PetscNew(&eval_times)); 5896 PetscCall(PetscMalloc1(n, &eval_times->time_points)); 5897 eval_times->reltol = 1e-6; 5898 eval_times->abstol = 10 * PETSC_MACHINE_EPSILON; 5899 eval_times->worktol = 0; 5900 ts->eval_times = eval_times; 5901 } 5902 ts->eval_times->num_time_points = n; 5903 PetscCall(PetscSortedReal(n, time_points, &is_sorted)); 5904 PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted"); 5905 PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n)); 5906 PetscFunctionReturn(PETSC_SUCCESS); 5907 } 5908 5909 /*@C 5910 TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()` 5911 5912 Not Collective 5913 5914 Input Parameter: 5915 . ts - the time-stepper 5916 5917 Output Parameters: 5918 + n - number of the time points 5919 - time_points - array of the time points 5920 5921 Level: beginner 5922 5923 Note: 5924 The values obtained are valid until the `TS` object is destroyed. 5925 5926 Both `n` and `time_points` can be `NULL`. 5927 5928 Also used to see time points set by `TSSetTimeSpan()`. 5929 5930 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()` 5931 @*/ 5932 PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[]) 5933 { 5934 PetscFunctionBegin; 5935 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5936 if (n) PetscAssertPointer(n, 2); 5937 if (time_points) PetscAssertPointer(time_points, 3); 5938 if (!ts->eval_times) { 5939 if (n) *n = 0; 5940 if (time_points) *time_points = NULL; 5941 } else { 5942 if (n) *n = ts->eval_times->num_time_points; 5943 if (time_points) *time_points = ts->eval_times->time_points; 5944 } 5945 PetscFunctionReturn(PETSC_SUCCESS); 5946 } 5947 5948 /*@C 5949 TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified 5950 5951 Input Parameter: 5952 . ts - the `TS` context obtained from `TSCreate()` 5953 5954 Output Parameters: 5955 + nsol - the number of solutions 5956 . sol_times - array of solution times corresponding to the solution vectors. See note below 5957 - Sols - the solution vectors 5958 5959 Level: intermediate 5960 5961 Notes: 5962 Both `nsol` and `Sols` can be `NULL`. 5963 5964 Some time points in the evaluation points may be skipped by `TS` so that `nsol` is less than the number of points specified by `TSSetEvaluationTimes()`. 5965 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times. 5966 5967 Also used to see view solutions requested by `TSSetTimeSpan()`. 5968 5969 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()` 5970 @*/ 5971 PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec **Sols) 5972 { 5973 PetscFunctionBegin; 5974 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5975 if (nsol) PetscAssertPointer(nsol, 2); 5976 if (sol_times) PetscAssertPointer(sol_times, 3); 5977 if (Sols) PetscAssertPointer(Sols, 4); 5978 if (!ts->eval_times) { 5979 if (nsol) *nsol = 0; 5980 if (sol_times) *sol_times = NULL; 5981 if (Sols) *Sols = NULL; 5982 } else { 5983 if (nsol) *nsol = ts->eval_times->sol_ctr; 5984 if (sol_times) *sol_times = ts->eval_times->sol_times; 5985 if (Sols) *Sols = ts->eval_times->sol_vecs; 5986 } 5987 PetscFunctionReturn(PETSC_SUCCESS); 5988 } 5989 5990 /*@ 5991 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 5992 5993 Collective 5994 5995 Input Parameters: 5996 + ts - the time-stepper 5997 . n - number of the time points (>=2) 5998 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5999 6000 Options Database Key: 6001 . -ts_time_span <t0,...tf> - Sets the time span 6002 6003 Level: intermediate 6004 6005 Notes: 6006 This function is identical to `TSSetEvaluationTimes()`, except that it also sets the initial time and final time for the `ts` to the first and last `span_times` entries. 6007 6008 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 6009 6010 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 6011 6012 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may 6013 pressure the memory system when using a large number of span points. 6014 6015 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()` 6016 @*/ 6017 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 6018 { 6019 PetscFunctionBegin; 6020 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6021 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 6022 PetscCall(TSSetEvaluationTimes(ts, n, span_times)); 6023 PetscCall(TSSetTime(ts, span_times[0])); 6024 PetscCall(TSSetMaxTime(ts, span_times[n - 1])); 6025 PetscFunctionReturn(PETSC_SUCCESS); 6026 } 6027 6028 /*@ 6029 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 6030 6031 Collective 6032 6033 Input Parameters: 6034 + ts - the `TS` context 6035 . J - Jacobian matrix (not altered in this routine) 6036 - B - newly computed Jacobian matrix to use with preconditioner 6037 6038 Level: intermediate 6039 6040 Notes: 6041 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 6042 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 6043 and multiple fields are involved. 6044 6045 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 6046 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 6047 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 6048 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 6049 6050 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 6051 @*/ 6052 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 6053 { 6054 MatColoring mc = NULL; 6055 ISColoring iscoloring = NULL; 6056 MatFDColoring matfdcoloring = NULL; 6057 6058 PetscFunctionBegin; 6059 /* Generate new coloring after eliminating zeros in the matrix */ 6060 PetscCall(MatEliminateZeros(B, PETSC_TRUE)); 6061 PetscCall(MatColoringCreate(B, &mc)); 6062 PetscCall(MatColoringSetDistance(mc, 2)); 6063 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 6064 PetscCall(MatColoringSetFromOptions(mc)); 6065 PetscCall(MatColoringApply(mc, &iscoloring)); 6066 PetscCall(MatColoringDestroy(&mc)); 6067 /* Replace the old coloring with the new one */ 6068 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 6069 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 6070 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 6071 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 6072 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 6073 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 6074 PetscCall(ISColoringDestroy(&iscoloring)); 6075 PetscFunctionReturn(PETSC_SUCCESS); 6076 } 6077