1 /* 2 Code for time stepping with the Runge-Kutta method 3 4 Notes: 5 The general system is written as 6 7 Udot = F(t,U) 8 9 */ 10 11 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 12 #include <petscdm.h> 13 #include <../src/ts/impls/explicit/rk/rk.h> 14 #include <../src/ts/impls/explicit/rk/mrk.h> 15 16 static TSRKType TSRKDefault = TSRK3BS; 17 static PetscBool TSRKRegisterAllCalled; 18 static PetscBool TSRKPackageInitialized; 19 20 static RKTableauLink RKTableauList; 21 22 /*MC 23 TSRK1FE - First order forward Euler scheme. 24 25 This method has one stage. 26 27 Options Database Key: 28 . -ts_rk_type 1fe - use type 1fe 29 30 Level: advanced 31 32 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 33 M*/ 34 /*MC 35 TSRK2A - Second order RK scheme (Heun's method). 36 37 This method has two stages. 38 39 Options Database Key: 40 . -ts_rk_type 2a - use type 2a 41 42 Level: advanced 43 44 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 45 M*/ 46 /*MC 47 TSRK2B - Second order RK scheme (the midpoint method). 48 49 This method has two stages. 50 51 Options Database Key: 52 . -ts_rk_type 2b - use type 2b 53 54 Level: advanced 55 56 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 57 M*/ 58 /*MC 59 TSRK3 - Third order RK scheme. 60 61 This method has three stages. 62 63 Options Database Key: 64 . -ts_rk_type 3 - use type 3 65 66 Level: advanced 67 68 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 69 M*/ 70 /*MC 71 TSRK3BS - Third order RK scheme of Bogacki-Shampine with 2nd order embedded method <https://doi.org/10.1016/0893-9659(89)90079-7> 72 73 This method has four stages with the First Same As Last (FSAL) property. 74 75 Options Database Key: 76 . -ts_rk_type 3bs - use type 3bs 77 78 Level: advanced 79 80 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 81 M*/ 82 /*MC 83 TSRK4 - Fourth order RK scheme. 84 85 This is the classical Runge-Kutta method with four stages. 86 87 Options Database Key: 88 . -ts_rk_type 4 - use type 4 89 90 Level: advanced 91 92 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 93 M*/ 94 /*MC 95 TSRK5F - Fifth order Fehlberg RK scheme with a 4th order embedded method. 96 97 This method has six stages. 98 99 Options Database Key: 100 . -ts_rk_type 5f - use type 5f 101 102 Level: advanced 103 104 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 105 M*/ 106 /*MC 107 TSRK5DP - Fifth order Dormand-Prince RK scheme with the 4th order embedded method <https://doi.org/10.1016/0771-050X(80)90013-3> 108 109 This method has seven stages with the First Same As Last (FSAL) property. 110 111 Options Database Key: 112 . -ts_rk_type 5dp - use type 5dp 113 114 Level: advanced 115 116 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 117 M*/ 118 /*MC 119 TSRK5BS - Fifth order Bogacki-Shampine RK scheme with 4th order embedded method <https://doi.org/10.1016/0898-1221(96)00141-1> 120 121 This method has eight stages with the First Same As Last (FSAL) property. 122 123 Options Database Key: 124 . -ts_rk_type 5bs - use type 5bs 125 126 Level: advanced 127 128 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 129 M*/ 130 /*MC 131 TSRK6VR - Sixth order robust Verner RK scheme with fifth order embedded method. 132 <http://people.math.sfu.ca/~jverner/RKV65.IIIXb.Robust.00010102836.081204.CoeffsOnlyRAT> 133 134 This method has nine stages with the First Same As Last (FSAL) property. 135 136 Options Database Key: 137 . -ts_rk_type 6vr - use type 6vr 138 139 Level: advanced 140 141 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 142 M*/ 143 /*MC 144 TSRK7VR - Seventh order robust Verner RK scheme with sixth order embedded method. 145 <http://people.math.sfu.ca/~jverner/RKV65.IIIXb.Robust.00010102836.081204.CoeffsOnlyRAT> 146 147 This method has ten stages. 148 149 Options Database Key: 150 . -ts_rk_type 7vr - use type 7vr 151 152 Level: advanced 153 154 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 155 M*/ 156 /*MC 157 TSRK8VR - Eighth order robust Verner RK scheme with seventh order embedded method. 158 <http://people.math.sfu.ca/~jverner/RKV87.IIa.Robust.00000754677.081208.CoeffsOnlyRATandFLOAT> 159 160 This method has thirteen stages. 161 162 Options Database Key: 163 . -ts_rk_type 8vr - use type 8vr 164 165 Level: advanced 166 167 .seealso: [](ch_ts), `TSRK`, `TSRKType`, `TSRKSetType()` 168 M*/ 169 170 /*@C 171 TSRKRegisterAll - Registers all of the Runge-Kutta explicit methods in `TSRK` 172 173 Not Collective, but should be called by all processes which will need the schemes to be registered 174 175 Level: advanced 176 177 .seealso: [](ch_ts), `TSRKRegisterDestroy()`, `TSRKRegister()` 178 @*/ 179 PetscErrorCode TSRKRegisterAll(void) 180 { 181 PetscFunctionBegin; 182 if (TSRKRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 183 TSRKRegisterAllCalled = PETSC_TRUE; 184 185 #define RC PetscRealConstant 186 { 187 const PetscReal A[1][1] = {{0}}; 188 const PetscReal b[1] = {RC(1.0)}; 189 PetscCall(TSRKRegister(TSRK1FE, 1, 1, &A[0][0], b, NULL, NULL, 0, NULL)); 190 } 191 { 192 const PetscReal A[2][2] = { 193 {0, 0}, 194 {RC(1.0), 0} 195 }; 196 const PetscReal b[2] = {RC(0.5), RC(0.5)}; 197 const PetscReal bembed[2] = {RC(1.0), 0}; 198 PetscCall(TSRKRegister(TSRK2A, 2, 2, &A[0][0], b, NULL, bembed, 0, NULL)); 199 } 200 { 201 const PetscReal A[2][2] = { 202 {0, 0}, 203 {RC(0.5), 0} 204 }; 205 const PetscReal b[2] = {0, RC(1.0)}; 206 PetscCall(TSRKRegister(TSRK2B, 2, 2, &A[0][0], b, NULL, NULL, 0, NULL)); 207 } 208 { 209 const PetscReal A[3][3] = { 210 {0, 0, 0}, 211 {RC(2.0) / RC(3.0), 0, 0}, 212 {RC(-1.0) / RC(3.0), RC(1.0), 0} 213 }; 214 const PetscReal b[3] = {RC(0.25), RC(0.5), RC(0.25)}; 215 PetscCall(TSRKRegister(TSRK3, 3, 3, &A[0][0], b, NULL, NULL, 0, NULL)); 216 } 217 { 218 const PetscReal A[4][4] = { 219 {0, 0, 0, 0}, 220 {RC(1.0) / RC(2.0), 0, 0, 0}, 221 {0, RC(3.0) / RC(4.0), 0, 0}, 222 {RC(2.0) / RC(9.0), RC(1.0) / RC(3.0), RC(4.0) / RC(9.0), 0} 223 }; 224 const PetscReal b[4] = {RC(2.0) / RC(9.0), RC(1.0) / RC(3.0), RC(4.0) / RC(9.0), 0}; 225 const PetscReal bembed[4] = {RC(7.0) / RC(24.0), RC(1.0) / RC(4.0), RC(1.0) / RC(3.0), RC(1.0) / RC(8.0)}; 226 PetscCall(TSRKRegister(TSRK3BS, 3, 4, &A[0][0], b, NULL, bembed, 0, NULL)); 227 } 228 { 229 const PetscReal A[4][4] = { 230 {0, 0, 0, 0}, 231 {RC(0.5), 0, 0, 0}, 232 {0, RC(0.5), 0, 0}, 233 {0, 0, RC(1.0), 0} 234 }; 235 const PetscReal b[4] = {RC(1.0) / RC(6.0), RC(1.0) / RC(3.0), RC(1.0) / RC(3.0), RC(1.0) / RC(6.0)}; 236 PetscCall(TSRKRegister(TSRK4, 4, 4, &A[0][0], b, NULL, NULL, 0, NULL)); 237 } 238 { 239 const PetscReal A[6][6] = { 240 {0, 0, 0, 0, 0, 0}, 241 {RC(0.25), 0, 0, 0, 0, 0}, 242 {RC(3.0) / RC(32.0), RC(9.0) / RC(32.0), 0, 0, 0, 0}, 243 {RC(1932.0) / RC(2197.0), RC(-7200.0) / RC(2197.0), RC(7296.0) / RC(2197.0), 0, 0, 0}, 244 {RC(439.0) / RC(216.0), RC(-8.0), RC(3680.0) / RC(513.0), RC(-845.0) / RC(4104.0), 0, 0}, 245 {RC(-8.0) / RC(27.0), RC(2.0), RC(-3544.0) / RC(2565.0), RC(1859.0) / RC(4104.0), RC(-11.0) / RC(40.0), 0} 246 }; 247 const PetscReal b[6] = {RC(16.0) / RC(135.0), 0, RC(6656.0) / RC(12825.0), RC(28561.0) / RC(56430.0), RC(-9.0) / RC(50.0), RC(2.0) / RC(55.0)}; 248 const PetscReal bembed[6] = {RC(25.0) / RC(216.0), 0, RC(1408.0) / RC(2565.0), RC(2197.0) / RC(4104.0), RC(-1.0) / RC(5.0), 0}; 249 PetscCall(TSRKRegister(TSRK5F, 5, 6, &A[0][0], b, NULL, bembed, 0, NULL)); 250 } 251 { 252 const PetscReal A[7][7] = { 253 {0, 0, 0, 0, 0, 0, 0}, 254 {RC(1.0) / RC(5.0), 0, 0, 0, 0, 0, 0}, 255 {RC(3.0) / RC(40.0), RC(9.0) / RC(40.0), 0, 0, 0, 0, 0}, 256 {RC(44.0) / RC(45.0), RC(-56.0) / RC(15.0), RC(32.0) / RC(9.0), 0, 0, 0, 0}, 257 {RC(19372.0) / RC(6561.0), RC(-25360.0) / RC(2187.0), RC(64448.0) / RC(6561.0), RC(-212.0) / RC(729.0), 0, 0, 0}, 258 {RC(9017.0) / RC(3168.0), RC(-355.0) / RC(33.0), RC(46732.0) / RC(5247.0), RC(49.0) / RC(176.0), RC(-5103.0) / RC(18656.0), 0, 0}, 259 {RC(35.0) / RC(384.0), 0, RC(500.0) / RC(1113.0), RC(125.0) / RC(192.0), RC(-2187.0) / RC(6784.0), RC(11.0) / RC(84.0), 0} 260 }; 261 const PetscReal b[7] = {RC(35.0) / RC(384.0), 0, RC(500.0) / RC(1113.0), RC(125.0) / RC(192.0), RC(-2187.0) / RC(6784.0), RC(11.0) / RC(84.0), 0}; 262 const PetscReal bembed[7] = {RC(5179.0) / RC(57600.0), 0, RC(7571.0) / RC(16695.0), RC(393.0) / RC(640.0), RC(-92097.0) / RC(339200.0), RC(187.0) / RC(2100.0), RC(1.0) / RC(40.0)}; 263 const PetscReal binterp[7][5] = { 264 {RC(1.0), RC(-4034104133.0) / RC(1410260304.0), RC(105330401.0) / RC(33982176.0), RC(-13107642775.0) / RC(11282082432.0), RC(6542295.0) / RC(470086768.0) }, 265 {0, 0, 0, 0, 0 }, 266 {0, RC(132343189600.0) / RC(32700410799.0), RC(-833316000.0) / RC(131326951.0), RC(91412856700.0) / RC(32700410799.0), RC(-523383600.0) / RC(10900136933.0) }, 267 {0, RC(-115792950.0) / RC(29380423.0), RC(185270875.0) / RC(16991088.0), RC(-12653452475.0) / RC(1880347072.0), RC(98134425.0) / RC(235043384.0) }, 268 {0, RC(70805911779.0) / RC(24914598704.0), RC(-4531260609.0) / RC(600351776.0), RC(988140236175.0) / RC(199316789632.0), RC(-14307999165.0) / RC(24914598704.0)}, 269 {0, RC(-331320693.0) / RC(205662961.0), RC(31361737.0) / RC(7433601.0), RC(-2426908385.0) / RC(822651844.0), RC(97305120.0) / RC(205662961.0) }, 270 {0, RC(44764047.0) / RC(29380423.0), RC(-1532549.0) / RC(353981.0), RC(90730570.0) / RC(29380423.0), RC(-8293050.0) / RC(29380423.0) } 271 }; 272 PetscCall(TSRKRegister(TSRK5DP, 5, 7, &A[0][0], b, NULL, bembed, 5, binterp[0])); 273 } 274 { 275 const PetscReal A[8][8] = { 276 {0, 0, 0, 0, 0, 0, 0, 0}, 277 {RC(1.0) / RC(6.0), 0, 0, 0, 0, 0, 0, 0}, 278 {RC(2.0) / RC(27.0), RC(4.0) / RC(27.0), 0, 0, 0, 0, 0, 0}, 279 {RC(183.0) / RC(1372.0), RC(-162.0) / RC(343.0), RC(1053.0) / RC(1372.0), 0, 0, 0, 0, 0}, 280 {RC(68.0) / RC(297.0), RC(-4.0) / RC(11.0), RC(42.0) / RC(143.0), RC(1960.0) / RC(3861.0), 0, 0, 0, 0}, 281 {RC(597.0) / RC(22528.0), RC(81.0) / RC(352.0), RC(63099.0) / RC(585728.0), RC(58653.0) / RC(366080.0), RC(4617.0) / RC(20480.0), 0, 0, 0}, 282 {RC(174197.0) / RC(959244.0), RC(-30942.0) / RC(79937.0), RC(8152137.0) / RC(19744439.0), RC(666106.0) / RC(1039181.0), RC(-29421.0) / RC(29068.0), RC(482048.0) / RC(414219.0), 0, 0}, 283 {RC(587.0) / RC(8064.0), 0, RC(4440339.0) / RC(15491840.0), RC(24353.0) / RC(124800.0), RC(387.0) / RC(44800.0), RC(2152.0) / RC(5985.0), RC(7267.0) / RC(94080.0), 0} 284 }; 285 const PetscReal b[8] = {RC(587.0) / RC(8064.0), 0, RC(4440339.0) / RC(15491840.0), RC(24353.0) / RC(124800.0), RC(387.0) / RC(44800.0), RC(2152.0) / RC(5985.0), RC(7267.0) / RC(94080.0), 0}; 286 const PetscReal bembed[8] = {RC(2479.0) / RC(34992.0), 0, RC(123.0) / RC(416.0), RC(612941.0) / RC(3411720.0), RC(43.0) / RC(1440.0), RC(2272.0) / RC(6561.0), RC(79937.0) / RC(1113912.0), RC(3293.0) / RC(556956.0)}; 287 PetscCall(TSRKRegister(TSRK5BS, 5, 8, &A[0][0], b, NULL, bembed, 0, NULL)); 288 } 289 { 290 const PetscReal A[9][9] = { 291 {0, 0, 0, 0, 0, 0, 0, 0, 0}, 292 {RC(1.8000000000000000000000000000000000000000e-01), 0, 0, 0, 0, 0, 0, 0, 0}, 293 {RC(8.9506172839506172839506172839506172839506e-02), RC(7.7160493827160493827160493827160493827160e-02), 0, 0, 0, 0, 0, 0, 0}, 294 {RC(6.2500000000000000000000000000000000000000e-02), 0, RC(1.8750000000000000000000000000000000000000e-01), 0, 0, 0, 0, 0, 0}, 295 {RC(3.1651600000000000000000000000000000000000e-01), 0, RC(-1.0449480000000000000000000000000000000000e+00), RC(1.2584320000000000000000000000000000000000e+00), 0, 0, 0, 0, 0}, 296 {RC(2.7232612736485626257225065566674305502508e-01), 0, RC(-8.2513360323886639676113360323886639676113e-01), RC(1.0480917678812415654520917678812415654521e+00), RC(1.0471570799276856873679117969088177628396e-01), 0, 0, 0, 0}, 297 {RC(-1.6699418599716514314329607278961797333198e-01), 0, RC(6.3170850202429149797570850202429149797571e-01), RC(1.7461044552773876082146758838488161796432e-01), RC(-1.0665356459086066122525194734018680677781e+00), RC(1.2272108843537414965986394557823129251701e+00), 0, 0, 0}, 298 {RC(3.6423751686909581646423751686909581646424e-01), 0, RC(-2.0404858299595141700404858299595141700405e-01), RC(-3.4883737816068643136312309244640071707741e-01), RC(3.2619323032856867443333608747142581729048e+00), RC(-2.7551020408163265306122448979591836734694e+00), RC(6.8181818181818181818181818181818181818182e-01), 0, 0}, 299 {RC(7.6388888888888888888888888888888888888889e-02), 0, 0, RC(3.6940836940836940836940836940836940836941e-01), 0, RC(2.4801587301587301587301587301587301587302e-01), RC(2.3674242424242424242424242424242424242424e-01), RC(6.9444444444444444444444444444444444444444e-02), 0} 300 }; 301 const PetscReal b[9] = {RC(7.6388888888888888888888888888888888888889e-02), 0, 0, RC(3.6940836940836940836940836940836940836941e-01), 0, RC(2.4801587301587301587301587301587301587302e-01), RC(2.3674242424242424242424242424242424242424e-01), 302 RC(6.9444444444444444444444444444444444444444e-02), 0}; 303 const PetscReal bembed[9] = {RC(5.8700209643605870020964360587002096436059e-02), 0, 0, RC(4.8072562358276643990929705215419501133787e-01), RC(-8.5341242076919085578832094861228313083563e-01), RC(1.2046485260770975056689342403628117913832e+00), 0, RC(-5.9242373072160306202859394348756050883710e-02), RC(1.6858043453788134639198468985703028256220e-01)}; 304 PetscCall(TSRKRegister(TSRK6VR, 6, 9, &A[0][0], b, NULL, bembed, 0, NULL)); 305 } 306 { 307 const PetscReal A[10][10] = { 308 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 309 {RC(5.0000000000000000000000000000000000000000e-03), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 310 {RC(-1.0767901234567901234567901234567901234568e+00), RC(1.1856790123456790123456790123456790123457e+00), 0, 0, 0, 0, 0, 0, 0, 0}, 311 {RC(4.0833333333333333333333333333333333333333e-02), 0, RC(1.2250000000000000000000000000000000000000e-01), 0, 0, 0, 0, 0, 0, 0}, 312 {RC(6.3607142857142857142857142857142857142857e-01), 0, RC(-2.4444642857142857142857142857142857142857e+00), RC(2.2633928571428571428571428571428571428571e+00), 0, 0, 0, 0, 0, 0}, 313 {RC(-2.5351211079349245229256383554660215487207e+00), 0, RC(1.0299374654449267920438514460756024913612e+01), RC(-7.9513032885990579949493217458266876536482e+00), RC(7.9301148923100592201226014271115261823800e-01), 0, 0, 0, 0, 0}, 314 {RC(1.0018765812524632961969196583094999808207e+00), 0, RC(-4.1665712824423798331313938005470971453189e+00), RC(3.8343432929128642412552665218251378665197e+00), RC(-5.0233333560710847547464330228611765612403e-01), RC(6.6768474388416077115385092269857695410259e-01), 0, 0, 0, 0}, 315 {RC(2.7255018354630767130333963819175005717348e+01), 0, RC(-4.2004617278410638355318645443909295369611e+01), RC(-1.0535713126619489917921081600546526103722e+01), RC(8.0495536711411937147983652158926826634202e+01), RC(-6.7343882271790513468549075963212975640927e+01), RC(1.3048657610777937463471187029566964762710e+01), 0, 0, 0}, 316 {RC(-3.0397378057114965146943658658755763226883e+00), 0, RC(1.0138161410329801111857946190709700150441e+01), RC(-6.4293056748647215721462825629555298064437e+00), RC(-1.5864371483408276587115312853798610579467e+00), RC(1.8921781841968424410864308909131353365021e+00), RC(1.9699335407608869061292360163336442838006e-02), RC(5.4416989827933235465102724247952572977903e-03), 0, 0}, 317 {RC(-1.4449518916777735137351003179355712360517e+00), 0, RC(8.0318913859955919224117033223019560435041e+00), RC(-7.5831741663401346820798883023671588604984e+00), RC(3.5816169353190074211247685442452878696855e+00), RC(-2.4369722632199529411183809065693752383733e+00), RC(8.5158999992326179339689766032486142173390e-01), 0, 0, 0} 318 }; 319 const PetscReal b[10] = {RC(4.7425837833706756083569172717574534698932e-02), 0, 0, RC(2.5622361659370562659961727458274623448160e-01), RC(2.6951376833074206619473817258075952886764e-01), RC(1.2686622409092782845989138364739173247882e-01), RC(2.4887225942060071622046449427647492767292e-01), RC(3.0744837408200631335304388479099184768645e-03), RC(4.8023809989496943308189063347143123323209e-02), 0}; 320 const PetscReal bembed[10] = {RC(4.7485247699299631037531273805727961552268e-02), 0, 0, RC(2.5599412588690633297154918245905393870497e-01), RC(2.7058478081067688722530891099268135732387e-01), RC(1.2505618684425992913638822323746917920448e-01), 321 RC(2.5204468723743860507184043820197442562182e-01), 0, 0, RC(4.8834971521418614557381971303093137592592e-02)}; 322 PetscCall(TSRKRegister(TSRK7VR, 7, 10, &A[0][0], b, NULL, bembed, 0, NULL)); 323 } 324 { 325 const PetscReal A[13][13] = { 326 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 327 {RC(2.5000000000000000000000000000000000000000e-01), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 328 {RC(8.7400846504915232052686327594877411977046e-02), RC(2.5487604938654321753087950620345685135815e-02), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 329 {RC(4.2333169291338582677165354330708661417323e-02), 0, RC(1.2699950787401574803149606299212598425197e-01), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 330 {RC(4.2609505888742261494881445237572274090942e-01), 0, RC(-1.5987952846591523265427733230657181117089e+00), RC(1.5967002257717297115939588706899953707994e+00), 0, 0, 0, 0, 0, 0, 0, 0, 0}, 331 {RC(5.0719337296713929515090618138513639239329e-02), 0, 0, RC(2.5433377264600407582754714408877778031369e-01), RC(2.0394689005728199465736223777270858044698e-01), 0, 0, 0, 0, 0, 0, 0, 0}, 332 {RC(-2.9000374717523110970388379285425896124091e-01), 0, 0, RC(1.3441873910260789889438681109414337003184e+00), RC(-2.8647779433614427309611103827036562829470e+00), RC(2.6775942995105948517211260646164815438695e+00), 0, 0, 0, 0, 0, 0, 0}, 333 {RC(9.8535011337993546469740402980727014284756e-02), 0, 0, 0, RC(2.2192680630751384842024036498197387903583e-01), RC(-1.8140622911806994312690338288073952457474e-01), RC(1.0944411472562548236922614918038631254153e-02), 0, 0, 0, 0, 0, 0}, 334 {RC(3.8711052545731144679444618165166373405645e-01), 0, 0, RC(-1.4424454974855277571256745553077927767173e+00), RC(2.9053981890699509317691346449233848441744e+00), RC(-1.8537710696301059290843332675811978025183e+00), RC(1.4003648098728154269497325109771241479223e-01), RC(5.7273940811495816575746774624447706488753e-01), 0, 0, 0, 0, 0}, 335 {RC(-1.6124403444439308100630016197913480595436e-01), 0, 0, RC(-1.7339602957358984083578404473962567894901e-01), RC(-1.3012892814065147406016812745172492529744e+00), RC(1.1379503751738617308558792131431003472124e+00), RC(-3.1747649663966880106923521138043024698980e-02), RC(9.3351293824933666439811064486056884856590e-01), RC(-8.3786318334733852703300855629616433201504e-02), 0, 0, 0, 0}, 336 {RC(-1.9199444881589533281510804651483576073142e-02), 0, 0, RC(2.7330857265264284907942326254016124275617e-01), RC(-6.7534973206944372919691611210942380856240e-01), RC(3.4151849813846016071738489974728382711981e-01), RC(-6.7950064803375772478920516198524629391910e-02), RC(9.6591752247623878884265586491216376509746e-02), RC(1.3253082511182101180721038466545389951226e-01), RC(3.6854959360386113446906329951531666812946e-01), 0, 0, 0}, 337 {RC(6.0918774036452898676888412111588817784584e-01), 0, 0, RC(-2.2725690858980016768999800931413088399719e+00), RC(4.7578983426940290068155255881914785497547e+00), RC(-5.5161067066927584824294689667844248244842e+00), RC(2.9005963696801192709095818565946174378180e-01), RC(5.6914239633590368229109858454801849145630e-01), RC(7.9267957603321670271339916205893327579951e-01), RC(1.5473720453288822894126190771849898232047e-01), RC(1.6149708956621816247083215106334544434974e+00), 0, 0}, 338 {RC(8.8735762208534719663211694051981022704884e-01), 0, 0, RC(-2.9754597821085367558513632804709301581977e+00), RC(5.6007170094881630597990392548350098923829e+00), RC(-5.9156074505366744680014930189941657351840e+00), RC(2.2029689156134927016879142540807638331238e-01), RC(1.0155097824462216666143271340902996997549e-01), RC(1.1514345647386055909780397752125850553556e+00), RC(1.9297101665271239396134361900805843653065e+00), 0, 0, 0} 339 }; 340 const PetscReal b[13] = {RC(4.4729564666695714203015840429049382466467e-02), 0, 0, 0, 0, RC(1.5691033527708199813368698010726645409175e-01), RC(1.8460973408151637740702451873526277892035e-01), RC(2.2516380602086991042479419400350721970920e-01), RC(1.4794615651970234687005179885449141753736e-01), RC(7.6055542444955825269798361910336491012732e-02), RC(1.2277290235018619610824346315921437388535e-01), RC(4.1811958638991631583384842800871882376786e-02), 0}; 341 const PetscReal bembed[13] = {RC(4.5847111400495925878664730122010282095875e-02), 0, 0, 0, 0, RC(2.6231891404152387437443356584845803392392e-01), RC(1.9169372337852611904485738635688429008025e-01), RC(2.1709172327902618330978407422906448568196e-01), RC(1.2738189624833706796803169450656737867900e-01), RC(1.1510530385365326258240515750043192148894e-01), 0, 0, RC(4.0561327798437566841823391436583608050053e-02)}; 342 PetscCall(TSRKRegister(TSRK8VR, 8, 13, &A[0][0], b, NULL, bembed, 0, NULL)); 343 } 344 #undef RC 345 PetscFunctionReturn(PETSC_SUCCESS); 346 } 347 348 /*@C 349 TSRKRegisterDestroy - Frees the list of schemes that were registered by `TSRKRegister()`. 350 351 Not Collective 352 353 Level: advanced 354 355 .seealso: [](ch_ts), `TSRK`, `TSRKRegister()`, `TSRKRegisterAll()` 356 @*/ 357 PetscErrorCode TSRKRegisterDestroy(void) 358 { 359 RKTableauLink link; 360 361 PetscFunctionBegin; 362 while ((link = RKTableauList)) { 363 RKTableau t = &link->tab; 364 RKTableauList = link->next; 365 PetscCall(PetscFree3(t->A, t->b, t->c)); 366 PetscCall(PetscFree(t->bembed)); 367 PetscCall(PetscFree(t->binterp)); 368 PetscCall(PetscFree(t->name)); 369 PetscCall(PetscFree(link)); 370 } 371 TSRKRegisterAllCalled = PETSC_FALSE; 372 PetscFunctionReturn(PETSC_SUCCESS); 373 } 374 375 /*@C 376 TSRKInitializePackage - This function initializes everything in the `TSRK` package. It is called 377 from `TSInitializePackage()`. 378 379 Level: developer 380 381 .seealso: [](ch_ts), `TSInitializePackage()`, `PetscInitialize()`, `TSRKFinalizePackage()` 382 @*/ 383 PetscErrorCode TSRKInitializePackage(void) 384 { 385 PetscFunctionBegin; 386 if (TSRKPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 387 TSRKPackageInitialized = PETSC_TRUE; 388 PetscCall(TSRKRegisterAll()); 389 PetscCall(PetscRegisterFinalize(TSRKFinalizePackage)); 390 PetscFunctionReturn(PETSC_SUCCESS); 391 } 392 393 /*@C 394 TSRKFinalizePackage - This function destroys everything in the `TSRK` package. It is 395 called from `PetscFinalize()`. 396 397 Level: developer 398 399 .seealso: [](ch_ts), `PetscFinalize()`, `TSRKInitializePackage()` 400 @*/ 401 PetscErrorCode TSRKFinalizePackage(void) 402 { 403 PetscFunctionBegin; 404 TSRKPackageInitialized = PETSC_FALSE; 405 PetscCall(TSRKRegisterDestroy()); 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*@C 410 TSRKRegister - register an `TSRK` scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 411 412 Not Collective, but the same schemes should be registered on all processes on which they will be used, No Fortran Support 413 414 Input Parameters: 415 + name - identifier for method 416 . order - approximation order of method 417 . s - number of stages, this is the dimension of the matrices below 418 . A - stage coefficients (dimension s*s, row-major) 419 . b - step completion table (dimension s; NULL to use last row of A) 420 . c - abscissa (dimension s; NULL to use row sums of A) 421 . bembed - completion table for embedded method (dimension s; NULL if not available) 422 . p - Order of the interpolation scheme, equal to the number of columns of binterp 423 - binterp - Coefficients of the interpolation formula (dimension s*p; NULL to reuse b with p=1) 424 425 Level: advanced 426 427 Note: 428 Several `TSRK` methods are provided, this function is only needed to create new methods. 429 430 .seealso: [](ch_ts), `TSRK` 431 @*/ 432 PetscErrorCode TSRKRegister(TSRKType name, PetscInt order, PetscInt s, const PetscReal A[], const PetscReal b[], const PetscReal c[], const PetscReal bembed[], PetscInt p, const PetscReal binterp[]) 433 { 434 RKTableauLink link; 435 RKTableau t; 436 PetscInt i, j; 437 438 PetscFunctionBegin; 439 PetscAssertPointer(name, 1); 440 PetscAssertPointer(A, 4); 441 if (b) PetscAssertPointer(b, 5); 442 if (c) PetscAssertPointer(c, 6); 443 if (bembed) PetscAssertPointer(bembed, 7); 444 if (binterp || p > 1) PetscAssertPointer(binterp, 9); 445 PetscCheck(s >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected number of stages s %" PetscInt_FMT " >= 0", s); 446 447 PetscCall(TSRKInitializePackage()); 448 PetscCall(PetscNew(&link)); 449 t = &link->tab; 450 451 PetscCall(PetscStrallocpy(name, &t->name)); 452 t->order = order; 453 t->s = s; 454 PetscCall(PetscMalloc3(s * s, &t->A, s, &t->b, s, &t->c)); 455 PetscCall(PetscArraycpy(t->A, A, s * s)); 456 if (b) PetscCall(PetscArraycpy(t->b, b, s)); 457 else 458 for (i = 0; i < s; i++) t->b[i] = A[(s - 1) * s + i]; 459 if (c) PetscCall(PetscArraycpy(t->c, c, s)); 460 else 461 for (i = 0; i < s; i++) 462 for (j = 0, t->c[i] = 0; j < s; j++) t->c[i] += A[i * s + j]; 463 t->FSAL = PETSC_TRUE; 464 for (i = 0; i < s; i++) 465 if (t->A[(s - 1) * s + i] != t->b[i]) t->FSAL = PETSC_FALSE; 466 467 if (bembed) { 468 PetscCall(PetscMalloc1(s, &t->bembed)); 469 PetscCall(PetscArraycpy(t->bembed, bembed, s)); 470 } 471 472 if (!binterp) { 473 p = 1; 474 binterp = t->b; 475 } 476 t->p = p; 477 PetscCall(PetscMalloc1(s * p, &t->binterp)); 478 PetscCall(PetscArraycpy(t->binterp, binterp, s * p)); 479 480 link->next = RKTableauList; 481 RKTableauList = link; 482 PetscFunctionReturn(PETSC_SUCCESS); 483 } 484 485 static PetscErrorCode TSRKGetTableau_RK(TS ts, PetscInt *s, const PetscReal **A, const PetscReal **b, const PetscReal **c, const PetscReal **bembed, PetscInt *p, const PetscReal **binterp, PetscBool *FSAL) 486 { 487 TS_RK *rk = (TS_RK *)ts->data; 488 RKTableau tab = rk->tableau; 489 490 PetscFunctionBegin; 491 if (s) *s = tab->s; 492 if (A) *A = tab->A; 493 if (b) *b = tab->b; 494 if (c) *c = tab->c; 495 if (bembed) *bembed = tab->bembed; 496 if (p) *p = tab->p; 497 if (binterp) *binterp = tab->binterp; 498 if (FSAL) *FSAL = tab->FSAL; 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 /*@C 503 TSRKGetTableau - Get info on the `TSRK` tableau 504 505 Not Collective 506 507 Input Parameter: 508 . ts - timestepping context 509 510 Output Parameters: 511 + s - number of stages, this is the dimension of the matrices below 512 . A - stage coefficients (dimension s*s, row-major) 513 . b - step completion table (dimension s) 514 . c - abscissa (dimension s) 515 . bembed - completion table for embedded method (dimension s; NULL if not available) 516 . p - Order of the interpolation scheme, equal to the number of columns of binterp 517 . binterp - Coefficients of the interpolation formula (dimension s*p) 518 - FSAL - whether or not the scheme has the First Same As Last property 519 520 Level: developer 521 522 .seealso: [](ch_ts), `TSRK`, `TSRKRegister()`, `TSRKSetType()` 523 @*/ 524 PetscErrorCode TSRKGetTableau(TS ts, PetscInt *s, const PetscReal **A, const PetscReal **b, const PetscReal **c, const PetscReal **bembed, PetscInt *p, const PetscReal **binterp, PetscBool *FSAL) 525 { 526 PetscFunctionBegin; 527 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 528 PetscUseMethod(ts, "TSRKGetTableau_C", (TS, PetscInt *, const PetscReal **, const PetscReal **, const PetscReal **, const PetscReal **, PetscInt *, const PetscReal **, PetscBool *), (ts, s, A, b, c, bembed, p, binterp, FSAL)); 529 PetscFunctionReturn(PETSC_SUCCESS); 530 } 531 532 /* 533 This is for single-step RK method 534 The step completion formula is 535 536 x1 = x0 + h b^T YdotRHS 537 538 This function can be called before or after ts->vec_sol has been updated. 539 Suppose we have a completion formula (b) and an embedded formula (be) of different order. 540 We can write 541 542 x1e = x0 + h be^T YdotRHS 543 = x1 - h b^T YdotRHS + h be^T YdotRHS 544 = x1 + h (be - b)^T YdotRHS 545 546 so we can evaluate the method with different order even after the step has been optimistically completed. 547 */ 548 static PetscErrorCode TSEvaluateStep_RK(TS ts, PetscInt order, Vec X, PetscBool *done) 549 { 550 TS_RK *rk = (TS_RK *)ts->data; 551 RKTableau tab = rk->tableau; 552 PetscScalar *w = rk->work; 553 PetscReal h; 554 PetscInt s = tab->s, j; 555 556 PetscFunctionBegin; 557 switch (rk->status) { 558 case TS_STEP_INCOMPLETE: 559 case TS_STEP_PENDING: 560 h = ts->time_step; 561 break; 562 case TS_STEP_COMPLETE: 563 h = ts->ptime - ts->ptime_prev; 564 break; 565 default: 566 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus"); 567 } 568 if (order == tab->order) { 569 if (rk->status == TS_STEP_INCOMPLETE) { 570 PetscCall(VecCopy(ts->vec_sol, X)); 571 for (j = 0; j < s; j++) w[j] = h * tab->b[j] / rk->dtratio; 572 PetscCall(VecMAXPY(X, s, w, rk->YdotRHS)); 573 } else PetscCall(VecCopy(ts->vec_sol, X)); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } else if (order == tab->order - 1) { 576 if (!tab->bembed) goto unavailable; 577 if (rk->status == TS_STEP_INCOMPLETE) { /*Complete with the embedded method (be)*/ 578 PetscCall(VecCopy(ts->vec_sol, X)); 579 for (j = 0; j < s; j++) w[j] = h * tab->bembed[j]; 580 PetscCall(VecMAXPY(X, s, w, rk->YdotRHS)); 581 } else { /*Rollback and re-complete using (be-b) */ 582 PetscCall(VecCopy(ts->vec_sol, X)); 583 for (j = 0; j < s; j++) w[j] = h * (tab->bembed[j] - tab->b[j]); 584 PetscCall(VecMAXPY(X, s, w, rk->YdotRHS)); 585 } 586 if (done) *done = PETSC_TRUE; 587 PetscFunctionReturn(PETSC_SUCCESS); 588 } 589 unavailable: 590 PetscCheck(done, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "RK '%s' of order %" PetscInt_FMT " cannot evaluate step at order %" PetscInt_FMT ". Consider using -ts_adapt_type none or a different method that has an embedded estimate.", tab->name, 591 tab->order, order); 592 *done = PETSC_FALSE; 593 PetscFunctionReturn(PETSC_SUCCESS); 594 } 595 596 static PetscErrorCode TSForwardCostIntegral_RK(TS ts) 597 { 598 TS_RK *rk = (TS_RK *)ts->data; 599 TS quadts = ts->quadraturets; 600 RKTableau tab = rk->tableau; 601 const PetscInt s = tab->s; 602 const PetscReal *b = tab->b, *c = tab->c; 603 Vec *Y = rk->Y; 604 PetscInt i; 605 606 PetscFunctionBegin; 607 /* No need to backup quadts->vec_sol since it can be reverted in TSRollBack_RK */ 608 for (i = s - 1; i >= 0; i--) { 609 /* Evolve quadrature TS solution to compute integrals */ 610 PetscCall(TSComputeRHSFunction(quadts, rk->ptime + rk->time_step * c[i], Y[i], ts->vec_costintegrand)); 611 PetscCall(VecAXPY(quadts->vec_sol, rk->time_step * b[i], ts->vec_costintegrand)); 612 } 613 PetscFunctionReturn(PETSC_SUCCESS); 614 } 615 616 static PetscErrorCode TSAdjointCostIntegral_RK(TS ts) 617 { 618 TS_RK *rk = (TS_RK *)ts->data; 619 RKTableau tab = rk->tableau; 620 TS quadts = ts->quadraturets; 621 const PetscInt s = tab->s; 622 const PetscReal *b = tab->b, *c = tab->c; 623 Vec *Y = rk->Y; 624 PetscInt i; 625 626 PetscFunctionBegin; 627 for (i = s - 1; i >= 0; i--) { 628 /* Evolve quadrature TS solution to compute integrals */ 629 PetscCall(TSComputeRHSFunction(quadts, ts->ptime + ts->time_step * (1.0 - c[i]), Y[i], ts->vec_costintegrand)); 630 PetscCall(VecAXPY(quadts->vec_sol, -ts->time_step * b[i], ts->vec_costintegrand)); 631 } 632 PetscFunctionReturn(PETSC_SUCCESS); 633 } 634 635 static PetscErrorCode TSRollBack_RK(TS ts) 636 { 637 TS_RK *rk = (TS_RK *)ts->data; 638 TS quadts = ts->quadraturets; 639 RKTableau tab = rk->tableau; 640 const PetscInt s = tab->s; 641 const PetscReal *b = tab->b, *c = tab->c; 642 PetscScalar *w = rk->work; 643 Vec *Y = rk->Y, *YdotRHS = rk->YdotRHS; 644 PetscInt j; 645 PetscReal h; 646 647 PetscFunctionBegin; 648 switch (rk->status) { 649 case TS_STEP_INCOMPLETE: 650 case TS_STEP_PENDING: 651 h = ts->time_step; 652 break; 653 case TS_STEP_COMPLETE: 654 h = ts->ptime - ts->ptime_prev; 655 break; 656 default: 657 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus"); 658 } 659 for (j = 0; j < s; j++) w[j] = -h * b[j]; 660 PetscCall(VecMAXPY(ts->vec_sol, s, w, YdotRHS)); 661 if (quadts && ts->costintegralfwd) { 662 for (j = 0; j < s; j++) { 663 /* Revert the quadrature TS solution */ 664 PetscCall(TSComputeRHSFunction(quadts, rk->ptime + h * c[j], Y[j], ts->vec_costintegrand)); 665 PetscCall(VecAXPY(quadts->vec_sol, -h * b[j], ts->vec_costintegrand)); 666 } 667 } 668 PetscFunctionReturn(PETSC_SUCCESS); 669 } 670 671 static PetscErrorCode TSForwardStep_RK(TS ts) 672 { 673 TS_RK *rk = (TS_RK *)ts->data; 674 RKTableau tab = rk->tableau; 675 Mat J, *MatsFwdSensipTemp = rk->MatsFwdSensipTemp; 676 const PetscInt s = tab->s; 677 const PetscReal *A = tab->A, *c = tab->c, *b = tab->b; 678 Vec *Y = rk->Y; 679 PetscInt i, j; 680 PetscReal stage_time, h = ts->time_step; 681 PetscBool zero; 682 683 PetscFunctionBegin; 684 PetscCall(MatCopy(ts->mat_sensip, rk->MatFwdSensip0, SAME_NONZERO_PATTERN)); 685 PetscCall(TSGetRHSJacobian(ts, &J, NULL, NULL, NULL)); 686 687 for (i = 0; i < s; i++) { 688 stage_time = ts->ptime + h * c[i]; 689 zero = PETSC_FALSE; 690 if (b[i] == 0 && i == s - 1) zero = PETSC_TRUE; 691 /* TLM Stage values */ 692 if (!i) { 693 PetscCall(MatCopy(ts->mat_sensip, rk->MatsFwdStageSensip[i], SAME_NONZERO_PATTERN)); 694 } else if (!zero) { 695 PetscCall(MatZeroEntries(rk->MatsFwdStageSensip[i])); 696 for (j = 0; j < i; j++) PetscCall(MatAXPY(rk->MatsFwdStageSensip[i], h * A[i * s + j], MatsFwdSensipTemp[j], SAME_NONZERO_PATTERN)); 697 PetscCall(MatAXPY(rk->MatsFwdStageSensip[i], 1., ts->mat_sensip, SAME_NONZERO_PATTERN)); 698 } else { 699 PetscCall(MatZeroEntries(rk->MatsFwdStageSensip[i])); 700 } 701 702 PetscCall(TSComputeRHSJacobian(ts, stage_time, Y[i], J, J)); 703 PetscCall(MatMatMult(J, rk->MatsFwdStageSensip[i], MAT_REUSE_MATRIX, PETSC_DETERMINE, &MatsFwdSensipTemp[i])); 704 if (ts->Jacprhs) { 705 PetscCall(TSComputeRHSJacobianP(ts, stage_time, Y[i], ts->Jacprhs)); /* get f_p */ 706 if (ts->vecs_sensi2p) { /* TLM used for 2nd-order adjoint */ 707 PetscScalar *xarr; 708 PetscCall(MatDenseGetColumn(MatsFwdSensipTemp[i], 0, &xarr)); 709 PetscCall(VecPlaceArray(rk->VecDeltaFwdSensipCol, xarr)); 710 PetscCall(MatMultAdd(ts->Jacprhs, ts->vec_dir, rk->VecDeltaFwdSensipCol, rk->VecDeltaFwdSensipCol)); 711 PetscCall(VecResetArray(rk->VecDeltaFwdSensipCol)); 712 PetscCall(MatDenseRestoreColumn(MatsFwdSensipTemp[i], &xarr)); 713 } else { 714 PetscCall(MatAXPY(MatsFwdSensipTemp[i], 1., ts->Jacprhs, SUBSET_NONZERO_PATTERN)); 715 } 716 } 717 } 718 719 for (i = 0; i < s; i++) PetscCall(MatAXPY(ts->mat_sensip, h * b[i], rk->MatsFwdSensipTemp[i], SAME_NONZERO_PATTERN)); 720 rk->status = TS_STEP_COMPLETE; 721 PetscFunctionReturn(PETSC_SUCCESS); 722 } 723 724 static PetscErrorCode TSForwardGetStages_RK(TS ts, PetscInt *ns, Mat **stagesensip) 725 { 726 TS_RK *rk = (TS_RK *)ts->data; 727 RKTableau tab = rk->tableau; 728 729 PetscFunctionBegin; 730 if (ns) *ns = tab->s; 731 if (stagesensip) *stagesensip = rk->MatsFwdStageSensip; 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 static PetscErrorCode TSForwardSetUp_RK(TS ts) 736 { 737 TS_RK *rk = (TS_RK *)ts->data; 738 RKTableau tab = rk->tableau; 739 PetscInt i; 740 741 PetscFunctionBegin; 742 /* backup sensitivity results for roll-backs */ 743 PetscCall(MatDuplicate(ts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &rk->MatFwdSensip0)); 744 745 PetscCall(PetscMalloc1(tab->s, &rk->MatsFwdStageSensip)); 746 PetscCall(PetscMalloc1(tab->s, &rk->MatsFwdSensipTemp)); 747 for (i = 0; i < tab->s; i++) { 748 PetscCall(MatDuplicate(ts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &rk->MatsFwdStageSensip[i])); 749 PetscCall(MatDuplicate(ts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &rk->MatsFwdSensipTemp[i])); 750 } 751 PetscCall(VecDuplicate(ts->vec_sol, &rk->VecDeltaFwdSensipCol)); 752 PetscFunctionReturn(PETSC_SUCCESS); 753 } 754 755 static PetscErrorCode TSForwardReset_RK(TS ts) 756 { 757 TS_RK *rk = (TS_RK *)ts->data; 758 RKTableau tab = rk->tableau; 759 PetscInt i; 760 761 PetscFunctionBegin; 762 PetscCall(MatDestroy(&rk->MatFwdSensip0)); 763 if (rk->MatsFwdStageSensip) { 764 for (i = 0; i < tab->s; i++) PetscCall(MatDestroy(&rk->MatsFwdStageSensip[i])); 765 PetscCall(PetscFree(rk->MatsFwdStageSensip)); 766 } 767 if (rk->MatsFwdSensipTemp) { 768 for (i = 0; i < tab->s; i++) PetscCall(MatDestroy(&rk->MatsFwdSensipTemp[i])); 769 PetscCall(PetscFree(rk->MatsFwdSensipTemp)); 770 } 771 PetscCall(VecDestroy(&rk->VecDeltaFwdSensipCol)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 static PetscErrorCode TSStep_RK(TS ts) 776 { 777 TS_RK *rk = (TS_RK *)ts->data; 778 RKTableau tab = rk->tableau; 779 const PetscInt s = tab->s; 780 const PetscReal *A = tab->A, *c = tab->c; 781 PetscScalar *w = rk->work; 782 Vec *Y = rk->Y, *YdotRHS = rk->YdotRHS; 783 PetscBool FSAL = (PetscBool)(tab->FSAL && !rk->newtableau); 784 TSAdapt adapt; 785 PetscInt i, j; 786 PetscInt rejections = 0; 787 PetscBool stageok, accept = PETSC_TRUE; 788 PetscReal next_time_step = ts->time_step; 789 790 PetscFunctionBegin; 791 if (ts->steprollback || ts->steprestart) FSAL = PETSC_FALSE; 792 if (FSAL) PetscCall(VecCopy(YdotRHS[s - 1], YdotRHS[0])); 793 rk->newtableau = PETSC_FALSE; 794 795 rk->status = TS_STEP_INCOMPLETE; 796 while (!ts->reason && rk->status != TS_STEP_COMPLETE) { 797 PetscReal t = ts->ptime; 798 PetscReal h = ts->time_step; 799 for (i = 0; i < s; i++) { 800 rk->stage_time = t + h * c[i]; 801 PetscCall(TSPreStage(ts, rk->stage_time)); 802 PetscCall(VecCopy(ts->vec_sol, Y[i])); 803 for (j = 0; j < i; j++) w[j] = h * A[i * s + j]; 804 PetscCall(VecMAXPY(Y[i], i, w, YdotRHS)); 805 PetscCall(TSPostStage(ts, rk->stage_time, i, Y)); 806 PetscCall(TSGetAdapt(ts, &adapt)); 807 PetscCall(TSAdaptCheckStage(adapt, ts, rk->stage_time, Y[i], &stageok)); 808 if (!stageok) goto reject_step; 809 if (FSAL && !i) continue; 810 PetscCall(TSComputeRHSFunction(ts, t + h * c[i], Y[i], YdotRHS[i])); 811 } 812 813 rk->status = TS_STEP_INCOMPLETE; 814 PetscCall(TSEvaluateStep(ts, tab->order, ts->vec_sol, NULL)); 815 rk->status = TS_STEP_PENDING; 816 PetscCall(TSGetAdapt(ts, &adapt)); 817 PetscCall(TSAdaptCandidatesClear(adapt)); 818 PetscCall(TSAdaptCandidateAdd(adapt, tab->name, tab->order, 1, tab->ccfl, (PetscReal)tab->s, PETSC_TRUE)); 819 PetscCall(TSAdaptChoose(adapt, ts, ts->time_step, NULL, &next_time_step, &accept)); 820 rk->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 821 if (!accept) { /* Roll back the current step */ 822 PetscCall(TSRollBack_RK(ts)); 823 ts->time_step = next_time_step; 824 goto reject_step; 825 } 826 827 if (ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 828 rk->ptime = ts->ptime; 829 rk->time_step = ts->time_step; 830 } 831 832 ts->ptime += ts->time_step; 833 ts->time_step = next_time_step; 834 break; 835 836 reject_step: 837 ts->reject++; 838 accept = PETSC_FALSE; 839 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 840 ts->reason = TS_DIVERGED_STEP_REJECTED; 841 PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections)); 842 } 843 } 844 PetscFunctionReturn(PETSC_SUCCESS); 845 } 846 847 static PetscErrorCode TSAdjointSetUp_RK(TS ts) 848 { 849 TS_RK *rk = (TS_RK *)ts->data; 850 RKTableau tab = rk->tableau; 851 PetscInt s = tab->s; 852 853 PetscFunctionBegin; 854 if (ts->adjointsetupcalled) PetscFunctionReturn(PETSC_SUCCESS); 855 ts->adjointsetupcalled = PETSC_TRUE; 856 PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], s * ts->numcost, &rk->VecsDeltaLam)); 857 PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &rk->VecsSensiTemp)); 858 if (ts->vecs_sensip) PetscCall(VecDuplicate(ts->vecs_sensip[0], &rk->VecDeltaMu)); 859 if (ts->vecs_sensi2) { 860 PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], s * ts->numcost, &rk->VecsDeltaLam2)); 861 PetscCall(VecDuplicateVecs(ts->vecs_sensi2[0], ts->numcost, &rk->VecsSensi2Temp)); 862 } 863 if (ts->vecs_sensi2p) PetscCall(VecDuplicate(ts->vecs_sensi2p[0], &rk->VecDeltaMu2)); 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 /* 868 Assumptions: 869 - TSStep_RK() always evaluates the step with b, not bembed. 870 */ 871 static PetscErrorCode TSAdjointStep_RK(TS ts) 872 { 873 TS_RK *rk = (TS_RK *)ts->data; 874 TS quadts = ts->quadraturets; 875 RKTableau tab = rk->tableau; 876 Mat J, Jpre, Jquad; 877 const PetscInt s = tab->s; 878 const PetscReal *A = tab->A, *b = tab->b, *c = tab->c; 879 PetscScalar *w = rk->work, *xarr; 880 Vec *Y = rk->Y, *VecsDeltaLam = rk->VecsDeltaLam, VecDeltaMu = rk->VecDeltaMu, *VecsSensiTemp = rk->VecsSensiTemp; 881 Vec *VecsDeltaLam2 = rk->VecsDeltaLam2, VecDeltaMu2 = rk->VecDeltaMu2, *VecsSensi2Temp = rk->VecsSensi2Temp; 882 Vec VecDRDUTransCol = ts->vec_drdu_col, VecDRDPTransCol = ts->vec_drdp_col; 883 PetscInt i, j, nadj; 884 PetscReal t = ts->ptime; 885 PetscReal h = ts->time_step; 886 887 PetscFunctionBegin; 888 rk->status = TS_STEP_INCOMPLETE; 889 890 PetscCall(TSGetRHSJacobian(ts, &J, &Jpre, NULL, NULL)); 891 if (quadts) PetscCall(TSGetRHSJacobian(quadts, &Jquad, NULL, NULL, NULL)); 892 for (i = s - 1; i >= 0; i--) { 893 if (tab->FSAL && i == s - 1) { 894 /* VecsDeltaLam[nadj*s+s-1] are initialized with zeros and the values never change.*/ 895 continue; 896 } 897 rk->stage_time = t + h * (1.0 - c[i]); 898 PetscCall(TSComputeSNESJacobian(ts, Y[i], J, Jpre)); 899 if (quadts) PetscCall(TSComputeRHSJacobian(quadts, rk->stage_time, Y[i], Jquad, Jquad)); /* get r_u^T */ 900 if (ts->vecs_sensip) { 901 PetscCall(TSComputeRHSJacobianP(ts, rk->stage_time, Y[i], ts->Jacprhs)); /* get f_p */ 902 if (quadts) PetscCall(TSComputeRHSJacobianP(quadts, rk->stage_time, Y[i], quadts->Jacprhs)); /* get f_p for the quadrature */ 903 } 904 905 if (b[i]) { 906 for (j = i + 1; j < s; j++) w[j - i - 1] = A[j * s + i] / b[i]; /* coefficients for computing VecsSensiTemp */ 907 } else { 908 for (j = i + 1; j < s; j++) w[j - i - 1] = A[j * s + i]; /* coefficients for computing VecsSensiTemp */ 909 } 910 911 for (nadj = 0; nadj < ts->numcost; nadj++) { 912 /* Stage values of lambda */ 913 if (b[i]) { 914 /* lambda_{n+1} + \sum_{j=i+1}^s a_{ji}/b[i]*lambda_{s,j} */ 915 PetscCall(VecCopy(ts->vecs_sensi[nadj], VecsSensiTemp[nadj])); /* VecDeltaLam is an vec array of size s by numcost */ 916 PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1])); 917 PetscCall(MatMultTranspose(J, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i])); /* VecsSensiTemp will be reused by 2nd-order adjoint */ 918 PetscCall(VecScale(VecsDeltaLam[nadj * s + i], -h * b[i])); 919 if (quadts) { 920 PetscCall(MatDenseGetColumn(Jquad, nadj, &xarr)); 921 PetscCall(VecPlaceArray(VecDRDUTransCol, xarr)); 922 PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], -h * b[i], VecDRDUTransCol)); 923 PetscCall(VecResetArray(VecDRDUTransCol)); 924 PetscCall(MatDenseRestoreColumn(Jquad, &xarr)); 925 } 926 } else { 927 /* \sum_{j=i+1}^s a_{ji}*lambda_{s,j} */ 928 PetscCall(VecSet(VecsSensiTemp[nadj], 0)); 929 PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1])); 930 PetscCall(MatMultTranspose(J, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i])); 931 PetscCall(VecScale(VecsDeltaLam[nadj * s + i], -h)); 932 } 933 934 /* Stage values of mu */ 935 if (ts->vecs_sensip) { 936 PetscCall(MatMultTranspose(ts->Jacprhs, VecsSensiTemp[nadj], VecDeltaMu)); 937 if (b[i]) { 938 PetscCall(VecScale(VecDeltaMu, -h * b[i])); 939 if (quadts) { 940 PetscCall(MatDenseGetColumn(quadts->Jacprhs, nadj, &xarr)); 941 PetscCall(VecPlaceArray(VecDRDPTransCol, xarr)); 942 PetscCall(VecAXPY(VecDeltaMu, -h * b[i], VecDRDPTransCol)); 943 PetscCall(VecResetArray(VecDRDPTransCol)); 944 PetscCall(MatDenseRestoreColumn(quadts->Jacprhs, &xarr)); 945 } 946 } else { 947 PetscCall(VecScale(VecDeltaMu, -h)); 948 } 949 PetscCall(VecAXPY(ts->vecs_sensip[nadj], 1., VecDeltaMu)); /* update sensip for each stage */ 950 } 951 } 952 953 if (ts->vecs_sensi2 && ts->forward_solve) { /* 2nd-order adjoint, TLM mode has to be turned on */ 954 /* Get w1 at t_{n+1} from TLM matrix */ 955 PetscCall(MatDenseGetColumn(rk->MatsFwdStageSensip[i], 0, &xarr)); 956 PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr)); 957 /* lambda_s^T F_UU w_1 */ 958 PetscCall(TSComputeRHSHessianProductFunctionUU(ts, rk->stage_time, Y[i], VecsSensiTemp, ts->vec_sensip_col, ts->vecs_guu)); 959 if (quadts) { 960 /* R_UU w_1 */ 961 PetscCall(TSComputeRHSHessianProductFunctionUU(quadts, rk->stage_time, Y[i], NULL, ts->vec_sensip_col, ts->vecs_guu)); 962 } 963 if (ts->vecs_sensip) { 964 /* lambda_s^T F_UP w_2 */ 965 PetscCall(TSComputeRHSHessianProductFunctionUP(ts, rk->stage_time, Y[i], VecsSensiTemp, ts->vec_dir, ts->vecs_gup)); 966 if (quadts) { 967 /* R_UP w_2 */ 968 PetscCall(TSComputeRHSHessianProductFunctionUP(quadts, rk->stage_time, Y[i], NULL, ts->vec_sensip_col, ts->vecs_gup)); 969 } 970 } 971 if (ts->vecs_sensi2p) { 972 /* lambda_s^T F_PU w_1 */ 973 PetscCall(TSComputeRHSHessianProductFunctionPU(ts, rk->stage_time, Y[i], VecsSensiTemp, ts->vec_sensip_col, ts->vecs_gpu)); 974 /* lambda_s^T F_PP w_2 */ 975 PetscCall(TSComputeRHSHessianProductFunctionPP(ts, rk->stage_time, Y[i], VecsSensiTemp, ts->vec_dir, ts->vecs_gpp)); 976 if (b[i] && quadts) { 977 /* R_PU w_1 */ 978 PetscCall(TSComputeRHSHessianProductFunctionPU(quadts, rk->stage_time, Y[i], NULL, ts->vec_sensip_col, ts->vecs_gpu)); 979 /* R_PP w_2 */ 980 PetscCall(TSComputeRHSHessianProductFunctionPP(quadts, rk->stage_time, Y[i], NULL, ts->vec_dir, ts->vecs_gpp)); 981 } 982 } 983 PetscCall(VecResetArray(ts->vec_sensip_col)); 984 PetscCall(MatDenseRestoreColumn(rk->MatsFwdStageSensip[i], &xarr)); 985 986 for (nadj = 0; nadj < ts->numcost; nadj++) { 987 /* Stage values of lambda */ 988 if (b[i]) { 989 /* J_i^T*(Lambda_{n+1}+\sum_{j=i+1}^s a_{ji}/b_i*Lambda_{s,j} */ 990 PetscCall(VecCopy(ts->vecs_sensi2[nadj], VecsSensi2Temp[nadj])); 991 PetscCall(VecMAXPY(VecsSensi2Temp[nadj], s - i - 1, w, &VecsDeltaLam2[nadj * s + i + 1])); 992 PetscCall(MatMultTranspose(J, VecsSensi2Temp[nadj], VecsDeltaLam2[nadj * s + i])); 993 PetscCall(VecScale(VecsDeltaLam2[nadj * s + i], -h * b[i])); 994 PetscCall(VecAXPY(VecsDeltaLam2[nadj * s + i], -h * b[i], ts->vecs_guu[nadj])); 995 if (ts->vecs_sensip) PetscCall(VecAXPY(VecsDeltaLam2[nadj * s + i], -h * b[i], ts->vecs_gup[nadj])); 996 } else { 997 /* \sum_{j=i+1}^s a_{ji}*Lambda_{s,j} */ 998 PetscCall(VecSet(VecsDeltaLam2[nadj * s + i], 0)); 999 PetscCall(VecMAXPY(VecsSensi2Temp[nadj], s - i - 1, w, &VecsDeltaLam2[nadj * s + i + 1])); 1000 PetscCall(MatMultTranspose(J, VecsSensi2Temp[nadj], VecsDeltaLam2[nadj * s + i])); 1001 PetscCall(VecScale(VecsDeltaLam2[nadj * s + i], -h)); 1002 PetscCall(VecAXPY(VecsDeltaLam2[nadj * s + i], -h, ts->vecs_guu[nadj])); 1003 if (ts->vecs_sensip) PetscCall(VecAXPY(VecsDeltaLam2[nadj * s + i], -h, ts->vecs_gup[nadj])); 1004 } 1005 if (ts->vecs_sensi2p) { /* 2nd-order adjoint for parameters */ 1006 PetscCall(MatMultTranspose(ts->Jacprhs, VecsSensi2Temp[nadj], VecDeltaMu2)); 1007 if (b[i]) { 1008 PetscCall(VecScale(VecDeltaMu2, -h * b[i])); 1009 PetscCall(VecAXPY(VecDeltaMu2, -h * b[i], ts->vecs_gpu[nadj])); 1010 PetscCall(VecAXPY(VecDeltaMu2, -h * b[i], ts->vecs_gpp[nadj])); 1011 } else { 1012 PetscCall(VecScale(VecDeltaMu2, -h)); 1013 PetscCall(VecAXPY(VecDeltaMu2, -h, ts->vecs_gpu[nadj])); 1014 PetscCall(VecAXPY(VecDeltaMu2, -h, ts->vecs_gpp[nadj])); 1015 } 1016 PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], 1, VecDeltaMu2)); /* update sensi2p for each stage */ 1017 } 1018 } 1019 } 1020 } 1021 1022 for (j = 0; j < s; j++) w[j] = 1.0; 1023 for (nadj = 0; nadj < ts->numcost; nadj++) { /* no need to do this for mu's */ 1024 PetscCall(VecMAXPY(ts->vecs_sensi[nadj], s, w, &VecsDeltaLam[nadj * s])); 1025 if (ts->vecs_sensi2) PetscCall(VecMAXPY(ts->vecs_sensi2[nadj], s, w, &VecsDeltaLam2[nadj * s])); 1026 } 1027 rk->status = TS_STEP_COMPLETE; 1028 PetscFunctionReturn(PETSC_SUCCESS); 1029 } 1030 1031 static PetscErrorCode TSAdjointReset_RK(TS ts) 1032 { 1033 TS_RK *rk = (TS_RK *)ts->data; 1034 RKTableau tab = rk->tableau; 1035 1036 PetscFunctionBegin; 1037 PetscCall(VecDestroyVecs(tab->s * ts->numcost, &rk->VecsDeltaLam)); 1038 PetscCall(VecDestroyVecs(ts->numcost, &rk->VecsSensiTemp)); 1039 PetscCall(VecDestroy(&rk->VecDeltaMu)); 1040 PetscCall(VecDestroyVecs(tab->s * ts->numcost, &rk->VecsDeltaLam2)); 1041 PetscCall(VecDestroy(&rk->VecDeltaMu2)); 1042 PetscCall(VecDestroyVecs(ts->numcost, &rk->VecsSensi2Temp)); 1043 PetscFunctionReturn(PETSC_SUCCESS); 1044 } 1045 1046 static PetscErrorCode TSInterpolate_RK(TS ts, PetscReal itime, Vec X) 1047 { 1048 TS_RK *rk = (TS_RK *)ts->data; 1049 PetscInt s = rk->tableau->s, p = rk->tableau->p, i, j; 1050 PetscReal h; 1051 PetscReal tt, t; 1052 PetscScalar *b; 1053 const PetscReal *B = rk->tableau->binterp; 1054 1055 PetscFunctionBegin; 1056 PetscCheck(B, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "TSRK %s does not have an interpolation formula", rk->tableau->name); 1057 1058 switch (rk->status) { 1059 case TS_STEP_INCOMPLETE: 1060 case TS_STEP_PENDING: 1061 h = ts->time_step; 1062 t = (itime - ts->ptime) / h; 1063 break; 1064 case TS_STEP_COMPLETE: 1065 h = ts->ptime - ts->ptime_prev; 1066 t = (itime - ts->ptime) / h + 1; /* In the interval [0,1] */ 1067 break; 1068 default: 1069 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus"); 1070 } 1071 PetscCall(PetscMalloc1(s, &b)); 1072 for (i = 0; i < s; i++) b[i] = 0; 1073 for (j = 0, tt = t; j < p; j++, tt *= t) { 1074 for (i = 0; i < s; i++) b[i] += h * B[i * p + j] * tt; 1075 } 1076 PetscCall(VecCopy(rk->Y[0], X)); 1077 PetscCall(VecMAXPY(X, s, b, rk->YdotRHS)); 1078 PetscCall(PetscFree(b)); 1079 PetscFunctionReturn(PETSC_SUCCESS); 1080 } 1081 1082 /*------------------------------------------------------------*/ 1083 1084 static PetscErrorCode TSRKTableauReset(TS ts) 1085 { 1086 TS_RK *rk = (TS_RK *)ts->data; 1087 RKTableau tab = rk->tableau; 1088 1089 PetscFunctionBegin; 1090 if (!tab) PetscFunctionReturn(PETSC_SUCCESS); 1091 PetscCall(PetscFree(rk->work)); 1092 PetscCall(VecDestroyVecs(tab->s, &rk->Y)); 1093 PetscCall(VecDestroyVecs(tab->s, &rk->YdotRHS)); 1094 PetscFunctionReturn(PETSC_SUCCESS); 1095 } 1096 1097 static PetscErrorCode TSReset_RK(TS ts) 1098 { 1099 PetscFunctionBegin; 1100 PetscCall(TSRKTableauReset(ts)); 1101 if (ts->use_splitrhsfunction) { 1102 PetscTryMethod(ts, "TSReset_RK_MultirateSplit_C", (TS), (ts)); 1103 } else { 1104 PetscTryMethod(ts, "TSReset_RK_MultirateNonsplit_C", (TS), (ts)); 1105 } 1106 PetscFunctionReturn(PETSC_SUCCESS); 1107 } 1108 1109 static PetscErrorCode DMCoarsenHook_TSRK(DM fine, DM coarse, void *ctx) 1110 { 1111 PetscFunctionBegin; 1112 PetscFunctionReturn(PETSC_SUCCESS); 1113 } 1114 1115 static PetscErrorCode DMRestrictHook_TSRK(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 1116 { 1117 PetscFunctionBegin; 1118 PetscFunctionReturn(PETSC_SUCCESS); 1119 } 1120 1121 static PetscErrorCode DMSubDomainHook_TSRK(DM dm, DM subdm, void *ctx) 1122 { 1123 PetscFunctionBegin; 1124 PetscFunctionReturn(PETSC_SUCCESS); 1125 } 1126 1127 static PetscErrorCode DMSubDomainRestrictHook_TSRK(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 1128 { 1129 PetscFunctionBegin; 1130 PetscFunctionReturn(PETSC_SUCCESS); 1131 } 1132 1133 static PetscErrorCode TSRKTableauSetUp(TS ts) 1134 { 1135 TS_RK *rk = (TS_RK *)ts->data; 1136 RKTableau tab = rk->tableau; 1137 1138 PetscFunctionBegin; 1139 PetscCall(PetscMalloc1(tab->s, &rk->work)); 1140 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &rk->Y)); 1141 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &rk->YdotRHS)); 1142 rk->newtableau = PETSC_TRUE; 1143 PetscFunctionReturn(PETSC_SUCCESS); 1144 } 1145 1146 static PetscErrorCode TSSetUp_RK(TS ts) 1147 { 1148 TS quadts = ts->quadraturets; 1149 DM dm; 1150 1151 PetscFunctionBegin; 1152 PetscCall(TSCheckImplicitTerm(ts)); 1153 PetscCall(TSRKTableauSetUp(ts)); 1154 if (quadts && ts->costintegralfwd) { 1155 Mat Jquad; 1156 PetscCall(TSGetRHSJacobian(quadts, &Jquad, NULL, NULL, NULL)); 1157 } 1158 PetscCall(TSGetDM(ts, &dm)); 1159 PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSRK, DMRestrictHook_TSRK, ts)); 1160 PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSRK, DMSubDomainRestrictHook_TSRK, ts)); 1161 if (ts->use_splitrhsfunction) { 1162 PetscTryMethod(ts, "TSSetUp_RK_MultirateSplit_C", (TS), (ts)); 1163 } else { 1164 PetscTryMethod(ts, "TSSetUp_RK_MultirateNonsplit_C", (TS), (ts)); 1165 } 1166 PetscFunctionReturn(PETSC_SUCCESS); 1167 } 1168 1169 static PetscErrorCode TSSetFromOptions_RK(TS ts, PetscOptionItems PetscOptionsObject) 1170 { 1171 TS_RK *rk = (TS_RK *)ts->data; 1172 1173 PetscFunctionBegin; 1174 PetscOptionsHeadBegin(PetscOptionsObject, "RK ODE solver options"); 1175 { 1176 RKTableauLink link; 1177 PetscInt count, choice; 1178 PetscBool flg, use_multirate = PETSC_FALSE; 1179 const char **namelist; 1180 1181 for (link = RKTableauList, count = 0; link; link = link->next, count++); 1182 PetscCall(PetscMalloc1(count, (char ***)&namelist)); 1183 for (link = RKTableauList, count = 0; link; link = link->next, count++) namelist[count] = link->tab.name; 1184 PetscCall(PetscOptionsBool("-ts_rk_multirate", "Use interpolation-based multirate RK method", "TSRKSetMultirate", rk->use_multirate, &use_multirate, &flg)); 1185 if (flg) PetscCall(TSRKSetMultirate(ts, use_multirate)); 1186 PetscCall(PetscOptionsEList("-ts_rk_type", "Family of RK method", "TSRKSetType", (const char *const *)namelist, count, rk->tableau->name, &choice, &flg)); 1187 if (flg) PetscCall(TSRKSetType(ts, namelist[choice])); 1188 PetscCall(PetscFree(namelist)); 1189 } 1190 PetscOptionsHeadEnd(); 1191 PetscOptionsBegin(PetscObjectComm((PetscObject)ts), NULL, "Multirate methods options", ""); 1192 PetscCall(PetscOptionsInt("-ts_rk_dtratio", "time step ratio between slow and fast", "", rk->dtratio, &rk->dtratio, NULL)); 1193 PetscOptionsEnd(); 1194 PetscFunctionReturn(PETSC_SUCCESS); 1195 } 1196 1197 static PetscErrorCode TSView_RK(TS ts, PetscViewer viewer) 1198 { 1199 TS_RK *rk = (TS_RK *)ts->data; 1200 PetscBool isascii; 1201 1202 PetscFunctionBegin; 1203 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1204 if (isascii) { 1205 RKTableau tab = rk->tableau; 1206 TSRKType rktype; 1207 const PetscReal *c; 1208 PetscInt s; 1209 char buf[512]; 1210 PetscBool FSAL; 1211 1212 PetscCall(TSRKGetType(ts, &rktype)); 1213 PetscCall(TSRKGetTableau(ts, &s, NULL, NULL, &c, NULL, NULL, NULL, &FSAL)); 1214 PetscCall(PetscViewerASCIIPrintf(viewer, " RK type %s\n", rktype)); 1215 PetscCall(PetscViewerASCIIPrintf(viewer, " Order: %" PetscInt_FMT "\n", tab->order)); 1216 PetscCall(PetscViewerASCIIPrintf(viewer, " FSAL property: %s\n", FSAL ? "yes" : "no")); 1217 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", s, c)); 1218 PetscCall(PetscViewerASCIIPrintf(viewer, " Abscissa c = %s\n", buf)); 1219 } 1220 PetscFunctionReturn(PETSC_SUCCESS); 1221 } 1222 1223 static PetscErrorCode TSLoad_RK(TS ts, PetscViewer viewer) 1224 { 1225 TSAdapt adapt; 1226 1227 PetscFunctionBegin; 1228 PetscCall(TSGetAdapt(ts, &adapt)); 1229 PetscCall(TSAdaptLoad(adapt, viewer)); 1230 PetscFunctionReturn(PETSC_SUCCESS); 1231 } 1232 1233 /*@ 1234 TSRKGetOrder - Get the order of the `TSRK` scheme 1235 1236 Not Collective 1237 1238 Input Parameter: 1239 . ts - timestepping context 1240 1241 Output Parameter: 1242 . order - order of `TSRK` scheme 1243 1244 Level: intermediate 1245 1246 .seealso: [](ch_ts), `TSRK`, `TSRKGetType()` 1247 @*/ 1248 PetscErrorCode TSRKGetOrder(TS ts, PetscInt *order) 1249 { 1250 PetscFunctionBegin; 1251 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1252 PetscAssertPointer(order, 2); 1253 PetscUseMethod(ts, "TSRKGetOrder_C", (TS, PetscInt *), (ts, order)); 1254 PetscFunctionReturn(PETSC_SUCCESS); 1255 } 1256 1257 /*@ 1258 TSRKSetType - Set the type of the `TSRK` scheme 1259 1260 Logically Collective 1261 1262 Input Parameters: 1263 + ts - timestepping context 1264 - rktype - type of `TSRK` scheme 1265 1266 Options Database Key: 1267 . -ts_rk_type - <1fe,2a,3,3bs,4,5f,5dp,5bs> 1268 1269 Level: intermediate 1270 1271 .seealso: [](ch_ts), `TSRKGetType()`, `TSRK`, `TSRKType`, `TSRK1FE`, `TSRK2A`, `TSRK2B`, `TSRK3`, `TSRK3BS`, `TSRK4`, `TSRK5F`, `TSRK5DP`, `TSRK5BS`, `TSRK6VR`, `TSRK7VR`, `TSRK8VR` 1272 @*/ 1273 PetscErrorCode TSRKSetType(TS ts, TSRKType rktype) 1274 { 1275 PetscFunctionBegin; 1276 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1277 PetscAssertPointer(rktype, 2); 1278 PetscTryMethod(ts, "TSRKSetType_C", (TS, TSRKType), (ts, rktype)); 1279 PetscFunctionReturn(PETSC_SUCCESS); 1280 } 1281 1282 /*@ 1283 TSRKGetType - Get the type of `TSRK` scheme 1284 1285 Not Collective 1286 1287 Input Parameter: 1288 . ts - timestepping context 1289 1290 Output Parameter: 1291 . rktype - type of `TSRK`-scheme 1292 1293 Level: intermediate 1294 1295 .seealso: [](ch_ts), `TSRKSetType()` 1296 @*/ 1297 PetscErrorCode TSRKGetType(TS ts, TSRKType *rktype) 1298 { 1299 PetscFunctionBegin; 1300 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1301 PetscUseMethod(ts, "TSRKGetType_C", (TS, TSRKType *), (ts, rktype)); 1302 PetscFunctionReturn(PETSC_SUCCESS); 1303 } 1304 1305 static PetscErrorCode TSRKGetOrder_RK(TS ts, PetscInt *order) 1306 { 1307 TS_RK *rk = (TS_RK *)ts->data; 1308 1309 PetscFunctionBegin; 1310 *order = rk->tableau->order; 1311 PetscFunctionReturn(PETSC_SUCCESS); 1312 } 1313 1314 static PetscErrorCode TSRKGetType_RK(TS ts, TSRKType *rktype) 1315 { 1316 TS_RK *rk = (TS_RK *)ts->data; 1317 1318 PetscFunctionBegin; 1319 *rktype = rk->tableau->name; 1320 PetscFunctionReturn(PETSC_SUCCESS); 1321 } 1322 1323 static PetscErrorCode TSRKSetType_RK(TS ts, TSRKType rktype) 1324 { 1325 TS_RK *rk = (TS_RK *)ts->data; 1326 PetscBool match; 1327 RKTableauLink link; 1328 1329 PetscFunctionBegin; 1330 if (rk->tableau) { 1331 PetscCall(PetscStrcmp(rk->tableau->name, rktype, &match)); 1332 if (match) PetscFunctionReturn(PETSC_SUCCESS); 1333 } 1334 for (link = RKTableauList; link; link = link->next) { 1335 PetscCall(PetscStrcmp(link->tab.name, rktype, &match)); 1336 if (match) { 1337 if (ts->setupcalled) PetscCall(TSRKTableauReset(ts)); 1338 rk->tableau = &link->tab; 1339 if (ts->setupcalled) PetscCall(TSRKTableauSetUp(ts)); 1340 ts->default_adapt_type = rk->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 1341 PetscFunctionReturn(PETSC_SUCCESS); 1342 } 1343 } 1344 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Could not find '%s'", rktype); 1345 } 1346 1347 static PetscErrorCode TSGetStages_RK(TS ts, PetscInt *ns, Vec **Y) 1348 { 1349 TS_RK *rk = (TS_RK *)ts->data; 1350 1351 PetscFunctionBegin; 1352 if (ns) *ns = rk->tableau->s; 1353 if (Y) *Y = rk->Y; 1354 PetscFunctionReturn(PETSC_SUCCESS); 1355 } 1356 1357 static PetscErrorCode TSDestroy_RK(TS ts) 1358 { 1359 PetscFunctionBegin; 1360 PetscCall(TSReset_RK(ts)); 1361 if (ts->dm) { 1362 PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSRK, DMRestrictHook_TSRK, ts)); 1363 PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSRK, DMSubDomainRestrictHook_TSRK, ts)); 1364 } 1365 PetscCall(PetscFree(ts->data)); 1366 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetOrder_C", NULL)); 1367 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetType_C", NULL)); 1368 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKSetType_C", NULL)); 1369 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetTableau_C", NULL)); 1370 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKSetMultirate_C", NULL)); 1371 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetMultirate_C", NULL)); 1372 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSSetUp_RK_MultirateSplit_C", NULL)); 1373 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSReset_RK_MultirateSplit_C", NULL)); 1374 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSSetUp_RK_MultirateNonsplit_C", NULL)); 1375 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSReset_RK_MultirateNonsplit_C", NULL)); 1376 PetscFunctionReturn(PETSC_SUCCESS); 1377 } 1378 1379 /* 1380 This defines the nonlinear equation that is to be solved with SNES 1381 We do not need to solve the equation; we just use SNES to approximate the Jacobian 1382 */ 1383 static PetscErrorCode SNESTSFormFunction_RK(SNES snes, Vec x, Vec y, TS ts) 1384 { 1385 TS_RK *rk = (TS_RK *)ts->data; 1386 DM dm, dmsave; 1387 1388 PetscFunctionBegin; 1389 PetscCall(SNESGetDM(snes, &dm)); 1390 /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 1391 dmsave = ts->dm; 1392 ts->dm = dm; 1393 PetscCall(TSComputeRHSFunction(ts, rk->stage_time, x, y)); 1394 ts->dm = dmsave; 1395 PetscFunctionReturn(PETSC_SUCCESS); 1396 } 1397 1398 static PetscErrorCode SNESTSFormJacobian_RK(SNES snes, Vec x, Mat A, Mat B, TS ts) 1399 { 1400 TS_RK *rk = (TS_RK *)ts->data; 1401 DM dm, dmsave; 1402 1403 PetscFunctionBegin; 1404 PetscCall(SNESGetDM(snes, &dm)); 1405 dmsave = ts->dm; 1406 ts->dm = dm; 1407 PetscCall(TSComputeRHSJacobian(ts, rk->stage_time, x, A, B)); 1408 ts->dm = dmsave; 1409 PetscFunctionReturn(PETSC_SUCCESS); 1410 } 1411 1412 /*@ 1413 TSRKSetMultirate - Use the interpolation-based multirate `TSRK` method 1414 1415 Logically Collective 1416 1417 Input Parameters: 1418 + ts - timestepping context 1419 - use_multirate - `PETSC_TRUE` enables the multirate `TSRK` method, sets the basic method to be RK2A and sets the ratio between slow stepsize and fast stepsize to be 2 1420 1421 Options Database Key: 1422 . -ts_rk_multirate - <true,false> 1423 1424 Level: intermediate 1425 1426 Note: 1427 The multirate method requires interpolation. The default interpolation works for 1st- and 2nd- order RK, but not for high-order RKs except `TSRK5DP` which comes with the interpolation coefficients (binterp). 1428 1429 .seealso: [](ch_ts), `TSRK`, `TSRKGetMultirate()` 1430 @*/ 1431 PetscErrorCode TSRKSetMultirate(TS ts, PetscBool use_multirate) 1432 { 1433 PetscFunctionBegin; 1434 PetscTryMethod(ts, "TSRKSetMultirate_C", (TS, PetscBool), (ts, use_multirate)); 1435 PetscFunctionReturn(PETSC_SUCCESS); 1436 } 1437 1438 /*@ 1439 TSRKGetMultirate - Gets whether to use the interpolation-based multirate `TSRK` method 1440 1441 Not Collective 1442 1443 Input Parameter: 1444 . ts - timestepping context 1445 1446 Output Parameter: 1447 . use_multirate - `PETSC_TRUE` if the multirate RK method is enabled, `PETSC_FALSE` otherwise 1448 1449 Level: intermediate 1450 1451 .seealso: [](ch_ts), `TSRK`, `TSRKSetMultirate()` 1452 @*/ 1453 PetscErrorCode TSRKGetMultirate(TS ts, PetscBool *use_multirate) 1454 { 1455 PetscFunctionBegin; 1456 PetscUseMethod(ts, "TSRKGetMultirate_C", (TS, PetscBool *), (ts, use_multirate)); 1457 PetscFunctionReturn(PETSC_SUCCESS); 1458 } 1459 1460 /*MC 1461 TSRK - ODE and DAE solver using Runge-Kutta schemes 1462 1463 The user should provide the right-hand side of the equation 1464 using `TSSetRHSFunction()`. 1465 1466 Level: beginner 1467 1468 Notes: 1469 The default is `TSRK3BS`, it can be changed with `TSRKSetType()` or -ts_rk_type 1470 1471 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSRK`, `TSSetType()`, `TSRKSetType()`, `TSRKGetType()`, `TSRK2D`, `TSRK2E`, `TSRK3`, 1472 `TSRK4`, `TSRK5`, `TSRKPRSSP2`, `TSRKBPR3`, `TSRKType`, `TSRKRegister()`, `TSRKSetMultirate()`, `TSRKGetMultirate()`, `TSType` 1473 M*/ 1474 PETSC_EXTERN PetscErrorCode TSCreate_RK(TS ts) 1475 { 1476 TS_RK *rk; 1477 1478 PetscFunctionBegin; 1479 PetscCall(TSRKInitializePackage()); 1480 1481 ts->ops->reset = TSReset_RK; 1482 ts->ops->destroy = TSDestroy_RK; 1483 ts->ops->view = TSView_RK; 1484 ts->ops->load = TSLoad_RK; 1485 ts->ops->setup = TSSetUp_RK; 1486 ts->ops->interpolate = TSInterpolate_RK; 1487 ts->ops->step = TSStep_RK; 1488 ts->ops->evaluatestep = TSEvaluateStep_RK; 1489 ts->ops->rollback = TSRollBack_RK; 1490 ts->ops->setfromoptions = TSSetFromOptions_RK; 1491 ts->ops->getstages = TSGetStages_RK; 1492 1493 ts->ops->snesfunction = SNESTSFormFunction_RK; 1494 ts->ops->snesjacobian = SNESTSFormJacobian_RK; 1495 ts->ops->adjointintegral = TSAdjointCostIntegral_RK; 1496 ts->ops->adjointsetup = TSAdjointSetUp_RK; 1497 ts->ops->adjointstep = TSAdjointStep_RK; 1498 ts->ops->adjointreset = TSAdjointReset_RK; 1499 1500 ts->ops->forwardintegral = TSForwardCostIntegral_RK; 1501 ts->ops->forwardsetup = TSForwardSetUp_RK; 1502 ts->ops->forwardreset = TSForwardReset_RK; 1503 ts->ops->forwardstep = TSForwardStep_RK; 1504 ts->ops->forwardgetstages = TSForwardGetStages_RK; 1505 1506 PetscCall(PetscNew(&rk)); 1507 ts->data = (void *)rk; 1508 1509 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetOrder_C", TSRKGetOrder_RK)); 1510 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetType_C", TSRKGetType_RK)); 1511 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKSetType_C", TSRKSetType_RK)); 1512 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetTableau_C", TSRKGetTableau_RK)); 1513 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKSetMultirate_C", TSRKSetMultirate_RK)); 1514 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSRKGetMultirate_C", TSRKGetMultirate_RK)); 1515 1516 PetscCall(TSRKSetType(ts, TSRKDefault)); 1517 rk->dtratio = 1; 1518 PetscFunctionReturn(PETSC_SUCCESS); 1519 } 1520