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 matrix used to compute the preconditioner, often the same as `A` 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 ODE integrators. 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 matrix used to construct the preconditioner 1571 1572 Level: developer 1573 1574 Notes: 1575 If $F(t,U,V,A) = 0$ is the DAE, the required Jacobian is 1576 1577 $$ 1578 dF/dU + shiftV*dF/dV + shiftA*dF/dA 1579 $$ 1580 1581 Most users should not need to explicitly call this routine, as it 1582 is used internally within the ODE integrators. 1583 1584 .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()` 1585 @*/ 1586 PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P) 1587 { 1588 DM dm; 1589 TSI2JacobianFn *I2Jacobian; 1590 void *ctx; 1591 TSRHSJacobianFn *rhsjacobian; 1592 1593 PetscFunctionBegin; 1594 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1595 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1596 PetscValidHeaderSpecific(V, VEC_CLASSID, 4); 1597 PetscValidHeaderSpecific(A, VEC_CLASSID, 5); 1598 PetscValidHeaderSpecific(J, MAT_CLASSID, 8); 1599 PetscValidHeaderSpecific(P, MAT_CLASSID, 9); 1600 1601 PetscCall(TSGetDM(ts, &dm)); 1602 PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx)); 1603 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL)); 1604 1605 if (!I2Jacobian) { 1606 PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE)); 1607 PetscFunctionReturn(PETSC_SUCCESS); 1608 } 1609 1610 PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P)); 1611 PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx)); 1612 if (rhsjacobian) { 1613 Mat Jrhs, Prhs; 1614 PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs)); 1615 PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs)); 1616 PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern)); 1617 if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern)); 1618 } 1619 1620 PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P)); 1621 PetscFunctionReturn(PETSC_SUCCESS); 1622 } 1623 1624 /*@C 1625 TSSetTransientVariable - sets function to transform from state to transient variables 1626 1627 Logically Collective 1628 1629 Input Parameters: 1630 + ts - time stepping context on which to change the transient variable 1631 . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence 1632 - ctx - a context for tvar 1633 1634 Level: advanced 1635 1636 Notes: 1637 This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`) 1638 can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to 1639 well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is 1640 C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be 1641 evaluated via the chain rule, as in 1642 .vb 1643 dF/dP + shift * dF/dCdot dC/dP. 1644 .ve 1645 1646 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()` 1647 @*/ 1648 PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, void *ctx) 1649 { 1650 DM dm; 1651 1652 PetscFunctionBegin; 1653 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1654 PetscCall(TSGetDM(ts, &dm)); 1655 PetscCall(DMTSSetTransientVariable(dm, tvar, ctx)); 1656 PetscFunctionReturn(PETSC_SUCCESS); 1657 } 1658 1659 /*@ 1660 TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables 1661 1662 Logically Collective 1663 1664 Input Parameters: 1665 + ts - TS on which to compute 1666 - U - state vector to be transformed to transient variables 1667 1668 Output Parameter: 1669 . C - transient (conservative) variable 1670 1671 Level: developer 1672 1673 Developer Notes: 1674 If `DMTSSetTransientVariable()` has not been called, then C is not modified in this routine and C = `NULL` is allowed. 1675 This makes it safe to call without a guard. One can use `TSHasTransientVariable()` to check if transient variables are 1676 being used. 1677 1678 .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()` 1679 @*/ 1680 PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C) 1681 { 1682 DM dm; 1683 DMTS dmts; 1684 1685 PetscFunctionBegin; 1686 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1687 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 1688 PetscCall(TSGetDM(ts, &dm)); 1689 PetscCall(DMGetDMTS(dm, &dmts)); 1690 if (dmts->ops->transientvar) { 1691 PetscValidHeaderSpecific(C, VEC_CLASSID, 3); 1692 PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx)); 1693 } 1694 PetscFunctionReturn(PETSC_SUCCESS); 1695 } 1696 1697 /*@ 1698 TSHasTransientVariable - determine whether transient variables have been set 1699 1700 Logically Collective 1701 1702 Input Parameter: 1703 . ts - `TS` on which to compute 1704 1705 Output Parameter: 1706 . has - `PETSC_TRUE` if transient variables have been set 1707 1708 Level: developer 1709 1710 .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()` 1711 @*/ 1712 PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has) 1713 { 1714 DM dm; 1715 DMTS dmts; 1716 1717 PetscFunctionBegin; 1718 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1719 PetscCall(TSGetDM(ts, &dm)); 1720 PetscCall(DMGetDMTS(dm, &dmts)); 1721 *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE; 1722 PetscFunctionReturn(PETSC_SUCCESS); 1723 } 1724 1725 /*@ 1726 TS2SetSolution - Sets the initial solution and time derivative vectors 1727 for use by the `TS` routines handling second order equations. 1728 1729 Logically Collective 1730 1731 Input Parameters: 1732 + ts - the `TS` context obtained from `TSCreate()` 1733 . u - the solution vector 1734 - v - the time derivative vector 1735 1736 Level: beginner 1737 1738 .seealso: [](ch_ts), `TS` 1739 @*/ 1740 PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v) 1741 { 1742 PetscFunctionBegin; 1743 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1744 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 1745 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 1746 PetscCall(TSSetSolution(ts, u)); 1747 PetscCall(PetscObjectReference((PetscObject)v)); 1748 PetscCall(VecDestroy(&ts->vec_dot)); 1749 ts->vec_dot = v; 1750 PetscFunctionReturn(PETSC_SUCCESS); 1751 } 1752 1753 /*@ 1754 TS2GetSolution - Returns the solution and time derivative at the present timestep 1755 for second order equations. 1756 1757 Not Collective 1758 1759 Input Parameter: 1760 . ts - the `TS` context obtained from `TSCreate()` 1761 1762 Output Parameters: 1763 + u - the vector containing the solution 1764 - v - the vector containing the time derivative 1765 1766 Level: intermediate 1767 1768 Notes: 1769 It is valid to call this routine inside the function 1770 that you are evaluating in order to move to the new timestep. This vector not 1771 changed until the solution at the next timestep has been calculated. 1772 1773 .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()` 1774 @*/ 1775 PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v) 1776 { 1777 PetscFunctionBegin; 1778 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1779 if (u) PetscAssertPointer(u, 2); 1780 if (v) PetscAssertPointer(v, 3); 1781 if (u) *u = ts->vec_sol; 1782 if (v) *v = ts->vec_dot; 1783 PetscFunctionReturn(PETSC_SUCCESS); 1784 } 1785 1786 /*@ 1787 TSLoad - Loads a `TS` that has been stored in binary with `TSView()`. 1788 1789 Collective 1790 1791 Input Parameters: 1792 + ts - the newly loaded `TS`, this needs to have been created with `TSCreate()` or 1793 some related function before a call to `TSLoad()`. 1794 - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 1795 1796 Level: intermediate 1797 1798 Note: 1799 The type is determined by the data in the file, any type set into the `TS` before this call is ignored. 1800 1801 .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()` 1802 @*/ 1803 PetscErrorCode TSLoad(TS ts, PetscViewer viewer) 1804 { 1805 PetscBool isbinary; 1806 PetscInt classid; 1807 char type[256]; 1808 DMTS sdm; 1809 DM dm; 1810 1811 PetscFunctionBegin; 1812 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1813 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1814 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1815 PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1816 1817 PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 1818 PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file"); 1819 PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 1820 PetscCall(TSSetType(ts, type)); 1821 PetscTryTypeMethod(ts, load, viewer); 1822 PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm)); 1823 PetscCall(DMLoad(dm, viewer)); 1824 PetscCall(TSSetDM(ts, dm)); 1825 PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol)); 1826 PetscCall(VecLoad(ts->vec_sol, viewer)); 1827 PetscCall(DMGetDMTS(ts->dm, &sdm)); 1828 PetscCall(DMTSLoad(sdm, viewer)); 1829 PetscFunctionReturn(PETSC_SUCCESS); 1830 } 1831 1832 #include <petscdraw.h> 1833 #if defined(PETSC_HAVE_SAWS) 1834 #include <petscviewersaws.h> 1835 #endif 1836 1837 /*@ 1838 TSViewFromOptions - View a `TS` based on values in the options database 1839 1840 Collective 1841 1842 Input Parameters: 1843 + ts - the `TS` context 1844 . obj - Optional object that provides the prefix for the options database keys 1845 - name - command line option string to be passed by user 1846 1847 Level: intermediate 1848 1849 .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()` 1850 @*/ 1851 PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[]) 1852 { 1853 PetscFunctionBegin; 1854 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1855 PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name)); 1856 PetscFunctionReturn(PETSC_SUCCESS); 1857 } 1858 1859 /*@ 1860 TSView - Prints the `TS` data structure. 1861 1862 Collective 1863 1864 Input Parameters: 1865 + ts - the `TS` context obtained from `TSCreate()` 1866 - viewer - visualization context 1867 1868 Options Database Key: 1869 . -ts_view - calls `TSView()` at end of `TSStep()` 1870 1871 Level: beginner 1872 1873 Notes: 1874 The available visualization contexts include 1875 + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 1876 - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 1877 output where only the first processor opens 1878 the file. All other processors send their 1879 data to the first processor to print. 1880 1881 The user can open an alternative visualization context with 1882 `PetscViewerASCIIOpen()` - output to a specified file. 1883 1884 In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer). 1885 1886 .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()` 1887 @*/ 1888 PetscErrorCode TSView(TS ts, PetscViewer viewer) 1889 { 1890 TSType type; 1891 PetscBool iascii, isstring, isundials, isbinary, isdraw; 1892 DMTS sdm; 1893 #if defined(PETSC_HAVE_SAWS) 1894 PetscBool issaws; 1895 #endif 1896 1897 PetscFunctionBegin; 1898 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1899 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer)); 1900 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1901 PetscCheckSameComm(ts, 1, viewer, 2); 1902 1903 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1904 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1905 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1906 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 1907 #if defined(PETSC_HAVE_SAWS) 1908 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1909 #endif 1910 if (iascii) { 1911 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer)); 1912 if (ts->ops->view) { 1913 PetscCall(PetscViewerASCIIPushTab(viewer)); 1914 PetscUseTypeMethod(ts, view, viewer); 1915 PetscCall(PetscViewerASCIIPopTab(viewer)); 1916 } 1917 if (ts->max_steps < PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum steps=%" PetscInt_FMT "\n", ts->max_steps)); 1918 if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum time=%g\n", (double)ts->max_time)); 1919 if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs)); 1920 if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs)); 1921 if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs)); 1922 if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs)); 1923 if (ts->usessnes) { 1924 PetscBool lin; 1925 if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its)); 1926 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its)); 1927 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, "")); 1928 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures)); 1929 } 1930 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of rejected steps=%" PetscInt_FMT "\n", ts->reject)); 1931 if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of relative error tolerances, ")); 1932 else PetscCall(PetscViewerASCIIPrintf(viewer, " using relative error tolerance of %g, ", (double)ts->rtol)); 1933 if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of absolute error tolerances\n")); 1934 else PetscCall(PetscViewerASCIIPrintf(viewer, " using absolute error tolerance of %g\n", (double)ts->atol)); 1935 PetscCall(PetscViewerASCIIPushTab(viewer)); 1936 PetscCall(TSAdaptView(ts->adapt, viewer)); 1937 PetscCall(PetscViewerASCIIPopTab(viewer)); 1938 } else if (isstring) { 1939 PetscCall(TSGetType(ts, &type)); 1940 PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type)); 1941 PetscTryTypeMethod(ts, view, viewer); 1942 } else if (isbinary) { 1943 PetscInt classid = TS_FILE_CLASSID; 1944 MPI_Comm comm; 1945 PetscMPIInt rank; 1946 char type[256]; 1947 1948 PetscCall(PetscObjectGetComm((PetscObject)ts, &comm)); 1949 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1950 if (rank == 0) { 1951 PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 1952 PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256)); 1953 PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR)); 1954 } 1955 PetscTryTypeMethod(ts, view, viewer); 1956 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer)); 1957 PetscCall(DMView(ts->dm, viewer)); 1958 PetscCall(VecView(ts->vec_sol, viewer)); 1959 PetscCall(DMGetDMTS(ts->dm, &sdm)); 1960 PetscCall(DMTSView(sdm, viewer)); 1961 } else if (isdraw) { 1962 PetscDraw draw; 1963 char str[36]; 1964 PetscReal x, y, bottom, h; 1965 1966 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1967 PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 1968 PetscCall(PetscStrncpy(str, "TS: ", sizeof(str))); 1969 PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str))); 1970 PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h)); 1971 bottom = y - h; 1972 PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 1973 PetscTryTypeMethod(ts, view, viewer); 1974 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer)); 1975 if (ts->snes) PetscCall(SNESView(ts->snes, viewer)); 1976 PetscCall(PetscDrawPopCurrentPoint(draw)); 1977 #if defined(PETSC_HAVE_SAWS) 1978 } else if (issaws) { 1979 PetscMPIInt rank; 1980 const char *name; 1981 1982 PetscCall(PetscObjectGetName((PetscObject)ts, &name)); 1983 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1984 if (!((PetscObject)ts)->amsmem && rank == 0) { 1985 char dir[1024]; 1986 1987 PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer)); 1988 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name)); 1989 PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT)); 1990 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name)); 1991 PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE)); 1992 } 1993 PetscTryTypeMethod(ts, view, viewer); 1994 #endif 1995 } 1996 if (ts->snes && ts->usessnes) { 1997 PetscCall(PetscViewerASCIIPushTab(viewer)); 1998 PetscCall(SNESView(ts->snes, viewer)); 1999 PetscCall(PetscViewerASCIIPopTab(viewer)); 2000 } 2001 PetscCall(DMGetDMTS(ts->dm, &sdm)); 2002 PetscCall(DMTSView(sdm, viewer)); 2003 2004 PetscCall(PetscViewerASCIIPushTab(viewer)); 2005 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &isundials)); 2006 PetscCall(PetscViewerASCIIPopTab(viewer)); 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 /*@ 2011 TSSetApplicationContext - Sets an optional user-defined context for the timesteppers that may be accessed, for example inside the user provided 2012 `TS` callbacks with `TSGetApplicationContext()` 2013 2014 Logically Collective 2015 2016 Input Parameters: 2017 + ts - the `TS` context obtained from `TSCreate()` 2018 - ctx - user context 2019 2020 Level: intermediate 2021 2022 Fortran Note: 2023 This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 2024 function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TSGetApplicationContext()` for 2025 an example. 2026 2027 .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()` 2028 @*/ 2029 PetscErrorCode TSSetApplicationContext(TS ts, PeCtx ctx) 2030 { 2031 PetscFunctionBegin; 2032 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2033 ts->ctx = ctx; 2034 PetscFunctionReturn(PETSC_SUCCESS); 2035 } 2036 2037 /*@ 2038 TSGetApplicationContext - Gets the user-defined context for the 2039 timestepper that was set with `TSSetApplicationContext()` 2040 2041 Not Collective 2042 2043 Input Parameter: 2044 . ts - the `TS` context obtained from `TSCreate()` 2045 2046 Output Parameter: 2047 . ctx - a pointer to the user context 2048 2049 Level: intermediate 2050 2051 Fortran Notes: 2052 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 2053 function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 2054 .vb 2055 Interface TSGetApplicationContext 2056 Subroutine TSGetApplicationContext(ts,ctx,ierr) 2057 #include <petsc/finclude/petscts.h> 2058 use petscts 2059 TS ts 2060 type(tUsertype), pointer :: ctx 2061 PetscErrorCode ierr 2062 End Subroutine 2063 End Interface TSGetApplicationContext 2064 .ve 2065 2066 The prototype for `ctx` must be 2067 .vb 2068 type(tUsertype), pointer :: ctx 2069 .ve 2070 2071 .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()` 2072 @*/ 2073 PetscErrorCode TSGetApplicationContext(TS ts, void *ctx) 2074 { 2075 PetscFunctionBegin; 2076 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2077 *(void **)ctx = ts->ctx; 2078 PetscFunctionReturn(PETSC_SUCCESS); 2079 } 2080 2081 /*@ 2082 TSGetStepNumber - Gets the number of time steps completed. 2083 2084 Not Collective 2085 2086 Input Parameter: 2087 . ts - the `TS` context obtained from `TSCreate()` 2088 2089 Output Parameter: 2090 . steps - number of steps completed so far 2091 2092 Level: intermediate 2093 2094 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()` 2095 @*/ 2096 PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps) 2097 { 2098 PetscFunctionBegin; 2099 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2100 PetscAssertPointer(steps, 2); 2101 *steps = ts->steps; 2102 PetscFunctionReturn(PETSC_SUCCESS); 2103 } 2104 2105 /*@ 2106 TSSetStepNumber - Sets the number of steps completed. 2107 2108 Logically Collective 2109 2110 Input Parameters: 2111 + ts - the `TS` context 2112 - steps - number of steps completed so far 2113 2114 Level: developer 2115 2116 Note: 2117 For most uses of the `TS` solvers the user need not explicitly call 2118 `TSSetStepNumber()`, as the step counter is appropriately updated in 2119 `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to 2120 reinitialize timestepping by setting the step counter to zero (and time 2121 to the initial time) to solve a similar problem with different initial 2122 conditions or parameters. Other possible use case is to continue 2123 timestepping from a previously interrupted run in such a way that `TS` 2124 monitors will be called with a initial nonzero step counter. 2125 2126 .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()` 2127 @*/ 2128 PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps) 2129 { 2130 PetscFunctionBegin; 2131 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2132 PetscValidLogicalCollectiveInt(ts, steps, 2); 2133 PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative"); 2134 ts->steps = steps; 2135 PetscFunctionReturn(PETSC_SUCCESS); 2136 } 2137 2138 /*@ 2139 TSSetTimeStep - Allows one to reset the timestep at any time, 2140 useful for simple pseudo-timestepping codes. 2141 2142 Logically Collective 2143 2144 Input Parameters: 2145 + ts - the `TS` context obtained from `TSCreate()` 2146 - time_step - the size of the timestep 2147 2148 Level: intermediate 2149 2150 .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()` 2151 @*/ 2152 PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step) 2153 { 2154 PetscFunctionBegin; 2155 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2156 PetscValidLogicalCollectiveReal(ts, time_step, 2); 2157 ts->time_step = time_step; 2158 PetscFunctionReturn(PETSC_SUCCESS); 2159 } 2160 2161 /*@ 2162 TSSetExactFinalTime - Determines whether to adapt the final time step to 2163 match the exact final time, to interpolate the solution to the exact final time, 2164 or to just return at the final time `TS` computed (which may be slightly larger 2165 than the requested final time). 2166 2167 Logically Collective 2168 2169 Input Parameters: 2170 + ts - the time-step context 2171 - eftopt - exact final time option 2172 .vb 2173 TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded, just use it 2174 TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded 2175 TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to ensure the computed final time exactly equals the requested final time 2176 .ve 2177 2178 Options Database Key: 2179 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime 2180 2181 Level: beginner 2182 2183 Note: 2184 If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time 2185 then the final time you selected. 2186 2187 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()` 2188 @*/ 2189 PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt) 2190 { 2191 PetscFunctionBegin; 2192 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2193 PetscValidLogicalCollectiveEnum(ts, eftopt, 2); 2194 ts->exact_final_time = eftopt; 2195 PetscFunctionReturn(PETSC_SUCCESS); 2196 } 2197 2198 /*@ 2199 TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()` 2200 2201 Not Collective 2202 2203 Input Parameter: 2204 . ts - the `TS` context 2205 2206 Output Parameter: 2207 . eftopt - exact final time option 2208 2209 Level: beginner 2210 2211 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()` 2212 @*/ 2213 PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt) 2214 { 2215 PetscFunctionBegin; 2216 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2217 PetscAssertPointer(eftopt, 2); 2218 *eftopt = ts->exact_final_time; 2219 PetscFunctionReturn(PETSC_SUCCESS); 2220 } 2221 2222 /*@ 2223 TSGetTimeStep - Gets the current timestep size. 2224 2225 Not Collective 2226 2227 Input Parameter: 2228 . ts - the `TS` context obtained from `TSCreate()` 2229 2230 Output Parameter: 2231 . dt - the current timestep size 2232 2233 Level: intermediate 2234 2235 .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()` 2236 @*/ 2237 PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt) 2238 { 2239 PetscFunctionBegin; 2240 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2241 PetscAssertPointer(dt, 2); 2242 *dt = ts->time_step; 2243 PetscFunctionReturn(PETSC_SUCCESS); 2244 } 2245 2246 /*@ 2247 TSGetSolution - Returns the solution at the present timestep. It 2248 is valid to call this routine inside the function that you are evaluating 2249 in order to move to the new timestep. This vector not changed until 2250 the solution at the next timestep has been calculated. 2251 2252 Not Collective, but v returned is parallel if ts is parallel 2253 2254 Input Parameter: 2255 . ts - the `TS` context obtained from `TSCreate()` 2256 2257 Output Parameter: 2258 . v - the vector containing the solution 2259 2260 Level: intermediate 2261 2262 Note: 2263 If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested 2264 final time. It returns the solution at the next timestep. 2265 2266 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()` 2267 @*/ 2268 PetscErrorCode TSGetSolution(TS ts, Vec *v) 2269 { 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2272 PetscAssertPointer(v, 2); 2273 *v = ts->vec_sol; 2274 PetscFunctionReturn(PETSC_SUCCESS); 2275 } 2276 2277 /*@ 2278 TSGetSolutionComponents - Returns any solution components at the present 2279 timestep, if available for the time integration method being used. 2280 Solution components are quantities that share the same size and 2281 structure as the solution vector. 2282 2283 Not Collective, but v returned is parallel if ts is parallel 2284 2285 Input Parameters: 2286 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2287 . n - If v is `NULL`, then the number of solution components is 2288 returned through n, else the n-th solution component is 2289 returned in v. 2290 - v - the vector containing the n-th solution component 2291 (may be `NULL` to use this function to find out 2292 the number of solutions components). 2293 2294 Level: advanced 2295 2296 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2297 @*/ 2298 PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v) 2299 { 2300 PetscFunctionBegin; 2301 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2302 if (!ts->ops->getsolutioncomponents) *n = 0; 2303 else PetscUseTypeMethod(ts, getsolutioncomponents, n, v); 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@ 2308 TSGetAuxSolution - Returns an auxiliary solution at the present 2309 timestep, if available for the time integration method being used. 2310 2311 Not Collective, but v returned is parallel if ts is parallel 2312 2313 Input Parameters: 2314 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2315 - v - the vector containing the auxiliary solution 2316 2317 Level: intermediate 2318 2319 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2320 @*/ 2321 PetscErrorCode TSGetAuxSolution(TS ts, Vec *v) 2322 { 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2325 if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v); 2326 else PetscCall(VecZeroEntries(*v)); 2327 PetscFunctionReturn(PETSC_SUCCESS); 2328 } 2329 2330 /*@ 2331 TSGetTimeError - Returns the estimated error vector, if the chosen 2332 `TSType` has an error estimation functionality and `TSSetTimeError()` was called 2333 2334 Not Collective, but v returned is parallel if ts is parallel 2335 2336 Input Parameters: 2337 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2338 . n - current estimate (n=0) or previous one (n=-1) 2339 - v - the vector containing the error (same size as the solution). 2340 2341 Level: intermediate 2342 2343 Note: 2344 MUST call after `TSSetUp()` 2345 2346 .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()` 2347 @*/ 2348 PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v) 2349 { 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2352 if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v); 2353 else PetscCall(VecZeroEntries(*v)); 2354 PetscFunctionReturn(PETSC_SUCCESS); 2355 } 2356 2357 /*@ 2358 TSSetTimeError - Sets the estimated error vector, if the chosen 2359 `TSType` has an error estimation functionality. This can be used 2360 to restart such a time integrator with a given error vector. 2361 2362 Not Collective, but v returned is parallel if ts is parallel 2363 2364 Input Parameters: 2365 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2366 - v - the vector containing the error (same size as the solution). 2367 2368 Level: intermediate 2369 2370 .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()` 2371 @*/ 2372 PetscErrorCode TSSetTimeError(TS ts, Vec v) 2373 { 2374 PetscFunctionBegin; 2375 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2376 PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first"); 2377 PetscTryTypeMethod(ts, settimeerror, v); 2378 PetscFunctionReturn(PETSC_SUCCESS); 2379 } 2380 2381 /* ----- Routines to initialize and destroy a timestepper ---- */ 2382 /*@ 2383 TSSetProblemType - Sets the type of problem to be solved. 2384 2385 Not collective 2386 2387 Input Parameters: 2388 + ts - The `TS` 2389 - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2390 .vb 2391 U_t - A U = 0 (linear) 2392 U_t - A(t) U = 0 (linear) 2393 F(t,U,U_t) = 0 (nonlinear) 2394 .ve 2395 2396 Level: beginner 2397 2398 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2399 @*/ 2400 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2401 { 2402 PetscFunctionBegin; 2403 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2404 ts->problem_type = type; 2405 if (type == TS_LINEAR) { 2406 SNES snes; 2407 PetscCall(TSGetSNES(ts, &snes)); 2408 PetscCall(SNESSetType(snes, SNESKSPONLY)); 2409 } 2410 PetscFunctionReturn(PETSC_SUCCESS); 2411 } 2412 2413 /*@ 2414 TSGetProblemType - Gets the type of problem to be solved. 2415 2416 Not collective 2417 2418 Input Parameter: 2419 . ts - The `TS` 2420 2421 Output Parameter: 2422 . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2423 .vb 2424 M U_t = A U 2425 M(t) U_t = A(t) U 2426 F(t,U,U_t) 2427 .ve 2428 2429 Level: beginner 2430 2431 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2432 @*/ 2433 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2434 { 2435 PetscFunctionBegin; 2436 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2437 PetscAssertPointer(type, 2); 2438 *type = ts->problem_type; 2439 PetscFunctionReturn(PETSC_SUCCESS); 2440 } 2441 2442 /* 2443 Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp() 2444 */ 2445 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts) 2446 { 2447 PetscBool isnone; 2448 2449 PetscFunctionBegin; 2450 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2451 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2452 2453 PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone)); 2454 if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 2455 else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE; 2456 PetscFunctionReturn(PETSC_SUCCESS); 2457 } 2458 2459 /*@ 2460 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2461 2462 Collective 2463 2464 Input Parameter: 2465 . ts - the `TS` context obtained from `TSCreate()` 2466 2467 Level: advanced 2468 2469 Note: 2470 For basic use of the `TS` solvers the user need not explicitly call 2471 `TSSetUp()`, since these actions will automatically occur during 2472 the call to `TSStep()` or `TSSolve()`. However, if one wishes to control this 2473 phase separately, `TSSetUp()` should be called after `TSCreate()` 2474 and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`. 2475 2476 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()` 2477 @*/ 2478 PetscErrorCode TSSetUp(TS ts) 2479 { 2480 DM dm; 2481 PetscErrorCode (*func)(SNES, Vec, Vec, void *); 2482 PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); 2483 TSIFunctionFn *ifun; 2484 TSIJacobianFn *ijac; 2485 TSI2JacobianFn *i2jac; 2486 TSRHSJacobianFn *rhsjac; 2487 2488 PetscFunctionBegin; 2489 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2490 if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 2491 2492 if (!((PetscObject)ts)->type_name) { 2493 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 2494 PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER)); 2495 } 2496 2497 if (!ts->vec_sol) { 2498 PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first"); 2499 PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol)); 2500 } 2501 2502 if (ts->eval_times) { 2503 if (!ts->eval_times->sol_vecs) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 2504 if (!ts->eval_times->sol_times) PetscCall(PetscMalloc1(ts->eval_times->num_time_points, &ts->eval_times->sol_times)); 2505 } 2506 if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */ 2507 PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs)); 2508 ts->Jacp = ts->Jacprhs; 2509 } 2510 2511 if (ts->quadraturets) { 2512 PetscCall(TSSetUp(ts->quadraturets)); 2513 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2514 PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand)); 2515 } 2516 2517 PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL)); 2518 if (rhsjac == TSComputeRHSJacobianConstant) { 2519 Mat Amat, Pmat; 2520 SNES snes; 2521 PetscCall(TSGetSNES(ts, &snes)); 2522 PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL)); 2523 /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would 2524 * have displaced the RHS matrix */ 2525 if (Amat && Amat == ts->Arhs) { 2526 /* 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 */ 2527 PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat)); 2528 PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL)); 2529 PetscCall(MatDestroy(&Amat)); 2530 } 2531 if (Pmat && Pmat == ts->Brhs) { 2532 PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat)); 2533 PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL)); 2534 PetscCall(MatDestroy(&Pmat)); 2535 } 2536 } 2537 2538 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2539 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2540 2541 PetscTryTypeMethod(ts, setup); 2542 2543 PetscCall(TSSetExactFinalTimeDefault(ts)); 2544 2545 /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction 2546 to be set right but can't do it elsewhere due to the overreliance on ctx=ts. 2547 */ 2548 PetscCall(TSGetDM(ts, &dm)); 2549 PetscCall(DMSNESGetFunction(dm, &func, NULL)); 2550 if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts)); 2551 2552 /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it. 2553 Otherwise, the SNES will use coloring internally to form the Jacobian. 2554 */ 2555 PetscCall(DMSNESGetJacobian(dm, &jac, NULL)); 2556 PetscCall(DMTSGetIJacobian(dm, &ijac, NULL)); 2557 PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL)); 2558 PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL)); 2559 if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts)); 2560 2561 /* if time integration scheme has a starting method, call it */ 2562 PetscTryTypeMethod(ts, startingmethod); 2563 2564 ts->setupcalled = PETSC_TRUE; 2565 PetscFunctionReturn(PETSC_SUCCESS); 2566 } 2567 2568 /*@ 2569 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 2570 2571 Collective 2572 2573 Input Parameter: 2574 . ts - the `TS` context obtained from `TSCreate()` 2575 2576 Level: developer 2577 2578 Notes: 2579 Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain. 2580 2581 See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration. 2582 2583 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSetResize()` 2584 @*/ 2585 PetscErrorCode TSReset(TS ts) 2586 { 2587 TS_RHSSplitLink ilink = ts->tsrhssplit, next; 2588 2589 PetscFunctionBegin; 2590 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2591 2592 PetscTryTypeMethod(ts, reset); 2593 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2594 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2595 2596 PetscCall(MatDestroy(&ts->Arhs)); 2597 PetscCall(MatDestroy(&ts->Brhs)); 2598 PetscCall(VecDestroy(&ts->Frhs)); 2599 PetscCall(VecDestroy(&ts->vec_sol)); 2600 PetscCall(VecDestroy(&ts->vec_sol0)); 2601 PetscCall(VecDestroy(&ts->vec_dot)); 2602 PetscCall(VecDestroy(&ts->vatol)); 2603 PetscCall(VecDestroy(&ts->vrtol)); 2604 PetscCall(VecDestroyVecs(ts->nwork, &ts->work)); 2605 2606 PetscCall(MatDestroy(&ts->Jacprhs)); 2607 PetscCall(MatDestroy(&ts->Jacp)); 2608 if (ts->forward_solve) PetscCall(TSForwardReset(ts)); 2609 if (ts->quadraturets) { 2610 PetscCall(TSReset(ts->quadraturets)); 2611 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2612 } 2613 while (ilink) { 2614 next = ilink->next; 2615 PetscCall(TSDestroy(&ilink->ts)); 2616 PetscCall(PetscFree(ilink->splitname)); 2617 PetscCall(ISDestroy(&ilink->is)); 2618 PetscCall(PetscFree(ilink)); 2619 ilink = next; 2620 } 2621 ts->tsrhssplit = NULL; 2622 ts->num_rhs_splits = 0; 2623 if (ts->eval_times) { 2624 PetscCall(PetscFree(ts->eval_times->time_points)); 2625 PetscCall(PetscFree(ts->eval_times->sol_times)); 2626 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 2627 PetscCall(PetscFree(ts->eval_times)); 2628 } 2629 ts->rhsjacobian.time = PETSC_MIN_REAL; 2630 ts->rhsjacobian.scale = 1.0; 2631 ts->ijacobian.shift = 1.0; 2632 ts->setupcalled = PETSC_FALSE; 2633 PetscFunctionReturn(PETSC_SUCCESS); 2634 } 2635 2636 static PetscErrorCode TSResizeReset(TS); 2637 2638 /*@ 2639 TSDestroy - Destroys the timestepper context that was created 2640 with `TSCreate()`. 2641 2642 Collective 2643 2644 Input Parameter: 2645 . ts - the `TS` context obtained from `TSCreate()` 2646 2647 Level: beginner 2648 2649 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2650 @*/ 2651 PetscErrorCode TSDestroy(TS *ts) 2652 { 2653 PetscFunctionBegin; 2654 if (!*ts) PetscFunctionReturn(PETSC_SUCCESS); 2655 PetscValidHeaderSpecific(*ts, TS_CLASSID, 1); 2656 if (--((PetscObject)*ts)->refct > 0) { 2657 *ts = NULL; 2658 PetscFunctionReturn(PETSC_SUCCESS); 2659 } 2660 2661 PetscCall(TSReset(*ts)); 2662 PetscCall(TSAdjointReset(*ts)); 2663 if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts)); 2664 PetscCall(TSResizeReset(*ts)); 2665 2666 /* if memory was published with SAWs then destroy it */ 2667 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2668 PetscTryTypeMethod(*ts, destroy); 2669 2670 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2671 2672 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2673 PetscCall(TSEventDestroy(&(*ts)->event)); 2674 2675 PetscCall(SNESDestroy(&(*ts)->snes)); 2676 PetscCall(SNESDestroy(&(*ts)->snesrhssplit)); 2677 PetscCall(DMDestroy(&(*ts)->dm)); 2678 PetscCall(TSMonitorCancel(*ts)); 2679 PetscCall(TSAdjointMonitorCancel(*ts)); 2680 2681 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2682 PetscCall(PetscHeaderDestroy(ts)); 2683 PetscFunctionReturn(PETSC_SUCCESS); 2684 } 2685 2686 /*@ 2687 TSGetSNES - Returns the `SNES` (nonlinear solver) associated with 2688 a `TS` (timestepper) context. Valid only for nonlinear problems. 2689 2690 Not Collective, but snes is parallel if ts is parallel 2691 2692 Input Parameter: 2693 . ts - the `TS` context obtained from `TSCreate()` 2694 2695 Output Parameter: 2696 . snes - the nonlinear solver context 2697 2698 Level: beginner 2699 2700 Notes: 2701 The user can then directly manipulate the `SNES` context to set various 2702 options, etc. Likewise, the user can then extract and manipulate the 2703 `KSP`, and `PC` contexts as well. 2704 2705 `TSGetSNES()` does not work for integrators that do not use `SNES`; in 2706 this case `TSGetSNES()` returns `NULL` in `snes`. 2707 2708 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2709 @*/ 2710 PetscErrorCode TSGetSNES(TS ts, SNES *snes) 2711 { 2712 PetscFunctionBegin; 2713 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2714 PetscAssertPointer(snes, 2); 2715 if (!ts->snes) { 2716 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes)); 2717 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options)); 2718 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2719 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1)); 2720 if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm)); 2721 if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 2722 } 2723 *snes = ts->snes; 2724 PetscFunctionReturn(PETSC_SUCCESS); 2725 } 2726 2727 /*@ 2728 TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context 2729 2730 Collective 2731 2732 Input Parameters: 2733 + ts - the `TS` context obtained from `TSCreate()` 2734 - snes - the nonlinear solver context 2735 2736 Level: developer 2737 2738 Note: 2739 Most users should have the `TS` created by calling `TSGetSNES()` 2740 2741 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2742 @*/ 2743 PetscErrorCode TSSetSNES(TS ts, SNES snes) 2744 { 2745 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 2746 2747 PetscFunctionBegin; 2748 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2749 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2750 PetscCall(PetscObjectReference((PetscObject)snes)); 2751 PetscCall(SNESDestroy(&ts->snes)); 2752 2753 ts->snes = snes; 2754 2755 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2756 PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL)); 2757 if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts)); 2758 PetscFunctionReturn(PETSC_SUCCESS); 2759 } 2760 2761 /*@ 2762 TSGetKSP - Returns the `KSP` (linear solver) associated with 2763 a `TS` (timestepper) context. 2764 2765 Not Collective, but `ksp` is parallel if `ts` is parallel 2766 2767 Input Parameter: 2768 . ts - the `TS` context obtained from `TSCreate()` 2769 2770 Output Parameter: 2771 . ksp - the nonlinear solver context 2772 2773 Level: beginner 2774 2775 Notes: 2776 The user can then directly manipulate the `KSP` context to set various 2777 options, etc. Likewise, the user can then extract and manipulate the 2778 `PC` context as well. 2779 2780 `TSGetKSP()` does not work for integrators that do not use `KSP`; 2781 in this case `TSGetKSP()` returns `NULL` in `ksp`. 2782 2783 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2784 @*/ 2785 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) 2786 { 2787 SNES snes; 2788 2789 PetscFunctionBegin; 2790 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2791 PetscAssertPointer(ksp, 2); 2792 PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first"); 2793 PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()"); 2794 PetscCall(TSGetSNES(ts, &snes)); 2795 PetscCall(SNESGetKSP(snes, ksp)); 2796 PetscFunctionReturn(PETSC_SUCCESS); 2797 } 2798 2799 /* ----------- Routines to set solver parameters ---------- */ 2800 2801 /*@ 2802 TSSetMaxSteps - Sets the maximum number of steps to use. 2803 2804 Logically Collective 2805 2806 Input Parameters: 2807 + ts - the `TS` context obtained from `TSCreate()` 2808 - maxsteps - maximum number of steps to use 2809 2810 Options Database Key: 2811 . -ts_max_steps <maxsteps> - Sets maxsteps 2812 2813 Level: intermediate 2814 2815 Note: 2816 Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set 2817 2818 The default maximum number of steps is 5,000 2819 2820 Fortran Note: 2821 Use `PETSC_DETERMINE_INTEGER` 2822 2823 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2824 @*/ 2825 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) 2826 { 2827 PetscFunctionBegin; 2828 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2829 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2830 if (maxsteps == PETSC_DETERMINE) { 2831 ts->max_steps = ts->default_max_steps; 2832 } else { 2833 PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative"); 2834 ts->max_steps = maxsteps; 2835 } 2836 PetscFunctionReturn(PETSC_SUCCESS); 2837 } 2838 2839 /*@ 2840 TSGetMaxSteps - Gets the maximum number of steps to use. 2841 2842 Not Collective 2843 2844 Input Parameter: 2845 . ts - the `TS` context obtained from `TSCreate()` 2846 2847 Output Parameter: 2848 . maxsteps - maximum number of steps to use 2849 2850 Level: advanced 2851 2852 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2853 @*/ 2854 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) 2855 { 2856 PetscFunctionBegin; 2857 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2858 PetscAssertPointer(maxsteps, 2); 2859 *maxsteps = ts->max_steps; 2860 PetscFunctionReturn(PETSC_SUCCESS); 2861 } 2862 2863 /*@ 2864 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2865 2866 Logically Collective 2867 2868 Input Parameters: 2869 + ts - the `TS` context obtained from `TSCreate()` 2870 - maxtime - final time to step to 2871 2872 Options Database Key: 2873 . -ts_max_time <maxtime> - Sets maxtime 2874 2875 Level: intermediate 2876 2877 Notes: 2878 Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set 2879 2880 The default maximum time is 5.0 2881 2882 Fortran Note: 2883 Use `PETSC_DETERMINE_REAL` 2884 2885 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2886 @*/ 2887 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) 2888 { 2889 PetscFunctionBegin; 2890 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2891 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 2892 if (maxtime == PETSC_DETERMINE) { 2893 ts->max_time = ts->default_max_time; 2894 } else { 2895 ts->max_time = maxtime; 2896 } 2897 PetscFunctionReturn(PETSC_SUCCESS); 2898 } 2899 2900 /*@ 2901 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2902 2903 Not Collective 2904 2905 Input Parameter: 2906 . ts - the `TS` context obtained from `TSCreate()` 2907 2908 Output Parameter: 2909 . maxtime - final time to step to 2910 2911 Level: advanced 2912 2913 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2914 @*/ 2915 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) 2916 { 2917 PetscFunctionBegin; 2918 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2919 PetscAssertPointer(maxtime, 2); 2920 *maxtime = ts->max_time; 2921 PetscFunctionReturn(PETSC_SUCCESS); 2922 } 2923 2924 // PetscClangLinter pragma disable: -fdoc-* 2925 /*@ 2926 TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`. 2927 2928 Level: deprecated 2929 2930 @*/ 2931 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) 2932 { 2933 PetscFunctionBegin; 2934 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2935 PetscCall(TSSetTime(ts, initial_time)); 2936 PetscCall(TSSetTimeStep(ts, time_step)); 2937 PetscFunctionReturn(PETSC_SUCCESS); 2938 } 2939 2940 // PetscClangLinter pragma disable: -fdoc-* 2941 /*@ 2942 TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`. 2943 2944 Level: deprecated 2945 2946 @*/ 2947 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 2948 { 2949 PetscFunctionBegin; 2950 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2951 if (maxsteps) { 2952 PetscAssertPointer(maxsteps, 2); 2953 *maxsteps = ts->max_steps; 2954 } 2955 if (maxtime) { 2956 PetscAssertPointer(maxtime, 3); 2957 *maxtime = ts->max_time; 2958 } 2959 PetscFunctionReturn(PETSC_SUCCESS); 2960 } 2961 2962 // PetscClangLinter pragma disable: -fdoc-* 2963 /*@ 2964 TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`. 2965 2966 Level: deprecated 2967 2968 @*/ 2969 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) 2970 { 2971 PetscFunctionBegin; 2972 if (maxsteps != PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps)); 2973 if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime)); 2974 PetscFunctionReturn(PETSC_SUCCESS); 2975 } 2976 2977 // PetscClangLinter pragma disable: -fdoc-* 2978 /*@ 2979 TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`. 2980 2981 Level: deprecated 2982 2983 @*/ 2984 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) 2985 { 2986 return TSGetStepNumber(ts, steps); 2987 } 2988 2989 // PetscClangLinter pragma disable: -fdoc-* 2990 /*@ 2991 TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`. 2992 2993 Level: deprecated 2994 2995 @*/ 2996 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) 2997 { 2998 return TSGetStepNumber(ts, steps); 2999 } 3000 3001 /*@ 3002 TSSetSolution - Sets the initial solution vector 3003 for use by the `TS` routines. 3004 3005 Logically Collective 3006 3007 Input Parameters: 3008 + ts - the `TS` context obtained from `TSCreate()` 3009 - u - the solution vector 3010 3011 Level: beginner 3012 3013 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 3014 @*/ 3015 PetscErrorCode TSSetSolution(TS ts, Vec u) 3016 { 3017 DM dm; 3018 3019 PetscFunctionBegin; 3020 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3021 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3022 PetscCall(PetscObjectReference((PetscObject)u)); 3023 PetscCall(VecDestroy(&ts->vec_sol)); 3024 ts->vec_sol = u; 3025 3026 PetscCall(TSGetDM(ts, &dm)); 3027 PetscCall(DMShellSetGlobalVector(dm, u)); 3028 PetscFunctionReturn(PETSC_SUCCESS); 3029 } 3030 3031 /*@C 3032 TSSetPreStep - Sets the general-purpose function 3033 called once at the beginning of each time step. 3034 3035 Logically Collective 3036 3037 Input Parameters: 3038 + ts - The `TS` context obtained from `TSCreate()` 3039 - func - The function 3040 3041 Calling sequence of `func`: 3042 . ts - the `TS` context 3043 3044 Level: intermediate 3045 3046 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3047 @*/ 3048 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts)) 3049 { 3050 PetscFunctionBegin; 3051 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3052 ts->prestep = func; 3053 PetscFunctionReturn(PETSC_SUCCESS); 3054 } 3055 3056 /*@ 3057 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3058 3059 Collective 3060 3061 Input Parameter: 3062 . ts - The `TS` context obtained from `TSCreate()` 3063 3064 Level: developer 3065 3066 Note: 3067 `TSPreStep()` is typically used within time stepping implementations, 3068 so most users would not generally call this routine themselves. 3069 3070 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3071 @*/ 3072 PetscErrorCode TSPreStep(TS ts) 3073 { 3074 PetscFunctionBegin; 3075 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3076 if (ts->prestep) { 3077 Vec U; 3078 PetscObjectId idprev; 3079 PetscBool sameObject; 3080 PetscObjectState sprev, spost; 3081 3082 PetscCall(TSGetSolution(ts, &U)); 3083 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3084 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3085 PetscCallBack("TS callback preset", (*ts->prestep)(ts)); 3086 PetscCall(TSGetSolution(ts, &U)); 3087 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3088 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3089 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3090 } 3091 PetscFunctionReturn(PETSC_SUCCESS); 3092 } 3093 3094 /*@C 3095 TSSetPreStage - Sets the general-purpose function 3096 called once at the beginning of each stage. 3097 3098 Logically Collective 3099 3100 Input Parameters: 3101 + ts - The `TS` context obtained from `TSCreate()` 3102 - func - The function 3103 3104 Calling sequence of `func`: 3105 + ts - the `TS` context 3106 - stagetime - the stage time 3107 3108 Level: intermediate 3109 3110 Note: 3111 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3112 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3113 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3114 3115 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3116 @*/ 3117 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime)) 3118 { 3119 PetscFunctionBegin; 3120 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3121 ts->prestage = func; 3122 PetscFunctionReturn(PETSC_SUCCESS); 3123 } 3124 3125 /*@C 3126 TSSetPostStage - Sets the general-purpose function 3127 called once at the end of each stage. 3128 3129 Logically Collective 3130 3131 Input Parameters: 3132 + ts - The `TS` context obtained from `TSCreate()` 3133 - func - The function 3134 3135 Calling sequence of `func`: 3136 + ts - the `TS` context 3137 . stagetime - the stage time 3138 . stageindex - the stage index 3139 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3140 3141 Level: intermediate 3142 3143 Note: 3144 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3145 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3146 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3147 3148 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3149 @*/ 3150 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)) 3151 { 3152 PetscFunctionBegin; 3153 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3154 ts->poststage = func; 3155 PetscFunctionReturn(PETSC_SUCCESS); 3156 } 3157 3158 /*@C 3159 TSSetPostEvaluate - Sets the general-purpose function 3160 called at the end of each step evaluation. 3161 3162 Logically Collective 3163 3164 Input Parameters: 3165 + ts - The `TS` context obtained from `TSCreate()` 3166 - func - The function 3167 3168 Calling sequence of `func`: 3169 . ts - the `TS` context 3170 3171 Level: intermediate 3172 3173 Note: 3174 The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback. 3175 Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be. 3176 The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`. 3177 The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`, 3178 but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below 3179 .vb 3180 ... 3181 Step() 3182 PostEvaluate() 3183 EventHandling() 3184 step_rollback ? PostEvaluate() : PostStep() 3185 ... 3186 .ve 3187 where EventHandling() may result in one of the following three outcomes 3188 .vb 3189 (1) | successful step | solution intact 3190 (2) | successful step | solution modified by `postevent()` 3191 (3) | step_rollback | solution rolled back 3192 .ve 3193 3194 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3195 @*/ 3196 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts)) 3197 { 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3200 ts->postevaluate = func; 3201 PetscFunctionReturn(PETSC_SUCCESS); 3202 } 3203 3204 /*@ 3205 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3206 3207 Collective 3208 3209 Input Parameters: 3210 + ts - The `TS` context obtained from `TSCreate()` 3211 - stagetime - The absolute time of the current stage 3212 3213 Level: developer 3214 3215 Note: 3216 `TSPreStage()` is typically used within time stepping implementations, 3217 most users would not generally call this routine themselves. 3218 3219 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3220 @*/ 3221 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3222 { 3223 PetscFunctionBegin; 3224 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3225 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3226 PetscFunctionReturn(PETSC_SUCCESS); 3227 } 3228 3229 /*@ 3230 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3231 3232 Collective 3233 3234 Input Parameters: 3235 + ts - The `TS` context obtained from `TSCreate()` 3236 . stagetime - The absolute time of the current stage 3237 . stageindex - Stage number 3238 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3239 3240 Level: developer 3241 3242 Note: 3243 `TSPostStage()` is typically used within time stepping implementations, 3244 most users would not generally call this routine themselves. 3245 3246 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3247 @*/ 3248 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3249 { 3250 PetscFunctionBegin; 3251 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3252 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3253 PetscFunctionReturn(PETSC_SUCCESS); 3254 } 3255 3256 /*@ 3257 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3258 3259 Collective 3260 3261 Input Parameter: 3262 . ts - The `TS` context obtained from `TSCreate()` 3263 3264 Level: developer 3265 3266 Note: 3267 `TSPostEvaluate()` is typically used within time stepping implementations, 3268 most users would not generally call this routine themselves. 3269 3270 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3271 @*/ 3272 PetscErrorCode TSPostEvaluate(TS ts) 3273 { 3274 PetscFunctionBegin; 3275 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3276 if (ts->postevaluate) { 3277 Vec U; 3278 PetscObjectState sprev, spost; 3279 3280 PetscCall(TSGetSolution(ts, &U)); 3281 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3282 PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts)); 3283 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3284 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3285 } 3286 PetscFunctionReturn(PETSC_SUCCESS); 3287 } 3288 3289 /*@C 3290 TSSetPostStep - Sets the general-purpose function 3291 called once at the end of each successful time step. 3292 3293 Logically Collective 3294 3295 Input Parameters: 3296 + ts - The `TS` context obtained from `TSCreate()` 3297 - func - The function 3298 3299 Calling sequence of `func`: 3300 . ts - the `TS` context 3301 3302 Level: intermediate 3303 3304 Note: 3305 The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the 3306 given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will 3307 contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback. 3308 The scheme of the relevant function calls in `TSSolve()` is shown below 3309 .vb 3310 ... 3311 Step() 3312 PostEvaluate() 3313 EventHandling() 3314 step_rollback ? PostEvaluate() : PostStep() 3315 ... 3316 .ve 3317 where EventHandling() may result in one of the following three outcomes 3318 .vb 3319 (1) | successful step | solution intact 3320 (2) | successful step | solution modified by `postevent()` 3321 (3) | step_rollback | solution rolled back 3322 .ve 3323 3324 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3325 @*/ 3326 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts)) 3327 { 3328 PetscFunctionBegin; 3329 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3330 ts->poststep = func; 3331 PetscFunctionReturn(PETSC_SUCCESS); 3332 } 3333 3334 /*@ 3335 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()` 3336 3337 Collective 3338 3339 Input Parameter: 3340 . ts - The `TS` context obtained from `TSCreate()` 3341 3342 Note: 3343 `TSPostStep()` is typically used within time stepping implementations, 3344 so most users would not generally call this routine themselves. 3345 3346 Level: developer 3347 3348 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPostStep()` 3349 @*/ 3350 PetscErrorCode TSPostStep(TS ts) 3351 { 3352 PetscFunctionBegin; 3353 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3354 if (ts->poststep) { 3355 Vec U; 3356 PetscObjectId idprev; 3357 PetscBool sameObject; 3358 PetscObjectState sprev, spost; 3359 3360 PetscCall(TSGetSolution(ts, &U)); 3361 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3362 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3363 PetscCallBack("TS callback poststep", (*ts->poststep)(ts)); 3364 PetscCall(TSGetSolution(ts, &U)); 3365 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3366 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3367 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3368 } 3369 PetscFunctionReturn(PETSC_SUCCESS); 3370 } 3371 3372 /*@ 3373 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3374 3375 Collective 3376 3377 Input Parameters: 3378 + ts - time stepping context 3379 - t - time to interpolate to 3380 3381 Output Parameter: 3382 . U - state at given time 3383 3384 Level: intermediate 3385 3386 Developer Notes: 3387 `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3388 3389 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()` 3390 @*/ 3391 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) 3392 { 3393 PetscFunctionBegin; 3394 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3395 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3396 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); 3397 PetscUseTypeMethod(ts, interpolate, t, U); 3398 PetscFunctionReturn(PETSC_SUCCESS); 3399 } 3400 3401 /*@ 3402 TSStep - Steps one time step 3403 3404 Collective 3405 3406 Input Parameter: 3407 . ts - the `TS` context obtained from `TSCreate()` 3408 3409 Level: developer 3410 3411 Notes: 3412 The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine. 3413 3414 The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may 3415 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3416 3417 This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the 3418 time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep. 3419 3420 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3421 @*/ 3422 PetscErrorCode TSStep(TS ts) 3423 { 3424 static PetscBool cite = PETSC_FALSE; 3425 PetscReal ptime; 3426 3427 PetscFunctionBegin; 3428 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3429 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3430 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3431 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3432 " journal = {arXiv e-preprints},\n" 3433 " eprint = {1806.01437},\n" 3434 " archivePrefix = {arXiv},\n" 3435 " year = {2018}\n}\n", 3436 &cite)); 3437 PetscCall(TSSetUp(ts)); 3438 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3439 if (ts->eval_times) 3440 ts->eval_times->worktol = 0; /* In each step of TSSolve() 'eval_times->worktol' will be meaningfully defined (later) only once: 3441 in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */ 3442 3443 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>"); 3444 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()"); 3445 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"); 3446 3447 if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0)); 3448 PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0)); 3449 ts->time_step0 = ts->time_step; 3450 3451 if (!ts->steps) ts->ptime_prev = ts->ptime; 3452 ptime = ts->ptime; 3453 3454 ts->ptime_prev_rollback = ts->ptime_prev; 3455 ts->reason = TS_CONVERGED_ITERATING; 3456 3457 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3458 PetscUseTypeMethod(ts, step); 3459 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3460 3461 if (ts->reason >= 0) { 3462 ts->ptime_prev = ptime; 3463 ts->steps++; 3464 ts->steprollback = PETSC_FALSE; 3465 ts->steprestart = PETSC_FALSE; 3466 ts->stepresize = PETSC_FALSE; 3467 } 3468 3469 if (ts->reason < 0 && ts->errorifstepfailed) { 3470 PetscCall(TSMonitorCancel(ts)); 3471 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]); 3472 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3473 } 3474 PetscFunctionReturn(PETSC_SUCCESS); 3475 } 3476 3477 /*@ 3478 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3479 at the end of a time step with a given order of accuracy. 3480 3481 Collective 3482 3483 Input Parameters: 3484 + ts - time stepping context 3485 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3486 3487 Input/Output Parameter: 3488 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`; 3489 on output, the actual order of the error evaluation 3490 3491 Output Parameter: 3492 . wlte - the weighted local truncation error norm 3493 3494 Level: advanced 3495 3496 Note: 3497 If the timestepper cannot evaluate the error in a particular step 3498 (eg. in the first step or restart steps after event handling), 3499 this routine returns wlte=-1.0 . 3500 3501 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3502 @*/ 3503 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3504 { 3505 PetscFunctionBegin; 3506 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3507 PetscValidType(ts, 1); 3508 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3509 if (order) PetscAssertPointer(order, 3); 3510 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3511 PetscAssertPointer(wlte, 4); 3512 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3513 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3514 PetscFunctionReturn(PETSC_SUCCESS); 3515 } 3516 3517 /*@ 3518 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3519 3520 Collective 3521 3522 Input Parameters: 3523 + ts - time stepping context 3524 . order - desired order of accuracy 3525 - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available) 3526 3527 Output Parameter: 3528 . U - state at the end of the current step 3529 3530 Level: advanced 3531 3532 Notes: 3533 This function cannot be called until all stages have been evaluated. 3534 3535 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. 3536 3537 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt` 3538 @*/ 3539 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3540 { 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3543 PetscValidType(ts, 1); 3544 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3545 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3546 PetscFunctionReturn(PETSC_SUCCESS); 3547 } 3548 3549 /*@C 3550 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3551 3552 Not collective 3553 3554 Input Parameter: 3555 . ts - time stepping context 3556 3557 Output Parameter: 3558 . initCondition - The function which computes an initial condition 3559 3560 Calling sequence of `initCondition`: 3561 + ts - The timestepping context 3562 - u - The input vector in which the initial condition is stored 3563 3564 Level: advanced 3565 3566 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3567 @*/ 3568 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u)) 3569 { 3570 PetscFunctionBegin; 3571 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3572 PetscAssertPointer(initCondition, 2); 3573 *initCondition = ts->ops->initcondition; 3574 PetscFunctionReturn(PETSC_SUCCESS); 3575 } 3576 3577 /*@C 3578 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3579 3580 Logically collective 3581 3582 Input Parameters: 3583 + ts - time stepping context 3584 - initCondition - The function which computes an initial condition 3585 3586 Calling sequence of `initCondition`: 3587 + ts - The timestepping context 3588 - e - The input vector in which the initial condition is to be stored 3589 3590 Level: advanced 3591 3592 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3593 @*/ 3594 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e)) 3595 { 3596 PetscFunctionBegin; 3597 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3598 PetscValidFunction(initCondition, 2); 3599 ts->ops->initcondition = initCondition; 3600 PetscFunctionReturn(PETSC_SUCCESS); 3601 } 3602 3603 /*@ 3604 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3605 3606 Collective 3607 3608 Input Parameters: 3609 + ts - time stepping context 3610 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3611 3612 Level: advanced 3613 3614 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3615 @*/ 3616 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3617 { 3618 PetscFunctionBegin; 3619 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3620 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3621 PetscTryTypeMethod(ts, initcondition, u); 3622 PetscFunctionReturn(PETSC_SUCCESS); 3623 } 3624 3625 /*@C 3626 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3627 3628 Not collective 3629 3630 Input Parameter: 3631 . ts - time stepping context 3632 3633 Output Parameter: 3634 . exactError - The function which computes the solution error 3635 3636 Calling sequence of `exactError`: 3637 + ts - The timestepping context 3638 . u - The approximate solution vector 3639 - e - The vector in which the error is stored 3640 3641 Level: advanced 3642 3643 .seealso: [](ch_ts), `TS`, `TSComputeExactError()` 3644 @*/ 3645 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e)) 3646 { 3647 PetscFunctionBegin; 3648 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3649 PetscAssertPointer(exactError, 2); 3650 *exactError = ts->ops->exacterror; 3651 PetscFunctionReturn(PETSC_SUCCESS); 3652 } 3653 3654 /*@C 3655 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3656 3657 Logically collective 3658 3659 Input Parameters: 3660 + ts - time stepping context 3661 - exactError - The function which computes the solution error 3662 3663 Calling sequence of `exactError`: 3664 + ts - The timestepping context 3665 . u - The approximate solution vector 3666 - e - The vector in which the error is stored 3667 3668 Level: advanced 3669 3670 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3671 @*/ 3672 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e)) 3673 { 3674 PetscFunctionBegin; 3675 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3676 PetscValidFunction(exactError, 2); 3677 ts->ops->exacterror = exactError; 3678 PetscFunctionReturn(PETSC_SUCCESS); 3679 } 3680 3681 /*@ 3682 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3683 3684 Collective 3685 3686 Input Parameters: 3687 + ts - time stepping context 3688 . u - The approximate solution 3689 - e - The `Vec` used to store the error 3690 3691 Level: advanced 3692 3693 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3694 @*/ 3695 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3696 { 3697 PetscFunctionBegin; 3698 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3699 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3700 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3701 PetscTryTypeMethod(ts, exacterror, u, e); 3702 PetscFunctionReturn(PETSC_SUCCESS); 3703 } 3704 3705 /*@C 3706 TSSetResize - Sets the resize callbacks. 3707 3708 Logically Collective 3709 3710 Input Parameters: 3711 + ts - The `TS` context obtained from `TSCreate()` 3712 . rollback - Whether a resize will restart the step 3713 . setup - The setup function 3714 . transfer - The transfer function 3715 - ctx - [optional] The user-defined context 3716 3717 Calling sequence of `setup`: 3718 + ts - the `TS` context 3719 . step - the current step 3720 . time - the current time 3721 . state - the current vector of state 3722 . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise 3723 - ctx - user defined context 3724 3725 Calling sequence of `transfer`: 3726 + ts - the `TS` context 3727 . nv - the number of vectors to be transferred 3728 . vecsin - array of vectors to be transferred 3729 . vecsout - array of transferred vectors 3730 - ctx - user defined context 3731 3732 Notes: 3733 The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()` 3734 depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators 3735 and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver 3736 that the size of the discrete problem has changed. 3737 In both cases, the solver will collect the needed vectors that will be 3738 transferred from the old to the new sizes using the `transfer` callback. These vectors will include the 3739 current solution vector, and other vectors needed by the specific solver used. 3740 For example, `TSBDF` uses previous solutions vectors to solve for the next time step. 3741 Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`, 3742 will be automatically reset if the sizes are changed and they must be specified again by the user 3743 inside the `transfer` function. 3744 The input and output arrays passed to `transfer` are allocated by PETSc. 3745 Vectors in `vecsout` must be created by the user. 3746 Ownership of vectors in `vecsout` is transferred to PETSc. 3747 3748 Level: advanced 3749 3750 .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()` 3751 @*/ 3752 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) 3753 { 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3756 ts->resizerollback = rollback; 3757 ts->resizesetup = setup; 3758 ts->resizetransfer = transfer; 3759 ts->resizectx = ctx; 3760 PetscFunctionReturn(PETSC_SUCCESS); 3761 } 3762 3763 /* 3764 TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`. 3765 3766 Collective 3767 3768 Input Parameters: 3769 + ts - The `TS` context obtained from `TSCreate()` 3770 - 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. 3771 3772 Level: developer 3773 3774 Note: 3775 `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is 3776 used within time stepping implementations, 3777 so most users would not generally call this routine themselves. 3778 3779 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3780 @*/ 3781 static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg) 3782 { 3783 PetscFunctionBegin; 3784 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3785 PetscTryTypeMethod(ts, resizeregister, flg); 3786 /* PetscTryTypeMethod(adapt, resizeregister, flg); */ 3787 PetscFunctionReturn(PETSC_SUCCESS); 3788 } 3789 3790 static PetscErrorCode TSResizeReset(TS ts) 3791 { 3792 PetscFunctionBegin; 3793 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3794 PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs)); 3795 PetscFunctionReturn(PETSC_SUCCESS); 3796 } 3797 3798 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[]) 3799 { 3800 PetscFunctionBegin; 3801 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3802 PetscValidLogicalCollectiveInt(ts, cnt, 2); 3803 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i])); 3804 if (ts->resizetransfer) { 3805 PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt)); 3806 PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx)); 3807 } 3808 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i])); 3809 PetscFunctionReturn(PETSC_SUCCESS); 3810 } 3811 3812 /*@C 3813 TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`. 3814 3815 Collective 3816 3817 Input Parameters: 3818 + ts - The `TS` context obtained from `TSCreate()` 3819 . name - A string identifying the vector 3820 - vec - The vector 3821 3822 Level: developer 3823 3824 Note: 3825 `TSResizeRegisterVec()` is typically used within time stepping implementations, 3826 so most users would not generally call this routine themselves. 3827 3828 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()` 3829 @*/ 3830 PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec) 3831 { 3832 PetscFunctionBegin; 3833 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3834 PetscAssertPointer(name, 2); 3835 if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3); 3836 PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec)); 3837 PetscFunctionReturn(PETSC_SUCCESS); 3838 } 3839 3840 /*@C 3841 TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`. 3842 3843 Collective 3844 3845 Input Parameters: 3846 + ts - The `TS` context obtained from `TSCreate()` 3847 . name - A string identifying the vector 3848 - vec - The vector 3849 3850 Level: developer 3851 3852 Note: 3853 `TSResizeRetrieveVec()` is typically used within time stepping implementations, 3854 so most users would not generally call this routine themselves. 3855 3856 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()` 3857 @*/ 3858 PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec) 3859 { 3860 PetscFunctionBegin; 3861 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3862 PetscAssertPointer(name, 2); 3863 PetscAssertPointer(vec, 3); 3864 PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec)); 3865 PetscFunctionReturn(PETSC_SUCCESS); 3866 } 3867 3868 static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[]) 3869 { 3870 PetscInt cnt; 3871 PetscObjectList tmp; 3872 Vec *vecsin = NULL; 3873 const char **namesin = NULL; 3874 3875 PetscFunctionBegin; 3876 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) 3877 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++; 3878 if (names) PetscCall(PetscMalloc1(cnt, &namesin)); 3879 if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin)); 3880 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) { 3881 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) { 3882 if (vecs) vecsin[cnt] = (Vec)tmp->obj; 3883 if (names) namesin[cnt] = tmp->name; 3884 cnt++; 3885 } 3886 } 3887 if (nv) *nv = cnt; 3888 if (names) *names = namesin; 3889 if (vecs) *vecs = vecsin; 3890 PetscFunctionReturn(PETSC_SUCCESS); 3891 } 3892 3893 /*@ 3894 TSResize - Runs the user-defined transfer functions provided with `TSSetResize()` 3895 3896 Collective 3897 3898 Input Parameter: 3899 . ts - The `TS` context obtained from `TSCreate()` 3900 3901 Level: developer 3902 3903 Note: 3904 `TSResize()` is typically used within time stepping implementations, 3905 so most users would not generally call this routine themselves. 3906 3907 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3908 @*/ 3909 PetscErrorCode TSResize(TS ts) 3910 { 3911 PetscInt nv = 0; 3912 const char **names = NULL; 3913 Vec *vecsin = NULL; 3914 const char *solname = "ts:vec_sol"; 3915 3916 PetscFunctionBegin; 3917 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3918 if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS); 3919 if (ts->resizesetup) { 3920 PetscCall(VecLockReadPush(ts->vec_sol)); 3921 PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx)); 3922 PetscCall(VecLockReadPop(ts->vec_sol)); 3923 if (ts->stepresize) { 3924 if (ts->resizerollback) { 3925 PetscCall(TSRollBack(ts)); 3926 ts->time_step = ts->time_step0; 3927 } 3928 PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol)); 3929 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */ 3930 } 3931 } 3932 3933 PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin)); 3934 if (nv) { 3935 Vec *vecsout, vecsol; 3936 3937 /* Reset internal objects */ 3938 PetscCall(TSReset(ts)); 3939 3940 /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */ 3941 PetscCall(PetscCalloc1(nv, &vecsout)); 3942 PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout)); 3943 for (PetscInt i = 0; i < nv; i++) { 3944 const char *name; 3945 char *oname; 3946 3947 PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name)); 3948 PetscCall(PetscStrallocpy(name, &oname)); 3949 PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i])); 3950 if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname)); 3951 PetscCall(PetscFree(oname)); 3952 PetscCall(VecDestroy(&vecsout[i])); 3953 } 3954 PetscCall(PetscFree(vecsout)); 3955 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */ 3956 3957 PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol)); 3958 if (vecsol) PetscCall(TSSetSolution(ts, vecsol)); 3959 PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution"); 3960 } 3961 3962 PetscCall(PetscFree(names)); 3963 PetscCall(PetscFree(vecsin)); 3964 PetscCall(TSResizeReset(ts)); 3965 PetscFunctionReturn(PETSC_SUCCESS); 3966 } 3967 3968 /*@ 3969 TSSolve - Steps the requested number of timesteps. 3970 3971 Collective 3972 3973 Input Parameters: 3974 + ts - the `TS` context obtained from `TSCreate()` 3975 - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used, 3976 otherwise it must contain the initial conditions and will contain the solution at the final requested time 3977 3978 Level: beginner 3979 3980 Notes: 3981 The final time returned by this function may be different from the time of the internally 3982 held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have 3983 stepped over the final time. 3984 3985 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3986 @*/ 3987 PetscErrorCode TSSolve(TS ts, Vec u) 3988 { 3989 Vec solution; 3990 3991 PetscFunctionBegin; 3992 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3993 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3994 3995 PetscCall(TSSetExactFinalTimeDefault(ts)); 3996 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 */ 3997 if (!ts->vec_sol || u == ts->vec_sol) { 3998 PetscCall(VecDuplicate(u, &solution)); 3999 PetscCall(TSSetSolution(ts, solution)); 4000 PetscCall(VecDestroy(&solution)); /* grant ownership */ 4001 } 4002 PetscCall(VecCopy(u, ts->vec_sol)); 4003 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 4004 } else if (u) PetscCall(TSSetSolution(ts, u)); 4005 PetscCall(TSSetUp(ts)); 4006 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 4007 4008 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>"); 4009 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()"); 4010 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"); 4011 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"); 4012 4013 if (ts->eval_times) { 4014 for (PetscInt i = 0; i < ts->eval_times->num_time_points; i++) { 4015 PetscBool is_close = PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[i], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0); 4016 if (ts->ptime <= ts->eval_times->time_points[i] || is_close) { 4017 ts->eval_times->time_point_idx = i; 4018 if (is_close) { /* starting point in evaluation times */ 4019 PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_ctr])); 4020 ts->eval_times->sol_times[ts->eval_times->sol_ctr] = ts->ptime; 4021 ts->eval_times->sol_ctr++; 4022 ts->eval_times->time_point_idx++; 4023 } 4024 break; 4025 } 4026 } 4027 } 4028 4029 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 4030 4031 /* reset number of steps only when the step is not restarted. ARKIMEX 4032 restarts the step after an event. Resetting these counters in such case causes 4033 TSTrajectory to incorrectly save the output files 4034 */ 4035 /* reset time step and iteration counters */ 4036 if (!ts->steps) { 4037 ts->ksp_its = 0; 4038 ts->snes_its = 0; 4039 ts->num_snes_failures = 0; 4040 ts->reject = 0; 4041 ts->steprestart = PETSC_TRUE; 4042 ts->steprollback = PETSC_FALSE; 4043 ts->stepresize = PETSC_FALSE; 4044 ts->rhsjacobian.time = PETSC_MIN_REAL; 4045 } 4046 4047 /* make sure initial time step does not overshoot final time or the next point in evaluation times */ 4048 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 4049 PetscReal maxdt; 4050 PetscReal dt = ts->time_step; 4051 4052 if (ts->eval_times) maxdt = ts->eval_times->time_points[ts->eval_times->time_point_idx] - ts->ptime; 4053 else maxdt = ts->max_time - ts->ptime; 4054 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 4055 } 4056 ts->reason = TS_CONVERGED_ITERATING; 4057 4058 { 4059 PetscViewer viewer; 4060 PetscViewerFormat format; 4061 PetscBool flg; 4062 static PetscBool incall = PETSC_FALSE; 4063 4064 if (!incall) { 4065 /* Estimate the convergence rate of the time discretization */ 4066 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 4067 if (flg) { 4068 PetscConvEst conv; 4069 DM dm; 4070 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4071 PetscInt Nf; 4072 PetscBool checkTemporal = PETSC_TRUE; 4073 4074 incall = PETSC_TRUE; 4075 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 4076 PetscCall(TSGetDM(ts, &dm)); 4077 PetscCall(DMGetNumFields(dm, &Nf)); 4078 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 4079 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 4080 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 4081 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 4082 PetscCall(PetscConvEstSetFromOptions(conv)); 4083 PetscCall(PetscConvEstSetUp(conv)); 4084 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4085 PetscCall(PetscViewerPushFormat(viewer, format)); 4086 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4087 PetscCall(PetscViewerPopFormat(viewer)); 4088 PetscCall(PetscViewerDestroy(&viewer)); 4089 PetscCall(PetscConvEstDestroy(&conv)); 4090 PetscCall(PetscFree(alpha)); 4091 incall = PETSC_FALSE; 4092 } 4093 } 4094 } 4095 4096 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 4097 4098 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 4099 PetscUseTypeMethod(ts, solve); 4100 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4101 ts->solvetime = ts->ptime; 4102 solution = ts->vec_sol; 4103 } else { /* Step the requested number of timesteps. */ 4104 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4105 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4106 4107 if (!ts->steps) { 4108 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4109 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 4110 } 4111 4112 while (!ts->reason) { 4113 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4114 if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts)); 4115 PetscCall(TSStep(ts)); 4116 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 4117 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 4118 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 4119 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4120 PetscCall(TSForwardCostIntegral(ts)); 4121 if (ts->reason >= 0) ts->steps++; 4122 } 4123 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 4124 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4125 PetscCall(TSForwardStep(ts)); 4126 if (ts->reason >= 0) ts->steps++; 4127 } 4128 PetscCall(TSPostEvaluate(ts)); 4129 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. */ 4130 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 4131 if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts)); 4132 /* check convergence */ 4133 if (!ts->reason) { 4134 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4135 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4136 } 4137 if (!ts->steprollback) { 4138 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4139 PetscCall(TSPostStep(ts)); 4140 if (!ts->resizerollback) PetscCall(TSResize(ts)); 4141 4142 if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points && ts->reason >= 0) { 4143 PetscCheck(ts->eval_times->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(eval_times->worktol > 0) in TSSolve()"); 4144 if (PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) { 4145 ts->eval_times->sol_times[ts->eval_times->sol_ctr] = ts->ptime; 4146 PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_ctr])); 4147 ts->eval_times->sol_ctr++; 4148 ts->eval_times->time_point_idx++; 4149 } 4150 } 4151 } 4152 } 4153 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4154 4155 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 4156 if (!u) u = ts->vec_sol; 4157 PetscCall(TSInterpolate(ts, ts->max_time, u)); 4158 ts->solvetime = ts->max_time; 4159 solution = u; 4160 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 4161 } else { 4162 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4163 ts->solvetime = ts->ptime; 4164 solution = ts->vec_sol; 4165 } 4166 } 4167 4168 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 4169 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 4170 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 4171 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 4172 PetscFunctionReturn(PETSC_SUCCESS); 4173 } 4174 4175 /*@ 4176 TSGetTime - Gets the time of the most recently completed step. 4177 4178 Not Collective 4179 4180 Input Parameter: 4181 . ts - the `TS` context obtained from `TSCreate()` 4182 4183 Output Parameter: 4184 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 4185 4186 Level: beginner 4187 4188 Note: 4189 When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`, 4190 `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated. 4191 4192 .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 4193 @*/ 4194 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 4195 { 4196 PetscFunctionBegin; 4197 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4198 PetscAssertPointer(t, 2); 4199 *t = ts->ptime; 4200 PetscFunctionReturn(PETSC_SUCCESS); 4201 } 4202 4203 /*@ 4204 TSGetPrevTime - Gets the starting time of the previously completed step. 4205 4206 Not Collective 4207 4208 Input Parameter: 4209 . ts - the `TS` context obtained from `TSCreate()` 4210 4211 Output Parameter: 4212 . t - the previous time 4213 4214 Level: beginner 4215 4216 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4217 @*/ 4218 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 4219 { 4220 PetscFunctionBegin; 4221 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4222 PetscAssertPointer(t, 2); 4223 *t = ts->ptime_prev; 4224 PetscFunctionReturn(PETSC_SUCCESS); 4225 } 4226 4227 /*@ 4228 TSSetTime - Allows one to reset the time. 4229 4230 Logically Collective 4231 4232 Input Parameters: 4233 + ts - the `TS` context obtained from `TSCreate()` 4234 - t - the time 4235 4236 Level: intermediate 4237 4238 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 4239 @*/ 4240 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4241 { 4242 PetscFunctionBegin; 4243 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4244 PetscValidLogicalCollectiveReal(ts, t, 2); 4245 ts->ptime = t; 4246 PetscFunctionReturn(PETSC_SUCCESS); 4247 } 4248 4249 /*@ 4250 TSSetOptionsPrefix - Sets the prefix used for searching for all 4251 TS options in the database. 4252 4253 Logically Collective 4254 4255 Input Parameters: 4256 + ts - The `TS` context 4257 - prefix - The prefix to prepend to all option names 4258 4259 Level: advanced 4260 4261 Note: 4262 A hyphen (-) must NOT be given at the beginning of the prefix name. 4263 The first character of all runtime options is AUTOMATICALLY the 4264 hyphen. 4265 4266 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 4267 @*/ 4268 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 4269 { 4270 SNES snes; 4271 4272 PetscFunctionBegin; 4273 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4274 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 4275 PetscCall(TSGetSNES(ts, &snes)); 4276 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 4277 PetscFunctionReturn(PETSC_SUCCESS); 4278 } 4279 4280 /*@ 4281 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4282 TS options in the database. 4283 4284 Logically Collective 4285 4286 Input Parameters: 4287 + ts - The `TS` context 4288 - prefix - The prefix to prepend to all option names 4289 4290 Level: advanced 4291 4292 Note: 4293 A hyphen (-) must NOT be given at the beginning of the prefix name. 4294 The first character of all runtime options is AUTOMATICALLY the 4295 hyphen. 4296 4297 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 4298 @*/ 4299 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 4300 { 4301 SNES snes; 4302 4303 PetscFunctionBegin; 4304 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4305 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 4306 PetscCall(TSGetSNES(ts, &snes)); 4307 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 4308 PetscFunctionReturn(PETSC_SUCCESS); 4309 } 4310 4311 /*@ 4312 TSGetOptionsPrefix - Sets the prefix used for searching for all 4313 `TS` options in the database. 4314 4315 Not Collective 4316 4317 Input Parameter: 4318 . ts - The `TS` context 4319 4320 Output Parameter: 4321 . prefix - A pointer to the prefix string used 4322 4323 Level: intermediate 4324 4325 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4326 @*/ 4327 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4328 { 4329 PetscFunctionBegin; 4330 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4331 PetscAssertPointer(prefix, 2); 4332 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4333 PetscFunctionReturn(PETSC_SUCCESS); 4334 } 4335 4336 /*@C 4337 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4338 4339 Not Collective, but parallel objects are returned if ts is parallel 4340 4341 Input Parameter: 4342 . ts - The `TS` context obtained from `TSCreate()` 4343 4344 Output Parameters: 4345 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4346 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4347 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4348 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4349 4350 Level: intermediate 4351 4352 Note: 4353 You can pass in `NULL` for any return argument you do not need. 4354 4355 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4356 4357 @*/ 4358 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx) 4359 { 4360 DM dm; 4361 4362 PetscFunctionBegin; 4363 if (Amat || Pmat) { 4364 SNES snes; 4365 PetscCall(TSGetSNES(ts, &snes)); 4366 PetscCall(SNESSetUpMatrices(snes)); 4367 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4368 } 4369 PetscCall(TSGetDM(ts, &dm)); 4370 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4371 PetscFunctionReturn(PETSC_SUCCESS); 4372 } 4373 4374 /*@C 4375 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4376 4377 Not Collective, but parallel objects are returned if ts is parallel 4378 4379 Input Parameter: 4380 . ts - The `TS` context obtained from `TSCreate()` 4381 4382 Output Parameters: 4383 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4384 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4385 . f - The function to compute the matrices 4386 - ctx - User-defined context for Jacobian evaluation routine 4387 4388 Level: advanced 4389 4390 Note: 4391 You can pass in `NULL` for any return argument you do not need. 4392 4393 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4394 @*/ 4395 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx) 4396 { 4397 DM dm; 4398 4399 PetscFunctionBegin; 4400 if (Amat || Pmat) { 4401 SNES snes; 4402 PetscCall(TSGetSNES(ts, &snes)); 4403 PetscCall(SNESSetUpMatrices(snes)); 4404 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4405 } 4406 PetscCall(TSGetDM(ts, &dm)); 4407 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4408 PetscFunctionReturn(PETSC_SUCCESS); 4409 } 4410 4411 #include <petsc/private/dmimpl.h> 4412 /*@ 4413 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4414 4415 Logically Collective 4416 4417 Input Parameters: 4418 + ts - the `TS` integrator object 4419 - dm - the dm, cannot be `NULL` 4420 4421 Level: intermediate 4422 4423 Notes: 4424 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4425 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4426 different problems using the same function space. 4427 4428 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4429 @*/ 4430 PetscErrorCode TSSetDM(TS ts, DM dm) 4431 { 4432 SNES snes; 4433 DMTS tsdm; 4434 4435 PetscFunctionBegin; 4436 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4437 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4438 PetscCall(PetscObjectReference((PetscObject)dm)); 4439 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4440 if (ts->dm->dmts && !dm->dmts) { 4441 PetscCall(DMCopyDMTS(ts->dm, dm)); 4442 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4443 /* Grant write privileges to the replacement DM */ 4444 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4445 } 4446 PetscCall(DMDestroy(&ts->dm)); 4447 } 4448 ts->dm = dm; 4449 4450 PetscCall(TSGetSNES(ts, &snes)); 4451 PetscCall(SNESSetDM(snes, dm)); 4452 PetscFunctionReturn(PETSC_SUCCESS); 4453 } 4454 4455 /*@ 4456 TSGetDM - Gets the `DM` that may be used by some preconditioners 4457 4458 Not Collective 4459 4460 Input Parameter: 4461 . ts - the `TS` 4462 4463 Output Parameter: 4464 . dm - the `DM` 4465 4466 Level: intermediate 4467 4468 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4469 @*/ 4470 PetscErrorCode TSGetDM(TS ts, DM *dm) 4471 { 4472 PetscFunctionBegin; 4473 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4474 if (!ts->dm) { 4475 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4476 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4477 } 4478 *dm = ts->dm; 4479 PetscFunctionReturn(PETSC_SUCCESS); 4480 } 4481 4482 /*@ 4483 SNESTSFormFunction - Function to evaluate nonlinear residual 4484 4485 Logically Collective 4486 4487 Input Parameters: 4488 + snes - nonlinear solver 4489 . U - the current state at which to evaluate the residual 4490 - ctx - user context, must be a TS 4491 4492 Output Parameter: 4493 . F - the nonlinear residual 4494 4495 Level: advanced 4496 4497 Note: 4498 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4499 It is most frequently passed to `MatFDColoringSetFunction()`. 4500 4501 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4502 @*/ 4503 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4504 { 4505 TS ts = (TS)ctx; 4506 4507 PetscFunctionBegin; 4508 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4509 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4510 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4511 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4512 PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name); 4513 PetscCall((*ts->ops->snesfunction)(snes, U, F, ts)); 4514 PetscFunctionReturn(PETSC_SUCCESS); 4515 } 4516 4517 /*@ 4518 SNESTSFormJacobian - Function to evaluate the Jacobian 4519 4520 Collective 4521 4522 Input Parameters: 4523 + snes - nonlinear solver 4524 . U - the current state at which to evaluate the residual 4525 - ctx - user context, must be a `TS` 4526 4527 Output Parameters: 4528 + A - the Jacobian 4529 - B - the matrix used to construct the preconditioner (often the same as `A`) 4530 4531 Level: developer 4532 4533 Note: 4534 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4535 4536 .seealso: [](ch_ts), `SNESSetJacobian()` 4537 @*/ 4538 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4539 { 4540 TS ts = (TS)ctx; 4541 4542 PetscFunctionBegin; 4543 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4544 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4545 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4546 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4547 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4548 PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name); 4549 PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts)); 4550 PetscFunctionReturn(PETSC_SUCCESS); 4551 } 4552 4553 /*@C 4554 TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only 4555 4556 Collective 4557 4558 Input Parameters: 4559 + ts - time stepping context 4560 . t - time at which to evaluate 4561 . U - state at which to evaluate 4562 - ctx - context 4563 4564 Output Parameter: 4565 . F - right-hand side 4566 4567 Level: intermediate 4568 4569 Note: 4570 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems. 4571 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4572 4573 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4574 @*/ 4575 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4576 { 4577 Mat Arhs, Brhs; 4578 4579 PetscFunctionBegin; 4580 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4581 /* undo the damage caused by shifting */ 4582 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4583 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4584 PetscCall(MatMult(Arhs, U, F)); 4585 PetscFunctionReturn(PETSC_SUCCESS); 4586 } 4587 4588 /*@C 4589 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4590 4591 Collective 4592 4593 Input Parameters: 4594 + ts - time stepping context 4595 . t - time at which to evaluate 4596 . U - state at which to evaluate 4597 - ctx - context 4598 4599 Output Parameters: 4600 + A - Jacobian 4601 - B - matrix used to construct the preconditioner, often the same as `A` 4602 4603 Level: intermediate 4604 4605 Note: 4606 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4607 4608 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4609 @*/ 4610 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4611 { 4612 PetscFunctionBegin; 4613 PetscFunctionReturn(PETSC_SUCCESS); 4614 } 4615 4616 /*@C 4617 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4618 4619 Collective 4620 4621 Input Parameters: 4622 + ts - time stepping context 4623 . t - time at which to evaluate 4624 . U - state at which to evaluate 4625 . Udot - time derivative of state vector 4626 - ctx - context 4627 4628 Output Parameter: 4629 . F - left hand side 4630 4631 Level: intermediate 4632 4633 Notes: 4634 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 4635 user is required to write their own `TSComputeIFunction()`. 4636 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4637 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4638 4639 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4640 4641 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4642 @*/ 4643 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4644 { 4645 Mat A, B; 4646 4647 PetscFunctionBegin; 4648 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4649 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4650 PetscCall(MatMult(A, Udot, F)); 4651 PetscFunctionReturn(PETSC_SUCCESS); 4652 } 4653 4654 /*@C 4655 TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE 4656 4657 Collective 4658 4659 Input Parameters: 4660 + ts - time stepping context 4661 . t - time at which to evaluate 4662 . U - state at which to evaluate 4663 . Udot - time derivative of state vector 4664 . shift - shift to apply 4665 - ctx - context 4666 4667 Output Parameters: 4668 + A - pointer to operator 4669 - B - pointer to matrix from which the preconditioner is built (often `A`) 4670 4671 Level: advanced 4672 4673 Notes: 4674 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4675 4676 It is only appropriate for problems of the form 4677 4678 $$ 4679 M \dot{U} = F(U,t) 4680 $$ 4681 4682 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4683 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4684 an implicit operator of the form 4685 4686 $$ 4687 shift*M + J 4688 $$ 4689 4690 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 4691 a copy of M or reassemble it when requested. 4692 4693 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4694 @*/ 4695 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4696 { 4697 PetscFunctionBegin; 4698 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4699 ts->ijacobian.shift = shift; 4700 PetscFunctionReturn(PETSC_SUCCESS); 4701 } 4702 4703 /*@ 4704 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4705 4706 Not Collective 4707 4708 Input Parameter: 4709 . ts - the `TS` context 4710 4711 Output Parameter: 4712 . equation_type - see `TSEquationType` 4713 4714 Level: beginner 4715 4716 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4717 @*/ 4718 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4719 { 4720 PetscFunctionBegin; 4721 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4722 PetscAssertPointer(equation_type, 2); 4723 *equation_type = ts->equation_type; 4724 PetscFunctionReturn(PETSC_SUCCESS); 4725 } 4726 4727 /*@ 4728 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4729 4730 Not Collective 4731 4732 Input Parameters: 4733 + ts - the `TS` context 4734 - equation_type - see `TSEquationType` 4735 4736 Level: advanced 4737 4738 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4739 @*/ 4740 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4741 { 4742 PetscFunctionBegin; 4743 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4744 ts->equation_type = equation_type; 4745 PetscFunctionReturn(PETSC_SUCCESS); 4746 } 4747 4748 /*@ 4749 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4750 4751 Not Collective 4752 4753 Input Parameter: 4754 . ts - the `TS` context 4755 4756 Output Parameter: 4757 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4758 manual pages for the individual convergence tests for complete lists 4759 4760 Level: beginner 4761 4762 Note: 4763 Can only be called after the call to `TSSolve()` is complete. 4764 4765 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4766 @*/ 4767 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4768 { 4769 PetscFunctionBegin; 4770 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4771 PetscAssertPointer(reason, 2); 4772 *reason = ts->reason; 4773 PetscFunctionReturn(PETSC_SUCCESS); 4774 } 4775 4776 /*@ 4777 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4778 4779 Logically Collective; reason must contain common value 4780 4781 Input Parameters: 4782 + ts - the `TS` context 4783 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4784 manual pages for the individual convergence tests for complete lists 4785 4786 Level: advanced 4787 4788 Note: 4789 Can only be called while `TSSolve()` is active. 4790 4791 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4792 @*/ 4793 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4794 { 4795 PetscFunctionBegin; 4796 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4797 ts->reason = reason; 4798 PetscFunctionReturn(PETSC_SUCCESS); 4799 } 4800 4801 /*@ 4802 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4803 4804 Not Collective 4805 4806 Input Parameter: 4807 . ts - the `TS` context 4808 4809 Output Parameter: 4810 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4811 4812 Level: beginner 4813 4814 Note: 4815 Can only be called after the call to `TSSolve()` is complete. 4816 4817 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4818 @*/ 4819 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4820 { 4821 PetscFunctionBegin; 4822 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4823 PetscAssertPointer(ftime, 2); 4824 *ftime = ts->solvetime; 4825 PetscFunctionReturn(PETSC_SUCCESS); 4826 } 4827 4828 /*@ 4829 TSGetSNESIterations - Gets the total number of nonlinear iterations 4830 used by the time integrator. 4831 4832 Not Collective 4833 4834 Input Parameter: 4835 . ts - `TS` context 4836 4837 Output Parameter: 4838 . nits - number of nonlinear iterations 4839 4840 Level: intermediate 4841 4842 Note: 4843 This counter is reset to zero for each successive call to `TSSolve()`. 4844 4845 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4846 @*/ 4847 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4848 { 4849 PetscFunctionBegin; 4850 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4851 PetscAssertPointer(nits, 2); 4852 *nits = ts->snes_its; 4853 PetscFunctionReturn(PETSC_SUCCESS); 4854 } 4855 4856 /*@ 4857 TSGetKSPIterations - Gets the total number of linear iterations 4858 used by the time integrator. 4859 4860 Not Collective 4861 4862 Input Parameter: 4863 . ts - `TS` context 4864 4865 Output Parameter: 4866 . lits - number of linear iterations 4867 4868 Level: intermediate 4869 4870 Note: 4871 This counter is reset to zero for each successive call to `TSSolve()`. 4872 4873 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()` 4874 @*/ 4875 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4876 { 4877 PetscFunctionBegin; 4878 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4879 PetscAssertPointer(lits, 2); 4880 *lits = ts->ksp_its; 4881 PetscFunctionReturn(PETSC_SUCCESS); 4882 } 4883 4884 /*@ 4885 TSGetStepRejections - Gets the total number of rejected steps. 4886 4887 Not Collective 4888 4889 Input Parameter: 4890 . ts - `TS` context 4891 4892 Output Parameter: 4893 . rejects - number of steps rejected 4894 4895 Level: intermediate 4896 4897 Note: 4898 This counter is reset to zero for each successive call to `TSSolve()`. 4899 4900 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4901 @*/ 4902 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4903 { 4904 PetscFunctionBegin; 4905 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4906 PetscAssertPointer(rejects, 2); 4907 *rejects = ts->reject; 4908 PetscFunctionReturn(PETSC_SUCCESS); 4909 } 4910 4911 /*@ 4912 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4913 4914 Not Collective 4915 4916 Input Parameter: 4917 . ts - `TS` context 4918 4919 Output Parameter: 4920 . fails - number of failed nonlinear solves 4921 4922 Level: intermediate 4923 4924 Note: 4925 This counter is reset to zero for each successive call to `TSSolve()`. 4926 4927 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4928 @*/ 4929 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4930 { 4931 PetscFunctionBegin; 4932 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4933 PetscAssertPointer(fails, 2); 4934 *fails = ts->num_snes_failures; 4935 PetscFunctionReturn(PETSC_SUCCESS); 4936 } 4937 4938 /*@ 4939 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4940 4941 Not Collective 4942 4943 Input Parameters: 4944 + ts - `TS` context 4945 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited 4946 4947 Options Database Key: 4948 . -ts_max_reject - Maximum number of step rejections before a step fails 4949 4950 Level: intermediate 4951 4952 Developer Note: 4953 The options database name is incorrect. 4954 4955 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4956 @*/ 4957 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4958 { 4959 PetscFunctionBegin; 4960 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4961 if (rejects == PETSC_UNLIMITED || rejects == -1) { 4962 ts->max_reject = PETSC_UNLIMITED; 4963 } else { 4964 PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections"); 4965 ts->max_reject = rejects; 4966 } 4967 PetscFunctionReturn(PETSC_SUCCESS); 4968 } 4969 4970 /*@ 4971 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4972 4973 Not Collective 4974 4975 Input Parameters: 4976 + ts - `TS` context 4977 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures. 4978 4979 Options Database Key: 4980 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4981 4982 Level: intermediate 4983 4984 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4985 @*/ 4986 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4987 { 4988 PetscFunctionBegin; 4989 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4990 if (fails == PETSC_UNLIMITED || fails == -1) { 4991 ts->max_snes_failures = PETSC_UNLIMITED; 4992 } else { 4993 PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 4994 ts->max_snes_failures = fails; 4995 } 4996 PetscFunctionReturn(PETSC_SUCCESS); 4997 } 4998 4999 /*@ 5000 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 5001 5002 Not Collective 5003 5004 Input Parameters: 5005 + ts - `TS` context 5006 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 5007 5008 Options Database Key: 5009 . -ts_error_if_step_fails - Error if no step succeeds 5010 5011 Level: intermediate 5012 5013 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()` 5014 @*/ 5015 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 5016 { 5017 PetscFunctionBegin; 5018 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5019 ts->errorifstepfailed = err; 5020 PetscFunctionReturn(PETSC_SUCCESS); 5021 } 5022 5023 /*@ 5024 TSGetAdapt - Get the adaptive controller context for the current method 5025 5026 Collective if controller has not yet been created 5027 5028 Input Parameter: 5029 . ts - time stepping context 5030 5031 Output Parameter: 5032 . adapt - adaptive controller 5033 5034 Level: intermediate 5035 5036 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 5037 @*/ 5038 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 5039 { 5040 PetscFunctionBegin; 5041 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5042 PetscAssertPointer(adapt, 2); 5043 if (!ts->adapt) { 5044 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 5045 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 5046 } 5047 *adapt = ts->adapt; 5048 PetscFunctionReturn(PETSC_SUCCESS); 5049 } 5050 5051 /*@ 5052 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 5053 5054 Logically Collective 5055 5056 Input Parameters: 5057 + ts - time integration context 5058 . atol - scalar absolute tolerances 5059 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present 5060 . rtol - scalar relative tolerances 5061 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present 5062 5063 Options Database Keys: 5064 + -ts_rtol <rtol> - relative tolerance for local truncation error 5065 - -ts_atol <atol> - Absolute tolerance for local truncation error 5066 5067 Level: beginner 5068 5069 Notes: 5070 `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value 5071 or the default value from when the object's type was set. 5072 5073 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5074 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5075 computed only for the differential or the algebraic part then this can be done using the vector of 5076 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5077 differential part and infinity for the algebraic part, the LTE calculation will include only the 5078 differential variables. 5079 5080 Fortran Note: 5081 Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`. 5082 5083 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5084 @*/ 5085 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5086 { 5087 PetscFunctionBegin; 5088 if (atol == (PetscReal)PETSC_DETERMINE) { 5089 ts->atol = ts->default_atol; 5090 } else if (atol != (PetscReal)PETSC_CURRENT) { 5091 PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol); 5092 ts->atol = atol; 5093 } 5094 5095 if (vatol) { 5096 PetscCall(PetscObjectReference((PetscObject)vatol)); 5097 PetscCall(VecDestroy(&ts->vatol)); 5098 ts->vatol = vatol; 5099 } 5100 5101 if (rtol == (PetscReal)PETSC_DETERMINE) { 5102 ts->rtol = ts->default_rtol; 5103 } else if (rtol != (PetscReal)PETSC_CURRENT) { 5104 PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol); 5105 ts->rtol = rtol; 5106 } 5107 5108 if (vrtol) { 5109 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5110 PetscCall(VecDestroy(&ts->vrtol)); 5111 ts->vrtol = vrtol; 5112 } 5113 PetscFunctionReturn(PETSC_SUCCESS); 5114 } 5115 5116 /*@ 5117 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5118 5119 Logically Collective 5120 5121 Input Parameter: 5122 . ts - time integration context 5123 5124 Output Parameters: 5125 + atol - scalar absolute tolerances, `NULL` to ignore 5126 . vatol - vector of absolute tolerances, `NULL` to ignore 5127 . rtol - scalar relative tolerances, `NULL` to ignore 5128 - vrtol - vector of relative tolerances, `NULL` to ignore 5129 5130 Level: beginner 5131 5132 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5133 @*/ 5134 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5135 { 5136 PetscFunctionBegin; 5137 if (atol) *atol = ts->atol; 5138 if (vatol) *vatol = ts->vatol; 5139 if (rtol) *rtol = ts->rtol; 5140 if (vrtol) *vrtol = ts->vrtol; 5141 PetscFunctionReturn(PETSC_SUCCESS); 5142 } 5143 5144 /*@ 5145 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5146 5147 Collective 5148 5149 Input Parameters: 5150 + ts - time stepping context 5151 . U - state vector, usually ts->vec_sol 5152 . Y - state vector to be compared to U 5153 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5154 5155 Output Parameters: 5156 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5157 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5158 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5159 5160 Options Database Key: 5161 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5162 5163 Level: developer 5164 5165 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5166 @*/ 5167 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5168 { 5169 PetscInt norma_loc, norm_loc, normr_loc; 5170 5171 PetscFunctionBegin; 5172 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5173 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)); 5174 if (wnormtype == NORM_2) { 5175 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5176 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5177 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5178 } 5179 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5180 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5181 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5182 PetscFunctionReturn(PETSC_SUCCESS); 5183 } 5184 5185 /*@ 5186 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5187 5188 Collective 5189 5190 Input Parameters: 5191 + ts - time stepping context 5192 . E - error vector 5193 . U - state vector, usually ts->vec_sol 5194 . Y - state vector, previous time step 5195 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5196 5197 Output Parameters: 5198 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5199 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5200 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5201 5202 Options Database Key: 5203 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5204 5205 Level: developer 5206 5207 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5208 @*/ 5209 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5210 { 5211 PetscInt norma_loc, norm_loc, normr_loc; 5212 5213 PetscFunctionBegin; 5214 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5215 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)); 5216 if (wnormtype == NORM_2) { 5217 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5218 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5219 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5220 } 5221 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5222 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5223 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5224 PetscFunctionReturn(PETSC_SUCCESS); 5225 } 5226 5227 /*@ 5228 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5229 5230 Logically Collective 5231 5232 Input Parameters: 5233 + ts - time stepping context 5234 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5235 5236 Note: 5237 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5238 5239 Level: intermediate 5240 5241 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5242 @*/ 5243 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5244 { 5245 PetscFunctionBegin; 5246 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5247 ts->cfltime_local = cfltime; 5248 ts->cfltime = -1.; 5249 PetscFunctionReturn(PETSC_SUCCESS); 5250 } 5251 5252 /*@ 5253 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5254 5255 Collective 5256 5257 Input Parameter: 5258 . ts - time stepping context 5259 5260 Output Parameter: 5261 . cfltime - maximum stable time step for forward Euler 5262 5263 Level: advanced 5264 5265 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5266 @*/ 5267 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5268 { 5269 PetscFunctionBegin; 5270 if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5271 *cfltime = ts->cfltime; 5272 PetscFunctionReturn(PETSC_SUCCESS); 5273 } 5274 5275 /*@ 5276 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5277 5278 Input Parameters: 5279 + ts - the `TS` context. 5280 . xl - lower bound. 5281 - xu - upper bound. 5282 5283 Level: advanced 5284 5285 Note: 5286 If this routine is not called then the lower and upper bounds are set to 5287 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5288 5289 .seealso: [](ch_ts), `TS` 5290 @*/ 5291 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5292 { 5293 SNES snes; 5294 5295 PetscFunctionBegin; 5296 PetscCall(TSGetSNES(ts, &snes)); 5297 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5298 PetscFunctionReturn(PETSC_SUCCESS); 5299 } 5300 5301 /*@ 5302 TSComputeLinearStability - computes the linear stability function at a point 5303 5304 Collective 5305 5306 Input Parameters: 5307 + ts - the `TS` context 5308 . xr - real part of input argument 5309 - xi - imaginary part of input argument 5310 5311 Output Parameters: 5312 + yr - real part of function value 5313 - yi - imaginary part of function value 5314 5315 Level: developer 5316 5317 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5318 @*/ 5319 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5320 { 5321 PetscFunctionBegin; 5322 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5323 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5324 PetscFunctionReturn(PETSC_SUCCESS); 5325 } 5326 5327 /*@ 5328 TSRestartStep - Flags the solver to restart the next step 5329 5330 Collective 5331 5332 Input Parameter: 5333 . ts - the `TS` context obtained from `TSCreate()` 5334 5335 Level: advanced 5336 5337 Notes: 5338 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5339 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5340 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5341 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5342 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5343 discontinuous source terms). 5344 5345 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5346 @*/ 5347 PetscErrorCode TSRestartStep(TS ts) 5348 { 5349 PetscFunctionBegin; 5350 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5351 ts->steprestart = PETSC_TRUE; 5352 PetscFunctionReturn(PETSC_SUCCESS); 5353 } 5354 5355 /*@ 5356 TSRollBack - Rolls back one time step 5357 5358 Collective 5359 5360 Input Parameter: 5361 . ts - the `TS` context obtained from `TSCreate()` 5362 5363 Level: advanced 5364 5365 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5366 @*/ 5367 PetscErrorCode TSRollBack(TS ts) 5368 { 5369 PetscFunctionBegin; 5370 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5371 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5372 PetscTryTypeMethod(ts, rollback); 5373 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 5374 ts->time_step = ts->ptime - ts->ptime_prev; 5375 ts->ptime = ts->ptime_prev; 5376 ts->ptime_prev = ts->ptime_prev_rollback; 5377 ts->steps--; 5378 ts->steprollback = PETSC_TRUE; 5379 PetscFunctionReturn(PETSC_SUCCESS); 5380 } 5381 5382 /*@ 5383 TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step 5384 5385 Not collective 5386 5387 Input Parameter: 5388 . ts - the `TS` context obtained from `TSCreate()` 5389 5390 Output Parameter: 5391 . flg - the rollback flag 5392 5393 Level: advanced 5394 5395 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()` 5396 @*/ 5397 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg) 5398 { 5399 PetscFunctionBegin; 5400 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5401 PetscAssertPointer(flg, 2); 5402 *flg = ts->steprollback; 5403 PetscFunctionReturn(PETSC_SUCCESS); 5404 } 5405 5406 /*@ 5407 TSGetStepResize - Get the internal flag indicating if the current step is after a resize. 5408 5409 Not collective 5410 5411 Input Parameter: 5412 . ts - the `TS` context obtained from `TSCreate()` 5413 5414 Output Parameter: 5415 . flg - the resize flag 5416 5417 Level: advanced 5418 5419 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()` 5420 @*/ 5421 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg) 5422 { 5423 PetscFunctionBegin; 5424 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5425 PetscAssertPointer(flg, 2); 5426 *flg = ts->stepresize; 5427 PetscFunctionReturn(PETSC_SUCCESS); 5428 } 5429 5430 /*@ 5431 TSGetStages - Get the number of stages and stage values 5432 5433 Input Parameter: 5434 . ts - the `TS` context obtained from `TSCreate()` 5435 5436 Output Parameters: 5437 + ns - the number of stages 5438 - Y - the current stage vectors 5439 5440 Level: advanced 5441 5442 Note: 5443 Both `ns` and `Y` can be `NULL`. 5444 5445 .seealso: [](ch_ts), `TS`, `TSCreate()` 5446 @*/ 5447 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5448 { 5449 PetscFunctionBegin; 5450 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5451 if (ns) PetscAssertPointer(ns, 2); 5452 if (Y) PetscAssertPointer(Y, 3); 5453 if (!ts->ops->getstages) { 5454 if (ns) *ns = 0; 5455 if (Y) *Y = NULL; 5456 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5457 PetscFunctionReturn(PETSC_SUCCESS); 5458 } 5459 5460 /*@C 5461 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5462 5463 Collective 5464 5465 Input Parameters: 5466 + ts - the `TS` context 5467 . t - current timestep 5468 . U - state vector 5469 . Udot - time derivative of state vector 5470 . shift - shift to apply, see note below 5471 - ctx - an optional user context 5472 5473 Output Parameters: 5474 + J - Jacobian matrix (not altered in this routine) 5475 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5476 5477 Level: intermediate 5478 5479 Notes: 5480 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5481 5482 dF/dU + shift*dF/dUdot 5483 5484 Most users should not need to explicitly call this routine, as it 5485 is used internally within the nonlinear solvers. 5486 5487 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5488 routine, then it will try to get the coloring from the matrix. This requires that the 5489 matrix have nonzero entries precomputed. 5490 5491 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5492 @*/ 5493 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5494 { 5495 SNES snes; 5496 MatFDColoring color; 5497 PetscBool hascolor, matcolor = PETSC_FALSE; 5498 5499 PetscFunctionBegin; 5500 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5501 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5502 if (!color) { 5503 DM dm; 5504 ISColoring iscoloring; 5505 5506 PetscCall(TSGetDM(ts, &dm)); 5507 PetscCall(DMHasColoring(dm, &hascolor)); 5508 if (hascolor && !matcolor) { 5509 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5510 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5511 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5512 PetscCall(MatFDColoringSetFromOptions(color)); 5513 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5514 PetscCall(ISColoringDestroy(&iscoloring)); 5515 } else { 5516 MatColoring mc; 5517 5518 PetscCall(MatColoringCreate(B, &mc)); 5519 PetscCall(MatColoringSetDistance(mc, 2)); 5520 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5521 PetscCall(MatColoringSetFromOptions(mc)); 5522 PetscCall(MatColoringApply(mc, &iscoloring)); 5523 PetscCall(MatColoringDestroy(&mc)); 5524 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5525 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 5526 PetscCall(MatFDColoringSetFromOptions(color)); 5527 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5528 PetscCall(ISColoringDestroy(&iscoloring)); 5529 } 5530 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5531 PetscCall(PetscObjectDereference((PetscObject)color)); 5532 } 5533 PetscCall(TSGetSNES(ts, &snes)); 5534 PetscCall(MatFDColoringApply(B, color, U, snes)); 5535 if (J != B) { 5536 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5537 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5538 } 5539 PetscFunctionReturn(PETSC_SUCCESS); 5540 } 5541 5542 /*@C 5543 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5544 5545 Input Parameters: 5546 + ts - the `TS` context 5547 - func - function called within `TSFunctionDomainError()` 5548 5549 Calling sequence of `func`: 5550 + ts - the `TS` context 5551 . time - the current time (of the stage) 5552 . state - the state to check if it is valid 5553 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable 5554 5555 Level: intermediate 5556 5557 Notes: 5558 If an implicit ODE solver is being used then, in addition to providing this routine, the 5559 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5560 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5561 Use `TSGetSNES()` to obtain the `SNES` object 5562 5563 Developer Notes: 5564 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5565 since one takes a function pointer and the other does not. 5566 5567 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5568 @*/ 5569 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept)) 5570 { 5571 PetscFunctionBegin; 5572 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5573 ts->functiondomainerror = func; 5574 PetscFunctionReturn(PETSC_SUCCESS); 5575 } 5576 5577 /*@ 5578 TSFunctionDomainError - Checks if the current state is valid 5579 5580 Input Parameters: 5581 + ts - the `TS` context 5582 . stagetime - time of the simulation 5583 - Y - state vector to check. 5584 5585 Output Parameter: 5586 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5587 5588 Level: developer 5589 5590 Note: 5591 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5592 to check if the current state is valid. 5593 5594 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5595 @*/ 5596 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5597 { 5598 PetscFunctionBegin; 5599 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5600 *accept = PETSC_TRUE; 5601 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5602 PetscFunctionReturn(PETSC_SUCCESS); 5603 } 5604 5605 /*@ 5606 TSClone - This function clones a time step `TS` object. 5607 5608 Collective 5609 5610 Input Parameter: 5611 . tsin - The input `TS` 5612 5613 Output Parameter: 5614 . tsout - The output `TS` (cloned) 5615 5616 Level: developer 5617 5618 Notes: 5619 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. 5620 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5621 5622 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 5623 .vb 5624 SNES snes_dup = NULL; 5625 TSGetSNES(ts,&snes_dup); 5626 TSSetSNES(ts,snes_dup); 5627 .ve 5628 5629 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5630 @*/ 5631 PetscErrorCode TSClone(TS tsin, TS *tsout) 5632 { 5633 TS t; 5634 SNES snes_start; 5635 DM dm; 5636 TSType type; 5637 5638 PetscFunctionBegin; 5639 PetscAssertPointer(tsin, 1); 5640 *tsout = NULL; 5641 5642 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5643 5644 /* General TS description */ 5645 t->numbermonitors = 0; 5646 t->monitorFrequency = 1; 5647 t->setupcalled = 0; 5648 t->ksp_its = 0; 5649 t->snes_its = 0; 5650 t->nwork = 0; 5651 t->rhsjacobian.time = PETSC_MIN_REAL; 5652 t->rhsjacobian.scale = 1.; 5653 t->ijacobian.shift = 1.; 5654 5655 PetscCall(TSGetSNES(tsin, &snes_start)); 5656 PetscCall(TSSetSNES(t, snes_start)); 5657 5658 PetscCall(TSGetDM(tsin, &dm)); 5659 PetscCall(TSSetDM(t, dm)); 5660 5661 t->adapt = tsin->adapt; 5662 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5663 5664 t->trajectory = tsin->trajectory; 5665 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5666 5667 t->event = tsin->event; 5668 if (t->event) t->event->refct++; 5669 5670 t->problem_type = tsin->problem_type; 5671 t->ptime = tsin->ptime; 5672 t->ptime_prev = tsin->ptime_prev; 5673 t->time_step = tsin->time_step; 5674 t->max_time = tsin->max_time; 5675 t->steps = tsin->steps; 5676 t->max_steps = tsin->max_steps; 5677 t->equation_type = tsin->equation_type; 5678 t->atol = tsin->atol; 5679 t->rtol = tsin->rtol; 5680 t->max_snes_failures = tsin->max_snes_failures; 5681 t->max_reject = tsin->max_reject; 5682 t->errorifstepfailed = tsin->errorifstepfailed; 5683 5684 PetscCall(TSGetType(tsin, &type)); 5685 PetscCall(TSSetType(t, type)); 5686 5687 t->vec_sol = NULL; 5688 5689 t->cfltime = tsin->cfltime; 5690 t->cfltime_local = tsin->cfltime_local; 5691 t->exact_final_time = tsin->exact_final_time; 5692 5693 t->ops[0] = tsin->ops[0]; 5694 5695 if (((PetscObject)tsin)->fortran_func_pointers) { 5696 PetscInt i; 5697 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5698 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5699 } 5700 *tsout = t; 5701 PetscFunctionReturn(PETSC_SUCCESS); 5702 } 5703 5704 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5705 { 5706 TS ts = (TS)ctx; 5707 5708 PetscFunctionBegin; 5709 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5710 PetscFunctionReturn(PETSC_SUCCESS); 5711 } 5712 5713 /*@ 5714 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5715 5716 Logically Collective 5717 5718 Input Parameter: 5719 . ts - the time stepping routine 5720 5721 Output Parameter: 5722 . flg - `PETSC_TRUE` if the multiply is likely correct 5723 5724 Options Database Key: 5725 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5726 5727 Level: advanced 5728 5729 Note: 5730 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5731 5732 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5733 @*/ 5734 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5735 { 5736 Mat J, B; 5737 TSRHSJacobianFn *func; 5738 void *ctx; 5739 5740 PetscFunctionBegin; 5741 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5742 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5743 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5744 PetscFunctionReturn(PETSC_SUCCESS); 5745 } 5746 5747 /*@ 5748 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5749 5750 Logically Collective 5751 5752 Input Parameter: 5753 . ts - the time stepping routine 5754 5755 Output Parameter: 5756 . flg - `PETSC_TRUE` if the multiply is likely correct 5757 5758 Options Database Key: 5759 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5760 5761 Level: advanced 5762 5763 Notes: 5764 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5765 5766 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5767 @*/ 5768 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5769 { 5770 Mat J, B; 5771 void *ctx; 5772 TSRHSJacobianFn *func; 5773 5774 PetscFunctionBegin; 5775 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5776 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5777 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5778 PetscFunctionReturn(PETSC_SUCCESS); 5779 } 5780 5781 /*@ 5782 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5783 5784 Logically Collective 5785 5786 Input Parameters: 5787 + ts - timestepping context 5788 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5789 5790 Options Database Key: 5791 . -ts_use_splitrhsfunction - <true,false> 5792 5793 Level: intermediate 5794 5795 Note: 5796 This is only for multirate methods 5797 5798 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5799 @*/ 5800 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5801 { 5802 PetscFunctionBegin; 5803 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5804 ts->use_splitrhsfunction = use_splitrhsfunction; 5805 PetscFunctionReturn(PETSC_SUCCESS); 5806 } 5807 5808 /*@ 5809 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5810 5811 Not Collective 5812 5813 Input Parameter: 5814 . ts - timestepping context 5815 5816 Output Parameter: 5817 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5818 5819 Level: intermediate 5820 5821 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5822 @*/ 5823 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5824 { 5825 PetscFunctionBegin; 5826 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5827 *use_splitrhsfunction = ts->use_splitrhsfunction; 5828 PetscFunctionReturn(PETSC_SUCCESS); 5829 } 5830 5831 /*@ 5832 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5833 5834 Logically Collective 5835 5836 Input Parameters: 5837 + ts - the time-stepper 5838 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5839 5840 Level: intermediate 5841 5842 Note: 5843 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5844 5845 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5846 @*/ 5847 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5848 { 5849 PetscFunctionBegin; 5850 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5851 ts->axpy_pattern = str; 5852 PetscFunctionReturn(PETSC_SUCCESS); 5853 } 5854 5855 /*@ 5856 TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested 5857 5858 Collective 5859 5860 Input Parameters: 5861 + ts - the time-stepper 5862 . n - number of the time points 5863 - time_points - array of the time points 5864 5865 Options Database Key: 5866 . -ts_eval_times <t0,...tn> - Sets the evaluation times 5867 5868 Level: intermediate 5869 5870 Notes: 5871 The elements in `time_points` must be all increasing. They correspond to the intermediate points for time integration. 5872 5873 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5874 5875 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may 5876 pressure the memory system when using a large number of time points. 5877 5878 .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()` 5879 @*/ 5880 PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal *time_points) 5881 { 5882 PetscBool is_sorted; 5883 5884 PetscFunctionBegin; 5885 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5886 if (ts->eval_times && n != ts->eval_times->num_time_points) { 5887 PetscCall(PetscFree(ts->eval_times->time_points)); 5888 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 5889 PetscCall(PetscMalloc1(n, &ts->eval_times->time_points)); 5890 } 5891 if (!ts->eval_times) { 5892 TSEvaluationTimes eval_times; 5893 PetscCall(PetscNew(&eval_times)); 5894 PetscCall(PetscMalloc1(n, &eval_times->time_points)); 5895 eval_times->reltol = 1e-6; 5896 eval_times->abstol = 10 * PETSC_MACHINE_EPSILON; 5897 eval_times->worktol = 0; 5898 ts->eval_times = eval_times; 5899 } 5900 ts->eval_times->num_time_points = n; 5901 PetscCall(PetscSortedReal(n, time_points, &is_sorted)); 5902 PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted"); 5903 PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n)); 5904 PetscFunctionReturn(PETSC_SUCCESS); 5905 } 5906 5907 /*@C 5908 TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()` 5909 5910 Not Collective 5911 5912 Input Parameter: 5913 . ts - the time-stepper 5914 5915 Output Parameters: 5916 + n - number of the time points 5917 - time_points - array of the time points 5918 5919 Level: beginner 5920 5921 Note: 5922 The values obtained are valid until the `TS` object is destroyed. 5923 5924 Both `n` and `time_points` can be `NULL`. 5925 5926 Also used to see time points set by `TSSetTimeSpan()`. 5927 5928 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()` 5929 @*/ 5930 PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[]) 5931 { 5932 PetscFunctionBegin; 5933 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5934 if (n) PetscAssertPointer(n, 2); 5935 if (time_points) PetscAssertPointer(time_points, 3); 5936 if (!ts->eval_times) { 5937 if (n) *n = 0; 5938 if (time_points) *time_points = NULL; 5939 } else { 5940 if (n) *n = ts->eval_times->num_time_points; 5941 if (time_points) *time_points = ts->eval_times->time_points; 5942 } 5943 PetscFunctionReturn(PETSC_SUCCESS); 5944 } 5945 5946 /*@C 5947 TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified 5948 5949 Input Parameter: 5950 . ts - the `TS` context obtained from `TSCreate()` 5951 5952 Output Parameters: 5953 + nsol - the number of solutions 5954 . sol_times - array of solution times corresponding to the solution vectors. See note below 5955 - Sols - the solution vectors 5956 5957 Level: intermediate 5958 5959 Notes: 5960 Both `nsol` and `Sols` can be `NULL`. 5961 5962 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()`. 5963 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times. 5964 5965 Also used to see view solutions requested by `TSSetTimeSpan()`. 5966 5967 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()` 5968 @*/ 5969 PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec **Sols) 5970 { 5971 PetscFunctionBegin; 5972 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5973 if (nsol) PetscAssertPointer(nsol, 2); 5974 if (sol_times) PetscAssertPointer(sol_times, 3); 5975 if (Sols) PetscAssertPointer(Sols, 4); 5976 if (!ts->eval_times) { 5977 if (nsol) *nsol = 0; 5978 if (sol_times) *sol_times = NULL; 5979 if (Sols) *Sols = NULL; 5980 } else { 5981 if (nsol) *nsol = ts->eval_times->sol_ctr; 5982 if (sol_times) *sol_times = ts->eval_times->sol_times; 5983 if (Sols) *Sols = ts->eval_times->sol_vecs; 5984 } 5985 PetscFunctionReturn(PETSC_SUCCESS); 5986 } 5987 5988 /*@ 5989 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 5990 5991 Collective 5992 5993 Input Parameters: 5994 + ts - the time-stepper 5995 . n - number of the time points (>=2) 5996 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5997 5998 Options Database Key: 5999 . -ts_time_span <t0,...tf> - Sets the time span 6000 6001 Level: intermediate 6002 6003 Notes: 6004 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. 6005 6006 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 6007 6008 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 6009 6010 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may 6011 pressure the memory system when using a large number of span points. 6012 6013 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()` 6014 @*/ 6015 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 6016 { 6017 PetscFunctionBegin; 6018 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6019 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 6020 PetscCall(TSSetEvaluationTimes(ts, n, span_times)); 6021 PetscCall(TSSetTime(ts, span_times[0])); 6022 PetscCall(TSSetMaxTime(ts, span_times[n - 1])); 6023 PetscFunctionReturn(PETSC_SUCCESS); 6024 } 6025 6026 /*@ 6027 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 6028 6029 Collective 6030 6031 Input Parameters: 6032 + ts - the `TS` context 6033 . J - Jacobian matrix (not altered in this routine) 6034 - B - newly computed Jacobian matrix to use with preconditioner 6035 6036 Level: intermediate 6037 6038 Notes: 6039 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 6040 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 6041 and multiple fields are involved. 6042 6043 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 6044 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 6045 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 6046 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 6047 6048 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 6049 @*/ 6050 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 6051 { 6052 MatColoring mc = NULL; 6053 ISColoring iscoloring = NULL; 6054 MatFDColoring matfdcoloring = NULL; 6055 6056 PetscFunctionBegin; 6057 /* Generate new coloring after eliminating zeros in the matrix */ 6058 PetscCall(MatEliminateZeros(B, PETSC_TRUE)); 6059 PetscCall(MatColoringCreate(B, &mc)); 6060 PetscCall(MatColoringSetDistance(mc, 2)); 6061 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 6062 PetscCall(MatColoringSetFromOptions(mc)); 6063 PetscCall(MatColoringApply(mc, &iscoloring)); 6064 PetscCall(MatColoringDestroy(&mc)); 6065 /* Replace the old coloring with the new one */ 6066 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 6067 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts)); 6068 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 6069 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 6070 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 6071 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 6072 PetscCall(ISColoringDestroy(&iscoloring)); 6073 PetscFunctionReturn(PETSC_SUCCESS); 6074 } 6075