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