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 PetscErrorCode ierr; 89 char monfilename[PETSC_MAX_PATH_LEN]; 90 PetscReal time_step,tspan[100]; 91 PetscInt nt = PETSC_STATIC_ARRAY_LENGTH(tspan); 92 TSExactFinalTimeOption eftopt; 93 char dir[16]; 94 TSIFunction ifun; 95 const char *defaultType; 96 char typeName[256]; 97 98 PetscFunctionBegin; 99 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 100 101 PetscCall(TSRegisterAll()); 102 PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL)); 103 104 ierr = PetscObjectOptionsBegin((PetscObject)ts);PetscCall(ierr); 105 if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name; 106 else defaultType = ifun ? TSBEULER : TSEULER; 107 PetscCall(PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt)); 108 if (opt) { 109 PetscCall(TSSetType(ts,typeName)); 110 } else { 111 PetscCall(TSSetType(ts,defaultType)); 112 } 113 114 /* Handle generic TS options */ 115 PetscCall(PetscOptionsDeprecated("-ts_final_time","-ts_max_time","3.10",NULL)); 116 PetscCall(PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL)); 117 PetscCall(PetscOptionsRealArray("-ts_time_span","Time span","TSSetTimeSpan",tspan,&nt,&flg)); 118 if (flg) PetscCall(TSSetTimeSpan(ts,nt,tspan)); 119 PetscCall(PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL)); 120 PetscCall(PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL)); 121 PetscCall(PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg)); 122 if (flg) PetscCall(TSSetTimeStep(ts,time_step)); 123 PetscCall(PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg)); 124 if (flg) PetscCall(TSSetExactFinalTime(ts,eftopt)); 125 PetscCall(PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL)); 126 PetscCall(PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL)); 127 PetscCall(PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL)); 128 PetscCall(PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL)); 129 PetscCall(PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL)); 130 131 PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL)); 132 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)); 133 PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction","Use the split RHS function for multirate solvers ","TSSetUseSplitRHSFunction",ts->use_splitrhsfunction,&ts->use_splitrhsfunction,NULL)); 134 #if defined(PETSC_HAVE_SAWS) 135 { 136 PetscBool set; 137 flg = PETSC_FALSE; 138 PetscCall(PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set)); 139 if (set) { 140 PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts,flg)); 141 } 142 } 143 #endif 144 145 /* Monitor options */ 146 PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL)); 147 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL)); 148 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_extreme","Monitor extreme values of the solution","TSMonitorExtreme",TSMonitorExtreme,NULL)); 149 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL)); 150 PetscCall(TSMonitorSetFromOptions(ts,"-ts_dmswarm_monitor_moments","Monitor moments of particle distribution","TSDMSwarmMonitorMoments",TSDMSwarmMonitorMoments,NULL)); 151 152 PetscCall(PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",NULL,monfilename,sizeof(monfilename),&flg)); 153 if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts,monfilename)); 154 155 PetscCall(PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt)); 156 if (opt) { 157 PetscInt howoften = 1; 158 DM dm; 159 PetscBool net; 160 161 PetscCall(PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL)); 162 PetscCall(TSGetDM(ts,&dm)); 163 PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMNETWORK,&net)); 164 if (net) { 165 TSMonitorLGCtxNetwork ctx; 166 PetscCall(TSMonitorLGCtxNetworkCreate(ts,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx)); 167 PetscCall(TSMonitorSet(ts,TSMonitorLGCtxNetworkSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxNetworkDestroy)); 168 PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy","Plot the solution with a semi-log axis","",ctx->semilogy,&ctx->semilogy,NULL)); 169 } else { 170 TSMonitorLGCtx ctx; 171 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 172 PetscCall(TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 173 } 174 } 175 176 PetscCall(PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt)); 177 if (opt) { 178 TSMonitorLGCtx ctx; 179 PetscInt howoften = 1; 180 181 PetscCall(PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL)); 182 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 183 PetscCall(TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 184 } 185 PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL)); 186 187 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt)); 188 if (opt) { 189 TSMonitorLGCtx ctx; 190 PetscInt howoften = 1; 191 192 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL)); 193 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 194 PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 195 } 196 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt)); 197 if (opt) { 198 TSMonitorLGCtx ctx; 199 PetscInt howoften = 1; 200 201 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL)); 202 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 203 PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 204 ctx->semilogy = PETSC_TRUE; 205 } 206 207 PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt)); 208 if (opt) { 209 TSMonitorLGCtx ctx; 210 PetscInt howoften = 1; 211 212 PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL)); 213 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 214 PetscCall(TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 215 } 216 PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt)); 217 if (opt) { 218 TSMonitorLGCtx ctx; 219 PetscInt howoften = 1; 220 221 PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL)); 222 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx)); 223 PetscCall(TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 224 } 225 PetscCall(PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt)); 226 if (opt) { 227 TSMonitorSPEigCtx ctx; 228 PetscInt howoften = 1; 229 230 PetscCall(PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL)); 231 PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 232 PetscCall(TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy)); 233 } 234 PetscCall(PetscOptionsName("-ts_monitor_sp_swarm","Display particle phase from the DMSwarm","TSMonitorSPSwarm",&opt)); 235 if (opt) { 236 TSMonitorSPCtx ctx; 237 PetscInt howoften = 1, retain = 0; 238 PetscBool phase = PETSC_TRUE; 239 240 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm","Display particles phase from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL)); 241 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL)); 242 PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL)); 243 PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject) ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, &ctx)); 244 PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void**))TSMonitorSPCtxDestroy)); 245 } 246 opt = PETSC_FALSE; 247 PetscCall(PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt)); 248 if (opt) { 249 TSMonitorDrawCtx ctx; 250 PetscInt howoften = 1; 251 252 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL)); 253 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 254 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 255 } 256 opt = PETSC_FALSE; 257 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt)); 258 if (opt) { 259 TSMonitorDrawCtx ctx; 260 PetscReal bounds[4]; 261 PetscInt n = 4; 262 PetscDraw draw; 263 PetscDrawAxis axis; 264 265 PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL)); 266 PetscCheck(n == 4,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field"); 267 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx)); 268 PetscCall(PetscViewerDrawGetDraw(ctx->viewer,0,&draw)); 269 PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis)); 270 PetscCall(PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3])); 271 PetscCall(PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2")); 272 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 273 } 274 opt = PETSC_FALSE; 275 PetscCall(PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt)); 276 if (opt) { 277 TSMonitorDrawCtx ctx; 278 PetscInt howoften = 1; 279 280 PetscCall(PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL)); 281 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 282 PetscCall(TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 283 } 284 opt = PETSC_FALSE; 285 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt)); 286 if (opt) { 287 TSMonitorDrawCtx ctx; 288 PetscInt howoften = 1; 289 290 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL)); 291 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx)); 292 PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy)); 293 } 294 295 opt = PETSC_FALSE; 296 PetscCall(PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",NULL,monfilename,sizeof(monfilename),&flg)); 297 if (flg) { 298 const char *ptr,*ptr2; 299 char *filetemplate; 300 PetscCheck(monfilename[0],PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts"); 301 /* Do some cursory validation of the input. */ 302 PetscCall(PetscStrstr(monfilename,"%",(char**)&ptr)); 303 PetscCheck(ptr,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts"); 304 for (ptr++; ptr && *ptr; ptr++) { 305 PetscCall(PetscStrchr("DdiouxX",*ptr,(char**)&ptr2)); 306 PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'),PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03D.vts"); 307 if (ptr2) break; 308 } 309 PetscCall(PetscStrallocpy(monfilename,&filetemplate)); 310 PetscCall(TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy)); 311 } 312 313 PetscCall(PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,sizeof(dir),&flg)); 314 if (flg) { 315 TSMonitorDMDARayCtx *rayctx; 316 int ray = 0; 317 DMDirection ddir; 318 DM da; 319 PetscMPIInt rank; 320 321 PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir); 322 if (dir[0] == 'x') ddir = DM_X; 323 else if (dir[0] == 'y') ddir = DM_Y; 324 else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir); 325 sscanf(dir+2,"%d",&ray); 326 327 PetscCall(PetscInfo(((PetscObject)ts),"Displaying DMDA ray %c = %d\n",dir[0],ray)); 328 PetscCall(PetscNew(&rayctx)); 329 PetscCall(TSGetDM(ts,&da)); 330 PetscCall(DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter)); 331 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank)); 332 if (rank == 0) { 333 PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF,NULL,NULL,0,0,600,300,&rayctx->viewer)); 334 } 335 rayctx->lgctx = NULL; 336 PetscCall(TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy)); 337 } 338 PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,sizeof(dir),&flg)); 339 if (flg) { 340 TSMonitorDMDARayCtx *rayctx; 341 int ray = 0; 342 DMDirection ddir; 343 DM da; 344 PetscInt howoften = 1; 345 346 PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir); 347 if (dir[0] == 'x') ddir = DM_X; 348 else if (dir[0] == 'y') ddir = DM_Y; 349 else SETERRQ(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir); 350 sscanf(dir+2, "%d", &ray); 351 352 PetscCall(PetscInfo(((PetscObject) ts),"Displaying LG DMDA ray %c = %d\n", dir[0], ray)); 353 PetscCall(PetscNew(&rayctx)); 354 PetscCall(TSGetDM(ts, &da)); 355 PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter)); 356 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx)); 357 PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy)); 358 } 359 360 PetscCall(PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt)); 361 if (opt) { 362 TSMonitorEnvelopeCtx ctx; 363 364 PetscCall(TSMonitorEnvelopeCtxCreate(ts,&ctx)); 365 PetscCall(TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy)); 366 } 367 flg = PETSC_FALSE; 368 PetscCall(PetscOptionsBool("-ts_monitor_cancel","Remove all monitors","TSMonitorCancel",flg,&flg,&opt)); 369 if (opt && flg) PetscCall(TSMonitorCancel(ts)); 370 371 flg = PETSC_FALSE; 372 PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL)); 373 if (flg) { 374 DM dm; 375 DMTS tdm; 376 377 PetscCall(TSGetDM(ts, &dm)); 378 PetscCall(DMGetDMTS(dm, &tdm)); 379 tdm->ijacobianctx = NULL; 380 PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL)); 381 PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n")); 382 } 383 384 /* Handle specific TS options */ 385 if (ts->ops->setfromoptions) { 386 PetscCall((*ts->ops->setfromoptions)(PetscOptionsObject,ts)); 387 } 388 389 /* Handle TSAdapt options */ 390 PetscCall(TSGetAdapt(ts,&ts->adapt)); 391 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 392 PetscCall(TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt)); 393 394 /* TS trajectory must be set after TS, since it may use some TS options above */ 395 tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE; 396 PetscCall(PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL)); 397 if (tflg) { 398 PetscCall(TSSetSaveTrajectory(ts)); 399 } 400 401 PetscCall(TSAdjointSetFromOptions(PetscOptionsObject,ts)); 402 403 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 404 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts)); 405 ierr = PetscOptionsEnd();PetscCall(ierr); 406 407 if (ts->trajectory) { 408 PetscCall(TSTrajectorySetFromOptions(ts->trajectory,ts)); 409 } 410 411 /* why do we have to do this here and not during TSSetUp? */ 412 PetscCall(TSGetSNES(ts,&ts->snes)); 413 if (ts->problem_type == TS_LINEAR) { 414 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&flg,SNESKSPONLY,SNESKSPTRANSPOSEONLY,"")); 415 if (!flg) PetscCall(SNESSetType(ts->snes,SNESKSPONLY)); 416 } 417 PetscCall(SNESSetFromOptions(ts->snes)); 418 PetscFunctionReturn(0); 419 } 420 421 /*@ 422 TSGetTrajectory - Gets the trajectory from a TS if it exists 423 424 Collective on TS 425 426 Input Parameters: 427 . ts - the TS context obtained from TSCreate() 428 429 Output Parameters: 430 . tr - the TSTrajectory object, if it exists 431 432 Note: This routine should be called after all TS options have been set 433 434 Level: advanced 435 436 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSTrajectory, TSTrajectoryCreate() 437 438 @*/ 439 PetscErrorCode TSGetTrajectory(TS ts,TSTrajectory *tr) 440 { 441 PetscFunctionBegin; 442 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 443 *tr = ts->trajectory; 444 PetscFunctionReturn(0); 445 } 446 447 /*@ 448 TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object 449 450 Collective on TS 451 452 Input Parameter: 453 . ts - the TS context obtained from TSCreate() 454 455 Options Database: 456 + -ts_save_trajectory - saves the trajectory to a file 457 - -ts_trajectory_type type - set trajectory type 458 459 Note: This routine should be called after all TS options have been set 460 461 The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and 462 MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m 463 464 Level: intermediate 465 466 .seealso: TSGetTrajectory(), TSAdjointSolve() 467 468 @*/ 469 PetscErrorCode TSSetSaveTrajectory(TS ts) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 473 if (!ts->trajectory) { 474 PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory)); 475 } 476 PetscFunctionReturn(0); 477 } 478 479 /*@ 480 TSResetTrajectory - Destroys and recreates the internal TSTrajectory object 481 482 Collective on TS 483 484 Input Parameters: 485 . ts - the TS context obtained from TSCreate() 486 487 Level: intermediate 488 489 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSRemoveTrajectory() 490 491 @*/ 492 PetscErrorCode TSResetTrajectory(TS ts) 493 { 494 PetscFunctionBegin; 495 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 496 if (ts->trajectory) { 497 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 498 PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory)); 499 } 500 PetscFunctionReturn(0); 501 } 502 503 /*@ 504 TSRemoveTrajectory - Destroys and removes the internal TSTrajectory object from TS 505 506 Collective on TS 507 508 Input Parameters: 509 . ts - the TS context obtained from TSCreate() 510 511 Level: intermediate 512 513 .seealso: TSResetTrajectory(), TSAdjointSolve() 514 515 @*/ 516 PetscErrorCode TSRemoveTrajectory(TS ts) 517 { 518 PetscFunctionBegin; 519 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 520 if (ts->trajectory) { 521 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 522 } 523 PetscFunctionReturn(0); 524 } 525 526 /*@ 527 TSComputeRHSJacobian - Computes the Jacobian matrix that has been 528 set with TSSetRHSJacobian(). 529 530 Collective on TS 531 532 Input Parameters: 533 + ts - the TS context 534 . t - current timestep 535 - U - input vector 536 537 Output Parameters: 538 + A - Jacobian matrix 539 - B - optional preconditioning matrix 540 541 Notes: 542 Most users should not need to explicitly call this routine, as it 543 is used internally within the nonlinear solvers. 544 545 Level: developer 546 547 .seealso: TSSetRHSJacobian(), KSPSetOperators() 548 @*/ 549 PetscErrorCode TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B) 550 { 551 PetscObjectState Ustate; 552 PetscObjectId Uid; 553 DM dm; 554 DMTS tsdm; 555 TSRHSJacobian rhsjacobianfunc; 556 void *ctx; 557 TSRHSFunction rhsfunction; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 561 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 562 PetscCheckSameComm(ts,1,U,3); 563 PetscCall(TSGetDM(ts,&dm)); 564 PetscCall(DMGetDMTS(dm,&tsdm)); 565 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 566 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx)); 567 PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate)); 568 PetscCall(PetscObjectGetId((PetscObject)U,&Uid)); 569 570 if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(0); 571 572 PetscCheck(ts->rhsjacobian.shift == 0.0 || !ts->rhsjacobian.reuse,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Should not call TSComputeRHSJacobian() on a shifted matrix (shift=%lf) when RHSJacobian is reusable.",ts->rhsjacobian.shift); 573 if (rhsjacobianfunc) { 574 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B)); 575 PetscStackPush("TS user Jacobian function"); 576 PetscCall((*rhsjacobianfunc)(ts,t,U,A,B,ctx)); 577 PetscStackPop; 578 ts->rhsjacs++; 579 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B)); 580 } else { 581 PetscCall(MatZeroEntries(A)); 582 if (B && A != B) PetscCall(MatZeroEntries(B)); 583 } 584 ts->rhsjacobian.time = t; 585 ts->rhsjacobian.shift = 0; 586 ts->rhsjacobian.scale = 1.; 587 PetscCall(PetscObjectGetId((PetscObject)U,&ts->rhsjacobian.Xid)); 588 PetscCall(PetscObjectStateGet((PetscObject)U,&ts->rhsjacobian.Xstate)); 589 PetscFunctionReturn(0); 590 } 591 592 /*@ 593 TSComputeRHSFunction - Evaluates the right-hand-side function. 594 595 Collective on TS 596 597 Input Parameters: 598 + ts - the TS context 599 . t - current time 600 - U - state vector 601 602 Output Parameter: 603 . y - right hand side 604 605 Note: 606 Most users should not need to explicitly call this routine, as it 607 is used internally within the nonlinear solvers. 608 609 Level: developer 610 611 .seealso: TSSetRHSFunction(), TSComputeIFunction() 612 @*/ 613 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y) 614 { 615 TSRHSFunction rhsfunction; 616 TSIFunction ifunction; 617 void *ctx; 618 DM dm; 619 620 PetscFunctionBegin; 621 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 622 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 623 PetscValidHeaderSpecific(y,VEC_CLASSID,4); 624 PetscCall(TSGetDM(ts,&dm)); 625 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,&ctx)); 626 PetscCall(DMTSGetIFunction(dm,&ifunction,NULL)); 627 628 PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()"); 629 630 if (rhsfunction) { 631 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,y,0)); 632 PetscCall(VecLockReadPush(U)); 633 PetscStackPush("TS user right-hand-side function"); 634 PetscCall((*rhsfunction)(ts,t,U,y,ctx)); 635 PetscStackPop; 636 PetscCall(VecLockReadPop(U)); 637 ts->rhsfuncs++; 638 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,y,0)); 639 } else { 640 PetscCall(VecZeroEntries(y)); 641 } 642 PetscFunctionReturn(0); 643 } 644 645 /*@ 646 TSComputeSolutionFunction - Evaluates the solution function. 647 648 Collective on TS 649 650 Input Parameters: 651 + ts - the TS context 652 - t - current time 653 654 Output Parameter: 655 . U - the solution 656 657 Note: 658 Most users should not need to explicitly call this routine, as it 659 is used internally within the nonlinear solvers. 660 661 Level: developer 662 663 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction() 664 @*/ 665 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U) 666 { 667 TSSolutionFunction solutionfunction; 668 void *ctx; 669 DM dm; 670 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 673 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 674 PetscCall(TSGetDM(ts,&dm)); 675 PetscCall(DMTSGetSolutionFunction(dm,&solutionfunction,&ctx)); 676 677 if (solutionfunction) { 678 PetscStackPush("TS user solution function"); 679 PetscCall((*solutionfunction)(ts,t,U,ctx)); 680 PetscStackPop; 681 } 682 PetscFunctionReturn(0); 683 } 684 /*@ 685 TSComputeForcingFunction - Evaluates the forcing function. 686 687 Collective on TS 688 689 Input Parameters: 690 + ts - the TS context 691 - t - current time 692 693 Output Parameter: 694 . U - the function value 695 696 Note: 697 Most users should not need to explicitly call this routine, as it 698 is used internally within the nonlinear solvers. 699 700 Level: developer 701 702 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction() 703 @*/ 704 PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U) 705 { 706 void *ctx; 707 DM dm; 708 TSForcingFunction forcing; 709 710 PetscFunctionBegin; 711 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 712 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 713 PetscCall(TSGetDM(ts,&dm)); 714 PetscCall(DMTSGetForcingFunction(dm,&forcing,&ctx)); 715 716 if (forcing) { 717 PetscStackPush("TS user forcing function"); 718 PetscCall((*forcing)(ts,t,U,ctx)); 719 PetscStackPop; 720 } 721 PetscFunctionReturn(0); 722 } 723 724 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs) 725 { 726 Vec F; 727 728 PetscFunctionBegin; 729 *Frhs = NULL; 730 PetscCall(TSGetIFunction(ts,&F,NULL,NULL)); 731 if (!ts->Frhs) { 732 PetscCall(VecDuplicate(F,&ts->Frhs)); 733 } 734 *Frhs = ts->Frhs; 735 PetscFunctionReturn(0); 736 } 737 738 PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs) 739 { 740 Mat A,B; 741 TSIJacobian ijacobian; 742 743 PetscFunctionBegin; 744 if (Arhs) *Arhs = NULL; 745 if (Brhs) *Brhs = NULL; 746 PetscCall(TSGetIJacobian(ts,&A,&B,&ijacobian,NULL)); 747 if (Arhs) { 748 if (!ts->Arhs) { 749 if (ijacobian) { 750 PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs)); 751 PetscCall(TSSetMatStructure(ts,SAME_NONZERO_PATTERN)); 752 } else { 753 ts->Arhs = A; 754 PetscCall(PetscObjectReference((PetscObject)A)); 755 } 756 } else { 757 PetscBool flg; 758 PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg)); 759 /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */ 760 if (flg && !ijacobian && ts->Arhs == ts->Brhs) { 761 PetscCall(PetscObjectDereference((PetscObject)ts->Arhs)); 762 ts->Arhs = A; 763 PetscCall(PetscObjectReference((PetscObject)A)); 764 } 765 } 766 *Arhs = ts->Arhs; 767 } 768 if (Brhs) { 769 if (!ts->Brhs) { 770 if (A != B) { 771 if (ijacobian) { 772 PetscCall(MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs)); 773 } else { 774 ts->Brhs = B; 775 PetscCall(PetscObjectReference((PetscObject)B)); 776 } 777 } else { 778 PetscCall(PetscObjectReference((PetscObject)ts->Arhs)); 779 ts->Brhs = ts->Arhs; 780 } 781 } 782 *Brhs = ts->Brhs; 783 } 784 PetscFunctionReturn(0); 785 } 786 787 /*@ 788 TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0 789 790 Collective on TS 791 792 Input Parameters: 793 + ts - the TS context 794 . t - current time 795 . U - state vector 796 . Udot - time derivative of state vector 797 - imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate 798 799 Output Parameter: 800 . Y - right hand side 801 802 Note: 803 Most users should not need to explicitly call this routine, as it 804 is used internally within the nonlinear solvers. 805 806 If the user did did not write their equations in implicit form, this 807 function recasts them in implicit form. 808 809 Level: developer 810 811 .seealso: TSSetIFunction(), TSComputeRHSFunction() 812 @*/ 813 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex) 814 { 815 TSIFunction ifunction; 816 TSRHSFunction rhsfunction; 817 void *ctx; 818 DM dm; 819 820 PetscFunctionBegin; 821 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 822 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 823 PetscValidHeaderSpecific(Udot,VEC_CLASSID,4); 824 PetscValidHeaderSpecific(Y,VEC_CLASSID,5); 825 826 PetscCall(TSGetDM(ts,&dm)); 827 PetscCall(DMTSGetIFunction(dm,&ifunction,&ctx)); 828 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 829 830 PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()"); 831 832 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y)); 833 if (ifunction) { 834 PetscStackPush("TS user implicit function"); 835 PetscCall((*ifunction)(ts,t,U,Udot,Y,ctx)); 836 PetscStackPop; 837 ts->ifuncs++; 838 } 839 if (imex) { 840 if (!ifunction) { 841 PetscCall(VecCopy(Udot,Y)); 842 } 843 } else if (rhsfunction) { 844 if (ifunction) { 845 Vec Frhs; 846 PetscCall(TSGetRHSVec_Private(ts,&Frhs)); 847 PetscCall(TSComputeRHSFunction(ts,t,U,Frhs)); 848 PetscCall(VecAXPY(Y,-1,Frhs)); 849 } else { 850 PetscCall(TSComputeRHSFunction(ts,t,U,Y)); 851 PetscCall(VecAYPX(Y,-1,Udot)); 852 } 853 } 854 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y)); 855 PetscFunctionReturn(0); 856 } 857 858 /* 859 TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call TSComputeRHSJacobian() on it. 860 861 Note: 862 This routine is needed when one switches from TSComputeIJacobian() to TSComputeRHSJacobian() because the Jacobian matrix may be shifted or scaled in TSComputeIJacobian(). 863 864 */ 865 static PetscErrorCode TSRecoverRHSJacobian(TS ts,Mat A,Mat B) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 869 PetscCheck(A == ts->Arhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Amat"); 870 PetscCheck(B == ts->Brhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Bmat"); 871 872 if (ts->rhsjacobian.shift) { 873 PetscCall(MatShift(A,-ts->rhsjacobian.shift)); 874 } 875 if (ts->rhsjacobian.scale == -1.) { 876 PetscCall(MatScale(A,-1)); 877 } 878 if (B && B == ts->Brhs && A != B) { 879 if (ts->rhsjacobian.shift) { 880 PetscCall(MatShift(B,-ts->rhsjacobian.shift)); 881 } 882 if (ts->rhsjacobian.scale == -1.) { 883 PetscCall(MatScale(B,-1)); 884 } 885 } 886 ts->rhsjacobian.shift = 0; 887 ts->rhsjacobian.scale = 1.; 888 PetscFunctionReturn(0); 889 } 890 891 /*@ 892 TSComputeIJacobian - Evaluates the Jacobian of the DAE 893 894 Collective on TS 895 896 Input 897 Input Parameters: 898 + ts - the TS context 899 . t - current timestep 900 . U - state vector 901 . Udot - time derivative of state vector 902 . shift - shift to apply, see note below 903 - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate 904 905 Output Parameters: 906 + A - Jacobian matrix 907 - B - matrix from which the preconditioner is constructed; often the same as A 908 909 Notes: 910 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 911 912 dF/dU + shift*dF/dUdot 913 914 Most users should not need to explicitly call this routine, as it 915 is used internally within the nonlinear solvers. 916 917 Level: developer 918 919 .seealso: TSSetIJacobian() 920 @*/ 921 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,PetscBool imex) 922 { 923 TSIJacobian ijacobian; 924 TSRHSJacobian rhsjacobian; 925 DM dm; 926 void *ctx; 927 928 PetscFunctionBegin; 929 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 930 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 931 PetscValidHeaderSpecific(Udot,VEC_CLASSID,4); 932 PetscValidPointer(A,6); 933 PetscValidHeaderSpecific(A,MAT_CLASSID,6); 934 PetscValidPointer(B,7); 935 PetscValidHeaderSpecific(B,MAT_CLASSID,7); 936 937 PetscCall(TSGetDM(ts,&dm)); 938 PetscCall(DMTSGetIJacobian(dm,&ijacobian,&ctx)); 939 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL)); 940 941 PetscCheck(rhsjacobian || ijacobian,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()"); 942 943 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B)); 944 if (ijacobian) { 945 PetscStackPush("TS user implicit Jacobian"); 946 PetscCall((*ijacobian)(ts,t,U,Udot,shift,A,B,ctx)); 947 ts->ijacs++; 948 PetscStackPop; 949 } 950 if (imex) { 951 if (!ijacobian) { /* system was written as Udot = G(t,U) */ 952 PetscBool assembled; 953 if (rhsjacobian) { 954 Mat Arhs = NULL; 955 PetscCall(TSGetRHSMats_Private(ts,&Arhs,NULL)); 956 if (A == Arhs) { 957 PetscCheck(rhsjacobian != TSComputeRHSJacobianConstant,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Unsupported operation! cannot use TSComputeRHSJacobianConstant"); /* there is no way to reconstruct shift*M-J since J cannot be reevaluated */ 958 ts->rhsjacobian.time = PETSC_MIN_REAL; 959 } 960 } 961 PetscCall(MatZeroEntries(A)); 962 PetscCall(MatAssembled(A,&assembled)); 963 if (!assembled) { 964 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 965 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 966 } 967 PetscCall(MatShift(A,shift)); 968 if (A != B) { 969 PetscCall(MatZeroEntries(B)); 970 PetscCall(MatAssembled(B,&assembled)); 971 if (!assembled) { 972 PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 973 PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 974 } 975 PetscCall(MatShift(B,shift)); 976 } 977 } 978 } else { 979 Mat Arhs = NULL,Brhs = NULL; 980 if (rhsjacobian) { /* RHSJacobian needs to be converted to part of IJacobian if exists */ 981 PetscCall(TSGetRHSMats_Private(ts,&Arhs,&Brhs)); 982 } 983 if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */ 984 PetscObjectState Ustate; 985 PetscObjectId Uid; 986 TSRHSFunction rhsfunction; 987 988 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 989 PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate)); 990 PetscCall(PetscObjectGetId((PetscObject)U,&Uid)); 991 if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) && ts->rhsjacobian.scale == -1.) { /* No need to recompute RHSJacobian */ 992 PetscCall(MatShift(A,shift-ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */ 993 if (A != B) { 994 PetscCall(MatShift(B,shift-ts->rhsjacobian.shift)); 995 } 996 } else { 997 PetscBool flg; 998 999 if (ts->rhsjacobian.reuse) { /* Undo the damage */ 1000 /* MatScale has a short path for this case. 1001 However, this code path is taken the first time TSComputeRHSJacobian is called 1002 and the matrices have not been assembled yet */ 1003 PetscCall(TSRecoverRHSJacobian(ts,A,B)); 1004 } 1005 PetscCall(TSComputeRHSJacobian(ts,t,U,A,B)); 1006 PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg)); 1007 /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */ 1008 if (!flg) { 1009 PetscCall(MatScale(A,-1)); 1010 PetscCall(MatShift(A,shift)); 1011 } 1012 if (A != B) { 1013 PetscCall(MatScale(B,-1)); 1014 PetscCall(MatShift(B,shift)); 1015 } 1016 } 1017 ts->rhsjacobian.scale = -1; 1018 ts->rhsjacobian.shift = shift; 1019 } else if (Arhs) { /* Both IJacobian and RHSJacobian */ 1020 if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */ 1021 PetscCall(MatZeroEntries(A)); 1022 PetscCall(MatShift(A,shift)); 1023 if (A != B) { 1024 PetscCall(MatZeroEntries(B)); 1025 PetscCall(MatShift(B,shift)); 1026 } 1027 } 1028 PetscCall(TSComputeRHSJacobian(ts,t,U,Arhs,Brhs)); 1029 PetscCall(MatAXPY(A,-1,Arhs,ts->axpy_pattern)); 1030 if (A != B) { 1031 PetscCall(MatAXPY(B,-1,Brhs,ts->axpy_pattern)); 1032 } 1033 } 1034 } 1035 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B)); 1036 PetscFunctionReturn(0); 1037 } 1038 1039 /*@C 1040 TSSetRHSFunction - Sets the routine for evaluating the function, 1041 where U_t = G(t,u). 1042 1043 Logically Collective on TS 1044 1045 Input Parameters: 1046 + ts - the TS context obtained from TSCreate() 1047 . r - vector to put the computed right hand side (or NULL to have it created) 1048 . f - routine for evaluating the right-hand-side function 1049 - ctx - [optional] user-defined context for private data for the 1050 function evaluation routine (may be NULL) 1051 1052 Calling sequence of f: 1053 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec F,void *ctx); 1054 1055 + ts - timestep context 1056 . t - current timestep 1057 . u - input vector 1058 . F - function vector 1059 - ctx - [optional] user-defined function context 1060 1061 Level: beginner 1062 1063 Notes: 1064 You must call this function or TSSetIFunction() to define your ODE. You cannot use this function when solving a DAE. 1065 1066 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSSetIFunction() 1067 @*/ 1068 PetscErrorCode TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx) 1069 { 1070 SNES snes; 1071 Vec ralloc = NULL; 1072 DM dm; 1073 1074 PetscFunctionBegin; 1075 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1076 if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2); 1077 1078 PetscCall(TSGetDM(ts,&dm)); 1079 PetscCall(DMTSSetRHSFunction(dm,f,ctx)); 1080 PetscCall(TSGetSNES(ts,&snes)); 1081 if (!r && !ts->dm && ts->vec_sol) { 1082 PetscCall(VecDuplicate(ts->vec_sol,&ralloc)); 1083 r = ralloc; 1084 } 1085 PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts)); 1086 PetscCall(VecDestroy(&ralloc)); 1087 PetscFunctionReturn(0); 1088 } 1089 1090 /*@C 1091 TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE 1092 1093 Logically Collective on TS 1094 1095 Input Parameters: 1096 + ts - the TS context obtained from TSCreate() 1097 . f - routine for evaluating the solution 1098 - ctx - [optional] user-defined context for private data for the 1099 function evaluation routine (may be NULL) 1100 1101 Calling sequence of f: 1102 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,void *ctx); 1103 1104 + t - current timestep 1105 . u - output vector 1106 - ctx - [optional] user-defined function context 1107 1108 Options Database: 1109 + -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided TSSetSolutionFunction() 1110 - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction() 1111 1112 Notes: 1113 This routine is used for testing accuracy of time integration schemes when you already know the solution. 1114 If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to 1115 create closed-form solutions with non-physical forcing terms. 1116 1117 For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history. 1118 1119 Level: beginner 1120 1121 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetForcingFunction(), TSSetSolution(), TSGetSolution(), TSMonitorLGError(), TSMonitorDrawError() 1122 @*/ 1123 PetscErrorCode TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx) 1124 { 1125 DM dm; 1126 1127 PetscFunctionBegin; 1128 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1129 PetscCall(TSGetDM(ts,&dm)); 1130 PetscCall(DMTSSetSolutionFunction(dm,f,ctx)); 1131 PetscFunctionReturn(0); 1132 } 1133 1134 /*@C 1135 TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE 1136 1137 Logically Collective on TS 1138 1139 Input Parameters: 1140 + ts - the TS context obtained from TSCreate() 1141 . func - routine for evaluating the forcing function 1142 - ctx - [optional] user-defined context for private data for the 1143 function evaluation routine (may be NULL) 1144 1145 Calling sequence of func: 1146 $ PetscErrorCode func (TS ts,PetscReal t,Vec f,void *ctx); 1147 1148 + t - current timestep 1149 . f - output vector 1150 - ctx - [optional] user-defined function context 1151 1152 Notes: 1153 This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to 1154 create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the 1155 definition of the problem you are solving and hence possibly introducing bugs. 1156 1157 This replaces the ODE F(u,u_t,t) = 0 the TS is solving with F(u,u_t,t) - func(t) = 0 1158 1159 This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the 1160 parameters can be passed in the ctx variable. 1161 1162 For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history. 1163 1164 Level: beginner 1165 1166 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetSolutionFunction() 1167 @*/ 1168 PetscErrorCode TSSetForcingFunction(TS ts,TSForcingFunction func,void *ctx) 1169 { 1170 DM dm; 1171 1172 PetscFunctionBegin; 1173 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1174 PetscCall(TSGetDM(ts,&dm)); 1175 PetscCall(DMTSSetForcingFunction(dm,func,ctx)); 1176 PetscFunctionReturn(0); 1177 } 1178 1179 /*@C 1180 TSSetRHSJacobian - Sets the function to compute the Jacobian of G, 1181 where U_t = G(U,t), as well as the location to store the matrix. 1182 1183 Logically Collective on TS 1184 1185 Input Parameters: 1186 + ts - the TS context obtained from TSCreate() 1187 . Amat - (approximate) Jacobian matrix 1188 . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat) 1189 . f - the Jacobian evaluation routine 1190 - ctx - [optional] user-defined context for private data for the 1191 Jacobian evaluation routine (may be NULL) 1192 1193 Calling sequence of f: 1194 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx); 1195 1196 + t - current timestep 1197 . u - input vector 1198 . Amat - (approximate) Jacobian matrix 1199 . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat) 1200 - ctx - [optional] user-defined context for matrix evaluation routine 1201 1202 Notes: 1203 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1204 1205 The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f() 1206 You should not assume the values are the same in the next call to f() as you set them in the previous call. 1207 1208 Level: beginner 1209 1210 .seealso: SNESComputeJacobianDefaultColor(), TSSetRHSFunction(), TSRHSJacobianSetReuse(), TSSetIJacobian() 1211 1212 @*/ 1213 PetscErrorCode TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx) 1214 { 1215 SNES snes; 1216 DM dm; 1217 TSIJacobian ijacobian; 1218 1219 PetscFunctionBegin; 1220 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1221 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1222 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 1223 if (Amat) PetscCheckSameComm(ts,1,Amat,2); 1224 if (Pmat) PetscCheckSameComm(ts,1,Pmat,3); 1225 1226 PetscCall(TSGetDM(ts,&dm)); 1227 PetscCall(DMTSSetRHSJacobian(dm,f,ctx)); 1228 PetscCall(DMTSGetIJacobian(dm,&ijacobian,NULL)); 1229 PetscCall(TSGetSNES(ts,&snes)); 1230 if (!ijacobian) { 1231 PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts)); 1232 } 1233 if (Amat) { 1234 PetscCall(PetscObjectReference((PetscObject)Amat)); 1235 PetscCall(MatDestroy(&ts->Arhs)); 1236 ts->Arhs = Amat; 1237 } 1238 if (Pmat) { 1239 PetscCall(PetscObjectReference((PetscObject)Pmat)); 1240 PetscCall(MatDestroy(&ts->Brhs)); 1241 ts->Brhs = Pmat; 1242 } 1243 PetscFunctionReturn(0); 1244 } 1245 1246 /*@C 1247 TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved. 1248 1249 Logically Collective on TS 1250 1251 Input Parameters: 1252 + ts - the TS context obtained from TSCreate() 1253 . r - vector to hold the residual (or NULL to have it created internally) 1254 . f - the function evaluation routine 1255 - ctx - user-defined context for private data for the function evaluation routine (may be NULL) 1256 1257 Calling sequence of f: 1258 $ PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx); 1259 1260 + t - time at step/stage being solved 1261 . u - state vector 1262 . u_t - time derivative of state vector 1263 . F - function vector 1264 - ctx - [optional] user-defined context for matrix evaluation routine 1265 1266 Important: 1267 The user MUST call either this routine or TSSetRHSFunction() to define the ODE. When solving DAEs you must use this function. 1268 1269 Level: beginner 1270 1271 .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian() 1272 @*/ 1273 PetscErrorCode TSSetIFunction(TS ts,Vec r,TSIFunction f,void *ctx) 1274 { 1275 SNES snes; 1276 Vec ralloc = NULL; 1277 DM dm; 1278 1279 PetscFunctionBegin; 1280 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1281 if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2); 1282 1283 PetscCall(TSGetDM(ts,&dm)); 1284 PetscCall(DMTSSetIFunction(dm,f,ctx)); 1285 1286 PetscCall(TSGetSNES(ts,&snes)); 1287 if (!r && !ts->dm && ts->vec_sol) { 1288 PetscCall(VecDuplicate(ts->vec_sol,&ralloc)); 1289 r = ralloc; 1290 } 1291 PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts)); 1292 PetscCall(VecDestroy(&ralloc)); 1293 PetscFunctionReturn(0); 1294 } 1295 1296 /*@C 1297 TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it. 1298 1299 Not Collective 1300 1301 Input Parameter: 1302 . ts - the TS context 1303 1304 Output Parameters: 1305 + r - vector to hold residual (or NULL) 1306 . func - the function to compute residual (or NULL) 1307 - ctx - the function context (or NULL) 1308 1309 Level: advanced 1310 1311 .seealso: TSSetIFunction(), SNESGetFunction() 1312 @*/ 1313 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx) 1314 { 1315 SNES snes; 1316 DM dm; 1317 1318 PetscFunctionBegin; 1319 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1320 PetscCall(TSGetSNES(ts,&snes)); 1321 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1322 PetscCall(TSGetDM(ts,&dm)); 1323 PetscCall(DMTSGetIFunction(dm,func,ctx)); 1324 PetscFunctionReturn(0); 1325 } 1326 1327 /*@C 1328 TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it. 1329 1330 Not Collective 1331 1332 Input Parameter: 1333 . ts - the TS context 1334 1335 Output Parameters: 1336 + r - vector to hold computed right hand side (or NULL) 1337 . func - the function to compute right hand side (or NULL) 1338 - ctx - the function context (or NULL) 1339 1340 Level: advanced 1341 1342 .seealso: TSSetRHSFunction(), SNESGetFunction() 1343 @*/ 1344 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx) 1345 { 1346 SNES snes; 1347 DM dm; 1348 1349 PetscFunctionBegin; 1350 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1351 PetscCall(TSGetSNES(ts,&snes)); 1352 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1353 PetscCall(TSGetDM(ts,&dm)); 1354 PetscCall(DMTSGetRHSFunction(dm,func,ctx)); 1355 PetscFunctionReturn(0); 1356 } 1357 1358 /*@C 1359 TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function 1360 provided with TSSetIFunction(). 1361 1362 Logically Collective on TS 1363 1364 Input Parameters: 1365 + ts - the TS context obtained from TSCreate() 1366 . Amat - (approximate) Jacobian matrix 1367 . Pmat - matrix used to compute preconditioner (usually the same as Amat) 1368 . f - the Jacobian evaluation routine 1369 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL) 1370 1371 Calling sequence of f: 1372 $ PetscErrorCode f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx); 1373 1374 + t - time at step/stage being solved 1375 . U - state vector 1376 . U_t - time derivative of state vector 1377 . a - shift 1378 . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t 1379 . Pmat - matrix used for constructing preconditioner, usually the same as Amat 1380 - ctx - [optional] user-defined context for matrix evaluation routine 1381 1382 Notes: 1383 The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve. 1384 1385 If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null 1386 space to Amat and the KSP solvers will automatically use that null space as needed during the solution process. 1387 1388 The matrix dF/dU + a*dF/dU_t you provide turns out to be 1389 the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved. 1390 The time integrator internally approximates U_t by W+a*U where the positive "shift" 1391 a and vector W depend on the integration method, step size, and past states. For example with 1392 the backward Euler method a = 1/dt and W = -a*U(previous timestep) so 1393 W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt 1394 1395 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1396 1397 The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f() 1398 You should not assume the values are the same in the next call to f() as you set them in the previous call. 1399 1400 Level: beginner 1401 1402 .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESComputeJacobianDefaultColor(), SNESComputeJacobianDefault(), TSSetRHSFunction() 1403 1404 @*/ 1405 PetscErrorCode TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx) 1406 { 1407 SNES snes; 1408 DM dm; 1409 1410 PetscFunctionBegin; 1411 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1412 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1413 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 1414 if (Amat) PetscCheckSameComm(ts,1,Amat,2); 1415 if (Pmat) PetscCheckSameComm(ts,1,Pmat,3); 1416 1417 PetscCall(TSGetDM(ts,&dm)); 1418 PetscCall(DMTSSetIJacobian(dm,f,ctx)); 1419 1420 PetscCall(TSGetSNES(ts,&snes)); 1421 PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts)); 1422 PetscFunctionReturn(0); 1423 } 1424 1425 /*@ 1426 TSRHSJacobianSetReuse - restore RHS Jacobian before re-evaluating. Without this flag, TS will change the sign and 1427 shift the RHS Jacobian for a finite-time-step implicit solve, in which case the user function will need to recompute 1428 the entire Jacobian. The reuse flag must be set if the evaluation function will assume that the matrix entries have 1429 not been changed by the TS. 1430 1431 Logically Collective 1432 1433 Input Parameters: 1434 + ts - TS context obtained from TSCreate() 1435 - reuse - PETSC_TRUE if the RHS Jacobian 1436 1437 Level: intermediate 1438 1439 .seealso: TSSetRHSJacobian(), TSComputeRHSJacobianConstant() 1440 @*/ 1441 PetscErrorCode TSRHSJacobianSetReuse(TS ts,PetscBool reuse) 1442 { 1443 PetscFunctionBegin; 1444 ts->rhsjacobian.reuse = reuse; 1445 PetscFunctionReturn(0); 1446 } 1447 1448 /*@C 1449 TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved. 1450 1451 Logically Collective on TS 1452 1453 Input Parameters: 1454 + ts - the TS context obtained from TSCreate() 1455 . F - vector to hold the residual (or NULL to have it created internally) 1456 . fun - the function evaluation routine 1457 - ctx - user-defined context for private data for the function evaluation routine (may be NULL) 1458 1459 Calling sequence of fun: 1460 $ PetscErrorCode fun(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,Vec F,ctx); 1461 1462 + t - time at step/stage being solved 1463 . U - state vector 1464 . U_t - time derivative of state vector 1465 . U_tt - second time derivative of state vector 1466 . F - function vector 1467 - ctx - [optional] user-defined context for matrix evaluation routine (may be NULL) 1468 1469 Level: beginner 1470 1471 .seealso: TSSetI2Jacobian(), TSSetIFunction(), TSCreate(), TSSetRHSFunction() 1472 @*/ 1473 PetscErrorCode TSSetI2Function(TS ts,Vec F,TSI2Function fun,void *ctx) 1474 { 1475 DM dm; 1476 1477 PetscFunctionBegin; 1478 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1479 if (F) PetscValidHeaderSpecific(F,VEC_CLASSID,2); 1480 PetscCall(TSSetIFunction(ts,F,NULL,NULL)); 1481 PetscCall(TSGetDM(ts,&dm)); 1482 PetscCall(DMTSSetI2Function(dm,fun,ctx)); 1483 PetscFunctionReturn(0); 1484 } 1485 1486 /*@C 1487 TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it. 1488 1489 Not Collective 1490 1491 Input Parameter: 1492 . ts - the TS context 1493 1494 Output Parameters: 1495 + r - vector to hold residual (or NULL) 1496 . fun - the function to compute residual (or NULL) 1497 - ctx - the function context (or NULL) 1498 1499 Level: advanced 1500 1501 .seealso: TSSetIFunction(), SNESGetFunction(), TSCreate() 1502 @*/ 1503 PetscErrorCode TSGetI2Function(TS ts,Vec *r,TSI2Function *fun,void **ctx) 1504 { 1505 SNES snes; 1506 DM dm; 1507 1508 PetscFunctionBegin; 1509 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1510 PetscCall(TSGetSNES(ts,&snes)); 1511 PetscCall(SNESGetFunction(snes,r,NULL,NULL)); 1512 PetscCall(TSGetDM(ts,&dm)); 1513 PetscCall(DMTSGetI2Function(dm,fun,ctx)); 1514 PetscFunctionReturn(0); 1515 } 1516 1517 /*@C 1518 TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t + a*dF/dU_tt 1519 where F(t,U,U_t,U_tt) is the function you provided with TSSetI2Function(). 1520 1521 Logically Collective on TS 1522 1523 Input Parameters: 1524 + ts - the TS context obtained from TSCreate() 1525 . J - Jacobian matrix 1526 . P - preconditioning matrix for J (may be same as J) 1527 . jac - the Jacobian evaluation routine 1528 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL) 1529 1530 Calling sequence of jac: 1531 $ PetscErrorCode jac(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,PetscReal v,PetscReal a,Mat J,Mat P,void *ctx); 1532 1533 + t - time at step/stage being solved 1534 . U - state vector 1535 . U_t - time derivative of state vector 1536 . U_tt - second time derivative of state vector 1537 . v - shift for U_t 1538 . a - shift for U_tt 1539 . J - Jacobian of G(U) = F(t,U,W+v*U,W'+a*U), equivalent to dF/dU + v*dF/dU_t + a*dF/dU_tt 1540 . P - preconditioning matrix for J, may be same as J 1541 - ctx - [optional] user-defined context for matrix evaluation routine 1542 1543 Notes: 1544 The matrices J and P are exactly the matrices that are used by SNES for the nonlinear solve. 1545 1546 The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be 1547 the Jacobian of G(U) = F(t,U,W+v*U,W'+a*U) where F(t,U,U_t,U_tt) = 0 is the DAE to be solved. 1548 The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U where the positive "shift" 1549 parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states. 1550 1551 Level: beginner 1552 1553 .seealso: TSSetI2Function(), TSGetI2Jacobian() 1554 @*/ 1555 PetscErrorCode TSSetI2Jacobian(TS ts,Mat J,Mat P,TSI2Jacobian jac,void *ctx) 1556 { 1557 DM dm; 1558 1559 PetscFunctionBegin; 1560 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1561 if (J) PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1562 if (P) PetscValidHeaderSpecific(P,MAT_CLASSID,3); 1563 PetscCall(TSSetIJacobian(ts,J,P,NULL,NULL)); 1564 PetscCall(TSGetDM(ts,&dm)); 1565 PetscCall(DMTSSetI2Jacobian(dm,jac,ctx)); 1566 PetscFunctionReturn(0); 1567 } 1568 1569 /*@C 1570 TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep. 1571 1572 Not Collective, but parallel objects are returned if TS is parallel 1573 1574 Input Parameter: 1575 . ts - The TS context obtained from TSCreate() 1576 1577 Output Parameters: 1578 + J - The (approximate) Jacobian of F(t,U,U_t,U_tt) 1579 . P - The matrix from which the preconditioner is constructed, often the same as J 1580 . jac - The function to compute the Jacobian matrices 1581 - ctx - User-defined context for Jacobian evaluation routine 1582 1583 Notes: 1584 You can pass in NULL for any return argument you do not need. 1585 1586 Level: advanced 1587 1588 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber(), TSSetI2Jacobian(), TSGetI2Function(), TSCreate() 1589 1590 @*/ 1591 PetscErrorCode TSGetI2Jacobian(TS ts,Mat *J,Mat *P,TSI2Jacobian *jac,void **ctx) 1592 { 1593 SNES snes; 1594 DM dm; 1595 1596 PetscFunctionBegin; 1597 PetscCall(TSGetSNES(ts,&snes)); 1598 PetscCall(SNESSetUpMatrices(snes)); 1599 PetscCall(SNESGetJacobian(snes,J,P,NULL,NULL)); 1600 PetscCall(TSGetDM(ts,&dm)); 1601 PetscCall(DMTSGetI2Jacobian(dm,jac,ctx)); 1602 PetscFunctionReturn(0); 1603 } 1604 1605 /*@ 1606 TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0 1607 1608 Collective on TS 1609 1610 Input Parameters: 1611 + ts - the TS context 1612 . t - current time 1613 . U - state vector 1614 . V - time derivative of state vector (U_t) 1615 - A - second time derivative of state vector (U_tt) 1616 1617 Output Parameter: 1618 . F - the residual vector 1619 1620 Note: 1621 Most users should not need to explicitly call this routine, as it 1622 is used internally within the nonlinear solvers. 1623 1624 Level: developer 1625 1626 .seealso: TSSetI2Function(), TSGetI2Function() 1627 @*/ 1628 PetscErrorCode TSComputeI2Function(TS ts,PetscReal t,Vec U,Vec V,Vec A,Vec F) 1629 { 1630 DM dm; 1631 TSI2Function I2Function; 1632 void *ctx; 1633 TSRHSFunction rhsfunction; 1634 1635 PetscFunctionBegin; 1636 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1637 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1638 PetscValidHeaderSpecific(V,VEC_CLASSID,4); 1639 PetscValidHeaderSpecific(A,VEC_CLASSID,5); 1640 PetscValidHeaderSpecific(F,VEC_CLASSID,6); 1641 1642 PetscCall(TSGetDM(ts,&dm)); 1643 PetscCall(DMTSGetI2Function(dm,&I2Function,&ctx)); 1644 PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL)); 1645 1646 if (!I2Function) { 1647 PetscCall(TSComputeIFunction(ts,t,U,A,F,PETSC_FALSE)); 1648 PetscFunctionReturn(0); 1649 } 1650 1651 PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,V,F)); 1652 1653 PetscStackPush("TS user implicit function"); 1654 PetscCall(I2Function(ts,t,U,V,A,F,ctx)); 1655 PetscStackPop; 1656 1657 if (rhsfunction) { 1658 Vec Frhs; 1659 PetscCall(TSGetRHSVec_Private(ts,&Frhs)); 1660 PetscCall(TSComputeRHSFunction(ts,t,U,Frhs)); 1661 PetscCall(VecAXPY(F,-1,Frhs)); 1662 } 1663 1664 PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,V,F)); 1665 PetscFunctionReturn(0); 1666 } 1667 1668 /*@ 1669 TSComputeI2Jacobian - Evaluates the Jacobian of the DAE 1670 1671 Collective on TS 1672 1673 Input Parameters: 1674 + ts - the TS context 1675 . t - current timestep 1676 . U - state vector 1677 . V - time derivative of state vector 1678 . A - second time derivative of state vector 1679 . shiftV - shift to apply, see note below 1680 - shiftA - shift to apply, see note below 1681 1682 Output Parameters: 1683 + J - Jacobian matrix 1684 - P - optional preconditioning matrix 1685 1686 Notes: 1687 If F(t,U,V,A)=0 is the DAE, the required Jacobian is 1688 1689 dF/dU + shiftV*dF/dV + shiftA*dF/dA 1690 1691 Most users should not need to explicitly call this routine, as it 1692 is used internally within the nonlinear solvers. 1693 1694 Level: developer 1695 1696 .seealso: TSSetI2Jacobian() 1697 @*/ 1698 PetscErrorCode TSComputeI2Jacobian(TS ts,PetscReal t,Vec U,Vec V,Vec A,PetscReal shiftV,PetscReal shiftA,Mat J,Mat P) 1699 { 1700 DM dm; 1701 TSI2Jacobian I2Jacobian; 1702 void *ctx; 1703 TSRHSJacobian rhsjacobian; 1704 1705 PetscFunctionBegin; 1706 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1707 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1708 PetscValidHeaderSpecific(V,VEC_CLASSID,4); 1709 PetscValidHeaderSpecific(A,VEC_CLASSID,5); 1710 PetscValidHeaderSpecific(J,MAT_CLASSID,8); 1711 PetscValidHeaderSpecific(P,MAT_CLASSID,9); 1712 1713 PetscCall(TSGetDM(ts,&dm)); 1714 PetscCall(DMTSGetI2Jacobian(dm,&I2Jacobian,&ctx)); 1715 PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL)); 1716 1717 if (!I2Jacobian) { 1718 PetscCall(TSComputeIJacobian(ts,t,U,A,shiftA,J,P,PETSC_FALSE)); 1719 PetscFunctionReturn(0); 1720 } 1721 1722 PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,J,P)); 1723 1724 PetscStackPush("TS user implicit Jacobian"); 1725 PetscCall(I2Jacobian(ts,t,U,V,A,shiftV,shiftA,J,P,ctx)); 1726 PetscStackPop; 1727 1728 if (rhsjacobian) { 1729 Mat Jrhs,Prhs; 1730 PetscCall(TSGetRHSMats_Private(ts,&Jrhs,&Prhs)); 1731 PetscCall(TSComputeRHSJacobian(ts,t,U,Jrhs,Prhs)); 1732 PetscCall(MatAXPY(J,-1,Jrhs,ts->axpy_pattern)); 1733 if (P != J) PetscCall(MatAXPY(P,-1,Prhs,ts->axpy_pattern)); 1734 } 1735 1736 PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,J,P)); 1737 PetscFunctionReturn(0); 1738 } 1739 1740 /*@C 1741 TSSetTransientVariable - sets function to transform from state to transient variables 1742 1743 Logically Collective 1744 1745 Input Parameters: 1746 + ts - time stepping context on which to change the transient variable 1747 . tvar - a function that transforms to transient variables 1748 - ctx - a context for tvar 1749 1750 Calling sequence of tvar: 1751 $ PetscErrorCode tvar(TS ts,Vec p,Vec c,void *ctx); 1752 1753 + ts - timestep context 1754 . p - input vector (primative form) 1755 . c - output vector, transient variables (conservative form) 1756 - ctx - [optional] user-defined function context 1757 1758 Level: advanced 1759 1760 Notes: 1761 This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., TSBDF) 1762 can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to 1763 well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is 1764 C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be 1765 evaluated via the chain rule, as in 1766 1767 dF/dP + shift * dF/dCdot dC/dP. 1768 1769 .seealso: DMTSSetTransientVariable(), DMTSGetTransientVariable(), TSSetIFunction(), TSSetIJacobian() 1770 @*/ 1771 PetscErrorCode TSSetTransientVariable(TS ts,TSTransientVariable tvar,void *ctx) 1772 { 1773 DM dm; 1774 1775 PetscFunctionBegin; 1776 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1777 PetscCall(TSGetDM(ts,&dm)); 1778 PetscCall(DMTSSetTransientVariable(dm,tvar,ctx)); 1779 PetscFunctionReturn(0); 1780 } 1781 1782 /*@ 1783 TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables 1784 1785 Logically Collective 1786 1787 Input Parameters: 1788 + ts - TS on which to compute 1789 - U - state vector to be transformed to transient variables 1790 1791 Output Parameters: 1792 . C - transient (conservative) variable 1793 1794 Developer Notes: 1795 If DMTSSetTransientVariable() has not been called, then C is not modified in this routine and C=NULL is allowed. 1796 This makes it safe to call without a guard. One can use TSHasTransientVariable() to check if transient variables are 1797 being used. 1798 1799 Level: developer 1800 1801 .seealso: DMTSSetTransientVariable(), TSComputeIFunction(), TSComputeIJacobian() 1802 @*/ 1803 PetscErrorCode TSComputeTransientVariable(TS ts,Vec U,Vec C) 1804 { 1805 DM dm; 1806 DMTS dmts; 1807 1808 PetscFunctionBegin; 1809 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1810 PetscValidHeaderSpecific(U,VEC_CLASSID,2); 1811 PetscCall(TSGetDM(ts,&dm)); 1812 PetscCall(DMGetDMTS(dm,&dmts)); 1813 if (dmts->ops->transientvar) { 1814 PetscValidHeaderSpecific(C,VEC_CLASSID,3); 1815 PetscCall((*dmts->ops->transientvar)(ts,U,C,dmts->transientvarctx)); 1816 } 1817 PetscFunctionReturn(0); 1818 } 1819 1820 /*@ 1821 TSHasTransientVariable - determine whether transient variables have been set 1822 1823 Logically Collective 1824 1825 Input Parameters: 1826 . ts - TS on which to compute 1827 1828 Output Parameters: 1829 . has - PETSC_TRUE if transient variables have been set 1830 1831 Level: developer 1832 1833 .seealso: DMTSSetTransientVariable(), TSComputeTransientVariable() 1834 @*/ 1835 PetscErrorCode TSHasTransientVariable(TS ts,PetscBool *has) 1836 { 1837 DM dm; 1838 DMTS dmts; 1839 1840 PetscFunctionBegin; 1841 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1842 PetscCall(TSGetDM(ts,&dm)); 1843 PetscCall(DMGetDMTS(dm,&dmts)); 1844 *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE; 1845 PetscFunctionReturn(0); 1846 } 1847 1848 /*@ 1849 TS2SetSolution - Sets the initial solution and time derivative vectors 1850 for use by the TS routines handling second order equations. 1851 1852 Logically Collective on TS 1853 1854 Input Parameters: 1855 + ts - the TS context obtained from TSCreate() 1856 . u - the solution vector 1857 - v - the time derivative vector 1858 1859 Level: beginner 1860 1861 @*/ 1862 PetscErrorCode TS2SetSolution(TS ts,Vec u,Vec v) 1863 { 1864 PetscFunctionBegin; 1865 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1866 PetscValidHeaderSpecific(u,VEC_CLASSID,2); 1867 PetscValidHeaderSpecific(v,VEC_CLASSID,3); 1868 PetscCall(TSSetSolution(ts,u)); 1869 PetscCall(PetscObjectReference((PetscObject)v)); 1870 PetscCall(VecDestroy(&ts->vec_dot)); 1871 ts->vec_dot = v; 1872 PetscFunctionReturn(0); 1873 } 1874 1875 /*@ 1876 TS2GetSolution - Returns the solution and time derivative at the present timestep 1877 for second order equations. It is valid to call this routine inside the function 1878 that you are evaluating in order to move to the new timestep. This vector not 1879 changed until the solution at the next timestep has been calculated. 1880 1881 Not Collective, but Vec returned is parallel if TS is parallel 1882 1883 Input Parameter: 1884 . ts - the TS context obtained from TSCreate() 1885 1886 Output Parameters: 1887 + u - the vector containing the solution 1888 - v - the vector containing the time derivative 1889 1890 Level: intermediate 1891 1892 .seealso: TS2SetSolution(), TSGetTimeStep(), TSGetTime() 1893 1894 @*/ 1895 PetscErrorCode TS2GetSolution(TS ts,Vec *u,Vec *v) 1896 { 1897 PetscFunctionBegin; 1898 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1899 if (u) PetscValidPointer(u,2); 1900 if (v) PetscValidPointer(v,3); 1901 if (u) *u = ts->vec_sol; 1902 if (v) *v = ts->vec_dot; 1903 PetscFunctionReturn(0); 1904 } 1905 1906 /*@C 1907 TSLoad - Loads a KSP that has been stored in binary with KSPView(). 1908 1909 Collective on PetscViewer 1910 1911 Input Parameters: 1912 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or 1913 some related function before a call to TSLoad(). 1914 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() 1915 1916 Level: intermediate 1917 1918 Notes: 1919 The type is determined by the data in the file, any type set into the TS before this call is ignored. 1920 1921 Notes for advanced users: 1922 Most users should not need to know the details of the binary storage 1923 format, since TSLoad() and TSView() completely hide these details. 1924 But for anyone who's interested, the standard binary matrix storage 1925 format is 1926 .vb 1927 has not yet been determined 1928 .ve 1929 1930 .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad() 1931 @*/ 1932 PetscErrorCode TSLoad(TS ts, PetscViewer viewer) 1933 { 1934 PetscBool isbinary; 1935 PetscInt classid; 1936 char type[256]; 1937 DMTS sdm; 1938 DM dm; 1939 1940 PetscFunctionBegin; 1941 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1942 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1943 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 1944 PetscCheck(isbinary,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1945 1946 PetscCall(PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT)); 1947 PetscCheck(classid == TS_FILE_CLASSID,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file"); 1948 PetscCall(PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR)); 1949 PetscCall(TSSetType(ts, type)); 1950 if (ts->ops->load) { 1951 PetscCall((*ts->ops->load)(ts,viewer)); 1952 } 1953 PetscCall(DMCreate(PetscObjectComm((PetscObject)ts),&dm)); 1954 PetscCall(DMLoad(dm,viewer)); 1955 PetscCall(TSSetDM(ts,dm)); 1956 PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol)); 1957 PetscCall(VecLoad(ts->vec_sol,viewer)); 1958 PetscCall(DMGetDMTS(ts->dm,&sdm)); 1959 PetscCall(DMTSLoad(sdm,viewer)); 1960 PetscFunctionReturn(0); 1961 } 1962 1963 #include <petscdraw.h> 1964 #if defined(PETSC_HAVE_SAWS) 1965 #include <petscviewersaws.h> 1966 #endif 1967 1968 /*@C 1969 TSViewFromOptions - View from Options 1970 1971 Collective on TS 1972 1973 Input Parameters: 1974 + A - the application ordering context 1975 . obj - Optional object 1976 - name - command line option 1977 1978 Level: intermediate 1979 .seealso: TS, TSView, PetscObjectViewFromOptions(), TSCreate() 1980 @*/ 1981 PetscErrorCode TSViewFromOptions(TS A,PetscObject obj,const char name[]) 1982 { 1983 PetscFunctionBegin; 1984 PetscValidHeaderSpecific(A,TS_CLASSID,1); 1985 PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 1986 PetscFunctionReturn(0); 1987 } 1988 1989 /*@C 1990 TSView - Prints the TS data structure. 1991 1992 Collective on TS 1993 1994 Input Parameters: 1995 + ts - the TS context obtained from TSCreate() 1996 - viewer - visualization context 1997 1998 Options Database Key: 1999 . -ts_view - calls TSView() at end of TSStep() 2000 2001 Notes: 2002 The available visualization contexts include 2003 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 2004 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 2005 output where only the first processor opens 2006 the file. All other processors send their 2007 data to the first processor to print. 2008 2009 The user can open an alternative visualization context with 2010 PetscViewerASCIIOpen() - output to a specified file. 2011 2012 In the debugger you can do "call TSView(ts,0)" to display the TS solver. (The same holds for any PETSc object viewer). 2013 2014 Level: beginner 2015 2016 .seealso: PetscViewerASCIIOpen() 2017 @*/ 2018 PetscErrorCode TSView(TS ts,PetscViewer viewer) 2019 { 2020 TSType type; 2021 PetscBool iascii,isstring,isundials,isbinary,isdraw; 2022 DMTS sdm; 2023 #if defined(PETSC_HAVE_SAWS) 2024 PetscBool issaws; 2025 #endif 2026 2027 PetscFunctionBegin; 2028 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2029 if (!viewer) { 2030 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer)); 2031 } 2032 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2033 PetscCheckSameComm(ts,1,viewer,2); 2034 2035 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 2036 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring)); 2037 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 2038 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw)); 2039 #if defined(PETSC_HAVE_SAWS) 2040 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws)); 2041 #endif 2042 if (iascii) { 2043 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer)); 2044 if (ts->ops->view) { 2045 PetscCall(PetscViewerASCIIPushTab(viewer)); 2046 PetscCall((*ts->ops->view)(ts,viewer)); 2047 PetscCall(PetscViewerASCIIPopTab(viewer)); 2048 } 2049 if (ts->max_steps < PETSC_MAX_INT) { 2050 PetscCall(PetscViewerASCIIPrintf(viewer," maximum steps=%D\n",ts->max_steps)); 2051 } 2052 if (ts->max_time < PETSC_MAX_REAL) { 2053 PetscCall(PetscViewerASCIIPrintf(viewer," maximum time=%g\n",(double)ts->max_time)); 2054 } 2055 if (ts->ifuncs) { 2056 PetscCall(PetscViewerASCIIPrintf(viewer," total number of I function evaluations=%D\n",ts->ifuncs)); 2057 } 2058 if (ts->ijacs) { 2059 PetscCall(PetscViewerASCIIPrintf(viewer," total number of I Jacobian evaluations=%D\n",ts->ijacs)); 2060 } 2061 if (ts->rhsfuncs) { 2062 PetscCall(PetscViewerASCIIPrintf(viewer," total number of RHS function evaluations=%D\n",ts->rhsfuncs)); 2063 } 2064 if (ts->rhsjacs) { 2065 PetscCall(PetscViewerASCIIPrintf(viewer," total number of RHS Jacobian evaluations=%D\n",ts->rhsjacs)); 2066 } 2067 if (ts->usessnes) { 2068 PetscBool lin; 2069 if (ts->problem_type == TS_NONLINEAR) { 2070 PetscCall(PetscViewerASCIIPrintf(viewer," total number of nonlinear solver iterations=%D\n",ts->snes_its)); 2071 } 2072 PetscCall(PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",ts->ksp_its)); 2073 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&lin,SNESKSPONLY,SNESKSPTRANSPOSEONLY,"")); 2074 PetscCall(PetscViewerASCIIPrintf(viewer," total number of %slinear solve failures=%D\n",lin ? "" : "non",ts->num_snes_failures)); 2075 } 2076 PetscCall(PetscViewerASCIIPrintf(viewer," total number of rejected steps=%D\n",ts->reject)); 2077 if (ts->vrtol) { 2078 PetscCall(PetscViewerASCIIPrintf(viewer," using vector of relative error tolerances, ")); 2079 } else { 2080 PetscCall(PetscViewerASCIIPrintf(viewer," using relative error tolerance of %g, ",(double)ts->rtol)); 2081 } 2082 if (ts->vatol) { 2083 PetscCall(PetscViewerASCIIPrintf(viewer," using vector of absolute error tolerances\n")); 2084 } else { 2085 PetscCall(PetscViewerASCIIPrintf(viewer," using absolute error tolerance of %g\n",(double)ts->atol)); 2086 } 2087 PetscCall(PetscViewerASCIIPushTab(viewer)); 2088 PetscCall(TSAdaptView(ts->adapt,viewer)); 2089 PetscCall(PetscViewerASCIIPopTab(viewer)); 2090 } else if (isstring) { 2091 PetscCall(TSGetType(ts,&type)); 2092 PetscCall(PetscViewerStringSPrintf(viewer," TSType: %-7.7s",type)); 2093 if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer)); 2094 } else if (isbinary) { 2095 PetscInt classid = TS_FILE_CLASSID; 2096 MPI_Comm comm; 2097 PetscMPIInt rank; 2098 char type[256]; 2099 2100 PetscCall(PetscObjectGetComm((PetscObject)ts,&comm)); 2101 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 2102 if (rank == 0) { 2103 PetscCall(PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT)); 2104 PetscCall(PetscStrncpy(type,((PetscObject)ts)->type_name,256)); 2105 PetscCall(PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR)); 2106 } 2107 if (ts->ops->view) { 2108 PetscCall((*ts->ops->view)(ts,viewer)); 2109 } 2110 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer)); 2111 PetscCall(DMView(ts->dm,viewer)); 2112 PetscCall(VecView(ts->vec_sol,viewer)); 2113 PetscCall(DMGetDMTS(ts->dm,&sdm)); 2114 PetscCall(DMTSView(sdm,viewer)); 2115 } else if (isdraw) { 2116 PetscDraw draw; 2117 char str[36]; 2118 PetscReal x,y,bottom,h; 2119 2120 PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw)); 2121 PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y)); 2122 PetscCall(PetscStrcpy(str,"TS: ")); 2123 PetscCall(PetscStrcat(str,((PetscObject)ts)->type_name)); 2124 PetscCall(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h)); 2125 bottom = y - h; 2126 PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom)); 2127 if (ts->ops->view) { 2128 PetscCall((*ts->ops->view)(ts,viewer)); 2129 } 2130 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer)); 2131 if (ts->snes) PetscCall(SNESView(ts->snes,viewer)); 2132 PetscCall(PetscDrawPopCurrentPoint(draw)); 2133 #if defined(PETSC_HAVE_SAWS) 2134 } else if (issaws) { 2135 PetscMPIInt rank; 2136 const char *name; 2137 2138 PetscCall(PetscObjectGetName((PetscObject)ts,&name)); 2139 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 2140 if (!((PetscObject)ts)->amsmem && rank == 0) { 2141 char dir[1024]; 2142 2143 PetscCall(PetscObjectViewSAWs((PetscObject)ts,viewer)); 2144 PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name)); 2145 PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT)); 2146 PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name)); 2147 PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE)); 2148 } 2149 if (ts->ops->view) { 2150 PetscCall((*ts->ops->view)(ts,viewer)); 2151 } 2152 #endif 2153 } 2154 if (ts->snes && ts->usessnes) { 2155 PetscCall(PetscViewerASCIIPushTab(viewer)); 2156 PetscCall(SNESView(ts->snes,viewer)); 2157 PetscCall(PetscViewerASCIIPopTab(viewer)); 2158 } 2159 PetscCall(DMGetDMTS(ts->dm,&sdm)); 2160 PetscCall(DMTSView(sdm,viewer)); 2161 2162 PetscCall(PetscViewerASCIIPushTab(viewer)); 2163 PetscCall(PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials)); 2164 PetscCall(PetscViewerASCIIPopTab(viewer)); 2165 PetscFunctionReturn(0); 2166 } 2167 2168 /*@ 2169 TSSetApplicationContext - Sets an optional user-defined context for 2170 the timesteppers. 2171 2172 Logically Collective on TS 2173 2174 Input Parameters: 2175 + ts - the TS context obtained from TSCreate() 2176 - usrP - optional user context 2177 2178 Fortran Notes: 2179 To use this from Fortran you must write a Fortran interface definition for this 2180 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 2181 2182 Level: intermediate 2183 2184 .seealso: TSGetApplicationContext() 2185 @*/ 2186 PetscErrorCode TSSetApplicationContext(TS ts,void *usrP) 2187 { 2188 PetscFunctionBegin; 2189 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2190 ts->user = usrP; 2191 PetscFunctionReturn(0); 2192 } 2193 2194 /*@ 2195 TSGetApplicationContext - Gets the user-defined context for the 2196 timestepper. 2197 2198 Not Collective 2199 2200 Input Parameter: 2201 . ts - the TS context obtained from TSCreate() 2202 2203 Output Parameter: 2204 . usrP - user context 2205 2206 Fortran Notes: 2207 To use this from Fortran you must write a Fortran interface definition for this 2208 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 2209 2210 Level: intermediate 2211 2212 .seealso: TSSetApplicationContext() 2213 @*/ 2214 PetscErrorCode TSGetApplicationContext(TS ts,void *usrP) 2215 { 2216 PetscFunctionBegin; 2217 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2218 *(void**)usrP = ts->user; 2219 PetscFunctionReturn(0); 2220 } 2221 2222 /*@ 2223 TSGetStepNumber - Gets the number of steps completed. 2224 2225 Not Collective 2226 2227 Input Parameter: 2228 . ts - the TS context obtained from TSCreate() 2229 2230 Output Parameter: 2231 . steps - number of steps completed so far 2232 2233 Level: intermediate 2234 2235 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSSetPostStep() 2236 @*/ 2237 PetscErrorCode TSGetStepNumber(TS ts,PetscInt *steps) 2238 { 2239 PetscFunctionBegin; 2240 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2241 PetscValidIntPointer(steps,2); 2242 *steps = ts->steps; 2243 PetscFunctionReturn(0); 2244 } 2245 2246 /*@ 2247 TSSetStepNumber - Sets the number of steps completed. 2248 2249 Logically Collective on TS 2250 2251 Input Parameters: 2252 + ts - the TS context 2253 - steps - number of steps completed so far 2254 2255 Notes: 2256 For most uses of the TS solvers the user need not explicitly call 2257 TSSetStepNumber(), as the step counter is appropriately updated in 2258 TSSolve()/TSStep()/TSRollBack(). Power users may call this routine to 2259 reinitialize timestepping by setting the step counter to zero (and time 2260 to the initial time) to solve a similar problem with different initial 2261 conditions or parameters. Other possible use case is to continue 2262 timestepping from a previously interrupted run in such a way that TS 2263 monitors will be called with a initial nonzero step counter. 2264 2265 Level: advanced 2266 2267 .seealso: TSGetStepNumber(), TSSetTime(), TSSetTimeStep(), TSSetSolution() 2268 @*/ 2269 PetscErrorCode TSSetStepNumber(TS ts,PetscInt steps) 2270 { 2271 PetscFunctionBegin; 2272 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2273 PetscValidLogicalCollectiveInt(ts,steps,2); 2274 PetscCheck(steps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Step number must be non-negative"); 2275 ts->steps = steps; 2276 PetscFunctionReturn(0); 2277 } 2278 2279 /*@ 2280 TSSetTimeStep - Allows one to reset the timestep at any time, 2281 useful for simple pseudo-timestepping codes. 2282 2283 Logically Collective on TS 2284 2285 Input Parameters: 2286 + ts - the TS context obtained from TSCreate() 2287 - time_step - the size of the timestep 2288 2289 Level: intermediate 2290 2291 .seealso: TSGetTimeStep(), TSSetTime() 2292 2293 @*/ 2294 PetscErrorCode TSSetTimeStep(TS ts,PetscReal time_step) 2295 { 2296 PetscFunctionBegin; 2297 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2298 PetscValidLogicalCollectiveReal(ts,time_step,2); 2299 ts->time_step = time_step; 2300 PetscFunctionReturn(0); 2301 } 2302 2303 /*@ 2304 TSSetExactFinalTime - Determines whether to adapt the final time step to 2305 match the exact final time, interpolate solution to the exact final time, 2306 or just return at the final time TS computed. 2307 2308 Logically Collective on TS 2309 2310 Input Parameters: 2311 + ts - the time-step context 2312 - eftopt - exact final time option 2313 2314 $ TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded 2315 $ TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time 2316 $ TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time 2317 2318 Options Database: 2319 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime 2320 2321 Warning: If you use the option TS_EXACTFINALTIME_STEPOVER the solution may be at a very different time 2322 then the final time you selected. 2323 2324 Level: beginner 2325 2326 .seealso: TSExactFinalTimeOption, TSGetExactFinalTime() 2327 @*/ 2328 PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt) 2329 { 2330 PetscFunctionBegin; 2331 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2332 PetscValidLogicalCollectiveEnum(ts,eftopt,2); 2333 ts->exact_final_time = eftopt; 2334 PetscFunctionReturn(0); 2335 } 2336 2337 /*@ 2338 TSGetExactFinalTime - Gets the exact final time option. 2339 2340 Not Collective 2341 2342 Input Parameter: 2343 . ts - the TS context 2344 2345 Output Parameter: 2346 . eftopt - exact final time option 2347 2348 Level: beginner 2349 2350 .seealso: TSExactFinalTimeOption, TSSetExactFinalTime() 2351 @*/ 2352 PetscErrorCode TSGetExactFinalTime(TS ts,TSExactFinalTimeOption *eftopt) 2353 { 2354 PetscFunctionBegin; 2355 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2356 PetscValidPointer(eftopt,2); 2357 *eftopt = ts->exact_final_time; 2358 PetscFunctionReturn(0); 2359 } 2360 2361 /*@ 2362 TSGetTimeStep - Gets the current timestep size. 2363 2364 Not Collective 2365 2366 Input Parameter: 2367 . ts - the TS context obtained from TSCreate() 2368 2369 Output Parameter: 2370 . dt - the current timestep size 2371 2372 Level: intermediate 2373 2374 .seealso: TSSetTimeStep(), TSGetTime() 2375 2376 @*/ 2377 PetscErrorCode TSGetTimeStep(TS ts,PetscReal *dt) 2378 { 2379 PetscFunctionBegin; 2380 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2381 PetscValidRealPointer(dt,2); 2382 *dt = ts->time_step; 2383 PetscFunctionReturn(0); 2384 } 2385 2386 /*@ 2387 TSGetSolution - Returns the solution at the present timestep. It 2388 is valid to call this routine inside the function that you are evaluating 2389 in order to move to the new timestep. This vector not changed until 2390 the solution at the next timestep has been calculated. 2391 2392 Not Collective, but Vec returned is parallel if TS is parallel 2393 2394 Input Parameter: 2395 . ts - the TS context obtained from TSCreate() 2396 2397 Output Parameter: 2398 . v - the vector containing the solution 2399 2400 Note: If you used TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); this does not return the solution at the requested 2401 final time. It returns the solution at the next timestep. 2402 2403 Level: intermediate 2404 2405 .seealso: TSGetTimeStep(), TSGetTime(), TSGetSolveTime(), TSGetSolutionComponents(), TSSetSolutionFunction() 2406 2407 @*/ 2408 PetscErrorCode TSGetSolution(TS ts,Vec *v) 2409 { 2410 PetscFunctionBegin; 2411 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2412 PetscValidPointer(v,2); 2413 *v = ts->vec_sol; 2414 PetscFunctionReturn(0); 2415 } 2416 2417 /*@ 2418 TSGetSolutionComponents - Returns any solution components at the present 2419 timestep, if available for the time integration method being used. 2420 Solution components are quantities that share the same size and 2421 structure as the solution vector. 2422 2423 Not Collective, but Vec returned is parallel if TS is parallel 2424 2425 Parameters : 2426 + ts - the TS context obtained from TSCreate() (input parameter). 2427 . n - If v is PETSC_NULL, then the number of solution components is 2428 returned through n, else the n-th solution component is 2429 returned in v. 2430 - v - the vector containing the n-th solution component 2431 (may be PETSC_NULL to use this function to find out 2432 the number of solutions components). 2433 2434 Level: advanced 2435 2436 .seealso: TSGetSolution() 2437 2438 @*/ 2439 PetscErrorCode TSGetSolutionComponents(TS ts,PetscInt *n,Vec *v) 2440 { 2441 PetscFunctionBegin; 2442 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2443 if (!ts->ops->getsolutioncomponents) *n = 0; 2444 else { 2445 PetscCall((*ts->ops->getsolutioncomponents)(ts,n,v)); 2446 } 2447 PetscFunctionReturn(0); 2448 } 2449 2450 /*@ 2451 TSGetAuxSolution - Returns an auxiliary solution at the present 2452 timestep, if available for the time integration method being used. 2453 2454 Not Collective, but Vec returned is parallel if TS is parallel 2455 2456 Parameters : 2457 + ts - the TS context obtained from TSCreate() (input parameter). 2458 - v - the vector containing the auxiliary solution 2459 2460 Level: intermediate 2461 2462 .seealso: TSGetSolution() 2463 2464 @*/ 2465 PetscErrorCode TSGetAuxSolution(TS ts,Vec *v) 2466 { 2467 PetscFunctionBegin; 2468 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2469 if (ts->ops->getauxsolution) { 2470 PetscCall((*ts->ops->getauxsolution)(ts,v)); 2471 } else { 2472 PetscCall(VecZeroEntries(*v)); 2473 } 2474 PetscFunctionReturn(0); 2475 } 2476 2477 /*@ 2478 TSGetTimeError - Returns the estimated error vector, if the chosen 2479 TSType has an error estimation functionality. 2480 2481 Not Collective, but Vec returned is parallel if TS is parallel 2482 2483 Note: MUST call after TSSetUp() 2484 2485 Parameters : 2486 + ts - the TS context obtained from TSCreate() (input parameter). 2487 . n - current estimate (n=0) or previous one (n=-1) 2488 - v - the vector containing the error (same size as the solution). 2489 2490 Level: intermediate 2491 2492 .seealso: TSGetSolution(), TSSetTimeError() 2493 2494 @*/ 2495 PetscErrorCode TSGetTimeError(TS ts,PetscInt n,Vec *v) 2496 { 2497 PetscFunctionBegin; 2498 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2499 if (ts->ops->gettimeerror) { 2500 PetscCall((*ts->ops->gettimeerror)(ts,n,v)); 2501 } else { 2502 PetscCall(VecZeroEntries(*v)); 2503 } 2504 PetscFunctionReturn(0); 2505 } 2506 2507 /*@ 2508 TSSetTimeError - Sets the estimated error vector, if the chosen 2509 TSType has an error estimation functionality. This can be used 2510 to restart such a time integrator with a given error vector. 2511 2512 Not Collective, but Vec returned is parallel if TS is parallel 2513 2514 Parameters : 2515 + ts - the TS context obtained from TSCreate() (input parameter). 2516 - v - the vector containing the error (same size as the solution). 2517 2518 Level: intermediate 2519 2520 .seealso: TSSetSolution(), TSGetTimeError) 2521 2522 @*/ 2523 PetscErrorCode TSSetTimeError(TS ts,Vec v) 2524 { 2525 PetscFunctionBegin; 2526 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2527 PetscCheck(ts->setupcalled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetUp() first"); 2528 if (ts->ops->settimeerror) { 2529 PetscCall((*ts->ops->settimeerror)(ts,v)); 2530 } 2531 PetscFunctionReturn(0); 2532 } 2533 2534 /* ----- Routines to initialize and destroy a timestepper ---- */ 2535 /*@ 2536 TSSetProblemType - Sets the type of problem to be solved. 2537 2538 Not collective 2539 2540 Input Parameters: 2541 + ts - The TS 2542 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms 2543 .vb 2544 U_t - A U = 0 (linear) 2545 U_t - A(t) U = 0 (linear) 2546 F(t,U,U_t) = 0 (nonlinear) 2547 .ve 2548 2549 Level: beginner 2550 2551 .seealso: TSSetUp(), TSProblemType, TS 2552 @*/ 2553 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2554 { 2555 PetscFunctionBegin; 2556 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2557 ts->problem_type = type; 2558 if (type == TS_LINEAR) { 2559 SNES snes; 2560 PetscCall(TSGetSNES(ts,&snes)); 2561 PetscCall(SNESSetType(snes,SNESKSPONLY)); 2562 } 2563 PetscFunctionReturn(0); 2564 } 2565 2566 /*@C 2567 TSGetProblemType - Gets the type of problem to be solved. 2568 2569 Not collective 2570 2571 Input Parameter: 2572 . ts - The TS 2573 2574 Output Parameter: 2575 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms 2576 .vb 2577 M U_t = A U 2578 M(t) U_t = A(t) U 2579 F(t,U,U_t) 2580 .ve 2581 2582 Level: beginner 2583 2584 .seealso: TSSetUp(), TSProblemType, TS 2585 @*/ 2586 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2587 { 2588 PetscFunctionBegin; 2589 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2590 PetscValidIntPointer(type,2); 2591 *type = ts->problem_type; 2592 PetscFunctionReturn(0); 2593 } 2594 2595 /* 2596 Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp() 2597 */ 2598 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts) 2599 { 2600 PetscBool isnone; 2601 2602 PetscFunctionBegin; 2603 PetscCall(TSGetAdapt(ts,&ts->adapt)); 2604 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 2605 2606 PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone)); 2607 if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) { 2608 ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 2609 } else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) { 2610 ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE; 2611 } 2612 PetscFunctionReturn(0); 2613 } 2614 2615 /*@ 2616 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2617 2618 Collective on TS 2619 2620 Input Parameter: 2621 . ts - the TS context obtained from TSCreate() 2622 2623 Notes: 2624 For basic use of the TS solvers the user need not explicitly call 2625 TSSetUp(), since these actions will automatically occur during 2626 the call to TSStep() or TSSolve(). However, if one wishes to control this 2627 phase separately, TSSetUp() should be called after TSCreate() 2628 and optional routines of the form TSSetXXX(), but before TSStep() and TSSolve(). 2629 2630 Level: advanced 2631 2632 .seealso: TSCreate(), TSStep(), TSDestroy(), TSSolve() 2633 @*/ 2634 PetscErrorCode TSSetUp(TS ts) 2635 { 2636 DM dm; 2637 PetscErrorCode (*func)(SNES,Vec,Vec,void*); 2638 PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*); 2639 TSIFunction ifun; 2640 TSIJacobian ijac; 2641 TSI2Jacobian i2jac; 2642 TSRHSJacobian rhsjac; 2643 2644 PetscFunctionBegin; 2645 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2646 if (ts->setupcalled) PetscFunctionReturn(0); 2647 2648 if (!((PetscObject)ts)->type_name) { 2649 PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL)); 2650 PetscCall(TSSetType(ts,ifun ? TSBEULER : TSEULER)); 2651 } 2652 2653 if (!ts->vec_sol) { 2654 if (ts->dm) { 2655 PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol)); 2656 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first"); 2657 } 2658 2659 if (ts->tspan) { 2660 if (!ts->tspan->vecs_sol) { 2661 PetscCall(VecDuplicateVecs(ts->vec_sol,ts->tspan->num_span_times,&ts->tspan->vecs_sol)); 2662 } 2663 } 2664 if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */ 2665 PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs)); 2666 ts->Jacp = ts->Jacprhs; 2667 } 2668 2669 if (ts->quadraturets) { 2670 PetscCall(TSSetUp(ts->quadraturets)); 2671 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2672 PetscCall(VecDuplicate(ts->quadraturets->vec_sol,&ts->vec_costintegrand)); 2673 } 2674 2675 PetscCall(TSGetRHSJacobian(ts,NULL,NULL,&rhsjac,NULL)); 2676 if (rhsjac == TSComputeRHSJacobianConstant) { 2677 Mat Amat,Pmat; 2678 SNES snes; 2679 PetscCall(TSGetSNES(ts,&snes)); 2680 PetscCall(SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL)); 2681 /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would 2682 * have displaced the RHS matrix */ 2683 if (Amat && Amat == ts->Arhs) { 2684 /* we need to copy the values of the matrix because for the constant Jacobian case the user will never set the numerical values in this new location */ 2685 PetscCall(MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat)); 2686 PetscCall(SNESSetJacobian(snes,Amat,NULL,NULL,NULL)); 2687 PetscCall(MatDestroy(&Amat)); 2688 } 2689 if (Pmat && Pmat == ts->Brhs) { 2690 PetscCall(MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat)); 2691 PetscCall(SNESSetJacobian(snes,NULL,Pmat,NULL,NULL)); 2692 PetscCall(MatDestroy(&Pmat)); 2693 } 2694 } 2695 2696 PetscCall(TSGetAdapt(ts,&ts->adapt)); 2697 PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type)); 2698 2699 if (ts->ops->setup) { 2700 PetscCall((*ts->ops->setup)(ts)); 2701 } 2702 2703 PetscCall(TSSetExactFinalTimeDefault(ts)); 2704 2705 /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction 2706 to be set right but can't do it elsewhere due to the overreliance on ctx=ts. 2707 */ 2708 PetscCall(TSGetDM(ts,&dm)); 2709 PetscCall(DMSNESGetFunction(dm,&func,NULL)); 2710 if (!func) { 2711 PetscCall(DMSNESSetFunction(dm,SNESTSFormFunction,ts)); 2712 } 2713 /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it. 2714 Otherwise, the SNES will use coloring internally to form the Jacobian. 2715 */ 2716 PetscCall(DMSNESGetJacobian(dm,&jac,NULL)); 2717 PetscCall(DMTSGetIJacobian(dm,&ijac,NULL)); 2718 PetscCall(DMTSGetI2Jacobian(dm,&i2jac,NULL)); 2719 PetscCall(DMTSGetRHSJacobian(dm,&rhsjac,NULL)); 2720 if (!jac && (ijac || i2jac || rhsjac)) { 2721 PetscCall(DMSNESSetJacobian(dm,SNESTSFormJacobian,ts)); 2722 } 2723 2724 /* if time integration scheme has a starting method, call it */ 2725 if (ts->ops->startingmethod) { 2726 PetscCall((*ts->ops->startingmethod)(ts)); 2727 } 2728 2729 ts->setupcalled = PETSC_TRUE; 2730 PetscFunctionReturn(0); 2731 } 2732 2733 /*@ 2734 TSReset - Resets a TS context and removes any allocated Vecs and Mats. 2735 2736 Collective on TS 2737 2738 Input Parameter: 2739 . ts - the TS context obtained from TSCreate() 2740 2741 Level: beginner 2742 2743 .seealso: TSCreate(), TSSetup(), TSDestroy() 2744 @*/ 2745 PetscErrorCode TSReset(TS ts) 2746 { 2747 TS_RHSSplitLink ilink = ts->tsrhssplit,next; 2748 2749 PetscFunctionBegin; 2750 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2751 2752 if (ts->ops->reset) { 2753 PetscCall((*ts->ops->reset)(ts)); 2754 } 2755 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2756 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2757 2758 PetscCall(MatDestroy(&ts->Arhs)); 2759 PetscCall(MatDestroy(&ts->Brhs)); 2760 PetscCall(VecDestroy(&ts->Frhs)); 2761 PetscCall(VecDestroy(&ts->vec_sol)); 2762 PetscCall(VecDestroy(&ts->vec_dot)); 2763 PetscCall(VecDestroy(&ts->vatol)); 2764 PetscCall(VecDestroy(&ts->vrtol)); 2765 PetscCall(VecDestroyVecs(ts->nwork,&ts->work)); 2766 2767 PetscCall(MatDestroy(&ts->Jacprhs)); 2768 PetscCall(MatDestroy(&ts->Jacp)); 2769 if (ts->forward_solve) { 2770 PetscCall(TSForwardReset(ts)); 2771 } 2772 if (ts->quadraturets) { 2773 PetscCall(TSReset(ts->quadraturets)); 2774 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2775 } 2776 while (ilink) { 2777 next = ilink->next; 2778 PetscCall(TSDestroy(&ilink->ts)); 2779 PetscCall(PetscFree(ilink->splitname)); 2780 PetscCall(ISDestroy(&ilink->is)); 2781 PetscCall(PetscFree(ilink)); 2782 ilink = next; 2783 } 2784 ts->tsrhssplit = NULL; 2785 ts->num_rhs_splits = 0; 2786 if (ts->tspan) { 2787 PetscCall(PetscFree(ts->tspan->span_times)); 2788 PetscCall(VecDestroyVecs(ts->tspan->num_span_times,&ts->tspan->vecs_sol)); 2789 PetscCall(PetscFree(ts->tspan)); 2790 } 2791 ts->setupcalled = PETSC_FALSE; 2792 PetscFunctionReturn(0); 2793 } 2794 2795 /*@C 2796 TSDestroy - Destroys the timestepper context that was created 2797 with TSCreate(). 2798 2799 Collective on TS 2800 2801 Input Parameter: 2802 . ts - the TS context obtained from TSCreate() 2803 2804 Level: beginner 2805 2806 .seealso: TSCreate(), TSSetUp(), TSSolve() 2807 @*/ 2808 PetscErrorCode TSDestroy(TS *ts) 2809 { 2810 PetscFunctionBegin; 2811 if (!*ts) PetscFunctionReturn(0); 2812 PetscValidHeaderSpecific(*ts,TS_CLASSID,1); 2813 if (--((PetscObject)(*ts))->refct > 0) {*ts = NULL; PetscFunctionReturn(0);} 2814 2815 PetscCall(TSReset(*ts)); 2816 PetscCall(TSAdjointReset(*ts)); 2817 if ((*ts)->forward_solve) { 2818 PetscCall(TSForwardReset(*ts)); 2819 } 2820 /* if memory was published with SAWs then destroy it */ 2821 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2822 if ((*ts)->ops->destroy) PetscCall((*(*ts)->ops->destroy)((*ts))); 2823 2824 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2825 2826 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2827 PetscCall(TSEventDestroy(&(*ts)->event)); 2828 2829 PetscCall(SNESDestroy(&(*ts)->snes)); 2830 PetscCall(DMDestroy(&(*ts)->dm)); 2831 PetscCall(TSMonitorCancel((*ts))); 2832 PetscCall(TSAdjointMonitorCancel((*ts))); 2833 2834 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2835 PetscCall(PetscHeaderDestroy(ts)); 2836 PetscFunctionReturn(0); 2837 } 2838 2839 /*@ 2840 TSGetSNES - Returns the SNES (nonlinear solver) associated with 2841 a TS (timestepper) context. Valid only for nonlinear problems. 2842 2843 Not Collective, but SNES is parallel if TS is parallel 2844 2845 Input Parameter: 2846 . ts - the TS context obtained from TSCreate() 2847 2848 Output Parameter: 2849 . snes - the nonlinear solver context 2850 2851 Notes: 2852 The user can then directly manipulate the SNES context to set various 2853 options, etc. Likewise, the user can then extract and manipulate the 2854 KSP, KSP, and PC contexts as well. 2855 2856 TSGetSNES() does not work for integrators that do not use SNES; in 2857 this case TSGetSNES() returns NULL in snes. 2858 2859 Level: beginner 2860 2861 @*/ 2862 PetscErrorCode TSGetSNES(TS ts,SNES *snes) 2863 { 2864 PetscFunctionBegin; 2865 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2866 PetscValidPointer(snes,2); 2867 if (!ts->snes) { 2868 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes)); 2869 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes,((PetscObject)ts)->options)); 2870 PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts)); 2871 PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes)); 2872 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1)); 2873 if (ts->dm) PetscCall(SNESSetDM(ts->snes,ts->dm)); 2874 if (ts->problem_type == TS_LINEAR) { 2875 PetscCall(SNESSetType(ts->snes,SNESKSPONLY)); 2876 } 2877 } 2878 *snes = ts->snes; 2879 PetscFunctionReturn(0); 2880 } 2881 2882 /*@ 2883 TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context 2884 2885 Collective 2886 2887 Input Parameters: 2888 + ts - the TS context obtained from TSCreate() 2889 - snes - the nonlinear solver context 2890 2891 Notes: 2892 Most users should have the TS created by calling TSGetSNES() 2893 2894 Level: developer 2895 2896 @*/ 2897 PetscErrorCode TSSetSNES(TS ts,SNES snes) 2898 { 2899 PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*); 2900 2901 PetscFunctionBegin; 2902 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2903 PetscValidHeaderSpecific(snes,SNES_CLASSID,2); 2904 PetscCall(PetscObjectReference((PetscObject)snes)); 2905 PetscCall(SNESDestroy(&ts->snes)); 2906 2907 ts->snes = snes; 2908 2909 PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts)); 2910 PetscCall(SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL)); 2911 if (func == SNESTSFormJacobian) { 2912 PetscCall(SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts)); 2913 } 2914 PetscFunctionReturn(0); 2915 } 2916 2917 /*@ 2918 TSGetKSP - Returns the KSP (linear solver) associated with 2919 a TS (timestepper) context. 2920 2921 Not Collective, but KSP is parallel if TS is parallel 2922 2923 Input Parameter: 2924 . ts - the TS context obtained from TSCreate() 2925 2926 Output Parameter: 2927 . ksp - the nonlinear solver context 2928 2929 Notes: 2930 The user can then directly manipulate the KSP context to set various 2931 options, etc. Likewise, the user can then extract and manipulate the 2932 KSP and PC contexts as well. 2933 2934 TSGetKSP() does not work for integrators that do not use KSP; 2935 in this case TSGetKSP() returns NULL in ksp. 2936 2937 Level: beginner 2938 2939 @*/ 2940 PetscErrorCode TSGetKSP(TS ts,KSP *ksp) 2941 { 2942 SNES snes; 2943 2944 PetscFunctionBegin; 2945 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2946 PetscValidPointer(ksp,2); 2947 PetscCheck(((PetscObject)ts)->type_name,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first"); 2948 PetscCheck(ts->problem_type == TS_LINEAR,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()"); 2949 PetscCall(TSGetSNES(ts,&snes)); 2950 PetscCall(SNESGetKSP(snes,ksp)); 2951 PetscFunctionReturn(0); 2952 } 2953 2954 /* ----------- Routines to set solver parameters ---------- */ 2955 2956 /*@ 2957 TSSetMaxSteps - Sets the maximum number of steps to use. 2958 2959 Logically Collective on TS 2960 2961 Input Parameters: 2962 + ts - the TS context obtained from TSCreate() 2963 - maxsteps - maximum number of steps to use 2964 2965 Options Database Keys: 2966 . -ts_max_steps <maxsteps> - Sets maxsteps 2967 2968 Notes: 2969 The default maximum number of steps is 5000 2970 2971 Level: intermediate 2972 2973 .seealso: TSGetMaxSteps(), TSSetMaxTime(), TSSetExactFinalTime() 2974 @*/ 2975 PetscErrorCode TSSetMaxSteps(TS ts,PetscInt maxsteps) 2976 { 2977 PetscFunctionBegin; 2978 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2979 PetscValidLogicalCollectiveInt(ts,maxsteps,2); 2980 PetscCheck(maxsteps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of steps must be non-negative"); 2981 ts->max_steps = maxsteps; 2982 PetscFunctionReturn(0); 2983 } 2984 2985 /*@ 2986 TSGetMaxSteps - Gets the maximum number of steps to use. 2987 2988 Not Collective 2989 2990 Input Parameters: 2991 . ts - the TS context obtained from TSCreate() 2992 2993 Output Parameter: 2994 . maxsteps - maximum number of steps to use 2995 2996 Level: advanced 2997 2998 .seealso: TSSetMaxSteps(), TSGetMaxTime(), TSSetMaxTime() 2999 @*/ 3000 PetscErrorCode TSGetMaxSteps(TS ts,PetscInt *maxsteps) 3001 { 3002 PetscFunctionBegin; 3003 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3004 PetscValidIntPointer(maxsteps,2); 3005 *maxsteps = ts->max_steps; 3006 PetscFunctionReturn(0); 3007 } 3008 3009 /*@ 3010 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 3011 3012 Logically Collective on TS 3013 3014 Input Parameters: 3015 + ts - the TS context obtained from TSCreate() 3016 - maxtime - final time to step to 3017 3018 Options Database Keys: 3019 . -ts_max_time <maxtime> - Sets maxtime 3020 3021 Notes: 3022 The default maximum time is 5.0 3023 3024 Level: intermediate 3025 3026 .seealso: TSGetMaxTime(), TSSetMaxSteps(), TSSetExactFinalTime() 3027 @*/ 3028 PetscErrorCode TSSetMaxTime(TS ts,PetscReal maxtime) 3029 { 3030 PetscFunctionBegin; 3031 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3032 PetscValidLogicalCollectiveReal(ts,maxtime,2); 3033 ts->max_time = maxtime; 3034 PetscFunctionReturn(0); 3035 } 3036 3037 /*@ 3038 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 3039 3040 Not Collective 3041 3042 Input Parameters: 3043 . ts - the TS context obtained from TSCreate() 3044 3045 Output Parameter: 3046 . maxtime - final time to step to 3047 3048 Level: advanced 3049 3050 .seealso: TSSetMaxTime(), TSGetMaxSteps(), TSSetMaxSteps() 3051 @*/ 3052 PetscErrorCode TSGetMaxTime(TS ts,PetscReal *maxtime) 3053 { 3054 PetscFunctionBegin; 3055 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3056 PetscValidRealPointer(maxtime,2); 3057 *maxtime = ts->max_time; 3058 PetscFunctionReturn(0); 3059 } 3060 3061 /*@ 3062 TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep(). 3063 3064 Level: deprecated 3065 3066 @*/ 3067 PetscErrorCode TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step) 3068 { 3069 PetscFunctionBegin; 3070 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3071 PetscCall(TSSetTime(ts,initial_time)); 3072 PetscCall(TSSetTimeStep(ts,time_step)); 3073 PetscFunctionReturn(0); 3074 } 3075 3076 /*@ 3077 TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime(). 3078 3079 Level: deprecated 3080 3081 @*/ 3082 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 3083 { 3084 PetscFunctionBegin; 3085 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3086 if (maxsteps) { 3087 PetscValidIntPointer(maxsteps,2); 3088 *maxsteps = ts->max_steps; 3089 } 3090 if (maxtime) { 3091 PetscValidRealPointer(maxtime,3); 3092 *maxtime = ts->max_time; 3093 } 3094 PetscFunctionReturn(0); 3095 } 3096 3097 /*@ 3098 TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime(). 3099 3100 Level: deprecated 3101 3102 @*/ 3103 PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime) 3104 { 3105 PetscFunctionBegin; 3106 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3107 PetscValidLogicalCollectiveInt(ts,maxsteps,2); 3108 PetscValidLogicalCollectiveReal(ts,maxtime,3); 3109 if (maxsteps >= 0) ts->max_steps = maxsteps; 3110 if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime; 3111 PetscFunctionReturn(0); 3112 } 3113 3114 /*@ 3115 TSGetTimeStepNumber - Deprecated, use TSGetStepNumber(). 3116 3117 Level: deprecated 3118 3119 @*/ 3120 PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); } 3121 3122 /*@ 3123 TSGetTotalSteps - Deprecated, use TSGetStepNumber(). 3124 3125 Level: deprecated 3126 3127 @*/ 3128 PetscErrorCode TSGetTotalSteps(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); } 3129 3130 /*@ 3131 TSSetSolution - Sets the initial solution vector 3132 for use by the TS routines. 3133 3134 Logically Collective on TS 3135 3136 Input Parameters: 3137 + ts - the TS context obtained from TSCreate() 3138 - u - the solution vector 3139 3140 Level: beginner 3141 3142 .seealso: TSSetSolutionFunction(), TSGetSolution(), TSCreate() 3143 @*/ 3144 PetscErrorCode TSSetSolution(TS ts,Vec u) 3145 { 3146 DM dm; 3147 3148 PetscFunctionBegin; 3149 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3150 PetscValidHeaderSpecific(u,VEC_CLASSID,2); 3151 PetscCall(PetscObjectReference((PetscObject)u)); 3152 PetscCall(VecDestroy(&ts->vec_sol)); 3153 ts->vec_sol = u; 3154 3155 PetscCall(TSGetDM(ts,&dm)); 3156 PetscCall(DMShellSetGlobalVector(dm,u)); 3157 PetscFunctionReturn(0); 3158 } 3159 3160 /*@C 3161 TSSetPreStep - Sets the general-purpose function 3162 called once at the beginning of each time step. 3163 3164 Logically Collective on TS 3165 3166 Input Parameters: 3167 + ts - The TS context obtained from TSCreate() 3168 - func - The function 3169 3170 Calling sequence of func: 3171 .vb 3172 PetscErrorCode func (TS ts); 3173 .ve 3174 3175 Level: intermediate 3176 3177 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep(), TSRestartStep() 3178 @*/ 3179 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS)) 3180 { 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3183 ts->prestep = func; 3184 PetscFunctionReturn(0); 3185 } 3186 3187 /*@ 3188 TSPreStep - Runs the user-defined pre-step function. 3189 3190 Collective on TS 3191 3192 Input Parameters: 3193 . ts - The TS context obtained from TSCreate() 3194 3195 Notes: 3196 TSPreStep() is typically used within time stepping implementations, 3197 so most users would not generally call this routine themselves. 3198 3199 Level: developer 3200 3201 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep() 3202 @*/ 3203 PetscErrorCode TSPreStep(TS ts) 3204 { 3205 PetscFunctionBegin; 3206 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3207 if (ts->prestep) { 3208 Vec U; 3209 PetscObjectId idprev; 3210 PetscBool sameObject; 3211 PetscObjectState sprev,spost; 3212 3213 PetscCall(TSGetSolution(ts,&U)); 3214 PetscCall(PetscObjectGetId((PetscObject)U,&idprev)); 3215 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3216 PetscStackCallStandard((*ts->prestep),ts); 3217 PetscCall(TSGetSolution(ts,&U)); 3218 PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject)); 3219 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3220 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3221 } 3222 PetscFunctionReturn(0); 3223 } 3224 3225 /*@C 3226 TSSetPreStage - Sets the general-purpose function 3227 called once at the beginning of each stage. 3228 3229 Logically Collective on TS 3230 3231 Input Parameters: 3232 + ts - The TS context obtained from TSCreate() 3233 - func - The function 3234 3235 Calling sequence of func: 3236 .vb 3237 PetscErrorCode func(TS ts, PetscReal stagetime); 3238 .ve 3239 3240 Level: intermediate 3241 3242 Note: 3243 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3244 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3245 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3246 3247 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext() 3248 @*/ 3249 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal)) 3250 { 3251 PetscFunctionBegin; 3252 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3253 ts->prestage = func; 3254 PetscFunctionReturn(0); 3255 } 3256 3257 /*@C 3258 TSSetPostStage - Sets the general-purpose function 3259 called once at the end of each stage. 3260 3261 Logically Collective on TS 3262 3263 Input Parameters: 3264 + ts - The TS context obtained from TSCreate() 3265 - func - The function 3266 3267 Calling sequence of func: 3268 .vb 3269 PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y); 3270 .ve 3271 3272 Level: intermediate 3273 3274 Note: 3275 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3276 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3277 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3278 3279 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext() 3280 @*/ 3281 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*)) 3282 { 3283 PetscFunctionBegin; 3284 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3285 ts->poststage = func; 3286 PetscFunctionReturn(0); 3287 } 3288 3289 /*@C 3290 TSSetPostEvaluate - Sets the general-purpose function 3291 called once at the end of each step evaluation. 3292 3293 Logically Collective on TS 3294 3295 Input Parameters: 3296 + ts - The TS context obtained from TSCreate() 3297 - func - The function 3298 3299 Calling sequence of func: 3300 .vb 3301 PetscErrorCode func(TS ts); 3302 .ve 3303 3304 Level: intermediate 3305 3306 Note: 3307 Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling 3308 thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep() 3309 may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step 3310 solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step 3311 with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime() 3312 3313 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext() 3314 @*/ 3315 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS)) 3316 { 3317 PetscFunctionBegin; 3318 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3319 ts->postevaluate = func; 3320 PetscFunctionReturn(0); 3321 } 3322 3323 /*@ 3324 TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage() 3325 3326 Collective on TS 3327 3328 Input Parameters: 3329 . ts - The TS context obtained from TSCreate() 3330 stagetime - The absolute time of the current stage 3331 3332 Notes: 3333 TSPreStage() is typically used within time stepping implementations, 3334 most users would not generally call this routine themselves. 3335 3336 Level: developer 3337 3338 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep() 3339 @*/ 3340 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3341 { 3342 PetscFunctionBegin; 3343 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3344 if (ts->prestage) { 3345 PetscStackCallStandard((*ts->prestage),ts,stagetime); 3346 } 3347 PetscFunctionReturn(0); 3348 } 3349 3350 /*@ 3351 TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage() 3352 3353 Collective on TS 3354 3355 Input Parameters: 3356 . ts - The TS context obtained from TSCreate() 3357 stagetime - The absolute time of the current stage 3358 stageindex - Stage number 3359 Y - Array of vectors (of size = total number 3360 of stages) with the stage solutions 3361 3362 Notes: 3363 TSPostStage() is typically used within time stepping implementations, 3364 most users would not generally call this routine themselves. 3365 3366 Level: developer 3367 3368 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep() 3369 @*/ 3370 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3371 { 3372 PetscFunctionBegin; 3373 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3374 if (ts->poststage) { 3375 PetscStackCallStandard((*ts->poststage),ts,stagetime,stageindex,Y); 3376 } 3377 PetscFunctionReturn(0); 3378 } 3379 3380 /*@ 3381 TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate() 3382 3383 Collective on TS 3384 3385 Input Parameters: 3386 . ts - The TS context obtained from TSCreate() 3387 3388 Notes: 3389 TSPostEvaluate() is typically used within time stepping implementations, 3390 most users would not generally call this routine themselves. 3391 3392 Level: developer 3393 3394 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep() 3395 @*/ 3396 PetscErrorCode TSPostEvaluate(TS ts) 3397 { 3398 PetscFunctionBegin; 3399 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3400 if (ts->postevaluate) { 3401 Vec U; 3402 PetscObjectState sprev,spost; 3403 3404 PetscCall(TSGetSolution(ts,&U)); 3405 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3406 PetscStackCallStandard((*ts->postevaluate),ts); 3407 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3408 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3409 } 3410 PetscFunctionReturn(0); 3411 } 3412 3413 /*@C 3414 TSSetPostStep - Sets the general-purpose function 3415 called once at the end of each time step. 3416 3417 Logically Collective on TS 3418 3419 Input Parameters: 3420 + ts - The TS context obtained from TSCreate() 3421 - func - The function 3422 3423 Calling sequence of func: 3424 $ func (TS ts); 3425 3426 Notes: 3427 The function set by TSSetPostStep() is called after each successful step. The solution vector X 3428 obtained by TSGetSolution() may be different than that computed at the step end if the event handler 3429 locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead. 3430 3431 Level: intermediate 3432 3433 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetStepNumber(), TSGetTime(), TSRestartStep() 3434 @*/ 3435 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS)) 3436 { 3437 PetscFunctionBegin; 3438 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 3439 ts->poststep = func; 3440 PetscFunctionReturn(0); 3441 } 3442 3443 /*@ 3444 TSPostStep - Runs the user-defined post-step function. 3445 3446 Collective on TS 3447 3448 Input Parameters: 3449 . ts - The TS context obtained from TSCreate() 3450 3451 Notes: 3452 TSPostStep() is typically used within time stepping implementations, 3453 so most users would not generally call this routine themselves. 3454 3455 Level: developer 3456 3457 @*/ 3458 PetscErrorCode TSPostStep(TS ts) 3459 { 3460 PetscFunctionBegin; 3461 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3462 if (ts->poststep) { 3463 Vec U; 3464 PetscObjectId idprev; 3465 PetscBool sameObject; 3466 PetscObjectState sprev,spost; 3467 3468 PetscCall(TSGetSolution(ts,&U)); 3469 PetscCall(PetscObjectGetId((PetscObject)U,&idprev)); 3470 PetscCall(PetscObjectStateGet((PetscObject)U,&sprev)); 3471 PetscStackCallStandard((*ts->poststep),ts); 3472 PetscCall(TSGetSolution(ts,&U)); 3473 PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject)); 3474 PetscCall(PetscObjectStateGet((PetscObject)U,&spost)); 3475 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3476 } 3477 PetscFunctionReturn(0); 3478 } 3479 3480 /*@ 3481 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3482 3483 Collective on TS 3484 3485 Input Parameters: 3486 + ts - time stepping context 3487 - t - time to interpolate to 3488 3489 Output Parameter: 3490 . U - state at given time 3491 3492 Level: intermediate 3493 3494 Developer Notes: 3495 TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3496 3497 .seealso: TSSetExactFinalTime(), TSSolve() 3498 @*/ 3499 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U) 3500 { 3501 PetscFunctionBegin; 3502 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3503 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 3504 PetscCheck(t >= ts->ptime_prev && t <= ts->ptime,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Requested time %g not in last time steps [%g,%g]",t,(double)ts->ptime_prev,(double)ts->ptime); 3505 PetscCheck(ts->ops->interpolate,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name); 3506 PetscCall((*ts->ops->interpolate)(ts,t,U)); 3507 PetscFunctionReturn(0); 3508 } 3509 3510 /*@ 3511 TSStep - Steps one time step 3512 3513 Collective on TS 3514 3515 Input Parameter: 3516 . ts - the TS context obtained from TSCreate() 3517 3518 Level: developer 3519 3520 Notes: 3521 The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine. 3522 3523 The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may 3524 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3525 3526 This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the 3527 time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep. 3528 3529 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate() 3530 @*/ 3531 PetscErrorCode TSStep(TS ts) 3532 { 3533 PetscErrorCode ierr; 3534 static PetscBool cite = PETSC_FALSE; 3535 PetscReal ptime; 3536 3537 PetscFunctionBegin; 3538 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3539 ierr = PetscCitationsRegister("@article{tspaper,\n" 3540 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3541 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3542 " journal = {arXiv e-preprints},\n" 3543 " eprint = {1806.01437},\n" 3544 " archivePrefix = {arXiv},\n" 3545 " year = {2018}\n}\n",&cite);PetscCall(ierr); 3546 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