1 /* 2 Code for time stepping with the multi-rate Runge-Kutta method 3 4 Notes: 5 1) The general system is written as 6 Udot = F(t,U) for the nonsplit version of multi-rate RK, 7 user should give the indexes for both slow and fast components; 8 2) The general system is written as 9 Usdot = Fs(t,Us,Uf) 10 Ufdot = Ff(t,Us,Uf) for multi-rate RK with RHS splits, 11 user should partioned RHS by themselves and also provide the indexes for both slow and fast components. 12 */ 13 14 #include <petsc/private/tsimpl.h> 15 #include <petscdm.h> 16 #include <../src/ts/impls/explicit/rk/rk.h> 17 #include <../src/ts/impls/explicit/rk/mrk.h> 18 19 static PetscErrorCode TSReset_RK_MultirateNonsplit(TS ts) 20 { 21 TS_RK *rk = (TS_RK*)ts->data; 22 RKTableau tab = rk->tableau; 23 PetscErrorCode ierr; 24 25 PetscFunctionBegin; 26 ierr = VecDestroy(&rk->X0);CHKERRQ(ierr); 27 ierr = VecDestroyVecs(tab->s,&rk->YdotRHS_slow);CHKERRQ(ierr); 28 PetscFunctionReturn(0); 29 } 30 31 static PetscErrorCode TSInterpolate_RK_MultirateNonsplit(TS ts,PetscReal itime,Vec X) 32 { 33 TS_RK *rk = (TS_RK*)ts->data; 34 PetscInt s = rk->tableau->s,p = rk->tableau->p,i,j; 35 PetscReal h = ts->time_step; 36 PetscReal tt,t; 37 PetscScalar *b; 38 const PetscReal *B = rk->tableau->binterp; 39 PetscErrorCode ierr; 40 41 PetscFunctionBegin; 42 if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRK %s does not have an interpolation formula",rk->tableau->name); 43 t = (itime - rk->ptime)/h; 44 ierr = PetscMalloc1(s,&b);CHKERRQ(ierr); 45 for (i=0; i<s; i++) b[i] = 0; 46 for (j=0,tt=t; j<p; j++,tt*=t) { 47 for (i=0; i<s; i++) { 48 b[i] += h * B[i*p+j] * tt; 49 } 50 } 51 ierr = VecCopy(rk->X0,X);CHKERRQ(ierr); 52 ierr = VecMAXPY(X,s,b,rk->YdotRHS_slow);CHKERRQ(ierr); 53 ierr = PetscFree(b);CHKERRQ(ierr); 54 PetscFunctionReturn(0); 55 } 56 57 static PetscErrorCode TSStepRefine_RK_MultirateNonsplit(TS ts) 58 { 59 TS previousts,subts; 60 TS_RK *rk = (TS_RK*)ts->data; 61 RKTableau tab = rk->tableau; 62 Vec *Y = rk->Y,*YdotRHS = rk->YdotRHS; 63 Vec vec_fast,subvec_fast; 64 const PetscInt s = tab->s; 65 const PetscReal *A = tab->A,*c = tab->c; 66 PetscScalar *w = rk->work; 67 PetscInt i,j,k; 68 PetscReal t = ts->ptime,h = ts->time_step; 69 PetscErrorCode ierr; 70 71 ierr = VecDuplicate(ts->vec_sol,&vec_fast);CHKERRQ(ierr); 72 previousts = rk->subts_current; 73 ierr = TSRHSSplitGetSubTS(rk->subts_current,"fast",&subts);CHKERRQ(ierr); 74 ierr = TSRHSSplitGetSubTS(subts,"fast",&subts);CHKERRQ(ierr); 75 for (k=0; k<rk->dtratio; k++) { 76 for (i=0; i<s; i++) { 77 ierr = TSInterpolate_RK_MultirateNonsplit(ts,t+k*h/rk->dtratio+h/rk->dtratio*c[i],Y[i]);CHKERRQ(ierr); 78 for (j=0; j<i; j++) w[j] = h/rk->dtratio*A[i*s+j]; 79 /* update the fast components in the stage value, the slow components will be ignored, so we do not care the slow part in vec_fast */ 80 ierr = VecCopy(ts->vec_sol,vec_fast);CHKERRQ(ierr); 81 ierr = VecMAXPY(vec_fast,i,w,YdotRHS);CHKERRQ(ierr); 82 /* update the fast components in the stage value */ 83 ierr = VecGetSubVector(vec_fast,rk->is_fast,&subvec_fast);CHKERRQ(ierr); 84 ierr = VecISCopy(Y[i],rk->is_fast,SCATTER_FORWARD,subvec_fast);CHKERRQ(ierr); 85 ierr = VecRestoreSubVector(vec_fast,rk->is_fast,&subvec_fast);CHKERRQ(ierr); 86 /* compute the stage RHS */ 87 ierr = TSComputeRHSFunction(ts,t+k*h/rk->dtratio+h/rk->dtratio*c[i],Y[i],YdotRHS[i]);CHKERRQ(ierr); 88 } 89 ierr = VecCopy(ts->vec_sol,vec_fast);CHKERRQ(ierr); 90 ierr = TSEvaluateStep(ts,tab->order,vec_fast,NULL);CHKERRQ(ierr); 91 /* update the fast components in the solution */ 92 ierr = VecGetSubVector(vec_fast,rk->is_fast,&subvec_fast);CHKERRQ(ierr); 93 ierr = VecISCopy(ts->vec_sol,rk->is_fast,SCATTER_FORWARD,subvec_fast);CHKERRQ(ierr); 94 ierr = VecRestoreSubVector(vec_fast,rk->is_fast,&subvec_fast);CHKERRQ(ierr); 95 96 if (subts) { 97 Vec *YdotRHS_copy; 98 ierr = VecDuplicateVecs(ts->vec_sol,s,&YdotRHS_copy);CHKERRQ(ierr); 99 rk->subts_current = rk->subts_fast; 100 ts->ptime = t+k*h/rk->dtratio; 101 ts->time_step = h/rk->dtratio; 102 ierr = TSRHSSplitGetIS(rk->subts_current,"fast",&rk->is_fast);CHKERRQ(ierr); 103 for (i=0; i<s; i++) { 104 ierr = VecCopy(rk->YdotRHS_slow[i],YdotRHS_copy[i]);CHKERRQ(ierr); 105 ierr = VecCopy(YdotRHS[i],rk->YdotRHS_slow[i]);CHKERRQ(ierr); 106 } 107 108 ierr = TSStepRefine_RK_MultirateNonsplit(ts);CHKERRQ(ierr); 109 110 rk->subts_current = previousts; 111 ts->ptime = t; 112 ts->time_step = h; 113 ierr = TSRHSSplitGetIS(previousts,"fast",&rk->is_fast);CHKERRQ(ierr); 114 for (i=0; i<s; i++) { 115 ierr = VecCopy(YdotRHS_copy[i],rk->YdotRHS_slow[i]);CHKERRQ(ierr); 116 } 117 ierr = VecDestroyVecs(s,&YdotRHS_copy);CHKERRQ(ierr); 118 } 119 } 120 ierr = VecDestroy(&vec_fast);CHKERRQ(ierr); 121 PetscFunctionReturn(0); 122 } 123 124 static PetscErrorCode TSStep_RK_MultirateNonsplit(TS ts) 125 { 126 TS_RK *rk = (TS_RK*)ts->data; 127 RKTableau tab = rk->tableau; 128 Vec *Y = rk->Y,*YdotRHS = rk->YdotRHS,*YdotRHS_slow = rk->YdotRHS_slow; 129 Vec stage_slow,sol_slow; /* vectors store the slow components */ 130 Vec subvec_slow; /* sub vector to store the slow components */ 131 IS is_slow = rk->is_slow; 132 const PetscInt s = tab->s; 133 const PetscReal *A = tab->A,*c = tab->c; 134 PetscScalar *w = rk->work; 135 PetscInt i,j,dtratio = rk->dtratio; 136 PetscReal next_time_step = ts->time_step,t = ts->ptime,h = ts->time_step; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 rk->status = TS_STEP_INCOMPLETE; 141 ierr = VecDuplicate(ts->vec_sol,&stage_slow);CHKERRQ(ierr); 142 ierr = VecDuplicate(ts->vec_sol,&sol_slow);CHKERRQ(ierr); 143 ierr = VecCopy(ts->vec_sol,rk->X0);CHKERRQ(ierr); 144 for (i=0; i<s; i++) { 145 rk->stage_time = t + h*c[i]; 146 ierr = TSPreStage(ts,rk->stage_time);CHKERRQ(ierr); 147 ierr = VecCopy(ts->vec_sol,Y[i]);CHKERRQ(ierr); 148 for (j=0; j<i; j++) w[j] = h*A[i*s+j]; 149 ierr = VecMAXPY(Y[i],i,w,YdotRHS_slow);CHKERRQ(ierr); 150 ierr = TSPostStage(ts,rk->stage_time,i,Y); CHKERRQ(ierr); 151 /* compute the stage RHS */ 152 ierr = TSComputeRHSFunction(ts,t+h*c[i],Y[i],YdotRHS_slow[i]);CHKERRQ(ierr); 153 } 154 /* update the slow components in the solution */ 155 rk->YdotRHS = YdotRHS_slow; 156 rk->dtratio = 1; 157 ierr = TSEvaluateStep(ts,tab->order,sol_slow,NULL);CHKERRQ(ierr); 158 rk->dtratio = dtratio; 159 rk->YdotRHS = YdotRHS; 160 /* update the slow components in the solution */ 161 ierr = VecGetSubVector(sol_slow,is_slow,&subvec_slow);CHKERRQ(ierr); 162 ierr = VecISCopy(ts->vec_sol,is_slow,SCATTER_FORWARD,subvec_slow);CHKERRQ(ierr); 163 ierr = VecRestoreSubVector(sol_slow,is_slow,&subvec_slow);CHKERRQ(ierr); 164 165 rk->subts_current = ts; 166 rk->ptime = t; 167 rk->time_step = h; 168 ierr = TSStepRefine_RK_MultirateNonsplit(ts);CHKERRQ(ierr); 169 170 ts->ptime = t + ts->time_step; 171 ts->time_step = next_time_step; 172 rk->status = TS_STEP_COMPLETE; 173 174 /* free memory of work vectors */ 175 ierr = VecDestroy(&stage_slow);CHKERRQ(ierr); 176 ierr = VecDestroy(&sol_slow);CHKERRQ(ierr); 177 PetscFunctionReturn(0); 178 } 179 180 static PetscErrorCode TSSetUp_RK_MultirateNonsplit(TS ts) 181 { 182 TS_RK *rk = (TS_RK*)ts->data; 183 RKTableau tab = rk->tableau; 184 PetscErrorCode ierr; 185 186 PetscFunctionBegin; 187 ierr = TSRHSSplitGetIS(ts,"slow",&rk->is_slow);CHKERRQ(ierr); 188 ierr = TSRHSSplitGetIS(ts,"fast",&rk->is_fast);CHKERRQ(ierr); 189 if (!rk->is_slow || !rk->is_fast) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up RHSSplits with TSRHSSplitSetIS() using split names 'slow' and 'fast' respectively in order to use multirate RK"); 190 ierr = TSRHSSplitGetSubTS(ts,"slow",&rk->subts_slow);CHKERRQ(ierr); 191 ierr = TSRHSSplitGetSubTS(ts,"fast",&rk->subts_fast);CHKERRQ(ierr); 192 if (!rk->subts_slow || !rk->subts_fast) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up the RHSFunctions for 'slow' and 'fast' components using TSRHSSplitSetRHSFunction() or calling TSSetRHSFunction() for each sub-TS"); 193 ierr = VecDuplicate(ts->vec_sol,&rk->X0);CHKERRQ(ierr); 194 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&rk->YdotRHS_slow);CHKERRQ(ierr); 195 rk->subts_current = rk->subts_fast; 196 197 ts->ops->step = TSStep_RK_MultirateNonsplit; 198 ts->ops->interpolate = TSInterpolate_RK_MultirateNonsplit; 199 PetscFunctionReturn(0); 200 } 201 202 /* 203 Copy DM from tssrc to tsdest, while keeping the original DMTS and DMSNES in tsdest. 204 */ 205 static PetscErrorCode TSCopyDM(TS tssrc,TS tsdest) 206 { 207 DM newdm,dmsrc,dmdest; 208 PetscErrorCode ierr; 209 210 PetscFunctionBegin; 211 ierr = TSGetDM(tssrc,&dmsrc);CHKERRQ(ierr); 212 ierr = DMClone(dmsrc,&newdm);CHKERRQ(ierr); 213 ierr = TSGetDM(tsdest,&dmdest);CHKERRQ(ierr); 214 ierr = DMCopyDMTS(dmdest,newdm);CHKERRQ(ierr); 215 ierr = DMCopyDMSNES(dmdest,newdm);CHKERRQ(ierr); 216 ierr = TSSetDM(tsdest,newdm);CHKERRQ(ierr); 217 ierr = DMDestroy(&newdm);CHKERRQ(ierr); 218 PetscFunctionReturn(0); 219 } 220 221 static PetscErrorCode TSReset_RK_MultirateSplit(TS ts) 222 { 223 TS_RK *rk = (TS_RK*)ts->data; 224 PetscErrorCode ierr; 225 226 PetscFunctionBegin; 227 if (rk->subts_slow) { 228 ierr = PetscFree(rk->subts_slow->data);CHKERRQ(ierr); 229 rk->subts_slow = NULL; 230 } 231 if (rk->subts_fast) { 232 ierr = PetscFree(rk->YdotRHS_fast);CHKERRQ(ierr); 233 ierr = PetscFree(rk->YdotRHS_slow);CHKERRQ(ierr); 234 ierr = VecDestroy(&rk->X0);CHKERRQ(ierr); 235 ierr = TSReset_RK_MultirateSplit(rk->subts_fast);CHKERRQ(ierr); 236 ierr = PetscFree(rk->subts_fast->data);CHKERRQ(ierr); 237 rk->subts_fast = NULL; 238 } 239 PetscFunctionReturn(0); 240 } 241 242 static PetscErrorCode TSInterpolate_RK_MultirateSplit(TS ts,PetscReal itime,Vec X) 243 { 244 TS_RK *rk = (TS_RK*)ts->data; 245 Vec Xslow; 246 PetscInt s = rk->tableau->s,p = rk->tableau->p,i,j; 247 PetscReal h; 248 PetscReal tt,t; 249 PetscScalar *b; 250 const PetscReal *B = rk->tableau->binterp; 251 PetscErrorCode ierr; 252 253 PetscFunctionBegin; 254 if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRK %s does not have an interpolation formula",rk->tableau->name); 255 256 switch (rk->status) { 257 case TS_STEP_INCOMPLETE: 258 case TS_STEP_PENDING: 259 h = ts->time_step; 260 t = (itime - ts->ptime)/h; 261 break; 262 case TS_STEP_COMPLETE: 263 h = ts->ptime - ts->ptime_prev; 264 t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 265 break; 266 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 267 } 268 ierr = PetscMalloc1(s,&b);CHKERRQ(ierr); 269 for (i=0; i<s; i++) b[i] = 0; 270 for (j=0,tt=t; j<p; j++,tt*=t) { 271 for (i=0; i<s; i++) { 272 b[i] += h * B[i*p+j] * tt; 273 } 274 } 275 for (i=0; i<s; i++) { 276 ierr = VecGetSubVector(rk->YdotRHS[i],rk->is_slow,&rk->YdotRHS_slow[i]);CHKERRQ(ierr); 277 } 278 ierr = VecGetSubVector(X,rk->is_slow,&Xslow);CHKERRQ(ierr); 279 ierr = VecISCopy(rk->X0,rk->is_slow,SCATTER_REVERSE,Xslow);CHKERRQ(ierr); 280 ierr = VecMAXPY(Xslow,s,b,rk->YdotRHS_slow);CHKERRQ(ierr); 281 ierr = VecRestoreSubVector(X,rk->is_slow,&Xslow);CHKERRQ(ierr); 282 for (i=0; i<s; i++) { 283 ierr = VecRestoreSubVector(rk->YdotRHS[i],rk->is_slow,&rk->YdotRHS_slow[i]);CHKERRQ(ierr); 284 } 285 ierr = PetscFree(b);CHKERRQ(ierr); 286 PetscFunctionReturn(0); 287 } 288 289 /* 290 This is for partitioned RHS multirate RK method 291 The step completion formula is 292 293 x1 = x0 + h b^T YdotRHS 294 295 */ 296 static PetscErrorCode TSEvaluateStep_RK_MultirateSplit(TS ts,PetscInt order,Vec X,PetscBool *done) 297 { 298 TS_RK *rk = (TS_RK*)ts->data; 299 RKTableau tab = rk->tableau; 300 Vec Xslow,Xfast; /* subvectors of X which store slow components and fast components respectively */ 301 PetscScalar *w = rk->work; 302 PetscReal h = ts->time_step; 303 PetscInt s = tab->s,j; 304 PetscErrorCode ierr; 305 306 PetscFunctionBegin; 307 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 308 if (rk->slow) { 309 for (j=0; j<s; j++) w[j] = h*tab->b[j]; 310 ierr = VecGetSubVector(ts->vec_sol,rk->is_slow,&Xslow);CHKERRQ(ierr); 311 ierr = VecMAXPY(Xslow,s,w,rk->YdotRHS_slow);CHKERRQ(ierr); 312 ierr = VecRestoreSubVector(ts->vec_sol,rk->is_slow,&Xslow);CHKERRQ(ierr);; 313 } else { 314 for (j=0; j<s; j++) w[j] = h/rk->dtratio*tab->b[j]; 315 ierr = VecGetSubVector(X,rk->is_fast,&Xfast);CHKERRQ(ierr); 316 ierr = VecMAXPY(Xfast,s,w,rk->YdotRHS_fast);CHKERRQ(ierr); 317 ierr = VecRestoreSubVector(X,rk->is_fast,&Xfast);CHKERRQ(ierr); 318 } 319 PetscFunctionReturn(0); 320 } 321 322 static PetscErrorCode TSStepRefine_RK_MultirateSplit(TS ts) 323 { 324 TS_RK *rk = (TS_RK*)ts->data; 325 TS subts_fast = rk->subts_fast,currentlevelts; 326 TS_RK *subrk_fast = (TS_RK*)subts_fast->data; 327 RKTableau tab = rk->tableau; 328 Vec *Y = rk->Y; 329 Vec *YdotRHS = rk->YdotRHS,*YdotRHS_fast = rk->YdotRHS_fast; 330 Vec Yfast,Xfast; 331 const PetscInt s = tab->s; 332 const PetscReal *A = tab->A,*c = tab->c; 333 PetscScalar *w = rk->work; 334 PetscInt i,j,k; 335 PetscReal t = ts->ptime,h = ts->time_step; 336 PetscErrorCode ierr; 337 338 for (k=0; k<rk->dtratio; k++) { 339 ierr = VecGetSubVector(ts->vec_sol,rk->is_fast,&Xfast);CHKERRQ(ierr); 340 for (i=0; i<s; i++) { 341 ierr = VecGetSubVector(YdotRHS[i],rk->is_fast,&YdotRHS_fast[i]);CHKERRQ(ierr); 342 } 343 /* propogate fast component using small time steps */ 344 for (i=0; i<s; i++) { 345 /* stage value for slow components */ 346 ierr = TSInterpolate_RK_MultirateSplit(rk->ts_root,t+k*h/rk->dtratio+h/rk->dtratio*c[i],Y[i]);CHKERRQ(ierr); 347 currentlevelts = rk->ts_root; 348 while (currentlevelts != ts) { /* all the slow parts need to be interpolated separated */ 349 currentlevelts = ((TS_RK*)currentlevelts->data)->subts_fast; 350 ierr = TSInterpolate_RK_MultirateSplit(currentlevelts,t+k*h/rk->dtratio+h/rk->dtratio*c[i],Y[i]);CHKERRQ(ierr); 351 } 352 for (j=0; j<i; j++) w[j] = h/rk->dtratio*A[i*s+j]; 353 subrk_fast->stage_time = t + h/rk->dtratio*c[i]; 354 ierr = TSPreStage(subts_fast,subrk_fast->stage_time);CHKERRQ(ierr); 355 /* stage value for fast components */ 356 ierr = VecGetSubVector(Y[i],rk->is_fast,&Yfast);CHKERRQ(ierr); 357 ierr = VecCopy(Xfast,Yfast);CHKERRQ(ierr); 358 ierr = VecMAXPY(Yfast,i,w,YdotRHS_fast);CHKERRQ(ierr); 359 ierr = VecRestoreSubVector(Y[i],rk->is_fast,&Yfast);CHKERRQ(ierr); 360 ierr = TSPostStage(subts_fast,subrk_fast->stage_time,i,Y);CHKERRQ(ierr); 361 /* compute the stage RHS for fast components */ 362 ierr = TSComputeRHSFunction(subts_fast,t+k*h*rk->dtratio+h/rk->dtratio*c[i],Y[i],YdotRHS_fast[i]);CHKERRQ(ierr); 363 } 364 ierr = VecRestoreSubVector(ts->vec_sol,rk->is_fast,&Xfast);CHKERRQ(ierr); 365 /* update the value of fast components using fast time step */ 366 rk->slow = PETSC_FALSE; 367 ierr = TSEvaluateStep_RK_MultirateSplit(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 368 for (i=0; i<s; i++) { 369 ierr = VecRestoreSubVector(YdotRHS[i],rk->is_fast,&YdotRHS_fast[i]);CHKERRQ(ierr); 370 } 371 372 if (subrk_fast->subts_fast) { 373 subts_fast->ptime = t+k*h/rk->dtratio; 374 subts_fast->time_step = h/rk->dtratio; 375 ierr = TSStepRefine_RK_MultirateSplit(subts_fast);CHKERRQ(ierr); 376 } 377 /* update the fast components of the solution */ 378 ierr = VecGetSubVector(ts->vec_sol,rk->is_fast,&Xfast);CHKERRQ(ierr); 379 ierr = VecISCopy(rk->X0,rk->is_fast,SCATTER_FORWARD,Xfast);CHKERRQ(ierr); 380 ierr = VecRestoreSubVector(ts->vec_sol,rk->is_fast,&Xfast);CHKERRQ(ierr); 381 } 382 PetscFunctionReturn(0); 383 } 384 385 static PetscErrorCode TSStep_RK_MultirateSplit(TS ts) 386 { 387 TS_RK *rk = (TS_RK*)ts->data; 388 RKTableau tab = rk->tableau; 389 Vec *Y = rk->Y,*YdotRHS = rk->YdotRHS; 390 Vec *YdotRHS_fast = rk->YdotRHS_fast,*YdotRHS_slow = rk->YdotRHS_slow; 391 Vec Yslow,Yfast; /* subvectors store the stges of slow components and fast components respectively */ 392 const PetscInt s = tab->s; 393 const PetscReal *A = tab->A,*c = tab->c; 394 PetscScalar *w = rk->work; 395 PetscInt i,j; 396 PetscReal next_time_step = ts->time_step,t = ts->ptime,h = ts->time_step; 397 PetscErrorCode ierr; 398 399 PetscFunctionBegin; 400 rk->status = TS_STEP_INCOMPLETE; 401 for (i=0; i<s; i++) { 402 ierr = VecGetSubVector(YdotRHS[i],rk->is_slow,&YdotRHS_slow[i]);CHKERRQ(ierr); 403 ierr = VecGetSubVector(YdotRHS[i],rk->is_fast,&YdotRHS_fast[i]);CHKERRQ(ierr); 404 } 405 ierr = VecCopy(ts->vec_sol,rk->X0);CHKERRQ(ierr); 406 /* propogate both slow and fast components using large time steps */ 407 for (i=0; i<s; i++) { 408 rk->stage_time = t + h*c[i]; 409 ierr = TSPreStage(ts,rk->stage_time);CHKERRQ(ierr); 410 ierr = VecCopy(ts->vec_sol,Y[i]);CHKERRQ(ierr); 411 ierr = VecGetSubVector(Y[i],rk->is_fast,&Yfast);CHKERRQ(ierr); 412 ierr = VecGetSubVector(Y[i],rk->is_slow,&Yslow);CHKERRQ(ierr); 413 for (j=0; j<i; j++) w[j] = h*A[i*s+j]; 414 ierr = VecMAXPY(Yfast,i,w,YdotRHS_fast);CHKERRQ(ierr); 415 ierr = VecMAXPY(Yslow,i,w,YdotRHS_slow);CHKERRQ(ierr); 416 ierr = VecRestoreSubVector(Y[i],rk->is_fast,&Yfast);CHKERRQ(ierr); 417 ierr = VecRestoreSubVector(Y[i],rk->is_slow,&Yslow);CHKERRQ(ierr); 418 ierr = TSPostStage(ts,rk->stage_time,i,Y); CHKERRQ(ierr); 419 ierr = TSComputeRHSFunction(rk->subts_slow,t+h*c[i],Y[i],YdotRHS_slow[i]);CHKERRQ(ierr); 420 ierr = TSComputeRHSFunction(rk->subts_fast,t+h*c[i],Y[i],YdotRHS_fast[i]);CHKERRQ(ierr); 421 } 422 rk->slow = PETSC_TRUE; 423 /* update the slow components of the solution using slow time step */ 424 ierr = TSEvaluateStep_RK_MultirateSplit(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 425 /* YdotRHS will be used for interpolation during refinement */ 426 for (i=0; i<s; i++) { 427 ierr = VecRestoreSubVector(YdotRHS[i],rk->is_slow,&YdotRHS_slow[i]);CHKERRQ(ierr); 428 ierr = VecRestoreSubVector(YdotRHS[i],rk->is_fast,&YdotRHS_fast[i]);CHKERRQ(ierr); 429 } 430 431 ierr = TSStepRefine_RK_MultirateSplit(ts);CHKERRQ(ierr); 432 433 ts->ptime = t + ts->time_step; 434 ts->time_step = next_time_step; 435 rk->status = TS_STEP_COMPLETE; 436 PetscFunctionReturn(0); 437 } 438 439 static PetscErrorCode TSSetUp_RK_MultirateSplit(TS ts) 440 { 441 TS_RK *rk = (TS_RK*)ts->data,*nextlevelrk,*currentlevelrk; 442 TS nextlevelts; 443 Vec X0; 444 PetscErrorCode ierr; 445 446 PetscFunctionBegin; 447 ierr = TSRHSSplitGetIS(ts,"slow",&rk->is_slow);CHKERRQ(ierr); 448 ierr = TSRHSSplitGetIS(ts,"fast",&rk->is_fast);CHKERRQ(ierr); 449 if (!rk->is_slow || !rk->is_fast) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up RHSSplits with TSRHSSplitSetIS() using split names 'slow' and 'fast' respectively in order to use -ts_type bsi"); 450 ierr = TSRHSSplitGetSubTS(ts,"slow",&rk->subts_slow);CHKERRQ(ierr); 451 ierr = TSRHSSplitGetSubTS(ts,"fast",&rk->subts_fast);CHKERRQ(ierr); 452 if (!rk->subts_slow || !rk->subts_fast) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up the RHSFunctions for 'slow' and 'fast' components using TSRHSSplitSetRHSFunction() or calling TSSetRHSFunction() for each sub-TS"); 453 454 ierr = VecDuplicate(ts->vec_sol,&X0);CHKERRQ(ierr); 455 /* The TS at each level share the same tableau, work array, solution vector, stage values and stage derivatives */ 456 currentlevelrk = rk; 457 while (currentlevelrk->subts_fast) { 458 ierr = PetscMalloc1(rk->tableau->s,¤tlevelrk->YdotRHS_fast);CHKERRQ(ierr); 459 ierr = PetscMalloc1(rk->tableau->s,¤tlevelrk->YdotRHS_slow);CHKERRQ(ierr); 460 ierr = PetscObjectReference((PetscObject)X0);CHKERRQ(ierr); 461 currentlevelrk->X0 = X0; 462 currentlevelrk->ts_root = ts; 463 464 /* set up the ts for the slow part */ 465 nextlevelts = currentlevelrk->subts_slow; 466 ierr = PetscNewLog(nextlevelts,&nextlevelrk);CHKERRQ(ierr); 467 nextlevelrk->tableau = rk->tableau; 468 nextlevelrk->work = rk->work; 469 nextlevelrk->Y = rk->Y; 470 nextlevelrk->YdotRHS = rk->YdotRHS; 471 nextlevelts->data = (void*)nextlevelrk; 472 ierr = TSCopyDM(ts,nextlevelts);CHKERRQ(ierr); 473 ierr = TSSetSolution(nextlevelts,ts->vec_sol);CHKERRQ(ierr); 474 475 /* set up the ts for the fast part */ 476 nextlevelts = currentlevelrk->subts_fast; 477 ierr = PetscNewLog(nextlevelts,&nextlevelrk);CHKERRQ(ierr); 478 nextlevelrk->tableau = rk->tableau; 479 nextlevelrk->work = rk->work; 480 nextlevelrk->Y = rk->Y; 481 nextlevelrk->YdotRHS = rk->YdotRHS; 482 nextlevelrk->dtratio = rk->dtratio; 483 ierr = TSRHSSplitGetIS(nextlevelts,"slow",&nextlevelrk->is_slow);CHKERRQ(ierr); 484 ierr = TSRHSSplitGetSubTS(nextlevelts,"slow",&nextlevelrk->subts_slow);CHKERRQ(ierr); 485 ierr = TSRHSSplitGetIS(nextlevelts,"fast",&nextlevelrk->is_fast);CHKERRQ(ierr); 486 ierr = TSRHSSplitGetSubTS(nextlevelts,"fast",&nextlevelrk->subts_fast);CHKERRQ(ierr); 487 nextlevelts->data = (void*)nextlevelrk; 488 ierr = TSCopyDM(ts,nextlevelts);CHKERRQ(ierr); 489 ierr = TSSetSolution(nextlevelts,ts->vec_sol);CHKERRQ(ierr); 490 491 currentlevelrk = nextlevelrk; 492 } 493 ierr = VecDestroy(&X0);CHKERRQ(ierr); 494 495 ts->ops->step = TSStep_RK_MultirateSplit; 496 ts->ops->evaluatestep = TSEvaluateStep_RK_MultirateSplit; 497 ts->ops->interpolate = TSInterpolate_RK_MultirateSplit; 498 PetscFunctionReturn(0); 499 } 500 501 PetscErrorCode TSRKSetMultirate_RK(TS ts,PetscBool use_multirate) 502 { 503 TS_RK *rk = (TS_RK*)ts->data; 504 PetscErrorCode ierr; 505 506 PetscFunctionBegin; 507 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 508 rk->use_multirate = use_multirate; 509 if (use_multirate) { 510 rk->dtratio = 2; 511 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSetUp_RK_MultirateSplit_C",TSSetUp_RK_MultirateSplit);CHKERRQ(ierr); 512 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSReset_RK_MultirateSplit_C",TSReset_RK_MultirateSplit);CHKERRQ(ierr); 513 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSetUp_RK_MultirateNonsplit_C",TSSetUp_RK_MultirateNonsplit);CHKERRQ(ierr); 514 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSReset_RK_MultirateNonsplit_C",TSReset_RK_MultirateNonsplit);CHKERRQ(ierr); 515 } else { 516 rk->dtratio = 0; 517 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSetUp_RK_MultirateSplit_C",NULL);CHKERRQ(ierr); 518 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSReset_RK_MultirateSplit_C",NULL);CHKERRQ(ierr); 519 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSetUp_RK_MultirateNonsplit_C",NULL);CHKERRQ(ierr); 520 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSReset_RK_MultirateNonsplit_C",NULL);CHKERRQ(ierr); 521 } 522 PetscFunctionReturn(0); 523 } 524 525 PetscErrorCode TSRKGetMultirate_RK(TS ts,PetscBool *use_multirate) 526 { 527 TS_RK *rk = (TS_RK*)ts->data; 528 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 531 *use_multirate = rk->use_multirate; 532 PetscFunctionReturn(0); 533 } 534