1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscdmshell.h> 3 #include <petscdmda.h> 4 #include <petscviewer.h> 5 #include <petscdraw.h> 6 #include <petscconvest.h> 7 8 #define SkipSmallValue(a,b,tol) if (PetscAbsScalar(a)< tol || PetscAbsScalar(b)< tol) continue; 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 PetscValidCharPointer(default_type,2); 21 if (!((PetscObject)adapt)->type_name) { 22 PetscCall(TSAdaptSetType(adapt,default_type)); 23 } 24 PetscFunctionReturn(0); 25 } 26 27 /*@ 28 TSSetFromOptions - Sets various TS parameters from user options. 29 30 Collective on TS 31 32 Input Parameter: 33 . ts - the TS context obtained from TSCreate() 34 35 Options Database Keys: 36 + -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSALPHA, TSGLLE, TSSSP, TSGLEE, TSBSYMP, TSIRK 37 . -ts_save_trajectory - checkpoint the solution at each time-step 38 . -ts_max_time <time> - maximum time to compute to 39 . -ts_time_span <t0,...tf> - sets the time span, solutions are computed and stored for each indicated time 40 . -ts_max_steps <steps> - maximum number of time-steps to take 41 . -ts_init_time <time> - initial time to start computation 42 . -ts_final_time <time> - final time to compute to (deprecated: use -ts_max_time) 43 . -ts_dt <dt> - initial time step 44 . -ts_exact_final_time <stepover,interpolate,matchstep> - whether to stop at the exact given final time and how to compute the solution at that time 45 . -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed 46 . -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails 47 . -ts_error_if_step_fails <true,false> - Error if no step succeeds 48 . -ts_rtol <rtol> - relative tolerance for local truncation error 49 . -ts_atol <atol> - Absolute tolerance for local truncation error 50 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function 51 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - test the Jacobian at each iteration against finite difference with RHS function 52 . -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 53 . -ts_fd_color - Use finite differences with coloring to compute IJacobian 54 . -ts_monitor - print information at each timestep 55 . -ts_monitor_cancel - Cancel all monitors 56 . -ts_monitor_lg_solution - Monitor solution graphically 57 . -ts_monitor_lg_error - Monitor error graphically 58 . -ts_monitor_error - Monitors norm of error 59 . -ts_monitor_lg_timestep - Monitor timestep size graphically 60 . -ts_monitor_lg_timestep_log - Monitor log timestep size graphically 61 . -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically 62 . -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically 63 . -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically 64 . -ts_monitor_draw_solution - Monitor solution graphically 65 . -ts_monitor_draw_solution_phase <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom 66 . -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction() 67 . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep 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_envelope - determine maximum and minimum value of each component of the solution over the solution time 70 71 Notes: 72 See SNESSetFromOptions() and KSPSetFromOptions() for how to control the nonlinear and linear solves used by the time-stepper. 73 74 Certain SNES options get reset for each new nonlinear solver, for example -snes_lag_jacobian <its> and -snes_lag_preconditioner <its>, in order 75 to retain them over the multiple nonlinear solves that TS uses you mush also provide -snes_lag_jacobian_persists true and 76 -snes_lag_preconditioner_persists true 77 78 Developer Note: 79 We should unify all the -ts_monitor options in the way that -xxx_view has been unified 80 81 Level: beginner 82 83 .seealso: `TSGetType()` 84 @*/ 85 PetscErrorCode TSSetFromOptions(TS ts) 86 { 87 PetscBool opt,flg,tflg; 88 char monfilename[PETSC_MAX_PATH_LEN]; 89 PetscReal time_step,tspan[100]; 90 PetscInt nt = PETSC_STATIC_ARRAY_LENGTH(tspan); 91 TSExactFinalTimeOption eftopt; 92 char dir[16]; 93 TSIFunction ifun; 94 const char *defaultType; 95 char typeName[256]; 96 97 PetscFunctionBegin; 98 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 99 100 PetscCall(TSRegisterAll()); 101 PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL)); 102 103 PetscObjectOptionsBegin((PetscObject)ts); 104 if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name; 105 else defaultType = ifun ? TSBEULER : TSEULER; 106 PetscCall(PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt)); 107 if (opt) { 108 PetscCall(TSSetType(ts,typeName)); 109 } else { 110 PetscCall(TSSetType(ts,defaultType)); 111 } 112 113 /* Handle generic TS options */ 114 PetscCall(PetscOptionsDeprecated("-ts_final_time","-ts_max_time","3.10",NULL)); 115 PetscCall(PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL)); 116 PetscCall(PetscOptionsRealArray("-ts_time_span","Time span","TSSetTimeSpan",tspan,&nt,&flg)); 117 if (flg) PetscCall(TSSetTimeSpan(ts,nt,tspan)); 118 PetscCall(PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL)); 119 PetscCall(PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL)); 120 PetscCall(PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg)); 121 if (flg) PetscCall(TSSetTimeStep(ts,time_step)); 122 PetscCall(PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg)); 123 if (flg) PetscCall(TSSetExactFinalTime(ts,eftopt)); 124 PetscCall(PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL)); 125 PetscCall(PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL)); 126 PetscCall(PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL)); 127 PetscCall(PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL)); 128 PetscCall(PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL)); 129 130 PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL)); 131 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)); 132 PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction","Use the split RHS function for multirate solvers ","TSSetUseSplitRHSFunction",ts->use_splitrhsfunction,&ts->use_splitrhsfunction,NULL)); 133 #if defined(PETSC_HAVE_SAWS) 134 { 135 PetscBool set; 136 flg = PETSC_FALSE; 137 PetscCall(PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set)); 138 if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts,flg)); 139 } 140 #endif 141 142 /* Monitor options */ 143 PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL)); 144 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL)); 145 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_extreme","Monitor extreme values of the solution","TSMonitorExtreme",TSMonitorExtreme,NULL)); 146 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL)); 147 PetscCall(TSMonitorSetFromOptions(ts,"-ts_dmswarm_monitor_moments","Monitor moments of particle distribution","TSDMSwarmMonitorMoments",TSDMSwarmMonitorMoments,NULL)); 148 149 PetscCall(PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",NULL,monfilename,sizeof(monfilename),&flg)); 150 if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts,monfilename)); 151 152 PetscCall(PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt)); 153 if (opt) { 154 PetscInt howoften = 1; 155 DM dm; 156 PetscBool net; 157 158 PetscCall(PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL)); 159 PetscCall(TSGetDM(ts,&dm)); 160 PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMNETWORK,&net)); 161 if (net) { 162 TSMonitorLGCtxNetwork ctx; 163 PetscCall(TSMonitorLGCtxNetworkCreate(ts,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx)); 164 PetscCall(TSMonitorSet(ts,TSMonitorLGCtxNetworkSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxNetworkDestroy)); 165 PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy","Plot the solution with a semi-log axis","",ctx->semilogy,&ctx->semilogy,NULL)); 166 } else { 167 TSMonitorLGCtx ctx; 168 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 169 PetscCall(TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 170 } 171 } 172 173 PetscCall(PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt)); 174 if (opt) { 175 TSMonitorLGCtx ctx; 176 PetscInt howoften = 1; 177 178 PetscCall(PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL)); 179 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 180 PetscCall(TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 181 } 182 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL)); 183 184 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt)); 185 if (opt) { 186 TSMonitorLGCtx ctx; 187 PetscInt howoften = 1; 188 189 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL)); 190 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 191 PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 192 } 193 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt)); 194 if (opt) { 195 TSMonitorLGCtx ctx; 196 PetscInt howoften = 1; 197 198 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL)); 199 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 200 PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 201 ctx->semilogy = PETSC_TRUE; 202 } 203 204 PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt)); 205 if (opt) { 206 TSMonitorLGCtx ctx; 207 PetscInt howoften = 1; 208 209 PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL)); 210 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 211 PetscCall(TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 212 } 213 PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt)); 214 if (opt) { 215 TSMonitorLGCtx ctx; 216 PetscInt howoften = 1; 217 218 PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL)); 219 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 220 PetscCall(TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 221 } 222 PetscCall(PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt)); 223 if (opt) { 224 TSMonitorSPEigCtx ctx; 225 PetscInt howoften = 1; 226 227 PetscCall(PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL)); 228 PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 229 PetscCall(TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy)); 230 } 231 PetscCall(PetscOptionsName("-ts_monitor_sp_swarm","Display particle phase from the DMSwarm","TSMonitorSPSwarm",&opt)); 232 if (opt) { 233 TSMonitorSPCtx ctx; 234 PetscInt howoften = 1, retain = 0; 235 PetscBool phase = PETSC_TRUE, create = PETSC_TRUE; 236 237 for (PetscInt i = 0; i < ts->numbermonitors; ++i) if (ts->monitor[i] == TSMonitorSPSwarmSolution) {create = PETSC_FALSE;break;} 238 if (create) { 239 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm","Display particles phase from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL)); 240 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL)); 241 PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL)); 242 PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject) ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, &ctx)); 243 PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void**))TSMonitorSPCtxDestroy)); 244 } 245 } 246 opt = PETSC_FALSE; 247 PetscCall(PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt)); 248 if (opt) { 249 TSMonitorDrawCtx ctx; 250 PetscInt howoften = 1; 251 252 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL)); 253 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 254 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 255 } 256 opt = PETSC_FALSE; 257 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt)); 258 if (opt) { 259 TSMonitorDrawCtx ctx; 260 PetscReal bounds[4]; 261 PetscInt n = 4; 262 PetscDraw draw; 263 PetscDrawAxis axis; 264 265 PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL)); 266 PetscCheck(n == 4,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field"); 267 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx)); 268 PetscCall(PetscViewerDrawGetDraw(ctx->viewer,0,&draw)); 269 PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis)); 270 PetscCall(PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3])); 271 PetscCall(PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2")); 272 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 273 } 274 opt = PETSC_FALSE; 275 PetscCall(PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt)); 276 if (opt) { 277 TSMonitorDrawCtx ctx; 278 PetscInt howoften = 1; 279 280 PetscCall(PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL)); 281 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 282 PetscCall(TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 283 } 284 opt = PETSC_FALSE; 285 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt)); 286 if (opt) { 287 TSMonitorDrawCtx ctx; 288 PetscInt howoften = 1; 289 290 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL)); 291 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 292 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 293 } 294 295 opt = PETSC_FALSE; 296 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)); 297 if (flg) { 298 const char *ptr,*ptr2; 299 char *filetemplate; 300 PetscCheck(monfilename[0],PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts"); 301 /* Do some cursory validation of the input. */ 302 PetscCall(PetscStrstr(monfilename,"%",(char**)&ptr)); 303 PetscCheck(ptr,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts"); 304 for (ptr++; ptr && *ptr; ptr++) { 305 PetscCall(PetscStrchr("DdiouxX",*ptr,(char**)&ptr2)); 306 PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'),PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03" PetscInt_FMT ".vts"); 307 if (ptr2) break; 308 } 309 PetscCall(PetscStrallocpy(monfilename,&filetemplate)); 310 PetscCall(TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy)); 311 } 312 313 PetscCall(PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,sizeof(dir),&flg)); 314 if (flg) { 315 TSMonitorDMDARayCtx *rayctx; 316 int ray = 0; 317 DMDirection ddir; 318 DM da; 319 PetscMPIInt rank; 320 321 PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir); 322 if (dir[0] == 'x') ddir = DM_X; 323 else if (dir[0] == 'y') ddir = DM_Y; 324 else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir); 325 sscanf(dir+2,"%d",&ray); 326 327 PetscCall(PetscInfo(((PetscObject)ts),"Displaying DMDA ray %c = %d\n",dir[0],ray)); 328 PetscCall(PetscNew(&rayctx)); 329 PetscCall(TSGetDM(ts,&da)); 330 PetscCall(DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter)); 331 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank)); 332 if (rank == 0) { 333 PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF,NULL,NULL,0,0,600,300,&rayctx->viewer)); 334 } 335 rayctx->lgctx = NULL; 336 PetscCall(TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy)); 337 } 338 PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,sizeof(dir),&flg)); 339 if (flg) { 340 TSMonitorDMDARayCtx *rayctx; 341 int ray = 0; 342 DMDirection ddir; 343 DM da; 344 PetscInt howoften = 1; 345 346 PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir); 347 if (dir[0] == 'x') ddir = DM_X; 348 else if (dir[0] == 'y') ddir = DM_Y; 349 else SETERRQ(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir); 350 sscanf(dir+2, "%d", &ray); 351 352 PetscCall(PetscInfo(((PetscObject) ts),"Displaying LG DMDA ray %c = %d\n", dir[0], ray)); 353 PetscCall(PetscNew(&rayctx)); 354 PetscCall(TSGetDM(ts, &da)); 355 PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter)); 356 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx)); 357 PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy)); 358 } 359 360 PetscCall(PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt)); 361 if (opt) { 362 TSMonitorEnvelopeCtx ctx; 363 364 PetscCall(TSMonitorEnvelopeCtxCreate(ts,&ctx)); 365 PetscCall(TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy)); 366 } 367 flg = PETSC_FALSE; 368 PetscCall(PetscOptionsBool("-ts_monitor_cancel","Remove all monitors","TSMonitorCancel",flg,&flg,&opt)); 369 if (opt && flg) PetscCall(TSMonitorCancel(ts)); 370 371 flg = PETSC_FALSE; 372 PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL)); 373 if (flg) { 374 DM dm; 375 DMTS tdm; 376 377 PetscCall(TSGetDM(ts, &dm)); 378 PetscCall(DMGetDMTS(dm, &tdm)); 379 tdm->ijacobianctx = NULL; 380 PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL)); 381 PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n")); 382 } 383 384 /* Handle specific TS options */ 385 if (ts->ops->setfromoptions) PetscCall((*ts->ops->setfromoptions)(PetscOptionsObject,ts)); 386 387 /* Handle TSAdapt options */ 388 PetscCall(TSGetAdapt(ts,&ts->adapt)); 389 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 390 PetscCall(TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt)); 391 392 /* TS trajectory must be set after TS, since it may use some TS options above */ 393 tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE; 394 PetscCall(PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL)); 395 if (tflg) PetscCall(TSSetSaveTrajectory(ts)); 396 397 PetscCall(TSAdjointSetFromOptions(PetscOptionsObject,ts)); 398 399 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 400 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts)); 401 PetscOptionsEnd(); 402 403 if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory,ts)); 404 405 /* why do we have to do this here and not during TSSetUp? */ 406 PetscCall(TSGetSNES(ts,&ts->snes)); 407 if (ts->problem_type == TS_LINEAR) { 408 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&flg,SNESKSPONLY,SNESKSPTRANSPOSEONLY,"")); 409 if (!flg) PetscCall(SNESSetType(ts->snes,SNESKSPONLY)); 410 } 411 PetscCall(SNESSetFromOptions(ts->snes)); 412 PetscFunctionReturn(0); 413 } 414 415 /*@ 416 TSGetTrajectory - Gets the trajectory from a TS if it exists 417 418 Collective on TS 419 420 Input Parameters: 421 . ts - the TS context obtained from TSCreate() 422 423 Output Parameters: 424 . tr - the TSTrajectory object, if it exists 425 426 Note: This routine should be called after all TS options have been set 427 428 Level: advanced 429 430 .seealso: `TSGetTrajectory()`, `TSAdjointSolve()`, `TSTrajectory`, `TSTrajectoryCreate()` 431 432 @*/ 433 PetscErrorCode TSGetTrajectory(TS ts,TSTrajectory *tr) 434 { 435 PetscFunctionBegin; 436 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 437 *tr = ts->trajectory; 438 PetscFunctionReturn(0); 439 } 440 441 /*@ 442 TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object 443 444 Collective on TS 445 446 Input Parameter: 447 . ts - the TS context obtained from TSCreate() 448 449 Options Database: 450 + -ts_save_trajectory - saves the trajectory to a file 451 - -ts_trajectory_type type - set trajectory type 452 453 Note: This routine should be called after all TS options have been set 454 455 The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and 456 MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m 457 458 Level: intermediate 459 460 .seealso: `TSGetTrajectory()`, `TSAdjointSolve()` 461 462 @*/ 463 PetscErrorCode TSSetSaveTrajectory(TS ts) 464 { 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 467 if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory)); 468 PetscFunctionReturn(0); 469 } 470 471 /*@ 472 TSResetTrajectory - Destroys and recreates the internal TSTrajectory object 473 474 Collective on TS 475 476 Input Parameters: 477 . ts - the TS context obtained from TSCreate() 478 479 Level: intermediate 480 481 .seealso: `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()` 482 483 @*/ 484 PetscErrorCode TSResetTrajectory(TS ts) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 488 if (ts->trajectory) { 489 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 490 PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory)); 491 } 492 PetscFunctionReturn(0); 493 } 494 495 /*@ 496 TSRemoveTrajectory - Destroys and removes the internal TSTrajectory object from TS 497 498 Collective on TS 499 500 Input Parameters: 501 . ts - the TS context obtained from TSCreate() 502 503 Level: intermediate 504 505 .seealso: `TSResetTrajectory()`, `TSAdjointSolve()` 506 507 @*/ 508 PetscErrorCode TSRemoveTrajectory(TS ts) 509 { 510 PetscFunctionBegin; 511 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 512 if (ts->trajectory) { 513 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 514 } 515 PetscFunctionReturn(0); 516 } 517 518 /*@ 519 TSComputeRHSJacobian - Computes the Jacobian matrix that has been 520 set with TSSetRHSJacobian(). 521 522 Collective on TS 523 524 Input Parameters: 525 + ts - the TS context 526 . t - current timestep 527 - U - input vector 528 529 Output Parameters: 530 + A - Jacobian matrix 531 - B - optional preconditioning matrix 532 533 Notes: 534 Most users should not need to explicitly call this routine, as it 535 is used internally within the nonlinear solvers. 536 537 Level: developer 538 539 .seealso: `TSSetRHSJacobian()`, `KSPSetOperators()` 540 @*/ 541 PetscErrorCode TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B) 542 { 543 PetscObjectState Ustate; 544 PetscObjectId Uid; 545 DM dm; 546 DMTS tsdm; 547 TSRHSJacobian rhsjacobianfunc; 548 void *ctx; 549 TSRHSFunction rhsfunction; 550 551 PetscFunctionBegin; 552 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 553 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 554 PetscCheckSameComm(ts,1,U,3); 555 PetscCall(TSGetDM(ts,&dm)); 556 PetscCall(DMGetDMTS(dm,&tsdm)); 557 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 558 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx)); 559 PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate)); 560 PetscCall(PetscObjectGetId((PetscObject)U,&Uid)); 561 562 if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(0); 563 564 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); 565 if (rhsjacobianfunc) { 566 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B)); 567 PetscStackPush("TS user Jacobian function"); 568 PetscCall((*rhsjacobianfunc)(ts,t,U,A,B,ctx)); 569 PetscStackPop; 570 ts->rhsjacs++; 571 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B)); 572 } else { 573 PetscCall(MatZeroEntries(A)); 574 if (B && A != B) PetscCall(MatZeroEntries(B)); 575 } 576 ts->rhsjacobian.time = t; 577 ts->rhsjacobian.shift = 0; 578 ts->rhsjacobian.scale = 1.; 579 PetscCall(PetscObjectGetId((PetscObject)U,&ts->rhsjacobian.Xid)); 580 PetscCall(PetscObjectStateGet((PetscObject)U,&ts->rhsjacobian.Xstate)); 581 PetscFunctionReturn(0); 582 } 583 584 /*@ 585 TSComputeRHSFunction - Evaluates the right-hand-side function. 586 587 Collective on TS 588 589 Input Parameters: 590 + ts - the TS context 591 . t - current time 592 - U - state vector 593 594 Output Parameter: 595 . y - right hand side 596 597 Note: 598 Most users should not need to explicitly call this routine, as it 599 is used internally within the nonlinear solvers. 600 601 Level: developer 602 603 .seealso: `TSSetRHSFunction()`, `TSComputeIFunction()` 604 @*/ 605 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y) 606 { 607 TSRHSFunction rhsfunction; 608 TSIFunction ifunction; 609 void *ctx; 610 DM dm; 611 612 PetscFunctionBegin; 613 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 614 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 615 PetscValidHeaderSpecific(y,VEC_CLASSID,4); 616 PetscCall(TSGetDM(ts,&dm)); 617 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,&ctx)); 618 PetscCall(DMTSGetIFunction(dm,&ifunction,NULL)); 619 620 PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()"); 621 622 if (rhsfunction) { 623 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,y,0)); 624 PetscCall(VecLockReadPush(U)); 625 PetscStackPush("TS user right-hand-side function"); 626 PetscCall((*rhsfunction)(ts,t,U,y,ctx)); 627 PetscStackPop; 628 PetscCall(VecLockReadPop(U)); 629 ts->rhsfuncs++; 630 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,y,0)); 631 } else { 632 PetscCall(VecZeroEntries(y)); 633 } 634 PetscFunctionReturn(0); 635 } 636 637 /*@ 638 TSComputeSolutionFunction - Evaluates the solution function. 639 640 Collective on TS 641 642 Input Parameters: 643 + ts - the TS context 644 - t - current time 645 646 Output Parameter: 647 . U - the solution 648 649 Note: 650 Most users should not need to explicitly call this routine, as it 651 is used internally within the nonlinear solvers. 652 653 Level: developer 654 655 .seealso: `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()` 656 @*/ 657 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U) 658 { 659 TSSolutionFunction solutionfunction; 660 void *ctx; 661 DM dm; 662 663 PetscFunctionBegin; 664 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 665 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 666 PetscCall(TSGetDM(ts,&dm)); 667 PetscCall(DMTSGetSolutionFunction(dm,&solutionfunction,&ctx)); 668 669 if (solutionfunction) { 670 PetscStackPush("TS user solution function"); 671 PetscCall((*solutionfunction)(ts,t,U,ctx)); 672 PetscStackPop; 673 } 674 PetscFunctionReturn(0); 675 } 676 /*@ 677 TSComputeForcingFunction - Evaluates the forcing function. 678 679 Collective on TS 680 681 Input Parameters: 682 + ts - the TS context 683 - t - current time 684 685 Output Parameter: 686 . U - the function value 687 688 Note: 689 Most users should not need to explicitly call this routine, as it 690 is used internally within the nonlinear solvers. 691 692 Level: developer 693 694 .seealso: `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()` 695 @*/ 696 PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U) 697 { 698 void *ctx; 699 DM dm; 700 TSForcingFunction forcing; 701 702 PetscFunctionBegin; 703 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 704 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 705 PetscCall(TSGetDM(ts,&dm)); 706 PetscCall(DMTSGetForcingFunction(dm,&forcing,&ctx)); 707 708 if (forcing) { 709 PetscStackPush("TS user forcing function"); 710 PetscCall((*forcing)(ts,t,U,ctx)); 711 PetscStackPop; 712 } 713 PetscFunctionReturn(0); 714 } 715 716 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs) 717 { 718 Vec F; 719 720 PetscFunctionBegin; 721 *Frhs = NULL; 722 PetscCall(TSGetIFunction(ts,&F,NULL,NULL)); 723 if (!ts->Frhs) { 724 PetscCall(VecDuplicate(F,&ts->Frhs)); 725 } 726 *Frhs = ts->Frhs; 727 PetscFunctionReturn(0); 728 } 729 730 PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs) 731 { 732 Mat A,B; 733 TSIJacobian ijacobian; 734 735 PetscFunctionBegin; 736 if (Arhs) *Arhs = NULL; 737 if (Brhs) *Brhs = NULL; 738 PetscCall(TSGetIJacobian(ts,&A,&B,&ijacobian,NULL)); 739 if (Arhs) { 740 if (!ts->Arhs) { 741 if (ijacobian) { 742 PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs)); 743 PetscCall(TSSetMatStructure(ts,SAME_NONZERO_PATTERN)); 744 } else { 745 ts->Arhs = A; 746 PetscCall(PetscObjectReference((PetscObject)A)); 747 } 748 } else { 749 PetscBool flg; 750 PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg)); 751 /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */ 752 if (flg && !ijacobian && ts->Arhs == ts->Brhs) { 753 PetscCall(PetscObjectDereference((PetscObject)ts->Arhs)); 754 ts->Arhs = A; 755 PetscCall(PetscObjectReference((PetscObject)A)); 756 } 757 } 758 *Arhs = ts->Arhs; 759 } 760 if (Brhs) { 761 if (!ts->Brhs) { 762 if (A != B) { 763 if (ijacobian) { 764 PetscCall(MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs)); 765 } else { 766 ts->Brhs = B; 767 PetscCall(PetscObjectReference((PetscObject)B)); 768 } 769 } else { 770 PetscCall(PetscObjectReference((PetscObject)ts->Arhs)); 771 ts->Brhs = ts->Arhs; 772 } 773 } 774 *Brhs = ts->Brhs; 775 } 776 PetscFunctionReturn(0); 777 } 778 779 /*@ 780 TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0 781 782 Collective on TS 783 784 Input Parameters: 785 + ts - the TS context 786 . t - current time 787 . U - state vector 788 . Udot - time derivative of state vector 789 - imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate 790 791 Output Parameter: 792 . Y - right hand side 793 794 Note: 795 Most users should not need to explicitly call this routine, as it 796 is used internally within the nonlinear solvers. 797 798 If the user did did not write their equations in implicit form, this 799 function recasts them in implicit form. 800 801 Level: developer 802 803 .seealso: `TSSetIFunction()`, `TSComputeRHSFunction()` 804 @*/ 805 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex) 806 { 807 TSIFunction ifunction; 808 TSRHSFunction rhsfunction; 809 void *ctx; 810 DM dm; 811 812 PetscFunctionBegin; 813 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 814 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 815 PetscValidHeaderSpecific(Udot,VEC_CLASSID,4); 816 PetscValidHeaderSpecific(Y,VEC_CLASSID,5); 817 818 PetscCall(TSGetDM(ts,&dm)); 819 PetscCall(DMTSGetIFunction(dm,&ifunction,&ctx)); 820 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 821 822 PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()"); 823 824 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y)); 825 if (ifunction) { 826 PetscStackPush("TS user implicit function"); 827 PetscCall((*ifunction)(ts,t,U,Udot,Y,ctx)); 828 PetscStackPop; 829 ts->ifuncs++; 830 } 831 if (imex) { 832 if (!ifunction) { 833 PetscCall(VecCopy(Udot,Y)); 834 } 835 } else if (rhsfunction) { 836 if (ifunction) { 837 Vec Frhs; 838 PetscCall(TSGetRHSVec_Private(ts,&Frhs)); 839 PetscCall(TSComputeRHSFunction(ts,t,U,Frhs)); 840 PetscCall(VecAXPY(Y,-1,Frhs)); 841 } else { 842 PetscCall(TSComputeRHSFunction(ts,t,U,Y)); 843 PetscCall(VecAYPX(Y,-1,Udot)); 844 } 845 } 846 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y)); 847 PetscFunctionReturn(0); 848 } 849 850 /* 851 TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call TSComputeRHSJacobian() on it. 852 853 Note: 854 This routine is needed when one switches from TSComputeIJacobian() to TSComputeRHSJacobian() because the Jacobian matrix may be shifted or scaled in TSComputeIJacobian(). 855 856 */ 857 static PetscErrorCode TSRecoverRHSJacobian(TS ts,Mat A,Mat B) 858 { 859 PetscFunctionBegin; 860 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 861 PetscCheck(A == ts->Arhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Amat"); 862 PetscCheck(B == ts->Brhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Bmat"); 863 864 if (ts->rhsjacobian.shift) PetscCall(MatShift(A,-ts->rhsjacobian.shift)); 865 if (ts->rhsjacobian.scale == -1.) { 866 PetscCall(MatScale(A,-1)); 867 } 868 if (B && B == ts->Brhs && A != B) { 869 if (ts->rhsjacobian.shift) PetscCall(MatShift(B,-ts->rhsjacobian.shift)); 870 if (ts->rhsjacobian.scale == -1.) { 871 PetscCall(MatScale(B,-1)); 872 } 873 } 874 ts->rhsjacobian.shift = 0; 875 ts->rhsjacobian.scale = 1.; 876 PetscFunctionReturn(0); 877 } 878 879 /*@ 880 TSComputeIJacobian - Evaluates the Jacobian of the DAE 881 882 Collective on TS 883 884 Input 885 Input Parameters: 886 + ts - the TS context 887 . t - current timestep 888 . U - state vector 889 . Udot - time derivative of state vector 890 . shift - shift to apply, see note below 891 - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate 892 893 Output Parameters: 894 + A - Jacobian matrix 895 - B - matrix from which the preconditioner is constructed; often the same as A 896 897 Notes: 898 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 899 900 dF/dU + shift*dF/dUdot 901 902 Most users should not need to explicitly call this routine, as it 903 is used internally within the nonlinear solvers. 904 905 Level: developer 906 907 .seealso: `TSSetIJacobian()` 908 @*/ 909 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,PetscBool imex) 910 { 911 TSIJacobian ijacobian; 912 TSRHSJacobian rhsjacobian; 913 DM dm; 914 void *ctx; 915 916 PetscFunctionBegin; 917 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 918 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 919 PetscValidHeaderSpecific(Udot,VEC_CLASSID,4); 920 PetscValidPointer(A,6); 921 PetscValidHeaderSpecific(A,MAT_CLASSID,6); 922 PetscValidPointer(B,7); 923 PetscValidHeaderSpecific(B,MAT_CLASSID,7); 924 925 PetscCall(TSGetDM(ts,&dm)); 926 PetscCall(DMTSGetIJacobian(dm,&ijacobian,&ctx)); 927 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL)); 928 929 PetscCheck(rhsjacobian || ijacobian,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()"); 930 931 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B)); 932 if (ijacobian) { 933 PetscStackPush("TS user implicit Jacobian"); 934 PetscCall((*ijacobian)(ts,t,U,Udot,shift,A,B,ctx)); 935 ts->ijacs++; 936 PetscStackPop; 937 } 938 if (imex) { 939 if (!ijacobian) { /* system was written as Udot = G(t,U) */ 940 PetscBool assembled; 941 if (rhsjacobian) { 942 Mat Arhs = NULL; 943 PetscCall(TSGetRHSMats_Private(ts,&Arhs,NULL)); 944 if (A == Arhs) { 945 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 */ 946 ts->rhsjacobian.time = PETSC_MIN_REAL; 947 } 948 } 949 PetscCall(MatZeroEntries(A)); 950 PetscCall(MatAssembled(A,&assembled)); 951 if (!assembled) { 952 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 953 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 954 } 955 PetscCall(MatShift(A,shift)); 956 if (A != B) { 957 PetscCall(MatZeroEntries(B)); 958 PetscCall(MatAssembled(B,&assembled)); 959 if (!assembled) { 960 PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 961 PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 962 } 963 PetscCall(MatShift(B,shift)); 964 } 965 } 966 } else { 967 Mat Arhs = NULL,Brhs = NULL; 968 if (rhsjacobian) { /* RHSJacobian needs to be converted to part of IJacobian if exists */ 969 PetscCall(TSGetRHSMats_Private(ts,&Arhs,&Brhs)); 970 } 971 if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */ 972 PetscObjectState Ustate; 973 PetscObjectId Uid; 974 TSRHSFunction rhsfunction; 975 976 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 977 PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate)); 978 PetscCall(PetscObjectGetId((PetscObject)U,&Uid)); 979 if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) && ts->rhsjacobian.scale == -1.) { /* No need to recompute RHSJacobian */ 980 PetscCall(MatShift(A,shift-ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */ 981 if (A != B) { 982 PetscCall(MatShift(B,shift-ts->rhsjacobian.shift)); 983 } 984 } else { 985 PetscBool flg; 986 987 if (ts->rhsjacobian.reuse) { /* Undo the damage */ 988 /* MatScale has a short path for this case. 989 However, this code path is taken the first time TSComputeRHSJacobian is called 990 and the matrices have not been assembled yet */ 991 PetscCall(TSRecoverRHSJacobian(ts,A,B)); 992 } 993 PetscCall(TSComputeRHSJacobian(ts,t,U,A,B)); 994 PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg)); 995 /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */ 996 if (!flg) { 997 PetscCall(MatScale(A,-1)); 998 PetscCall(MatShift(A,shift)); 999 } 1000 if (A != B) { 1001 PetscCall(MatScale(B,-1)); 1002 PetscCall(MatShift(B,shift)); 1003 } 1004 } 1005 ts->rhsjacobian.scale = -1; 1006 ts->rhsjacobian.shift = shift; 1007 } else if (Arhs) { /* Both IJacobian and RHSJacobian */ 1008 if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */ 1009 PetscCall(MatZeroEntries(A)); 1010 PetscCall(MatShift(A,shift)); 1011 if (A != B) { 1012 PetscCall(MatZeroEntries(B)); 1013 PetscCall(MatShift(B,shift)); 1014 } 1015 } 1016 PetscCall(TSComputeRHSJacobian(ts,t,U,Arhs,Brhs)); 1017 PetscCall(MatAXPY(A,-1,Arhs,ts->axpy_pattern)); 1018 if (A != B) { 1019 PetscCall(MatAXPY(B,-1,Brhs,ts->axpy_pattern)); 1020 } 1021 } 1022 } 1023 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B)); 1024 PetscFunctionReturn(0); 1025 } 1026 1027 /*@C 1028 TSSetRHSFunction - Sets the routine for evaluating the function, 1029 where U_t = G(t,u). 1030 1031 Logically Collective on TS 1032 1033 Input Parameters: 1034 + ts - the TS context obtained from TSCreate() 1035 . r - vector to put the computed right hand side (or NULL to have it created) 1036 . f - routine for evaluating the right-hand-side function 1037 - ctx - [optional] user-defined context for private data for the 1038 function evaluation routine (may be NULL) 1039 1040 Calling sequence of f: 1041 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec F,void *ctx); 1042 1043 + ts - timestep context 1044 . t - current timestep 1045 . u - input vector 1046 . F - function vector 1047 - ctx - [optional] user-defined function context 1048 1049 Level: beginner 1050 1051 Notes: 1052 You must call this function or TSSetIFunction() to define your ODE. You cannot use this function when solving a DAE. 1053 1054 .seealso: `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()` 1055 @*/ 1056 PetscErrorCode TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx) 1057 { 1058 SNES snes; 1059 Vec ralloc = NULL; 1060 DM dm; 1061 1062 PetscFunctionBegin; 1063 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1064 if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2); 1065 1066 PetscCall(TSGetDM(ts,&dm)); 1067 PetscCall(DMTSSetRHSFunction(dm,f,ctx)); 1068 PetscCall(TSGetSNES(ts,&snes)); 1069 if (!r && !ts->dm && ts->vec_sol) { 1070 PetscCall(VecDuplicate(ts->vec_sol,&ralloc)); 1071 r = ralloc; 1072 } 1073 PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts)); 1074 PetscCall(VecDestroy(&ralloc)); 1075 PetscFunctionReturn(0); 1076 } 1077 1078 /*@C 1079 TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE 1080 1081 Logically Collective on TS 1082 1083 Input Parameters: 1084 + ts - the TS context obtained from TSCreate() 1085 . f - routine for evaluating the solution 1086 - ctx - [optional] user-defined context for private data for the 1087 function evaluation routine (may be NULL) 1088 1089 Calling sequence of f: 1090 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,void *ctx); 1091 1092 + t - current timestep 1093 . u - output vector 1094 - ctx - [optional] user-defined function context 1095 1096 Options Database: 1097 + -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided TSSetSolutionFunction() 1098 - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction() 1099 1100 Notes: 1101 This routine is used for testing accuracy of time integration schemes when you already know the solution. 1102 If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to 1103 create closed-form solutions with non-physical forcing terms. 1104 1105 For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history. 1106 1107 Level: beginner 1108 1109 .seealso: `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()` 1110 @*/ 1111 PetscErrorCode TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx) 1112 { 1113 DM dm; 1114 1115 PetscFunctionBegin; 1116 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1117 PetscCall(TSGetDM(ts,&dm)); 1118 PetscCall(DMTSSetSolutionFunction(dm,f,ctx)); 1119 PetscFunctionReturn(0); 1120 } 1121 1122 /*@C 1123 TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE 1124 1125 Logically Collective on TS 1126 1127 Input Parameters: 1128 + ts - the TS context obtained from TSCreate() 1129 . func - routine for evaluating the forcing function 1130 - ctx - [optional] user-defined context for private data for the 1131 function evaluation routine (may be NULL) 1132 1133 Calling sequence of func: 1134 $ PetscErrorCode func (TS ts,PetscReal t,Vec f,void *ctx); 1135 1136 + t - current timestep 1137 . f - output vector 1138 - ctx - [optional] user-defined function context 1139 1140 Notes: 1141 This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to 1142 create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the 1143 definition of the problem you are solving and hence possibly introducing bugs. 1144 1145 This replaces the ODE F(u,u_t,t) = 0 the TS is solving with F(u,u_t,t) - func(t) = 0 1146 1147 This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the 1148 parameters can be passed in the ctx variable. 1149 1150 For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history. 1151 1152 Level: beginner 1153 1154 .seealso: `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetSolutionFunction()` 1155 @*/ 1156 PetscErrorCode TSSetForcingFunction(TS ts,TSForcingFunction func,void *ctx) 1157 { 1158 DM dm; 1159 1160 PetscFunctionBegin; 1161 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1162 PetscCall(TSGetDM(ts,&dm)); 1163 PetscCall(DMTSSetForcingFunction(dm,func,ctx)); 1164 PetscFunctionReturn(0); 1165 } 1166 1167 /*@C 1168 TSSetRHSJacobian - Sets the function to compute the Jacobian of G, 1169 where U_t = G(U,t), as well as the location to store the matrix. 1170 1171 Logically Collective on TS 1172 1173 Input Parameters: 1174 + ts - the TS context obtained from TSCreate() 1175 . Amat - (approximate) Jacobian matrix 1176 . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat) 1177 . f - the Jacobian evaluation routine 1178 - ctx - [optional] user-defined context for private data for the 1179 Jacobian evaluation routine (may be NULL) 1180 1181 Calling sequence of f: 1182 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx); 1183 1184 + t - current timestep 1185 . u - input vector 1186 . Amat - (approximate) Jacobian matrix 1187 . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat) 1188 - ctx - [optional] user-defined context for matrix evaluation routine 1189 1190 Notes: 1191 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1192 1193 The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f() 1194 You should not assume the values are the same in the next call to f() as you set them in the previous call. 1195 1196 Level: beginner 1197 1198 .seealso: `SNESComputeJacobianDefaultColor()`, `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()` 1199 1200 @*/ 1201 PetscErrorCode TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx) 1202 { 1203 SNES snes; 1204 DM dm; 1205 TSIJacobian ijacobian; 1206 1207 PetscFunctionBegin; 1208 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1209 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1210 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 1211 if (Amat) PetscCheckSameComm(ts,1,Amat,2); 1212 if (Pmat) PetscCheckSameComm(ts,1,Pmat,3); 1213 1214 PetscCall(TSGetDM(ts,&dm)); 1215 PetscCall(DMTSSetRHSJacobian(dm,f,ctx)); 1216 PetscCall(DMTSGetIJacobian(dm,&ijacobian,NULL)); 1217 PetscCall(TSGetSNES(ts,&snes)); 1218 if (!ijacobian) { 1219 PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts)); 1220 } 1221 if (Amat) { 1222 PetscCall(PetscObjectReference((PetscObject)Amat)); 1223 PetscCall(MatDestroy(&ts->Arhs)); 1224 ts->Arhs = Amat; 1225 } 1226 if (Pmat) { 1227 PetscCall(PetscObjectReference((PetscObject)Pmat)); 1228 PetscCall(MatDestroy(&ts->Brhs)); 1229 ts->Brhs = Pmat; 1230 } 1231 PetscFunctionReturn(0); 1232 } 1233 1234 /*@C 1235 TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved. 1236 1237 Logically Collective on TS 1238 1239 Input Parameters: 1240 + ts - the TS context obtained from TSCreate() 1241 . r - vector to hold the residual (or NULL to have it created internally) 1242 . f - the function evaluation routine 1243 - ctx - user-defined context for private data for the function evaluation routine (may be NULL) 1244 1245 Calling sequence of f: 1246 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx); 1247 1248 + t - time at step/stage being solved 1249 . u - state vector 1250 . u_t - time derivative of state vector 1251 . F - function vector 1252 - ctx - [optional] user-defined context for matrix evaluation routine 1253 1254 Important: 1255 The user MUST call either this routine or TSSetRHSFunction() to define the ODE. When solving DAEs you must use this function. 1256 1257 Level: beginner 1258 1259 .seealso: `TSSetRHSJacobian()`, `TSSetRHSFunction()`, `TSSetIJacobian()` 1260 @*/ 1261 PetscErrorCode TSSetIFunction(TS ts,Vec r,TSIFunction f,void *ctx) 1262 { 1263 SNES snes; 1264 Vec ralloc = NULL; 1265 DM dm; 1266 1267 PetscFunctionBegin; 1268 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1269 if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2); 1270 1271 PetscCall(TSGetDM(ts,&dm)); 1272 PetscCall(DMTSSetIFunction(dm,f,ctx)); 1273 1274 PetscCall(TSGetSNES(ts,&snes)); 1275 if (!r && !ts->dm && ts->vec_sol) { 1276 PetscCall(VecDuplicate(ts->vec_sol,&ralloc)); 1277 r = ralloc; 1278 } 1279 PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts)); 1280 PetscCall(VecDestroy(&ralloc)); 1281 PetscFunctionReturn(0); 1282 } 1283 1284 /*@C 1285 TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it. 1286 1287 Not Collective 1288 1289 Input Parameter: 1290 . ts - the TS context 1291 1292 Output Parameters: 1293 + r - vector to hold residual (or NULL) 1294 . func - the function to compute residual (or NULL) 1295 - ctx - the function context (or NULL) 1296 1297 Level: advanced 1298 1299 .seealso: `TSSetIFunction()`, `SNESGetFunction()` 1300 @*/ 1301 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx) 1302 { 1303 SNES snes; 1304 DM dm; 1305 1306 PetscFunctionBegin; 1307 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1308 PetscCall(TSGetSNES(ts,&snes)); 1309 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1310 PetscCall(TSGetDM(ts,&dm)); 1311 PetscCall(DMTSGetIFunction(dm,func,ctx)); 1312 PetscFunctionReturn(0); 1313 } 1314 1315 /*@C 1316 TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it. 1317 1318 Not Collective 1319 1320 Input Parameter: 1321 . ts - the TS context 1322 1323 Output Parameters: 1324 + r - vector to hold computed right hand side (or NULL) 1325 . func - the function to compute right hand side (or NULL) 1326 - ctx - the function context (or NULL) 1327 1328 Level: advanced 1329 1330 .seealso: `TSSetRHSFunction()`, `SNESGetFunction()` 1331 @*/ 1332 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx) 1333 { 1334 SNES snes; 1335 DM dm; 1336 1337 PetscFunctionBegin; 1338 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1339 PetscCall(TSGetSNES(ts,&snes)); 1340 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1341 PetscCall(TSGetDM(ts,&dm)); 1342 PetscCall(DMTSGetRHSFunction(dm,func,ctx)); 1343 PetscFunctionReturn(0); 1344 } 1345 1346 /*@C 1347 TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function 1348 provided with TSSetIFunction(). 1349 1350 Logically Collective on TS 1351 1352 Input Parameters: 1353 + ts - the TS context obtained from TSCreate() 1354 . Amat - (approximate) Jacobian matrix 1355 . Pmat - matrix used to compute preconditioner (usually the same as Amat) 1356 . f - the Jacobian evaluation routine 1357 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL) 1358 1359 Calling sequence of f: 1360 $ PetscErrorCode f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx); 1361 1362 + t - time at step/stage being solved 1363 . U - state vector 1364 . U_t - time derivative of state vector 1365 . a - shift 1366 . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t 1367 . Pmat - matrix used for constructing preconditioner, usually the same as Amat 1368 - ctx - [optional] user-defined context for matrix evaluation routine 1369 1370 Notes: 1371 The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve. 1372 1373 If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null 1374 space to Amat and the KSP solvers will automatically use that null space as needed during the solution process. 1375 1376 The matrix dF/dU + a*dF/dU_t you provide turns out to be 1377 the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved. 1378 The time integrator internally approximates U_t by W+a*U where the positive "shift" 1379 a and vector W depend on the integration method, step size, and past states. For example with 1380 the backward Euler method a = 1/dt and W = -a*U(previous timestep) so 1381 W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt 1382 1383 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1384 1385 The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f() 1386 You should not assume the values are the same in the next call to f() as you set them in the previous call. 1387 1388 Level: beginner 1389 1390 .seealso: `TSSetIFunction()`, `TSSetRHSJacobian()`, `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()` 1391 1392 @*/ 1393 PetscErrorCode TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx) 1394 { 1395 SNES snes; 1396 DM dm; 1397 1398 PetscFunctionBegin; 1399 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1400 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1401 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 1402 if (Amat) PetscCheckSameComm(ts,1,Amat,2); 1403 if (Pmat) PetscCheckSameComm(ts,1,Pmat,3); 1404 1405 PetscCall(TSGetDM(ts,&dm)); 1406 PetscCall(DMTSSetIJacobian(dm,f,ctx)); 1407 1408 PetscCall(TSGetSNES(ts,&snes)); 1409 PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts)); 1410 PetscFunctionReturn(0); 1411 } 1412 1413 /*@ 1414 TSRHSJacobianSetReuse - restore RHS Jacobian before re-evaluating. Without this flag, TS will change the sign and 1415 shift the RHS Jacobian for a finite-time-step implicit solve, in which case the user function will need to recompute 1416 the entire Jacobian. The reuse flag must be set if the evaluation function will assume that the matrix entries have 1417 not been changed by the TS. 1418 1419 Logically Collective 1420 1421 Input Parameters: 1422 + ts - TS context obtained from TSCreate() 1423 - reuse - PETSC_TRUE if the RHS Jacobian 1424 1425 Level: intermediate 1426 1427 .seealso: `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 1428 @*/ 1429 PetscErrorCode TSRHSJacobianSetReuse(TS ts,PetscBool reuse) 1430 { 1431 PetscFunctionBegin; 1432 ts->rhsjacobian.reuse = reuse; 1433 PetscFunctionReturn(0); 1434 } 1435 1436 /*@C 1437 TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved. 1438 1439 Logically Collective on TS 1440 1441 Input Parameters: 1442 + ts - the TS context obtained from TSCreate() 1443 . F - vector to hold the residual (or NULL to have it created internally) 1444 . fun - the function evaluation routine 1445 - ctx - user-defined context for private data for the function evaluation routine (may be NULL) 1446 1447 Calling sequence of fun: 1448 $ PetscErrorCode fun(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,Vec F,ctx); 1449 1450 + t - time at step/stage being solved 1451 . U - state vector 1452 . U_t - time derivative of state vector 1453 . U_tt - second time derivative of state vector 1454 . F - function vector 1455 - ctx - [optional] user-defined context for matrix evaluation routine (may be NULL) 1456 1457 Level: beginner 1458 1459 .seealso: `TSSetI2Jacobian()`, `TSSetIFunction()`, `TSCreate()`, `TSSetRHSFunction()` 1460 @*/ 1461 PetscErrorCode TSSetI2Function(TS ts,Vec F,TSI2Function fun,void *ctx) 1462 { 1463 DM dm; 1464 1465 PetscFunctionBegin; 1466 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1467 if (F) PetscValidHeaderSpecific(F,VEC_CLASSID,2); 1468 PetscCall(TSSetIFunction(ts,F,NULL,NULL)); 1469 PetscCall(TSGetDM(ts,&dm)); 1470 PetscCall(DMTSSetI2Function(dm,fun,ctx)); 1471 PetscFunctionReturn(0); 1472 } 1473 1474 /*@C 1475 TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it. 1476 1477 Not Collective 1478 1479 Input Parameter: 1480 . ts - the TS context 1481 1482 Output Parameters: 1483 + r - vector to hold residual (or NULL) 1484 . fun - the function to compute residual (or NULL) 1485 - ctx - the function context (or NULL) 1486 1487 Level: advanced 1488 1489 .seealso: `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()` 1490 @*/ 1491 PetscErrorCode TSGetI2Function(TS ts,Vec *r,TSI2Function *fun,void **ctx) 1492 { 1493 SNES snes; 1494 DM dm; 1495 1496 PetscFunctionBegin; 1497 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1498 PetscCall(TSGetSNES(ts,&snes)); 1499 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1500 PetscCall(TSGetDM(ts,&dm)); 1501 PetscCall(DMTSGetI2Function(dm,fun,ctx)); 1502 PetscFunctionReturn(0); 1503 } 1504 1505 /*@C 1506 TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t + a*dF/dU_tt 1507 where F(t,U,U_t,U_tt) is the function you provided with TSSetI2Function(). 1508 1509 Logically Collective on TS 1510 1511 Input Parameters: 1512 + ts - the TS context obtained from TSCreate() 1513 . J - Jacobian matrix 1514 . P - preconditioning matrix for J (may be same as J) 1515 . jac - the Jacobian evaluation routine 1516 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL) 1517 1518 Calling sequence of jac: 1519 $ PetscErrorCode jac(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,PetscReal v,PetscReal a,Mat J,Mat P,void *ctx); 1520 1521 + t - time at step/stage being solved 1522 . U - state vector 1523 . U_t - time derivative of state vector 1524 . U_tt - second time derivative of state vector 1525 . v - shift for U_t 1526 . a - shift for U_tt 1527 . J - Jacobian of G(U) = F(t,U,W+v*U,W'+a*U), equivalent to dF/dU + v*dF/dU_t + a*dF/dU_tt 1528 . P - preconditioning matrix for J, may be same as J 1529 - ctx - [optional] user-defined context for matrix evaluation routine 1530 1531 Notes: 1532 The matrices J and P are exactly the matrices that are used by SNES for the nonlinear solve. 1533 1534 The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be 1535 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. 1536 The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U where the positive "shift" 1537 parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states. 1538 1539 Level: beginner 1540 1541 .seealso: `TSSetI2Function()`, `TSGetI2Jacobian()` 1542 @*/ 1543 PetscErrorCode TSSetI2Jacobian(TS ts,Mat J,Mat P,TSI2Jacobian jac,void *ctx) 1544 { 1545 DM dm; 1546 1547 PetscFunctionBegin; 1548 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1549 if (J) PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1550 if (P) PetscValidHeaderSpecific(P,MAT_CLASSID,3); 1551 PetscCall(TSSetIJacobian(ts,J,P,NULL,NULL)); 1552 PetscCall(TSGetDM(ts,&dm)); 1553 PetscCall(DMTSSetI2Jacobian(dm,jac,ctx)); 1554 PetscFunctionReturn(0); 1555 } 1556 1557 /*@C 1558 TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep. 1559 1560 Not Collective, but parallel objects are returned if TS is parallel 1561 1562 Input Parameter: 1563 . ts - The TS context obtained from TSCreate() 1564 1565 Output Parameters: 1566 + J - The (approximate) Jacobian of F(t,U,U_t,U_tt) 1567 . P - The matrix from which the preconditioner is constructed, often the same as J 1568 . jac - The function to compute the Jacobian matrices 1569 - ctx - User-defined context for Jacobian evaluation routine 1570 1571 Notes: 1572 You can pass in NULL for any return argument you do not need. 1573 1574 Level: advanced 1575 1576 .seealso: `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()` 1577 1578 @*/ 1579 PetscErrorCode TSGetI2Jacobian(TS ts,Mat *J,Mat *P,TSI2Jacobian *jac,void **ctx) 1580 { 1581 SNES snes; 1582 DM dm; 1583 1584 PetscFunctionBegin; 1585 PetscCall(TSGetSNES(ts,&snes)); 1586 PetscCall(SNESSetUpMatrices(snes)); 1587 PetscCall(SNESGetJacobian(snes,J,P,NULL,NULL)); 1588 PetscCall(TSGetDM(ts,&dm)); 1589 PetscCall(DMTSGetI2Jacobian(dm,jac,ctx)); 1590 PetscFunctionReturn(0); 1591 } 1592 1593 /*@ 1594 TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0 1595 1596 Collective on TS 1597 1598 Input Parameters: 1599 + ts - the TS context 1600 . t - current time 1601 . U - state vector 1602 . V - time derivative of state vector (U_t) 1603 - A - second time derivative of state vector (U_tt) 1604 1605 Output Parameter: 1606 . F - the residual vector 1607 1608 Note: 1609 Most users should not need to explicitly call this routine, as it 1610 is used internally within the nonlinear solvers. 1611 1612 Level: developer 1613 1614 .seealso: `TSSetI2Function()`, `TSGetI2Function()` 1615 @*/ 1616 PetscErrorCode TSComputeI2Function(TS ts,PetscReal t,Vec U,Vec V,Vec A,Vec F) 1617 { 1618 DM dm; 1619 TSI2Function I2Function; 1620 void *ctx; 1621 TSRHSFunction rhsfunction; 1622 1623 PetscFunctionBegin; 1624 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1625 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1626 PetscValidHeaderSpecific(V,VEC_CLASSID,4); 1627 PetscValidHeaderSpecific(A,VEC_CLASSID,5); 1628 PetscValidHeaderSpecific(F,VEC_CLASSID,6); 1629 1630 PetscCall(TSGetDM(ts,&dm)); 1631 PetscCall(DMTSGetI2Function(dm,&I2Function,&ctx)); 1632 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 1633 1634 if (!I2Function) { 1635 PetscCall(TSComputeIFunction(ts,t,U,A,F,PETSC_FALSE)); 1636 PetscFunctionReturn(0); 1637 } 1638 1639 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,V,F)); 1640 1641 PetscStackPush("TS user implicit function"); 1642 PetscCall(I2Function(ts,t,U,V,A,F,ctx)); 1643 PetscStackPop; 1644 1645 if (rhsfunction) { 1646 Vec Frhs; 1647 PetscCall(TSGetRHSVec_Private(ts,&Frhs)); 1648 PetscCall(TSComputeRHSFunction(ts,t,U,Frhs)); 1649 PetscCall(VecAXPY(F,-1,Frhs)); 1650 } 1651 1652 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,V,F)); 1653 PetscFunctionReturn(0); 1654 } 1655 1656 /*@ 1657 TSComputeI2Jacobian - Evaluates the Jacobian of the DAE 1658 1659 Collective on TS 1660 1661 Input Parameters: 1662 + ts - the TS context 1663 . t - current timestep 1664 . U - state vector 1665 . V - time derivative of state vector 1666 . A - second time derivative of state vector 1667 . shiftV - shift to apply, see note below 1668 - shiftA - shift to apply, see note below 1669 1670 Output Parameters: 1671 + J - Jacobian matrix 1672 - P - optional preconditioning matrix 1673 1674 Notes: 1675 If F(t,U,V,A)=0 is the DAE, the required Jacobian is 1676 1677 dF/dU + shiftV*dF/dV + shiftA*dF/dA 1678 1679 Most users should not need to explicitly call this routine, as it 1680 is used internally within the nonlinear solvers. 1681 1682 Level: developer 1683 1684 .seealso: `TSSetI2Jacobian()` 1685 @*/ 1686 PetscErrorCode TSComputeI2Jacobian(TS ts,PetscReal t,Vec U,Vec V,Vec A,PetscReal shiftV,PetscReal shiftA,Mat J,Mat P) 1687 { 1688 DM dm; 1689 TSI2Jacobian I2Jacobian; 1690 void *ctx; 1691 TSRHSJacobian rhsjacobian; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1695 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1696 PetscValidHeaderSpecific(V,VEC_CLASSID,4); 1697 PetscValidHeaderSpecific(A,VEC_CLASSID,5); 1698 PetscValidHeaderSpecific(J,MAT_CLASSID,8); 1699 PetscValidHeaderSpecific(P,MAT_CLASSID,9); 1700 1701 PetscCall(TSGetDM(ts,&dm)); 1702 PetscCall(DMTSGetI2Jacobian(dm,&I2Jacobian,&ctx)); 1703 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL)); 1704 1705 if (!I2Jacobian) { 1706 PetscCall(TSComputeIJacobian(ts,t,U,A,shiftA,J,P,PETSC_FALSE)); 1707 PetscFunctionReturn(0); 1708 } 1709 1710 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,J,P)); 1711 1712 PetscStackPush("TS user implicit Jacobian"); 1713 PetscCall(I2Jacobian(ts,t,U,V,A,shiftV,shiftA,J,P,ctx)); 1714 PetscStackPop; 1715 1716 if (rhsjacobian) { 1717 Mat Jrhs,Prhs; 1718 PetscCall(TSGetRHSMats_Private(ts,&Jrhs,&Prhs)); 1719 PetscCall(TSComputeRHSJacobian(ts,t,U,Jrhs,Prhs)); 1720 PetscCall(MatAXPY(J,-1,Jrhs,ts->axpy_pattern)); 1721 if (P != J) PetscCall(MatAXPY(P,-1,Prhs,ts->axpy_pattern)); 1722 } 1723 1724 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,J,P)); 1725 PetscFunctionReturn(0); 1726 } 1727 1728 /*@C 1729 TSSetTransientVariable - sets function to transform from state to transient variables 1730 1731 Logically Collective 1732 1733 Input Parameters: 1734 + ts - time stepping context on which to change the transient variable 1735 . tvar - a function that transforms to transient variables 1736 - ctx - a context for tvar 1737 1738 Calling sequence of tvar: 1739 $ PetscErrorCode tvar(TS ts,Vec p,Vec c,void *ctx); 1740 1741 + ts - timestep context 1742 . p - input vector (primitive form) 1743 . c - output vector, transient variables (conservative form) 1744 - ctx - [optional] user-defined function context 1745 1746 Level: advanced 1747 1748 Notes: 1749 This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., TSBDF) 1750 can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to 1751 well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is 1752 C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be 1753 evaluated via the chain rule, as in 1754 1755 dF/dP + shift * dF/dCdot dC/dP. 1756 1757 .seealso: `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()` 1758 @*/ 1759 PetscErrorCode TSSetTransientVariable(TS ts,TSTransientVariable tvar,void *ctx) 1760 { 1761 DM dm; 1762 1763 PetscFunctionBegin; 1764 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1765 PetscCall(TSGetDM(ts,&dm)); 1766 PetscCall(DMTSSetTransientVariable(dm,tvar,ctx)); 1767 PetscFunctionReturn(0); 1768 } 1769 1770 /*@ 1771 TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables 1772 1773 Logically Collective 1774 1775 Input Parameters: 1776 + ts - TS on which to compute 1777 - U - state vector to be transformed to transient variables 1778 1779 Output Parameters: 1780 . C - transient (conservative) variable 1781 1782 Developer Notes: 1783 If DMTSSetTransientVariable() has not been called, then C is not modified in this routine and C=NULL is allowed. 1784 This makes it safe to call without a guard. One can use TSHasTransientVariable() to check if transient variables are 1785 being used. 1786 1787 Level: developer 1788 1789 .seealso: `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()` 1790 @*/ 1791 PetscErrorCode TSComputeTransientVariable(TS ts,Vec U,Vec C) 1792 { 1793 DM dm; 1794 DMTS dmts; 1795 1796 PetscFunctionBegin; 1797 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1798 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 1799 PetscCall(TSGetDM(ts,&dm)); 1800 PetscCall(DMGetDMTS(dm,&dmts)); 1801 if (dmts->ops->transientvar) { 1802 PetscValidHeaderSpecific(C,VEC_CLASSID,3); 1803 PetscCall((*dmts->ops->transientvar)(ts,U,C,dmts->transientvarctx)); 1804 } 1805 PetscFunctionReturn(0); 1806 } 1807 1808 /*@ 1809 TSHasTransientVariable - determine whether transient variables have been set 1810 1811 Logically Collective 1812 1813 Input Parameters: 1814 . ts - TS on which to compute 1815 1816 Output Parameters: 1817 . has - PETSC_TRUE if transient variables have been set 1818 1819 Level: developer 1820 1821 .seealso: `DMTSSetTransientVariable()`, `TSComputeTransientVariable()` 1822 @*/ 1823 PetscErrorCode TSHasTransientVariable(TS ts,PetscBool *has) 1824 { 1825 DM dm; 1826 DMTS dmts; 1827 1828 PetscFunctionBegin; 1829 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1830 PetscCall(TSGetDM(ts,&dm)); 1831 PetscCall(DMGetDMTS(dm,&dmts)); 1832 *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE; 1833 PetscFunctionReturn(0); 1834 } 1835 1836 /*@ 1837 TS2SetSolution - Sets the initial solution and time derivative vectors 1838 for use by the TS routines handling second order equations. 1839 1840 Logically Collective on TS 1841 1842 Input Parameters: 1843 + ts - the TS context obtained from TSCreate() 1844 . u - the solution vector 1845 - v - the time derivative vector 1846 1847 Level: beginner 1848 1849 @*/ 1850 PetscErrorCode TS2SetSolution(TS ts,Vec u,Vec v) 1851 { 1852 PetscFunctionBegin; 1853 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1854 PetscValidHeaderSpecific(u,VEC_CLASSID,2); 1855 PetscValidHeaderSpecific(v,VEC_CLASSID,3); 1856 PetscCall(TSSetSolution(ts,u)); 1857 PetscCall(PetscObjectReference((PetscObject)v)); 1858 PetscCall(VecDestroy(&ts->vec_dot)); 1859 ts->vec_dot = v; 1860 PetscFunctionReturn(0); 1861 } 1862 1863 /*@ 1864 TS2GetSolution - Returns the solution and time derivative at the present timestep 1865 for second order equations. It is valid to call this routine inside the function 1866 that you are evaluating in order to move to the new timestep. This vector not 1867 changed until the solution at the next timestep has been calculated. 1868 1869 Not Collective, but Vec returned is parallel if TS is parallel 1870 1871 Input Parameter: 1872 . ts - the TS context obtained from TSCreate() 1873 1874 Output Parameters: 1875 + u - the vector containing the solution 1876 - v - the vector containing the time derivative 1877 1878 Level: intermediate 1879 1880 .seealso: `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()` 1881 1882 @*/ 1883 PetscErrorCode TS2GetSolution(TS ts,Vec *u,Vec *v) 1884 { 1885 PetscFunctionBegin; 1886 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1887 if (u) PetscValidPointer(u,2); 1888 if (v) PetscValidPointer(v,3); 1889 if (u) *u = ts->vec_sol; 1890 if (v) *v = ts->vec_dot; 1891 PetscFunctionReturn(0); 1892 } 1893 1894 /*@C 1895 TSLoad - Loads a KSP that has been stored in binary with KSPView(). 1896 1897 Collective on PetscViewer 1898 1899 Input Parameters: 1900 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or 1901 some related function before a call to TSLoad(). 1902 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() 1903 1904 Level: intermediate 1905 1906 Notes: 1907 The type is determined by the data in the file, any type set into the TS before this call is ignored. 1908 1909 Notes for advanced users: 1910 Most users should not need to know the details of the binary storage 1911 format, since TSLoad() and TSView() completely hide these details. 1912 But for anyone who's interested, the standard binary matrix storage 1913 format is 1914 .vb 1915 has not yet been determined 1916 .ve 1917 1918 .seealso: `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()` 1919 @*/ 1920 PetscErrorCode TSLoad(TS ts, PetscViewer viewer) 1921 { 1922 PetscBool isbinary; 1923 PetscInt classid; 1924 char type[256]; 1925 DMTS sdm; 1926 DM dm; 1927 1928 PetscFunctionBegin; 1929 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1930 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1931 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 1932 PetscCheck(isbinary,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1933 1934 PetscCall(PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT)); 1935 PetscCheck(classid == TS_FILE_CLASSID,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file"); 1936 PetscCall(PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR)); 1937 PetscCall(TSSetType(ts, type)); 1938 if (ts->ops->load) PetscCall((*ts->ops->load)(ts,viewer)); 1939 PetscCall(DMCreate(PetscObjectComm((PetscObject)ts),&dm)); 1940 PetscCall(DMLoad(dm,viewer)); 1941 PetscCall(TSSetDM(ts,dm)); 1942 PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol)); 1943 PetscCall(VecLoad(ts->vec_sol,viewer)); 1944 PetscCall(DMGetDMTS(ts->dm,&sdm)); 1945 PetscCall(DMTSLoad(sdm,viewer)); 1946 PetscFunctionReturn(0); 1947 } 1948 1949 #include <petscdraw.h> 1950 #if defined(PETSC_HAVE_SAWS) 1951 #include <petscviewersaws.h> 1952 #endif 1953 1954 /*@C 1955 TSViewFromOptions - View from Options 1956 1957 Collective on TS 1958 1959 Input Parameters: 1960 + A - the application ordering context 1961 . obj - Optional object 1962 - name - command line option 1963 1964 Level: intermediate 1965 .seealso: `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()` 1966 @*/ 1967 PetscErrorCode TSViewFromOptions(TS A,PetscObject obj,const char name[]) 1968 { 1969 PetscFunctionBegin; 1970 PetscValidHeaderSpecific(A,TS_CLASSID,1); 1971 PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 1972 PetscFunctionReturn(0); 1973 } 1974 1975 /*@C 1976 TSView - Prints the TS data structure. 1977 1978 Collective on TS 1979 1980 Input Parameters: 1981 + ts - the TS context obtained from TSCreate() 1982 - viewer - visualization context 1983 1984 Options Database Key: 1985 . -ts_view - calls TSView() at end of TSStep() 1986 1987 Notes: 1988 The available visualization contexts include 1989 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 1990 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 1991 output where only the first processor opens 1992 the file. All other processors send their 1993 data to the first processor to print. 1994 1995 The user can open an alternative visualization context with 1996 PetscViewerASCIIOpen() - output to a specified file. 1997 1998 In the debugger you can do "call TSView(ts,0)" to display the TS solver. (The same holds for any PETSc object viewer). 1999 2000 Level: beginner 2001 2002 .seealso: `PetscViewerASCIIOpen()` 2003 @*/ 2004 PetscErrorCode TSView(TS ts,PetscViewer viewer) 2005 { 2006 TSType type; 2007 PetscBool iascii,isstring,isundials,isbinary,isdraw; 2008 DMTS sdm; 2009 #if defined(PETSC_HAVE_SAWS) 2010 PetscBool issaws; 2011 #endif 2012 2013 PetscFunctionBegin; 2014 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2015 if (!viewer) { 2016 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer)); 2017 } 2018 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2019 PetscCheckSameComm(ts,1,viewer,2); 2020 2021 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 2022 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring)); 2023 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 2024 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw)); 2025 #if defined(PETSC_HAVE_SAWS) 2026 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws)); 2027 #endif 2028 if (iascii) { 2029 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer)); 2030 if (ts->ops->view) { 2031 PetscCall(PetscViewerASCIIPushTab(viewer)); 2032 PetscCall((*ts->ops->view)(ts,viewer)); 2033 PetscCall(PetscViewerASCIIPopTab(viewer)); 2034 } 2035 if (ts->max_steps < PETSC_MAX_INT) { 2036 PetscCall(PetscViewerASCIIPrintf(viewer," maximum steps=%" PetscInt_FMT "\n",ts->max_steps)); 2037 } 2038 if (ts->max_time < PETSC_MAX_REAL) { 2039 PetscCall(PetscViewerASCIIPrintf(viewer," maximum time=%g\n",(double)ts->max_time)); 2040 } 2041 if (ts->ifuncs) { 2042 PetscCall(PetscViewerASCIIPrintf(viewer," total number of I function evaluations=%" PetscInt_FMT "\n",ts->ifuncs)); 2043 } 2044 if (ts->ijacs) { 2045 PetscCall(PetscViewerASCIIPrintf(viewer," total number of I Jacobian evaluations=%" PetscInt_FMT "\n",ts->ijacs)); 2046 } 2047 if (ts->rhsfuncs) { 2048 PetscCall(PetscViewerASCIIPrintf(viewer," total number of RHS function evaluations=%" PetscInt_FMT "\n",ts->rhsfuncs)); 2049 } 2050 if (ts->rhsjacs) { 2051 PetscCall(PetscViewerASCIIPrintf(viewer," total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n",ts->rhsjacs)); 2052 } 2053 if (ts->usessnes) { 2054 PetscBool lin; 2055 if (ts->problem_type == TS_NONLINEAR) { 2056 PetscCall(PetscViewerASCIIPrintf(viewer," total number of nonlinear solver iterations=%" PetscInt_FMT "\n",ts->snes_its)); 2057 } 2058 PetscCall(PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%" PetscInt_FMT "\n",ts->ksp_its)); 2059 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&lin,SNESKSPONLY,SNESKSPTRANSPOSEONLY,"")); 2060 PetscCall(PetscViewerASCIIPrintf(viewer," total number of %slinear solve failures=%" PetscInt_FMT "\n",lin ? "" : "non",ts->num_snes_failures)); 2061 } 2062 PetscCall(PetscViewerASCIIPrintf(viewer," total number of rejected steps=%" PetscInt_FMT "\n",ts->reject)); 2063 if (ts->vrtol) { 2064 PetscCall(PetscViewerASCIIPrintf(viewer," using vector of relative error tolerances, ")); 2065 } else { 2066 PetscCall(PetscViewerASCIIPrintf(viewer," using relative error tolerance of %g, ",(double)ts->rtol)); 2067 } 2068 if (ts->vatol) { 2069 PetscCall(PetscViewerASCIIPrintf(viewer," using vector of absolute error tolerances\n")); 2070 } else { 2071 PetscCall(PetscViewerASCIIPrintf(viewer," using absolute error tolerance of %g\n",(double)ts->atol)); 2072 } 2073 PetscCall(PetscViewerASCIIPushTab(viewer)); 2074 PetscCall(TSAdaptView(ts->adapt,viewer)); 2075 PetscCall(PetscViewerASCIIPopTab(viewer)); 2076 } else if (isstring) { 2077 PetscCall(TSGetType(ts,&type)); 2078 PetscCall(PetscViewerStringSPrintf(viewer," TSType: %-7.7s",type)); 2079 if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer)); 2080 } else if (isbinary) { 2081 PetscInt classid = TS_FILE_CLASSID; 2082 MPI_Comm comm; 2083 PetscMPIInt rank; 2084 char type[256]; 2085 2086 PetscCall(PetscObjectGetComm((PetscObject)ts,&comm)); 2087 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 2088 if (rank == 0) { 2089 PetscCall(PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT)); 2090 PetscCall(PetscStrncpy(type,((PetscObject)ts)->type_name,256)); 2091 PetscCall(PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR)); 2092 } 2093 if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer)); 2094 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer)); 2095 PetscCall(DMView(ts->dm,viewer)); 2096 PetscCall(VecView(ts->vec_sol,viewer)); 2097 PetscCall(DMGetDMTS(ts->dm,&sdm)); 2098 PetscCall(DMTSView(sdm,viewer)); 2099 } else if (isdraw) { 2100 PetscDraw draw; 2101 char str[36]; 2102 PetscReal x,y,bottom,h; 2103 2104 PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw)); 2105 PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y)); 2106 PetscCall(PetscStrcpy(str,"TS: ")); 2107 PetscCall(PetscStrcat(str,((PetscObject)ts)->type_name)); 2108 PetscCall(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h)); 2109 bottom = y - h; 2110 PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom)); 2111 if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer)); 2112 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer)); 2113 if (ts->snes) PetscCall(SNESView(ts->snes,viewer)); 2114 PetscCall(PetscDrawPopCurrentPoint(draw)); 2115 #if defined(PETSC_HAVE_SAWS) 2116 } else if (issaws) { 2117 PetscMPIInt rank; 2118 const char *name; 2119 2120 PetscCall(PetscObjectGetName((PetscObject)ts,&name)); 2121 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 2122 if (!((PetscObject)ts)->amsmem && rank == 0) { 2123 char dir[1024]; 2124 2125 PetscCall(PetscObjectViewSAWs((PetscObject)ts,viewer)); 2126 PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name)); 2127 PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT)); 2128 PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name)); 2129 PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE)); 2130 } 2131 if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer)); 2132 #endif 2133 } 2134 if (ts->snes && ts->usessnes) { 2135 PetscCall(PetscViewerASCIIPushTab(viewer)); 2136 PetscCall(SNESView(ts->snes,viewer)); 2137 PetscCall(PetscViewerASCIIPopTab(viewer)); 2138 } 2139 PetscCall(DMGetDMTS(ts->dm,&sdm)); 2140 PetscCall(DMTSView(sdm,viewer)); 2141 2142 PetscCall(PetscViewerASCIIPushTab(viewer)); 2143 PetscCall(PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials)); 2144 PetscCall(PetscViewerASCIIPopTab(viewer)); 2145 PetscFunctionReturn(0); 2146 } 2147 2148 /*@ 2149 TSSetApplicationContext - Sets an optional user-defined context for 2150 the timesteppers. 2151 2152 Logically Collective on TS 2153 2154 Input Parameters: 2155 + ts - the TS context obtained from TSCreate() 2156 - usrP - optional user context 2157 2158 Fortran Notes: 2159 To use this from Fortran you must write a Fortran interface definition for this 2160 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 2161 2162 Level: intermediate 2163 2164 .seealso: `TSGetApplicationContext()` 2165 @*/ 2166 PetscErrorCode TSSetApplicationContext(TS ts,void *usrP) 2167 { 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2170 ts->user = usrP; 2171 PetscFunctionReturn(0); 2172 } 2173 2174 /*@ 2175 TSGetApplicationContext - Gets the user-defined context for the 2176 timestepper. 2177 2178 Not Collective 2179 2180 Input Parameter: 2181 . ts - the TS context obtained from TSCreate() 2182 2183 Output Parameter: 2184 . usrP - user context 2185 2186 Fortran Notes: 2187 To use this from Fortran you must write a Fortran interface definition for this 2188 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 2189 2190 Level: intermediate 2191 2192 .seealso: `TSSetApplicationContext()` 2193 @*/ 2194 PetscErrorCode TSGetApplicationContext(TS ts,void *usrP) 2195 { 2196 PetscFunctionBegin; 2197 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2198 *(void**)usrP = ts->user; 2199 PetscFunctionReturn(0); 2200 } 2201 2202 /*@ 2203 TSGetStepNumber - Gets the number of steps completed. 2204 2205 Not Collective 2206 2207 Input Parameter: 2208 . ts - the TS context obtained from TSCreate() 2209 2210 Output Parameter: 2211 . steps - number of steps completed so far 2212 2213 Level: intermediate 2214 2215 .seealso: `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()` 2216 @*/ 2217 PetscErrorCode TSGetStepNumber(TS ts,PetscInt *steps) 2218 { 2219 PetscFunctionBegin; 2220 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2221 PetscValidIntPointer(steps,2); 2222 *steps = ts->steps; 2223 PetscFunctionReturn(0); 2224 } 2225 2226 /*@ 2227 TSSetStepNumber - Sets the number of steps completed. 2228 2229 Logically Collective on TS 2230 2231 Input Parameters: 2232 + ts - the TS context 2233 - steps - number of steps completed so far 2234 2235 Notes: 2236 For most uses of the TS solvers the user need not explicitly call 2237 TSSetStepNumber(), as the step counter is appropriately updated in 2238 TSSolve()/TSStep()/TSRollBack(). Power users may call this routine to 2239 reinitialize timestepping by setting the step counter to zero (and time 2240 to the initial time) to solve a similar problem with different initial 2241 conditions or parameters. Other possible use case is to continue 2242 timestepping from a previously interrupted run in such a way that TS 2243 monitors will be called with a initial nonzero step counter. 2244 2245 Level: advanced 2246 2247 .seealso: `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()` 2248 @*/ 2249 PetscErrorCode TSSetStepNumber(TS ts,PetscInt steps) 2250 { 2251 PetscFunctionBegin; 2252 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2253 PetscValidLogicalCollectiveInt(ts,steps,2); 2254 PetscCheck(steps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Step number must be non-negative"); 2255 ts->steps = steps; 2256 PetscFunctionReturn(0); 2257 } 2258 2259 /*@ 2260 TSSetTimeStep - Allows one to reset the timestep at any time, 2261 useful for simple pseudo-timestepping codes. 2262 2263 Logically Collective on TS 2264 2265 Input Parameters: 2266 + ts - the TS context obtained from TSCreate() 2267 - time_step - the size of the timestep 2268 2269 Level: intermediate 2270 2271 .seealso: `TSGetTimeStep()`, `TSSetTime()` 2272 2273 @*/ 2274 PetscErrorCode TSSetTimeStep(TS ts,PetscReal time_step) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2278 PetscValidLogicalCollectiveReal(ts,time_step,2); 2279 ts->time_step = time_step; 2280 PetscFunctionReturn(0); 2281 } 2282 2283 /*@ 2284 TSSetExactFinalTime - Determines whether to adapt the final time step to 2285 match the exact final time, interpolate solution to the exact final time, 2286 or just return at the final time TS computed. 2287 2288 Logically Collective on TS 2289 2290 Input Parameters: 2291 + ts - the time-step context 2292 - eftopt - exact final time option 2293 2294 $ TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded 2295 $ TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time 2296 $ TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time 2297 2298 Options Database: 2299 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime 2300 2301 Warning: If you use the option TS_EXACTFINALTIME_STEPOVER the solution may be at a very different time 2302 then the final time you selected. 2303 2304 Level: beginner 2305 2306 .seealso: `TSExactFinalTimeOption`, `TSGetExactFinalTime()` 2307 @*/ 2308 PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt) 2309 { 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2312 PetscValidLogicalCollectiveEnum(ts,eftopt,2); 2313 ts->exact_final_time = eftopt; 2314 PetscFunctionReturn(0); 2315 } 2316 2317 /*@ 2318 TSGetExactFinalTime - Gets the exact final time option. 2319 2320 Not Collective 2321 2322 Input Parameter: 2323 . ts - the TS context 2324 2325 Output Parameter: 2326 . eftopt - exact final time option 2327 2328 Level: beginner 2329 2330 .seealso: `TSExactFinalTimeOption`, `TSSetExactFinalTime()` 2331 @*/ 2332 PetscErrorCode TSGetExactFinalTime(TS ts,TSExactFinalTimeOption *eftopt) 2333 { 2334 PetscFunctionBegin; 2335 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2336 PetscValidPointer(eftopt,2); 2337 *eftopt = ts->exact_final_time; 2338 PetscFunctionReturn(0); 2339 } 2340 2341 /*@ 2342 TSGetTimeStep - Gets the current timestep size. 2343 2344 Not Collective 2345 2346 Input Parameter: 2347 . ts - the TS context obtained from TSCreate() 2348 2349 Output Parameter: 2350 . dt - the current timestep size 2351 2352 Level: intermediate 2353 2354 .seealso: `TSSetTimeStep()`, `TSGetTime()` 2355 2356 @*/ 2357 PetscErrorCode TSGetTimeStep(TS ts,PetscReal *dt) 2358 { 2359 PetscFunctionBegin; 2360 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2361 PetscValidRealPointer(dt,2); 2362 *dt = ts->time_step; 2363 PetscFunctionReturn(0); 2364 } 2365 2366 /*@ 2367 TSGetSolution - Returns the solution at the present timestep. It 2368 is valid to call this routine inside the function that you are evaluating 2369 in order to move to the new timestep. This vector not changed until 2370 the solution at the next timestep has been calculated. 2371 2372 Not Collective, but Vec returned is parallel if TS is parallel 2373 2374 Input Parameter: 2375 . ts - the TS context obtained from TSCreate() 2376 2377 Output Parameter: 2378 . v - the vector containing the solution 2379 2380 Note: If you used TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); this does not return the solution at the requested 2381 final time. It returns the solution at the next timestep. 2382 2383 Level: intermediate 2384 2385 .seealso: `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()` 2386 2387 @*/ 2388 PetscErrorCode TSGetSolution(TS ts,Vec *v) 2389 { 2390 PetscFunctionBegin; 2391 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2392 PetscValidPointer(v,2); 2393 *v = ts->vec_sol; 2394 PetscFunctionReturn(0); 2395 } 2396 2397 /*@ 2398 TSGetSolutionComponents - Returns any solution components at the present 2399 timestep, if available for the time integration method being used. 2400 Solution components are quantities that share the same size and 2401 structure as the solution vector. 2402 2403 Not Collective, but Vec returned is parallel if TS is parallel 2404 2405 Parameters : 2406 + ts - the TS context obtained from TSCreate() (input parameter). 2407 . n - If v is PETSC_NULL, then the number of solution components is 2408 returned through n, else the n-th solution component is 2409 returned in v. 2410 - v - the vector containing the n-th solution component 2411 (may be PETSC_NULL to use this function to find out 2412 the number of solutions components). 2413 2414 Level: advanced 2415 2416 .seealso: `TSGetSolution()` 2417 2418 @*/ 2419 PetscErrorCode TSGetSolutionComponents(TS ts,PetscInt *n,Vec *v) 2420 { 2421 PetscFunctionBegin; 2422 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2423 if (!ts->ops->getsolutioncomponents) *n = 0; 2424 else { 2425 PetscCall((*ts->ops->getsolutioncomponents)(ts,n,v)); 2426 } 2427 PetscFunctionReturn(0); 2428 } 2429 2430 /*@ 2431 TSGetAuxSolution - Returns an auxiliary solution at the present 2432 timestep, if available for the time integration method being used. 2433 2434 Not Collective, but Vec returned is parallel if TS is parallel 2435 2436 Parameters : 2437 + ts - the TS context obtained from TSCreate() (input parameter). 2438 - v - the vector containing the auxiliary solution 2439 2440 Level: intermediate 2441 2442 .seealso: `TSGetSolution()` 2443 2444 @*/ 2445 PetscErrorCode TSGetAuxSolution(TS ts,Vec *v) 2446 { 2447 PetscFunctionBegin; 2448 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2449 if (ts->ops->getauxsolution) { 2450 PetscCall((*ts->ops->getauxsolution)(ts,v)); 2451 } else { 2452 PetscCall(VecZeroEntries(*v)); 2453 } 2454 PetscFunctionReturn(0); 2455 } 2456 2457 /*@ 2458 TSGetTimeError - Returns the estimated error vector, if the chosen 2459 TSType has an error estimation functionality. 2460 2461 Not Collective, but Vec returned is parallel if TS is parallel 2462 2463 Note: MUST call after TSSetUp() 2464 2465 Parameters : 2466 + ts - the TS context obtained from TSCreate() (input parameter). 2467 . n - current estimate (n=0) or previous one (n=-1) 2468 - v - the vector containing the error (same size as the solution). 2469 2470 Level: intermediate 2471 2472 .seealso: `TSGetSolution()`, `TSSetTimeError()` 2473 2474 @*/ 2475 PetscErrorCode TSGetTimeError(TS ts,PetscInt n,Vec *v) 2476 { 2477 PetscFunctionBegin; 2478 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2479 if (ts->ops->gettimeerror) { 2480 PetscCall((*ts->ops->gettimeerror)(ts,n,v)); 2481 } else { 2482 PetscCall(VecZeroEntries(*v)); 2483 } 2484 PetscFunctionReturn(0); 2485 } 2486 2487 /*@ 2488 TSSetTimeError - Sets the estimated error vector, if the chosen 2489 TSType has an error estimation functionality. This can be used 2490 to restart such a time integrator with a given error vector. 2491 2492 Not Collective, but Vec returned is parallel if TS is parallel 2493 2494 Parameters : 2495 + ts - the TS context obtained from TSCreate() (input parameter). 2496 - v - the vector containing the error (same size as the solution). 2497 2498 Level: intermediate 2499 2500 .seealso: `TSSetSolution()`, `TSGetTimeError)` 2501 2502 @*/ 2503 PetscErrorCode TSSetTimeError(TS ts,Vec v) 2504 { 2505 PetscFunctionBegin; 2506 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2507 PetscCheck(ts->setupcalled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetUp() first"); 2508 if (ts->ops->settimeerror) PetscCall((*ts->ops->settimeerror)(ts,v)); 2509 PetscFunctionReturn(0); 2510 } 2511 2512 /* ----- Routines to initialize and destroy a timestepper ---- */ 2513 /*@ 2514 TSSetProblemType - Sets the type of problem to be solved. 2515 2516 Not collective 2517 2518 Input Parameters: 2519 + ts - The TS 2520 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms 2521 .vb 2522 U_t - A U = 0 (linear) 2523 U_t - A(t) U = 0 (linear) 2524 F(t,U,U_t) = 0 (nonlinear) 2525 .ve 2526 2527 Level: beginner 2528 2529 .seealso: `TSSetUp()`, `TSProblemType`, `TS` 2530 @*/ 2531 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2532 { 2533 PetscFunctionBegin; 2534 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2535 ts->problem_type = type; 2536 if (type == TS_LINEAR) { 2537 SNES snes; 2538 PetscCall(TSGetSNES(ts,&snes)); 2539 PetscCall(SNESSetType(snes,SNESKSPONLY)); 2540 } 2541 PetscFunctionReturn(0); 2542 } 2543 2544 /*@C 2545 TSGetProblemType - Gets the type of problem to be solved. 2546 2547 Not collective 2548 2549 Input Parameter: 2550 . ts - The TS 2551 2552 Output Parameter: 2553 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms 2554 .vb 2555 M U_t = A U 2556 M(t) U_t = A(t) U 2557 F(t,U,U_t) 2558 .ve 2559 2560 Level: beginner 2561 2562 .seealso: `TSSetUp()`, `TSProblemType`, `TS` 2563 @*/ 2564 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2565 { 2566 PetscFunctionBegin; 2567 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2568 PetscValidIntPointer(type,2); 2569 *type = ts->problem_type; 2570 PetscFunctionReturn(0); 2571 } 2572 2573 /* 2574 Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp() 2575 */ 2576 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts) 2577 { 2578 PetscBool isnone; 2579 2580 PetscFunctionBegin; 2581 PetscCall(TSGetAdapt(ts,&ts->adapt)); 2582 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 2583 2584 PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone)); 2585 if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) { 2586 ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 2587 } else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) { 2588 ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE; 2589 } 2590 PetscFunctionReturn(0); 2591 } 2592 2593 /*@ 2594 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2595 2596 Collective on TS 2597 2598 Input Parameter: 2599 . ts - the TS context obtained from TSCreate() 2600 2601 Notes: 2602 For basic use of the TS solvers the user need not explicitly call 2603 TSSetUp(), since these actions will automatically occur during 2604 the call to TSStep() or TSSolve(). However, if one wishes to control this 2605 phase separately, TSSetUp() should be called after TSCreate() 2606 and optional routines of the form TSSetXXX(), but before TSStep() and TSSolve(). 2607 2608 Level: advanced 2609 2610 .seealso: `TSCreate()`, `TSStep()`, `TSDestroy()`, `TSSolve()` 2611 @*/ 2612 PetscErrorCode TSSetUp(TS ts) 2613 { 2614 DM dm; 2615 PetscErrorCode (*func)(SNES,Vec,Vec,void*); 2616 PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*); 2617 TSIFunction ifun; 2618 TSIJacobian ijac; 2619 TSI2Jacobian i2jac; 2620 TSRHSJacobian rhsjac; 2621 2622 PetscFunctionBegin; 2623 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2624 if (ts->setupcalled) PetscFunctionReturn(0); 2625 2626 if (!((PetscObject)ts)->type_name) { 2627 PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL)); 2628 PetscCall(TSSetType(ts,ifun ? TSBEULER : TSEULER)); 2629 } 2630 2631 if (!ts->vec_sol) { 2632 if (ts->dm) { 2633 PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol)); 2634 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first"); 2635 } 2636 2637 if (ts->tspan) { 2638 if (!ts->tspan->vecs_sol) { 2639 PetscCall(VecDuplicateVecs(ts->vec_sol,ts->tspan->num_span_times,&ts->tspan->vecs_sol)); 2640 } 2641 } 2642 if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */ 2643 PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs)); 2644 ts->Jacp = ts->Jacprhs; 2645 } 2646 2647 if (ts->quadraturets) { 2648 PetscCall(TSSetUp(ts->quadraturets)); 2649 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2650 PetscCall(VecDuplicate(ts->quadraturets->vec_sol,&ts->vec_costintegrand)); 2651 } 2652 2653 PetscCall(TSGetRHSJacobian(ts,NULL,NULL,&rhsjac,NULL)); 2654 if (rhsjac == TSComputeRHSJacobianConstant) { 2655 Mat Amat,Pmat; 2656 SNES snes; 2657 PetscCall(TSGetSNES(ts,&snes)); 2658 PetscCall(SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL)); 2659 /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would 2660 * have displaced the RHS matrix */ 2661 if (Amat && Amat == ts->Arhs) { 2662 /* 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 */ 2663 PetscCall(MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat)); 2664 PetscCall(SNESSetJacobian(snes,Amat,NULL,NULL,NULL)); 2665 PetscCall(MatDestroy(&Amat)); 2666 } 2667 if (Pmat && Pmat == ts->Brhs) { 2668 PetscCall(MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat)); 2669 PetscCall(SNESSetJacobian(snes,NULL,Pmat,NULL,NULL)); 2670 PetscCall(MatDestroy(&Pmat)); 2671 } 2672 } 2673 2674 PetscCall(TSGetAdapt(ts,&ts->adapt)); 2675 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 2676 2677 if (ts->ops->setup) PetscCall((*ts->ops->setup)(ts)); 2678 2679 PetscCall(TSSetExactFinalTimeDefault(ts)); 2680 2681 /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction 2682 to be set right but can't do it elsewhere due to the overreliance on ctx=ts. 2683 */ 2684 PetscCall(TSGetDM(ts,&dm)); 2685 PetscCall(DMSNESGetFunction(dm,&func,NULL)); 2686 if (!func) { 2687 PetscCall(DMSNESSetFunction(dm,SNESTSFormFunction,ts)); 2688 } 2689 /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it. 2690 Otherwise, the SNES will use coloring internally to form the Jacobian. 2691 */ 2692 PetscCall(DMSNESGetJacobian(dm,&jac,NULL)); 2693 PetscCall(DMTSGetIJacobian(dm,&ijac,NULL)); 2694 PetscCall(DMTSGetI2Jacobian(dm,&i2jac,NULL)); 2695 PetscCall(DMTSGetRHSJacobian(dm,&rhsjac,NULL)); 2696 if (!jac && (ijac || i2jac || rhsjac)) { 2697 PetscCall(DMSNESSetJacobian(dm,SNESTSFormJacobian,ts)); 2698 } 2699 2700 /* if time integration scheme has a starting method, call it */ 2701 if (ts->ops->startingmethod) PetscCall((*ts->ops->startingmethod)(ts)); 2702 2703 ts->setupcalled = PETSC_TRUE; 2704 PetscFunctionReturn(0); 2705 } 2706 2707 /*@ 2708 TSReset - Resets a TS context and removes any allocated Vecs and Mats. 2709 2710 Collective on TS 2711 2712 Input Parameter: 2713 . ts - the TS context obtained from TSCreate() 2714 2715 Level: beginner 2716 2717 .seealso: `TSCreate()`, `TSSetup()`, `TSDestroy()` 2718 @*/ 2719 PetscErrorCode TSReset(TS ts) 2720 { 2721 TS_RHSSplitLink ilink = ts->tsrhssplit,next; 2722 2723 PetscFunctionBegin; 2724 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2725 2726 if (ts->ops->reset) PetscCall((*ts->ops->reset)(ts)); 2727 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2728 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2729 2730 PetscCall(MatDestroy(&ts->Arhs)); 2731 PetscCall(MatDestroy(&ts->Brhs)); 2732 PetscCall(VecDestroy(&ts->Frhs)); 2733 PetscCall(VecDestroy(&ts->vec_sol)); 2734 PetscCall(VecDestroy(&ts->vec_dot)); 2735 PetscCall(VecDestroy(&ts->vatol)); 2736 PetscCall(VecDestroy(&ts->vrtol)); 2737 PetscCall(VecDestroyVecs(ts->nwork,&ts->work)); 2738 2739 PetscCall(MatDestroy(&ts->Jacprhs)); 2740 PetscCall(MatDestroy(&ts->Jacp)); 2741 if (ts->forward_solve) PetscCall(TSForwardReset(ts)); 2742 if (ts->quadraturets) { 2743 PetscCall(TSReset(ts->quadraturets)); 2744 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2745 } 2746 while (ilink) { 2747 next = ilink->next; 2748 PetscCall(TSDestroy(&ilink->ts)); 2749 PetscCall(PetscFree(ilink->splitname)); 2750 PetscCall(ISDestroy(&ilink->is)); 2751 PetscCall(PetscFree(ilink)); 2752 ilink = next; 2753 } 2754 ts->tsrhssplit = NULL; 2755 ts->num_rhs_splits = 0; 2756 if (ts->tspan) { 2757 PetscCall(PetscFree(ts->tspan->span_times)); 2758 PetscCall(VecDestroyVecs(ts->tspan->num_span_times,&ts->tspan->vecs_sol)); 2759 PetscCall(PetscFree(ts->tspan)); 2760 } 2761 ts->setupcalled = PETSC_FALSE; 2762 PetscFunctionReturn(0); 2763 } 2764 2765 /*@C 2766 TSDestroy - Destroys the timestepper context that was created 2767 with TSCreate(). 2768 2769 Collective on TS 2770 2771 Input Parameter: 2772 . ts - the TS context obtained from TSCreate() 2773 2774 Level: beginner 2775 2776 .seealso: `TSCreate()`, `TSSetUp()`, `TSSolve()` 2777 @*/ 2778 PetscErrorCode TSDestroy(TS *ts) 2779 { 2780 PetscFunctionBegin; 2781 if (!*ts) PetscFunctionReturn(0); 2782 PetscValidHeaderSpecific(*ts,TS_CLASSID,1); 2783 if (--((PetscObject)(*ts))->refct > 0) {*ts = NULL; PetscFunctionReturn(0);} 2784 2785 PetscCall(TSReset(*ts)); 2786 PetscCall(TSAdjointReset(*ts)); 2787 if ((*ts)->forward_solve) { 2788 PetscCall(TSForwardReset(*ts)); 2789 } 2790 /* if memory was published with SAWs then destroy it */ 2791 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2792 if ((*ts)->ops->destroy) PetscCall((*(*ts)->ops->destroy)((*ts))); 2793 2794 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2795 2796 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2797 PetscCall(TSEventDestroy(&(*ts)->event)); 2798 2799 PetscCall(SNESDestroy(&(*ts)->snes)); 2800 PetscCall(DMDestroy(&(*ts)->dm)); 2801 PetscCall(TSMonitorCancel((*ts))); 2802 PetscCall(TSAdjointMonitorCancel((*ts))); 2803 2804 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2805 PetscCall(PetscHeaderDestroy(ts)); 2806 PetscFunctionReturn(0); 2807 } 2808 2809 /*@ 2810 TSGetSNES - Returns the SNES (nonlinear solver) associated with 2811 a TS (timestepper) context. Valid only for nonlinear problems. 2812 2813 Not Collective, but SNES is parallel if TS is parallel 2814 2815 Input Parameter: 2816 . ts - the TS context obtained from TSCreate() 2817 2818 Output Parameter: 2819 . snes - the nonlinear solver context 2820 2821 Notes: 2822 The user can then directly manipulate the SNES context to set various 2823 options, etc. Likewise, the user can then extract and manipulate the 2824 KSP, KSP, and PC contexts as well. 2825 2826 TSGetSNES() does not work for integrators that do not use SNES; in 2827 this case TSGetSNES() returns NULL in snes. 2828 2829 Level: beginner 2830 2831 @*/ 2832 PetscErrorCode TSGetSNES(TS ts,SNES *snes) 2833 { 2834 PetscFunctionBegin; 2835 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2836 PetscValidPointer(snes,2); 2837 if (!ts->snes) { 2838 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes)); 2839 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes,((PetscObject)ts)->options)); 2840 PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts)); 2841 PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes)); 2842 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1)); 2843 if (ts->dm) PetscCall(SNESSetDM(ts->snes,ts->dm)); 2844 if (ts->problem_type == TS_LINEAR) { 2845 PetscCall(SNESSetType(ts->snes,SNESKSPONLY)); 2846 } 2847 } 2848 *snes = ts->snes; 2849 PetscFunctionReturn(0); 2850 } 2851 2852 /*@ 2853 TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context 2854 2855 Collective 2856 2857 Input Parameters: 2858 + ts - the TS context obtained from TSCreate() 2859 - snes - the nonlinear solver context 2860 2861 Notes: 2862 Most users should have the TS created by calling TSGetSNES() 2863 2864 Level: developer 2865 2866 @*/ 2867 PetscErrorCode TSSetSNES(TS ts,SNES snes) 2868 { 2869 PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*); 2870 2871 PetscFunctionBegin; 2872 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2873 PetscValidHeaderSpecific(snes,SNES_CLASSID,2); 2874 PetscCall(PetscObjectReference((PetscObject)snes)); 2875 PetscCall(SNESDestroy(&ts->snes)); 2876 2877 ts->snes = snes; 2878 2879 PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts)); 2880 PetscCall(SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL)); 2881 if (func == SNESTSFormJacobian) { 2882 PetscCall(SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts)); 2883 } 2884 PetscFunctionReturn(0); 2885 } 2886 2887 /*@ 2888 TSGetKSP - Returns the KSP (linear solver) associated with 2889 a TS (timestepper) context. 2890 2891 Not Collective, but KSP is parallel if TS is parallel 2892 2893 Input Parameter: 2894 . ts - the TS context obtained from TSCreate() 2895 2896 Output Parameter: 2897 . ksp - the nonlinear solver context 2898 2899 Notes: 2900 The user can then directly manipulate the KSP context to set various 2901 options, etc. Likewise, the user can then extract and manipulate the 2902 KSP and PC contexts as well. 2903 2904 TSGetKSP() does not work for integrators that do not use KSP; 2905 in this case TSGetKSP() returns NULL in ksp. 2906 2907 Level: beginner 2908 2909 @*/ 2910 PetscErrorCode TSGetKSP(TS ts,KSP *ksp) 2911 { 2912 SNES snes; 2913 2914 PetscFunctionBegin; 2915 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2916 PetscValidPointer(ksp,2); 2917 PetscCheck(((PetscObject)ts)->type_name,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first"); 2918 PetscCheck(ts->problem_type == TS_LINEAR,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()"); 2919 PetscCall(TSGetSNES(ts,&snes)); 2920 PetscCall(SNESGetKSP(snes,ksp)); 2921 PetscFunctionReturn(0); 2922 } 2923 2924 /* ----------- Routines to set solver parameters ---------- */ 2925 2926 /*@ 2927 TSSetMaxSteps - Sets the maximum number of steps to use. 2928 2929 Logically Collective on TS 2930 2931 Input Parameters: 2932 + ts - the TS context obtained from TSCreate() 2933 - maxsteps - maximum number of steps to use 2934 2935 Options Database Keys: 2936 . -ts_max_steps <maxsteps> - Sets maxsteps 2937 2938 Notes: 2939 The default maximum number of steps is 5000 2940 2941 Level: intermediate 2942 2943 .seealso: `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2944 @*/ 2945 PetscErrorCode TSSetMaxSteps(TS ts,PetscInt maxsteps) 2946 { 2947 PetscFunctionBegin; 2948 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2949 PetscValidLogicalCollectiveInt(ts,maxsteps,2); 2950 PetscCheck(maxsteps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of steps must be non-negative"); 2951 ts->max_steps = maxsteps; 2952 PetscFunctionReturn(0); 2953 } 2954 2955 /*@ 2956 TSGetMaxSteps - Gets the maximum number of steps to use. 2957 2958 Not Collective 2959 2960 Input Parameters: 2961 . ts - the TS context obtained from TSCreate() 2962 2963 Output Parameter: 2964 . maxsteps - maximum number of steps to use 2965 2966 Level: advanced 2967 2968 .seealso: `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2969 @*/ 2970 PetscErrorCode TSGetMaxSteps(TS ts,PetscInt *maxsteps) 2971 { 2972 PetscFunctionBegin; 2973 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2974 PetscValidIntPointer(maxsteps,2); 2975 *maxsteps = ts->max_steps; 2976 PetscFunctionReturn(0); 2977 } 2978 2979 /*@ 2980 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2981 2982 Logically Collective on TS 2983 2984 Input Parameters: 2985 + ts - the TS context obtained from TSCreate() 2986 - maxtime - final time to step to 2987 2988 Options Database Keys: 2989 . -ts_max_time <maxtime> - Sets maxtime 2990 2991 Notes: 2992 The default maximum time is 5.0 2993 2994 Level: intermediate 2995 2996 .seealso: `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2997 @*/ 2998 PetscErrorCode TSSetMaxTime(TS ts,PetscReal maxtime) 2999 { 3000 PetscFunctionBegin; 3001 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3002 PetscValidLogicalCollectiveReal(ts,maxtime,2); 3003 ts->max_time = maxtime; 3004 PetscFunctionReturn(0); 3005 } 3006 3007 /*@ 3008 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 3009 3010 Not Collective 3011 3012 Input Parameters: 3013 . ts - the TS context obtained from TSCreate() 3014 3015 Output Parameter: 3016 . maxtime - final time to step to 3017 3018 Level: advanced 3019 3020 .seealso: `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 3021 @*/ 3022 PetscErrorCode TSGetMaxTime(TS ts,PetscReal *maxtime) 3023 { 3024 PetscFunctionBegin; 3025 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3026 PetscValidRealPointer(maxtime,2); 3027 *maxtime = ts->max_time; 3028 PetscFunctionReturn(0); 3029 } 3030 3031 /*@ 3032 TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep(). 3033 3034 Level: deprecated 3035 3036 @*/ 3037 PetscErrorCode TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step) 3038 { 3039 PetscFunctionBegin; 3040 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3041 PetscCall(TSSetTime(ts,initial_time)); 3042 PetscCall(TSSetTimeStep(ts,time_step)); 3043 PetscFunctionReturn(0); 3044 } 3045 3046 /*@ 3047 TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime(). 3048 3049 Level: deprecated 3050 3051 @*/ 3052 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 3053 { 3054 PetscFunctionBegin; 3055 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3056 if (maxsteps) { 3057 PetscValidIntPointer(maxsteps,2); 3058 *maxsteps = ts->max_steps; 3059 } 3060 if (maxtime) { 3061 PetscValidRealPointer(maxtime,3); 3062 *maxtime = ts->max_time; 3063 } 3064 PetscFunctionReturn(0); 3065 } 3066 3067 /*@ 3068 TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime(). 3069 3070 Level: deprecated 3071 3072 @*/ 3073 PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime) 3074 { 3075 PetscFunctionBegin; 3076 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3077 PetscValidLogicalCollectiveInt(ts,maxsteps,2); 3078 PetscValidLogicalCollectiveReal(ts,maxtime,3); 3079 if (maxsteps >= 0) ts->max_steps = maxsteps; 3080 if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime; 3081 PetscFunctionReturn(0); 3082 } 3083 3084 /*@ 3085 TSGetTimeStepNumber - Deprecated, use TSGetStepNumber(). 3086 3087 Level: deprecated 3088 3089 @*/ 3090 PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); } 3091 3092 /*@ 3093 TSGetTotalSteps - Deprecated, use TSGetStepNumber(). 3094 3095 Level: deprecated 3096 3097 @*/ 3098 PetscErrorCode TSGetTotalSteps(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); } 3099 3100 /*@ 3101 TSSetSolution - Sets the initial solution vector 3102 for use by the TS routines. 3103 3104 Logically Collective on TS 3105 3106 Input Parameters: 3107 + ts - the TS context obtained from TSCreate() 3108 - u - the solution vector 3109 3110 Level: beginner 3111 3112 .seealso: `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 3113 @*/ 3114 PetscErrorCode TSSetSolution(TS ts,Vec u) 3115 { 3116 DM dm; 3117 3118 PetscFunctionBegin; 3119 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3120 PetscValidHeaderSpecific(u,VEC_CLASSID,2); 3121 PetscCall(PetscObjectReference((PetscObject)u)); 3122 PetscCall(VecDestroy(&ts->vec_sol)); 3123 ts->vec_sol = u; 3124 3125 PetscCall(TSGetDM(ts,&dm)); 3126 PetscCall(DMShellSetGlobalVector(dm,u)); 3127 PetscFunctionReturn(0); 3128 } 3129 3130 /*@C 3131 TSSetPreStep - Sets the general-purpose function 3132 called once at the beginning of each time step. 3133 3134 Logically Collective on TS 3135 3136 Input Parameters: 3137 + ts - The TS context obtained from TSCreate() 3138 - func - The function 3139 3140 Calling sequence of func: 3141 .vb 3142 PetscErrorCode func (TS ts); 3143 .ve 3144 3145 Level: intermediate 3146 3147 .seealso: `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3148 @*/ 3149 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS)) 3150 { 3151 PetscFunctionBegin; 3152 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3153 ts->prestep = func; 3154 PetscFunctionReturn(0); 3155 } 3156 3157 /*@ 3158 TSPreStep - Runs the user-defined pre-step function. 3159 3160 Collective on TS 3161 3162 Input Parameters: 3163 . ts - The TS context obtained from TSCreate() 3164 3165 Notes: 3166 TSPreStep() is typically used within time stepping implementations, 3167 so most users would not generally call this routine themselves. 3168 3169 Level: developer 3170 3171 .seealso: `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3172 @*/ 3173 PetscErrorCode TSPreStep(TS ts) 3174 { 3175 PetscFunctionBegin; 3176 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3177 if (ts->prestep) { 3178 Vec U; 3179 PetscObjectId idprev; 3180 PetscBool sameObject; 3181 PetscObjectState sprev,spost; 3182 3183 PetscCall(TSGetSolution(ts,&U)); 3184 PetscCall(PetscObjectGetId((PetscObject)U,&idprev)); 3185 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3186 PetscStackCallStandard((*ts->prestep),ts); 3187 PetscCall(TSGetSolution(ts,&U)); 3188 PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject)); 3189 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3190 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3191 } 3192 PetscFunctionReturn(0); 3193 } 3194 3195 /*@C 3196 TSSetPreStage - Sets the general-purpose function 3197 called once at the beginning of each stage. 3198 3199 Logically Collective on TS 3200 3201 Input Parameters: 3202 + ts - The TS context obtained from TSCreate() 3203 - func - The function 3204 3205 Calling sequence of func: 3206 .vb 3207 PetscErrorCode func(TS ts, PetscReal stagetime); 3208 .ve 3209 3210 Level: intermediate 3211 3212 Note: 3213 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3214 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3215 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3216 3217 .seealso: `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3218 @*/ 3219 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal)) 3220 { 3221 PetscFunctionBegin; 3222 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3223 ts->prestage = func; 3224 PetscFunctionReturn(0); 3225 } 3226 3227 /*@C 3228 TSSetPostStage - Sets the general-purpose function 3229 called once at the end of each stage. 3230 3231 Logically Collective on TS 3232 3233 Input Parameters: 3234 + ts - The TS context obtained from TSCreate() 3235 - func - The function 3236 3237 Calling sequence of func: 3238 .vb 3239 PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y); 3240 .ve 3241 3242 Level: intermediate 3243 3244 Note: 3245 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3246 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3247 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3248 3249 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3250 @*/ 3251 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*)) 3252 { 3253 PetscFunctionBegin; 3254 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3255 ts->poststage = func; 3256 PetscFunctionReturn(0); 3257 } 3258 3259 /*@C 3260 TSSetPostEvaluate - Sets the general-purpose function 3261 called once at the end of each step evaluation. 3262 3263 Logically Collective on TS 3264 3265 Input Parameters: 3266 + ts - The TS context obtained from TSCreate() 3267 - func - The function 3268 3269 Calling sequence of func: 3270 .vb 3271 PetscErrorCode func(TS ts); 3272 .ve 3273 3274 Level: intermediate 3275 3276 Note: 3277 Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling 3278 thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep() 3279 may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step 3280 solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step 3281 with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime() 3282 3283 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3284 @*/ 3285 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS)) 3286 { 3287 PetscFunctionBegin; 3288 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3289 ts->postevaluate = func; 3290 PetscFunctionReturn(0); 3291 } 3292 3293 /*@ 3294 TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage() 3295 3296 Collective on TS 3297 3298 Input Parameters: 3299 . ts - The TS context obtained from TSCreate() 3300 stagetime - The absolute time of the current stage 3301 3302 Notes: 3303 TSPreStage() is typically used within time stepping implementations, 3304 most users would not generally call this routine themselves. 3305 3306 Level: developer 3307 3308 .seealso: `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3309 @*/ 3310 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3311 { 3312 PetscFunctionBegin; 3313 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3314 if (ts->prestage) { 3315 PetscStackCallStandard((*ts->prestage),ts,stagetime); 3316 } 3317 PetscFunctionReturn(0); 3318 } 3319 3320 /*@ 3321 TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage() 3322 3323 Collective on TS 3324 3325 Input Parameters: 3326 . ts - The TS context obtained from TSCreate() 3327 stagetime - The absolute time of the current stage 3328 stageindex - Stage number 3329 Y - Array of vectors (of size = total number 3330 of stages) with the stage solutions 3331 3332 Notes: 3333 TSPostStage() is typically used within time stepping implementations, 3334 most users would not generally call this routine themselves. 3335 3336 Level: developer 3337 3338 .seealso: `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3339 @*/ 3340 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3341 { 3342 PetscFunctionBegin; 3343 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3344 if (ts->poststage) { 3345 PetscStackCallStandard((*ts->poststage),ts,stagetime,stageindex,Y); 3346 } 3347 PetscFunctionReturn(0); 3348 } 3349 3350 /*@ 3351 TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate() 3352 3353 Collective on TS 3354 3355 Input Parameters: 3356 . ts - The TS context obtained from TSCreate() 3357 3358 Notes: 3359 TSPostEvaluate() is typically used within time stepping implementations, 3360 most users would not generally call this routine themselves. 3361 3362 Level: developer 3363 3364 .seealso: `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3365 @*/ 3366 PetscErrorCode TSPostEvaluate(TS ts) 3367 { 3368 PetscFunctionBegin; 3369 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3370 if (ts->postevaluate) { 3371 Vec U; 3372 PetscObjectState sprev,spost; 3373 3374 PetscCall(TSGetSolution(ts,&U)); 3375 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3376 PetscStackCallStandard((*ts->postevaluate),ts); 3377 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3378 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3379 } 3380 PetscFunctionReturn(0); 3381 } 3382 3383 /*@C 3384 TSSetPostStep - Sets the general-purpose function 3385 called once at the end of each time step. 3386 3387 Logically Collective on TS 3388 3389 Input Parameters: 3390 + ts - The TS context obtained from TSCreate() 3391 - func - The function 3392 3393 Calling sequence of func: 3394 $ func (TS ts); 3395 3396 Notes: 3397 The function set by TSSetPostStep() is called after each successful step. The solution vector X 3398 obtained by TSGetSolution() may be different than that computed at the step end if the event handler 3399 locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead. 3400 3401 Level: intermediate 3402 3403 .seealso: `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3404 @*/ 3405 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS)) 3406 { 3407 PetscFunctionBegin; 3408 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3409 ts->poststep = func; 3410 PetscFunctionReturn(0); 3411 } 3412 3413 /*@ 3414 TSPostStep - Runs the user-defined post-step function. 3415 3416 Collective on TS 3417 3418 Input Parameters: 3419 . ts - The TS context obtained from TSCreate() 3420 3421 Notes: 3422 TSPostStep() is typically used within time stepping implementations, 3423 so most users would not generally call this routine themselves. 3424 3425 Level: developer 3426 3427 @*/ 3428 PetscErrorCode TSPostStep(TS ts) 3429 { 3430 PetscFunctionBegin; 3431 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3432 if (ts->poststep) { 3433 Vec U; 3434 PetscObjectId idprev; 3435 PetscBool sameObject; 3436 PetscObjectState sprev,spost; 3437 3438 PetscCall(TSGetSolution(ts,&U)); 3439 PetscCall(PetscObjectGetId((PetscObject)U,&idprev)); 3440 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3441 PetscStackCallStandard((*ts->poststep),ts); 3442 PetscCall(TSGetSolution(ts,&U)); 3443 PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject)); 3444 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3445 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3446 } 3447 PetscFunctionReturn(0); 3448 } 3449 3450 /*@ 3451 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3452 3453 Collective on TS 3454 3455 Input Parameters: 3456 + ts - time stepping context 3457 - t - time to interpolate to 3458 3459 Output Parameter: 3460 . U - state at given time 3461 3462 Level: intermediate 3463 3464 Developer Notes: 3465 TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3466 3467 .seealso: `TSSetExactFinalTime()`, `TSSolve()` 3468 @*/ 3469 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U) 3470 { 3471 PetscFunctionBegin; 3472 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3473 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 3474 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); 3475 PetscCheck(ts->ops->interpolate,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name); 3476 PetscCall((*ts->ops->interpolate)(ts,t,U)); 3477 PetscFunctionReturn(0); 3478 } 3479 3480 /*@ 3481 TSStep - Steps one time step 3482 3483 Collective on TS 3484 3485 Input Parameter: 3486 . ts - the TS context obtained from TSCreate() 3487 3488 Level: developer 3489 3490 Notes: 3491 The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine. 3492 3493 The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may 3494 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3495 3496 This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the 3497 time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep. 3498 3499 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3500 @*/ 3501 PetscErrorCode TSStep(TS ts) 3502 { 3503 static PetscBool cite = PETSC_FALSE; 3504 PetscReal ptime; 3505 3506 PetscFunctionBegin; 3507 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3508 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3509 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3510 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3511 " journal = {arXiv e-preprints},\n" 3512 " eprint = {1806.01437},\n" 3513 " archivePrefix = {arXiv},\n" 3514 " year = {2018}\n}\n",&cite)); 3515 PetscCall(TSSetUp(ts)); 3516 PetscCall(TSTrajectorySetUp(ts->trajectory,ts)); 3517 3518 PetscCheck(ts->ops->step,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name); 3519 PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_MAX_INT,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>"); 3520 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()"); 3521 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"); 3522 3523 if (!ts->steps) ts->ptime_prev = ts->ptime; 3524 ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev; 3525 ts->reason = TS_CONVERGED_ITERATING; 3526 3527 PetscCall(PetscLogEventBegin(TS_Step,ts,0,0,0)); 3528 PetscCall((*ts->ops->step)(ts)); 3529 PetscCall(PetscLogEventEnd(TS_Step,ts,0,0,0)); 3530 3531 if (ts->reason >= 0) { 3532 ts->ptime_prev = ptime; 3533 ts->steps++; 3534 ts->steprollback = PETSC_FALSE; 3535 ts->steprestart = PETSC_FALSE; 3536 if (ts->tspan && PetscIsCloseAtTol(ts->ptime,ts->tspan->span_times[ts->tspan->spanctr],10*PETSC_MACHINE_EPSILON,0) && ts->tspan->spanctr < ts->tspan->num_span_times) PetscCall(VecCopy(ts->vec_sol,ts->tspan->vecs_sol[ts->tspan->spanctr++])); 3537 } 3538 3539 if (!ts->reason) { 3540 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3541 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3542 } 3543 3544 PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed || 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 make negative to attempt recovery",TSConvergedReasons[ts->reason]); 3545 PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed,PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]); 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /*@ 3550 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3551 at the end of a time step with a given order of accuracy. 3552 3553 Collective on TS 3554 3555 Input Parameters: 3556 + ts - time stepping context 3557 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 3558 3559 Input/Output Parameter: 3560 . order - optional, desired order for the error evaluation or PETSC_DECIDE; 3561 on output, the actual order of the error evaluation 3562 3563 Output Parameter: 3564 . wlte - the weighted local truncation error norm 3565 3566 Level: advanced 3567 3568 Notes: 3569 If the timestepper cannot evaluate the error in a particular step 3570 (eg. in the first step or restart steps after event handling), 3571 this routine returns wlte=-1.0 . 3572 3573 .seealso: `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3574 @*/ 3575 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 3576 { 3577 PetscFunctionBegin; 3578 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3579 PetscValidType(ts,1); 3580 PetscValidLogicalCollectiveEnum(ts,wnormtype,2); 3581 if (order) PetscValidIntPointer(order,3); 3582 if (order) PetscValidLogicalCollectiveInt(ts,*order,3); 3583 PetscValidRealPointer(wlte,4); 3584 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]); 3585 PetscCheck(ts->ops->evaluatewlte,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name); 3586 PetscCall((*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte)); 3587 PetscFunctionReturn(0); 3588 } 3589 3590 /*@ 3591 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3592 3593 Collective on TS 3594 3595 Input Parameters: 3596 + ts - time stepping context 3597 . order - desired order of accuracy 3598 - done - whether the step was evaluated at this order (pass NULL to generate an error if not available) 3599 3600 Output Parameter: 3601 . U - state at the end of the current step 3602 3603 Level: advanced 3604 3605 Notes: 3606 This function cannot be called until all stages have been evaluated. 3607 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. 3608 3609 .seealso: `TSStep()`, `TSAdapt` 3610 @*/ 3611 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done) 3612 { 3613 PetscFunctionBegin; 3614 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3615 PetscValidType(ts,1); 3616 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 3617 PetscCheck(ts->ops->evaluatestep,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name); 3618 PetscCall((*ts->ops->evaluatestep)(ts,order,U,done)); 3619 PetscFunctionReturn(0); 3620 } 3621 3622 /*@C 3623 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3624 3625 Not collective 3626 3627 Input Parameter: 3628 . ts - time stepping context 3629 3630 Output Parameter: 3631 . initConditions - The function which computes an initial condition 3632 3633 Level: advanced 3634 3635 Notes: 3636 The calling sequence for the function is 3637 $ initCondition(TS ts, Vec u) 3638 $ ts - The timestepping context 3639 $ u - The input vector in which the initial condition is stored 3640 3641 .seealso: `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3642 @*/ 3643 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec)) 3644 { 3645 PetscFunctionBegin; 3646 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3647 PetscValidPointer(initCondition, 2); 3648 *initCondition = ts->ops->initcondition; 3649 PetscFunctionReturn(0); 3650 } 3651 3652 /*@C 3653 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3654 3655 Logically collective on ts 3656 3657 Input Parameters: 3658 + ts - time stepping context 3659 - initCondition - The function which computes an initial condition 3660 3661 Level: advanced 3662 3663 Calling sequence for initCondition: 3664 $ PetscErrorCode initCondition(TS ts, Vec u) 3665 3666 + ts - The timestepping context 3667 - u - The input vector in which the initial condition is to be stored 3668 3669 .seealso: `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3670 @*/ 3671 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec)) 3672 { 3673 PetscFunctionBegin; 3674 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3675 PetscValidFunction(initCondition, 2); 3676 ts->ops->initcondition = initCondition; 3677 PetscFunctionReturn(0); 3678 } 3679 3680 /*@ 3681 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set. 3682 3683 Collective on ts 3684 3685 Input Parameters: 3686 + ts - time stepping context 3687 - u - The Vec to store the condition in which will be used in TSSolve() 3688 3689 Level: advanced 3690 3691 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3692 @*/ 3693 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3694 { 3695 PetscFunctionBegin; 3696 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3697 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3698 if (ts->ops->initcondition) PetscCall((*ts->ops->initcondition)(ts, u)); 3699 PetscFunctionReturn(0); 3700 } 3701 3702 /*@C 3703 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3704 3705 Not collective 3706 3707 Input Parameter: 3708 . ts - time stepping context 3709 3710 Output Parameter: 3711 . exactError - The function which computes the solution error 3712 3713 Level: advanced 3714 3715 Calling sequence for exactError: 3716 $ PetscErrorCode exactError(TS ts, Vec u) 3717 3718 + ts - The timestepping context 3719 . u - The approximate solution vector 3720 - e - The input vector in which the error is stored 3721 3722 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()` 3723 @*/ 3724 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec)) 3725 { 3726 PetscFunctionBegin; 3727 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3728 PetscValidPointer(exactError, 2); 3729 *exactError = ts->ops->exacterror; 3730 PetscFunctionReturn(0); 3731 } 3732 3733 /*@C 3734 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3735 3736 Logically collective on ts 3737 3738 Input Parameters: 3739 + ts - time stepping context 3740 - exactError - The function which computes the solution error 3741 3742 Level: advanced 3743 3744 Calling sequence for exactError: 3745 $ PetscErrorCode exactError(TS ts, Vec u) 3746 3747 + ts - The timestepping context 3748 . u - The approximate solution vector 3749 - e - The input vector in which the error is stored 3750 3751 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()` 3752 @*/ 3753 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec)) 3754 { 3755 PetscFunctionBegin; 3756 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3757 PetscValidFunction(exactError, 2); 3758 ts->ops->exacterror = exactError; 3759 PetscFunctionReturn(0); 3760 } 3761 3762 /*@ 3763 TSComputeExactError - Compute the solution error for the timestepping using the function previously set. 3764 3765 Collective on ts 3766 3767 Input Parameters: 3768 + ts - time stepping context 3769 . u - The approximate solution 3770 - e - The Vec used to store the error 3771 3772 Level: advanced 3773 3774 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3775 @*/ 3776 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3777 { 3778 PetscFunctionBegin; 3779 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3780 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3781 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3782 if (ts->ops->exacterror) PetscCall((*ts->ops->exacterror)(ts, u, e)); 3783 PetscFunctionReturn(0); 3784 } 3785 3786 /*@ 3787 TSSolve - Steps the requested number of timesteps. 3788 3789 Collective on TS 3790 3791 Input Parameters: 3792 + ts - the TS context obtained from TSCreate() 3793 - u - the solution vector (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used, 3794 otherwise must contain the initial conditions and will contain the solution at the final requested time 3795 3796 Level: beginner 3797 3798 Notes: 3799 The final time returned by this function may be different from the time of the internally 3800 held state accessible by TSGetSolution() and TSGetTime() because the method may have 3801 stepped over the final time. 3802 3803 .seealso: `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3804 @*/ 3805 PetscErrorCode TSSolve(TS ts,Vec u) 3806 { 3807 Vec solution; 3808 3809 PetscFunctionBegin; 3810 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3811 if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2); 3812 3813 PetscCall(TSSetExactFinalTimeDefault(ts)); 3814 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 */ 3815 if (!ts->vec_sol || u == ts->vec_sol) { 3816 PetscCall(VecDuplicate(u,&solution)); 3817 PetscCall(TSSetSolution(ts,solution)); 3818 PetscCall(VecDestroy(&solution)); /* grant ownership */ 3819 } 3820 PetscCall(VecCopy(u,ts->vec_sol)); 3821 PetscCheck(!ts->forward_solve,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 3822 } else if (u) PetscCall(TSSetSolution(ts,u)); 3823 PetscCall(TSSetUp(ts)); 3824 PetscCall(TSTrajectorySetUp(ts->trajectory,ts)); 3825 3826 PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_MAX_INT,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>"); 3827 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()"); 3828 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"); 3829 PetscCheck(!(ts->tspan && ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP),PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"You must use TS_EXACTFINALTIME_MATCHSTEP when using time span"); 3830 3831 if (ts->tspan && PetscIsCloseAtTol(ts->ptime,ts->tspan->span_times[0],10*PETSC_MACHINE_EPSILON,0)) { /* starting point in time span */ 3832 PetscCall(VecCopy(ts->vec_sol,ts->tspan->vecs_sol[0])); 3833 ts->tspan->spanctr = 1; 3834 } 3835 3836 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 3837 3838 /* reset number of steps only when the step is not restarted. ARKIMEX 3839 restarts the step after an event. Resetting these counters in such case causes 3840 TSTrajectory to incorrectly save the output files 3841 */ 3842 /* reset time step and iteration counters */ 3843 if (!ts->steps) { 3844 ts->ksp_its = 0; 3845 ts->snes_its = 0; 3846 ts->num_snes_failures = 0; 3847 ts->reject = 0; 3848 ts->steprestart = PETSC_TRUE; 3849 ts->steprollback = PETSC_FALSE; 3850 ts->rhsjacobian.time = PETSC_MIN_REAL; 3851 } 3852 3853 /* make sure initial time step does not overshoot final time or the next point in tspan */ 3854 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 3855 PetscReal maxdt; 3856 PetscReal dt = ts->time_step; 3857 3858 if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime; 3859 else maxdt = ts->max_time - ts->ptime; 3860 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt); 3861 } 3862 ts->reason = TS_CONVERGED_ITERATING; 3863 3864 { 3865 PetscViewer viewer; 3866 PetscViewerFormat format; 3867 PetscBool flg; 3868 static PetscBool incall = PETSC_FALSE; 3869 3870 if (!incall) { 3871 /* Estimate the convergence rate of the time discretization */ 3872 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject) ts),((PetscObject)ts)->options, ((PetscObject) ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 3873 if (flg) { 3874 PetscConvEst conv; 3875 DM dm; 3876 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 3877 PetscInt Nf; 3878 PetscBool checkTemporal = PETSC_TRUE; 3879 3880 incall = PETSC_TRUE; 3881 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject) ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 3882 PetscCall(TSGetDM(ts, &dm)); 3883 PetscCall(DMGetNumFields(dm, &Nf)); 3884 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 3885 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject) ts), &conv)); 3886 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 3887 PetscCall(PetscConvEstSetSolver(conv, (PetscObject) ts)); 3888 PetscCall(PetscConvEstSetFromOptions(conv)); 3889 PetscCall(PetscConvEstSetUp(conv)); 3890 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 3891 PetscCall(PetscViewerPushFormat(viewer, format)); 3892 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 3893 PetscCall(PetscViewerPopFormat(viewer)); 3894 PetscCall(PetscViewerDestroy(&viewer)); 3895 PetscCall(PetscConvEstDestroy(&conv)); 3896 PetscCall(PetscFree(alpha)); 3897 incall = PETSC_FALSE; 3898 } 3899 } 3900 } 3901 3902 PetscCall(TSViewFromOptions(ts,NULL,"-ts_view_pre")); 3903 3904 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 3905 PetscCall((*ts->ops->solve)(ts)); 3906 if (u) PetscCall(VecCopy(ts->vec_sol,u)); 3907 ts->solvetime = ts->ptime; 3908 solution = ts->vec_sol; 3909 } else { /* Step the requested number of timesteps. */ 3910 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3911 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3912 3913 if (!ts->steps) { 3914 PetscCall(TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol)); 3915 PetscCall(TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol)); 3916 } 3917 3918 while (!ts->reason) { 3919 PetscCall(TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol)); 3920 if (!ts->steprollback) { 3921 PetscCall(TSPreStep(ts)); 3922 } 3923 PetscCall(TSStep(ts)); 3924 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts,NULL)); 3925 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts,NULL)); 3926 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 3927 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3928 PetscCall(TSForwardCostIntegral(ts)); 3929 if (ts->reason >= 0) ts->steps++; 3930 } 3931 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 3932 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3933 PetscCall(TSForwardStep(ts)); 3934 if (ts->reason >= 0) ts->steps++; 3935 } 3936 PetscCall(TSPostEvaluate(ts)); 3937 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. */ 3938 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 3939 if (!ts->steprollback) { 3940 PetscCall(TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol)); 3941 PetscCall(TSPostStep(ts)); 3942 } 3943 } 3944 PetscCall(TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol)); 3945 3946 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 3947 PetscCall(TSInterpolate(ts,ts->max_time,u)); 3948 ts->solvetime = ts->max_time; 3949 solution = u; 3950 PetscCall(TSMonitor(ts,-1,ts->solvetime,solution)); 3951 } else { 3952 if (u) PetscCall(VecCopy(ts->vec_sol,u)); 3953 ts->solvetime = ts->ptime; 3954 solution = ts->vec_sol; 3955 } 3956 } 3957 3958 PetscCall(TSViewFromOptions(ts,NULL,"-ts_view")); 3959 PetscCall(VecViewFromOptions(solution,(PetscObject)ts,"-ts_view_solution")); 3960 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 3961 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 3962 PetscFunctionReturn(0); 3963 } 3964 3965 /*@ 3966 TSGetTime - Gets the time of the most recently completed step. 3967 3968 Not Collective 3969 3970 Input Parameter: 3971 . ts - the TS context obtained from TSCreate() 3972 3973 Output Parameter: 3974 . t - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime(). 3975 3976 Level: beginner 3977 3978 Note: 3979 When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(), 3980 TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated. 3981 3982 .seealso: `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 3983 3984 @*/ 3985 PetscErrorCode TSGetTime(TS ts,PetscReal *t) 3986 { 3987 PetscFunctionBegin; 3988 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3989 PetscValidRealPointer(t,2); 3990 *t = ts->ptime; 3991 PetscFunctionReturn(0); 3992 } 3993 3994 /*@ 3995 TSGetPrevTime - Gets the starting time of the previously completed step. 3996 3997 Not Collective 3998 3999 Input Parameter: 4000 . ts - the TS context obtained from TSCreate() 4001 4002 Output Parameter: 4003 . t - the previous time 4004 4005 Level: beginner 4006 4007 .seealso: `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4008 4009 @*/ 4010 PetscErrorCode TSGetPrevTime(TS ts,PetscReal *t) 4011 { 4012 PetscFunctionBegin; 4013 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4014 PetscValidRealPointer(t,2); 4015 *t = ts->ptime_prev; 4016 PetscFunctionReturn(0); 4017 } 4018 4019 /*@ 4020 TSSetTime - Allows one to reset the time. 4021 4022 Logically Collective on TS 4023 4024 Input Parameters: 4025 + ts - the TS context obtained from TSCreate() 4026 - time - the time 4027 4028 Level: intermediate 4029 4030 .seealso: `TSGetTime()`, `TSSetMaxSteps()` 4031 4032 @*/ 4033 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4034 { 4035 PetscFunctionBegin; 4036 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4037 PetscValidLogicalCollectiveReal(ts,t,2); 4038 ts->ptime = t; 4039 PetscFunctionReturn(0); 4040 } 4041 4042 /*@C 4043 TSSetOptionsPrefix - Sets the prefix used for searching for all 4044 TS options in the database. 4045 4046 Logically Collective on TS 4047 4048 Input Parameters: 4049 + ts - The TS context 4050 - prefix - The prefix to prepend to all option names 4051 4052 Notes: 4053 A hyphen (-) must NOT be given at the beginning of the prefix name. 4054 The first character of all runtime options is AUTOMATICALLY the 4055 hyphen. 4056 4057 Level: advanced 4058 4059 .seealso: `TSSetFromOptions()` 4060 4061 @*/ 4062 PetscErrorCode TSSetOptionsPrefix(TS ts,const char prefix[]) 4063 { 4064 SNES snes; 4065 4066 PetscFunctionBegin; 4067 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4068 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts,prefix)); 4069 PetscCall(TSGetSNES(ts,&snes)); 4070 PetscCall(SNESSetOptionsPrefix(snes,prefix)); 4071 PetscFunctionReturn(0); 4072 } 4073 4074 /*@C 4075 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4076 TS options in the database. 4077 4078 Logically Collective on TS 4079 4080 Input Parameters: 4081 + ts - The TS context 4082 - prefix - The prefix to prepend to all option names 4083 4084 Notes: 4085 A hyphen (-) must NOT be given at the beginning of the prefix name. 4086 The first character of all runtime options is AUTOMATICALLY the 4087 hyphen. 4088 4089 Level: advanced 4090 4091 .seealso: `TSGetOptionsPrefix()` 4092 4093 @*/ 4094 PetscErrorCode TSAppendOptionsPrefix(TS ts,const char prefix[]) 4095 { 4096 SNES snes; 4097 4098 PetscFunctionBegin; 4099 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4100 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix)); 4101 PetscCall(TSGetSNES(ts,&snes)); 4102 PetscCall(SNESAppendOptionsPrefix(snes,prefix)); 4103 PetscFunctionReturn(0); 4104 } 4105 4106 /*@C 4107 TSGetOptionsPrefix - Sets the prefix used for searching for all 4108 TS options in the database. 4109 4110 Not Collective 4111 4112 Input Parameter: 4113 . ts - The TS context 4114 4115 Output Parameter: 4116 . prefix - A pointer to the prefix string used 4117 4118 Notes: 4119 On the fortran side, the user should pass in a string 'prifix' of 4120 sufficient length to hold the prefix. 4121 4122 Level: intermediate 4123 4124 .seealso: `TSAppendOptionsPrefix()` 4125 @*/ 4126 PetscErrorCode TSGetOptionsPrefix(TS ts,const char *prefix[]) 4127 { 4128 PetscFunctionBegin; 4129 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4130 PetscValidPointer(prefix,2); 4131 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts,prefix)); 4132 PetscFunctionReturn(0); 4133 } 4134 4135 /*@C 4136 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4137 4138 Not Collective, but parallel objects are returned if TS is parallel 4139 4140 Input Parameter: 4141 . ts - The TS context obtained from TSCreate() 4142 4143 Output Parameters: 4144 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or NULL) 4145 . Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat (or NULL) 4146 . func - Function to compute the Jacobian of the RHS (or NULL) 4147 - ctx - User-defined context for Jacobian evaluation routine (or NULL) 4148 4149 Notes: 4150 You can pass in NULL for any return argument you do not need. 4151 4152 Level: intermediate 4153 4154 .seealso: `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4155 4156 @*/ 4157 PetscErrorCode TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx) 4158 { 4159 DM dm; 4160 4161 PetscFunctionBegin; 4162 if (Amat || Pmat) { 4163 SNES snes; 4164 PetscCall(TSGetSNES(ts,&snes)); 4165 PetscCall(SNESSetUpMatrices(snes)); 4166 PetscCall(SNESGetJacobian(snes,Amat,Pmat,NULL,NULL)); 4167 } 4168 PetscCall(TSGetDM(ts,&dm)); 4169 PetscCall(DMTSGetRHSJacobian(dm,func,ctx)); 4170 PetscFunctionReturn(0); 4171 } 4172 4173 /*@C 4174 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4175 4176 Not Collective, but parallel objects are returned if TS is parallel 4177 4178 Input Parameter: 4179 . ts - The TS context obtained from TSCreate() 4180 4181 Output Parameters: 4182 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4183 . Pmat - The matrix from which the preconditioner is constructed, often the same as Amat 4184 . f - The function to compute the matrices 4185 - ctx - User-defined context for Jacobian evaluation routine 4186 4187 Notes: 4188 You can pass in NULL for any return argument you do not need. 4189 4190 Level: advanced 4191 4192 .seealso: `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4193 4194 @*/ 4195 PetscErrorCode TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx) 4196 { 4197 DM dm; 4198 4199 PetscFunctionBegin; 4200 if (Amat || Pmat) { 4201 SNES snes; 4202 PetscCall(TSGetSNES(ts,&snes)); 4203 PetscCall(SNESSetUpMatrices(snes)); 4204 PetscCall(SNESGetJacobian(snes,Amat,Pmat,NULL,NULL)); 4205 } 4206 PetscCall(TSGetDM(ts,&dm)); 4207 PetscCall(DMTSGetIJacobian(dm,f,ctx)); 4208 PetscFunctionReturn(0); 4209 } 4210 4211 #include <petsc/private/dmimpl.h> 4212 /*@ 4213 TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS 4214 4215 Logically Collective on ts 4216 4217 Input Parameters: 4218 + ts - the ODE integrator object 4219 - dm - the dm, cannot be NULL 4220 4221 Notes: 4222 A DM can only be used for solving one problem at a time because information about the problem is stored on the DM, 4223 even when not using interfaces like DMTSSetIFunction(). Use DMClone() to get a distinct DM when solving 4224 different problems using the same function space. 4225 4226 Level: intermediate 4227 4228 .seealso: `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4229 @*/ 4230 PetscErrorCode TSSetDM(TS ts,DM dm) 4231 { 4232 SNES snes; 4233 DMTS tsdm; 4234 4235 PetscFunctionBegin; 4236 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4237 PetscValidHeaderSpecific(dm,DM_CLASSID,2); 4238 PetscCall(PetscObjectReference((PetscObject)dm)); 4239 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4240 if (ts->dm->dmts && !dm->dmts) { 4241 PetscCall(DMCopyDMTS(ts->dm,dm)); 4242 PetscCall(DMGetDMTS(ts->dm,&tsdm)); 4243 if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */ 4244 tsdm->originaldm = dm; 4245 } 4246 } 4247 PetscCall(DMDestroy(&ts->dm)); 4248 } 4249 ts->dm = dm; 4250 4251 PetscCall(TSGetSNES(ts,&snes)); 4252 PetscCall(SNESSetDM(snes,dm)); 4253 PetscFunctionReturn(0); 4254 } 4255 4256 /*@ 4257 TSGetDM - Gets the DM that may be used by some preconditioners 4258 4259 Not Collective 4260 4261 Input Parameter: 4262 . ts - the preconditioner context 4263 4264 Output Parameter: 4265 . dm - the dm 4266 4267 Level: intermediate 4268 4269 .seealso: `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4270 @*/ 4271 PetscErrorCode TSGetDM(TS ts,DM *dm) 4272 { 4273 PetscFunctionBegin; 4274 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4275 if (!ts->dm) { 4276 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm)); 4277 if (ts->snes) PetscCall(SNESSetDM(ts->snes,ts->dm)); 4278 } 4279 *dm = ts->dm; 4280 PetscFunctionReturn(0); 4281 } 4282 4283 /*@ 4284 SNESTSFormFunction - Function to evaluate nonlinear residual 4285 4286 Logically Collective on SNES 4287 4288 Input Parameters: 4289 + snes - nonlinear solver 4290 . U - the current state at which to evaluate the residual 4291 - ctx - user context, must be a TS 4292 4293 Output Parameter: 4294 . F - the nonlinear residual 4295 4296 Notes: 4297 This function is not normally called by users and is automatically registered with the SNES used by TS. 4298 It is most frequently passed to MatFDColoringSetFunction(). 4299 4300 Level: advanced 4301 4302 .seealso: `SNESSetFunction()`, `MatFDColoringSetFunction()` 4303 @*/ 4304 PetscErrorCode SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx) 4305 { 4306 TS ts = (TS)ctx; 4307 4308 PetscFunctionBegin; 4309 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4310 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 4311 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 4312 PetscValidHeaderSpecific(ts,TS_CLASSID,4); 4313 PetscCall((ts->ops->snesfunction)(snes,U,F,ts)); 4314 PetscFunctionReturn(0); 4315 } 4316 4317 /*@ 4318 SNESTSFormJacobian - Function to evaluate the Jacobian 4319 4320 Collective on SNES 4321 4322 Input Parameters: 4323 + snes - nonlinear solver 4324 . U - the current state at which to evaluate the residual 4325 - ctx - user context, must be a TS 4326 4327 Output Parameters: 4328 + A - the Jacobian 4329 - B - the preconditioning matrix (may be the same as A) 4330 4331 Notes: 4332 This function is not normally called by users and is automatically registered with the SNES used by TS. 4333 4334 Level: developer 4335 4336 .seealso: `SNESSetJacobian()` 4337 @*/ 4338 PetscErrorCode SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx) 4339 { 4340 TS ts = (TS)ctx; 4341 4342 PetscFunctionBegin; 4343 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4344 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 4345 PetscValidPointer(A,3); 4346 PetscValidHeaderSpecific(A,MAT_CLASSID,3); 4347 PetscValidPointer(B,4); 4348 PetscValidHeaderSpecific(B,MAT_CLASSID,4); 4349 PetscValidHeaderSpecific(ts,TS_CLASSID,5); 4350 PetscCall((ts->ops->snesjacobian)(snes,U,A,B,ts)); 4351 PetscFunctionReturn(0); 4352 } 4353 4354 /*@C 4355 TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only 4356 4357 Collective on TS 4358 4359 Input Parameters: 4360 + ts - time stepping context 4361 . t - time at which to evaluate 4362 . U - state at which to evaluate 4363 - ctx - context 4364 4365 Output Parameter: 4366 . F - right hand side 4367 4368 Level: intermediate 4369 4370 Notes: 4371 This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems. 4372 The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian(). 4373 4374 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4375 @*/ 4376 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx) 4377 { 4378 Mat Arhs,Brhs; 4379 4380 PetscFunctionBegin; 4381 PetscCall(TSGetRHSMats_Private(ts,&Arhs,&Brhs)); 4382 /* undo the damage caused by shifting */ 4383 PetscCall(TSRecoverRHSJacobian(ts,Arhs,Brhs)); 4384 PetscCall(TSComputeRHSJacobian(ts,t,U,Arhs,Brhs)); 4385 PetscCall(MatMult(Arhs,U,F)); 4386 PetscFunctionReturn(0); 4387 } 4388 4389 /*@C 4390 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4391 4392 Collective on TS 4393 4394 Input Parameters: 4395 + ts - time stepping context 4396 . t - time at which to evaluate 4397 . U - state at which to evaluate 4398 - ctx - context 4399 4400 Output Parameters: 4401 + A - pointer to operator 4402 - B - pointer to preconditioning matrix 4403 4404 Level: intermediate 4405 4406 Notes: 4407 This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems. 4408 4409 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4410 @*/ 4411 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx) 4412 { 4413 PetscFunctionBegin; 4414 PetscFunctionReturn(0); 4415 } 4416 4417 /*@C 4418 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4419 4420 Collective on TS 4421 4422 Input Parameters: 4423 + ts - time stepping context 4424 . t - time at which to evaluate 4425 . U - state at which to evaluate 4426 . Udot - time derivative of state vector 4427 - ctx - context 4428 4429 Output Parameter: 4430 . F - left hand side 4431 4432 Level: intermediate 4433 4434 Notes: 4435 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 4436 user is required to write their own TSComputeIFunction. 4437 This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems. 4438 The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian(). 4439 4440 Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U 4441 4442 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4443 @*/ 4444 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx) 4445 { 4446 Mat A,B; 4447 4448 PetscFunctionBegin; 4449 PetscCall(TSGetIJacobian(ts,&A,&B,NULL,NULL)); 4450 PetscCall(TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE)); 4451 PetscCall(MatMult(A,Udot,F)); 4452 PetscFunctionReturn(0); 4453 } 4454 4455 /*@C 4456 TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE 4457 4458 Collective on TS 4459 4460 Input Parameters: 4461 + ts - time stepping context 4462 . t - time at which to evaluate 4463 . U - state at which to evaluate 4464 . Udot - time derivative of state vector 4465 . shift - shift to apply 4466 - ctx - context 4467 4468 Output Parameters: 4469 + A - pointer to operator 4470 - B - pointer to preconditioning matrix 4471 4472 Level: advanced 4473 4474 Notes: 4475 This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems. 4476 4477 It is only appropriate for problems of the form 4478 4479 $ M Udot = F(U,t) 4480 4481 where M is constant and F is non-stiff. The user must pass M to TSSetIJacobian(). The current implementation only 4482 works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing 4483 an implicit operator of the form 4484 4485 $ shift*M + J 4486 4487 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 4488 a copy of M or reassemble it when requested. 4489 4490 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4491 @*/ 4492 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx) 4493 { 4494 PetscFunctionBegin; 4495 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4496 ts->ijacobian.shift = shift; 4497 PetscFunctionReturn(0); 4498 } 4499 4500 /*@ 4501 TSGetEquationType - Gets the type of the equation that TS is solving. 4502 4503 Not Collective 4504 4505 Input Parameter: 4506 . ts - the TS context 4507 4508 Output Parameter: 4509 . equation_type - see TSEquationType 4510 4511 Level: beginner 4512 4513 .seealso: `TSSetEquationType()`, `TSEquationType` 4514 @*/ 4515 PetscErrorCode TSGetEquationType(TS ts,TSEquationType *equation_type) 4516 { 4517 PetscFunctionBegin; 4518 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4519 PetscValidPointer(equation_type,2); 4520 *equation_type = ts->equation_type; 4521 PetscFunctionReturn(0); 4522 } 4523 4524 /*@ 4525 TSSetEquationType - Sets the type of the equation that TS is solving. 4526 4527 Not Collective 4528 4529 Input Parameters: 4530 + ts - the TS context 4531 - equation_type - see TSEquationType 4532 4533 Level: advanced 4534 4535 .seealso: `TSGetEquationType()`, `TSEquationType` 4536 @*/ 4537 PetscErrorCode TSSetEquationType(TS ts,TSEquationType equation_type) 4538 { 4539 PetscFunctionBegin; 4540 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4541 ts->equation_type = equation_type; 4542 PetscFunctionReturn(0); 4543 } 4544 4545 /*@ 4546 TSGetConvergedReason - Gets the reason the TS iteration was stopped. 4547 4548 Not Collective 4549 4550 Input Parameter: 4551 . ts - the TS context 4552 4553 Output Parameter: 4554 . reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the 4555 manual pages for the individual convergence tests for complete lists 4556 4557 Level: beginner 4558 4559 Notes: 4560 Can only be called after the call to TSSolve() is complete. 4561 4562 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason` 4563 @*/ 4564 PetscErrorCode TSGetConvergedReason(TS ts,TSConvergedReason *reason) 4565 { 4566 PetscFunctionBegin; 4567 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4568 PetscValidPointer(reason,2); 4569 *reason = ts->reason; 4570 PetscFunctionReturn(0); 4571 } 4572 4573 /*@ 4574 TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve. 4575 4576 Logically Collective; reason must contain common value 4577 4578 Input Parameters: 4579 + ts - the TS context 4580 - reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the 4581 manual pages for the individual convergence tests for complete lists 4582 4583 Level: advanced 4584 4585 Notes: 4586 Can only be called while TSSolve() is active. 4587 4588 .seealso: `TSConvergedReason` 4589 @*/ 4590 PetscErrorCode TSSetConvergedReason(TS ts,TSConvergedReason reason) 4591 { 4592 PetscFunctionBegin; 4593 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4594 ts->reason = reason; 4595 PetscFunctionReturn(0); 4596 } 4597 4598 /*@ 4599 TSGetSolveTime - Gets the time after a call to TSSolve() 4600 4601 Not Collective 4602 4603 Input Parameter: 4604 . ts - the TS context 4605 4606 Output Parameter: 4607 . ftime - the final time. This time corresponds to the final time set with TSSetMaxTime() 4608 4609 Level: beginner 4610 4611 Notes: 4612 Can only be called after the call to TSSolve() is complete. 4613 4614 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason` 4615 @*/ 4616 PetscErrorCode TSGetSolveTime(TS ts,PetscReal *ftime) 4617 { 4618 PetscFunctionBegin; 4619 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4620 PetscValidRealPointer(ftime,2); 4621 *ftime = ts->solvetime; 4622 PetscFunctionReturn(0); 4623 } 4624 4625 /*@ 4626 TSGetSNESIterations - Gets the total number of nonlinear iterations 4627 used by the time integrator. 4628 4629 Not Collective 4630 4631 Input Parameter: 4632 . ts - TS context 4633 4634 Output Parameter: 4635 . nits - number of nonlinear iterations 4636 4637 Notes: 4638 This counter is reset to zero for each successive call to TSSolve(). 4639 4640 Level: intermediate 4641 4642 .seealso: `TSGetKSPIterations()` 4643 @*/ 4644 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits) 4645 { 4646 PetscFunctionBegin; 4647 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4648 PetscValidIntPointer(nits,2); 4649 *nits = ts->snes_its; 4650 PetscFunctionReturn(0); 4651 } 4652 4653 /*@ 4654 TSGetKSPIterations - Gets the total number of linear iterations 4655 used by the time integrator. 4656 4657 Not Collective 4658 4659 Input Parameter: 4660 . ts - TS context 4661 4662 Output Parameter: 4663 . lits - number of linear iterations 4664 4665 Notes: 4666 This counter is reset to zero for each successive call to TSSolve(). 4667 4668 Level: intermediate 4669 4670 .seealso: `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4671 @*/ 4672 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits) 4673 { 4674 PetscFunctionBegin; 4675 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4676 PetscValidIntPointer(lits,2); 4677 *lits = ts->ksp_its; 4678 PetscFunctionReturn(0); 4679 } 4680 4681 /*@ 4682 TSGetStepRejections - Gets the total number of rejected steps. 4683 4684 Not Collective 4685 4686 Input Parameter: 4687 . ts - TS context 4688 4689 Output Parameter: 4690 . rejects - number of steps rejected 4691 4692 Notes: 4693 This counter is reset to zero for each successive call to TSSolve(). 4694 4695 Level: intermediate 4696 4697 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4698 @*/ 4699 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects) 4700 { 4701 PetscFunctionBegin; 4702 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4703 PetscValidIntPointer(rejects,2); 4704 *rejects = ts->reject; 4705 PetscFunctionReturn(0); 4706 } 4707 4708 /*@ 4709 TSGetSNESFailures - Gets the total number of failed SNES solves 4710 4711 Not Collective 4712 4713 Input Parameter: 4714 . ts - TS context 4715 4716 Output Parameter: 4717 . fails - number of failed nonlinear solves 4718 4719 Notes: 4720 This counter is reset to zero for each successive call to TSSolve(). 4721 4722 Level: intermediate 4723 4724 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4725 @*/ 4726 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails) 4727 { 4728 PetscFunctionBegin; 4729 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4730 PetscValidIntPointer(fails,2); 4731 *fails = ts->num_snes_failures; 4732 PetscFunctionReturn(0); 4733 } 4734 4735 /*@ 4736 TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails 4737 4738 Not Collective 4739 4740 Input Parameters: 4741 + ts - TS context 4742 - rejects - maximum number of rejected steps, pass -1 for unlimited 4743 4744 Notes: 4745 The counter is reset to zero for each step 4746 4747 Options Database Key: 4748 . -ts_max_reject - Maximum number of step rejections before a step fails 4749 4750 Level: intermediate 4751 4752 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4753 @*/ 4754 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects) 4755 { 4756 PetscFunctionBegin; 4757 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4758 ts->max_reject = rejects; 4759 PetscFunctionReturn(0); 4760 } 4761 4762 /*@ 4763 TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves 4764 4765 Not Collective 4766 4767 Input Parameters: 4768 + ts - TS context 4769 - fails - maximum number of failed nonlinear solves, pass -1 for unlimited 4770 4771 Notes: 4772 The counter is reset to zero for each successive call to TSSolve(). 4773 4774 Options Database Key: 4775 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4776 4777 Level: intermediate 4778 4779 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4780 @*/ 4781 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails) 4782 { 4783 PetscFunctionBegin; 4784 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4785 ts->max_snes_failures = fails; 4786 PetscFunctionReturn(0); 4787 } 4788 4789 /*@ 4790 TSSetErrorIfStepFails - Error if no step succeeds 4791 4792 Not Collective 4793 4794 Input Parameters: 4795 + ts - TS context 4796 - err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure 4797 4798 Options Database Key: 4799 . -ts_error_if_step_fails - Error if no step succeeds 4800 4801 Level: intermediate 4802 4803 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4804 @*/ 4805 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err) 4806 { 4807 PetscFunctionBegin; 4808 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4809 ts->errorifstepfailed = err; 4810 PetscFunctionReturn(0); 4811 } 4812 4813 /*@ 4814 TSGetAdapt - Get the adaptive controller context for the current method 4815 4816 Collective on TS if controller has not been created yet 4817 4818 Input Parameter: 4819 . ts - time stepping context 4820 4821 Output Parameter: 4822 . adapt - adaptive controller 4823 4824 Level: intermediate 4825 4826 .seealso: `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 4827 @*/ 4828 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt) 4829 { 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4832 PetscValidPointer(adapt,2); 4833 if (!ts->adapt) { 4834 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt)); 4835 PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt)); 4836 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1)); 4837 } 4838 *adapt = ts->adapt; 4839 PetscFunctionReturn(0); 4840 } 4841 4842 /*@ 4843 TSSetTolerances - Set tolerances for local truncation error when using adaptive controller 4844 4845 Logically Collective 4846 4847 Input Parameters: 4848 + ts - time integration context 4849 . atol - scalar absolute tolerances, PETSC_DECIDE to leave current value 4850 . vatol - vector of absolute tolerances or NULL, used in preference to atol if present 4851 . rtol - scalar relative tolerances, PETSC_DECIDE to leave current value 4852 - vrtol - vector of relative tolerances or NULL, used in preference to atol if present 4853 4854 Options Database keys: 4855 + -ts_rtol <rtol> - relative tolerance for local truncation error 4856 - -ts_atol <atol> - Absolute tolerance for local truncation error 4857 4858 Notes: 4859 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 4860 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 4861 computed only for the differential or the algebraic part then this can be done using the vector of 4862 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 4863 differential part and infinity for the algebraic part, the LTE calculation will include only the 4864 differential variables. 4865 4866 Level: beginner 4867 4868 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 4869 @*/ 4870 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol) 4871 { 4872 PetscFunctionBegin; 4873 if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol; 4874 if (vatol) { 4875 PetscCall(PetscObjectReference((PetscObject)vatol)); 4876 PetscCall(VecDestroy(&ts->vatol)); 4877 ts->vatol = vatol; 4878 } 4879 if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol; 4880 if (vrtol) { 4881 PetscCall(PetscObjectReference((PetscObject)vrtol)); 4882 PetscCall(VecDestroy(&ts->vrtol)); 4883 ts->vrtol = vrtol; 4884 } 4885 PetscFunctionReturn(0); 4886 } 4887 4888 /*@ 4889 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 4890 4891 Logically Collective 4892 4893 Input Parameter: 4894 . ts - time integration context 4895 4896 Output Parameters: 4897 + atol - scalar absolute tolerances, NULL to ignore 4898 . vatol - vector of absolute tolerances, NULL to ignore 4899 . rtol - scalar relative tolerances, NULL to ignore 4900 - vrtol - vector of relative tolerances, NULL to ignore 4901 4902 Level: beginner 4903 4904 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 4905 @*/ 4906 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol) 4907 { 4908 PetscFunctionBegin; 4909 if (atol) *atol = ts->atol; 4910 if (vatol) *vatol = ts->vatol; 4911 if (rtol) *rtol = ts->rtol; 4912 if (vrtol) *vrtol = ts->vrtol; 4913 PetscFunctionReturn(0); 4914 } 4915 4916 /*@ 4917 TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors 4918 4919 Collective on TS 4920 4921 Input Parameters: 4922 + ts - time stepping context 4923 . U - state vector, usually ts->vec_sol 4924 - Y - state vector to be compared to U 4925 4926 Output Parameters: 4927 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 4928 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 4929 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 4930 4931 Level: developer 4932 4933 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNormInfinity()` 4934 @*/ 4935 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr) 4936 { 4937 PetscInt i,n,N,rstart; 4938 PetscInt n_loc,na_loc,nr_loc; 4939 PetscReal n_glb,na_glb,nr_glb; 4940 const PetscScalar *u,*y; 4941 PetscReal sum,suma,sumr,gsum,gsuma,gsumr,diff; 4942 PetscReal tol,tola,tolr; 4943 PetscReal err_loc[6],err_glb[6]; 4944 4945 PetscFunctionBegin; 4946 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4947 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 4948 PetscValidHeaderSpecific(Y,VEC_CLASSID,3); 4949 PetscValidType(U,2); 4950 PetscValidType(Y,3); 4951 PetscCheckSameComm(U,2,Y,3); 4952 PetscValidRealPointer(norm,4); 4953 PetscValidRealPointer(norma,5); 4954 PetscValidRealPointer(normr,6); 4955 PetscCheck(U != Y,PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector"); 4956 4957 PetscCall(VecGetSize(U,&N)); 4958 PetscCall(VecGetLocalSize(U,&n)); 4959 PetscCall(VecGetOwnershipRange(U,&rstart,NULL)); 4960 PetscCall(VecGetArrayRead(U,&u)); 4961 PetscCall(VecGetArrayRead(Y,&y)); 4962 sum = 0.; n_loc = 0; 4963 suma = 0.; na_loc = 0; 4964 sumr = 0.; nr_loc = 0; 4965 if (ts->vatol && ts->vrtol) { 4966 const PetscScalar *atol,*rtol; 4967 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 4968 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 4969 for (i=0; i<n; i++) { 4970 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 4971 diff = PetscAbsScalar(y[i] - u[i]); 4972 tola = PetscRealPart(atol[i]); 4973 if (tola>0.) { 4974 suma += PetscSqr(diff/tola); 4975 na_loc++; 4976 } 4977 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 4978 if (tolr>0.) { 4979 sumr += PetscSqr(diff/tolr); 4980 nr_loc++; 4981 } 4982 tol=tola+tolr; 4983 if (tol>0.) { 4984 sum += PetscSqr(diff/tol); 4985 n_loc++; 4986 } 4987 } 4988 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 4989 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 4990 } else if (ts->vatol) { /* vector atol, scalar rtol */ 4991 const PetscScalar *atol; 4992 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 4993 for (i=0; i<n; i++) { 4994 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 4995 diff = PetscAbsScalar(y[i] - u[i]); 4996 tola = PetscRealPart(atol[i]); 4997 if (tola>0.) { 4998 suma += PetscSqr(diff/tola); 4999 na_loc++; 5000 } 5001 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5002 if (tolr>0.) { 5003 sumr += PetscSqr(diff/tolr); 5004 nr_loc++; 5005 } 5006 tol=tola+tolr; 5007 if (tol>0.) { 5008 sum += PetscSqr(diff/tol); 5009 n_loc++; 5010 } 5011 } 5012 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5013 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5014 const PetscScalar *rtol; 5015 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5016 for (i=0; i<n; i++) { 5017 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5018 diff = PetscAbsScalar(y[i] - u[i]); 5019 tola = ts->atol; 5020 if (tola>0.) { 5021 suma += PetscSqr(diff/tola); 5022 na_loc++; 5023 } 5024 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5025 if (tolr>0.) { 5026 sumr += PetscSqr(diff/tolr); 5027 nr_loc++; 5028 } 5029 tol=tola+tolr; 5030 if (tol>0.) { 5031 sum += PetscSqr(diff/tol); 5032 n_loc++; 5033 } 5034 } 5035 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5036 } else { /* scalar atol, scalar rtol */ 5037 for (i=0; i<n; i++) { 5038 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5039 diff = PetscAbsScalar(y[i] - u[i]); 5040 tola = ts->atol; 5041 if (tola>0.) { 5042 suma += PetscSqr(diff/tola); 5043 na_loc++; 5044 } 5045 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5046 if (tolr>0.) { 5047 sumr += PetscSqr(diff/tolr); 5048 nr_loc++; 5049 } 5050 tol=tola+tolr; 5051 if (tol>0.) { 5052 sum += PetscSqr(diff/tol); 5053 n_loc++; 5054 } 5055 } 5056 } 5057 PetscCall(VecRestoreArrayRead(U,&u)); 5058 PetscCall(VecRestoreArrayRead(Y,&y)); 5059 5060 err_loc[0] = sum; 5061 err_loc[1] = suma; 5062 err_loc[2] = sumr; 5063 err_loc[3] = (PetscReal)n_loc; 5064 err_loc[4] = (PetscReal)na_loc; 5065 err_loc[5] = (PetscReal)nr_loc; 5066 5067 PetscCall(MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts))); 5068 5069 gsum = err_glb[0]; 5070 gsuma = err_glb[1]; 5071 gsumr = err_glb[2]; 5072 n_glb = err_glb[3]; 5073 na_glb = err_glb[4]; 5074 nr_glb = err_glb[5]; 5075 5076 *norm = 0.; 5077 if (n_glb>0.) {*norm = PetscSqrtReal(gsum / n_glb);} 5078 *norma = 0.; 5079 if (na_glb>0.) {*norma = PetscSqrtReal(gsuma / na_glb);} 5080 *normr = 0.; 5081 if (nr_glb>0.) {*normr = PetscSqrtReal(gsumr / nr_glb);} 5082 5083 PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 5084 PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma"); 5085 PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr"); 5086 PetscFunctionReturn(0); 5087 } 5088 5089 /*@ 5090 TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors 5091 5092 Collective on TS 5093 5094 Input Parameters: 5095 + ts - time stepping context 5096 . U - state vector, usually ts->vec_sol 5097 - Y - state vector to be compared to U 5098 5099 Output Parameters: 5100 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5101 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5102 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5103 5104 Level: developer 5105 5106 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNorm2()` 5107 @*/ 5108 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr) 5109 { 5110 PetscInt i,n,N,rstart; 5111 const PetscScalar *u,*y; 5112 PetscReal max,gmax,maxa,gmaxa,maxr,gmaxr; 5113 PetscReal tol,tola,tolr,diff; 5114 PetscReal err_loc[3],err_glb[3]; 5115 5116 PetscFunctionBegin; 5117 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5118 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 5119 PetscValidHeaderSpecific(Y,VEC_CLASSID,3); 5120 PetscValidType(U,2); 5121 PetscValidType(Y,3); 5122 PetscCheckSameComm(U,2,Y,3); 5123 PetscValidRealPointer(norm,4); 5124 PetscValidRealPointer(norma,5); 5125 PetscValidRealPointer(normr,6); 5126 PetscCheck(U != Y,PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector"); 5127 5128 PetscCall(VecGetSize(U,&N)); 5129 PetscCall(VecGetLocalSize(U,&n)); 5130 PetscCall(VecGetOwnershipRange(U,&rstart,NULL)); 5131 PetscCall(VecGetArrayRead(U,&u)); 5132 PetscCall(VecGetArrayRead(Y,&y)); 5133 5134 max=0.; 5135 maxa=0.; 5136 maxr=0.; 5137 5138 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 5139 const PetscScalar *atol,*rtol; 5140 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5141 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5142 5143 for (i=0; i<n; i++) { 5144 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5145 diff = PetscAbsScalar(y[i] - u[i]); 5146 tola = PetscRealPart(atol[i]); 5147 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5148 tol = tola+tolr; 5149 if (tola>0.) { 5150 maxa = PetscMax(maxa,diff / tola); 5151 } 5152 if (tolr>0.) { 5153 maxr = PetscMax(maxr,diff / tolr); 5154 } 5155 if (tol>0.) { 5156 max = PetscMax(max,diff / tol); 5157 } 5158 } 5159 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5160 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5161 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5162 const PetscScalar *atol; 5163 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5164 for (i=0; i<n; i++) { 5165 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5166 diff = PetscAbsScalar(y[i] - u[i]); 5167 tola = PetscRealPart(atol[i]); 5168 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5169 tol = tola+tolr; 5170 if (tola>0.) { 5171 maxa = PetscMax(maxa,diff / tola); 5172 } 5173 if (tolr>0.) { 5174 maxr = PetscMax(maxr,diff / tolr); 5175 } 5176 if (tol>0.) { 5177 max = PetscMax(max,diff / tol); 5178 } 5179 } 5180 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5181 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5182 const PetscScalar *rtol; 5183 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5184 5185 for (i=0; i<n; i++) { 5186 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5187 diff = PetscAbsScalar(y[i] - u[i]); 5188 tola = ts->atol; 5189 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5190 tol = tola+tolr; 5191 if (tola>0.) { 5192 maxa = PetscMax(maxa,diff / tola); 5193 } 5194 if (tolr>0.) { 5195 maxr = PetscMax(maxr,diff / tolr); 5196 } 5197 if (tol>0.) { 5198 max = PetscMax(max,diff / tol); 5199 } 5200 } 5201 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5202 } else { /* scalar atol, scalar rtol */ 5203 5204 for (i=0; i<n; i++) { 5205 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5206 diff = PetscAbsScalar(y[i] - u[i]); 5207 tola = ts->atol; 5208 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5209 tol = tola+tolr; 5210 if (tola>0.) { 5211 maxa = PetscMax(maxa,diff / tola); 5212 } 5213 if (tolr>0.) { 5214 maxr = PetscMax(maxr,diff / tolr); 5215 } 5216 if (tol>0.) { 5217 max = PetscMax(max,diff / tol); 5218 } 5219 } 5220 } 5221 PetscCall(VecRestoreArrayRead(U,&u)); 5222 PetscCall(VecRestoreArrayRead(Y,&y)); 5223 err_loc[0] = max; 5224 err_loc[1] = maxa; 5225 err_loc[2] = maxr; 5226 PetscCall(MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts))); 5227 gmax = err_glb[0]; 5228 gmaxa = err_glb[1]; 5229 gmaxr = err_glb[2]; 5230 5231 *norm = gmax; 5232 *norma = gmaxa; 5233 *normr = gmaxr; 5234 PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 5235 PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma"); 5236 PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr"); 5237 PetscFunctionReturn(0); 5238 } 5239 5240 /*@ 5241 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5242 5243 Collective on TS 5244 5245 Input Parameters: 5246 + ts - time stepping context 5247 . U - state vector, usually ts->vec_sol 5248 . Y - state vector to be compared to U 5249 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 5250 5251 Output Parameters: 5252 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5253 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5254 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5255 5256 Options Database Keys: 5257 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5258 5259 Level: developer 5260 5261 .seealso: `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`, `TSErrorWeightedENorm` 5262 @*/ 5263 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr) 5264 { 5265 PetscFunctionBegin; 5266 if (wnormtype == NORM_2) { 5267 PetscCall(TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr)); 5268 } else if (wnormtype == NORM_INFINITY) { 5269 PetscCall(TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr)); 5270 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]); 5271 PetscFunctionReturn(0); 5272 } 5273 5274 /*@ 5275 TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances 5276 5277 Collective on TS 5278 5279 Input Parameters: 5280 + ts - time stepping context 5281 . E - error vector 5282 . U - state vector, usually ts->vec_sol 5283 - Y - state vector, previous time step 5284 5285 Output Parameters: 5286 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5287 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5288 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5289 5290 Level: developer 5291 5292 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENormInfinity()` 5293 @*/ 5294 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr) 5295 { 5296 PetscInt i,n,N,rstart; 5297 PetscInt n_loc,na_loc,nr_loc; 5298 PetscReal n_glb,na_glb,nr_glb; 5299 const PetscScalar *e,*u,*y; 5300 PetscReal err,sum,suma,sumr,gsum,gsuma,gsumr; 5301 PetscReal tol,tola,tolr; 5302 PetscReal err_loc[6],err_glb[6]; 5303 5304 PetscFunctionBegin; 5305 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5306 PetscValidHeaderSpecific(E,VEC_CLASSID,2); 5307 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 5308 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 5309 PetscValidType(E,2); 5310 PetscValidType(U,3); 5311 PetscValidType(Y,4); 5312 PetscCheckSameComm(E,2,U,3); 5313 PetscCheckSameComm(U,3,Y,4); 5314 PetscValidRealPointer(norm,5); 5315 PetscValidRealPointer(norma,6); 5316 PetscValidRealPointer(normr,7); 5317 5318 PetscCall(VecGetSize(E,&N)); 5319 PetscCall(VecGetLocalSize(E,&n)); 5320 PetscCall(VecGetOwnershipRange(E,&rstart,NULL)); 5321 PetscCall(VecGetArrayRead(E,&e)); 5322 PetscCall(VecGetArrayRead(U,&u)); 5323 PetscCall(VecGetArrayRead(Y,&y)); 5324 sum = 0.; n_loc = 0; 5325 suma = 0.; na_loc = 0; 5326 sumr = 0.; nr_loc = 0; 5327 if (ts->vatol && ts->vrtol) { 5328 const PetscScalar *atol,*rtol; 5329 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5330 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5331 for (i=0; i<n; i++) { 5332 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5333 err = PetscAbsScalar(e[i]); 5334 tola = PetscRealPart(atol[i]); 5335 if (tola>0.) { 5336 suma += PetscSqr(err/tola); 5337 na_loc++; 5338 } 5339 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5340 if (tolr>0.) { 5341 sumr += PetscSqr(err/tolr); 5342 nr_loc++; 5343 } 5344 tol=tola+tolr; 5345 if (tol>0.) { 5346 sum += PetscSqr(err/tol); 5347 n_loc++; 5348 } 5349 } 5350 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5351 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5352 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5353 const PetscScalar *atol; 5354 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5355 for (i=0; i<n; i++) { 5356 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5357 err = PetscAbsScalar(e[i]); 5358 tola = PetscRealPart(atol[i]); 5359 if (tola>0.) { 5360 suma += PetscSqr(err/tola); 5361 na_loc++; 5362 } 5363 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5364 if (tolr>0.) { 5365 sumr += PetscSqr(err/tolr); 5366 nr_loc++; 5367 } 5368 tol=tola+tolr; 5369 if (tol>0.) { 5370 sum += PetscSqr(err/tol); 5371 n_loc++; 5372 } 5373 } 5374 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5375 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5376 const PetscScalar *rtol; 5377 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5378 for (i=0; i<n; i++) { 5379 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5380 err = PetscAbsScalar(e[i]); 5381 tola = ts->atol; 5382 if (tola>0.) { 5383 suma += PetscSqr(err/tola); 5384 na_loc++; 5385 } 5386 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5387 if (tolr>0.) { 5388 sumr += PetscSqr(err/tolr); 5389 nr_loc++; 5390 } 5391 tol=tola+tolr; 5392 if (tol>0.) { 5393 sum += PetscSqr(err/tol); 5394 n_loc++; 5395 } 5396 } 5397 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5398 } else { /* scalar atol, scalar rtol */ 5399 for (i=0; i<n; i++) { 5400 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5401 err = PetscAbsScalar(e[i]); 5402 tola = ts->atol; 5403 if (tola>0.) { 5404 suma += PetscSqr(err/tola); 5405 na_loc++; 5406 } 5407 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5408 if (tolr>0.) { 5409 sumr += PetscSqr(err/tolr); 5410 nr_loc++; 5411 } 5412 tol=tola+tolr; 5413 if (tol>0.) { 5414 sum += PetscSqr(err/tol); 5415 n_loc++; 5416 } 5417 } 5418 } 5419 PetscCall(VecRestoreArrayRead(E,&e)); 5420 PetscCall(VecRestoreArrayRead(U,&u)); 5421 PetscCall(VecRestoreArrayRead(Y,&y)); 5422 5423 err_loc[0] = sum; 5424 err_loc[1] = suma; 5425 err_loc[2] = sumr; 5426 err_loc[3] = (PetscReal)n_loc; 5427 err_loc[4] = (PetscReal)na_loc; 5428 err_loc[5] = (PetscReal)nr_loc; 5429 5430 PetscCall(MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts))); 5431 5432 gsum = err_glb[0]; 5433 gsuma = err_glb[1]; 5434 gsumr = err_glb[2]; 5435 n_glb = err_glb[3]; 5436 na_glb = err_glb[4]; 5437 nr_glb = err_glb[5]; 5438 5439 *norm = 0.; 5440 if (n_glb>0.) {*norm = PetscSqrtReal(gsum / n_glb);} 5441 *norma = 0.; 5442 if (na_glb>0.) {*norma = PetscSqrtReal(gsuma / na_glb);} 5443 *normr = 0.; 5444 if (nr_glb>0.) {*normr = PetscSqrtReal(gsumr / nr_glb);} 5445 5446 PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 5447 PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma"); 5448 PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr"); 5449 PetscFunctionReturn(0); 5450 } 5451 5452 /*@ 5453 TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances 5454 Collective on TS 5455 5456 Input Parameters: 5457 + ts - time stepping context 5458 . E - error vector 5459 . U - state vector, usually ts->vec_sol 5460 - Y - state vector, previous time step 5461 5462 Output Parameters: 5463 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5464 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5465 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5466 5467 Level: developer 5468 5469 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENorm2()` 5470 @*/ 5471 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr) 5472 { 5473 PetscInt i,n,N,rstart; 5474 const PetscScalar *e,*u,*y; 5475 PetscReal err,max,gmax,maxa,gmaxa,maxr,gmaxr; 5476 PetscReal tol,tola,tolr; 5477 PetscReal err_loc[3],err_glb[3]; 5478 5479 PetscFunctionBegin; 5480 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5481 PetscValidHeaderSpecific(E,VEC_CLASSID,2); 5482 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 5483 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 5484 PetscValidType(E,2); 5485 PetscValidType(U,3); 5486 PetscValidType(Y,4); 5487 PetscCheckSameComm(E,2,U,3); 5488 PetscCheckSameComm(U,3,Y,4); 5489 PetscValidRealPointer(norm,5); 5490 PetscValidRealPointer(norma,6); 5491 PetscValidRealPointer(normr,7); 5492 5493 PetscCall(VecGetSize(E,&N)); 5494 PetscCall(VecGetLocalSize(E,&n)); 5495 PetscCall(VecGetOwnershipRange(E,&rstart,NULL)); 5496 PetscCall(VecGetArrayRead(E,&e)); 5497 PetscCall(VecGetArrayRead(U,&u)); 5498 PetscCall(VecGetArrayRead(Y,&y)); 5499 5500 max=0.; 5501 maxa=0.; 5502 maxr=0.; 5503 5504 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 5505 const PetscScalar *atol,*rtol; 5506 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5507 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5508 5509 for (i=0; i<n; i++) { 5510 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5511 err = PetscAbsScalar(e[i]); 5512 tola = PetscRealPart(atol[i]); 5513 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5514 tol = tola+tolr; 5515 if (tola>0.) { 5516 maxa = PetscMax(maxa,err / tola); 5517 } 5518 if (tolr>0.) { 5519 maxr = PetscMax(maxr,err / tolr); 5520 } 5521 if (tol>0.) { 5522 max = PetscMax(max,err / tol); 5523 } 5524 } 5525 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5526 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5527 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5528 const PetscScalar *atol; 5529 PetscCall(VecGetArrayRead(ts->vatol,&atol)); 5530 for (i=0; i<n; i++) { 5531 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5532 err = PetscAbsScalar(e[i]); 5533 tola = PetscRealPart(atol[i]); 5534 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5535 tol = tola+tolr; 5536 if (tola>0.) { 5537 maxa = PetscMax(maxa,err / tola); 5538 } 5539 if (tolr>0.) { 5540 maxr = PetscMax(maxr,err / tolr); 5541 } 5542 if (tol>0.) { 5543 max = PetscMax(max,err / tol); 5544 } 5545 } 5546 PetscCall(VecRestoreArrayRead(ts->vatol,&atol)); 5547 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5548 const PetscScalar *rtol; 5549 PetscCall(VecGetArrayRead(ts->vrtol,&rtol)); 5550 5551 for (i=0; i<n; i++) { 5552 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5553 err = PetscAbsScalar(e[i]); 5554 tola = ts->atol; 5555 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5556 tol = tola+tolr; 5557 if (tola>0.) { 5558 maxa = PetscMax(maxa,err / tola); 5559 } 5560 if (tolr>0.) { 5561 maxr = PetscMax(maxr,err / tolr); 5562 } 5563 if (tol>0.) { 5564 max = PetscMax(max,err / tol); 5565 } 5566 } 5567 PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol)); 5568 } else { /* scalar atol, scalar rtol */ 5569 5570 for (i=0; i<n; i++) { 5571 SkipSmallValue(y[i],u[i],ts->adapt->ignore_max); 5572 err = PetscAbsScalar(e[i]); 5573 tola = ts->atol; 5574 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i])); 5575 tol = tola+tolr; 5576 if (tola>0.) { 5577 maxa = PetscMax(maxa,err / tola); 5578 } 5579 if (tolr>0.) { 5580 maxr = PetscMax(maxr,err / tolr); 5581 } 5582 if (tol>0.) { 5583 max = PetscMax(max,err / tol); 5584 } 5585 } 5586 } 5587 PetscCall(VecRestoreArrayRead(E,&e)); 5588 PetscCall(VecRestoreArrayRead(U,&u)); 5589 PetscCall(VecRestoreArrayRead(Y,&y)); 5590 err_loc[0] = max; 5591 err_loc[1] = maxa; 5592 err_loc[2] = maxr; 5593 PetscCall(MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts))); 5594 gmax = err_glb[0]; 5595 gmaxa = err_glb[1]; 5596 gmaxr = err_glb[2]; 5597 5598 *norm = gmax; 5599 *norma = gmaxa; 5600 *normr = gmaxr; 5601 PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 5602 PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma"); 5603 PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr"); 5604 PetscFunctionReturn(0); 5605 } 5606 5607 /*@ 5608 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5609 5610 Collective on TS 5611 5612 Input Parameters: 5613 + ts - time stepping context 5614 . E - error vector 5615 . U - state vector, usually ts->vec_sol 5616 . Y - state vector, previous time step 5617 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 5618 5619 Output Parameters: 5620 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5621 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5622 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5623 5624 Options Database Keys: 5625 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5626 5627 Level: developer 5628 5629 .seealso: `TSErrorWeightedENormInfinity()`, `TSErrorWeightedENorm2()`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()` 5630 @*/ 5631 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr) 5632 { 5633 PetscFunctionBegin; 5634 if (wnormtype == NORM_2) { 5635 PetscCall(TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr)); 5636 } else if (wnormtype == NORM_INFINITY) { 5637 PetscCall(TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr)); 5638 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]); 5639 PetscFunctionReturn(0); 5640 } 5641 5642 /*@ 5643 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5644 5645 Logically Collective on TS 5646 5647 Input Parameters: 5648 + ts - time stepping context 5649 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5650 5651 Note: 5652 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5653 5654 Level: intermediate 5655 5656 .seealso: `TSGetCFLTime()`, `TSADAPTCFL` 5657 @*/ 5658 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime) 5659 { 5660 PetscFunctionBegin; 5661 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5662 ts->cfltime_local = cfltime; 5663 ts->cfltime = -1.; 5664 PetscFunctionReturn(0); 5665 } 5666 5667 /*@ 5668 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5669 5670 Collective on TS 5671 5672 Input Parameter: 5673 . ts - time stepping context 5674 5675 Output Parameter: 5676 . cfltime - maximum stable time step for forward Euler 5677 5678 Level: advanced 5679 5680 .seealso: `TSSetCFLTimeLocal()` 5681 @*/ 5682 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime) 5683 { 5684 PetscFunctionBegin; 5685 if (ts->cfltime < 0) { 5686 PetscCall(MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts))); 5687 } 5688 *cfltime = ts->cfltime; 5689 PetscFunctionReturn(0); 5690 } 5691 5692 /*@ 5693 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5694 5695 Input Parameters: 5696 + ts - the TS context. 5697 . xl - lower bound. 5698 - xu - upper bound. 5699 5700 Notes: 5701 If this routine is not called then the lower and upper bounds are set to 5702 PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp(). 5703 5704 Level: advanced 5705 5706 @*/ 5707 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5708 { 5709 SNES snes; 5710 5711 PetscFunctionBegin; 5712 PetscCall(TSGetSNES(ts,&snes)); 5713 PetscCall(SNESVISetVariableBounds(snes,xl,xu)); 5714 PetscFunctionReturn(0); 5715 } 5716 5717 /*@ 5718 TSComputeLinearStability - computes the linear stability function at a point 5719 5720 Collective on TS 5721 5722 Input Parameters: 5723 + ts - the TS context 5724 - xr,xi - real and imaginary part of input arguments 5725 5726 Output Parameters: 5727 . yr,yi - real and imaginary part of function value 5728 5729 Level: developer 5730 5731 .seealso: `TSSetRHSFunction()`, `TSComputeIFunction()` 5732 @*/ 5733 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 5734 { 5735 PetscFunctionBegin; 5736 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5737 PetscCheck(ts->ops->linearstability,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method"); 5738 PetscCall((*ts->ops->linearstability)(ts,xr,xi,yr,yi)); 5739 PetscFunctionReturn(0); 5740 } 5741 5742 /*@ 5743 TSRestartStep - Flags the solver to restart the next step 5744 5745 Collective on TS 5746 5747 Input Parameter: 5748 . ts - the TS context obtained from TSCreate() 5749 5750 Level: advanced 5751 5752 Notes: 5753 Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5754 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5755 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5756 the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce 5757 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5758 discontinuous source terms). 5759 5760 .seealso: `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5761 @*/ 5762 PetscErrorCode TSRestartStep(TS ts) 5763 { 5764 PetscFunctionBegin; 5765 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5766 ts->steprestart = PETSC_TRUE; 5767 PetscFunctionReturn(0); 5768 } 5769 5770 /*@ 5771 TSRollBack - Rolls back one time step 5772 5773 Collective on TS 5774 5775 Input Parameter: 5776 . ts - the TS context obtained from TSCreate() 5777 5778 Level: advanced 5779 5780 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5781 @*/ 5782 PetscErrorCode TSRollBack(TS ts) 5783 { 5784 PetscFunctionBegin; 5785 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 5786 PetscCheck(!ts->steprollback,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called"); 5787 PetscCheck(ts->ops->rollback,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name); 5788 PetscCall((*ts->ops->rollback)(ts)); 5789 ts->time_step = ts->ptime - ts->ptime_prev; 5790 ts->ptime = ts->ptime_prev; 5791 ts->ptime_prev = ts->ptime_prev_rollback; 5792 ts->steps--; 5793 ts->steprollback = PETSC_TRUE; 5794 PetscFunctionReturn(0); 5795 } 5796 5797 /*@ 5798 TSGetStages - Get the number of stages and stage values 5799 5800 Input Parameter: 5801 . ts - the TS context obtained from TSCreate() 5802 5803 Output Parameters: 5804 + ns - the number of stages 5805 - Y - the current stage vectors 5806 5807 Level: advanced 5808 5809 Notes: Both ns and Y can be NULL. 5810 5811 .seealso: `TSCreate()` 5812 @*/ 5813 PetscErrorCode TSGetStages(TS ts,PetscInt *ns,Vec **Y) 5814 { 5815 PetscFunctionBegin; 5816 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 5817 if (ns) PetscValidIntPointer(ns,2); 5818 if (Y) PetscValidPointer(Y,3); 5819 if (!ts->ops->getstages) { 5820 if (ns) *ns = 0; 5821 if (Y) *Y = NULL; 5822 } else { 5823 PetscCall((*ts->ops->getstages)(ts,ns,Y)); 5824 } 5825 PetscFunctionReturn(0); 5826 } 5827 5828 /*@C 5829 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5830 5831 Collective on SNES 5832 5833 Input Parameters: 5834 + ts - the TS context 5835 . t - current timestep 5836 . U - state vector 5837 . Udot - time derivative of state vector 5838 . shift - shift to apply, see note below 5839 - ctx - an optional user context 5840 5841 Output Parameters: 5842 + J - Jacobian matrix (not altered in this routine) 5843 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 5844 5845 Level: intermediate 5846 5847 Notes: 5848 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5849 5850 dF/dU + shift*dF/dUdot 5851 5852 Most users should not need to explicitly call this routine, as it 5853 is used internally within the nonlinear solvers. 5854 5855 This will first try to get the coloring from the DM. If the DM type has no coloring 5856 routine, then it will try to get the coloring from the matrix. This requires that the 5857 matrix have nonzero entries precomputed. 5858 5859 .seealso: `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5860 @*/ 5861 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx) 5862 { 5863 SNES snes; 5864 MatFDColoring color; 5865 PetscBool hascolor, matcolor = PETSC_FALSE; 5866 5867 PetscFunctionBegin; 5868 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5869 PetscCall(PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color)); 5870 if (!color) { 5871 DM dm; 5872 ISColoring iscoloring; 5873 5874 PetscCall(TSGetDM(ts, &dm)); 5875 PetscCall(DMHasColoring(dm, &hascolor)); 5876 if (hascolor && !matcolor) { 5877 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5878 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5879 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts)); 5880 PetscCall(MatFDColoringSetFromOptions(color)); 5881 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5882 PetscCall(ISColoringDestroy(&iscoloring)); 5883 } else { 5884 MatColoring mc; 5885 5886 PetscCall(MatColoringCreate(B, &mc)); 5887 PetscCall(MatColoringSetDistance(mc, 2)); 5888 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5889 PetscCall(MatColoringSetFromOptions(mc)); 5890 PetscCall(MatColoringApply(mc, &iscoloring)); 5891 PetscCall(MatColoringDestroy(&mc)); 5892 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5893 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts)); 5894 PetscCall(MatFDColoringSetFromOptions(color)); 5895 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5896 PetscCall(ISColoringDestroy(&iscoloring)); 5897 } 5898 PetscCall(PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color)); 5899 PetscCall(PetscObjectDereference((PetscObject) color)); 5900 } 5901 PetscCall(TSGetSNES(ts, &snes)); 5902 PetscCall(MatFDColoringApply(B, color, U, snes)); 5903 if (J != B) { 5904 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5905 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5906 } 5907 PetscFunctionReturn(0); 5908 } 5909 5910 /*@ 5911 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5912 5913 Input Parameters: 5914 + ts - the TS context 5915 - func - function called within TSFunctionDomainError 5916 5917 Calling sequence of func: 5918 $ PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject) 5919 5920 + ts - the TS context 5921 . time - the current time (of the stage) 5922 . state - the state to check if it is valid 5923 - reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable 5924 5925 Level: intermediate 5926 5927 Notes: 5928 If an implicit ODE solver is being used then, in addition to providing this routine, the 5929 user's code should call SNESSetFunctionDomainError() when domain errors occur during 5930 function evaluations where the functions are provided by TSSetIFunction() or TSSetRHSFunction(). 5931 Use TSGetSNES() to obtain the SNES object 5932 5933 Developer Notes: 5934 The naming of this function is inconsistent with the SNESSetFunctionDomainError() 5935 since one takes a function pointer and the other does not. 5936 5937 .seealso: `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5938 @*/ 5939 5940 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*)) 5941 { 5942 PetscFunctionBegin; 5943 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 5944 ts->functiondomainerror = func; 5945 PetscFunctionReturn(0); 5946 } 5947 5948 /*@ 5949 TSFunctionDomainError - Checks if the current state is valid 5950 5951 Input Parameters: 5952 + ts - the TS context 5953 . stagetime - time of the simulation 5954 - Y - state vector to check. 5955 5956 Output Parameter: 5957 . accept - Set to PETSC_FALSE if the current state vector is valid. 5958 5959 Note: 5960 This function is called by the TS integration routines and calls the user provided function (set with TSSetFunctionDomainError()) 5961 to check if the current state is valid. 5962 5963 Level: developer 5964 5965 .seealso: `TSSetFunctionDomainError()` 5966 @*/ 5967 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept) 5968 { 5969 PetscFunctionBegin; 5970 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5971 *accept = PETSC_TRUE; 5972 if (ts->functiondomainerror) { 5973 PetscStackCallStandard((*ts->functiondomainerror),ts,stagetime,Y,accept); 5974 } 5975 PetscFunctionReturn(0); 5976 } 5977 5978 /*@C 5979 TSClone - This function clones a time step object. 5980 5981 Collective 5982 5983 Input Parameter: 5984 . tsin - The input TS 5985 5986 Output Parameter: 5987 . tsout - The output TS (cloned) 5988 5989 Notes: 5990 This function is used to create a clone of a TS object. It is used in ARKIMEX for initializing the slope for first stage explicit methods. It will likely be replaced in the future with a mechanism of switching methods on the fly. 5991 5992 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 SNES snes_dup=NULL; TSGetSNES(ts,&snes_dup); TSSetSNES(ts,snes_dup); 5993 5994 Level: developer 5995 5996 .seealso: `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5997 @*/ 5998 PetscErrorCode TSClone(TS tsin, TS *tsout) 5999 { 6000 TS t; 6001 SNES snes_start; 6002 DM dm; 6003 TSType type; 6004 6005 PetscFunctionBegin; 6006 PetscValidPointer(tsin,1); 6007 *tsout = NULL; 6008 6009 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 6010 6011 /* General TS description */ 6012 t->numbermonitors = 0; 6013 t->monitorFrequency = 1; 6014 t->setupcalled = 0; 6015 t->ksp_its = 0; 6016 t->snes_its = 0; 6017 t->nwork = 0; 6018 t->rhsjacobian.time = PETSC_MIN_REAL; 6019 t->rhsjacobian.scale = 1.; 6020 t->ijacobian.shift = 1.; 6021 6022 PetscCall(TSGetSNES(tsin,&snes_start)); 6023 PetscCall(TSSetSNES(t,snes_start)); 6024 6025 PetscCall(TSGetDM(tsin,&dm)); 6026 PetscCall(TSSetDM(t,dm)); 6027 6028 t->adapt = tsin->adapt; 6029 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 6030 6031 t->trajectory = tsin->trajectory; 6032 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 6033 6034 t->event = tsin->event; 6035 if (t->event) t->event->refct++; 6036 6037 t->problem_type = tsin->problem_type; 6038 t->ptime = tsin->ptime; 6039 t->ptime_prev = tsin->ptime_prev; 6040 t->time_step = tsin->time_step; 6041 t->max_time = tsin->max_time; 6042 t->steps = tsin->steps; 6043 t->max_steps = tsin->max_steps; 6044 t->equation_type = tsin->equation_type; 6045 t->atol = tsin->atol; 6046 t->rtol = tsin->rtol; 6047 t->max_snes_failures = tsin->max_snes_failures; 6048 t->max_reject = tsin->max_reject; 6049 t->errorifstepfailed = tsin->errorifstepfailed; 6050 6051 PetscCall(TSGetType(tsin,&type)); 6052 PetscCall(TSSetType(t,type)); 6053 6054 t->vec_sol = NULL; 6055 6056 t->cfltime = tsin->cfltime; 6057 t->cfltime_local = tsin->cfltime_local; 6058 t->exact_final_time = tsin->exact_final_time; 6059 6060 PetscCall(PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps))); 6061 6062 if (((PetscObject)tsin)->fortran_func_pointers) { 6063 PetscInt i; 6064 PetscCall(PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers)); 6065 for (i=0; i<10; i++) { 6066 ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 6067 } 6068 } 6069 *tsout = t; 6070 PetscFunctionReturn(0); 6071 } 6072 6073 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y) 6074 { 6075 TS ts = (TS) ctx; 6076 6077 PetscFunctionBegin; 6078 PetscCall(TSComputeRHSFunction(ts,0,x,y)); 6079 PetscFunctionReturn(0); 6080 } 6081 6082 /*@ 6083 TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function. 6084 6085 Logically Collective on TS 6086 6087 Input Parameters: 6088 TS - the time stepping routine 6089 6090 Output Parameter: 6091 . flg - PETSC_TRUE if the multiply is likely correct 6092 6093 Options Database: 6094 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 6095 6096 Level: advanced 6097 6098 Notes: 6099 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 6100 6101 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 6102 @*/ 6103 PetscErrorCode TSRHSJacobianTest(TS ts,PetscBool *flg) 6104 { 6105 Mat J,B; 6106 TSRHSJacobian func; 6107 void* ctx; 6108 6109 PetscFunctionBegin; 6110 PetscCall(TSGetRHSJacobian(ts,&J,&B,&func,&ctx)); 6111 PetscCall((*func)(ts,0.0,ts->vec_sol,J,B,ctx)); 6112 PetscCall(MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg)); 6113 PetscFunctionReturn(0); 6114 } 6115 6116 /*@C 6117 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function. 6118 6119 Logically Collective on TS 6120 6121 Input Parameters: 6122 TS - the time stepping routine 6123 6124 Output Parameter: 6125 . flg - PETSC_TRUE if the multiply is likely correct 6126 6127 Options Database: 6128 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 6129 6130 Notes: 6131 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 6132 6133 Level: advanced 6134 6135 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 6136 @*/ 6137 PetscErrorCode TSRHSJacobianTestTranspose(TS ts,PetscBool *flg) 6138 { 6139 Mat J,B; 6140 void *ctx; 6141 TSRHSJacobian func; 6142 6143 PetscFunctionBegin; 6144 PetscCall(TSGetRHSJacobian(ts,&J,&B,&func,&ctx)); 6145 PetscCall((*func)(ts,0.0,ts->vec_sol,J,B,ctx)); 6146 PetscCall(MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg)); 6147 PetscFunctionReturn(0); 6148 } 6149 6150 /*@ 6151 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 6152 6153 Logically collective 6154 6155 Input Parameters: 6156 + ts - timestepping context 6157 - use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used 6158 6159 Options Database: 6160 . -ts_use_splitrhsfunction - <true,false> 6161 6162 Notes: 6163 This is only useful for multirate methods 6164 6165 Level: intermediate 6166 6167 .seealso: `TSGetUseSplitRHSFunction()` 6168 @*/ 6169 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 6170 { 6171 PetscFunctionBegin; 6172 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 6173 ts->use_splitrhsfunction = use_splitrhsfunction; 6174 PetscFunctionReturn(0); 6175 } 6176 6177 /*@ 6178 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 6179 6180 Not collective 6181 6182 Input Parameter: 6183 . ts - timestepping context 6184 6185 Output Parameter: 6186 . use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used 6187 6188 Level: intermediate 6189 6190 .seealso: `TSSetUseSplitRHSFunction()` 6191 @*/ 6192 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 6193 { 6194 PetscFunctionBegin; 6195 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 6196 *use_splitrhsfunction = ts->use_splitrhsfunction; 6197 PetscFunctionReturn(0); 6198 } 6199 6200 /*@ 6201 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 6202 6203 Logically Collective on ts 6204 6205 Input Parameters: 6206 + ts - the time-stepper 6207 - str - the structure (the default is UNKNOWN_NONZERO_PATTERN) 6208 6209 Level: intermediate 6210 6211 Notes: 6212 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 6213 6214 .seealso: `MatAXPY()`, `MatStructure` 6215 @*/ 6216 PetscErrorCode TSSetMatStructure(TS ts,MatStructure str) 6217 { 6218 PetscFunctionBegin; 6219 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 6220 ts->axpy_pattern = str; 6221 PetscFunctionReturn(0); 6222 } 6223 6224 /*@ 6225 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested. 6226 6227 Collective on ts 6228 6229 Input Parameters: 6230 + ts - the time-stepper 6231 . n - number of the time points (>=2) 6232 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 6233 6234 Options Database Keys: 6235 . -ts_time_span <t0,...tf> - Sets the time span 6236 6237 Level: beginner 6238 6239 Notes: 6240 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 6241 TS_EXACTFINALTIME_MATCHSTEP must be used to make the last time step in each sub-interval match the intermediate points specified. 6242 The intermediate solutions are saved in a vector array that can be accessed with TSGetSolutions(). Thus using time span may 6243 pressure the memory system when using a large number of span points. 6244 6245 .seealso: `TSGetTimeSpan()`, `TSGetSolutions()` 6246 @*/ 6247 PetscErrorCode TSSetTimeSpan(TS ts,PetscInt n,PetscReal *span_times) 6248 { 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 6251 PetscCheck(n >= 2,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Minimum time span size is 2 but %" PetscInt_FMT " is provided",n); 6252 if (ts->tspan && n != ts->tspan->num_span_times) { 6253 PetscCall(PetscFree(ts->tspan->span_times)); 6254 PetscCall(VecDestroyVecs(ts->tspan->num_span_times,&ts->tspan->vecs_sol)); 6255 PetscCall(PetscMalloc1(n,&ts->tspan->span_times)); 6256 } 6257 if (!ts->tspan) { 6258 TSTimeSpan tspan; 6259 PetscCall(PetscNew(&tspan)); 6260 PetscCall(PetscMalloc1(n,&tspan->span_times)); 6261 ts->tspan = tspan; 6262 } 6263 ts->tspan->num_span_times = n; 6264 PetscCall(PetscArraycpy(ts->tspan->span_times,span_times,n)); 6265 PetscCall(TSSetTime(ts,ts->tspan->span_times[0])); 6266 PetscCall(TSSetMaxTime(ts,ts->tspan->span_times[n-1])); 6267 PetscFunctionReturn(0); 6268 } 6269 6270 /*@C 6271 TSGetTimeSpan - gets the time span. 6272 6273 Not Collective 6274 6275 Input Parameter: 6276 . ts - the time-stepper 6277 6278 Output Parameters: 6279 + n - number of the time points (>=2) 6280 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. The values are valid until the TS object is destroyed. 6281 6282 Level: beginner 6283 Notes: Both n and span_times can be NULL. 6284 6285 .seealso: `TSSetTimeSpan()`, `TSGetSolutions()` 6286 @*/ 6287 PetscErrorCode TSGetTimeSpan(TS ts,PetscInt *n,const PetscReal **span_times) 6288 { 6289 PetscFunctionBegin; 6290 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 6291 if (n) PetscValidIntPointer(n,2); 6292 if (span_times) PetscValidPointer(span_times,3); 6293 if (!ts->tspan) { 6294 if (n) *n = 0; 6295 if (span_times) *span_times = NULL; 6296 } else { 6297 if (n) *n = ts->tspan->num_span_times; 6298 if (span_times) *span_times = ts->tspan->span_times; 6299 } 6300 PetscFunctionReturn(0); 6301 } 6302 6303 /*@ 6304 TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span. 6305 6306 Input Parameter: 6307 . ts - the TS context obtained from TSCreate() 6308 6309 Output Parameters: 6310 + nsol - the number of solutions 6311 - Sols - the solution vectors 6312 6313 Level: beginner 6314 6315 Notes: 6316 Both nsol and Sols can be NULL. 6317 Some time points in the time span may be skipped by TS so that nsol is less than the number of points specified by TSSetTimeSpan(). For example, manipulating the step size, especially with a reduced precision, may cause TS to step over certain points in the span. 6318 6319 .seealso: `TSSetTimeSpan()` 6320 @*/ 6321 PetscErrorCode TSGetTimeSpanSolutions(TS ts,PetscInt *nsol,Vec **Sols) 6322 { 6323 PetscFunctionBegin; 6324 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 6325 if (nsol) PetscValidIntPointer(nsol,2); 6326 if (Sols) PetscValidPointer(Sols,3); 6327 if (!ts->tspan) { 6328 if (nsol) *nsol = 0; 6329 if (Sols) *Sols = NULL; 6330 } else { 6331 if (nsol) *nsol = ts->tspan->spanctr; 6332 if (Sols) *Sols = ts->tspan->vecs_sol; 6333 } 6334 PetscFunctionReturn(0); 6335 } 6336