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