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