1 /* 2 Code for Timestepping with explicit SSP. 3 */ 4 #include <private/tsimpl.h> /*I "petscts.h" I*/ 5 6 PetscFList TSSSPList = 0; 7 #define TSSSPType char* 8 9 #define TSSSPRKS2 "rks2" 10 #define TSSSPRKS3 "rks3" 11 #define TSSSPRK104 "rk104" 12 13 typedef struct { 14 PetscErrorCode (*onestep)(TS,PetscReal,PetscReal,Vec); 15 PetscInt nstages; 16 Vec *work; 17 PetscInt nwork; 18 PetscBool workout; 19 } TS_SSP; 20 21 22 #undef __FUNCT__ 23 #define __FUNCT__ "SSPGetWorkVectors" 24 static PetscErrorCode SSPGetWorkVectors(TS ts,PetscInt n,Vec **work) 25 { 26 TS_SSP *ssp = (TS_SSP*)ts->data; 27 PetscErrorCode ierr; 28 29 PetscFunctionBegin; 30 if (ssp->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Work vectors already gotten"); 31 if (ssp->nwork < n) { 32 if (ssp->nwork > 0) { 33 ierr = VecDestroyVecs(ssp->nwork,&ssp->work);CHKERRQ(ierr); 34 } 35 ierr = VecDuplicateVecs(ts->vec_sol,n,&ssp->work);CHKERRQ(ierr); 36 ssp->nwork = n; 37 } 38 *work = ssp->work; 39 ssp->workout = PETSC_TRUE; 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "SSPRestoreWorkVectors" 45 static PetscErrorCode SSPRestoreWorkVectors(TS ts,PetscInt n,Vec **work) 46 { 47 TS_SSP *ssp = (TS_SSP*)ts->data; 48 49 PetscFunctionBegin; 50 if (!ssp->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Work vectors have not been gotten"); 51 if (*work != ssp->work) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong work vectors checked out"); 52 ssp->workout = PETSC_FALSE; 53 *work = PETSC_NULL; 54 PetscFunctionReturn(0); 55 } 56 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "SSPStep_RK_2" 60 /* Optimal second order SSP Runge-Kutta, low-storage, c_eff=(s-1)/s */ 61 /* Pseudocode 2 of Ketcheson 2008 */ 62 static PetscErrorCode SSPStep_RK_2(TS ts,PetscReal t0,PetscReal dt,Vec sol) 63 { 64 TS_SSP *ssp = (TS_SSP*)ts->data; 65 Vec *work,F; 66 PetscInt i,s; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 s = ssp->nstages; 71 ierr = SSPGetWorkVectors(ts,2,&work);CHKERRQ(ierr); 72 F = work[1]; 73 ierr = VecCopy(sol,work[0]);CHKERRQ(ierr); 74 for (i=0; i<s-1; i++) { 75 ierr = TSComputeRHSFunction(ts,t0+dt*(i/(s-1.)),work[0],F);CHKERRQ(ierr); 76 ierr = VecAXPY(work[0],dt/(s-1.),F);CHKERRQ(ierr); 77 } 78 ierr = TSComputeRHSFunction(ts,t0+dt,work[0],F);CHKERRQ(ierr); 79 ierr = VecAXPBYPCZ(sol,(s-1.)/s,dt/s,1./s,work[0],F);CHKERRQ(ierr); 80 ierr = SSPRestoreWorkVectors(ts,2,&work);CHKERRQ(ierr); 81 PetscFunctionReturn(0); 82 } 83 84 #undef __FUNCT__ 85 #define __FUNCT__ "SSPStep_RK_3" 86 /* Optimal third order SSP Runge-Kutta, low-storage, c_eff=(sqrt(s)-1)/sqrt(s), where sqrt(s) is an integer */ 87 /* Pseudocode 2 of Ketcheson 2008 */ 88 static PetscErrorCode SSPStep_RK_3(TS ts,PetscReal t0,PetscReal dt,Vec sol) 89 { 90 TS_SSP *ssp = (TS_SSP*)ts->data; 91 Vec *work,F; 92 PetscInt i,s,n,r; 93 PetscReal c; 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 s = ssp->nstages; 98 n = (PetscInt)(sqrt((PetscReal)s)+0.001); 99 r = s-n; 100 if (n*n != s) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for optimal third order schemes with %d stages, must be a square number at least 4",s); 101 ierr = SSPGetWorkVectors(ts,3,&work);CHKERRQ(ierr); 102 F = work[2]; 103 ierr = VecCopy(sol,work[0]);CHKERRQ(ierr); 104 for (i=0; i<(n-1)*(n-2)/2; i++) { 105 c = (i<n*(n+1)/2) ? 1.*i/(s-n) : (1.*i-n)/(s-n); 106 ierr = TSComputeRHSFunction(ts,t0+c*dt,work[0],F);CHKERRQ(ierr); 107 ierr = VecAXPY(work[0],dt/r,F);CHKERRQ(ierr); 108 } 109 ierr = VecCopy(work[0],work[1]);CHKERRQ(ierr); 110 for ( ; i<n*(n+1)/2-1; i++) { 111 c = (i<n*(n+1)/2) ? 1.*i/(s-n) : (1.*i-n)/(s-n); 112 ierr = TSComputeRHSFunction(ts,t0+c*dt,work[0],F);CHKERRQ(ierr); 113 ierr = VecAXPY(work[0],dt/r,F);CHKERRQ(ierr); 114 } 115 { 116 c = (i<n*(n+1)/2) ? 1.*i/(s-n) : (1.*i-n)/(s-n); 117 ierr = TSComputeRHSFunction(ts,t0+c*dt,work[0],F);CHKERRQ(ierr); 118 ierr = VecAXPBYPCZ(work[0],1.*n/(2*n-1.),(n-1.)*dt/(r*(2*n-1)),(n-1.)/(2*n-1.),work[1],F);CHKERRQ(ierr); 119 i++; 120 } 121 for ( ; i<s; i++) { 122 c = (i<n*(n+1)/2) ? 1.*i/(s-n) : (1.*i-n)/(s-n); 123 ierr = TSComputeRHSFunction(ts,t0+c*dt,work[0],F);CHKERRQ(ierr); 124 ierr = VecAXPY(work[0],dt/r,F);CHKERRQ(ierr); 125 } 126 ierr = VecCopy(work[0],sol);CHKERRQ(ierr); 127 ierr = SSPRestoreWorkVectors(ts,3,&work);CHKERRQ(ierr); 128 PetscFunctionReturn(0); 129 } 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "SSPStep_RK_10_4" 133 /* Optimal fourth order SSP Runge-Kutta, low-storage (2N), c_eff=0.6 */ 134 /* SSPRK(10,4), Pseudocode 3 of Ketcheson 2008 */ 135 static PetscErrorCode SSPStep_RK_10_4(TS ts,PetscReal t0,PetscReal dt,Vec sol) 136 { 137 const PetscReal c[10] = {0, 1./6, 2./6, 3./6, 4./6, 2./6, 3./6, 4./6, 5./6, 1}; 138 Vec *work,F; 139 PetscInt i; 140 PetscErrorCode ierr; 141 142 PetscFunctionBegin; 143 ierr = SSPGetWorkVectors(ts,3,&work);CHKERRQ(ierr); 144 F = work[2]; 145 ierr = VecCopy(sol,work[0]);CHKERRQ(ierr); 146 for (i=0; i<5; i++) { 147 ierr = TSComputeRHSFunction(ts,t0+c[i],work[0],F);CHKERRQ(ierr); 148 ierr = VecAXPY(work[0],dt/6,F);CHKERRQ(ierr); 149 } 150 ierr = VecAXPBYPCZ(work[1],1./25,9./25,0,sol,work[0]);CHKERRQ(ierr); 151 ierr = VecAXPBY(work[0],15,-5,work[1]);CHKERRQ(ierr); 152 for ( ; i<9; i++) { 153 ierr = TSComputeRHSFunction(ts,t0+c[i],work[0],F);CHKERRQ(ierr); 154 ierr = VecAXPY(work[0],dt/6,F);CHKERRQ(ierr); 155 } 156 ierr = TSComputeRHSFunction(ts,t0+dt,work[0],F);CHKERRQ(ierr); 157 ierr = VecAXPBYPCZ(work[1],3./5,dt/10,1,work[0],F);CHKERRQ(ierr); 158 ierr = VecCopy(work[1],sol);CHKERRQ(ierr); 159 ierr = SSPRestoreWorkVectors(ts,3,&work);CHKERRQ(ierr); 160 PetscFunctionReturn(0); 161 } 162 163 164 #undef __FUNCT__ 165 #define __FUNCT__ "TSSetUp_SSP" 166 static PetscErrorCode TSSetUp_SSP(TS ts) 167 { 168 /* TS_SSP *ssp = (TS_SSP*)ts->data; */ 169 /* PetscErrorCode ierr; */ 170 171 PetscFunctionBegin; 172 PetscFunctionReturn(0); 173 } 174 175 #undef __FUNCT__ 176 #define __FUNCT__ "TSStep_SSP" 177 static PetscErrorCode TSStep_SSP(TS ts,PetscInt *steps,PetscReal *ptime) 178 { 179 TS_SSP *ssp = (TS_SSP*)ts->data; 180 Vec sol = ts->vec_sol; 181 PetscInt i; 182 PetscErrorCode ierr; 183 184 PetscFunctionBegin; 185 *steps = -ts->steps; 186 *ptime = ts->ptime; 187 188 ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr); 189 190 for (i=0; i<ts->max_steps; i++) { 191 if (ts->ptime + ts->time_step > ts->max_time) break; 192 ierr = TSPreStep(ts);CHKERRQ(ierr); 193 194 ierr = (*ssp->onestep)(ts,ts->ptime,ts->time_step,sol);CHKERRQ(ierr); 195 196 ts->ptime += ts->time_step; 197 ts->steps++; 198 199 ierr = TSPostStep(ts);CHKERRQ(ierr); 200 ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr); 201 } 202 203 *steps += ts->steps; 204 *ptime = ts->ptime; 205 PetscFunctionReturn(0); 206 } 207 /*------------------------------------------------------------*/ 208 #undef __FUNCT__ 209 #define __FUNCT__ "TSReset_SSP" 210 static PetscErrorCode TSReset_SSP(TS ts) 211 { 212 TS_SSP *ssp = (TS_SSP*)ts->data; 213 PetscErrorCode ierr; 214 215 PetscFunctionBegin; 216 if (ssp->work) {ierr = VecDestroyVecs(ssp->nwork,&ssp->work);CHKERRQ(ierr);} 217 ssp->nwork = 0; 218 ssp->workout = PETSC_FALSE; 219 PetscFunctionReturn(0); 220 } 221 222 #undef __FUNCT__ 223 #define __FUNCT__ "TSDestroy_SSP" 224 static PetscErrorCode TSDestroy_SSP(TS ts) 225 { 226 PetscErrorCode ierr; 227 228 PetscFunctionBegin; 229 ierr = TSReset_SSP(ts);CHKERRQ(ierr); 230 ierr = PetscFree(ts->data);CHKERRQ(ierr); 231 PetscFunctionReturn(0); 232 } 233 /*------------------------------------------------------------*/ 234 235 #undef __FUNCT__ 236 #define __FUNCT__ "TSSSPSetType" 237 static PetscErrorCode TSSSPSetType(TS ts,const TSSSPType type) 238 { 239 PetscErrorCode ierr,(*r)(TS,PetscReal,PetscReal,Vec); 240 TS_SSP *ssp = (TS_SSP*)ts->data; 241 242 PetscFunctionBegin; 243 ierr = PetscFListFind(TSSSPList,((PetscObject)ts)->comm,type,PETSC_TRUE,(void(**)(void))&r);CHKERRQ(ierr); 244 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TS_SSP type %s given",type); 245 ssp->onestep = r; 246 PetscFunctionReturn(0); 247 } 248 249 #undef __FUNCT__ 250 #define __FUNCT__ "TSSetFromOptions_SSP" 251 static PetscErrorCode TSSetFromOptions_SSP(TS ts) 252 { 253 char tname[256] = TSSSPRKS2; 254 TS_SSP *ssp = (TS_SSP*)ts->data; 255 PetscErrorCode ierr; 256 PetscBool flg; 257 258 PetscFunctionBegin; 259 ierr = PetscOptionsHead("SSP ODE solver options");CHKERRQ(ierr); 260 { 261 ierr = PetscOptionsList("-ts_ssp_type","Type of SSP method","TSSSPSetType",TSSSPList,tname,tname,sizeof(tname),&flg);CHKERRQ(ierr); 262 if (flg) { 263 ierr = TSSSPSetType(ts,tname);CHKERRQ(ierr); 264 } 265 ierr = PetscOptionsInt("-ts_ssp_nstages","Number of stages","TSSSPSetNumStages",ssp->nstages,&ssp->nstages,PETSC_NULL);CHKERRQ(ierr); 266 } 267 ierr = PetscOptionsTail();CHKERRQ(ierr); 268 PetscFunctionReturn(0); 269 } 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "TSView_SSP" 273 static PetscErrorCode TSView_SSP(TS ts,PetscViewer viewer) 274 { 275 PetscFunctionBegin; 276 PetscFunctionReturn(0); 277 } 278 279 /* ------------------------------------------------------------ */ 280 281 /*MC 282 TSSSP - Explicit strong stability preserving ODE solver 283 284 Most hyperbolic conservation laws have exact solutions that are total variation diminishing (TVD) or total variation 285 bounded (TVB) although these solutions often contain discontinuities. Spatial discretizations such as Godunov's 286 scheme and high-resolution finite volume methods (TVD limiters, ENO/WENO) are designed to preserve these properties, 287 but they are usually formulated using a forward Euler time discretization or by coupling the space and time 288 discretization as in the classical Lax-Wendroff scheme. When the space and time discretization is coupled, it is very 289 difficult to produce schemes with high temporal accuracy while preserving TVD properties. An alternative is the 290 semidiscrete formulation where we choose a spatial discretization that is TVD with forward Euler and then choose a 291 time discretization that preserves the TVD property. Such integrators are called strong stability preserving (SSP). 292 293 Let c_eff be the minimum number of function evaluations required to step as far as one step of forward Euler while 294 still being SSP. Some theoretical bounds 295 296 1. There are no explicit methods with c_eff > 1. 297 298 2. There are no explicit methods beyond order 4 (for nonlinear problems) and c_eff > 0. 299 300 3. There are no implicit methods with order greater than 1 and c_eff > 2. 301 302 This integrator provides Runge-Kutta methods of order 2, 3, and 4 with maximal values of c_eff. More stages allows 303 for larger values of c_eff which improves efficiency. These implementations are low-memory and only use 2 or 3 work 304 vectors regardless of the total number of stages, so e.g. 25-stage 3rd order methods may be an excellent choice. 305 306 Methods can be chosen with -ts_ssp_type {rks2,rks3,rk104} 307 308 rks2: Second order methods with any number s>1 of stages. c_eff = (s-1)/s 309 310 rks3: Third order methods with s=n^2 stages, n>1. c_eff = (s-n)/s 311 312 rk104: A 10-stage fourth order method. c_eff = 0.6 313 314 Level: beginner 315 316 References: 317 Ketcheson, Highly efficient strong stability preserving Runge-Kutta methods with low-storage implementations, SISC, 2008. 318 319 Gottlieb, Ketcheson, and Shu, High order strong stability preserving time discretizations, J Scientific Computing, 2009. 320 321 .seealso: TSCreate(), TS, TSSetType() 322 323 M*/ 324 EXTERN_C_BEGIN 325 #undef __FUNCT__ 326 #define __FUNCT__ "TSCreate_SSP" 327 PetscErrorCode TSCreate_SSP(TS ts) 328 { 329 TS_SSP *ssp; 330 PetscErrorCode ierr; 331 332 PetscFunctionBegin; 333 if (!TSSSPList) { 334 ierr = PetscFListAdd(&TSSSPList,TSSSPRKS2, "SSPStep_RK_2", (void(*)(void))SSPStep_RK_2);CHKERRQ(ierr); 335 ierr = PetscFListAdd(&TSSSPList,TSSSPRKS3, "SSPStep_RK_3", (void(*)(void))SSPStep_RK_3);CHKERRQ(ierr); 336 ierr = PetscFListAdd(&TSSSPList,TSSSPRK104, "SSPStep_RK_10_4",(void(*)(void))SSPStep_RK_10_4);CHKERRQ(ierr); 337 } 338 339 ts->ops->setup = TSSetUp_SSP; 340 ts->ops->step = TSStep_SSP; 341 ts->ops->reset = TSReset_SSP; 342 ts->ops->destroy = TSDestroy_SSP; 343 ts->ops->setfromoptions = TSSetFromOptions_SSP; 344 ts->ops->view = TSView_SSP; 345 346 ierr = PetscNewLog(ts,TS_SSP,&ssp);CHKERRQ(ierr); 347 ts->data = (void*)ssp; 348 349 ierr = TSSSPSetType(ts,TSSSPRKS2);CHKERRQ(ierr); 350 ssp->nstages = 5; 351 PetscFunctionReturn(0); 352 } 353 EXTERN_C_END 354