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