xref: /petsc/src/ts/impls/arkimex/arkimex.c (revision 8e010fa18d00c25e58c23165efbc8aef665b8a2c)
1 /*
2   Code for timestepping with additive Runge-Kutta IMEX method or Diagonally Implicit Runge-Kutta methods.
3 
4   Notes:
5   For ARK, the general system is written as
6 
7   F(t,U,Udot) = G(t,U)
8 
9   where F represents the stiff part of the physics and G represents the non-stiff part.
10 
11 */
12 #include <petsc/private/tsimpl.h> /*I   "petscts.h"   I*/
13 #include <petscdm.h>
14 
15 static TSARKIMEXType  TSARKIMEXDefault = TSARKIMEX3;
16 static TSDIRKType     TSDIRKDefault    = TSDIRKES213SAL;
17 static PetscBool      TSARKIMEXRegisterAllCalled;
18 static PetscBool      TSARKIMEXPackageInitialized;
19 static PetscErrorCode TSExtrapolate_ARKIMEX(TS, PetscReal, Vec);
20 
21 typedef struct _ARKTableau *ARKTableau;
22 struct _ARKTableau {
23   char      *name;
24   PetscBool  additive;             /* If False, it is a DIRK method */
25   PetscInt   order;                /* Classical approximation order of the method */
26   PetscInt   s;                    /* Number of stages */
27   PetscBool  stiffly_accurate;     /* The implicit part is stiffly accurate */
28   PetscBool  FSAL_implicit;        /* The implicit part is FSAL */
29   PetscBool  explicit_first_stage; /* The implicit part has an explicit first stage */
30   PetscInt   pinterp;              /* Interpolation order */
31   PetscReal *At, *bt, *ct;         /* Stiff tableau */
32   PetscReal *A, *b, *c;            /* Non-stiff tableau */
33   PetscReal *bembedt, *bembed;     /* Embedded formula of order one less (order-1) */
34   PetscReal *binterpt, *binterp;   /* Dense output formula */
35   PetscReal  ccfl;                 /* Placeholder for CFL coefficient relative to forward Euler */
36 };
37 typedef struct _ARKTableauLink *ARKTableauLink;
38 struct _ARKTableauLink {
39   struct _ARKTableau tab;
40   ARKTableauLink     next;
41 };
42 static ARKTableauLink ARKTableauList;
43 
44 typedef struct {
45   ARKTableau   tableau;
46   Vec         *Y;            /* States computed during the step */
47   Vec         *YdotI;        /* Time derivatives for the stiff part */
48   Vec         *YdotRHS;      /* Function evaluations for the non-stiff part */
49   Vec         *Y_prev;       /* States computed during the previous time step */
50   Vec         *YdotI_prev;   /* Time derivatives for the stiff part for the previous time step*/
51   Vec         *YdotRHS_prev; /* Function evaluations for the non-stiff part for the previous time step*/
52   Vec          Ydot0;        /* Holds the slope from the previous step in FSAL case */
53   Vec          Ydot;         /* Work vector holding Ydot during residual evaluation */
54   Vec          Z;            /* Ydot = shift(Y-Z) */
55   PetscScalar *work;         /* Scalar work */
56   PetscReal    scoeff;       /* shift = scoeff/dt */
57   PetscReal    stage_time;
58   PetscBool    imex;
59   PetscBool    extrapolate; /* Extrapolate initial guess from previous time-step stage values */
60   TSStepStatus status;
61 
62   /* context for sensitivity analysis */
63   Vec *VecsDeltaLam;   /* Increment of the adjoint sensitivity w.r.t IC at stage */
64   Vec *VecsSensiTemp;  /* Vectors to be multiplied with Jacobian transpose */
65   Vec *VecsSensiPTemp; /* Temporary Vectors to store JacobianP-transpose-vector product */
66 } TS_ARKIMEX;
67 
68 /*MC
69      TSARKIMEXARS122 - Second order ARK IMEX scheme.
70 
71      This method has one explicit stage and one implicit stage.
72 
73      Options Database Key:
74 .      -ts_arkimex_type ars122 - set arkimex type to ars122
75 
76      Level: advanced
77 
78      References:
79 .    * - U. Ascher, S. Ruuth, R. J. Spiteri, Implicit explicit Runge Kutta methods for time dependent Partial Differential Equations. Appl. Numer. Math. 25, (1997).
80 
81 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
82 M*/
83 
84 /*MC
85      TSARKIMEXA2 - Second order ARK IMEX scheme with A-stable implicit part.
86 
87      This method has an explicit stage and one implicit stage, and has an A-stable implicit scheme. This method was provided by Emil Constantinescu.
88 
89      Options Database Key:
90 .      -ts_arkimex_type a2 - set arkimex type to a2
91 
92      Level: advanced
93 
94 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
95 M*/
96 
97 /*MC
98      TSARKIMEXL2 - Second order ARK IMEX scheme with L-stable implicit part.
99 
100      This method has two implicit stages, and L-stable implicit scheme.
101 
102      Options Database Key:
103 .      -ts_arkimex_type l2 - set arkimex type to l2
104 
105      Level: advanced
106 
107     References:
108 .   * - L. Pareschi, G. Russo, Implicit Explicit Runge Kutta schemes and applications to hyperbolic systems with relaxations. Journal of Scientific Computing Volume: 25, Issue: 1, October, 2005.
109 
110 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
111 M*/
112 
113 /*MC
114      TSARKIMEX1BEE - First order backward Euler represented as an ARK IMEX scheme with extrapolation as error estimator. This is a 3-stage method.
115 
116      This method is aimed at starting the integration of implicit DAEs when explicit first-stage ARK methods are used.
117 
118      Options Database Key:
119 .      -ts_arkimex_type 1bee - set arkimex type to 1bee
120 
121      Level: advanced
122 
123 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
124 M*/
125 
126 /*MC
127      TSARKIMEX2C - Second order ARK IMEX scheme with L-stable implicit part.
128 
129      This method has one explicit stage and two implicit stages. The implicit part is the same as in TSARKIMEX2D and TSARKIMEX2E, but the explicit part has a larger stability region on the negative real axis. This method was provided by Emil Constantinescu.
130 
131      Options Database Key:
132 .      -ts_arkimex_type 2c - set arkimex type to 2c
133 
134      Level: advanced
135 
136 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
137 M*/
138 
139 /*MC
140      TSARKIMEX2D - Second order ARK IMEX scheme with L-stable implicit part.
141 
142      This method has one explicit stage and two implicit stages. The stability function is independent of the explicit part in the infinity limit of the implicit component. This method was provided by Emil Constantinescu.
143 
144      Options Database Key:
145 .      -ts_arkimex_type 2d - set arkimex type to 2d
146 
147      Level: advanced
148 
149 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
150 M*/
151 
152 /*MC
153      TSARKIMEX2E - Second order ARK IMEX scheme with L-stable implicit part.
154 
155      This method has one explicit stage and two implicit stages. It is is an optimal method developed by Emil Constantinescu.
156 
157      Options Database Key:
158 .      -ts_arkimex_type 2e - set arkimex type to 2e
159 
160     Level: advanced
161 
162 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
163 M*/
164 
165 /*MC
166      TSARKIMEXPRSSP2 - Second order SSP ARK IMEX scheme.
167 
168      This method has three implicit stages.
169 
170      References:
171 .    * - L. Pareschi, G. Russo, Implicit Explicit Runge Kutta schemes and applications to hyperbolic systems with relaxations. Journal of Scientific Computing Volume: 25, Issue: 1, October, 2005.
172 
173      This method is referred to as SSP2-(3,3,2) in https://arxiv.org/abs/1110.4375
174 
175      Options Database Key:
176 .      -ts_arkimex_type prssp2 - set arkimex type to prssp2
177 
178      Level: advanced
179 
180 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
181 M*/
182 
183 /*MC
184      TSARKIMEX3 - Third order ARK IMEX scheme with L-stable implicit part.
185 
186      This method has one explicit stage and three implicit stages.
187 
188      Options Database Key:
189 .      -ts_arkimex_type 3 - set arkimex type to 3
190 
191      Level: advanced
192 
193      References:
194 .    * - Kennedy and Carpenter 2003.
195 
196 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
197 M*/
198 
199 /*MC
200      TSARKIMEXARS443 - Third order ARK IMEX scheme.
201 
202      This method has one explicit stage and four implicit stages.
203 
204      Options Database Key:
205 .      -ts_arkimex_type ars443 - set arkimex type to ars443
206 
207      Level: advanced
208 
209      References:
210 +    * - U. Ascher, S. Ruuth, R. J. Spiteri, Implicit explicit Runge Kutta methods for time dependent Partial Differential Equations. Appl. Numer. Math. 25, (1997).
211 -    * - This method is referred to as ARS(4,4,3) in https://arxiv.org/abs/1110.4375
212 
213 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
214 M*/
215 
216 /*MC
217      TSARKIMEXBPR3 - Third order ARK IMEX scheme.
218 
219      This method has one explicit stage and four implicit stages.
220 
221      Options Database Key:
222 .      -ts_arkimex_type bpr3 - set arkimex type to bpr3
223 
224      Level: advanced
225 
226      References:
227 .    * - This method is referred to as ARK3 in https://arxiv.org/abs/1110.4375
228 
229 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
230 M*/
231 
232 /*MC
233      TSARKIMEX4 - Fourth order ARK IMEX scheme with L-stable implicit part.
234 
235      This method has one explicit stage and four implicit stages.
236 
237      Options Database Key:
238 .      -ts_arkimex_type 4 - set arkimex type to4
239 
240      Level: advanced
241 
242      References:
243 .    * - Kennedy and Carpenter 2003.
244 
245 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
246 M*/
247 
248 /*MC
249      TSARKIMEX5 - Fifth order ARK IMEX scheme with L-stable implicit part.
250 
251      This method has one explicit stage and five implicit stages.
252 
253      Options Database Key:
254 .      -ts_arkimex_type 5 - set arkimex type to 5
255 
256      Level: advanced
257 
258      References:
259 .    * - Kennedy and Carpenter 2003.
260 
261 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()`
262 M*/
263 
264 /*MC
265      TSDIRKS212 - Second order DIRK scheme.
266 
267      This method has two implicit stages with an embedded method of other 1.
268      See `TSDIRK` for additional details.
269 
270      Options Database Key:
271 .      -ts_dirk_type s212 - select this method.
272 
273      Level: advanced
274 
275      Note:
276      This is the default DIRK scheme in SUNDIALS.
277 
278 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
279 M*/
280 
281 /*MC
282      TSDIRKES122SAL - First order DIRK scheme.
283 
284      Uses backward Euler as advancing method and trapezoidal rule as embedded method. See `TSDIRK` for additional details.
285 
286      Options Database Key:
287 .      -ts_dirk_type es122sal - select this method.
288 
289      Level: advanced
290 
291      References:
292 .    * - https://arxiv.org/abs/1803.01613
293 
294 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
295 M*/
296 
297 /*MC
298      TSDIRKES213SAL - Second order DIRK scheme.
299 
300      See `TSDIRK` for additional details.
301 
302      Options Database Key:
303 .      -ts_dirk_type es213sal - select this method.
304 
305      Level: advanced
306 
307      Note:
308      This is the default DIRK scheme used in PETSc.
309 
310      References:
311 +    * - Kennedy and Carpenter, Diagonally Implicit Runge-Kutta methods for stiff ODEs (2016), https://ntrs.nasa.gov/api/citations/20160005923/downloads/20160005923.pdf
312 -    * - This method is also known as TR-BDF2, see M.E. Hosea and L.F. Shampine, Analysis and implementation of TR-BDF2, Appl. Numer. Math., 20(1) (1996) 21-37.
313 
314 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
315 M*/
316 
317 /*MC
318      TSDIRKES324SAL - Third order DIRK scheme.
319 
320      See `TSDIRK` for additional details.
321 
322      Options Database Key:
323 .      -ts_dirk_type es324sal - select this method.
324 
325      Level: advanced
326 
327      References:
328 .    * - Kennedy and Carpenter, Diagonally Implicit Runge-Kutta methods for stiff ODEs (2016), https://ntrs.nasa.gov/api/citations/20160005923/downloads/20160005923.pdf
329 
330 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
331 M*/
332 
333 /*MC
334      TSDIRKES325SAL - Third order DIRK scheme.
335 
336      See `TSDIRK` for additional details.
337 
338      Options Database Key:
339 .      -ts_dirk_type es325sal - select this method.
340 
341      Level: advanced
342 
343      References:
344 .    * - Kennedy and Carpenter, Diagonally Implicit Runge-Kutta methods for stiff ODEs (2016), https://ntrs.nasa.gov/api/citations/20160005923/downloads/20160005923.pdf
345 
346 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
347 M*/
348 
349 /*MC
350      TSDIRK657A - Sixth order DIRK scheme.
351 
352      See `TSDIRK` for additional details.
353 
354      Options Database Key:
355 .      -ts_dirk_type 657a - select this method.
356 
357      Level: advanced
358 
359      References:
360 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
361 
362 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
363 M*/
364 
365 /*MC
366      TSDIRKES648SA - Sixth order DIRK scheme.
367 
368      See `TSDIRK` for additional details.
369 
370      Options Database Key:
371 .      -ts_dirk_type es648sa - select this method.
372 
373      Level: advanced
374 
375      References:
376 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
377 
378 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
379 M*/
380 
381 /*MC
382      TSDIRK658A - Sixth order DIRK scheme.
383 
384      See `TSDIRK` for additional details.
385 
386      Options Database Key:
387 .      -ts_dirk_type 658a - select this method.
388 
389      Level: advanced
390 
391      References:
392 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
393 
394 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
395 M*/
396 
397 /*MC
398      TSDIRKS659A - Sixth order DIRK scheme.
399 
400      See `TSDIRK` for additional details.
401 
402      Options Database Key:
403 .      -ts_dirk_type s659a - select this method.
404 
405      Level: advanced
406 
407      References:
408 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
409 
410 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
411 M*/
412 
413 /*MC
414      TSDIRK7510SAL - Seventh order DIRK scheme.
415 
416      See `TSDIRK` for additional details.
417 
418      Options Database Key:
419 .      -ts_dirk_type 7510sal - select this method.
420 
421      Level: advanced
422 
423      References:
424 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
425 
426 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
427 M*/
428 
429 /*MC
430      TSDIRKES7510SA - Seventh order DIRK scheme.
431 
432      See `TSDIRK` for additional details.
433 
434      Options Database Key:
435 .      -ts_dirk_type es7510sa - select this method.
436 
437      Level: advanced
438 
439      References:
440 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
441 
442 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
443 M*/
444 
445 /*MC
446      TSDIRK759A - Seventh order DIRK scheme.
447 
448      See `TSDIRK` for additional details.
449 
450      Options Database Key:
451 .      -ts_dirk_type 759a - select this method.
452 
453      Level: advanced
454 
455      References:
456 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
457 
458 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
459 M*/
460 
461 /*MC
462      TSDIRKS7511SAL - Seventh order DIRK scheme.
463 
464      See `TSDIRK` for additional details.
465 
466      Options Database Key:
467 .      -ts_dirk_type s7511sal - select this method.
468 
469      Level: advanced
470 
471      References:
472 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
473 
474 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
475 M*/
476 
477 /*MC
478      TSDIRK8614A - Eighth order DIRK scheme.
479 
480      See `TSDIRK` for additional details.
481 
482      Options Database Key:
483 .      -ts_dirk_type 8614a - select this method.
484 
485      Level: advanced
486 
487      References:
488 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
489 
490 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
491 M*/
492 
493 /*MC
494      TSDIRK8616SAL - Eighth order DIRK scheme.
495 
496      See `TSDIRK` for additional details.
497 
498      Options Database Key:
499 .      -ts_dirk_type 8616sal - select this method.
500 
501      Level: advanced
502 
503      References:
504 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
505 
506 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
507 M*/
508 
509 /*MC
510      TSDIRKES8516SAL - Eighth order DIRK scheme.
511 
512      See `TSDIRK` for additional details.
513 
514      Options Database Key:
515 .      -ts_dirk_type es8516sal - select this method.
516 
517      Level: advanced
518 
519      References:
520 .    * - https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
521 
522 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()`
523 M*/
524 
525 static PetscErrorCode TSHasRHSFunction(TS ts, PetscBool *has)
526 {
527   TSRHSFunction func;
528 
529   PetscFunctionBegin;
530   *has = PETSC_FALSE;
531   PetscCall(DMTSGetRHSFunction(ts->dm, &func, NULL));
532   if (func) *has = PETSC_TRUE;
533   PetscFunctionReturn(PETSC_SUCCESS);
534 }
535 
536 /*@C
537   TSARKIMEXRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in `TSARKIMEX`
538 
539   Not Collective, but should be called by all processes which will need the schemes to be registered
540 
541   Level: advanced
542 
543 .seealso: [](ch_ts), `TS`, `TSARKIMEX`, `TSARKIMEXRegisterDestroy()`
544 @*/
545 PetscErrorCode TSARKIMEXRegisterAll(void)
546 {
547   PetscFunctionBegin;
548   if (TSARKIMEXRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
549   TSARKIMEXRegisterAllCalled = PETSC_TRUE;
550 
551 #define RC  PetscRealConstant
552 #define s2  RC(1.414213562373095048802)  /* PetscSqrtReal((PetscReal)2.0) */
553 #define us2 RC(0.2928932188134524755992) /* 1.0-1.0/PetscSqrtReal((PetscReal)2.0); */
554 
555   /* Diagonally implicit methods */
556   {
557     /* DIRK212, default of SUNDIALS */
558     const PetscReal A[2][2] = {
559       {RC(1.0),  RC(0.0)},
560       {RC(-1.0), RC(1.0)}
561     };
562     const PetscReal b[2]      = {RC(0.5), RC(0.5)};
563     const PetscReal bembed[2] = {RC(1.0), RC(0.0)};
564     PetscCall(TSDIRKRegister(TSDIRKS212, 2, 2, &A[0][0], b, NULL, bembed, 1, b));
565   }
566 
567   {
568     /* ESDIRK12 from https://arxiv.org/pdf/1803.01613.pdf */
569     const PetscReal A[2][2] = {
570       {RC(0.0), RC(0.0)},
571       {RC(0.0), RC(1.0)}
572     };
573     const PetscReal b[2]      = {RC(0.0), RC(1.0)};
574     const PetscReal bembed[2] = {RC(0.5), RC(0.5)};
575     PetscCall(TSDIRKRegister(TSDIRKES122SAL, 1, 2, &A[0][0], b, NULL, bembed, 1, b));
576   }
577 
578   {
579     /* ESDIRK213L[2]SA from KC16.
580        TR-BDF2 from Hosea and Shampine
581        ESDIRK23 in https://arxiv.org/pdf/1803.01613.pdf */
582     const PetscReal A[3][3] = {
583       {RC(0.0),      RC(0.0),      RC(0.0)},
584       {us2,          us2,          RC(0.0)},
585       {s2 / RC(4.0), s2 / RC(4.0), us2    },
586     };
587     const PetscReal b[3]      = {s2 / RC(4.0), s2 / RC(4.0), us2};
588     const PetscReal bembed[3] = {(RC(1.0) - s2 / RC(4.0)) / RC(3.0), (RC(3.0) * s2 / RC(4.0) + RC(1.0)) / RC(3.0), us2 / RC(3.0)};
589     PetscCall(TSDIRKRegister(TSDIRKES213SAL, 2, 3, &A[0][0], b, NULL, bembed, 1, b));
590   }
591 
592   {
593 #define g   RC(0.43586652150845899941601945)
594 #define g2  PetscSqr(g)
595 #define g3  g *g2
596 #define g4  PetscSqr(g2)
597 #define g5  g *g4
598 #define c3  RC(1.0)
599 #define a32 c3 *(c3 - RC(2.0) * g) / (RC(4.0) * g)
600 #define b2  (-RC(2.0) + RC(3.0) * c3 + RC(6.0) * g * (RC(1.0) - c3)) / (RC(12.0) * g * (c3 - RC(2.0) * g))
601 #define b3  (RC(1.0) - RC(6.0) * g + RC(6.0) * g2) / (RC(3.0) * c3 * (c3 - RC(2.0) * g))
602 #if 0
603 /* This is for c3 = 3/5 */
604   #define bh2 \
605     c3 * (-RC(1.0) + RC(6.0) * g - RC(23.0) * g3 + RC(12.0) * g4 - RC(6.0) * g5) / (RC(4.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2)) + (RC(3.0) - RC(27.0) * g + RC(68.0) * g2 - RC(55.0) * g3 + RC(21.0) * g4 - RC(6.0) * g5) / (RC(2.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2))
606   #define bh3 -g * (-RC(2.0) + RC(21.0) * g - RC(68.0) * g2 + RC(79.0) * g3 - RC(33.0) * g4 + RC(12.0) * g5) / (RC(2.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2))
607   #define bh4 -RC(3.0) * g2 * (-RC(1.0) + RC(4.0) * g - RC(2.0) * g2 + g3) / (RC(1.0) - RC(6.0) * g + RC(6.0) * g2)
608 #else
609   /* This is for c3 = 1.0 */
610   #define bh2 a32
611   #define bh3 g
612   #define bh4 RC(0.0)
613 #endif
614     /* ESDIRK3(2I)4L[2]SA from KC16 with c3 = 1.0 */
615     /* Given by Kvaerno https://link.springer.com/article/10.1023/b:bitn.0000046811.70614.38 */
616     const PetscReal A[4][4] = {
617       {RC(0.0),               RC(0.0), RC(0.0), RC(0.0)},
618       {g,                     g,       RC(0.0), RC(0.0)},
619       {c3 - a32 - g,          a32,     g,       RC(0.0)},
620       {RC(1.0) - b2 - b3 - g, b2,      b3,      g      },
621     };
622     const PetscReal b[4]      = {RC(1.0) - b2 - b3 - g, b2, b3, g};
623     const PetscReal bembed[4] = {RC(1.0) - bh2 - bh3 - bh4, bh2, bh3, bh4};
624     PetscCall(TSDIRKRegister(TSDIRKES324SAL, 3, 4, &A[0][0], b, NULL, bembed, 1, b));
625 #undef g
626 #undef g2
627 #undef g3
628 #undef c3
629 #undef a32
630 #undef b2
631 #undef b3
632 #undef bh2
633 #undef bh3
634 #undef bh4
635   }
636 
637   {
638     /* ESDIRK3(2I)5L[2]SA from KC16 */
639     const PetscReal A[5][5] = {
640       {RC(0.0),                  RC(0.0),                  RC(0.0),                 RC(0.0),                   RC(0.0)           },
641       {RC(9.0) / RC(40.0),       RC(9.0) / RC(40.0),       RC(0.0),                 RC(0.0),                   RC(0.0)           },
642       {RC(19.0) / RC(72.0),      RC(14.0) / RC(45.0),      RC(9.0) / RC(40.0),      RC(0.0),                   RC(0.0)           },
643       {RC(3337.0) / RC(11520.0), RC(233.0) / RC(720.0),    RC(207.0) / RC(1280.0),  RC(9.0) / RC(40.0),        RC(0.0)           },
644       {RC(7415.0) / RC(34776.0), RC(9920.0) / RC(30429.0), RC(4845.0) / RC(9016.0), -RC(5827.0) / RC(19320.0), RC(9.0) / RC(40.0)},
645     };
646     const PetscReal b[5]      = {RC(7415.0) / RC(34776.0), RC(9920.0) / RC(30429.0), RC(4845.0) / RC(9016.0), -RC(5827.0) / RC(19320.0), RC(9.0) / RC(40.0)};
647     const PetscReal bembed[5] = {RC(23705.0) / RC(104328.0), RC(29720.0) / RC(91287.0), RC(4225.0) / RC(9016.0), -RC(69304987.0) / RC(337732920.0), RC(42843.0) / RC(233080.0)};
648     PetscCall(TSDIRKRegister(TSDIRKES325SAL, 3, 5, &A[0][0], b, NULL, bembed, 1, b));
649   }
650 
651   {
652     // DIRK(6,6)[1]A[(7,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
653     const PetscReal A[7][7] = {
654       {RC(0.303487844706747),    RC(0.0),                RC(0.0),                   RC(0.0),                   RC(0.0),                 RC(0.0),                RC(0.0)              },
655       {RC(-0.279756492709814),   RC(0.500032236020747),  RC(0.0),                   RC(0.0),                   RC(0.0),                 RC(0.0),                RC(0.0)              },
656       {RC(0.280583215743895),    RC(-0.438560061586751), RC(0.217250734515736),     RC(0.0),                   RC(0.0),                 RC(0.0),                RC(0.0)              },
657       {RC(-0.0677678738539846),  RC(0.984312781232293),  RC(-0.266720192540149),    RC(0.2476680834526),       RC(0.0),                 RC(0.0),                RC(0.0)              },
658       {RC(0.125671616147993),    RC(-0.995401751002415), RC(0.761333109549059),     RC(-0.210281837202208),    RC(0.866743712636936),   RC(0.0),                RC(0.0)              },
659       {RC(-0.368056238801488),   RC(-0.999928082701516), RC(0.534734253232519),     RC(-0.174856916279082),    RC(0.615007160285509),   RC(0.696549912132029),  RC(0.0)              },
660       {RC(-0.00570546839653984), RC(-0.113110431835656), RC(-0.000965563207671587), RC(-0.000130490084629567), RC(0.00111737736895673), RC(-0.279385587378871), RC(0.618455906845342)}
661     };
662     const PetscReal b[7]      = {RC(0.257561510484877), RC(0.234281287047716), RC(0.126658904241469), RC(0.252363215441784), RC(0.396701083526306), RC(-0.267566000742152), RC(0.0)};
663     const PetscReal bembed[7] = {RC(0.257561510484945), RC(0.387312822934391), RC(0.126658904241468), RC(0.252363215441784), RC(0.396701083526306), RC(-0.267566000742225), RC(-0.153031535886669)};
664     PetscCall(TSDIRKRegister(TSDIRK657A, 6, 7, &A[0][0], b, NULL, bembed, 1, b));
665   }
666   {
667     // ESDIRK(8,6)[2]SA[(8,4)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
668     const PetscReal A[8][8] = {
669       {RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),                RC(0.0),                RC(0.0),               RC(0.0)              },
670       {RC(0.333222149217725),  RC(0.333222149217725),   RC(0.0),                 RC(0.0),               RC(0.0),                RC(0.0),                RC(0.0),               RC(0.0)              },
671       {RC(0.0639743773182214), RC(-0.0830330224410214), RC(0.333222149217725),   RC(0.0),               RC(0.0),                RC(0.0),                RC(0.0),               RC(0.0)              },
672       {RC(-0.728522201369326), RC(-0.210414479522485),  RC(0.532519916559342),   RC(0.333222149217725), RC(0.0),                RC(0.0),                RC(0.0),               RC(0.0)              },
673       {RC(-0.175135269272067), RC(0.666675582067552),   RC(-0.304400907370867),  RC(0.656797712445756), RC(0.333222149217725),  RC(0.0),                RC(0.0),               RC(0.0)              },
674       {RC(0.222695802705462),  RC(-0.0948971794681061), RC(-0.0234336346686545), RC(-0.45385925012042), RC(0.0283910313826958), RC(0.333222149217725),  RC(0.0),               RC(0.0)              },
675       {RC(-0.132534078051299), RC(0.702597935004879),   RC(-0.433316453128078),  RC(0.893717488547587), RC(0.057381454791406),  RC(-0.207798411552402), RC(0.333222149217725), RC(0.0)              },
676       {RC(0.0802253121418085), RC(0.281196044671022),   RC(0.406758926172157),   RC(-0.01945708512416), RC(-0.41785600088526),  RC(0.0545342658870322), RC(0.281376387919675), RC(0.333222149217725)}
677     };
678     const PetscReal b[8]      = {RC(0.0802253121418085), RC(0.281196044671022), RC(0.406758926172157), RC(-0.01945708512416), RC(-0.41785600088526), RC(0.0545342658870322), RC(0.281376387919675), RC(0.333222149217725)};
679     const PetscReal bembed[8] = {RC(0.0), RC(0.292331064554014), RC(0.409676102283681), RC(-0.002094718084982), RC(-0.282771520835975), RC(0.113862336644901), RC(0.181973572260693), RC(0.287023163177669)};
680     PetscCall(TSDIRKRegister(TSDIRKES648SA, 6, 8, &A[0][0], b, NULL, bembed, 1, b));
681   }
682   {
683     // DIRK(8,6)[1]SAL[(8,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
684     const PetscReal A[8][8] = {
685       {RC(0.477264457385826),    RC(0.0),                RC(0.0),                   RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                 RC(0.0)              },
686       {RC(-0.197052588415002),   RC(0.476363428459584),  RC(0.0),                   RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                 RC(0.0)              },
687       {RC(-0.0347674430372966),  RC(0.633051807335483),  RC(0.193634310075028),     RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                 RC(0.0)              },
688       {RC(0.0967797668578702),   RC(-0.193533526466535), RC(-0.000207622945800473), RC(0.159572204849431),   RC(0.0),                RC(0.0),                RC(0.0),                 RC(0.0)              },
689       {RC(0.162527231819875),    RC(-0.249672513547382), RC(-0.0459079972041795),   RC(0.36579476400859),    RC(0.255752838307699),  RC(0.0),                RC(0.0),                 RC(0.0)              },
690       {RC(-0.00707603197171262), RC(0.846299854860295),  RC(0.344020016925018),     RC(-0.0720926054548865), RC(-0.215492331980875), RC(0.104341097622161),  RC(0.0),                 RC(0.0)              },
691       {RC(0.00176857935179744),  RC(0.0779960013127515), RC(0.303333277564557),     RC(0.213160806732836),   RC(0.351769320319038),  RC(-0.381545894386538), RC(0.433517909105558),   RC(0.0)              },
692       {RC(0.0),                  RC(0.22732353410559),   RC(0.308415837980118),     RC(0.157263419573007),   RC(0.243551137152275),  RC(-0.120953626732831), RC(-0.0802678473399899), RC(0.264667545261832)}
693     };
694     const PetscReal b[8]      = {RC(0.0), RC(0.22732353410559), RC(0.308415837980118), RC(0.157263419573007), RC(0.243551137152275), RC(-0.120953626732831), RC(-0.0802678473399899), RC(0.264667545261832)};
695     const PetscReal bembed[8] = {RC(0.0), RC(0.22732353410559), RC(0.308415837980118), RC(0.157263419573007), RC(0.243551137152275), RC(-0.103483943222765), RC(-0.0103721771642262), RC(0.177302191576001)};
696     PetscCall(TSDIRKRegister(TSDIRK658A, 6, 8, &A[0][0], b, NULL, bembed, 1, b));
697   }
698   {
699     // SDIRK(9,6)[1]SAL[(9,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
700     const PetscReal A[9][9] = {
701       {RC(0.218127781944908),   RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)              },
702       {RC(-0.0903514856119419), RC(0.218127781944908),  RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)              },
703       {RC(0.172952039138937),   RC(-0.35365501036282),  RC(0.218127781944908),   RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)              },
704       {RC(0.511999875919193),   RC(0.0289640332201925), RC(-0.0144030945657094), RC(0.218127781944908),   RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)              },
705       {RC(0.00465303495506782), RC(-0.075635818766597), RC(0.217273030786712),   RC(-0.0206519428725472), RC(0.218127781944908),  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)              },
706       {RC(0.896145501762472),   RC(0.139267327700498),  RC(-0.186920979752805),  RC(0.0672971012371723),  RC(-0.350891963442176), RC(0.218127781944908),  RC(0.0),                RC(0.0),                RC(0.0)              },
707       {RC(0.552959701885751),   RC(-0.439360579793662), RC(0.333704002325091),   RC(-0.0339426520778416), RC(-0.151947445912595), RC(0.0213825661026943), RC(0.218127781944908),  RC(0.0),                RC(0.0)              },
708       {RC(0.631360374036476),   RC(0.724733619641466),  RC(-0.432170625425258),  RC(0.598611382182477),   RC(-0.709087197034345), RC(-0.483986685696934), RC(0.378391562905131),  RC(0.218127781944908),  RC(0.0)              },
709       {RC(0.0),                 RC(-0.15504452530869),  RC(0.194518478660789),   RC(0.63515640279203),    RC(0.81172278664173),   RC(0.110736108691585),  RC(-0.495304692414479), RC(-0.319912341007872), RC(0.218127781944908)}
710     };
711     const PetscReal b[9]      = {RC(0.0), RC(-0.15504452530869), RC(0.194518478660789), RC(0.63515640279203), RC(0.81172278664173), RC(0.110736108691585), RC(-0.495304692414479), RC(-0.319912341007872), RC(0.218127781944908)};
712     const PetscReal bembed[9] = {RC(3.62671059311602e-16), RC(0.0736615558278942), RC(0.103527397262229), RC(1.00247481935499), RC(0.361377289250057), RC(-0.785425929961365), RC(-0.0170499047960784), RC(0.296321252214769), RC(-0.0348864791524953)};
713     PetscCall(TSDIRKRegister(TSDIRKS659A, 6, 9, &A[0][0], b, NULL, bembed, 1, b));
714   }
715   {
716     // DIRK(10,7)[1]SAL[(10,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
717     const PetscReal A[10][10] = {
718       {RC(0.233704632125264),   RC(0.0),                RC(0.0),                  RC(0.0),                  RC(0.0),                   RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
719       {RC(-0.0739324813149407), RC(0.200056838146104),  RC(0.0),                  RC(0.0),                  RC(0.0),                   RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
720       {RC(0.0943790344044812),  RC(0.264056067701605),  RC(0.133245202456465),    RC(0.0),                  RC(0.0),                   RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
721       {RC(0.269084810601201),   RC(-0.503479002548384), RC(-0.00486736469695022), RC(0.251518716213569),    RC(0.0),                   RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
722       {RC(0.145665801918423),   RC(0.204983170463176),  RC(0.407154634069484),    RC(-0.0121039135200389),  RC(0.190243622486334),     RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
723       {RC(0.985450198547345),   RC(0.806942652811456),  RC(-0.808130934167263),   RC(-0.669035819439391),   RC(0.0269384406756128),    RC(0.462144080607327),    RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
724       {RC(0.163902957809563),   RC(0.228315094960095),  RC(0.0745971021260249),   RC(0.000509793400156559), RC(0.0166533681378294),    RC(-0.0229383879045797),  RC(0.103505486637336),  RC(0.0),                 RC(0.0),               RC(0.0)              },
725       {RC(-0.162694156858437),  RC(0.0453478837428434), RC(0.997443481211424),    RC(0.200251514941093),    RC(-0.000161755458839048), RC(-0.0848134335980281),  RC(-0.36438666566666),  RC(0.158604420136055),   RC(0.0),               RC(0.0)              },
726       {RC(0.200733156477425),   RC(0.239686443444433),  RC(0.303837014418929),    RC(-0.0534390596279896),  RC(0.0314067599640569),    RC(-0.00764032790448536), RC(0.0609191260198661), RC(-0.0736319201590642), RC(0.204602530607021), RC(0.0)              },
727       {RC(0.0),                 RC(0.235563761744267),  RC(0.658651488684319),    RC(0.0308877804992098),   RC(-0.906514945595336),    RC(-0.0248488551739974),  RC(-0.309967582365257), RC(0.191663316925525),   RC(0.923933712199542), RC(0.200631323081727)}
728     };
729     const PetscReal b[10] = {RC(0.0), RC(0.235563761744267), RC(0.658651488684319), RC(0.0308877804992098), RC(-0.906514945595336), RC(-0.0248488551739974), RC(-0.309967582365257), RC(0.191663316925525), RC(0.923933712199542), RC(0.200631323081727)};
730     const PetscReal bembed[10] =
731       {RC(0.0), RC(0.222929376486581), RC(0.950668440138169), RC(0.0342694607044032), RC(0.362875840545746), RC(0.223572979288581), RC(-0.764361723526727), RC(0.563476909230026), RC(-0.690896961894185), RC(0.0974656790270323)};
732     PetscCall(TSDIRKRegister(TSDIRK7510SAL, 7, 10, &A[0][0], b, NULL, bembed, 1, b));
733   }
734   {
735     // ESDIRK(10,7)[2]SA[(10,5)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
736     const PetscReal A[10][10] = {
737       {RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
738       {RC(0.210055790203419),   RC(0.210055790203419),   RC(0.0),                 RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
739       {RC(0.255781739921086),   RC(0.239850916980976),   RC(0.210055790203419),   RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
740       {RC(0.286789624880437),   RC(0.230494748834778),   RC(0.263925149885491),   RC(0.210055790203419),    RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
741       {RC(-0.0219118128774335), RC(0.897684380345907),   RC(-0.657954605498907),  RC(0.124962304722633),    RC(0.210055790203419),    RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
742       {RC(-0.065614879584776),  RC(-0.0565630711859497), RC(0.0254881105065311),  RC(-0.00368981790650006), RC(-0.0115178258446329),  RC(0.210055790203419),    RC(0.0),                RC(0.0),                 RC(0.0),               RC(0.0)              },
743       {RC(0.399860851232098),   RC(0.915588469718705),   RC(-0.0758429094934412), RC(-0.263369154872759),   RC(0.719687583564526),    RC(-0.787410407015369),   RC(0.210055790203419),  RC(0.0),                 RC(0.0),               RC(0.0)              },
744       {RC(0.51693616104628),    RC(1.00000540846973),    RC(-0.0485110663289207), RC(-0.315208041581942),   RC(0.749742806451587),    RC(-0.990975090921248),   RC(0.0159279583407308), RC(0.210055790203419),   RC(0.0),               RC(0.0)              },
745       {RC(-0.0303062129076945), RC(-0.297035174659034),  RC(0.184724697462164),   RC(-0.0351876079516183),  RC(-0.00324668230690761), RC(0.216151004053531),    RC(-0.126676252098317), RC(0.114040254365262),   RC(0.210055790203419), RC(0.0)              },
746       {RC(0.0705997961586714),  RC(-0.0281516061956374), RC(0.314600470734633),   RC(-0.0907057557963371),  RC(0.168078953957742),    RC(-0.00655694984590575), RC(0.0505384497804303), RC(-0.0569572058725042), RC(0.368498056875488), RC(0.210055790203419)}
747     };
748     const PetscReal b[10]      = {RC(0.0705997961586714),   RC(-0.0281516061956374), RC(0.314600470734633),   RC(-0.0907057557963371), RC(0.168078953957742),
749                                   RC(-0.00655694984590575), RC(0.0505384497804303),  RC(-0.0569572058725042), RC(0.368498056875488),   RC(0.210055790203419)};
750     const PetscReal bembed[10] = {RC(-0.015494246543626), RC(0.167657963820093), RC(0.269858958144236),  RC(-0.0443258997755156), RC(0.150049236875266),
751                                   RC(0.259452082755846),  RC(0.244624573502521), RC(-0.215528446920284), RC(0.0487601760292619),  RC(0.134945602112201)};
752     PetscCall(TSDIRKRegister(TSDIRKES7510SA, 7, 10, &A[0][0], b, NULL, bembed, 1, b));
753   }
754   {
755     // DIRK(9,7)[1]A[(9,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
756     const PetscReal A[9][9] = {
757       {RC(0.179877789855839),   RC(0.0),                 RC(0.0),                RC(0.0),                  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
758       {RC(-0.100405844885157),  RC(0.214948590644819),   RC(0.0),                RC(0.0),                  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
759       {RC(0.112251360198995),   RC(-0.206162139150298),  RC(0.125159642941958),  RC(0.0),                  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
760       {RC(-0.0335164000768257), RC(0.999942349946143),   RC(-0.491470853833294), RC(0.19820086325566),     RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
761       {RC(-0.0417345265478321), RC(0.187864510308215),   RC(0.0533789224305102), RC(-0.00822060284862916), RC(0.127670843671646),  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
762       {RC(-0.0278257925239257), RC(0.600979340683382),   RC(-0.242632273241134), RC(-0.11318753652081),    RC(0.164326917632931),  RC(0.284116597781395),  RC(0.0),                RC(0.0),                RC(0.0)               },
763       {RC(0.041465583858922),   RC(0.429657872601836),   RC(-0.381323410582524), RC(0.391934277498434),    RC(-0.245918275501241), RC(-0.35960669741231),  RC(0.184000022289158),  RC(0.0),                RC(0.0)               },
764       {RC(-0.105565651574538),  RC(-0.0557833155018609), RC(0.358967568942643),  RC(-0.13489263413921),    RC(0.129553247260677),  RC(0.0992493795371489), RC(-0.15716610563461),  RC(0.17918862279814),   RC(0.0)               },
765       {RC(0.00439696079965225), RC(0.960250486570491),   RC(0.143558372286706),  RC(0.0819015241056593),   RC(0.999562318563625),  RC(0.325203439314358),  RC(-0.679013149331228), RC(-0.990589559837246), RC(0.0773648037639896)}
766     };
767 
768     const PetscReal b[9]      = {RC(0.0), RC(0.179291520437966), RC(0.115310295273026), RC(-0.857943261453138), RC(0.654911318641998), RC(1.18713633508094), RC(-0.0949482361570542), RC(-0.37661430946407), RC(0.19285633764033)};
769     const PetscReal bembed[9] = {RC(0.0), RC(0.1897135479408), RC(0.127461414808862), RC(-0.835810807663404), RC(0.665114177777166), RC(1.16481046518346), RC(-0.11661858889792), RC(-0.387303251022099), RC(0.192633041873135)};
770     PetscCall(TSDIRKRegister(TSDIRK759A, 7, 9, &A[0][0], b, NULL, bembed, 1, b));
771   }
772   {
773     // SDIRK(11,7)[1]SAL[(11,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
774     const PetscReal A[11][11] = {
775       {RC(0.200252661187742),  RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
776       {RC(-0.082947368165267), RC(0.200252661187742),   RC(0.0),                  RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
777       {RC(0.483452690540751),  RC(0.0),                 RC(0.200252661187742),    RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
778       {RC(0.771076453481321),  RC(-0.22936926341842),   RC(0.289733373208823),    RC(0.200252661187742),   RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
779       {RC(0.0329683054968892), RC(-0.162397421903366),  RC(0.000951777538562805), RC(0.0),                 RC(0.200252661187742),   RC(0.0),                 RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
780       {RC(0.265888743485945),  RC(0.606743151103931),   RC(0.173443800537369),    RC(-0.0433968261546912), RC(-0.385211017224481),  RC(0.200252661187742),   RC(0.0),                 RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
781       {RC(0.220662294551146),  RC(-0.0465078507657608), RC(-0.0333111995282464),  RC(0.011801580836998),   RC(0.169480801030105),   RC(-0.0167974432139385), RC(0.200252661187742),   RC(0.0),                 RC(0.0),               RC(0.0),               RC(0.0)              },
782       {RC(0.323099728365267),  RC(0.0288371831672575),  RC(-0.0543404318773196),  RC(0.0137765831431662),  RC(0.0516799019060702),  RC(-0.0421359763835713), RC(0.181297932037826),   RC(0.200252661187742),   RC(0.0),               RC(0.0),               RC(0.0)              },
783       {RC(-0.164226696476538), RC(0.187552004946792),   RC(0.0628674420973025),   RC(-0.0108886582703428), RC(-0.0117628641717889), RC(0.0432176880867965),  RC(-0.0315206836275473), RC(-0.0846007021638797), RC(0.200252661187742), RC(0.0),               RC(0.0)              },
784       {RC(0.651428598623771),  RC(-0.10208078475356),   RC(0.198305701801888),    RC(-0.0117354096673789), RC(-0.0440385966743686), RC(-0.0358364455795087), RC(-0.0075408087654097), RC(0.160320941654639),   RC(0.017940248694499), RC(0.200252661187742), RC(0.0)              },
785       {RC(0.0),                RC(-0.266259448580236),  RC(-0.615982357748271),   RC(0.561474126687165),   RC(0.266911112787025),   RC(0.219775952207137),   RC(0.387847665451514),   RC(0.612483137773236),   RC(0.330027015806089), RC(-0.6965298655714),  RC(0.200252661187742)}
786     };
787     const PetscReal b[11] =
788       {RC(0.0), RC(-0.266259448580236), RC(-0.615982357748271), RC(0.561474126687165), RC(0.266911112787025), RC(0.219775952207137), RC(0.387847665451514), RC(0.612483137773236), RC(0.330027015806089), RC(-0.6965298655714), RC(0.200252661187742)};
789     const PetscReal bembed[11] =
790       {RC(0.0), RC(0.180185524442613), RC(-0.628869710835338), RC(0.186185675988647), RC(0.0484716652630425), RC(0.203927720607141), RC(0.44041662512573), RC(0.615710527731245), RC(0.0689648839032607), RC(-0.253599870605903), RC(0.138606958379488)};
791     PetscCall(TSDIRKRegister(TSDIRKS7511SAL, 7, 11, &A[0][0], b, NULL, bembed, 1, b));
792   }
793   {
794     // DIRK(13,8)[1]A[(14,6)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
795     const PetscReal A[14][14] = {
796       {RC(0.421050745442291),   RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
797       {RC(-0.0761079419591268), RC(0.264353986580857),  RC(0.0),                 RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
798       {RC(0.0727106904170694),  RC(-0.204265976977285), RC(0.181608196544136),   RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
799       {RC(0.55763054816611),    RC(-0.409773579543499), RC(0.510926516886944),   RC(0.259892204518476),    RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
800       {RC(0.0228083864844437),  RC(-0.445569051836454), RC(-0.0915242778636248), RC(0.00450055909321655),  RC(0.6397807199983),      RC(0.0),                RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
801       {RC(-0.135945849505152),  RC(0.0946509646963754), RC(-0.236110197279175),  RC(0.00318944206456517),  RC(0.255453021028118),    RC(0.174805219173446),  RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
802       {RC(-0.147960260670772),  RC(-0.402188192230535), RC(-0.703014530043888),  RC(0.00941974677418186),  RC(0.885747111289207),    RC(0.261314066449028),  RC(0.16307697503668),    RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
803       {RC(0.165597241042244),   RC(0.824182962188923),  RC(-0.0280136160783609), RC(0.282372386631758),    RC(-0.957721354131182),   RC(0.489439550159977),  RC(0.170094415598103),   RC(0.0522519785718563),   RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
804       {RC(0.0335292011495618),  RC(0.575750388029166),  RC(0.223289855356637),   RC(-0.00317458833242804), RC(-0.112890382135193),   RC(-0.419809267954284), RC(0.0466136902102104),  RC(-0.00115413813041085), RC(0.109685363692383),  RC(0.0),                 RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
805       {RC(-0.0512616878252355), RC(0.699261265830807),  RC(-0.117939611738769),  RC(0.0021745241931243),   RC(-0.00932826702640947), RC(-0.267575057469428), RC(0.126949139814065),   RC(0.00330353204502163),  RC(0.185949445053766),  RC(0.0938215615963721),  RC(0.0),                RC(0.0),                RC(0.0),                RC(0.0)               },
806       {RC(-0.106521517960343),  RC(0.41835889096168),   RC(0.353585905881916),   RC(-0.0746474161579599),  RC(-0.015450626460289),   RC(-0.46224659192275),  RC(-0.0576406327329181), RC(-0.00712066942504018), RC(0.377776558014452),  RC(0.36890054338294),    RC(0.0618488746331837), RC(0.0),                RC(0.0),                RC(0.0)               },
807       {RC(-0.163079104890997),  RC(0.644561721693806),  RC(0.636968661639572),   RC(-0.122346720085377),   RC(-0.333062564990312),   RC(-0.3054226490478),   RC(-0.357820712828352),  RC(-0.0125510510334706),  RC(0.371263681186311),  RC(0.371979640363694),   RC(0.0531090658708968), RC(0.0518279459132049), RC(0.0),                RC(0.0)               },
808       {RC(0.579993784455521),   RC(-0.188833728676494), RC(0.999975696843775),   RC(0.0572810855901161),   RC(-0.264374735003671),   RC(0.165091739976854),  RC(-0.546675809010452),  RC(-0.0283821822291982),  RC(-0.102639860418374), RC(-0.0343251040446405), RC(0.4762598462591),    RC(-0.304153104931261), RC(0.0953911855943621), RC(0.0)               },
809       {RC(0.0848552694007844),  RC(0.287193912340074),  RC(0.543683503004232),   RC(-0.081311059300692),   RC(-0.0328661289388557),  RC(-0.323456834372922), RC(-0.240378871658975),  RC(-0.0189913019930369),  RC(0.220663114082036),  RC(0.253029984360864),   RC(0.252011799370563),  RC(-0.154882222605423), RC(0.0315202264687415), RC(0.0514095812104714)}
810     };
811     const PetscReal b[14] = {RC(0.0), RC(0.516650324205117), RC(0.0773227217357826), RC(-0.12474204666975), RC(-0.0241052115180679), RC(-0.325821145180359), RC(0.0907237460123951), RC(0.0459271880596652), RC(0.221012259404702), RC(0.235510906761942), RC(0.491109674204385), RC(-0.323506525837343), RC(0.119918108821531), RC(0.0)};
812     const PetscReal bembed[14] = {RC(2.32345691433618e-16), RC(0.499150900944401), RC(0.080991997189243), RC(-0.0359440417166322), RC(-0.0258910397441454), RC(-0.304540350278636),  RC(0.0836627473632563),
813                                   RC(0.0417664613347638),   RC(0.223636394275293), RC(0.231569156867596), RC(0.240526201277663),   RC(-0.222933582911926),  RC(-0.0111479879597561), RC(0.19915314335888)};
814     PetscCall(TSDIRKRegister(TSDIRK8614A, 8, 14, &A[0][0], b, NULL, bembed, 1, b));
815   }
816   {
817     // DIRK(15,8)[1]SAL[(16,6)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
818     const PetscReal A[16][16] = {
819       {RC(0.498904981271193),   RC(0.0),                  RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
820       {RC(-0.303806037341816),  RC(0.886299445992379),    RC(0.0),                 RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
821       {RC(-0.581440223471476),  RC(0.371003719460259),    RC(0.43844717752802),    RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
822       {RC(0.531852638870051),   RC(-0.339363014907108),   RC(0.422373239795441),   RC(0.223854203543397),    RC(0.0),                RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
823       {RC(0.118517891868867),   RC(-0.0756235584174296),  RC(-0.0864284870668712), RC(0.000536692838658312), RC(0.10101418329932),   RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
824       {RC(0.218733626116401),   RC(-0.139568928299635),   RC(0.30473612813488),    RC(0.00354038623073564),  RC(0.0932085751160559), RC(0.140161806097591),   RC(0.0),                RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
825       {RC(0.0692944686081835),  RC(-0.0442152168939502),  RC(-0.0903375348855603), RC(0.00259030241156141),  RC(0.204514233679515),  RC(-0.0245383758960002), RC(0.199289437094059),  RC(0.0),                 RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
826       {RC(0.990640016505571),   RC(-0.632104756315967),   RC(0.856971425234221),   RC(0.174494099232246),    RC(-0.113715829680145), RC(-0.151494045307366),  RC(-0.438268629569005), RC(0.120578398912139),   RC(0.0),                   RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
827       {RC(-0.099415677713136),  RC(0.211832014309207),    RC(-0.245998265866888),  RC(-0.182249672235861),   RC(0.167897635713799),  RC(0.212850335030069),   RC(-0.391739299440123), RC(-0.0118718506876767), RC(0.526293701659093),     RC(0.0),                 RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
828       {RC(0.383983914845461),   RC(-0.245011361219604),   RC(0.46717278554955),    RC(-0.0361272447593202),  RC(0.0742234660511333), RC(-0.0474816271948766), RC(-0.229859978525756), RC(0.0516283729206322),  RC(0.0),                   RC(0.193823890777594),   RC(0.0),                  RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
829       {RC(0.0967855003180134),  RC(-0.0481037037916184),  RC(0.191268138832434),   RC(0.234977164564126),    RC(0.0620265921753097), RC(0.403432826534738),   RC(0.152403846687238),  RC(-0.118420429237746),  RC(0.0582141598685892),    RC(-0.13924540906863),   RC(0.106661313117545),    RC(0.0),                 RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
830       {RC(0.133941307432055),   RC(-0.0722076602896254),  RC(0.217086297689275),   RC(0.00495499602192887),  RC(0.0306090174933995), RC(0.26483526755746),    RC(0.204442440745605),  RC(0.196883395136708),   RC(0.056527012583996),     RC(-0.150216381356784),  RC(-0.217209415757333),   RC(0.330353722743315),   RC(0.0),               RC(0.0),                 RC(0.0),                 RC(0.0)              },
831       {RC(0.157014274561299),   RC(-0.0883810256381874),  RC(0.117193033885034),   RC(-0.0362304243769466),  RC(0.0169030211466111), RC(-0.169835753576141),  RC(0.399749979234113),  RC(0.31806704093008),    RC(0.050340008347693),     RC(0.120284837472214),   RC(-0.235313193645423),   RC(0.232488522208926),   RC(0.117719679450729), RC(0.0),                 RC(0.0),                 RC(0.0)              },
832       {RC(0.00276453816875833), RC(-0.00366028255231782), RC(-0.331078914515559),  RC(0.623377549031949),    RC(0.167618142989491),  RC(0.0748467945312516),  RC(0.797629286699677),  RC(-0.390714256799583),  RC(-0.00808553925131555),  RC(0.014840324980952),   RC(-0.0856180410248133),  RC(0.602943304937827),   RC(-0.5771359338496),  RC(0.112273026653282),   RC(0.0),                 RC(0.0)              },
833       {RC(0.0),                 RC(0.0),                  RC(0.085283971980307),   RC(0.51334393454179),     RC(0.144355978013514),  RC(0.255379109487853),   RC(0.225075750790524),  RC(-0.343241323394982),  RC(0.0),                   RC(0.0798250392218852),  RC(0.0528824734082655),   RC(-0.0830350888900362), RC(0.022567388707279), RC(-0.0592631119040204), RC(0.106825878037621),   RC(0.0)              },
834       {RC(0.173784481207652),   RC(-0.110887906116241),   RC(0.190052513365204),   RC(-0.0688345422674029),  RC(0.10326505079603),   RC(0.267127097115219),   RC(0.141703423176897),  RC(0.0117966866651728),  RC(-6.65650091812762e-15), RC(-0.0213725083662519), RC(-0.00931148598712566), RC(-0.10007679077114),   RC(0.123471797451553), RC(0.00203684241073055), RC(-0.0294320891781173), RC(0.195746619921528)}
835     };
836     const PetscReal b[16] = {RC(0.0), RC(0.0), RC(0.085283971980307), RC(0.51334393454179), RC(0.144355978013514), RC(0.255379109487853), RC(0.225075750790524), RC(-0.343241323394982), RC(0.0), RC(0.0798250392218852), RC(0.0528824734082655), RC(-0.0830350888900362), RC(0.022567388707279), RC(-0.0592631119040204), RC(0.106825878037621), RC(0.0)};
837     const PetscReal bembed[16] = {RC(-1.31988512519898e-15), RC(7.53606601764004e-16), RC(0.0886789133915965),   RC(0.0968726531622137),  RC(0.143815375874267),     RC(0.335214773313601),  RC(0.221862366978063),  RC(-0.147408947987273),
838                                   RC(4.16297599203445e-16),  RC(0.000727276166520566), RC(-0.00284892677941246), RC(0.00512492274297611), RC(-0.000275595071215218), RC(0.0136014719350733), RC(0.0165190013607726), RC(0.228116714912817)};
839     PetscCall(TSDIRKRegister(TSDIRK8616SAL, 8, 16, &A[0][0], b, NULL, bembed, 1, b));
840   }
841   {
842     // ESDIRK(16,8)[2]SAL[(16,5)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs
843     const PetscReal A[16][16] = {
844       {RC(0.0),                  RC(0.0),                 RC(0.0),                  RC(0.0),                   RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
845       {RC(0.117318819358521),    RC(0.117318819358521),   RC(0.0),                  RC(0.0),                   RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
846       {RC(0.0557014605974616),   RC(0.385525646638742),   RC(0.117318819358521),    RC(0.0),                   RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
847       {RC(0.063493276428895),    RC(0.373556126263681),   RC(0.0082994166438953),   RC(0.117318819358521),     RC(0.0),                  RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
848       {RC(0.0961351856230088),   RC(0.335558324517178),   RC(0.207077765910132),    RC(-0.0581917140797146),   RC(0.117318819358521),    RC(0.0),                  RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
849       {RC(0.0497669214238319),   RC(0.384288616546039),   RC(0.0821728117583936),   RC(0.120337007107103),     RC(0.202262782645888),    RC(0.117318819358521),    RC(0.0),                  RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
850       {RC(0.00626710666809847),  RC(0.496491452640725),   RC(-0.111303249827358),   RC(0.170478821683603),     RC(0.166517073971103),    RC(-0.0328669811542241),  RC(0.117318819358521),    RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
851       {RC(0.0463439767281591),   RC(0.00306724391019652), RC(-0.00816305222386205), RC(-0.0353302599538294),   RC(0.0139313601702569),   RC(-0.00992014507967429), RC(0.0210087909090165),   RC(0.117318819358521),  RC(0.0),                 RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
852       {RC(0.111574049232048),    RC(0.467639166482209),   RC(0.237773114804619),    RC(0.0798895699267508),    RC(0.109580615914593),    RC(0.0307353103825936),   RC(-0.0404391509541147),  RC(-0.16942110744293),  RC(0.117318819358521),   RC(0.0),                 RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
853       {RC(-0.0107072484863877),  RC(-0.231376703354252),  RC(0.017541113036611),    RC(0.144871527682418),     RC(-0.041855459769806),   RC(0.0841832168332261),   RC(-0.0850020937282192),  RC(0.486170343825899),  RC(-0.0526717116822739), RC(0.117318819358521),   RC(0.0),                RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
854       {RC(-0.0142238262314935),  RC(0.14752923682514),    RC(0.238235830732566),    RC(0.037950291904103),     RC(0.252075123381518),    RC(0.0474266904224567),   RC(-0.00363139069342027), RC(0.274081442388563),  RC(-0.0599166970745255), RC(-0.0527138812389185), RC(0.117318819358521),  RC(0.0),                 RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
855       {RC(-0.11837020183211),    RC(-0.635712481821264),  RC(0.239738832602538),    RC(0.330058936651707),     RC(-0.325784087988237),   RC(-0.0506514314589253),  RC(-0.281914404487009),   RC(0.852596345144291),  RC(0.651444614298805),   RC(-0.103476387303591),  RC(-0.354835880209975), RC(0.117318819358521),   RC(0.0),                 RC(0.0),                  RC(0.0),               RC(0.0)              },
856       {RC(-0.00458164025442349), RC(0.296219694015248),   RC(0.322146049419995),    RC(0.15917778285238),      RC(0.284864871688843),    RC(0.185509526463076),    RC(-0.0784621067883274),  RC(0.166312223692047),  RC(-0.284152486083397),  RC(-0.357125104338944),  RC(0.078437074055306),  RC(0.0884129667114481),  RC(0.117318819358521),   RC(0.0),                  RC(0.0),               RC(0.0)              },
857       {RC(-0.0545561913848106),  RC(0.675785423442753),   RC(0.423066443201941),    RC(-0.000165300126841193), RC(0.104252994793763),    RC(-0.105763019303021),   RC(-0.15988308809318),    RC(0.0515050001032011), RC(0.56013979290924),    RC(-0.45781539708603),   RC(-0.255870699752664), RC(0.026960254296416),   RC(-0.0721245985053681), RC(0.117318819358521),    RC(0.0),               RC(0.0)              },
858       {RC(0.0649253995775223),   RC(-0.0216056457922249), RC(-0.073738139377975),   RC(0.0931033310077225),    RC(-0.0194339577299149),  RC(-0.0879623837313009),  RC(0.057125517179467),    RC(0.205120850488097),  RC(0.132576503537441),   RC(0.489416890627328),   RC(-0.1106765720501),   RC(-0.081038793996096),  RC(0.0606031613503788),  RC(-0.00241467937442272), RC(0.117318819358521), RC(0.0)              },
859       {RC(0.0459979286336779),   RC(0.0780075394482806),  RC(0.015021874148058),    RC(0.195180277284195),     RC(-0.00246643310153235), RC(0.0473977117068314),   RC(-0.0682773558610363),  RC(0.19568019123878),   RC(-0.0876765449323747), RC(0.177874852409192),   RC(-0.337519251582222), RC(-0.0123255553640736), RC(0.311573291192553),   RC(0.0458604327754991),   RC(0.278352222645651), RC(0.117318819358521)}
860     };
861     const PetscReal b[16]      = {RC(0.0459979286336779),  RC(0.0780075394482806), RC(0.015021874148058),  RC(0.195180277284195),   RC(-0.00246643310153235), RC(0.0473977117068314), RC(-0.0682773558610363), RC(0.19568019123878),
862                                   RC(-0.0876765449323747), RC(0.177874852409192),  RC(-0.337519251582222), RC(-0.0123255553640736), RC(0.311573291192553),    RC(0.0458604327754991), RC(0.278352222645651),   RC(0.117318819358521)};
863     const PetscReal bembed[16] = {RC(0.0603373529853206),   RC(0.175453809423998),  RC(0.0537707777611352), RC(0.195309248607308),  RC(0.0135893741970232), RC(-0.0221160259296707), RC(-0.00726526156430691), RC(0.102961059369124),
864                                   RC(0.000900215457460583), RC(0.0547959465692338), RC(-0.334995726863153), RC(0.0464409662093384), RC(0.301388101652194),  RC(0.00524851570622031), RC(0.229538601845236),    RC(0.124643044573514)};
865     PetscCall(TSDIRKRegister(TSDIRKES8516SAL, 8, 16, &A[0][0], b, NULL, bembed, 1, b));
866   }
867 
868   /* Additive methods */
869   {
870     const PetscReal A[3][3] = {
871       {0.0, 0.0, 0.0},
872       {0.0, 0.0, 0.0},
873       {0.0, 0.5, 0.0}
874     };
875     const PetscReal At[3][3] = {
876       {1.0, 0.0, 0.0},
877       {0.0, 0.5, 0.0},
878       {0.0, 0.5, 0.5}
879     };
880     const PetscReal b[3]       = {0.0, 0.5, 0.5};
881     const PetscReal bembedt[3] = {1.0, 0.0, 0.0};
882     PetscCall(TSARKIMEXRegister(TSARKIMEX1BEE, 2, 3, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL));
883   }
884   {
885     const PetscReal A[2][2] = {
886       {0.0, 0.0},
887       {0.5, 0.0}
888     };
889     const PetscReal At[2][2] = {
890       {0.0, 0.0},
891       {0.0, 0.5}
892     };
893     const PetscReal b[2]       = {0.0, 1.0};
894     const PetscReal bembedt[2] = {0.5, 0.5};
895     /* binterpt[2][2] = {{1.0,-1.0},{0.0,1.0}};  second order dense output has poor stability properties and hence it is not currently in use */
896     PetscCall(TSARKIMEXRegister(TSARKIMEXARS122, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL));
897   }
898   {
899     const PetscReal A[2][2] = {
900       {0.0, 0.0},
901       {1.0, 0.0}
902     };
903     const PetscReal At[2][2] = {
904       {0.0, 0.0},
905       {0.5, 0.5}
906     };
907     const PetscReal b[2]       = {0.5, 0.5};
908     const PetscReal bembedt[2] = {0.0, 1.0};
909     /* binterpt[2][2] = {{1.0,-0.5},{0.0,0.5}}  second order dense output has poor stability properties and hence it is not currently in use */
910     PetscCall(TSARKIMEXRegister(TSARKIMEXA2, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL));
911   }
912   {
913     const PetscReal A[2][2] = {
914       {0.0, 0.0},
915       {1.0, 0.0}
916     };
917     const PetscReal At[2][2] = {
918       {us2,             0.0},
919       {1.0 - 2.0 * us2, us2}
920     };
921     const PetscReal b[2]           = {0.5, 0.5};
922     const PetscReal bembedt[2]     = {0.0, 1.0};
923     const PetscReal binterpt[2][2] = {
924       {(us2 - 1.0) / (2.0 * us2 - 1.0),     -1 / (2.0 * (1.0 - 2.0 * us2))},
925       {1 - (us2 - 1.0) / (2.0 * us2 - 1.0), -1 / (2.0 * (1.0 - 2.0 * us2))}
926     };
927     const PetscReal binterp[2][2] = {
928       {1.0, -0.5},
929       {0.0, 0.5 }
930     };
931     PetscCall(TSARKIMEXRegister(TSARKIMEXL2, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 2, binterpt[0], binterp[0]));
932   }
933   {
934     const PetscReal A[3][3] = {
935       {0,      0,   0},
936       {2 - s2, 0,   0},
937       {0.5,    0.5, 0}
938     };
939     const PetscReal At[3][3] = {
940       {0,            0,            0         },
941       {1 - 1 / s2,   1 - 1 / s2,   0         },
942       {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2}
943     };
944     const PetscReal bembedt[3]     = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)};
945     const PetscReal binterpt[3][2] = {
946       {1.0 / s2, -1.0 / (2.0 * s2)},
947       {1.0 / s2, -1.0 / (2.0 * s2)},
948       {1.0 - s2, 1.0 / s2         }
949     };
950     PetscCall(TSARKIMEXRegister(TSARKIMEX2C, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL));
951   }
952   {
953     const PetscReal A[3][3] = {
954       {0,      0,    0},
955       {2 - s2, 0,    0},
956       {0.75,   0.25, 0}
957     };
958     const PetscReal At[3][3] = {
959       {0,            0,            0         },
960       {1 - 1 / s2,   1 - 1 / s2,   0         },
961       {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2}
962     };
963     const PetscReal bembedt[3]     = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)};
964     const PetscReal binterpt[3][2] = {
965       {1.0 / s2, -1.0 / (2.0 * s2)},
966       {1.0 / s2, -1.0 / (2.0 * s2)},
967       {1.0 - s2, 1.0 / s2         }
968     };
969     PetscCall(TSARKIMEXRegister(TSARKIMEX2D, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL));
970   }
971   { /* Optimal for linear implicit part */
972     const PetscReal A[3][3] = {
973       {0,                0,                0},
974       {2 - s2,           0,                0},
975       {(3 - 2 * s2) / 6, (3 + 2 * s2) / 6, 0}
976     };
977     const PetscReal At[3][3] = {
978       {0,            0,            0         },
979       {1 - 1 / s2,   1 - 1 / s2,   0         },
980       {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2}
981     };
982     const PetscReal bembedt[3]     = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)};
983     const PetscReal binterpt[3][2] = {
984       {1.0 / s2, -1.0 / (2.0 * s2)},
985       {1.0 / s2, -1.0 / (2.0 * s2)},
986       {1.0 - s2, 1.0 / s2         }
987     };
988     PetscCall(TSARKIMEXRegister(TSARKIMEX2E, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL));
989   }
990   { /* Optimal for linear implicit part */
991     const PetscReal A[3][3] = {
992       {0,   0,   0},
993       {0.5, 0,   0},
994       {0.5, 0.5, 0}
995     };
996     const PetscReal At[3][3] = {
997       {0.25,   0,      0     },
998       {0,      0.25,   0     },
999       {1. / 3, 1. / 3, 1. / 3}
1000     };
1001     PetscCall(TSARKIMEXRegister(TSARKIMEXPRSSP2, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL));
1002   }
1003   {
1004     const PetscReal A[4][4] = {
1005       {0,                                0,                                0,                                 0},
1006       {1767732205903. / 2027836641118.,  0,                                0,                                 0},
1007       {5535828885825. / 10492691773637., 788022342437. / 10882634858940.,  0,                                 0},
1008       {6485989280629. / 16251701735622., -4246266847089. / 9704473918619., 10755448449292. / 10357097424841., 0}
1009     };
1010     const PetscReal At[4][4] = {
1011       {0,                                0,                                0,                                 0                              },
1012       {1767732205903. / 4055673282236.,  1767732205903. / 4055673282236.,  0,                                 0                              },
1013       {2746238789719. / 10658868560708., -640167445237. / 6845629431997.,  1767732205903. / 4055673282236.,   0                              },
1014       {1471266399579. / 7840856788654.,  -4482444167858. / 7529755066697., 11266239266428. / 11593286722821., 1767732205903. / 4055673282236.}
1015     };
1016     const PetscReal bembedt[4]     = {2756255671327. / 12835298489170., -10771552573575. / 22201958757719., 9247589265047. / 10645013368117., 2193209047091. / 5459859503100.};
1017     const PetscReal binterpt[4][2] = {
1018       {4655552711362. / 22874653954995.,  -215264564351. / 13552729205753.  },
1019       {-18682724506714. / 9892148508045., 17870216137069. / 13817060693119. },
1020       {34259539580243. / 13192909600954., -28141676662227. / 17317692491321.},
1021       {584795268549. / 6622622206610.,    2508943948391. / 7218656332882.   }
1022     };
1023     PetscCall(TSARKIMEXRegister(TSARKIMEX3, 3, 4, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL));
1024   }
1025   {
1026     const PetscReal A[5][5] = {
1027       {0,        0,       0,      0,       0},
1028       {1. / 2,   0,       0,      0,       0},
1029       {11. / 18, 1. / 18, 0,      0,       0},
1030       {5. / 6,   -5. / 6, .5,     0,       0},
1031       {1. / 4,   7. / 4,  3. / 4, -7. / 4, 0}
1032     };
1033     const PetscReal At[5][5] = {
1034       {0, 0,       0,       0,      0     },
1035       {0, 1. / 2,  0,       0,      0     },
1036       {0, 1. / 6,  1. / 2,  0,      0     },
1037       {0, -1. / 2, 1. / 2,  1. / 2, 0     },
1038       {0, 3. / 2,  -3. / 2, 1. / 2, 1. / 2}
1039     };
1040     PetscCall(TSARKIMEXRegister(TSARKIMEXARS443, 3, 5, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL));
1041   }
1042   {
1043     const PetscReal A[5][5] = {
1044       {0,      0,      0,      0, 0},
1045       {1,      0,      0,      0, 0},
1046       {4. / 9, 2. / 9, 0,      0, 0},
1047       {1. / 4, 0,      3. / 4, 0, 0},
1048       {1. / 4, 0,      3. / 5, 0, 0}
1049     };
1050     const PetscReal At[5][5] = {
1051       {0,       0,       0,   0,   0 },
1052       {.5,      .5,      0,   0,   0 },
1053       {5. / 18, -1. / 9, .5,  0,   0 },
1054       {.5,      0,       0,   .5,  0 },
1055       {.25,     0,       .75, -.5, .5}
1056     };
1057     PetscCall(TSARKIMEXRegister(TSARKIMEXBPR3, 3, 5, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL));
1058   }
1059   {
1060     const PetscReal A[6][6] = {
1061       {0,                               0,                                 0,                                 0,                                0,              0},
1062       {1. / 2,                          0,                                 0,                                 0,                                0,              0},
1063       {13861. / 62500.,                 6889. / 62500.,                    0,                                 0,                                0,              0},
1064       {-116923316275. / 2393684061468., -2731218467317. / 15368042101831., 9408046702089. / 11113171139209.,  0,                                0,              0},
1065       {-451086348788. / 2902428689909., -2682348792572. / 7519795681897.,  12662868775082. / 11960479115383., 3355817975965. / 11060851509271., 0,              0},
1066       {647845179188. / 3216320057751.,  73281519250. / 8382639484533.,     552539513391. / 3454668386233.,    3354512671639. / 8306763924573.,  4040. / 17871., 0}
1067     };
1068     const PetscReal At[6][6] = {
1069       {0,                            0,                       0,                       0,                   0,             0     },
1070       {1. / 4,                       1. / 4,                  0,                       0,                   0,             0     },
1071       {8611. / 62500.,               -1743. / 31250.,         1. / 4,                  0,                   0,             0     },
1072       {5012029. / 34652500.,         -654441. / 2922500.,     174375. / 388108.,       1. / 4,              0,             0     },
1073       {15267082809. / 155376265600., -71443401. / 120774400., 730878875. / 902184768., 2285395. / 8070912., 1. / 4,        0     },
1074       {82889. / 524892.,             0,                       15625. / 83664.,         69875. / 102672.,    -2260. / 8211, 1. / 4}
1075     };
1076     const PetscReal bembedt[6]     = {4586570599. / 29645900160., 0, 178811875. / 945068544., 814220225. / 1159782912., -3700637. / 11593932., 61727. / 225920.};
1077     const PetscReal binterpt[6][3] = {
1078       {6943876665148. / 7220017795957.,   -54480133. / 30881146., 6818779379841. / 7100303317025.  },
1079       {0,                                 0,                      0                                },
1080       {7640104374378. / 9702883013639.,   -11436875. / 14766696., 2173542590792. / 12501825683035. },
1081       {-20649996744609. / 7521556579894., 174696575. / 18121608., -31592104683404. / 5083833661969.},
1082       {8854892464581. / 2390941311638.,   -12120380. / 966161.,   61146701046299. / 7138195549469. },
1083       {-11397109935349. / 6675773540249., 3843. / 706.,           -17219254887155. / 4939391667607.}
1084     };
1085     PetscCall(TSARKIMEXRegister(TSARKIMEX4, 4, 6, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 3, binterpt[0], NULL));
1086   }
1087   {
1088     const PetscReal A[8][8] = {
1089       {0,                                  0,                              0,                                 0,                                  0,                               0,                                 0,                               0},
1090       {41. / 100,                          0,                              0,                                 0,                                  0,                               0,                                 0,                               0},
1091       {367902744464. / 2072280473677.,     677623207551. / 8224143866563., 0,                                 0,                                  0,                               0,                                 0,                               0},
1092       {1268023523408. / 10340822734521.,   0,                              1029933939417. / 13636558850479.,  0,                                  0,                               0,                                 0,                               0},
1093       {14463281900351. / 6315353703477.,   0,                              66114435211212. / 5879490589093.,  -54053170152839. / 4284798021562.,  0,                               0,                                 0,                               0},
1094       {14090043504691. / 34967701212078.,  0,                              15191511035443. / 11219624916014., -18461159152457. / 12425892160975., -281667163811. / 9011619295870., 0,                                 0,                               0},
1095       {19230459214898. / 13134317526959.,  0,                              21275331358303. / 2942455364971.,  -38145345988419. / 4862620318723.,  -1. / 8,                         -1. / 8,                           0,                               0},
1096       {-19977161125411. / 11928030595625., 0,                              -40795976796054. / 6384907823539., 177454434618887. / 12078138498510., 782672205425. / 8267701900261.,  -69563011059811. / 9646580694205., 7356628210526. / 4942186776405., 0}
1097     };
1098     const PetscReal At[8][8] = {
1099       {0,                                0,                                0,                                 0,                                  0,                                0,                                  0,                                 0         },
1100       {41. / 200.,                       41. / 200.,                       0,                                 0,                                  0,                                0,                                  0,                                 0         },
1101       {41. / 400.,                       -567603406766. / 11931857230679., 41. / 200.,                        0,                                  0,                                0,                                  0,                                 0         },
1102       {683785636431. / 9252920307686.,   0,                                -110385047103. / 1367015193373.,   41. / 200.,                         0,                                0,                                  0,                                 0         },
1103       {3016520224154. / 10081342136671., 0,                                30586259806659. / 12414158314087., -22760509404356. / 11113319521817., 41. / 200.,                       0,                                  0,                                 0         },
1104       {218866479029. / 1489978393911.,   0,                                638256894668. / 5436446318841.,    -1179710474555. / 5321154724896.,   -60928119172. / 8023461067671.,   41. / 200.,                         0,                                 0         },
1105       {1020004230633. / 5715676835656.,  0,                                25762820946817. / 25263940353407., -2161375909145. / 9755907335909.,   -211217309593. / 5846859502534.,  -4269925059573. / 7827059040749.,   41. / 200,                         0         },
1106       {-872700587467. / 9133579230613.,  0,                                0,                                 22348218063261. / 9555858737531.,   -1143369518992. / 8141816002931., -39379526789629. / 19018526304540., 32727382324388. / 42900044865799., 41. / 200.}
1107     };
1108     const PetscReal bembedt[8]     = {-975461918565. / 9796059967033., 0, 0, 78070527104295. / 32432590147079., -548382580838. / 3424219808633., -33438840321285. / 15594753105479., 3629800801594. / 4656183773603., 4035322873751. / 18575991585200.};
1109     const PetscReal binterpt[8][3] = {
1110       {-17674230611817. / 10670229744614., 43486358583215. / 12773830924787.,  -9257016797708. / 5021505065439. },
1111       {0,                                  0,                                  0                                },
1112       {0,                                  0,                                  0                                },
1113       {65168852399939. / 7868540260826.,   -91478233927265. / 11067650958493., 26096422576131. / 11239449250142.},
1114       {15494834004392. / 5936557850923.,   -79368583304911. / 10890268929626., 92396832856987. / 20362823103730.},
1115       {-99329723586156. / 26959484932159., -12239297817655. / 9152339842473.,  30029262896817. / 10175596800299.},
1116       {-19024464361622. / 5461577185407.,  115839755401235. / 10719374521269., -26136350496073. / 3983972220547.},
1117       {-6511271360970. / 6095937251113.,   5843115559534. / 2180450260947.,    -5289405421727. / 3760307252460. }
1118     };
1119     PetscCall(TSARKIMEXRegister(TSARKIMEX5, 5, 8, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 3, binterpt[0], NULL));
1120   }
1121 #undef RC
1122 #undef us2
1123 #undef s2
1124   PetscFunctionReturn(PETSC_SUCCESS);
1125 }
1126 
1127 /*@C
1128   TSARKIMEXRegisterDestroy - Frees the list of schemes that were registered by `TSARKIMEXRegister()`.
1129 
1130   Not Collective
1131 
1132   Level: advanced
1133 
1134 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXRegister()`, `TSARKIMEXRegisterAll()`
1135 @*/
1136 PetscErrorCode TSARKIMEXRegisterDestroy(void)
1137 {
1138   ARKTableauLink link;
1139 
1140   PetscFunctionBegin;
1141   while ((link = ARKTableauList)) {
1142     ARKTableau t   = &link->tab;
1143     ARKTableauList = link->next;
1144     PetscCall(PetscFree6(t->At, t->bt, t->ct, t->A, t->b, t->c));
1145     PetscCall(PetscFree2(t->bembedt, t->bembed));
1146     PetscCall(PetscFree2(t->binterpt, t->binterp));
1147     PetscCall(PetscFree(t->name));
1148     PetscCall(PetscFree(link));
1149   }
1150   TSARKIMEXRegisterAllCalled = PETSC_FALSE;
1151   PetscFunctionReturn(PETSC_SUCCESS);
1152 }
1153 
1154 /*@C
1155   TSARKIMEXInitializePackage - This function initializes everything in the `TSARKIMEX` package. It is called
1156   from `TSInitializePackage()`.
1157 
1158   Level: developer
1159 
1160 .seealso: [](ch_ts), `PetscInitialize()`, `TSARKIMEXFinalizePackage()`
1161 @*/
1162 PetscErrorCode TSARKIMEXInitializePackage(void)
1163 {
1164   PetscFunctionBegin;
1165   if (TSARKIMEXPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
1166   TSARKIMEXPackageInitialized = PETSC_TRUE;
1167   PetscCall(TSARKIMEXRegisterAll());
1168   PetscCall(PetscRegisterFinalize(TSARKIMEXFinalizePackage));
1169   PetscFunctionReturn(PETSC_SUCCESS);
1170 }
1171 
1172 /*@C
1173   TSARKIMEXFinalizePackage - This function destroys everything in the `TSARKIMEX` package. It is
1174   called from `PetscFinalize()`.
1175 
1176   Level: developer
1177 
1178 .seealso: [](ch_ts), `PetscFinalize()`, `TSARKIMEXInitializePackage()`
1179 @*/
1180 PetscErrorCode TSARKIMEXFinalizePackage(void)
1181 {
1182   PetscFunctionBegin;
1183   TSARKIMEXPackageInitialized = PETSC_FALSE;
1184   PetscCall(TSARKIMEXRegisterDestroy());
1185   PetscFunctionReturn(PETSC_SUCCESS);
1186 }
1187 
1188 /*@C
1189   TSARKIMEXRegister - register a `TSARKIMEX` scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation
1190 
1191   Logically Collective.
1192 
1193   Input Parameters:
1194 + name     - identifier for method
1195 . order    - approximation order of method
1196 . s        - number of stages, this is the dimension of the matrices below
1197 . At       - Butcher table of stage coefficients for stiff part (dimension s*s, row-major)
1198 . bt       - Butcher table for completing the stiff part of the step (dimension s; NULL to use the last row of At)
1199 . ct       - Abscissa of each stiff stage (dimension s, NULL to use row sums of At)
1200 . A        - Non-stiff stage coefficients (dimension s*s, row-major)
1201 . b        - Non-stiff step completion table (dimension s; NULL to use last row of At)
1202 . c        - Non-stiff abscissa (dimension s; NULL to use row sums of A)
1203 . bembedt  - Stiff part of completion table for embedded method (dimension s; NULL if not available)
1204 . bembed   - Non-stiff part of completion table for embedded method (dimension s; NULL to use bembedt if provided)
1205 . pinterp  - Order of the interpolation scheme, equal to the number of columns of binterpt and binterp
1206 . binterpt - Coefficients of the interpolation formula for the stiff part (dimension s*pinterp)
1207 - binterp  - Coefficients of the interpolation formula for the non-stiff part (dimension s*pinterp; NULL to reuse binterpt)
1208 
1209   Level: advanced
1210 
1211   Note:
1212   Several `TSARKIMEX` methods are provided, this function is only needed to create new methods.
1213 
1214 .seealso: [](ch_ts), `TSARKIMEX`, `TSType`, `TS`
1215 @*/
1216 PetscErrorCode TSARKIMEXRegister(TSARKIMEXType name, PetscInt order, PetscInt s, const PetscReal At[], const PetscReal bt[], const PetscReal ct[], const PetscReal A[], const PetscReal b[], const PetscReal c[], const PetscReal bembedt[], const PetscReal bembed[], PetscInt pinterp, const PetscReal binterpt[], const PetscReal binterp[])
1217 {
1218   ARKTableauLink link;
1219   ARKTableau     t;
1220   PetscInt       i, j;
1221 
1222   PetscFunctionBegin;
1223   PetscCall(TSARKIMEXInitializePackage());
1224   for (link = ARKTableauList; link; link = link->next) {
1225     PetscBool match;
1226 
1227     PetscCall(PetscStrcmp(link->tab.name, name, &match));
1228     PetscCheck(!match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Method with name \"%s\" already registered", name);
1229   }
1230   PetscCall(PetscNew(&link));
1231   t = &link->tab;
1232   PetscCall(PetscStrallocpy(name, &t->name));
1233   t->order = order;
1234   t->s     = s;
1235   PetscCall(PetscMalloc6(s * s, &t->At, s, &t->bt, s, &t->ct, s * s, &t->A, s, &t->b, s, &t->c));
1236   PetscCall(PetscArraycpy(t->At, At, s * s));
1237   if (A) {
1238     PetscCall(PetscArraycpy(t->A, A, s * s));
1239     t->additive = PETSC_TRUE;
1240   }
1241 
1242   if (bt) PetscCall(PetscArraycpy(t->bt, bt, s));
1243   else
1244     for (i = 0; i < s; i++) t->bt[i] = At[(s - 1) * s + i];
1245 
1246   if (t->additive) {
1247     if (b) PetscCall(PetscArraycpy(t->b, b, s));
1248     else
1249       for (i = 0; i < s; i++) t->b[i] = t->bt[i];
1250   } else PetscCall(PetscArrayzero(t->b, s));
1251 
1252   if (ct) PetscCall(PetscArraycpy(t->ct, ct, s));
1253   else
1254     for (i = 0; i < s; i++)
1255       for (j = 0, t->ct[i] = 0; j < s; j++) t->ct[i] += At[i * s + j];
1256 
1257   if (t->additive) {
1258     if (c) PetscCall(PetscArraycpy(t->c, c, s));
1259     else
1260       for (i = 0; i < s; i++)
1261         for (j = 0, t->c[i] = 0; j < s; j++) t->c[i] += A[i * s + j];
1262   } else PetscCall(PetscArrayzero(t->c, s));
1263 
1264   t->stiffly_accurate = PETSC_TRUE;
1265   for (i = 0; i < s; i++)
1266     if (t->At[(s - 1) * s + i] != t->bt[i]) t->stiffly_accurate = PETSC_FALSE;
1267 
1268   t->explicit_first_stage = PETSC_TRUE;
1269   for (i = 0; i < s; i++)
1270     if (t->At[i] != 0.0) t->explicit_first_stage = PETSC_FALSE;
1271 
1272   /* def of FSAL can be made more precise */
1273   t->FSAL_implicit = (PetscBool)(t->explicit_first_stage && t->stiffly_accurate);
1274 
1275   if (bembedt) {
1276     PetscCall(PetscMalloc2(s, &t->bembedt, s, &t->bembed));
1277     PetscCall(PetscArraycpy(t->bembedt, bembedt, s));
1278     PetscCall(PetscArraycpy(t->bembed, bembed ? bembed : bembedt, s));
1279   }
1280 
1281   t->pinterp = pinterp;
1282   PetscCall(PetscMalloc2(s * pinterp, &t->binterpt, s * pinterp, &t->binterp));
1283   PetscCall(PetscArraycpy(t->binterpt, binterpt, s * pinterp));
1284   PetscCall(PetscArraycpy(t->binterp, binterp ? binterp : binterpt, s * pinterp));
1285 
1286   link->next     = ARKTableauList;
1287   ARKTableauList = link;
1288   PetscFunctionReturn(PETSC_SUCCESS);
1289 }
1290 
1291 /*@C
1292   TSDIRKRegister - register a `TSDIRK` scheme by providing the entries in its Butcher tableau and, optionally, embedded approximations and interpolation
1293 
1294   Logically Collective.
1295 
1296   Input Parameters:
1297 + name     - identifier for method
1298 . order    - approximation order of method
1299 . s        - number of stages, this is the dimension of the matrices below
1300 . At       - Butcher table of stage coefficients (dimension `s`*`s`, row-major order)
1301 . bt       - Butcher table for completing the step (dimension `s`; pass `NULL` to use the last row of `At`)
1302 . ct       - Abscissa of each stage (dimension s, NULL to use row sums of At)
1303 . bembedt  - Stiff part of completion table for embedded method (dimension s; `NULL` if not available)
1304 . pinterp  - Order of the interpolation scheme, equal to the number of columns of `binterpt` and `binterp`
1305 - binterpt - Coefficients of the interpolation formula (dimension s*pinterp)
1306 
1307   Level: advanced
1308 
1309   Note:
1310   Several `TSDIRK` methods are provided, the use of this function is only needed to create new methods.
1311 
1312 .seealso: [](ch_ts), `TSDIRK`, `TSType`, `TS`
1313 @*/
1314 PetscErrorCode TSDIRKRegister(TSDIRKType name, PetscInt order, PetscInt s, const PetscReal At[], const PetscReal bt[], const PetscReal ct[], const PetscReal bembedt[], PetscInt pinterp, const PetscReal binterpt[])
1315 {
1316   PetscFunctionBegin;
1317   PetscCall(TSARKIMEXRegister(name, order, s, At, bt, ct, NULL, NULL, NULL, bembedt, NULL, pinterp, binterpt, NULL));
1318   PetscFunctionReturn(PETSC_SUCCESS);
1319 }
1320 
1321 /*
1322  The step completion formula is
1323 
1324  x1 = x0 - h bt^T YdotI + h b^T YdotRHS
1325 
1326  This function can be called before or after ts->vec_sol has been updated.
1327  Suppose we have a completion formula (bt,b) and an embedded formula (bet,be) of different order.
1328  We can write
1329 
1330  x1e = x0 - h bet^T YdotI + h be^T YdotRHS
1331      = x1 + h bt^T YdotI - h b^T YdotRHS - h bet^T YdotI + h be^T YdotRHS
1332      = x1 - h (bet - bt)^T YdotI + h (be - b)^T YdotRHS
1333 
1334  so we can evaluate the method with different order even after the step has been optimistically completed.
1335 */
1336 static PetscErrorCode TSEvaluateStep_ARKIMEX(TS ts, PetscInt order, Vec X, PetscBool *done)
1337 {
1338   TS_ARKIMEX  *ark = (TS_ARKIMEX *)ts->data;
1339   ARKTableau   tab = ark->tableau;
1340   PetscScalar *w   = ark->work;
1341   PetscReal    h;
1342   PetscInt     s = tab->s, j;
1343   PetscBool    hasE;
1344 
1345   PetscFunctionBegin;
1346   switch (ark->status) {
1347   case TS_STEP_INCOMPLETE:
1348   case TS_STEP_PENDING:
1349     h = ts->time_step;
1350     break;
1351   case TS_STEP_COMPLETE:
1352     h = ts->ptime - ts->ptime_prev;
1353     break;
1354   default:
1355     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus");
1356   }
1357   if (order == tab->order) {
1358     if (ark->status == TS_STEP_INCOMPLETE) {
1359       if (!ark->imex && tab->stiffly_accurate) { /* Only the stiffly accurate implicit formula is used */
1360         PetscCall(VecCopy(ark->Y[s - 1], X));
1361       } else { /* Use the standard completion formula (bt,b) */
1362         PetscCall(VecCopy(ts->vec_sol, X));
1363         for (j = 0; j < s; j++) w[j] = h * tab->bt[j];
1364         PetscCall(VecMAXPY(X, s, w, ark->YdotI));
1365         if (tab->additive && ark->imex) { /* Method is IMEX, complete the explicit formula */
1366           PetscCall(TSHasRHSFunction(ts, &hasE));
1367           if (hasE) {
1368             for (j = 0; j < s; j++) w[j] = h * tab->b[j];
1369             PetscCall(VecMAXPY(X, s, w, ark->YdotRHS));
1370           }
1371         }
1372       }
1373     } else PetscCall(VecCopy(ts->vec_sol, X));
1374     if (done) *done = PETSC_TRUE;
1375     PetscFunctionReturn(PETSC_SUCCESS);
1376   } else if (order == tab->order - 1) {
1377     if (!tab->bembedt) goto unavailable;
1378     if (ark->status == TS_STEP_INCOMPLETE) { /* Complete with the embedded method (bet,be) */
1379       PetscCall(VecCopy(ts->vec_sol, X));
1380       for (j = 0; j < s; j++) w[j] = h * tab->bembedt[j];
1381       PetscCall(VecMAXPY(X, s, w, ark->YdotI));
1382       if (tab->additive) {
1383         PetscCall(TSHasRHSFunction(ts, &hasE));
1384         if (hasE) {
1385           for (j = 0; j < s; j++) w[j] = h * tab->bembed[j];
1386           PetscCall(VecMAXPY(X, s, w, ark->YdotRHS));
1387         }
1388       }
1389     } else { /* Rollback and re-complete using (bet-be,be-b) */
1390       PetscCall(VecCopy(ts->vec_sol, X));
1391       for (j = 0; j < s; j++) w[j] = h * (tab->bembedt[j] - tab->bt[j]);
1392       PetscCall(VecMAXPY(X, tab->s, w, ark->YdotI));
1393       if (tab->additive) {
1394         PetscCall(TSHasRHSFunction(ts, &hasE));
1395         if (hasE) {
1396           for (j = 0; j < s; j++) w[j] = h * (tab->bembed[j] - tab->b[j]);
1397           PetscCall(VecMAXPY(X, s, w, ark->YdotRHS));
1398         }
1399       }
1400     }
1401     if (done) *done = PETSC_TRUE;
1402     PetscFunctionReturn(PETSC_SUCCESS);
1403   }
1404 unavailable:
1405   if (done) *done = PETSC_FALSE;
1406   else
1407     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "ARKIMEX '%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,
1408             tab->order, order);
1409   PetscFunctionReturn(PETSC_SUCCESS);
1410 }
1411 
1412 static PetscErrorCode TSARKIMEXTestMassIdentity(TS ts, PetscBool *id)
1413 {
1414   Vec         Udot, Y1, Y2;
1415   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1416   PetscReal   norm;
1417 
1418   PetscFunctionBegin;
1419   PetscCall(VecDuplicate(ts->vec_sol, &Udot));
1420   PetscCall(VecDuplicate(ts->vec_sol, &Y1));
1421   PetscCall(VecDuplicate(ts->vec_sol, &Y2));
1422   PetscCall(TSComputeIFunction(ts, ts->ptime, ts->vec_sol, Udot, Y1, ark->imex));
1423   PetscCall(VecSetRandom(Udot, NULL));
1424   PetscCall(TSComputeIFunction(ts, ts->ptime, ts->vec_sol, Udot, Y2, ark->imex));
1425   PetscCall(VecAXPY(Y2, -1.0, Y1));
1426   PetscCall(VecAXPY(Y2, -1.0, Udot));
1427   PetscCall(VecNorm(Y2, NORM_2, &norm));
1428   if (norm < 100.0 * PETSC_MACHINE_EPSILON) {
1429     *id = PETSC_TRUE;
1430   } else {
1431     *id = PETSC_FALSE;
1432     PetscCall(PetscInfo((PetscObject)ts, "IFunction(Udot = random) - IFunction(Udot = 0) is not near Udot, %g, suspect mass matrix implied in IFunction() is not the identity as required\n", (double)norm));
1433   }
1434   PetscCall(VecDestroy(&Udot));
1435   PetscCall(VecDestroy(&Y1));
1436   PetscCall(VecDestroy(&Y2));
1437   PetscFunctionReturn(PETSC_SUCCESS);
1438 }
1439 
1440 static PetscErrorCode TSRollBack_ARKIMEX(TS ts)
1441 {
1442   TS_ARKIMEX      *ark = (TS_ARKIMEX *)ts->data;
1443   ARKTableau       tab = ark->tableau;
1444   const PetscInt   s   = tab->s;
1445   const PetscReal *bt = tab->bt, *b = tab->b;
1446   PetscScalar     *w     = ark->work;
1447   Vec             *YdotI = ark->YdotI, *YdotRHS = ark->YdotRHS;
1448   PetscInt         j;
1449   PetscReal        h;
1450 
1451   PetscFunctionBegin;
1452   switch (ark->status) {
1453   case TS_STEP_INCOMPLETE:
1454   case TS_STEP_PENDING:
1455     h = ts->time_step;
1456     break;
1457   case TS_STEP_COMPLETE:
1458     h = ts->ptime - ts->ptime_prev;
1459     break;
1460   default:
1461     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus");
1462   }
1463   for (j = 0; j < s; j++) w[j] = -h * bt[j];
1464   PetscCall(VecMAXPY(ts->vec_sol, s, w, YdotI));
1465   if (tab->additive) {
1466     PetscBool hasE;
1467 
1468     PetscCall(TSHasRHSFunction(ts, &hasE));
1469     if (hasE) {
1470       for (j = 0; j < s; j++) w[j] = -h * b[j];
1471       PetscCall(VecMAXPY(ts->vec_sol, s, w, YdotRHS));
1472     }
1473   }
1474   PetscFunctionReturn(PETSC_SUCCESS);
1475 }
1476 
1477 static PetscErrorCode TSStep_ARKIMEX(TS ts)
1478 {
1479   TS_ARKIMEX      *ark = (TS_ARKIMEX *)ts->data;
1480   ARKTableau       tab = ark->tableau;
1481   const PetscInt   s   = tab->s;
1482   const PetscReal *At = tab->At, *A = tab->A, *ct = tab->ct, *c = tab->c;
1483   PetscScalar     *w = ark->work;
1484   Vec             *Y = ark->Y, *YdotI = ark->YdotI, *YdotRHS = ark->YdotRHS, Ydot = ark->Ydot, Ydot0 = ark->Ydot0, Z = ark->Z;
1485   PetscBool        extrapolate = ark->extrapolate;
1486   TSAdapt          adapt;
1487   SNES             snes;
1488   PetscInt         i, j, its, lits;
1489   PetscInt         rejections = 0;
1490   PetscBool        hasE = PETSC_FALSE, dirk = (PetscBool)(!tab->additive), stageok, accept = PETSC_TRUE;
1491   PetscReal        next_time_step = ts->time_step;
1492 
1493   PetscFunctionBegin;
1494   if (ark->extrapolate && !ark->Y_prev) {
1495     PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y_prev));
1496     PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI_prev));
1497     if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS_prev));
1498   }
1499 
1500   if (!dirk) PetscCall(TSHasRHSFunction(ts, &hasE));
1501   if (!hasE) dirk = PETSC_TRUE;
1502 
1503   if (!ts->steprollback) {
1504     if (dirk || ts->equation_type >= TS_EQ_IMPLICIT) { /* Save the initial slope for the next step */
1505       PetscCall(VecCopy(YdotI[s - 1], Ydot0));
1506     }
1507     if (ark->extrapolate && !ts->steprestart) { /* Save the Y, YdotI, YdotRHS for extrapolation initial guess */
1508       for (i = 0; i < s; i++) {
1509         PetscCall(VecCopy(Y[i], ark->Y_prev[i]));
1510         PetscCall(VecCopy(YdotI[i], ark->YdotI_prev[i]));
1511         if (tab->additive && hasE) PetscCall(VecCopy(YdotRHS[i], ark->YdotRHS_prev[i]));
1512       }
1513     }
1514   }
1515 
1516   /* For fully implicit formulations we can solve the equations
1517        F(tn,xn,xdot) = 0
1518      for the explicit first stage */
1519   if (dirk && tab->explicit_first_stage && ts->steprestart) {
1520     ark->scoeff = 0.0;
1521     PetscCall(VecCopy(ts->vec_sol, Z));
1522     PetscCall(TSGetSNES(ts, &snes));
1523     PetscCall(SNESSolve(snes, NULL, Ydot0));
1524   }
1525 
1526   /* For IMEX we compute a step */
1527   if (!dirk && ts->equation_type >= TS_EQ_IMPLICIT && tab->explicit_first_stage && ts->steprestart) {
1528     TS ts_start;
1529     if (PetscDefined(USE_DEBUG) && hasE) {
1530       PetscBool id = PETSC_FALSE;
1531       PetscCall(TSARKIMEXTestMassIdentity(ts, &id));
1532       PetscCheck(id, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_INCOMP, "This scheme requires an identity mass matrix, however the TSIFunction you provided does not utilize an identity mass matrix");
1533     }
1534     PetscCall(TSClone(ts, &ts_start));
1535     PetscCall(TSSetSolution(ts_start, ts->vec_sol));
1536     PetscCall(TSSetTime(ts_start, ts->ptime));
1537     PetscCall(TSSetMaxSteps(ts_start, ts->steps + 1));
1538     PetscCall(TSSetMaxTime(ts_start, ts->ptime + ts->time_step));
1539     PetscCall(TSSetExactFinalTime(ts_start, TS_EXACTFINALTIME_STEPOVER));
1540     PetscCall(TSSetTimeStep(ts_start, ts->time_step));
1541     PetscCall(TSSetType(ts_start, TSARKIMEX));
1542     PetscCall(TSARKIMEXSetFullyImplicit(ts_start, PETSC_TRUE));
1543     PetscCall(TSARKIMEXSetType(ts_start, TSARKIMEX1BEE));
1544 
1545     PetscCall(TSRestartStep(ts_start));
1546     PetscCall(TSSolve(ts_start, ts->vec_sol));
1547     PetscCall(TSGetTime(ts_start, &ts->ptime));
1548     PetscCall(TSGetTimeStep(ts_start, &ts->time_step));
1549 
1550     { /* Save the initial slope for the next step */
1551       TS_ARKIMEX *ark_start = (TS_ARKIMEX *)ts_start->data;
1552       PetscCall(VecCopy(ark_start->YdotI[ark_start->tableau->s - 1], Ydot0));
1553     }
1554     ts->steps++;
1555 
1556     /* Set the correct TS in SNES */
1557     /* We'll try to bypass this by changing the method on the fly */
1558     {
1559       PetscCall(TSGetSNES(ts, &snes));
1560       PetscCall(TSSetSNES(ts, snes));
1561     }
1562     PetscCall(TSDestroy(&ts_start));
1563   }
1564 
1565   ark->status = TS_STEP_INCOMPLETE;
1566   while (!ts->reason && ark->status != TS_STEP_COMPLETE) {
1567     PetscReal t = ts->ptime;
1568     PetscReal h = ts->time_step;
1569     for (i = 0; i < s; i++) {
1570       ark->stage_time = t + h * ct[i];
1571       PetscCall(TSPreStage(ts, ark->stage_time));
1572       if (At[i * s + i] == 0) { /* This stage is explicit */
1573         PetscCheck(i == 0 || ts->equation_type < TS_EQ_IMPLICIT, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Explicit stages other than the first one are not supported for implicit problems");
1574         PetscCall(VecCopy(ts->vec_sol, Y[i]));
1575         for (j = 0; j < i; j++) w[j] = h * At[i * s + j];
1576         PetscCall(VecMAXPY(Y[i], i, w, YdotI));
1577         if (tab->additive && hasE) {
1578           for (j = 0; j < i; j++) w[j] = h * A[i * s + j];
1579           PetscCall(VecMAXPY(Y[i], i, w, YdotRHS));
1580         }
1581       } else {
1582         ark->scoeff = 1. / At[i * s + i];
1583         /* Ydot = shift*(Y-Z) */
1584         PetscCall(VecCopy(ts->vec_sol, Z));
1585         for (j = 0; j < i; j++) w[j] = h * At[i * s + j];
1586         PetscCall(VecMAXPY(Z, i, w, YdotI));
1587         if (tab->additive && hasE) {
1588           for (j = 0; j < i; j++) w[j] = h * A[i * s + j];
1589           PetscCall(VecMAXPY(Z, i, w, YdotRHS));
1590         }
1591         if (extrapolate && !ts->steprestart) {
1592           /* Initial guess extrapolated from previous time step stage values */
1593           PetscCall(TSExtrapolate_ARKIMEX(ts, c[i], Y[i]));
1594         } else {
1595           /* Initial guess taken from last stage */
1596           PetscCall(VecCopy(i > 0 ? Y[i - 1] : ts->vec_sol, Y[i]));
1597         }
1598         PetscCall(TSGetSNES(ts, &snes));
1599         PetscCall(SNESSolve(snes, NULL, Y[i]));
1600         PetscCall(SNESGetIterationNumber(snes, &its));
1601         PetscCall(SNESGetLinearSolveIterations(snes, &lits));
1602         ts->snes_its += its;
1603         ts->ksp_its += lits;
1604         PetscCall(TSGetAdapt(ts, &adapt));
1605         PetscCall(TSAdaptCheckStage(adapt, ts, ark->stage_time, Y[i], &stageok));
1606         if (!stageok) {
1607           /* We are likely rejecting the step because of solver or function domain problems so we should not attempt to
1608            * use extrapolation to initialize the solves on the next attempt. */
1609           extrapolate = PETSC_FALSE;
1610           goto reject_step;
1611         }
1612       }
1613       if (dirk || ts->equation_type >= TS_EQ_IMPLICIT) {
1614         if (i == 0 && tab->explicit_first_stage) {
1615           PetscCheck(tab->stiffly_accurate, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "%s %s is not stiffly accurate and therefore explicit-first stage methods cannot be used if the equation is implicit because the slope cannot be evaluated",
1616                      ((PetscObject)ts)->type_name, ark->tableau->name);
1617           PetscCall(VecCopy(Ydot0, YdotI[0])); /* YdotI = YdotI(tn-1) */
1618         } else {
1619           PetscCall(VecAXPBYPCZ(YdotI[i], -ark->scoeff / h, ark->scoeff / h, 0, Z, Y[i])); /* YdotI = shift*(X-Z) */
1620         }
1621       } else {
1622         if (i == 0 && tab->explicit_first_stage) {
1623           PetscCall(VecZeroEntries(Ydot));
1624           PetscCall(TSComputeIFunction(ts, t + h * ct[i], Y[i], Ydot, YdotI[i], ark->imex)); /* YdotI = -G(t,Y,0)   */
1625           PetscCall(VecScale(YdotI[i], -1.0));
1626         } else {
1627           PetscCall(VecAXPBYPCZ(YdotI[i], -ark->scoeff / h, ark->scoeff / h, 0, Z, Y[i])); /* YdotI = shift*(X-Z) */
1628         }
1629         if (hasE) {
1630           if (ark->imex) {
1631             PetscCall(TSComputeRHSFunction(ts, t + h * c[i], Y[i], YdotRHS[i]));
1632           } else {
1633             PetscCall(VecZeroEntries(YdotRHS[i]));
1634           }
1635         }
1636       }
1637       PetscCall(TSPostStage(ts, ark->stage_time, i, Y));
1638     }
1639 
1640     ark->status = TS_STEP_INCOMPLETE;
1641     PetscCall(TSEvaluateStep_ARKIMEX(ts, tab->order, ts->vec_sol, NULL));
1642     ark->status = TS_STEP_PENDING;
1643     PetscCall(TSGetAdapt(ts, &adapt));
1644     PetscCall(TSAdaptCandidatesClear(adapt));
1645     PetscCall(TSAdaptCandidateAdd(adapt, tab->name, tab->order, 1, tab->ccfl, (PetscReal)tab->s, PETSC_TRUE));
1646     PetscCall(TSAdaptChoose(adapt, ts, ts->time_step, NULL, &next_time_step, &accept));
1647     ark->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
1648     if (!accept) { /* Roll back the current step */
1649       PetscCall(TSRollBack_ARKIMEX(ts));
1650       ts->time_step = next_time_step;
1651       goto reject_step;
1652     }
1653 
1654     ts->ptime += ts->time_step;
1655     ts->time_step = next_time_step;
1656     break;
1657 
1658   reject_step:
1659     ts->reject++;
1660     accept = PETSC_FALSE;
1661     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
1662       ts->reason = TS_DIVERGED_STEP_REJECTED;
1663       PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections));
1664     }
1665   }
1666   PetscFunctionReturn(PETSC_SUCCESS);
1667 }
1668 
1669 /*
1670   This adjoint step function assumes the partitioned ODE system has an identity mass matrix and thus can be represented in the form
1671   Udot = H(t,U) + G(t,U)
1672   This corresponds to F(t,U,Udot) = Udot-H(t,U).
1673 
1674   The complete adjoint equations are
1675   (shift*I - dHdu) lambda_s[i]   = 1/at[i][i] (
1676     (b_i dGdU + bt[i] dHdU) lambda_{n+1} + dGdU \sum_{j=i+1}^s a[j][i] lambda_s[j]
1677     + dHdU \sum_{j=i+1}^s at[j][i] lambda_s[j]),  i = s-1,...,0
1678   lambda_n = lambda_{n+1} + \sum_{j=1}^s lambda_s[j]
1679   mu_{n+1}[i]   = h (at[i][i] dHdP lambda_s[i]
1680     + (b_i dGdP + bt[i] dHdP) lambda_{n+1} + dGdP \sum_{j=i+1}^s a[j][i] lambda_s[j]
1681     + dHdP \sum_{j=i+1}^s at[j][i] lambda_s[j]), i = s-1,...,0
1682   mu_n = mu_{n+1} + \sum_{j=1}^s mu_{n+1}[j]
1683   where shift = 1/(at[i][i]*h)
1684 
1685   If at[i][i] is 0, the first equation falls back to
1686   lambda_s[i] = h (
1687     (b_i dGdU + bt[i] dHdU) lambda_{n+1} + dGdU \sum_{j=i+1}^s a[j][i] lambda_s[j]
1688     + dHdU \sum_{j=i+1}^s at[j][i] lambda_s[j])
1689 
1690 */
1691 static PetscErrorCode TSAdjointStep_ARKIMEX(TS ts)
1692 {
1693   TS_ARKIMEX      *ark = (TS_ARKIMEX *)ts->data;
1694   ARKTableau       tab = ark->tableau;
1695   const PetscInt   s   = tab->s;
1696   const PetscReal *At = tab->At, *A = tab->A, *ct = tab->ct, *c = tab->c, *b = tab->b, *bt = tab->bt;
1697   PetscScalar     *w = ark->work;
1698   Vec             *Y = ark->Y, Ydot = ark->Ydot, *VecsDeltaLam = ark->VecsDeltaLam, *VecsSensiTemp = ark->VecsSensiTemp, *VecsSensiPTemp = ark->VecsSensiPTemp;
1699   Mat              Jex, Jim, Jimpre;
1700   PetscInt         i, j, nadj;
1701   PetscReal        t                 = ts->ptime, stage_time_ex;
1702   PetscReal        adjoint_time_step = -ts->time_step; /* always positive since ts->time_step is negative */
1703   KSP              ksp;
1704 
1705   PetscFunctionBegin;
1706   ark->status = TS_STEP_INCOMPLETE;
1707   PetscCall(SNESGetKSP(ts->snes, &ksp));
1708   PetscCall(TSGetRHSMats_Private(ts, &Jex, NULL));
1709   PetscCall(TSGetIJacobian(ts, &Jim, &Jimpre, NULL, NULL));
1710 
1711   for (i = s - 1; i >= 0; i--) {
1712     ark->stage_time = t - adjoint_time_step * (1.0 - ct[i]);
1713     stage_time_ex   = t - adjoint_time_step * (1.0 - c[i]);
1714     if (At[i * s + i] == 0) { // This stage is explicit
1715       ark->scoeff = 0.;
1716     } else {
1717       ark->scoeff = -1. / At[i * s + i]; // this makes shift=ark->scoeff/ts->time_step positive since ts->time_step is negative
1718     }
1719     PetscCall(TSComputeSNESJacobian(ts, Y[i], Jim, Jimpre));
1720     PetscCall(TSComputeRHSJacobian(ts, stage_time_ex, Y[i], Jex, Jex));
1721     if (ts->vecs_sensip) {
1722       PetscCall(TSComputeIJacobianP(ts, ark->stage_time, Y[i], Ydot, ark->scoeff / adjoint_time_step, ts->Jacp, PETSC_TRUE)); // get dFdP (-dHdP), Ydot not really used since mass matrix is identity
1723       PetscCall(TSComputeRHSJacobianP(ts, stage_time_ex, Y[i], ts->Jacprhs));                                                 // get dGdP
1724     }
1725     for (nadj = 0; nadj < ts->numcost; nadj++) {
1726       /* Build RHS (stored in VecsDeltaLam) for first-order adjoint */
1727       if (s - i - 1 > 0) {
1728         /* Temp = -\sum_{j=i+1}^s at[j][i] lambda_s[j] */
1729         for (j = i + 1; j < s; j++) w[j - i - 1] = -At[j * s + i];
1730         PetscCall(VecSet(VecsSensiTemp[nadj], 0));
1731         PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1]));
1732         /* (shift I - dHdU) Temp */
1733         PetscCall(MatMultTranspose(Jim, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i]));
1734         /* cancel out shift Temp where shift=-scoeff/h */
1735         PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], ark->scoeff / adjoint_time_step, VecsSensiTemp[nadj]));
1736         if (ts->vecs_sensip) {
1737           /* - dHdP Temp */
1738           PetscCall(MatMultTranspose(ts->Jacp, VecsSensiTemp[nadj], VecsSensiPTemp[nadj]));
1739           /* mu_n += h dHdP Temp */
1740           PetscCall(VecAXPY(ts->vecs_sensip[nadj], -adjoint_time_step, VecsSensiPTemp[nadj]));
1741         }
1742         /* Temp = \sum_{j=i+1}^s a[j][i] lambda_s[j] */
1743         for (j = i + 1; j < s; j++) w[j - i - 1] = A[j * s + i];
1744         PetscCall(VecSet(VecsSensiTemp[nadj], 0));
1745         PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1]));
1746         /* dGdU Temp */
1747         PetscCall(MatMultTransposeAdd(Jex, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i], VecsDeltaLam[nadj * s + i]));
1748         if (ts->vecs_sensip) {
1749           /* dGdP Temp */
1750           PetscCall(MatMultTranspose(ts->Jacprhs, VecsSensiTemp[nadj], VecsSensiPTemp[nadj]));
1751           /* mu_n += h dGdP Temp */
1752           PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step, VecsSensiPTemp[nadj]));
1753         }
1754       } else {
1755         PetscCall(VecSet(VecsDeltaLam[nadj * s + i], 0)); // make sure it is initialized
1756       }
1757       if (bt[i]) { // bt[i] dHdU lambda_{n+1}
1758         /* (shift I - dHdU)^T lambda_{n+1} */
1759         PetscCall(MatMultTranspose(Jim, ts->vecs_sensi[nadj], VecsSensiTemp[nadj]));
1760         /* -bt[i] (shift I - dHdU)^T lambda_{n+1} */
1761         PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], -bt[i], VecsSensiTemp[nadj]));
1762         /* cancel out -bt[i] shift lambda_{n+1} */
1763         PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], -bt[i] * ark->scoeff / adjoint_time_step, ts->vecs_sensi[nadj]));
1764         if (ts->vecs_sensip) {
1765           /* -dHdP lambda_{n+1} */
1766           PetscCall(MatMultTranspose(ts->Jacp, ts->vecs_sensi[nadj], VecsSensiPTemp[nadj]));
1767           /* mu_n += h bt[i] dHdP lambda_{n+1} */
1768           PetscCall(VecAXPY(ts->vecs_sensip[nadj], -bt[i] * adjoint_time_step, VecsSensiPTemp[nadj]));
1769         }
1770       }
1771       if (b[i]) { // b[i] dGdU lambda_{n+1}
1772         /* dGdU lambda_{n+1} */
1773         PetscCall(MatMultTranspose(Jex, ts->vecs_sensi[nadj], VecsSensiTemp[nadj]));
1774         /* b[i] dGdU lambda_{n+1} */
1775         PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], b[i], VecsSensiTemp[nadj]));
1776         if (ts->vecs_sensip) {
1777           /* dGdP lambda_{n+1} */
1778           PetscCall(MatMultTranspose(ts->Jacprhs, ts->vecs_sensi[nadj], VecsSensiPTemp[nadj]));
1779           /* mu_n += h b[i] dGdP lambda_{n+1} */
1780           PetscCall(VecAXPY(ts->vecs_sensip[nadj], b[i] * adjoint_time_step, VecsSensiPTemp[nadj]));
1781         }
1782       }
1783       /* Build LHS for first-order adjoint */
1784       if (At[i * s + i] == 0) { // This stage is explicit
1785         PetscCall(VecScale(VecsDeltaLam[nadj * s + i], adjoint_time_step));
1786       } else {
1787         KSP                ksp;
1788         KSPConvergedReason kspreason;
1789         PetscCall(SNESGetKSP(ts->snes, &ksp));
1790         PetscCall(KSPSetOperators(ksp, Jim, Jimpre));
1791         PetscCall(VecScale(VecsDeltaLam[nadj * s + i], 1. / At[i * s + i]));
1792         PetscCall(KSPSolveTranspose(ksp, VecsDeltaLam[nadj * s + i], VecsDeltaLam[nadj * s + i]));
1793         PetscCall(KSPGetConvergedReason(ksp, &kspreason));
1794         if (kspreason < 0) {
1795           ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
1796           PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n", ts->steps, nadj));
1797         }
1798         if (ts->vecs_sensip) {
1799           /* -dHdP lambda_s[i] */
1800           PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj * s + i], VecsSensiPTemp[nadj]));
1801           /* mu_n += h at[i][i] dHdP lambda_s[i] */
1802           PetscCall(VecAXPY(ts->vecs_sensip[nadj], -At[i * s + i] * adjoint_time_step, VecsSensiPTemp[nadj]));
1803         }
1804       }
1805     }
1806   }
1807   for (j = 0; j < s; j++) w[j] = 1.0;
1808   for (nadj = 0; nadj < ts->numcost; nadj++) // no need to do this for mu's
1809     PetscCall(VecMAXPY(ts->vecs_sensi[nadj], s, w, &VecsDeltaLam[nadj * s]));
1810   ark->status = TS_STEP_COMPLETE;
1811   PetscFunctionReturn(PETSC_SUCCESS);
1812 }
1813 
1814 static PetscErrorCode TSInterpolate_ARKIMEX(TS ts, PetscReal itime, Vec X)
1815 {
1816   TS_ARKIMEX      *ark = (TS_ARKIMEX *)ts->data;
1817   ARKTableau       tab = ark->tableau;
1818   PetscInt         s = tab->s, pinterp = tab->pinterp, i, j;
1819   PetscReal        h;
1820   PetscReal        tt, t;
1821   PetscScalar     *bt = ark->work, *b = ark->work + s;
1822   const PetscReal *Bt = tab->binterpt, *B = tab->binterp;
1823 
1824   PetscFunctionBegin;
1825   PetscCheck(Bt && B, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "%s %s does not have an interpolation formula", ((PetscObject)ts)->type_name, ark->tableau->name);
1826   switch (ark->status) {
1827   case TS_STEP_INCOMPLETE:
1828   case TS_STEP_PENDING:
1829     h = ts->time_step;
1830     t = (itime - ts->ptime) / h;
1831     break;
1832   case TS_STEP_COMPLETE:
1833     h = ts->ptime - ts->ptime_prev;
1834     t = (itime - ts->ptime) / h + 1; /* In the interval [0,1] */
1835     break;
1836   default:
1837     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus");
1838   }
1839   for (i = 0; i < s; i++) bt[i] = b[i] = 0;
1840   for (j = 0, tt = t; j < pinterp; j++, tt *= t) {
1841     for (i = 0; i < s; i++) {
1842       bt[i] += h * Bt[i * pinterp + j] * tt;
1843       b[i] += h * B[i * pinterp + j] * tt;
1844     }
1845   }
1846   PetscCall(VecCopy(ark->Y[0], X));
1847   PetscCall(VecMAXPY(X, s, bt, ark->YdotI));
1848   if (tab->additive) {
1849     PetscBool hasE;
1850     PetscCall(TSHasRHSFunction(ts, &hasE));
1851     if (hasE) PetscCall(VecMAXPY(X, s, b, ark->YdotRHS));
1852   }
1853   PetscFunctionReturn(PETSC_SUCCESS);
1854 }
1855 
1856 static PetscErrorCode TSExtrapolate_ARKIMEX(TS ts, PetscReal c, Vec X)
1857 {
1858   TS_ARKIMEX      *ark = (TS_ARKIMEX *)ts->data;
1859   ARKTableau       tab = ark->tableau;
1860   PetscInt         s = tab->s, pinterp = tab->pinterp, i, j;
1861   PetscReal        h, h_prev, t, tt;
1862   PetscScalar     *bt = ark->work, *b = ark->work + s;
1863   const PetscReal *Bt = tab->binterpt, *B = tab->binterp;
1864 
1865   PetscFunctionBegin;
1866   PetscCheck(Bt && B, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "TSARKIMEX %s does not have an interpolation formula", ark->tableau->name);
1867   h      = ts->time_step;
1868   h_prev = ts->ptime - ts->ptime_prev;
1869   t      = 1 + h / h_prev * c;
1870   for (i = 0; i < s; i++) bt[i] = b[i] = 0;
1871   for (j = 0, tt = t; j < pinterp; j++, tt *= t) {
1872     for (i = 0; i < s; i++) {
1873       bt[i] += h * Bt[i * pinterp + j] * tt;
1874       b[i] += h * B[i * pinterp + j] * tt;
1875     }
1876   }
1877   PetscCheck(ark->Y_prev, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Stages from previous step have not been stored");
1878   PetscCall(VecCopy(ark->Y_prev[0], X));
1879   PetscCall(VecMAXPY(X, s, bt, ark->YdotI_prev));
1880   if (tab->additive) {
1881     PetscBool hasE;
1882     PetscCall(TSHasRHSFunction(ts, &hasE));
1883     if (hasE) PetscCall(VecMAXPY(X, s, b, ark->YdotRHS_prev));
1884   }
1885   PetscFunctionReturn(PETSC_SUCCESS);
1886 }
1887 
1888 static PetscErrorCode TSARKIMEXTableauReset(TS ts)
1889 {
1890   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1891   ARKTableau  tab = ark->tableau;
1892 
1893   PetscFunctionBegin;
1894   if (!tab) PetscFunctionReturn(PETSC_SUCCESS);
1895   PetscCall(PetscFree(ark->work));
1896   PetscCall(VecDestroyVecs(tab->s, &ark->Y));
1897   PetscCall(VecDestroyVecs(tab->s, &ark->YdotI));
1898   PetscCall(VecDestroyVecs(tab->s, &ark->YdotRHS));
1899   PetscCall(VecDestroyVecs(tab->s, &ark->Y_prev));
1900   PetscCall(VecDestroyVecs(tab->s, &ark->YdotI_prev));
1901   PetscCall(VecDestroyVecs(tab->s, &ark->YdotRHS_prev));
1902   PetscFunctionReturn(PETSC_SUCCESS);
1903 }
1904 
1905 static PetscErrorCode TSReset_ARKIMEX(TS ts)
1906 {
1907   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1908 
1909   PetscFunctionBegin;
1910   PetscCall(TSARKIMEXTableauReset(ts));
1911   PetscCall(VecDestroy(&ark->Ydot));
1912   PetscCall(VecDestroy(&ark->Ydot0));
1913   PetscCall(VecDestroy(&ark->Z));
1914   PetscFunctionReturn(PETSC_SUCCESS);
1915 }
1916 
1917 static PetscErrorCode TSAdjointReset_ARKIMEX(TS ts)
1918 {
1919   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1920   ARKTableau  tab = ark->tableau;
1921 
1922   PetscFunctionBegin;
1923   PetscCall(VecDestroyVecs(tab->s * ts->numcost, &ark->VecsDeltaLam));
1924   PetscCall(VecDestroyVecs(ts->numcost, &ark->VecsSensiTemp));
1925   PetscCall(VecDestroyVecs(ts->numcost, &ark->VecsSensiPTemp));
1926   PetscFunctionReturn(PETSC_SUCCESS);
1927 }
1928 
1929 static PetscErrorCode TSARKIMEXGetVecs(TS ts, DM dm, Vec *Z, Vec *Ydot)
1930 {
1931   TS_ARKIMEX *ax = (TS_ARKIMEX *)ts->data;
1932 
1933   PetscFunctionBegin;
1934   if (Z) {
1935     if (dm && dm != ts->dm) {
1936       PetscCall(DMGetNamedGlobalVector(dm, "TSARKIMEX_Z", Z));
1937     } else *Z = ax->Z;
1938   }
1939   if (Ydot) {
1940     if (dm && dm != ts->dm) {
1941       PetscCall(DMGetNamedGlobalVector(dm, "TSARKIMEX_Ydot", Ydot));
1942     } else *Ydot = ax->Ydot;
1943   }
1944   PetscFunctionReturn(PETSC_SUCCESS);
1945 }
1946 
1947 static PetscErrorCode TSARKIMEXRestoreVecs(TS ts, DM dm, Vec *Z, Vec *Ydot)
1948 {
1949   PetscFunctionBegin;
1950   if (Z) {
1951     if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSARKIMEX_Z", Z));
1952   }
1953   if (Ydot) {
1954     if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSARKIMEX_Ydot", Ydot));
1955   }
1956   PetscFunctionReturn(PETSC_SUCCESS);
1957 }
1958 
1959 /*
1960   This defines the nonlinear equation that is to be solved with SNES
1961   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
1962 */
1963 static PetscErrorCode SNESTSFormFunction_ARKIMEX(SNES snes, Vec X, Vec F, TS ts)
1964 {
1965   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1966   DM          dm, dmsave;
1967   Vec         Z, Ydot;
1968   PetscReal   shift = ark->scoeff / ts->time_step;
1969 
1970   PetscFunctionBegin;
1971   PetscCall(SNESGetDM(snes, &dm));
1972   PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, &Ydot));
1973   dmsave = ts->dm;
1974   ts->dm = dm;
1975 
1976   if (ark->scoeff == 0.0) {
1977     /* We are solving F(t,x_n,xdot) = 0 to start the method */
1978     PetscCall(TSComputeIFunction(ts, ark->stage_time, Z, X, F, ark->imex));
1979   } else {
1980     PetscCall(VecAXPBYPCZ(Ydot, -shift, shift, 0, Z, X)); /* Ydot = shift*(X-Z) */
1981     PetscCall(TSComputeIFunction(ts, ark->stage_time, X, Ydot, F, ark->imex));
1982   }
1983 
1984   ts->dm = dmsave;
1985   PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, &Ydot));
1986   PetscFunctionReturn(PETSC_SUCCESS);
1987 }
1988 
1989 static PetscErrorCode SNESTSFormJacobian_ARKIMEX(SNES snes, Vec X, Mat A, Mat B, TS ts)
1990 {
1991   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
1992   DM          dm, dmsave;
1993   Vec         Ydot, Z;
1994   PetscReal   shift = ark->scoeff / ts->time_step;
1995 
1996   PetscFunctionBegin;
1997   PetscCall(SNESGetDM(snes, &dm));
1998   PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, &Ydot));
1999   /* ark->Ydot has already been computed in SNESTSFormFunction_ARKIMEX (SNES guarantees this) */
2000   dmsave = ts->dm;
2001   ts->dm = dm;
2002 
2003   if (ark->scoeff == 0.0) {
2004     /* We are solving F(t,x_n,xdot) = 0 to start the method, we only only dF/dXdot
2005        Jed's proposal is to compute with a very large shift and scale back the matrix */
2006     shift = 1.0 / PETSC_MACHINE_EPSILON;
2007     PetscCall(TSComputeIJacobian(ts, ark->stage_time, Z, X, shift, A, B, ark->imex));
2008     PetscCall(MatScale(B, PETSC_MACHINE_EPSILON));
2009     if (A != B) PetscCall(MatScale(A, PETSC_MACHINE_EPSILON));
2010   } else {
2011     PetscCall(TSComputeIJacobian(ts, ark->stage_time, X, Ydot, shift, A, B, ark->imex));
2012   }
2013   ts->dm = dmsave;
2014   PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, &Ydot));
2015   PetscFunctionReturn(PETSC_SUCCESS);
2016 }
2017 
2018 static PetscErrorCode TSGetStages_ARKIMEX(TS ts, PetscInt *ns, Vec *Y[])
2019 {
2020   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2021 
2022   PetscFunctionBegin;
2023   if (ns) *ns = ark->tableau->s;
2024   if (Y) *Y = ark->Y;
2025   PetscFunctionReturn(PETSC_SUCCESS);
2026 }
2027 
2028 static PetscErrorCode DMCoarsenHook_TSARKIMEX(DM fine, DM coarse, void *ctx)
2029 {
2030   PetscFunctionBegin;
2031   PetscFunctionReturn(PETSC_SUCCESS);
2032 }
2033 
2034 static PetscErrorCode DMRestrictHook_TSARKIMEX(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx)
2035 {
2036   TS  ts = (TS)ctx;
2037   Vec Z, Z_c;
2038 
2039   PetscFunctionBegin;
2040   PetscCall(TSARKIMEXGetVecs(ts, fine, &Z, NULL));
2041   PetscCall(TSARKIMEXGetVecs(ts, coarse, &Z_c, NULL));
2042   PetscCall(MatRestrict(restrct, Z, Z_c));
2043   PetscCall(VecPointwiseMult(Z_c, rscale, Z_c));
2044   PetscCall(TSARKIMEXRestoreVecs(ts, fine, &Z, NULL));
2045   PetscCall(TSARKIMEXRestoreVecs(ts, coarse, &Z_c, NULL));
2046   PetscFunctionReturn(PETSC_SUCCESS);
2047 }
2048 
2049 static PetscErrorCode DMSubDomainHook_TSARKIMEX(DM dm, DM subdm, void *ctx)
2050 {
2051   PetscFunctionBegin;
2052   PetscFunctionReturn(PETSC_SUCCESS);
2053 }
2054 
2055 static PetscErrorCode DMSubDomainRestrictHook_TSARKIMEX(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx)
2056 {
2057   TS  ts = (TS)ctx;
2058   Vec Z, Z_c;
2059 
2060   PetscFunctionBegin;
2061   PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, NULL));
2062   PetscCall(TSARKIMEXGetVecs(ts, subdm, &Z_c, NULL));
2063 
2064   PetscCall(VecScatterBegin(gscat, Z, Z_c, INSERT_VALUES, SCATTER_FORWARD));
2065   PetscCall(VecScatterEnd(gscat, Z, Z_c, INSERT_VALUES, SCATTER_FORWARD));
2066 
2067   PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, NULL));
2068   PetscCall(TSARKIMEXRestoreVecs(ts, subdm, &Z_c, NULL));
2069   PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 
2072 static PetscErrorCode TSARKIMEXTableauSetUp(TS ts)
2073 {
2074   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2075   ARKTableau  tab = ark->tableau;
2076 
2077   PetscFunctionBegin;
2078   PetscCall(PetscMalloc1(2 * tab->s, &ark->work));
2079   PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y));
2080   PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI));
2081   if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS));
2082   if (ark->extrapolate) {
2083     PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y_prev));
2084     PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI_prev));
2085     if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS_prev));
2086   }
2087   PetscFunctionReturn(PETSC_SUCCESS);
2088 }
2089 
2090 static PetscErrorCode TSSetUp_ARKIMEX(TS ts)
2091 {
2092   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2093   DM          dm;
2094   SNES        snes;
2095 
2096   PetscFunctionBegin;
2097   PetscCall(TSARKIMEXTableauSetUp(ts));
2098   PetscCall(VecDuplicate(ts->vec_sol, &ark->Ydot));
2099   PetscCall(VecDuplicate(ts->vec_sol, &ark->Ydot0));
2100   PetscCall(VecDuplicate(ts->vec_sol, &ark->Z));
2101   PetscCall(TSGetDM(ts, &dm));
2102   PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSARKIMEX, DMRestrictHook_TSARKIMEX, ts));
2103   PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSARKIMEX, DMSubDomainRestrictHook_TSARKIMEX, ts));
2104   PetscCall(TSGetSNES(ts, &snes));
2105   PetscFunctionReturn(PETSC_SUCCESS);
2106 }
2107 
2108 static PetscErrorCode TSAdjointSetUp_ARKIMEX(TS ts)
2109 {
2110   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2111   ARKTableau  tab = ark->tableau;
2112 
2113   PetscFunctionBegin;
2114   PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], tab->s * ts->numcost, &ark->VecsDeltaLam));
2115   PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &ark->VecsSensiTemp));
2116   if (ts->vecs_sensip) { PetscCall(VecDuplicateVecs(ts->vecs_sensip[0], ts->numcost, &ark->VecsSensiPTemp)); }
2117   if (PetscDefined(USE_DEBUG)) {
2118     PetscBool id = PETSC_FALSE;
2119     PetscCall(TSARKIMEXTestMassIdentity(ts, &id));
2120     PetscCheck(id, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_INCOMP, "Adjoint ARKIMEX requires an identity mass matrix, however the TSIFunction you provided does not utilize an identity mass matrix");
2121   }
2122   PetscFunctionReturn(PETSC_SUCCESS);
2123 }
2124 
2125 static PetscErrorCode TSSetFromOptions_ARKIMEX(TS ts, PetscOptionItems *PetscOptionsObject)
2126 {
2127   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2128   PetscBool   dirk;
2129 
2130   PetscFunctionBegin;
2131   PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk));
2132   PetscOptionsHeadBegin(PetscOptionsObject, dirk ? "DIRK ODE solver options" : "ARKIMEX ODE solver options");
2133   {
2134     ARKTableauLink link;
2135     PetscInt       count, choice;
2136     PetscBool      flg;
2137     const char   **namelist;
2138     for (link = ARKTableauList, count = 0; link; link = link->next) {
2139       if (!dirk && link->tab.additive) count++;
2140       if (dirk && !link->tab.additive) count++;
2141     }
2142     PetscCall(PetscMalloc1(count, (char ***)&namelist));
2143     for (link = ARKTableauList, count = 0; link; link = link->next) {
2144       if (!dirk && link->tab.additive) namelist[count++] = link->tab.name;
2145       if (dirk && !link->tab.additive) namelist[count++] = link->tab.name;
2146     }
2147     if (dirk) {
2148       PetscCall(PetscOptionsEList("-ts_dirk_type", "Family of DIRK method", "TSDIRKSetType", (const char *const *)namelist, count, ark->tableau->name, &choice, &flg));
2149       if (flg) PetscCall(TSDIRKSetType(ts, namelist[choice]));
2150     } else {
2151       PetscCall(PetscOptionsEList("-ts_arkimex_type", "Family of ARK IMEX method", "TSARKIMEXSetType", (const char *const *)namelist, count, ark->tableau->name, &choice, &flg));
2152       if (flg) PetscCall(TSARKIMEXSetType(ts, namelist[choice]));
2153       flg = (PetscBool)!ark->imex;
2154       PetscCall(PetscOptionsBool("-ts_arkimex_fully_implicit", "Solve the problem fully implicitly", "TSARKIMEXSetFullyImplicit", flg, &flg, NULL));
2155       ark->imex = (PetscBool)!flg;
2156     }
2157     PetscCall(PetscFree(namelist));
2158     PetscCall(PetscOptionsBool("-ts_arkimex_initial_guess_extrapolate", "Extrapolate the initial guess for the stage solution from stage values of the previous time step", "", ark->extrapolate, &ark->extrapolate, NULL));
2159   }
2160   PetscOptionsHeadEnd();
2161   PetscFunctionReturn(PETSC_SUCCESS);
2162 }
2163 
2164 static PetscErrorCode TSView_ARKIMEX(TS ts, PetscViewer viewer)
2165 {
2166   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2167   PetscBool   iascii, dirk;
2168 
2169   PetscFunctionBegin;
2170   PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk));
2171   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2172   if (iascii) {
2173     PetscViewerFormat format;
2174     ARKTableau        tab = ark->tableau;
2175     TSARKIMEXType     arktype;
2176     char              buf[2048];
2177     PetscBool         flg;
2178 
2179     PetscCall(TSARKIMEXGetType(ts, &arktype));
2180     PetscCall(TSARKIMEXGetFullyImplicit(ts, &flg));
2181     PetscCall(PetscViewerASCIIPrintf(viewer, "  %s %s\n", dirk ? "DIRK" : "ARK IMEX", arktype));
2182     PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->ct));
2183     PetscCall(PetscViewerASCIIPrintf(viewer, "  %sabscissa       ct = %s\n", dirk ? "" : "Stiff ", buf));
2184     PetscCall(PetscViewerGetFormat(viewer, &format));
2185     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2186       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sAt =\n", dirk ? "" : "Stiff "));
2187       for (PetscInt i = 0; i < tab->s; i++) {
2188         PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->At + i * tab->s));
2189         PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", buf));
2190       }
2191       PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->bt));
2192       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sbt = %s\n", dirk ? "" : "Stiff ", buf));
2193       PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->bembedt));
2194       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sbet = %s\n", dirk ? "" : "Stiff ", buf));
2195     }
2196     PetscCall(PetscViewerASCIIPrintf(viewer, "Fully implicit: %s\n", flg ? "yes" : "no"));
2197     PetscCall(PetscViewerASCIIPrintf(viewer, "Stiffly accurate: %s\n", tab->stiffly_accurate ? "yes" : "no"));
2198     PetscCall(PetscViewerASCIIPrintf(viewer, "Explicit first stage: %s\n", tab->explicit_first_stage ? "yes" : "no"));
2199     PetscCall(PetscViewerASCIIPrintf(viewer, "FSAL property: %s\n", tab->FSAL_implicit ? "yes" : "no"));
2200     if (!dirk) {
2201       PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->c));
2202       PetscCall(PetscViewerASCIIPrintf(viewer, "  Nonstiff abscissa     c = %s\n", buf));
2203     }
2204   }
2205   PetscFunctionReturn(PETSC_SUCCESS);
2206 }
2207 
2208 static PetscErrorCode TSLoad_ARKIMEX(TS ts, PetscViewer viewer)
2209 {
2210   SNES    snes;
2211   TSAdapt adapt;
2212 
2213   PetscFunctionBegin;
2214   PetscCall(TSGetAdapt(ts, &adapt));
2215   PetscCall(TSAdaptLoad(adapt, viewer));
2216   PetscCall(TSGetSNES(ts, &snes));
2217   PetscCall(SNESLoad(snes, viewer));
2218   /* function and Jacobian context for SNES when used with TS is always ts object */
2219   PetscCall(SNESSetFunction(snes, NULL, NULL, ts));
2220   PetscCall(SNESSetJacobian(snes, NULL, NULL, NULL, ts));
2221   PetscFunctionReturn(PETSC_SUCCESS);
2222 }
2223 
2224 /*@C
2225   TSARKIMEXSetType - Set the type of `TSARKIMEX` scheme
2226 
2227   Logically Collective
2228 
2229   Input Parameters:
2230 + ts      - timestepping context
2231 - arktype - type of `TSARKIMEX` scheme
2232 
2233   Options Database Key:
2234 . -ts_arkimex_type <1bee,a2,l2,ars122,2c,2d,2e,prssp2,3,bpr3,ars443,4,5> - set `TSARKIMEX` scheme type
2235 
2236   Level: intermediate
2237 
2238 .seealso: [](ch_ts), `TSARKIMEXGetType()`, `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEX1BEE`, `TSARKIMEXA2`, `TSARKIMEXL2`, `TSARKIMEXARS122`, `TSARKIMEX2C`, `TSARKIMEX2D`, `TSARKIMEX2E`, `TSARKIMEXPRSSP2`,
2239           `TSARKIMEX3`, `TSARKIMEXBPR3`, `TSARKIMEXARS443`, `TSARKIMEX4`, `TSARKIMEX5`
2240 @*/
2241 PetscErrorCode TSARKIMEXSetType(TS ts, TSARKIMEXType arktype)
2242 {
2243   PetscFunctionBegin;
2244   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2245   PetscAssertPointer(arktype, 2);
2246   PetscTryMethod(ts, "TSARKIMEXSetType_C", (TS, TSARKIMEXType), (ts, arktype));
2247   PetscFunctionReturn(PETSC_SUCCESS);
2248 }
2249 
2250 /*@C
2251   TSARKIMEXGetType - Get the type of `TSARKIMEX` scheme
2252 
2253   Logically Collective
2254 
2255   Input Parameter:
2256 . ts - timestepping context
2257 
2258   Output Parameter:
2259 . arktype - type of `TSARKIMEX` scheme
2260 
2261   Level: intermediate
2262 
2263 .seealso: [](ch_ts), `TSARKIMEXc`
2264 @*/
2265 PetscErrorCode TSARKIMEXGetType(TS ts, TSARKIMEXType *arktype)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2269   PetscUseMethod(ts, "TSARKIMEXGetType_C", (TS, TSARKIMEXType *), (ts, arktype));
2270   PetscFunctionReturn(PETSC_SUCCESS);
2271 }
2272 
2273 /*@
2274   TSARKIMEXSetFullyImplicit - Solve both parts of the equation implicitly, including the part that is normally solved explicitly
2275 
2276   Logically Collective
2277 
2278   Input Parameters:
2279 + ts  - timestepping context
2280 - flg - `PETSC_TRUE` for fully implicit
2281 
2282   Level: intermediate
2283 
2284 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXGetType()`, `TSARKIMEXGetFullyImplicit()`
2285 @*/
2286 PetscErrorCode TSARKIMEXSetFullyImplicit(TS ts, PetscBool flg)
2287 {
2288   PetscFunctionBegin;
2289   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2290   PetscValidLogicalCollectiveBool(ts, flg, 2);
2291   PetscTryMethod(ts, "TSARKIMEXSetFullyImplicit_C", (TS, PetscBool), (ts, flg));
2292   PetscFunctionReturn(PETSC_SUCCESS);
2293 }
2294 
2295 /*@
2296   TSARKIMEXGetFullyImplicit - Inquires if both parts of the equation are solved implicitly
2297 
2298   Logically Collective
2299 
2300   Input Parameter:
2301 . ts - timestepping context
2302 
2303   Output Parameter:
2304 . flg - `PETSC_TRUE` for fully implicit
2305 
2306   Level: intermediate
2307 
2308 .seealso: [](ch_ts), `TSARKIMEXGetType()`, `TSARKIMEXSetFullyImplicit()`
2309 @*/
2310 PetscErrorCode TSARKIMEXGetFullyImplicit(TS ts, PetscBool *flg)
2311 {
2312   PetscFunctionBegin;
2313   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2314   PetscAssertPointer(flg, 2);
2315   PetscUseMethod(ts, "TSARKIMEXGetFullyImplicit_C", (TS, PetscBool *), (ts, flg));
2316   PetscFunctionReturn(PETSC_SUCCESS);
2317 }
2318 
2319 static PetscErrorCode TSARKIMEXGetType_ARKIMEX(TS ts, TSARKIMEXType *arktype)
2320 {
2321   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2322 
2323   PetscFunctionBegin;
2324   *arktype = ark->tableau->name;
2325   PetscFunctionReturn(PETSC_SUCCESS);
2326 }
2327 
2328 static PetscErrorCode TSARKIMEXSetType_ARKIMEX(TS ts, TSARKIMEXType arktype)
2329 {
2330   TS_ARKIMEX    *ark = (TS_ARKIMEX *)ts->data;
2331   PetscBool      match;
2332   ARKTableauLink link;
2333 
2334   PetscFunctionBegin;
2335   if (ark->tableau) {
2336     PetscCall(PetscStrcmp(ark->tableau->name, arktype, &match));
2337     if (match) PetscFunctionReturn(PETSC_SUCCESS);
2338   }
2339   for (link = ARKTableauList; link; link = link->next) {
2340     PetscCall(PetscStrcmp(link->tab.name, arktype, &match));
2341     if (match) {
2342       if (ts->setupcalled) PetscCall(TSARKIMEXTableauReset(ts));
2343       ark->tableau = &link->tab;
2344       if (ts->setupcalled) PetscCall(TSARKIMEXTableauSetUp(ts));
2345       ts->default_adapt_type = ark->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE;
2346       PetscFunctionReturn(PETSC_SUCCESS);
2347     }
2348   }
2349   SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Could not find '%s'", arktype);
2350 }
2351 
2352 static PetscErrorCode TSARKIMEXSetFullyImplicit_ARKIMEX(TS ts, PetscBool flg)
2353 {
2354   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2355 
2356   PetscFunctionBegin;
2357   ark->imex = (PetscBool)!flg;
2358   PetscFunctionReturn(PETSC_SUCCESS);
2359 }
2360 
2361 static PetscErrorCode TSARKIMEXGetFullyImplicit_ARKIMEX(TS ts, PetscBool *flg)
2362 {
2363   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2364 
2365   PetscFunctionBegin;
2366   *flg = (PetscBool)!ark->imex;
2367   PetscFunctionReturn(PETSC_SUCCESS);
2368 }
2369 
2370 static PetscErrorCode TSDestroy_ARKIMEX(TS ts)
2371 {
2372   PetscFunctionBegin;
2373   PetscCall(TSReset_ARKIMEX(ts));
2374   if (ts->dm) {
2375     PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSARKIMEX, DMRestrictHook_TSARKIMEX, ts));
2376     PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSARKIMEX, DMSubDomainRestrictHook_TSARKIMEX, ts));
2377   }
2378   PetscCall(PetscFree(ts->data));
2379   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKGetType_C", NULL));
2380   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKSetType_C", NULL));
2381   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetType_C", NULL));
2382   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetType_C", NULL));
2383   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetFullyImplicit_C", NULL));
2384   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetFullyImplicit_C", NULL));
2385   PetscFunctionReturn(PETSC_SUCCESS);
2386 }
2387 
2388 /* ------------------------------------------------------------ */
2389 /*MC
2390       TSARKIMEX - ODE and DAE solver using additive Runge-Kutta IMEX schemes
2391 
2392   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly
2393   nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part
2394   of the equation using `TSSetIFunction()` and the non-stiff part with `TSSetRHSFunction()`.
2395 
2396   Level: beginner
2397 
2398   Notes:
2399   The default is `TSARKIMEX3`, it can be changed with `TSARKIMEXSetType()` or -ts_arkimex_type
2400 
2401   If the equation is implicit or a DAE, then `TSSetEquationType()` needs to be set accordingly. Refer to the manual for further information.
2402 
2403   Methods with an explicit stage can only be used with ODE in which the stiff part G(t,X,Xdot) has the form Xdot + Ghat(t,X).
2404 
2405   Consider trying `TSROSW` if the stiff part is linear or weakly nonlinear.
2406 
2407 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSARKIMEXSetType()`, `TSARKIMEXGetType()`, `TSARKIMEXSetFullyImplicit()`, `TSARKIMEXGetFullyImplicit()`,
2408           `TSARKIMEX1BEE`, `TSARKIMEX2C`, `TSARKIMEX2D`, `TSARKIMEX2E`, `TSARKIMEX3`, `TSARKIMEXL2`, `TSARKIMEXA2`, `TSARKIMEXARS122`,
2409           `TSARKIMEX4`, `TSARKIMEX5`, `TSARKIMEXPRSSP2`, `TSARKIMEXARS443`, `TSARKIMEXBPR3`, `TSARKIMEXType`, `TSARKIMEXRegister()`, `TSType`
2410 M*/
2411 PETSC_EXTERN PetscErrorCode TSCreate_ARKIMEX(TS ts)
2412 {
2413   TS_ARKIMEX *ark;
2414   PetscBool   dirk;
2415 
2416   PetscFunctionBegin;
2417   PetscCall(TSARKIMEXInitializePackage());
2418   PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk));
2419 
2420   ts->ops->reset          = TSReset_ARKIMEX;
2421   ts->ops->adjointreset   = TSAdjointReset_ARKIMEX;
2422   ts->ops->destroy        = TSDestroy_ARKIMEX;
2423   ts->ops->view           = TSView_ARKIMEX;
2424   ts->ops->load           = TSLoad_ARKIMEX;
2425   ts->ops->setup          = TSSetUp_ARKIMEX;
2426   ts->ops->adjointsetup   = TSAdjointSetUp_ARKIMEX;
2427   ts->ops->step           = TSStep_ARKIMEX;
2428   ts->ops->interpolate    = TSInterpolate_ARKIMEX;
2429   ts->ops->evaluatestep   = TSEvaluateStep_ARKIMEX;
2430   ts->ops->rollback       = TSRollBack_ARKIMEX;
2431   ts->ops->setfromoptions = TSSetFromOptions_ARKIMEX;
2432   ts->ops->snesfunction   = SNESTSFormFunction_ARKIMEX;
2433   ts->ops->snesjacobian   = SNESTSFormJacobian_ARKIMEX;
2434   ts->ops->getstages      = TSGetStages_ARKIMEX;
2435   ts->ops->adjointstep    = TSAdjointStep_ARKIMEX;
2436 
2437   ts->usessnes = PETSC_TRUE;
2438 
2439   PetscCall(PetscNew(&ark));
2440   ts->data  = (void *)ark;
2441   ark->imex = dirk ? PETSC_FALSE : PETSC_TRUE;
2442 
2443   ark->VecsDeltaLam   = NULL;
2444   ark->VecsSensiTemp  = NULL;
2445   ark->VecsSensiPTemp = NULL;
2446 
2447   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetType_C", TSARKIMEXGetType_ARKIMEX));
2448   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetFullyImplicit_C", TSARKIMEXGetFullyImplicit_ARKIMEX));
2449   if (!dirk) {
2450     PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetType_C", TSARKIMEXSetType_ARKIMEX));
2451     PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetFullyImplicit_C", TSARKIMEXSetFullyImplicit_ARKIMEX));
2452     PetscCall(TSARKIMEXSetType(ts, TSARKIMEXDefault));
2453   }
2454   PetscFunctionReturn(PETSC_SUCCESS);
2455 }
2456 
2457 /* ------------------------------------------------------------ */
2458 
2459 static PetscErrorCode TSDIRKSetType_DIRK(TS ts, TSDIRKType dirktype)
2460 {
2461   TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data;
2462 
2463   PetscFunctionBegin;
2464   PetscCall(TSARKIMEXSetType_ARKIMEX(ts, dirktype));
2465   PetscCheck(!ark->tableau->additive, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Method \"%s\" is not DIRK", dirktype);
2466   PetscFunctionReturn(PETSC_SUCCESS);
2467 }
2468 
2469 /*@C
2470   TSDIRKSetType - Set the type of `TSDIRK` scheme
2471 
2472   Logically Collective
2473 
2474   Input Parameters:
2475 + ts       - timestepping context
2476 - dirktype - type of `TSDIRK` scheme
2477 
2478   Options Database Key:
2479 . -ts_dirkimex_type - set `TSDIRK` scheme type
2480 
2481   Level: intermediate
2482 
2483 .seealso: [](ch_ts), `TSDIRKGetType()`, `TSDIRK`, `TSDIRKType`
2484 @*/
2485 PetscErrorCode TSDIRKSetType(TS ts, TSDIRKType dirktype)
2486 {
2487   PetscFunctionBegin;
2488   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2489   PetscAssertPointer(dirktype, 2);
2490   PetscTryMethod(ts, "TSDIRKSetType_C", (TS, TSDIRKType), (ts, dirktype));
2491   PetscFunctionReturn(PETSC_SUCCESS);
2492 }
2493 
2494 /*@C
2495   TSDIRKGetType - Get the type of `TSDIRK` scheme
2496 
2497   Logically Collective
2498 
2499   Input Parameter:
2500 . ts - timestepping context
2501 
2502   Output Parameter:
2503 . dirktype - type of `TSDIRK` scheme
2504 
2505   Level: intermediate
2506 
2507 .seealso: [](ch_ts), `TSDIRKSetType()`
2508 @*/
2509 PetscErrorCode TSDIRKGetType(TS ts, TSDIRKType *dirktype)
2510 {
2511   PetscFunctionBegin;
2512   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2513   PetscUseMethod(ts, "TSDIRKGetType_C", (TS, TSDIRKType *), (ts, dirktype));
2514   PetscFunctionReturn(PETSC_SUCCESS);
2515 }
2516 
2517 /*MC
2518       TSDIRK - ODE and DAE solver using Diagonally implicit Runge-Kutta schemes.
2519 
2520   Level: beginner
2521 
2522   Notes:
2523   The default is `TSDIRKES213SAL`, it can be changed with `TSDIRKSetType()` or -ts_dirk_type.
2524   The convention used in PETSc to name the DIRK methods is TSDIRK[E][S]PQS[SA][L][A] with:
2525 + E - whether the method has an explicit first stage
2526 . S - whether the method is single diagonal
2527 . P - order of the advancing method
2528 . Q - order of the embedded method
2529 . S - number of stages
2530 . SA - whether the method is stiffly accurate
2531 . L - whether the method is L-stable
2532 - A - whether the method is A-stable
2533 
2534 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSDIRKSetType()`, `TSDIRKGetType()`, `TSDIRKRegister()`.
2535 M*/
2536 PETSC_EXTERN PetscErrorCode TSCreate_DIRK(TS ts)
2537 {
2538   PetscFunctionBegin;
2539   PetscCall(TSCreate_ARKIMEX(ts));
2540   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKGetType_C", TSARKIMEXGetType_ARKIMEX));
2541   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKSetType_C", TSDIRKSetType_DIRK));
2542   PetscCall(TSDIRKSetType(ts, TSDIRKDefault));
2543   PetscFunctionReturn(PETSC_SUCCESS);
2544 }
2545