14b84eec9SHong Zhang /* 2f944a40eSHong Zhang Code for time stepping with the Multirate Partitioned Runge-Kutta method 34b84eec9SHong Zhang 44b84eec9SHong Zhang Notes: 54b84eec9SHong Zhang 1) The general system is written as 6f944a40eSHong Zhang Udot = F(t,U) 7f944a40eSHong Zhang if one does not split the RHS function, but gives the indexes for both slow and fast components; 84b84eec9SHong Zhang 2) The general system is written as 94b84eec9SHong Zhang Usdot = Fs(t,Us,Uf) 10f944a40eSHong Zhang Ufdot = Ff(t,Us,Uf) 11f944a40eSHong Zhang for component-wise partitioned system, 12f944a40eSHong Zhang users should split the RHS function themselves and also provide the indexes for both slow and fast components. 1319c2959aSHong Zhang 3) To correct The confusing terminology in the paper, we use 'slow method', 'slow buffer method' and 'fast method' to denote the methods applied to 'slow region', 'slow buffer region' and 'fast region' respectively. The 'slow method' in the original paper actually means the 'slow buffer method'. 1419c2959aSHong Zhang 4) Why does the buffer region have to be inside the slow region? The buffer region is treated with a slow method essentially. Applying the slow method to a region with a fast characteristic time scale is apparently not a good choice. 1519c2959aSHong Zhang 1619c2959aSHong Zhang Reference: 1719c2959aSHong Zhang Emil M. Constantinescu, Adrian Sandu, Multirate Timestepping Methods for Hyperbolic Conservation Laws, Journal of Scientific Computing 2007 184b84eec9SHong Zhang */ 194b84eec9SHong Zhang 204b84eec9SHong Zhang #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 214b84eec9SHong Zhang #include <petscdm.h> 224b84eec9SHong Zhang 2319c2959aSHong Zhang static TSMPRKType TSMPRKDefault = TSMPRK2A22; 244b84eec9SHong Zhang static PetscBool TSMPRKRegisterAllCalled; 254b84eec9SHong Zhang static PetscBool TSMPRKPackageInitialized; 264b84eec9SHong Zhang 274b84eec9SHong Zhang typedef struct _MPRKTableau *MPRKTableau; 284b84eec9SHong Zhang struct _MPRKTableau { 294b84eec9SHong Zhang char *name; 304b84eec9SHong Zhang PetscInt order; /* Classical approximation order of the method i */ 3179bc8a77SHong Zhang PetscInt sbase; /* Number of stages in the base method*/ 324b84eec9SHong Zhang PetscInt s; /* Number of stages */ 3319c2959aSHong Zhang PetscInt np; /* Number of partitions */ 344b84eec9SHong Zhang PetscReal *Af, *bf, *cf; /* Tableau for fast components */ 3519c2959aSHong Zhang PetscReal *Amb, *bmb, *cmb; /* Tableau for medium components */ 3619c2959aSHong Zhang PetscInt *rmb; /* Array of flags for repeated stages in medium method */ 3719c2959aSHong Zhang PetscReal *Asb, *bsb, *csb; /* Tableau for slow components */ 3819c2959aSHong Zhang PetscInt *rsb; /* Array of flags for repeated staged in slow method*/ 394b84eec9SHong Zhang }; 404b84eec9SHong Zhang typedef struct _MPRKTableauLink *MPRKTableauLink; 414b84eec9SHong Zhang struct _MPRKTableauLink { 424b84eec9SHong Zhang struct _MPRKTableau tab; 434b84eec9SHong Zhang MPRKTableauLink next; 444b84eec9SHong Zhang }; 454b84eec9SHong Zhang static MPRKTableauLink MPRKTableauList; 464b84eec9SHong Zhang 474b84eec9SHong Zhang typedef struct { 484b84eec9SHong Zhang MPRKTableau tableau; 494b84eec9SHong Zhang Vec *Y; /* States computed during the step */ 507c0df07dSHong Zhang Vec *YdotRHS; 514b84eec9SHong Zhang Vec *YdotRHS_slow; /* Function evaluations by slow tableau for slow components */ 5219c2959aSHong Zhang Vec *YdotRHS_slowbuffer; /* Function evaluations by slow tableau for slow components */ 5319c2959aSHong Zhang Vec *YdotRHS_medium; /* Function evaluations by slow tableau for slow components */ 5419c2959aSHong Zhang Vec *YdotRHS_mediumbuffer; /* Function evaluations by slow tableau for slow components */ 5519c2959aSHong Zhang Vec *YdotRHS_fast; /* Function evaluations by fast tableau for fast components */ 564b84eec9SHong Zhang PetscScalar *work_slow; /* Scalar work_slow by slow tableau */ 5719c2959aSHong Zhang PetscScalar *work_slowbuffer; /* Scalar work_slow by slow tableau */ 5819c2959aSHong Zhang PetscScalar *work_medium; /* Scalar work_slow by medium tableau */ 5919c2959aSHong Zhang PetscScalar *work_mediumbuffer; /* Scalar work_slow by medium tableau */ 6019c2959aSHong Zhang PetscScalar *work_fast; /* Scalar work_fast by fast tableau */ 614b84eec9SHong Zhang PetscReal stage_time; 624b84eec9SHong Zhang TSStepStatus status; 634b84eec9SHong Zhang PetscReal ptime; 644b84eec9SHong Zhang PetscReal time_step; 6519c2959aSHong Zhang IS is_slow, is_slowbuffer, is_medium, is_mediumbuffer, is_fast; 6619c2959aSHong Zhang TS subts_slow, subts_slowbuffer, subts_medium, subts_mediumbuffer, subts_fast; 674b84eec9SHong Zhang } TS_MPRK; 684b84eec9SHong Zhang 69d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKGenerateTableau2(PetscInt ratio, PetscInt s, const PetscReal Abase[], const PetscReal bbase[], PetscReal A1[], PetscReal b1[], PetscReal A2[], PetscReal b2[]) 70d71ae5a4SJacob Faibussowitsch { 7119c2959aSHong Zhang PetscInt i, j, k, l; 7219c2959aSHong Zhang 7319c2959aSHong Zhang PetscFunctionBegin; 7419c2959aSHong Zhang for (k = 0; k < ratio; k++) { 7519c2959aSHong Zhang /* diagonal blocks */ 7619c2959aSHong Zhang for (i = 0; i < s; i++) 7719c2959aSHong Zhang for (j = 0; j < s; j++) { 7819c2959aSHong Zhang A1[(k * s + i) * ratio * s + k * s + j] = Abase[i * s + j]; 7919c2959aSHong Zhang A2[(k * s + i) * ratio * s + k * s + j] = Abase[i * s + j] / ratio; 8019c2959aSHong Zhang } 8119c2959aSHong Zhang /* off diagonal blocks */ 8219c2959aSHong Zhang for (l = 0; l < k; l++) 8319c2959aSHong Zhang for (i = 0; i < s; i++) 849371c9d4SSatish Balay for (j = 0; j < s; j++) A2[(k * s + i) * ratio * s + l * s + j] = bbase[j] / ratio; 8519c2959aSHong Zhang for (j = 0; j < s; j++) { 8619c2959aSHong Zhang b1[k * s + j] = bbase[j] / ratio; 8719c2959aSHong Zhang b2[k * s + j] = bbase[j] / ratio; 8819c2959aSHong Zhang } 8919c2959aSHong Zhang } 903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9119c2959aSHong Zhang } 9219c2959aSHong Zhang 93d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKGenerateTableau3(PetscInt ratio, PetscInt s, const PetscReal Abase[], const PetscReal bbase[], PetscReal A1[], PetscReal b1[], PetscReal A2[], PetscReal b2[], PetscReal A3[], PetscReal b3[]) 94d71ae5a4SJacob Faibussowitsch { 9519c2959aSHong Zhang PetscInt i, j, k, l, m, n; 9619c2959aSHong Zhang 9719c2959aSHong Zhang PetscFunctionBegin; 9819c2959aSHong Zhang for (k = 0; k < ratio; k++) { /* diagonal blocks of size ratio*s by ratio*s */ 9919c2959aSHong Zhang for (l = 0; l < ratio; l++) /* diagonal sub-blocks of size s by s */ 10019c2959aSHong Zhang for (i = 0; i < s; i++) 10119c2959aSHong Zhang for (j = 0; j < s; j++) { 10219c2959aSHong Zhang A1[((k * ratio + l) * s + i) * ratio * ratio * s + (k * ratio + l) * s + j] = Abase[i * s + j]; 10319c2959aSHong Zhang A2[((k * ratio + l) * s + i) * ratio * ratio * s + (k * ratio + l) * s + j] = Abase[i * s + j] / ratio; 10419c2959aSHong Zhang A3[((k * ratio + l) * s + i) * ratio * ratio * s + (k * ratio + l) * s + j] = Abase[i * s + j] / ratio / ratio; 10519c2959aSHong Zhang } 10619c2959aSHong Zhang for (l = 0; l < k; l++) /* off-diagonal blocks of size ratio*s by ratio*s */ 10719c2959aSHong Zhang for (m = 0; m < ratio; m++) 10819c2959aSHong Zhang for (n = 0; n < ratio; n++) 10919c2959aSHong Zhang for (i = 0; i < s; i++) 11019c2959aSHong Zhang for (j = 0; j < s; j++) { 11119c2959aSHong Zhang A2[((k * ratio + m) * s + i) * ratio * ratio * s + (l * ratio + n) * s + j] = bbase[j] / ratio / ratio; 11219c2959aSHong Zhang A3[((k * ratio + m) * s + i) * ratio * ratio * s + (l * ratio + n) * s + j] = bbase[j] / ratio / ratio; 11319c2959aSHong Zhang } 11419c2959aSHong Zhang for (m = 0; m < ratio; m++) 11519c2959aSHong Zhang for (n = 0; n < m; n++) /* off-diagonal sub-blocks of size s by s in the diagonal blocks */ 11619c2959aSHong Zhang for (i = 0; i < s; i++) 1179371c9d4SSatish Balay for (j = 0; j < s; j++) A3[((k * ratio + m) * s + i) * ratio * ratio * s + (k * ratio + n) * s + j] = bbase[j] / ratio / ratio; 11819c2959aSHong Zhang for (n = 0; n < ratio; n++) 11919c2959aSHong Zhang for (j = 0; j < s; j++) { 12019c2959aSHong Zhang b1[(k * ratio + n) * s + j] = bbase[j] / ratio / ratio; 12119c2959aSHong Zhang b2[(k * ratio + n) * s + j] = bbase[j] / ratio / ratio; 12219c2959aSHong Zhang b3[(k * ratio + n) * s + j] = bbase[j] / ratio / ratio; 12319c2959aSHong Zhang } 12419c2959aSHong Zhang } 1253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12619c2959aSHong Zhang } 12719c2959aSHong Zhang 1284b84eec9SHong Zhang /*MC 129f944a40eSHong Zhang TSMPRK2A22 - Second Order Multirate Partitioned Runge Kutta scheme based on RK2A. 1304b84eec9SHong Zhang 13119c2959aSHong Zhang This method has four stages for slow and fast parts. The refinement factor of the stepsize is 2. 13219c2959aSHong Zhang r = 2, np = 2 133147403d9SBarry Smith 134bcf0153eSBarry Smith Options Database Key: 135147403d9SBarry Smith . -ts_mprk_type 2a22 - select this scheme 1364b84eec9SHong Zhang 1374b84eec9SHong Zhang Level: advanced 1384b84eec9SHong Zhang 139*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 1404b84eec9SHong Zhang M*/ 1414b84eec9SHong Zhang /*MC 142f944a40eSHong Zhang TSMPRK2A23 - Second Order Multirate Partitioned Runge-Kutta scheme based on RK2A. 14319c2959aSHong Zhang 14419c2959aSHong Zhang This method has eight stages for slow and medium and fast parts. The refinement factor of the stepsize is 2. 14519c2959aSHong Zhang r = 2, np = 3 146147403d9SBarry Smith 147bcf0153eSBarry Smith Options Database Key: 148147403d9SBarry Smith . -ts_mprk_type 2a23 - select this scheme 14919c2959aSHong Zhang 15019c2959aSHong Zhang Level: advanced 15119c2959aSHong Zhang 152*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 15319c2959aSHong Zhang M*/ 15419c2959aSHong Zhang /*MC 155f944a40eSHong Zhang TSMPRK2A32 - Second Order Multirate Partitioned Runge-Kutta scheme based on RK2A. 15619c2959aSHong Zhang 15719c2959aSHong Zhang This method has four stages for slow and fast parts. The refinement factor of the stepsize is 3. 15819c2959aSHong Zhang r = 3, np = 2 159147403d9SBarry Smith 160bcf0153eSBarry Smith Options Database Key: 161147403d9SBarry Smith . -ts_mprk_type 2a32 - select this scheme 16219c2959aSHong Zhang 16319c2959aSHong Zhang Level: advanced 16419c2959aSHong Zhang 165*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 16619c2959aSHong Zhang M*/ 16719c2959aSHong Zhang /*MC 168f944a40eSHong Zhang TSMPRK2A33 - Second Order Multirate Partitioned Runge-Kutta scheme based on RK2A. 16919c2959aSHong Zhang 17019c2959aSHong Zhang This method has eight stages for slow and medium and fast parts. The refinement factor of the stepsize is 3. 17119c2959aSHong Zhang r = 3, np = 3 172147403d9SBarry Smith 173bcf0153eSBarry Smith Options Database Key: 174147403d9SBarry Smith . -ts_mprk_type 2a33- select this scheme 17519c2959aSHong Zhang 17619c2959aSHong Zhang Level: advanced 17719c2959aSHong Zhang 178*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 17919c2959aSHong Zhang M*/ 18019c2959aSHong Zhang /*MC 181f944a40eSHong Zhang TSMPRK3P2M - Third Order Multirate Partitioned Runge-Kutta scheme. 1824b84eec9SHong Zhang 1834b84eec9SHong Zhang This method has eight stages for both slow and fast parts. 1844b84eec9SHong Zhang 185bcf0153eSBarry Smith Options Database Key: 186147403d9SBarry Smith . -ts_mprk_type pm3 - select this scheme 1874b84eec9SHong Zhang 1884b84eec9SHong Zhang Level: advanced 1894b84eec9SHong Zhang 190*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 1914b84eec9SHong Zhang M*/ 1924b84eec9SHong Zhang /*MC 193f944a40eSHong Zhang TSMPRKP2 - Second Order Multirate Partitioned Runge-Kutta scheme. 1944b84eec9SHong Zhang 1954b84eec9SHong Zhang This method has five stages for both slow and fast parts. 1964b84eec9SHong Zhang 197bcf0153eSBarry Smith Options Database Key: 198147403d9SBarry Smith . -ts_mprk_type p2 - select this scheme 1994b84eec9SHong Zhang 2004b84eec9SHong Zhang Level: advanced 2014b84eec9SHong Zhang 202*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 2034b84eec9SHong Zhang M*/ 2044b84eec9SHong Zhang /*MC 205f944a40eSHong Zhang TSMPRKP3 - Third Order Multirate Partitioned Runge-Kutta scheme. 2064b84eec9SHong Zhang 2074b84eec9SHong Zhang This method has ten stages for both slow and fast parts. 2084b84eec9SHong Zhang 209bcf0153eSBarry Smith Options Database Key: 210147403d9SBarry Smith . -ts_mprk_type p3 - select this scheme 2114b84eec9SHong Zhang 2124b84eec9SHong Zhang Level: advanced 2134b84eec9SHong Zhang 214*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKType`, `TSMPRKSetType()` 2154b84eec9SHong Zhang M*/ 2164b84eec9SHong Zhang 2174b84eec9SHong Zhang /*@C 218d5b43468SJose E. Roman TSMPRKRegisterAll - Registers all of the Partitioned Runge-Kutta explicit methods in `TSMPRK` 2194b84eec9SHong Zhang 2204b84eec9SHong Zhang Not Collective, but should be called by all processes which will need the schemes to be registered 2214b84eec9SHong Zhang 2224b84eec9SHong Zhang Level: advanced 2234b84eec9SHong Zhang 224*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKRegisterDestroy()` 2254b84eec9SHong Zhang @*/ 226d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKRegisterAll(void) 227d71ae5a4SJacob Faibussowitsch { 2284b84eec9SHong Zhang PetscFunctionBegin; 2293ba16761SJacob Faibussowitsch if (TSMPRKRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 2304b84eec9SHong Zhang TSMPRKRegisterAllCalled = PETSC_TRUE; 2314b84eec9SHong Zhang 2324b84eec9SHong Zhang #define RC PetscRealConstant 2334b84eec9SHong Zhang { 2349371c9d4SSatish Balay const PetscReal Abase[2][2] = 2359371c9d4SSatish Balay { 2369371c9d4SSatish Balay {0, 0}, 2379371c9d4SSatish Balay {RC(1.0), 0} 2389371c9d4SSatish Balay }, 23919c2959aSHong Zhang bbase[2] = {RC(0.5), RC(0.5)}; 2409371c9d4SSatish Balay PetscReal Asb[4][4] = {{0}}, Af[4][4] = {{0}}, bsb[4] = {0}, bf[4] = {0}; 2419371c9d4SSatish Balay PetscInt rsb[4] = {0, 0, 1, 2}; 2429566063dSJacob Faibussowitsch PetscCall(TSMPRKGenerateTableau2(2, 2, &Abase[0][0], bbase, &Asb[0][0], bsb, &Af[0][0], bf)); 2439566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRK2A22, 2, 2, 2, 1, &Asb[0][0], bsb, NULL, rsb, NULL, NULL, NULL, NULL, &Af[0][0], bf, NULL)); 2444b84eec9SHong Zhang } 24519c2959aSHong Zhang { 2469371c9d4SSatish Balay const PetscReal Abase[2][2] = 2479371c9d4SSatish Balay { 2489371c9d4SSatish Balay {0, 0}, 2499371c9d4SSatish Balay {RC(1.0), 0} 2509371c9d4SSatish Balay }, 25119c2959aSHong Zhang bbase[2] = {RC(0.5), RC(0.5)}; 2529371c9d4SSatish Balay PetscReal Asb[8][8] = {{0}}, Amb[8][8] = {{0}}, Af[8][8] = {{0}}, bsb[8] = {0}, bmb[8] = {0}, bf[8] = {0}; 2539371c9d4SSatish Balay PetscInt rsb[8] = {0, 0, 1, 2, 1, 2, 1, 2}, rmb[8] = {0, 0, 1, 2, 0, 0, 5, 6}; 2549566063dSJacob Faibussowitsch PetscCall(TSMPRKGenerateTableau3(2, 2, &Abase[0][0], bbase, &Asb[0][0], bsb, &Amb[0][0], bmb, &Af[0][0], bf)); 2559566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRK2A23, 2, 2, 2, 2, &Asb[0][0], bsb, NULL, rsb, &Amb[0][0], bmb, NULL, rmb, &Af[0][0], bf, NULL)); 25619c2959aSHong Zhang } 25719c2959aSHong Zhang { 2589371c9d4SSatish Balay const PetscReal Abase[2][2] = 2599371c9d4SSatish Balay { 2609371c9d4SSatish Balay {0, 0}, 2619371c9d4SSatish Balay {RC(1.0), 0} 2629371c9d4SSatish Balay }, 26319c2959aSHong Zhang bbase[2] = {RC(0.5), RC(0.5)}; 2649371c9d4SSatish Balay PetscReal Asb[6][6] = {{0}}, Af[6][6] = {{0}}, bsb[6] = {0}, bf[6] = {0}; 2659371c9d4SSatish Balay PetscInt rsb[6] = {0, 0, 1, 2, 1, 2}; 2669566063dSJacob Faibussowitsch PetscCall(TSMPRKGenerateTableau2(3, 2, &Abase[0][0], bbase, &Asb[0][0], bsb, &Af[0][0], bf)); 2679566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRK2A32, 2, 2, 3, 1, &Asb[0][0], bsb, NULL, rsb, NULL, NULL, NULL, NULL, &Af[0][0], bf, NULL)); 26819c2959aSHong Zhang } 26919c2959aSHong Zhang { 2709371c9d4SSatish Balay const PetscReal Abase[2][2] = 2719371c9d4SSatish Balay { 2729371c9d4SSatish Balay {0, 0}, 2739371c9d4SSatish Balay {RC(1.0), 0} 2749371c9d4SSatish Balay }, 27519c2959aSHong Zhang bbase[2] = {RC(0.5), RC(0.5)}; 2769371c9d4SSatish Balay PetscReal Asb[18][18] = {{0}}, Amb[18][18] = {{0}}, Af[18][18] = {{0}}, bsb[18] = {0}, bmb[18] = {0}, bf[18] = {0}; 2779371c9d4SSatish Balay PetscInt rsb[18] = {0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}, rmb[18] = {0, 0, 1, 2, 1, 2, 0, 0, 7, 8, 7, 8, 0, 0, 13, 14, 13, 14}; 2789566063dSJacob Faibussowitsch PetscCall(TSMPRKGenerateTableau3(3, 2, &Abase[0][0], bbase, &Asb[0][0], bsb, &Amb[0][0], bmb, &Af[0][0], bf)); 2799566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRK2A33, 2, 2, 3, 3, &Asb[0][0], bsb, NULL, rsb, &Amb[0][0], bmb, NULL, rmb, &Af[0][0], bf, NULL)); 28019c2959aSHong Zhang } 28119c2959aSHong Zhang /* 28219c2959aSHong Zhang PetscReal 28319c2959aSHong Zhang Asb[8][8] = {{Abase[0][0],Abase[0][1],0,0,0,0,0,0}, 28419c2959aSHong Zhang {Abase[1][0],Abase[1][1],0,0,0,0,0,0}, 28519c2959aSHong Zhang {0,0,Abase[0][0],Abase[0][1],0,0,0,0}, 28619c2959aSHong Zhang {0,0,Abase[1][0],Abase[1][1],0,0,0,0}, 28719c2959aSHong Zhang {0,0,0,0,Abase[0][0],Abase[0][1],0,0}, 28819c2959aSHong Zhang {0,0,0,0,Abase[1][0],Abase[1][1],0,0}, 28919c2959aSHong Zhang {0,0,0,0,0,0,Abase[0][0],Abase[0][1]}, 29019c2959aSHong Zhang {0,0,0,0,0,0,Abase[1][0],Abase[1][1]}}, 29119c2959aSHong Zhang Amb[8][8] = {{Abase[0][0]/m,Abase[0][1]/m,0,0,0,0,0,0}, 29219c2959aSHong Zhang {Abase[1][0]/m,Abase[1][1]/m,0,0,0,0,0,0}, 29319c2959aSHong Zhang {0,0,Abase[0][0]/m,Abase[0][1]/m,0,0,0,0}, 29419c2959aSHong Zhang {0,0,Abase[1][0]/m,Abase[1][1]/m,0,0,0,0}, 29519c2959aSHong Zhang {bbase[0]/m,bbase[1]/m,bbase[0]/m,bbase[1]/m,Abase[0][0]/m,Abase[0][1]/m,0,0}, 29619c2959aSHong Zhang {bbase[0]/m,bbase[1]/m,bbase[0]/m,bbase[1]/m,Abase[1][0]/m,Abase[1][1]/m,0,0}, 29719c2959aSHong Zhang {bbase[0]/m,bbase[1]/m,bbase[0]/m,bbase[1]/m,0,0,Abase[0][0]/m,Abase[0][1]/m}, 29819c2959aSHong Zhang {bbase[0]/m,bbase[1]/m,bbase[0]/m,bbase[1]/m,0,0,Abase[1][0]/m,Abase[1][1]/m}}, 29919c2959aSHong Zhang Af[8][8] = {{Abase[0][0]/m/m,Abase[0][1]/m/m,0,0,0,0,0,0}, 30019c2959aSHong Zhang {Abase[1][0]/m/m,Abase[1][1]/m/m,0,0,0,0,0,0}, 30119c2959aSHong Zhang {0,0,Abase[0][0]/m/m,Abase[0][1]/m/m,0,0,0,0}, 30219c2959aSHong Zhang {0,0,Abase[1][0]/m/m,Abase[1][1]/m/m,0,0,0,0}, 30319c2959aSHong Zhang {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,Abase[0][0]/m/m,Abase[0][1]/m/m,0,0}, 30419c2959aSHong Zhang {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,Abase[1][0]/m/m,Abase[1][1]/m/m,0,0}, 30519c2959aSHong Zhang {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,Abase[0][0]/m,Abase[0][1]/m}, 30619c2959aSHong Zhang {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,Abase[1][0]/m,Abase[1][1]/m}}, 30719c2959aSHong Zhang bsb[8] = {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m}, 30819c2959aSHong Zhang bmb[8] = {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m,bbase[1]/m/m}, 30919c2959aSHong Zhang bf[8] = {bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m/m,bbase[0]/m/m,bbase[1]/m,bbase[0]/m/m,bbase[1]/m/m}, 31019c2959aSHong Zhang */ 3114b84eec9SHong Zhang /*{ 3124b84eec9SHong Zhang const PetscReal 3134b84eec9SHong Zhang As[8][8] = {{0,0,0,0,0,0,0,0}, 3144b84eec9SHong Zhang {RC(1.0)/RC(2.0),0,0,0,0,0,0,0}, 3154b84eec9SHong Zhang {RC(-1.0)/RC(6.0),RC(2.0)/RC(3.0),0,0,0,0,0,0}, 3164b84eec9SHong Zhang {RC(1.0)/RC(3.0),RC(-1.0)/RC(3.0),RC(1.0),0,0,0,0,0}, 3174b84eec9SHong Zhang {0,0,0,0,0,0,0,0}, 3184b84eec9SHong Zhang {0,0,0,0,RC(1.0)/RC(2.0),0,0,0}, 3194b84eec9SHong Zhang {0,0,0,0,RC(-1.0)/RC(6.0),RC(2.0)/RC(3.0),0,0}, 3204b84eec9SHong Zhang {0,0,0,0,RC(1.0)/RC(3.0),RC(-1.0)/RC(3.0),RC(1.0),0}}, 3214b84eec9SHong Zhang A[8][8] = {{0,0,0,0,0,0,0,0}, 3224b84eec9SHong Zhang {RC(1.0)/RC(4.0),0,0,0,0,0,0,0}, 3234b84eec9SHong Zhang {RC(-1.0)/RC(12.0),RC(1.0)/RC(3.0),0,0,0,0,0,0}, 3244b84eec9SHong Zhang {RC(1.0)/RC(6.0),RC(-1.0)/RC(6.0),RC(1.0)/RC(2.0),0,0,0,0,0}, 3254b84eec9SHong Zhang {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),0,0,0,0}, 3264b84eec9SHong Zhang {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),RC(1.0)/RC(4.0),0,0,0}, 3274b84eec9SHong Zhang {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),RC(-1.0)/RC(12.0),RC(1.0)/RC(3.0),0,0}, 3284b84eec9SHong Zhang {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(-1.0)/RC(6.0),RC(1.0)/RC(2.0),0}}, 3294b84eec9SHong Zhang bs[8] = {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0)}, 3304b84eec9SHong Zhang b[8] = {RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0),RC(1.0)/RC(12.0),RC(1.0)/RC(6.0),RC(1.0)/RC(6.0),RC(1.0)/RC(12.0)}; 3319566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRKPM3,3,8,&As[0][0],bs,NULL,&A[0][0],b,NULL)); 3324b84eec9SHong Zhang }*/ 3334b84eec9SHong Zhang 3344b84eec9SHong Zhang { 3359371c9d4SSatish Balay const PetscReal Asb[5][5] = 3369371c9d4SSatish Balay { 3379371c9d4SSatish Balay {0, 0, 0, 0, 0}, 3384b84eec9SHong Zhang {RC(1.0) / RC(2.0), 0, 0, 0, 0}, 3394b84eec9SHong Zhang {RC(1.0) / RC(2.0), 0, 0, 0, 0}, 3404b84eec9SHong Zhang {RC(1.0), 0, 0, 0, 0}, 3419371c9d4SSatish Balay {RC(1.0), 0, 0, 0, 0} 3429371c9d4SSatish Balay }, 3439371c9d4SSatish Balay Af[5][5] = {{0, 0, 0, 0, 0}, {RC(1.0) / RC(2.0), 0, 0, 0, 0}, {RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), 0, 0, 0}, {RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), RC(1.0) / RC(2.0), 0, 0}, {RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), 0}}, bsb[5] = {RC(1.0) / RC(2.0), 0, 0, 0, RC(1.0) / RC(2.0)}, bf[5] = {RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), RC(1.0) / RC(4.0), 0}; 3449371c9d4SSatish Balay const PetscInt rsb[5] = {0, 0, 2, 0, 4}; 3459566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRKP2, 2, 5, 1, 1, &Asb[0][0], bsb, NULL, rsb, NULL, NULL, NULL, NULL, &Af[0][0], bf, NULL)); 3464b84eec9SHong Zhang } 3474b84eec9SHong Zhang 3484b84eec9SHong Zhang { 3499371c9d4SSatish Balay const PetscReal Asb[10][10] = 3509371c9d4SSatish Balay { 3519371c9d4SSatish Balay {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3524b84eec9SHong Zhang {RC(1.0) / RC(4.0), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3534b84eec9SHong Zhang {RC(1.0) / RC(4.0), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3544b84eec9SHong Zhang {RC(1.0) / RC(2.0), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3554b84eec9SHong Zhang {RC(1.0) / RC(2.0), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3564b84eec9SHong Zhang {RC(-1.0) / RC(6.0), 0, 0, 0, RC(2.0) / RC(3.0), 0, 0, 0, 0, 0}, 3574b84eec9SHong Zhang {RC(1.0) / RC(12.0), 0, 0, 0, RC(1.0) / RC(6.0), RC(1.0) / RC(2.0), 0, 0, 0, 0}, 3584b84eec9SHong Zhang {RC(1.0) / RC(12.0), 0, 0, 0, RC(1.0) / RC(6.0), RC(1.0) / RC(2.0), 0, 0, 0, 0}, 3594b84eec9SHong Zhang {RC(1.0) / RC(3.0), 0, 0, 0, RC(-1.0) / RC(3.0), RC(1.0), 0, 0, 0, 0}, 3609371c9d4SSatish Balay {RC(1.0) / RC(3.0), 0, 0, 0, RC(-1.0) / RC(3.0), RC(1.0), 0, 0, 0, 0} 3619371c9d4SSatish Balay }, 3629371c9d4SSatish Balay Af[10][10] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {RC(1.0) / RC(4.0), 0, 0, 0, 0, 0, 0, 0, 0, 0}, {RC(-1.0) / RC(12.0), RC(1.0) / RC(3.0), 0, 0, 0, 0, 0, 0, 0, 0}, {RC(1.0) / RC(6.0), RC(-1.0) / RC(6.0), RC(1.0) / RC(2.0), 0, 0, 0, 0, 0, 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, 0, 0, 0, 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, 0, 0, 0, 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, RC(1.0) / RC(4.0), 0, 0, 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, RC(-1.0) / RC(12.0), RC(1.0) / RC(3.0), 0, 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, RC(1.0) / RC(6.0), RC(-1.0) / RC(6.0), RC(1.0) / RC(2.0), 0, 0}, {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0}}, bsb[10] = {RC(1.0) / RC(6.0), 0, 0, 0, RC(1.0) / RC(3.0), RC(1.0) / RC(3.0), 0, 0, 0, RC(1.0) / RC(6.0)}, bf[10] = {RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0, RC(1.0) / RC(12.0), RC(1.0) / RC(6.0), RC(1.0) / RC(6.0), RC(1.0) / RC(12.0), 0}; 3639371c9d4SSatish Balay const PetscInt rsb[10] = {0, 0, 2, 0, 4, 0, 0, 7, 0, 9}; 3649566063dSJacob Faibussowitsch PetscCall(TSMPRKRegister(TSMPRKP3, 3, 5, 2, 1, &Asb[0][0], bsb, NULL, rsb, NULL, NULL, NULL, NULL, &Af[0][0], bf, NULL)); 3654b84eec9SHong Zhang } 3664b84eec9SHong Zhang #undef RC 3673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3684b84eec9SHong Zhang } 3694b84eec9SHong Zhang 3704b84eec9SHong Zhang /*@C 371bcf0153eSBarry Smith TSMPRKRegisterDestroy - Frees the list of schemes that were registered by `TSMPRKRegister()`. 3724b84eec9SHong Zhang 3734b84eec9SHong Zhang Not Collective 3744b84eec9SHong Zhang 3754b84eec9SHong Zhang Level: advanced 3764b84eec9SHong Zhang 377*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `TSMPRKRegister()`, `TSMPRKRegisterAll()` 3784b84eec9SHong Zhang @*/ 379d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKRegisterDestroy(void) 380d71ae5a4SJacob Faibussowitsch { 3814b84eec9SHong Zhang MPRKTableauLink link; 3824b84eec9SHong Zhang 3834b84eec9SHong Zhang PetscFunctionBegin; 3844b84eec9SHong Zhang while ((link = MPRKTableauList)) { 3854b84eec9SHong Zhang MPRKTableau t = &link->tab; 3864b84eec9SHong Zhang MPRKTableauList = link->next; 3879566063dSJacob Faibussowitsch PetscCall(PetscFree3(t->Asb, t->bsb, t->csb)); 3889566063dSJacob Faibussowitsch PetscCall(PetscFree3(t->Amb, t->bmb, t->cmb)); 3899566063dSJacob Faibussowitsch PetscCall(PetscFree3(t->Af, t->bf, t->cf)); 3909566063dSJacob Faibussowitsch PetscCall(PetscFree(t->rsb)); 3919566063dSJacob Faibussowitsch PetscCall(PetscFree(t->rmb)); 3929566063dSJacob Faibussowitsch PetscCall(PetscFree(t->name)); 3939566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 3944b84eec9SHong Zhang } 3954b84eec9SHong Zhang TSMPRKRegisterAllCalled = PETSC_FALSE; 3963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3974b84eec9SHong Zhang } 3984b84eec9SHong Zhang 3994b84eec9SHong Zhang /*@C 400bcf0153eSBarry Smith TSMPRKInitializePackage - This function initializes everything in the `TSMPRK` package. It is called 401bcf0153eSBarry Smith from `PetscDLLibraryRegister()` when using dynamic libraries, and on the first call to `TSCreate_MPRK()` 4024b84eec9SHong Zhang when using static libraries. 4034b84eec9SHong Zhang 4044b84eec9SHong Zhang Level: developer 4054b84eec9SHong Zhang 406*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `PetscInitialize()` 4074b84eec9SHong Zhang @*/ 408d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKInitializePackage(void) 409d71ae5a4SJacob Faibussowitsch { 4104b84eec9SHong Zhang PetscFunctionBegin; 4113ba16761SJacob Faibussowitsch if (TSMPRKPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 4124b84eec9SHong Zhang TSMPRKPackageInitialized = PETSC_TRUE; 4139566063dSJacob Faibussowitsch PetscCall(TSMPRKRegisterAll()); 4149566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(TSMPRKFinalizePackage)); 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4164b84eec9SHong Zhang } 4174b84eec9SHong Zhang 4184b84eec9SHong Zhang /*@C 419bcf0153eSBarry Smith TSMPRKFinalizePackage - This function destroys everything in the `TSMPRK` package. It is 420bcf0153eSBarry Smith called from `PetscFinalize()`. 4214b84eec9SHong Zhang 4224b84eec9SHong Zhang Level: developer 4234b84eec9SHong Zhang 424*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK`, `PetscFinalize()` 4254b84eec9SHong Zhang @*/ 426d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKFinalizePackage(void) 427d71ae5a4SJacob Faibussowitsch { 4284b84eec9SHong Zhang PetscFunctionBegin; 4294b84eec9SHong Zhang TSMPRKPackageInitialized = PETSC_FALSE; 4309566063dSJacob Faibussowitsch PetscCall(TSMPRKRegisterDestroy()); 4313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4324b84eec9SHong Zhang } 4334b84eec9SHong Zhang 4344b84eec9SHong Zhang /*@C 435bcf0153eSBarry Smith TSMPRKRegister - register a `TSMPRK` scheme by providing the entries in the Butcher tableau 4364b84eec9SHong Zhang 4374b84eec9SHong Zhang Not Collective, but the same schemes should be registered on all processes on which they will be used 4384b84eec9SHong Zhang 4394b84eec9SHong Zhang Input Parameters: 4404b84eec9SHong Zhang + name - identifier for method 4414b84eec9SHong Zhang . order - approximation order of method 4422fe279fdSBarry Smith . sbase - number of stages in the base methods 44379bc8a77SHong Zhang . ratio1 - stepsize ratio at 1st level (e.g. slow/medium) 44479bc8a77SHong Zhang . ratio2 - stepsize ratio at 2nd level (e.g. medium/fast) 4454b84eec9SHong Zhang . Af - stage coefficients for fast components(dimension s*s, row-major) 4464b84eec9SHong Zhang . bf - step completion table for fast components(dimension s) 4474b84eec9SHong Zhang . cf - abscissa for fast components(dimension s) 4484b84eec9SHong Zhang . As - stage coefficients for slow components(dimension s*s, row-major) 4494b84eec9SHong Zhang . bs - step completion table for slow components(dimension s) 4504b84eec9SHong Zhang - cs - abscissa for slow components(dimension s) 4514b84eec9SHong Zhang 4524b84eec9SHong Zhang Level: advanced 4534b84eec9SHong Zhang 454bcf0153eSBarry Smith Note: 455bcf0153eSBarry Smith Several `TSMPRK` methods are provided, this function is only needed to create new methods. 456bcf0153eSBarry Smith 457*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRK` 4584b84eec9SHong Zhang @*/ 459d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKRegister(TSMPRKType name, PetscInt order, PetscInt sbase, PetscInt ratio1, PetscInt ratio2, const PetscReal Asb[], const PetscReal bsb[], const PetscReal csb[], const PetscInt rsb[], const PetscReal Amb[], const PetscReal bmb[], const PetscReal cmb[], const PetscInt rmb[], const PetscReal Af[], const PetscReal bf[], const PetscReal cf[]) 460d71ae5a4SJacob Faibussowitsch { 4614b84eec9SHong Zhang MPRKTableauLink link; 4624b84eec9SHong Zhang MPRKTableau t; 46379bc8a77SHong Zhang PetscInt s, i, j; 4644b84eec9SHong Zhang 4654b84eec9SHong Zhang PetscFunctionBegin; 4664b84eec9SHong Zhang PetscValidCharPointer(name, 1); 467064a246eSJacob Faibussowitsch PetscValidRealPointer(Asb, 6); 46879bc8a77SHong Zhang if (bsb) PetscValidRealPointer(bsb, 7); 46979bc8a77SHong Zhang if (csb) PetscValidRealPointer(csb, 8); 470064a246eSJacob Faibussowitsch if (rsb) PetscValidIntPointer(rsb, 9); 47179bc8a77SHong Zhang if (Amb) PetscValidRealPointer(Amb, 10); 47279bc8a77SHong Zhang if (bmb) PetscValidRealPointer(bmb, 11); 47379bc8a77SHong Zhang if (cmb) PetscValidRealPointer(cmb, 12); 474064a246eSJacob Faibussowitsch if (rmb) PetscValidIntPointer(rmb, 13); 47579bc8a77SHong Zhang PetscValidRealPointer(Af, 14); 47679bc8a77SHong Zhang if (bf) PetscValidRealPointer(bf, 15); 47779bc8a77SHong Zhang if (cf) PetscValidRealPointer(cf, 16); 4784b84eec9SHong Zhang 4799566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 4804b84eec9SHong Zhang t = &link->tab; 4814b84eec9SHong Zhang 4829566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &t->name)); 48379bc8a77SHong Zhang s = sbase * ratio1 * ratio2; /* this is the dimension of the matrices below */ 4844b84eec9SHong Zhang t->order = order; 48579bc8a77SHong Zhang t->sbase = sbase; 4864b84eec9SHong Zhang t->s = s; 48719c2959aSHong Zhang t->np = 2; 48879bc8a77SHong Zhang 4899566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(s * s, &t->Af, s, &t->bf, s, &t->cf)); 4909566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->Af, Af, s * s)); 4914b84eec9SHong Zhang if (bf) { 4929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->bf, bf, s)); 49319c2959aSHong Zhang } else 4944b84eec9SHong Zhang for (i = 0; i < s; i++) t->bf[i] = Af[(s - 1) * s + i]; 4954b84eec9SHong Zhang if (cf) { 4969566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->cf, cf, s)); 49719c2959aSHong Zhang } else { 4984b84eec9SHong Zhang for (i = 0; i < s; i++) 4999371c9d4SSatish Balay for (j = 0, t->cf[i] = 0; j < s; j++) t->cf[i] += Af[i * s + j]; 5004b84eec9SHong Zhang } 50119c2959aSHong Zhang 50219c2959aSHong Zhang if (Amb) { 50319c2959aSHong Zhang t->np = 3; 5049566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(s * s, &t->Amb, s, &t->bmb, s, &t->cmb)); 5059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->Amb, Amb, s * s)); 50619c2959aSHong Zhang if (bmb) { 5079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->bmb, bmb, s)); 50819c2959aSHong Zhang } else { 50919c2959aSHong Zhang for (i = 0; i < s; i++) t->bmb[i] = Amb[(s - 1) * s + i]; 5104b84eec9SHong Zhang } 51119c2959aSHong Zhang if (cmb) { 5129566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->cmb, cmb, s)); 51319c2959aSHong Zhang } else { 5144b84eec9SHong Zhang for (i = 0; i < s; i++) 5159371c9d4SSatish Balay for (j = 0, t->cmb[i] = 0; j < s; j++) t->cmb[i] += Amb[i * s + j]; 51619c2959aSHong Zhang } 51719c2959aSHong Zhang if (rmb) { 5189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(s, &t->rmb)); 5199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->rmb, rmb, s)); 520071fcb05SBarry Smith } else { 5219566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(s, &t->rmb)); 52219c2959aSHong Zhang } 52319c2959aSHong Zhang } 52419c2959aSHong Zhang 5259566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(s * s, &t->Asb, s, &t->bsb, s, &t->csb)); 5269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->Asb, Asb, s * s)); 52719c2959aSHong Zhang if (bsb) { 5289566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->bsb, bsb, s)); 52919c2959aSHong Zhang } else 53019c2959aSHong Zhang for (i = 0; i < s; i++) t->bsb[i] = Asb[(s - 1) * s + i]; 53119c2959aSHong Zhang if (csb) { 5329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->csb, csb, s)); 53319c2959aSHong Zhang } else { 53419c2959aSHong Zhang for (i = 0; i < s; i++) 5359371c9d4SSatish Balay for (j = 0, t->csb[i] = 0; j < s; j++) t->csb[i] += Asb[i * s + j]; 53619c2959aSHong Zhang } 53719c2959aSHong Zhang if (rsb) { 5389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(s, &t->rsb)); 5399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(t->rsb, rsb, s)); 540071fcb05SBarry Smith } else { 5419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(s, &t->rsb)); 5424b84eec9SHong Zhang } 5434b84eec9SHong Zhang link->next = MPRKTableauList; 5444b84eec9SHong Zhang MPRKTableauList = link; 5453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5464b84eec9SHong Zhang } 5474b84eec9SHong Zhang 548d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKSetSplits(TS ts) 549d71ae5a4SJacob Faibussowitsch { 5504b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 55119c2959aSHong Zhang MPRKTableau tab = mprk->tableau; 5524b84eec9SHong Zhang DM dm, subdm, newdm; 5534b84eec9SHong Zhang 5544b84eec9SHong Zhang PetscFunctionBegin; 5559566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "slow", &mprk->subts_slow)); 5569566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "fast", &mprk->subts_fast)); 5573c633725SBarry Smith PetscCheck(mprk->subts_slow && mprk->subts_fast, 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"); 5584b84eec9SHong Zhang 55919c2959aSHong Zhang /* Only copy the DM */ 5609566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 56119c2959aSHong Zhang 5629566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "slowbuffer", &mprk->subts_slowbuffer)); 56319c2959aSHong Zhang if (!mprk->subts_slowbuffer) { 56419c2959aSHong Zhang mprk->subts_slowbuffer = mprk->subts_slow; 56519c2959aSHong Zhang mprk->subts_slow = NULL; 56619c2959aSHong Zhang } 56719c2959aSHong Zhang if (mprk->subts_slow) { 5689566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &newdm)); 5699566063dSJacob Faibussowitsch PetscCall(TSGetDM(mprk->subts_slow, &subdm)); 5709566063dSJacob Faibussowitsch PetscCall(DMCopyDMTS(subdm, newdm)); 5719566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(subdm, newdm)); 5729566063dSJacob Faibussowitsch PetscCall(TSSetDM(mprk->subts_slow, newdm)); 5739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newdm)); 57419c2959aSHong Zhang } 5759566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &newdm)); 5769566063dSJacob Faibussowitsch PetscCall(TSGetDM(mprk->subts_slowbuffer, &subdm)); 5779566063dSJacob Faibussowitsch PetscCall(DMCopyDMTS(subdm, newdm)); 5789566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(subdm, newdm)); 5799566063dSJacob Faibussowitsch PetscCall(TSSetDM(mprk->subts_slowbuffer, newdm)); 5809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newdm)); 58119c2959aSHong Zhang 5829566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &newdm)); 5839566063dSJacob Faibussowitsch PetscCall(TSGetDM(mprk->subts_fast, &subdm)); 5849566063dSJacob Faibussowitsch PetscCall(DMCopyDMTS(subdm, newdm)); 5859566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(subdm, newdm)); 5869566063dSJacob Faibussowitsch PetscCall(TSSetDM(mprk->subts_fast, newdm)); 5879566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newdm)); 58819c2959aSHong Zhang 58919c2959aSHong Zhang if (tab->np == 3) { 5909566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "medium", &mprk->subts_medium)); 5919566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "mediumbuffer", &mprk->subts_mediumbuffer)); 59219c2959aSHong Zhang if (mprk->subts_medium && !mprk->subts_mediumbuffer) { 59319c2959aSHong Zhang mprk->subts_mediumbuffer = mprk->subts_medium; 59419c2959aSHong Zhang mprk->subts_medium = NULL; 59519c2959aSHong Zhang } 59619c2959aSHong Zhang if (mprk->subts_medium) { 5979566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &newdm)); 5989566063dSJacob Faibussowitsch PetscCall(TSGetDM(mprk->subts_medium, &subdm)); 5999566063dSJacob Faibussowitsch PetscCall(DMCopyDMTS(subdm, newdm)); 6009566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(subdm, newdm)); 6019566063dSJacob Faibussowitsch PetscCall(TSSetDM(mprk->subts_medium, newdm)); 6029566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newdm)); 60319c2959aSHong Zhang } 6049566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &newdm)); 6059566063dSJacob Faibussowitsch PetscCall(TSGetDM(mprk->subts_mediumbuffer, &subdm)); 6069566063dSJacob Faibussowitsch PetscCall(DMCopyDMTS(subdm, newdm)); 6079566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(subdm, newdm)); 6089566063dSJacob Faibussowitsch PetscCall(TSSetDM(mprk->subts_mediumbuffer, newdm)); 6099566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newdm)); 61019c2959aSHong Zhang } 6113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6124b84eec9SHong Zhang } 6134b84eec9SHong Zhang 6144b84eec9SHong Zhang /* 6154b84eec9SHong Zhang This if for nonsplit RHS MPRK 6164b84eec9SHong Zhang The step completion formula is 6174b84eec9SHong Zhang 6184b84eec9SHong Zhang x1 = x0 + h b^T YdotRHS 6194b84eec9SHong Zhang 6204b84eec9SHong Zhang */ 621d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSEvaluateStep_MPRK(TS ts, PetscInt order, Vec X, PetscBool *done) 622d71ae5a4SJacob Faibussowitsch { 6234b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 6244b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 6257c0df07dSHong Zhang PetscScalar *wf = mprk->work_fast; 6264b84eec9SHong Zhang PetscReal h = ts->time_step; 6274b84eec9SHong Zhang PetscInt s = tab->s, j; 6284b84eec9SHong Zhang 6294b84eec9SHong Zhang PetscFunctionBegin; 6304b84eec9SHong Zhang for (j = 0; j < s; j++) wf[j] = h * tab->bf[j]; 6319566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, X)); 6329566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X, s, wf, mprk->YdotRHS)); 6333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6344b84eec9SHong Zhang } 6354b84eec9SHong Zhang 636d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_MPRK(TS ts) 637d71ae5a4SJacob Faibussowitsch { 6384b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 6397c0df07dSHong Zhang Vec *Y = mprk->Y, *YdotRHS = mprk->YdotRHS, *YdotRHS_fast = mprk->YdotRHS_fast, *YdotRHS_slow = mprk->YdotRHS_slow, *YdotRHS_slowbuffer = mprk->YdotRHS_slowbuffer; 6407c0df07dSHong Zhang Vec Yslow, Yslowbuffer, Yfast; 6414b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 6424b84eec9SHong Zhang const PetscInt s = tab->s; 64319c2959aSHong Zhang const PetscReal *Af = tab->Af, *cf = tab->cf, *Asb = tab->Asb, *csb = tab->csb; 644ebd5ed4eSHong Zhang PetscScalar *wf = mprk->work_fast, *wsb = mprk->work_slowbuffer; 645ebd5ed4eSHong Zhang PetscInt i, j; 6464b84eec9SHong Zhang PetscReal next_time_step = ts->time_step, t = ts->ptime, h = ts->time_step; 6474b84eec9SHong Zhang 6484b84eec9SHong Zhang PetscFunctionBegin; 6494b84eec9SHong Zhang for (i = 0; i < s; i++) { 6504b84eec9SHong Zhang mprk->stage_time = t + h * cf[i]; 6519566063dSJacob Faibussowitsch PetscCall(TSPreStage(ts, mprk->stage_time)); 6529566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, Y[i])); 6534b84eec9SHong Zhang 6547c0df07dSHong Zhang /* slow buffer region */ 65519c2959aSHong Zhang for (j = 0; j < i; j++) wsb[j] = h * Asb[i * s + j]; 65648a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecGetSubVector(YdotRHS[j], mprk->is_slowbuffer, &YdotRHS_slowbuffer[j])); 6579566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 6589566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yslowbuffer, i, wsb, mprk->YdotRHS_slowbuffer)); 6599566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 66048a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecRestoreSubVector(YdotRHS[j], mprk->is_slowbuffer, &YdotRHS_slowbuffer[j])); 6617c0df07dSHong Zhang /* slow region */ 6627c0df07dSHong Zhang if (mprk->is_slow) { 66348a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecGetSubVector(YdotRHS[j], mprk->is_slow, &YdotRHS_slow[j])); 6649566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slow, &Yslow)); 6659566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yslow, i, wsb, mprk->YdotRHS_slow)); 6669566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slow, &Yslow)); 66748a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecRestoreSubVector(YdotRHS[j], mprk->is_slow, &YdotRHS_slow[j])); 6687c0df07dSHong Zhang } 6694b84eec9SHong Zhang 6707c0df07dSHong Zhang /* fast region */ 6714b84eec9SHong Zhang for (j = 0; j < i; j++) wf[j] = h * Af[i * s + j]; 67248a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecGetSubVector(YdotRHS[j], mprk->is_fast, &YdotRHS_fast[j])); 6739566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_fast, &Yfast)); 6749566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yfast, i, wf, mprk->YdotRHS_fast)); 6759566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_fast, &Yfast)); 67648a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecRestoreSubVector(YdotRHS[j], mprk->is_fast, &YdotRHS_fast[j])); 6777c0df07dSHong Zhang if (tab->np == 3) { 6787c0df07dSHong Zhang Vec *YdotRHS_medium = mprk->YdotRHS_medium, *YdotRHS_mediumbuffer = mprk->YdotRHS_mediumbuffer; 6797c0df07dSHong Zhang Vec Ymedium, Ymediumbuffer; 680ebd5ed4eSHong Zhang PetscScalar *wmb = mprk->work_mediumbuffer; 681ebd5ed4eSHong Zhang 682ebd5ed4eSHong Zhang for (j = 0; j < i; j++) wmb[j] = h * tab->Amb[i * s + j]; 6837c0df07dSHong Zhang /* medium region */ 6847c0df07dSHong Zhang if (mprk->is_medium) { 68548a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecGetSubVector(YdotRHS[j], mprk->is_medium, &YdotRHS_medium[j])); 6869566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_medium, &Ymedium)); 6879566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Ymedium, i, wmb, mprk->YdotRHS_medium)); 6889566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_medium, &Ymedium)); 68948a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecRestoreSubVector(YdotRHS[j], mprk->is_medium, &YdotRHS_medium[j])); 6907c0df07dSHong Zhang } 6917c0df07dSHong Zhang /* medium buffer region */ 69248a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecGetSubVector(YdotRHS[j], mprk->is_mediumbuffer, &YdotRHS_mediumbuffer[j])); 6939566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_mediumbuffer, &Ymediumbuffer)); 6949566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Ymediumbuffer, i, wmb, mprk->YdotRHS_mediumbuffer)); 6959566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_mediumbuffer, &Ymediumbuffer)); 69648a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecRestoreSubVector(YdotRHS[j], mprk->is_mediumbuffer, &YdotRHS_mediumbuffer[j])); 6977c0df07dSHong Zhang } 6989566063dSJacob Faibussowitsch PetscCall(TSPostStage(ts, mprk->stage_time, i, Y)); 6994b84eec9SHong Zhang /* compute the stage RHS by fast and slow tableau respectively */ 7009566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(ts, t + h * csb[i], Y[i], YdotRHS[i])); 7014b84eec9SHong Zhang } 7029566063dSJacob Faibussowitsch PetscCall(TSEvaluateStep(ts, tab->order, ts->vec_sol, NULL)); 7034b84eec9SHong Zhang ts->ptime += ts->time_step; 7044b84eec9SHong Zhang ts->time_step = next_time_step; 7053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7064b84eec9SHong Zhang } 7074b84eec9SHong Zhang 7084b84eec9SHong Zhang /* 709f944a40eSHong Zhang This if for the case when split RHS is used 7104b84eec9SHong Zhang The step completion formula is 7114b84eec9SHong Zhang x1 = x0 + h b^T YdotRHS 7124b84eec9SHong Zhang */ 713d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSEvaluateStep_MPRKSPLIT(TS ts, PetscInt order, Vec X, PetscBool *done) 714d71ae5a4SJacob Faibussowitsch { 7154b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 7164b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 7176aad120cSJose E. Roman Vec Xslow, Xfast, Xslowbuffer; /* subvectors for slow and fast components in X respectively */ 71819c2959aSHong Zhang PetscScalar *wf = mprk->work_fast, *ws = mprk->work_slow, *wsb = mprk->work_slowbuffer; 7194b84eec9SHong Zhang PetscReal h = ts->time_step; 72079bc8a77SHong Zhang PetscInt s = tab->s, j, computedstages; 7214b84eec9SHong Zhang 7224b84eec9SHong Zhang PetscFunctionBegin; 7239566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, X)); 72419c2959aSHong Zhang 72519c2959aSHong Zhang /* slow region */ 72619c2959aSHong Zhang if (mprk->is_slow) { 72779bc8a77SHong Zhang computedstages = 0; 72819c2959aSHong Zhang for (j = 0; j < s; j++) { 7299849be05SHong Zhang if (tab->rsb[j]) ws[tab->rsb[j] - 1] += h * tab->bsb[j]; 73079bc8a77SHong Zhang else ws[computedstages++] = h * tab->bsb[j]; 73119c2959aSHong Zhang } 7329566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_slow, &Xslow)); 7339566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xslow, computedstages, ws, mprk->YdotRHS_slow)); 7349566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_slow, &Xslow)); 73519c2959aSHong Zhang } 73619c2959aSHong Zhang 7379d6e09e9SHong Zhang if (tab->np == 3 && mprk->is_medium) { 7389d6e09e9SHong Zhang computedstages = 0; 7399d6e09e9SHong Zhang for (j = 0; j < s; j++) { 7409d6e09e9SHong Zhang if (tab->rmb[j]) wsb[computedstages - tab->sbase + (tab->rmb[j] - 1) % tab->sbase] += h * tab->bsb[j]; 7419d6e09e9SHong Zhang else wsb[computedstages++] = h * tab->bsb[j]; 7429d6e09e9SHong Zhang } 7439566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_slowbuffer, &Xslowbuffer)); 7449566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xslowbuffer, computedstages, wsb, mprk->YdotRHS_slowbuffer)); 7459566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_slowbuffer, &Xslowbuffer)); 7469d6e09e9SHong Zhang } else { 74719c2959aSHong Zhang /* slow buffer region */ 74819c2959aSHong Zhang for (j = 0; j < s; j++) wsb[j] = h * tab->bsb[j]; 7499566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_slowbuffer, &Xslowbuffer)); 7509566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xslowbuffer, s, wsb, mprk->YdotRHS_slowbuffer)); 7519566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_slowbuffer, &Xslowbuffer)); 7529d6e09e9SHong Zhang } 75319c2959aSHong Zhang if (tab->np == 3) { 75419c2959aSHong Zhang Vec Xmedium, Xmediumbuffer; 75519c2959aSHong Zhang PetscScalar *wm = mprk->work_medium, *wmb = mprk->work_mediumbuffer; 7569d6e09e9SHong Zhang /* medium region and slow buffer region */ 75719c2959aSHong Zhang if (mprk->is_medium) { 75879bc8a77SHong Zhang computedstages = 0; 75919c2959aSHong Zhang for (j = 0; j < s; j++) { 76079bc8a77SHong Zhang if (tab->rmb[j]) wm[computedstages - tab->sbase + (tab->rmb[j] - 1) % tab->sbase] += h * tab->bmb[j]; 76179bc8a77SHong Zhang else wm[computedstages++] = h * tab->bmb[j]; 76219c2959aSHong Zhang } 7639566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_medium, &Xmedium)); 7649566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xmedium, computedstages, wm, mprk->YdotRHS_medium)); 7659566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_medium, &Xmedium)); 76619c2959aSHong Zhang } 76719c2959aSHong Zhang /* medium buffer region */ 76819c2959aSHong Zhang for (j = 0; j < s; j++) wmb[j] = h * tab->bmb[j]; 7699566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_mediumbuffer, &Xmediumbuffer)); 7709566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xmediumbuffer, s, wmb, mprk->YdotRHS_mediumbuffer)); 7719566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_mediumbuffer, &Xmediumbuffer)); 77219c2959aSHong Zhang } 77319c2959aSHong Zhang /* fast region */ 77419c2959aSHong Zhang for (j = 0; j < s; j++) wf[j] = h * tab->bf[j]; 7759566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(X, mprk->is_fast, &Xfast)); 7769566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Xfast, s, wf, mprk->YdotRHS_fast)); 7779566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(X, mprk->is_fast, &Xfast)); 7783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7794b84eec9SHong Zhang } 7804b84eec9SHong Zhang 781d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_MPRKSPLIT(TS ts) 782d71ae5a4SJacob Faibussowitsch { 7834b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 7844b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 78519c2959aSHong Zhang Vec *Y = mprk->Y, *YdotRHS_fast = mprk->YdotRHS_fast, *YdotRHS_slow = mprk->YdotRHS_slow, *YdotRHS_slowbuffer = mprk->YdotRHS_slowbuffer; 78619c2959aSHong Zhang Vec Yslow, Yslowbuffer, Yfast; /* subvectors for slow and fast components in Y[i] respectively */ 78719c2959aSHong Zhang PetscInt s = tab->s; 78819c2959aSHong Zhang const PetscReal *Af = tab->Af, *cf = tab->cf, *Asb = tab->Asb, *csb = tab->csb; 78919c2959aSHong Zhang PetscScalar *wf = mprk->work_fast, *ws = mprk->work_slow, *wsb = mprk->work_slowbuffer; 79079bc8a77SHong Zhang PetscInt i, j, computedstages; 7914b84eec9SHong Zhang PetscReal next_time_step = ts->time_step, t = ts->ptime, h = ts->time_step; 7924b84eec9SHong Zhang 7934b84eec9SHong Zhang PetscFunctionBegin; 7944b84eec9SHong Zhang for (i = 0; i < s; i++) { 7954b84eec9SHong Zhang mprk->stage_time = t + h * cf[i]; 7969566063dSJacob Faibussowitsch PetscCall(TSPreStage(ts, mprk->stage_time)); 7974b84eec9SHong Zhang /* calculate the stage value for fast and slow components respectively */ 7989566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, Y[i])); 79919c2959aSHong Zhang for (j = 0; j < i; j++) wsb[j] = h * Asb[i * s + j]; 80019c2959aSHong Zhang 80119c2959aSHong Zhang /* slow buffer region */ 8029d6e09e9SHong Zhang if (tab->np == 3 && mprk->is_medium) { 8039d6e09e9SHong Zhang if (tab->rmb[i]) { 8049566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8059566063dSJacob Faibussowitsch PetscCall(VecISCopy(Y[tab->rmb[i] - 1], mprk->is_slowbuffer, SCATTER_REVERSE, Yslowbuffer)); 8069566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8079d6e09e9SHong Zhang } else { 8089d6e09e9SHong Zhang PetscScalar *wm = mprk->work_medium; 8099d6e09e9SHong Zhang computedstages = 0; 8109d6e09e9SHong Zhang for (j = 0; j < i; j++) { 8119d6e09e9SHong Zhang if (tab->rmb[j]) wm[computedstages - tab->sbase + (tab->rmb[j] - 1) % tab->sbase] += wsb[j]; 8129d6e09e9SHong Zhang else wm[computedstages++] = wsb[j]; 8139d6e09e9SHong Zhang } 8149566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8159566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yslowbuffer, computedstages, wm, YdotRHS_slowbuffer)); 8169566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8179d6e09e9SHong Zhang } 8189d6e09e9SHong Zhang } else { 8199566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8209566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yslowbuffer, i, wsb, YdotRHS_slowbuffer)); 8219566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slowbuffer, &Yslowbuffer)); 8229d6e09e9SHong Zhang } 8239849be05SHong Zhang 82419c2959aSHong Zhang /* slow region */ 8259849be05SHong Zhang if (mprk->is_slow) { 8269849be05SHong Zhang if (tab->rsb[i]) { /* repeat previous stage */ 8279566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slow, &Yslow)); 8289566063dSJacob Faibussowitsch PetscCall(VecISCopy(Y[tab->rsb[i] - 1], mprk->is_slow, SCATTER_REVERSE, Yslow)); 8299566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slow, &Yslow)); 8309849be05SHong Zhang } else { 83179bc8a77SHong Zhang computedstages = 0; 83219c2959aSHong Zhang for (j = 0; j < i; j++) { 83379bc8a77SHong Zhang if (tab->rsb[j]) ws[tab->rsb[j] - 1] += wsb[j]; 83479bc8a77SHong Zhang else ws[computedstages++] = wsb[j]; 83519c2959aSHong Zhang } 8369566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_slow, &Yslow)); 8379566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yslow, computedstages, ws, YdotRHS_slow)); 8389566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_slow, &Yslow)); 83919c2959aSHong Zhang /* only depends on the slow buffer region */ 8409566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(mprk->subts_slow, t + h * csb[i], Y[i], YdotRHS_slow[computedstages])); 84119c2959aSHong Zhang } 8429849be05SHong Zhang } 84319c2959aSHong Zhang 84419c2959aSHong Zhang /* fast region */ 84519c2959aSHong Zhang for (j = 0; j < i; j++) wf[j] = h * Af[i * s + j]; 8469566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_fast, &Yfast)); 8479566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Yfast, i, wf, YdotRHS_fast)); 8489566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_fast, &Yfast)); 84919c2959aSHong Zhang 85019c2959aSHong Zhang if (tab->np == 3) { 85119c2959aSHong Zhang Vec *YdotRHS_medium = mprk->YdotRHS_medium, *YdotRHS_mediumbuffer = mprk->YdotRHS_mediumbuffer; 85219c2959aSHong Zhang Vec Ymedium, Ymediumbuffer; 85319c2959aSHong Zhang const PetscReal *Amb = tab->Amb, *cmb = tab->cmb; 85419c2959aSHong Zhang PetscScalar *wm = mprk->work_medium, *wmb = mprk->work_mediumbuffer; 85519c2959aSHong Zhang 85619c2959aSHong Zhang for (j = 0; j < i; j++) wmb[j] = h * Amb[i * s + j]; 85719c2959aSHong Zhang /* medium buffer region */ 8589566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_mediumbuffer, &Ymediumbuffer)); 8599566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Ymediumbuffer, i, wmb, YdotRHS_mediumbuffer)); 8609566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_mediumbuffer, &Ymediumbuffer)); 86119c2959aSHong Zhang /* medium region */ 86279bc8a77SHong Zhang if (mprk->is_medium) { 86379bc8a77SHong Zhang if (tab->rmb[i]) { /* repeat previous stage */ 8649566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_medium, &Ymedium)); 8659566063dSJacob Faibussowitsch PetscCall(VecISCopy(Y[tab->rmb[i] - 1], mprk->is_medium, SCATTER_REVERSE, Ymedium)); 8669566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_medium, &Ymedium)); 86779bc8a77SHong Zhang } else { 86879bc8a77SHong Zhang computedstages = 0; 86979bc8a77SHong Zhang for (j = 0; j < i; j++) { 87079bc8a77SHong Zhang if (tab->rmb[j]) wm[computedstages - tab->sbase + (tab->rmb[j] - 1) % tab->sbase] += wmb[j]; 87179bc8a77SHong Zhang else wm[computedstages++] = wmb[j]; 87279bc8a77SHong Zhang } 8739566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(Y[i], mprk->is_medium, &Ymedium)); 8749566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Ymedium, computedstages, wm, YdotRHS_medium)); 8759566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(Y[i], mprk->is_medium, &Ymedium)); 87679bc8a77SHong Zhang /* only depends on the medium buffer region */ 8779566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(mprk->subts_medium, t + h * cmb[i], Y[i], YdotRHS_medium[computedstages])); 8789d6e09e9SHong Zhang /* must be computed after all regions are updated in Y */ 8799566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(mprk->subts_slowbuffer, t + h * csb[i], Y[i], YdotRHS_slowbuffer[computedstages])); 88079bc8a77SHong Zhang } 88119c2959aSHong Zhang } 88219c2959aSHong Zhang /* must be computed after fast region and slow region are updated in Y */ 8839566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(mprk->subts_mediumbuffer, t + h * cmb[i], Y[i], YdotRHS_mediumbuffer[i])); 88419c2959aSHong Zhang } 88548a46eb9SPierre Jolivet if (!(tab->np == 3 && mprk->is_medium)) PetscCall(TSComputeRHSFunction(mprk->subts_slowbuffer, t + h * csb[i], Y[i], YdotRHS_slowbuffer[i])); 8869566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(mprk->subts_fast, t + h * cf[i], Y[i], YdotRHS_fast[i])); 8874b84eec9SHong Zhang } 88879bc8a77SHong Zhang 8899566063dSJacob Faibussowitsch PetscCall(TSEvaluateStep(ts, tab->order, ts->vec_sol, NULL)); 8904b84eec9SHong Zhang ts->ptime += ts->time_step; 8914b84eec9SHong Zhang ts->time_step = next_time_step; 8923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8934b84eec9SHong Zhang } 8944b84eec9SHong Zhang 895d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKTableauReset(TS ts) 896d71ae5a4SJacob Faibussowitsch { 8974b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 8984b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 8994b84eec9SHong Zhang 9004b84eec9SHong Zhang PetscFunctionBegin; 9013ba16761SJacob Faibussowitsch if (!tab) PetscFunctionReturn(PETSC_SUCCESS); 9029566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->work_fast)); 9039566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->work_slow)); 9049566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->work_slowbuffer)); 9059566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->work_medium)); 9069566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->work_mediumbuffer)); 9079566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->Y)); 9080fe4d17eSHong Zhang if (ts->use_splitrhsfunction) { 9099566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS_fast)); 9109566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS_slow)); 9119566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS_slowbuffer)); 9129566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS_medium)); 9139566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS_mediumbuffer)); 9140fe4d17eSHong Zhang } else { 9159566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(tab->s, &mprk->YdotRHS)); 9161baa6e33SBarry Smith if (mprk->is_slow) PetscCall(PetscFree(mprk->YdotRHS_slow)); 9179566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->YdotRHS_slowbuffer)); 9187c0df07dSHong Zhang if (tab->np == 3) { 9191baa6e33SBarry Smith if (mprk->is_medium) PetscCall(PetscFree(mprk->YdotRHS_medium)); 9209566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->YdotRHS_mediumbuffer)); 9217c0df07dSHong Zhang } 9229566063dSJacob Faibussowitsch PetscCall(PetscFree(mprk->YdotRHS_fast)); 9237c0df07dSHong Zhang } 9243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9254b84eec9SHong Zhang } 9264b84eec9SHong Zhang 927d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_MPRK(TS ts) 928d71ae5a4SJacob Faibussowitsch { 9294b84eec9SHong Zhang PetscFunctionBegin; 9309566063dSJacob Faibussowitsch PetscCall(TSMPRKTableauReset(ts)); 9313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9324b84eec9SHong Zhang } 9334b84eec9SHong Zhang 934d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_TSMPRK(DM fine, DM coarse, void *ctx) 935d71ae5a4SJacob Faibussowitsch { 9364b84eec9SHong Zhang PetscFunctionBegin; 9373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9384b84eec9SHong Zhang } 9394b84eec9SHong Zhang 940d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_TSMPRK(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 941d71ae5a4SJacob Faibussowitsch { 9424b84eec9SHong Zhang PetscFunctionBegin; 9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9444b84eec9SHong Zhang } 9454b84eec9SHong Zhang 946d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_TSMPRK(DM dm, DM subdm, void *ctx) 947d71ae5a4SJacob Faibussowitsch { 9484b84eec9SHong Zhang PetscFunctionBegin; 9493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9504b84eec9SHong Zhang } 9514b84eec9SHong Zhang 952d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainRestrictHook_TSMPRK(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 953d71ae5a4SJacob Faibussowitsch { 9544b84eec9SHong Zhang PetscFunctionBegin; 9553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9564b84eec9SHong Zhang } 9574b84eec9SHong Zhang 958d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKTableauSetUp(TS ts) 959d71ae5a4SJacob Faibussowitsch { 9604b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 9614b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 96219c2959aSHong Zhang Vec YdotRHS_slow, YdotRHS_slowbuffer, YdotRHS_medium, YdotRHS_mediumbuffer, YdotRHS_fast; 9634b84eec9SHong Zhang 9644b84eec9SHong Zhang PetscFunctionBegin; 9659566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &mprk->Y)); 96648a46eb9SPierre Jolivet if (mprk->is_slow) PetscCall(PetscMalloc1(tab->s, &mprk->work_slow)); 9679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->work_slowbuffer)); 9687c0df07dSHong Zhang if (tab->np == 3) { 96948a46eb9SPierre Jolivet if (mprk->is_medium) PetscCall(PetscMalloc1(tab->s, &mprk->work_medium)); 9709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->work_mediumbuffer)); 9717c0df07dSHong Zhang } 9729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->work_fast)); 9737c0df07dSHong Zhang 9740fe4d17eSHong Zhang if (ts->use_splitrhsfunction) { 97519c2959aSHong Zhang if (mprk->is_slow) { 9769566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, mprk->is_slow, &YdotRHS_slow)); 9779566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(YdotRHS_slow, tab->s, &mprk->YdotRHS_slow)); 9789566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, mprk->is_slow, &YdotRHS_slow)); 97919c2959aSHong Zhang } 9809566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, mprk->is_slowbuffer, &YdotRHS_slowbuffer)); 9819566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(YdotRHS_slowbuffer, tab->s, &mprk->YdotRHS_slowbuffer)); 9829566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, mprk->is_slowbuffer, &YdotRHS_slowbuffer)); 98319c2959aSHong Zhang if (tab->np == 3) { 98419c2959aSHong Zhang if (mprk->is_medium) { 9859566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, mprk->is_medium, &YdotRHS_medium)); 9869566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(YdotRHS_medium, tab->s, &mprk->YdotRHS_medium)); 9879566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, mprk->is_medium, &YdotRHS_medium)); 98819c2959aSHong Zhang } 9899566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, mprk->is_mediumbuffer, &YdotRHS_mediumbuffer)); 9909566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(YdotRHS_mediumbuffer, tab->s, &mprk->YdotRHS_mediumbuffer)); 9919566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, mprk->is_mediumbuffer, &YdotRHS_mediumbuffer)); 99219c2959aSHong Zhang } 9939566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, mprk->is_fast, &YdotRHS_fast)); 9949566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(YdotRHS_fast, tab->s, &mprk->YdotRHS_fast)); 9959566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, mprk->is_fast, &YdotRHS_fast)); 9960fe4d17eSHong Zhang } else { 9979566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &mprk->YdotRHS)); 99848a46eb9SPierre Jolivet if (mprk->is_slow) PetscCall(PetscMalloc1(tab->s, &mprk->YdotRHS_slow)); 9999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->YdotRHS_slowbuffer)); 10000fe4d17eSHong Zhang if (tab->np == 3) { 100148a46eb9SPierre Jolivet if (mprk->is_medium) PetscCall(PetscMalloc1(tab->s, &mprk->YdotRHS_medium)); 10029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->YdotRHS_mediumbuffer)); 10030fe4d17eSHong Zhang } 10049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tab->s, &mprk->YdotRHS_fast)); 10054b84eec9SHong Zhang } 10063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10074b84eec9SHong Zhang } 10084b84eec9SHong Zhang 1009d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_MPRK(TS ts) 1010d71ae5a4SJacob Faibussowitsch { 10114b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 101219c2959aSHong Zhang MPRKTableau tab = mprk->tableau; 10134b84eec9SHong Zhang DM dm; 10144b84eec9SHong Zhang 10154b84eec9SHong Zhang PetscFunctionBegin; 10169566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "slow", &mprk->is_slow)); 10179566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "fast", &mprk->is_fast)); 10183c633725SBarry Smith PetscCheck(mprk->is_slow && mprk->is_fast, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must set up RHSSplits with TSRHSSplitSetIS() using split names 'slow' and 'fast' respectively in order to use the method '%s'", tab->name); 101919c2959aSHong Zhang 102019c2959aSHong Zhang if (tab->np == 3) { 10219566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "medium", &mprk->is_medium)); 10223c633725SBarry Smith PetscCheck(mprk->is_medium, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must set up RHSSplits with TSRHSSplitSetIS() using split names 'slow' and 'medium' and 'fast' respectively in order to use the method '%s'", tab->name); 10239566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "mediumbuffer", &mprk->is_mediumbuffer)); 102419c2959aSHong Zhang if (!mprk->is_mediumbuffer) { /* let medium buffer cover whole medium region */ 102519c2959aSHong Zhang mprk->is_mediumbuffer = mprk->is_medium; 102619c2959aSHong Zhang mprk->is_medium = NULL; 102719c2959aSHong Zhang } 102819c2959aSHong Zhang } 102919c2959aSHong Zhang 103019c2959aSHong Zhang /* If users do not provide buffer region settings, the solver will do them automatically, but with a performance penalty */ 10319566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "slowbuffer", &mprk->is_slowbuffer)); 103219c2959aSHong Zhang if (!mprk->is_slowbuffer) { /* let slow buffer cover whole slow region */ 103319c2959aSHong Zhang mprk->is_slowbuffer = mprk->is_slow; 103419c2959aSHong Zhang mprk->is_slow = NULL; 103519c2959aSHong Zhang } 10369566063dSJacob Faibussowitsch PetscCall(TSCheckImplicitTerm(ts)); 10379566063dSJacob Faibussowitsch PetscCall(TSMPRKTableauSetUp(ts)); 10389566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 10399566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSMPRK, DMRestrictHook_TSMPRK, ts)); 10409566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSMPRK, DMSubDomainRestrictHook_TSMPRK, ts)); 10410fe4d17eSHong Zhang if (ts->use_splitrhsfunction) { 10420fe4d17eSHong Zhang ts->ops->step = TSStep_MPRKSPLIT; 10430fe4d17eSHong Zhang ts->ops->evaluatestep = TSEvaluateStep_MPRKSPLIT; 10449566063dSJacob Faibussowitsch PetscCall(TSMPRKSetSplits(ts)); 10450fe4d17eSHong Zhang } else { 10460fe4d17eSHong Zhang ts->ops->step = TSStep_MPRK; 10470fe4d17eSHong Zhang ts->ops->evaluatestep = TSEvaluateStep_MPRK; 10480fe4d17eSHong Zhang } 10493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10504b84eec9SHong Zhang } 10514b84eec9SHong Zhang 1052d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetFromOptions_MPRK(TS ts, PetscOptionItems *PetscOptionsObject) 1053d71ae5a4SJacob Faibussowitsch { 10544b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 10554b84eec9SHong Zhang 10564b84eec9SHong Zhang PetscFunctionBegin; 1057d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PRK ODE solver options"); 10584b84eec9SHong Zhang { 10594b84eec9SHong Zhang MPRKTableauLink link; 10604b84eec9SHong Zhang PetscInt count, choice; 10614b84eec9SHong Zhang PetscBool flg; 10624b84eec9SHong Zhang const char **namelist; 10639371c9d4SSatish Balay for (link = MPRKTableauList, count = 0; link; link = link->next, count++) 10649371c9d4SSatish Balay ; 10659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count, (char ***)&namelist)); 10664b84eec9SHong Zhang for (link = MPRKTableauList, count = 0; link; link = link->next, count++) namelist[count] = link->tab.name; 10679566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-ts_mprk_type", "Family of MPRK method", "TSMPRKSetType", (const char *const *)namelist, count, mprk->tableau->name, &choice, &flg)); 10689566063dSJacob Faibussowitsch if (flg) PetscCall(TSMPRKSetType(ts, namelist[choice])); 10699566063dSJacob Faibussowitsch PetscCall(PetscFree(namelist)); 10704b84eec9SHong Zhang } 1071d0609cedSBarry Smith PetscOptionsHeadEnd(); 10723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10734b84eec9SHong Zhang } 10744b84eec9SHong Zhang 1075d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_MPRK(TS ts, PetscViewer viewer) 1076d71ae5a4SJacob Faibussowitsch { 10774b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 10784b84eec9SHong Zhang PetscBool iascii; 10794b84eec9SHong Zhang 10804b84eec9SHong Zhang PetscFunctionBegin; 10819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 10824b84eec9SHong Zhang if (iascii) { 10834b84eec9SHong Zhang MPRKTableau tab = mprk->tableau; 10844b84eec9SHong Zhang TSMPRKType mprktype; 10854b84eec9SHong Zhang char fbuf[512]; 10864b84eec9SHong Zhang char sbuf[512]; 108719c2959aSHong Zhang PetscInt i; 10889566063dSJacob Faibussowitsch PetscCall(TSMPRKGetType(ts, &mprktype)); 10899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " MPRK type %s\n", mprktype)); 109063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Order: %" PetscInt_FMT "\n", tab->order)); 109119c2959aSHong Zhang 10929566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(fbuf, sizeof(fbuf), "% 8.6f", tab->s, tab->cf)); 10939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Abscissa cf = %s\n", fbuf)); 10949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Af = \n")); 109519c2959aSHong Zhang for (i = 0; i < tab->s; i++) { 10969566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(fbuf, sizeof(fbuf), "% 8.6f", tab->s, &tab->Af[i * tab->s])); 10979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", fbuf)); 109819c2959aSHong Zhang } 10999566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(fbuf, sizeof(fbuf), "% 8.6f", tab->s, tab->bf)); 11009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " bf = %s\n", fbuf)); 110119c2959aSHong Zhang 11029566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(sbuf, sizeof(sbuf), "% 8.6f", tab->s, tab->csb)); 11039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Abscissa csb = %s\n", sbuf)); 11049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Asb = \n")); 110519c2959aSHong Zhang for (i = 0; i < tab->s; i++) { 11069566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(sbuf, sizeof(sbuf), "% 8.6f", tab->s, &tab->Asb[i * tab->s])); 11079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", sbuf)); 110819c2959aSHong Zhang } 11099566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(sbuf, sizeof(sbuf), "% 8.6f", tab->s, tab->bsb)); 11109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " bsb = %s\n", sbuf)); 111119c2959aSHong Zhang 111219c2959aSHong Zhang if (tab->np == 3) { 111319c2959aSHong Zhang char mbuf[512]; 11149566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(mbuf, sizeof(mbuf), "% 8.6f", tab->s, tab->cmb)); 11159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Abscissa cmb = %s\n", mbuf)); 11169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Amb = \n")); 111719c2959aSHong Zhang for (i = 0; i < tab->s; i++) { 11189566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(mbuf, sizeof(mbuf), "% 8.6f", tab->s, &tab->Amb[i * tab->s])); 11199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", mbuf)); 112019c2959aSHong Zhang } 11219566063dSJacob Faibussowitsch PetscCall(PetscFormatRealArray(mbuf, sizeof(mbuf), "% 8.6f", tab->s, tab->bmb)); 11229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " bmb = %s\n", mbuf)); 112319c2959aSHong Zhang } 11244b84eec9SHong Zhang } 11253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11264b84eec9SHong Zhang } 11274b84eec9SHong Zhang 1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSLoad_MPRK(TS ts, PetscViewer viewer) 1129d71ae5a4SJacob Faibussowitsch { 11304b84eec9SHong Zhang TSAdapt adapt; 11314b84eec9SHong Zhang 11324b84eec9SHong Zhang PetscFunctionBegin; 11339566063dSJacob Faibussowitsch PetscCall(TSGetAdapt(ts, &adapt)); 11349566063dSJacob Faibussowitsch PetscCall(TSAdaptLoad(adapt, viewer)); 11353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11364b84eec9SHong Zhang } 11374b84eec9SHong Zhang 11384b84eec9SHong Zhang /*@C 1139bcf0153eSBarry Smith TSMPRKSetType - Set the type of `TSMPRK` scheme 11404b84eec9SHong Zhang 114120f4b53cSBarry Smith Not Collective 11424b84eec9SHong Zhang 1143d8d19677SJose E. Roman Input Parameters: 11444b84eec9SHong Zhang + ts - timestepping context 1145bcf0153eSBarry Smith - mprktype - type of `TSMPRK` scheme 11464b84eec9SHong Zhang 1147bcf0153eSBarry Smith Options Database Key: 1148147403d9SBarry Smith . -ts_mprk_type - <pm2,p2,p3> - select the specific scheme 11494b84eec9SHong Zhang 11504b84eec9SHong Zhang Level: intermediate 11514b84eec9SHong Zhang 1152*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRKGetType()`, `TSMPRK`, `TSMPRKType` 11534b84eec9SHong Zhang @*/ 1154d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKSetType(TS ts, TSMPRKType mprktype) 1155d71ae5a4SJacob Faibussowitsch { 11564b84eec9SHong Zhang PetscFunctionBegin; 11574b84eec9SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 11584b84eec9SHong Zhang PetscValidCharPointer(mprktype, 2); 1159cac4c232SBarry Smith PetscTryMethod(ts, "TSMPRKSetType_C", (TS, TSMPRKType), (ts, mprktype)); 11603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11614b84eec9SHong Zhang } 11624b84eec9SHong Zhang 11634b84eec9SHong Zhang /*@C 1164bcf0153eSBarry Smith TSMPRKGetType - Get the type of `TSMPRK` scheme 11654b84eec9SHong Zhang 116620f4b53cSBarry Smith Not Collective 11674b84eec9SHong Zhang 11684b84eec9SHong Zhang Input Parameter: 11694b84eec9SHong Zhang . ts - timestepping context 11704b84eec9SHong Zhang 11714b84eec9SHong Zhang Output Parameter: 1172bcf0153eSBarry Smith . mprktype - type of `TSMPRK` scheme 11734b84eec9SHong Zhang 11744b84eec9SHong Zhang Level: intermediate 11754b84eec9SHong Zhang 1176*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSMPRKGetType()`, `TSMPRK` 11774b84eec9SHong Zhang @*/ 1178d71ae5a4SJacob Faibussowitsch PetscErrorCode TSMPRKGetType(TS ts, TSMPRKType *mprktype) 1179d71ae5a4SJacob Faibussowitsch { 11804b84eec9SHong Zhang PetscFunctionBegin; 11814b84eec9SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1182cac4c232SBarry Smith PetscUseMethod(ts, "TSMPRKGetType_C", (TS, TSMPRKType *), (ts, mprktype)); 11833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11844b84eec9SHong Zhang } 11854b84eec9SHong Zhang 1186d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKGetType_MPRK(TS ts, TSMPRKType *mprktype) 1187d71ae5a4SJacob Faibussowitsch { 11884b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 11894b84eec9SHong Zhang 11904b84eec9SHong Zhang PetscFunctionBegin; 11914b84eec9SHong Zhang *mprktype = mprk->tableau->name; 11923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11934b84eec9SHong Zhang } 11944b84eec9SHong Zhang 1195d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSMPRKSetType_MPRK(TS ts, TSMPRKType mprktype) 1196d71ae5a4SJacob Faibussowitsch { 11974b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 11984b84eec9SHong Zhang PetscBool match; 11994b84eec9SHong Zhang MPRKTableauLink link; 12004b84eec9SHong Zhang 12014b84eec9SHong Zhang PetscFunctionBegin; 12024b84eec9SHong Zhang if (mprk->tableau) { 12039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mprk->tableau->name, mprktype, &match)); 12043ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 12054b84eec9SHong Zhang } 12064b84eec9SHong Zhang for (link = MPRKTableauList; link; link = link->next) { 12079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(link->tab.name, mprktype, &match)); 12084b84eec9SHong Zhang if (match) { 12099566063dSJacob Faibussowitsch if (ts->setupcalled) PetscCall(TSMPRKTableauReset(ts)); 12104b84eec9SHong Zhang mprk->tableau = &link->tab; 12119566063dSJacob Faibussowitsch if (ts->setupcalled) PetscCall(TSMPRKTableauSetUp(ts)); 12123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12134b84eec9SHong Zhang } 12144b84eec9SHong Zhang } 121598921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Could not find '%s'", mprktype); 12164b84eec9SHong Zhang } 12174b84eec9SHong Zhang 1218d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGetStages_MPRK(TS ts, PetscInt *ns, Vec **Y) 1219d71ae5a4SJacob Faibussowitsch { 12204b84eec9SHong Zhang TS_MPRK *mprk = (TS_MPRK *)ts->data; 12214b84eec9SHong Zhang 12224b84eec9SHong Zhang PetscFunctionBegin; 12234b84eec9SHong Zhang *ns = mprk->tableau->s; 12244b84eec9SHong Zhang if (Y) *Y = mprk->Y; 12253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12264b84eec9SHong Zhang } 12274b84eec9SHong Zhang 1228d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_MPRK(TS ts) 1229d71ae5a4SJacob Faibussowitsch { 12304b84eec9SHong Zhang PetscFunctionBegin; 12319566063dSJacob Faibussowitsch PetscCall(TSReset_MPRK(ts)); 12324b84eec9SHong Zhang if (ts->dm) { 12339566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSMPRK, DMRestrictHook_TSMPRK, ts)); 12349566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSMPRK, DMSubDomainRestrictHook_TSMPRK, ts)); 12354b84eec9SHong Zhang } 12369566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data)); 12379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSMPRKGetType_C", NULL)); 12389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSMPRKSetType_C", NULL)); 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12404b84eec9SHong Zhang } 12414b84eec9SHong Zhang 12424b84eec9SHong Zhang /*MC 1243f944a40eSHong Zhang TSMPRK - ODE solver using Multirate Partitioned Runge-Kutta schemes 12444b84eec9SHong Zhang 1245bcf0153eSBarry Smith The user should provide the right hand side of the equation using `TSSetRHSFunction()`. 12464b84eec9SHong Zhang 12474b84eec9SHong Zhang Level: beginner 12484b84eec9SHong Zhang 1249bcf0153eSBarry Smith Note: 1250bcf0153eSBarry Smith The default is `TSMPRKPM2`, it can be changed with `TSMPRKSetType()` or -ts_mprk_type 12514b84eec9SHong Zhang 1252*1cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSMPRKSetType()`, `TSMPRKGetType()`, `TSMPRKType`, `TSMPRKRegister()`, `TSMPRKSetMultirateType()` 1253bcf0153eSBarry Smith `TSMPRKM2`, `TSMPRKM3`, `TSMPRKRFSMR3`, `TSMPRKRFSMR2`, `TSType` 12544b84eec9SHong Zhang M*/ 1255d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_MPRK(TS ts) 1256d71ae5a4SJacob Faibussowitsch { 12574b84eec9SHong Zhang TS_MPRK *mprk; 12584b84eec9SHong Zhang 12594b84eec9SHong Zhang PetscFunctionBegin; 12609566063dSJacob Faibussowitsch PetscCall(TSMPRKInitializePackage()); 12614b84eec9SHong Zhang 12624b84eec9SHong Zhang ts->ops->reset = TSReset_MPRK; 12634b84eec9SHong Zhang ts->ops->destroy = TSDestroy_MPRK; 12644b84eec9SHong Zhang ts->ops->view = TSView_MPRK; 12654b84eec9SHong Zhang ts->ops->load = TSLoad_MPRK; 12664b84eec9SHong Zhang ts->ops->setup = TSSetUp_MPRK; 12674b84eec9SHong Zhang ts->ops->step = TSStep_MPRK; 12684b84eec9SHong Zhang ts->ops->evaluatestep = TSEvaluateStep_MPRK; 12694b84eec9SHong Zhang ts->ops->setfromoptions = TSSetFromOptions_MPRK; 12704b84eec9SHong Zhang ts->ops->getstages = TSGetStages_MPRK; 12714b84eec9SHong Zhang 12724dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mprk)); 12734b84eec9SHong Zhang ts->data = (void *)mprk; 12744b84eec9SHong Zhang 12759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSMPRKGetType_C", TSMPRKGetType_MPRK)); 12769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSMPRKSetType_C", TSMPRKSetType_MPRK)); 12774b84eec9SHong Zhang 12789566063dSJacob Faibussowitsch PetscCall(TSMPRKSetType(ts, TSMPRKDefault)); 12793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12804b84eec9SHong Zhang } 1281