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