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