xref: /petsc/src/ts/impls/arkimex/arkimex.c (revision a17b68dadd7775c9b244fee4bcdfe4f41260b71e)
18a381b04SJed Brown /*
28a381b04SJed Brown   Code for timestepping with additive Runge-Kutta IMEX method
38a381b04SJed Brown 
48a381b04SJed Brown   Notes:
58a381b04SJed Brown   The general system is written as
68a381b04SJed Brown 
78a381b04SJed Brown   F(t,X,Xdot) = G(t,X)
88a381b04SJed Brown 
98a381b04SJed Brown   where F represents the stiff part of the physics and G represents the non-stiff part.
108a381b04SJed Brown 
118a381b04SJed Brown */
128a381b04SJed Brown #include <private/tsimpl.h>                /*I   "petscts.h"   I*/
138a381b04SJed Brown 
148a381b04SJed Brown static const TSARKIMEXType TSARKIMEXDefault = TSARKIMEX2D;
158a381b04SJed Brown static PetscBool TSARKIMEXRegisterAllCalled;
168a381b04SJed Brown static PetscBool TSARKIMEXPackageInitialized;
178a381b04SJed Brown 
188a381b04SJed Brown typedef struct _ARKTableau *ARKTableau;
198a381b04SJed Brown struct _ARKTableau {
208a381b04SJed Brown   char *name;
218a381b04SJed Brown   PetscInt order;
228a381b04SJed Brown   PetscInt s;
238a381b04SJed Brown   PetscReal *At,*bt,*ct;
248a381b04SJed Brown   PetscReal *A,*b,*c;           /* Non-stiff tableau */
258a381b04SJed Brown };
268a381b04SJed Brown typedef struct _ARKTableauLink *ARKTableauLink;
278a381b04SJed Brown struct _ARKTableauLink {
288a381b04SJed Brown   struct _ARKTableau tab;
298a381b04SJed Brown   ARKTableauLink next;
308a381b04SJed Brown };
318a381b04SJed Brown static ARKTableauLink ARKTableauList;
328a381b04SJed Brown 
338a381b04SJed Brown typedef struct {
348a381b04SJed Brown   ARKTableau  tableau;
358a381b04SJed Brown   Vec         *Y;               /* States computed during the step */
368a381b04SJed Brown   Vec         *YdotI;           /* Time derivatives for the stiff part */
378a381b04SJed Brown   Vec         *YdotRHS;         /* Function evaluations for the non-stiff part */
388a381b04SJed Brown   Vec         Ydot;             /* Work vector holding Ydot during residual evaluation */
398a381b04SJed Brown   Vec         Work;             /* Generic work vector */
408a381b04SJed Brown   Vec         Z;                /* Ydot = shift(Y-Z) */
418a381b04SJed Brown   PetscScalar *work;            /* Scalar work */
428a381b04SJed Brown   PetscReal   shift;
438a381b04SJed Brown   PetscReal   stage_time;
448a381b04SJed Brown } TS_ARKIMEX;
458a381b04SJed Brown 
468a381b04SJed Brown #undef __FUNCT__
478a381b04SJed Brown #define __FUNCT__ "TSARKIMEXRegisterAll"
488a381b04SJed Brown /*@C
498a381b04SJed Brown   TSARKIMEXRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in TSARKIMEX
508a381b04SJed Brown 
518a381b04SJed Brown   Not Collective
528a381b04SJed Brown 
538a381b04SJed Brown   Level: advanced
548a381b04SJed Brown 
558a381b04SJed Brown .keywords: TS, TSARKIMEX, register, all
568a381b04SJed Brown 
578a381b04SJed Brown .seealso:  TSARKIMEXRegisterDestroy()
588a381b04SJed Brown @*/
598a381b04SJed Brown PetscErrorCode TSARKIMEXRegisterAll(void)
608a381b04SJed Brown {
618a381b04SJed Brown   PetscErrorCode ierr;
628a381b04SJed Brown 
638a381b04SJed Brown   PetscFunctionBegin;
648a381b04SJed Brown   if (TSARKIMEXRegisterAllCalled) PetscFunctionReturn(0);
658a381b04SJed Brown   TSARKIMEXRegisterAllCalled = PETSC_TRUE;
668a381b04SJed Brown 
678a381b04SJed Brown   {
688a381b04SJed Brown     const PetscReal
698a381b04SJed Brown       A[3][3] = {{0,0,0},
708a381b04SJed Brown                  {0.41421356237309504880,0,0},
718a381b04SJed Brown                  {0.75,0.25,0}},
728a381b04SJed Brown       At[3][3] = {{0,0,0},
738a381b04SJed Brown                   {0.12132034355964257320,0.29289321881345247560,0},
748a381b04SJed Brown                   {0.20710678118654752440,0.50000000000000000000,0.29289321881345247560}};
758a381b04SJed Brown       ierr = TSARKIMEXRegister(TSARKIMEX2D,2,3,&At[0][0],PETSC_NULL,PETSC_NULL,&A[0][0],PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
768a381b04SJed Brown   }
778a381b04SJed Brown   PetscFunctionReturn(0);
788a381b04SJed Brown }
798a381b04SJed Brown 
808a381b04SJed Brown #undef __FUNCT__
818a381b04SJed Brown #define __FUNCT__ "TSARKIMEXRegisterDestroy"
828a381b04SJed Brown /*@C
838a381b04SJed Brown    TSARKIMEXRegisterDestroy - Frees the list of schemes that were registered by TSARKIMEXRegister().
848a381b04SJed Brown 
858a381b04SJed Brown    Not Collective
868a381b04SJed Brown 
878a381b04SJed Brown    Level: advanced
888a381b04SJed Brown 
898a381b04SJed Brown .keywords: TSARKIMEX, register, destroy
908a381b04SJed Brown .seealso: TSARKIMEXRegister(), TSARKIMEXRegisterAll(), TSARKIMEXRegisterDynamic()
918a381b04SJed Brown @*/
928a381b04SJed Brown PetscErrorCode TSARKIMEXRegisterDestroy(void)
938a381b04SJed Brown {
948a381b04SJed Brown   PetscErrorCode ierr;
958a381b04SJed Brown   ARKTableauLink link;
968a381b04SJed Brown 
978a381b04SJed Brown   PetscFunctionBegin;
988a381b04SJed Brown   while ((link = ARKTableauList)) {
998a381b04SJed Brown     ARKTableau t = &link->tab;
1008a381b04SJed Brown     ARKTableauList = link->next;
1018a381b04SJed Brown     ierr = PetscFree6(t->At,t->bt,t->ct,t->A,t->b,t->c);CHKERRQ(ierr);
1028a381b04SJed Brown     ierr = PetscFree(t->name);CHKERRQ(ierr);
1038a381b04SJed Brown     ierr = PetscFree(link);CHKERRQ(ierr);
1048a381b04SJed Brown   }
1058a381b04SJed Brown   TSARKIMEXRegisterAllCalled = PETSC_FALSE;
1068a381b04SJed Brown   PetscFunctionReturn(0);
1078a381b04SJed Brown }
1088a381b04SJed Brown 
1098a381b04SJed Brown #undef __FUNCT__
1108a381b04SJed Brown #define __FUNCT__ "TSARKIMEXInitializePackage"
1118a381b04SJed Brown /*@C
1128a381b04SJed Brown   TSARKIMEXInitializePackage - This function initializes everything in the TSARKIMEX package. It is called
1138a381b04SJed Brown   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_ARKIMEX()
1148a381b04SJed Brown   when using static libraries.
1158a381b04SJed Brown 
1168a381b04SJed Brown   Input Parameter:
1178a381b04SJed Brown   path - The dynamic library path, or PETSC_NULL
1188a381b04SJed Brown 
1198a381b04SJed Brown   Level: developer
1208a381b04SJed Brown 
1218a381b04SJed Brown .keywords: TS, TSARKIMEX, initialize, package
1228a381b04SJed Brown .seealso: PetscInitialize()
1238a381b04SJed Brown @*/
1248a381b04SJed Brown PetscErrorCode TSARKIMEXInitializePackage(const char path[])
1258a381b04SJed Brown {
1268a381b04SJed Brown   PetscErrorCode ierr;
1278a381b04SJed Brown 
1288a381b04SJed Brown   PetscFunctionBegin;
1298a381b04SJed Brown   if (TSARKIMEXPackageInitialized) PetscFunctionReturn(0);
1308a381b04SJed Brown   TSARKIMEXPackageInitialized = PETSC_TRUE;
1318a381b04SJed Brown   ierr = TSARKIMEXRegisterAll();CHKERRQ(ierr);
1328a381b04SJed Brown   ierr = PetscRegisterFinalize(TSARKIMEXFinalizePackage);CHKERRQ(ierr);
1338a381b04SJed Brown   PetscFunctionReturn(0);
1348a381b04SJed Brown }
1358a381b04SJed Brown 
1368a381b04SJed Brown #undef __FUNCT__
1378a381b04SJed Brown #define __FUNCT__ "TSARKIMEXFinalizePackage"
1388a381b04SJed Brown /*@C
1398a381b04SJed Brown   TSARKIMEXFinalizePackage - This function destroys everything in the TSARKIMEX package. It is
1408a381b04SJed Brown   called from PetscFinalize().
1418a381b04SJed Brown 
1428a381b04SJed Brown   Level: developer
1438a381b04SJed Brown 
1448a381b04SJed Brown .keywords: Petsc, destroy, package
1458a381b04SJed Brown .seealso: PetscFinalize()
1468a381b04SJed Brown @*/
1478a381b04SJed Brown PetscErrorCode TSARKIMEXFinalizePackage(void)
1488a381b04SJed Brown {
1498a381b04SJed Brown   PetscErrorCode ierr;
1508a381b04SJed Brown 
1518a381b04SJed Brown   PetscFunctionBegin;
1528a381b04SJed Brown   TSARKIMEXPackageInitialized = PETSC_FALSE;
1538a381b04SJed Brown   ierr = TSARKIMEXRegisterDestroy();CHKERRQ(ierr);
1548a381b04SJed Brown   PetscFunctionReturn(0);
1558a381b04SJed Brown }
1568a381b04SJed Brown 
1578a381b04SJed Brown #undef __FUNCT__
1588a381b04SJed Brown #define __FUNCT__ "TSARKIMEXRegister"
1598a381b04SJed Brown PetscErrorCode TSARKIMEXRegister(const TSARKIMEXType name,PetscInt order,PetscInt s,
1608a381b04SJed Brown                                  const PetscReal At[],const PetscReal bt[],const PetscReal ct[],
1618a381b04SJed Brown                                  const PetscReal A[],const PetscReal b[],const PetscReal c[])
1628a381b04SJed Brown {
1638a381b04SJed Brown   PetscErrorCode ierr;
1648a381b04SJed Brown   ARKTableauLink link;
1658a381b04SJed Brown   ARKTableau t;
1668a381b04SJed Brown   PetscInt i,j;
1678a381b04SJed Brown 
1688a381b04SJed Brown   PetscFunctionBegin;
1698a381b04SJed Brown   ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr);
1708a381b04SJed Brown   t = &link->tab;
1718a381b04SJed Brown   ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
1728a381b04SJed Brown   t->order = order;
1738a381b04SJed Brown   t->s = s;
1748a381b04SJed Brown   ierr = PetscMalloc6(s*s,PetscReal,&t->At,s,PetscReal,&t->bt,s,PetscReal,&t->ct,s*s,PetscReal,&t->A,s,PetscReal,&t->b,s,PetscReal,&t->c);CHKERRQ(ierr);
1758a381b04SJed Brown   ierr = PetscMemcpy(t->At,At,s*s*sizeof(At[0]));CHKERRQ(ierr);
1768a381b04SJed Brown   ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
1778a381b04SJed Brown   if (bt) {ierr = PetscMemcpy(t->bt,bt,s*sizeof(bt[0]));CHKERRQ(ierr);}
1788a381b04SJed Brown   else for (i=0; i<s; i++) t->bt[i] = At[(s-1)*s+i];
1798a381b04SJed Brown   if (b) {ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr);}
1808a381b04SJed Brown   else for (i=0; i<s; i++) t->b[i] = At[(s-1)*s+i];
1818a381b04SJed Brown   if (ct) {ierr = PetscMemcpy(t->ct,ct,s*sizeof(ct[0]));CHKERRQ(ierr);}
1828a381b04SJed Brown   else for (i=0; i<s; i++) for (j=0,t->ct[i]=0; j<s; j++) t->ct[i] += At[i*s+j];
1838a381b04SJed Brown   if (c) {ierr = PetscMemcpy(t->c,c,s*sizeof(c[0]));CHKERRQ(ierr);}
1848a381b04SJed Brown   else for (i=0; i<s; i++) for (j=0,t->c[i]=0; j<s; j++) t->c[i] += A[i*s+j];
1858a381b04SJed Brown   link->next = ARKTableauList;
1868a381b04SJed Brown   ARKTableauList = link;
1878a381b04SJed Brown   PetscFunctionReturn(0);
1888a381b04SJed Brown }
1898a381b04SJed Brown 
1908a381b04SJed Brown #undef __FUNCT__
1918a381b04SJed Brown #define __FUNCT__ "TSStep_ARKIMEX"
1928a381b04SJed Brown static PetscErrorCode TSStep_ARKIMEX(TS ts)
1938a381b04SJed Brown {
1948a381b04SJed Brown   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
1958a381b04SJed Brown   ARKTableau      tab  = ark->tableau;
1968a381b04SJed Brown   const PetscInt  s    = tab->s;
1978a381b04SJed Brown   const PetscReal *At  = tab->At,*A = tab->A,*bt = tab->bt,*b = tab->b,*ct = tab->ct,*c = tab->c;
1988a381b04SJed Brown   PetscReal       *w   = ark->work;
1998a381b04SJed Brown   Vec             *Y   = ark->Y,*YdotI = ark->YdotI,*YdotRHS = ark->YdotRHS,Ydot = ark->Ydot,W = ark->Work,Z = ark->Z;
2008a381b04SJed Brown   SNES            snes;
2018a381b04SJed Brown   PetscInt        i,j,its,lits;
2028a381b04SJed Brown   PetscReal       h,t;
2038a381b04SJed Brown   PetscErrorCode  ierr;
2048a381b04SJed Brown 
2058a381b04SJed Brown   PetscFunctionBegin;
2068a381b04SJed Brown   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2078a381b04SJed Brown   h = ts->time_step = ts->next_time_step;
2088a381b04SJed Brown   t = ts->ptime;
2098a381b04SJed Brown 
2108a381b04SJed Brown   for (i=0; i<s; i++) {
2118a381b04SJed Brown     if (At[i*s+i] == 0) {           /* This stage is explicit */
2128a381b04SJed Brown       ierr = VecCopy(ts->vec_sol,Y[i]);CHKERRQ(ierr);
2138a381b04SJed Brown       for (j=0; j<i; j++) w[j] = -h*At[i*s+j];
2148a381b04SJed Brown       ierr = VecMAXPY(Y[i],i,w,YdotI);CHKERRQ(ierr);
2158a381b04SJed Brown       for (j=0; j<i; j++) w[j] = h*A[i*s+j];
2168a381b04SJed Brown       ierr = VecMAXPY(Y[i],i,w,YdotRHS);CHKERRQ(ierr);
2178a381b04SJed Brown     } else {
2188a381b04SJed Brown       ark->stage_time = t + h*ct[i];
2198a381b04SJed Brown       ark->shift = 1./(h*At[i*s+i]);
2208a381b04SJed Brown       /* Affine part */
2218a381b04SJed Brown       ierr = VecZeroEntries(W);CHKERRQ(ierr);
2228a381b04SJed Brown       for (j=0; j<i; j++) w[j] = h*A[i*s+j];
2238a381b04SJed Brown       ierr = VecMAXPY(W,i,w,YdotRHS);CHKERRQ(ierr);
2248a381b04SJed Brown       /* Ydot = shift*(Y-Z) */
2258a381b04SJed Brown       ierr = VecCopy(ts->vec_sol,Z);CHKERRQ(ierr);
2268a381b04SJed Brown       for (j=0; j<i; j++) w[j] = h*At[i*s+j];
2278a381b04SJed Brown       ierr = VecMAXPY(Z,i,w,YdotRHS);CHKERRQ(ierr);
2288a381b04SJed Brown       /* Initial guess taken from last stage */
2298a381b04SJed Brown       ierr = VecCopy(i>0?Y[i-1]:ts->vec_sol,Y[i]);CHKERRQ(ierr);
2308a381b04SJed Brown       ierr = SNESSolve(snes,W,Y[i]);CHKERRQ(ierr);
2318a381b04SJed Brown       ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
2328a381b04SJed Brown       ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
2338a381b04SJed Brown       ts->nonlinear_its += its; ts->linear_its += lits;
2348a381b04SJed Brown     }
2358a381b04SJed Brown     ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);
2368a381b04SJed Brown     ierr = TSComputeIFunction(ts,t+h*ct[i],Y[i],Ydot,YdotI[i],PETSC_TRUE);CHKERRQ(ierr);
2378a381b04SJed Brown     ierr = TSComputeRHSFunction(ts,t+h*c[i],Y[i],YdotRHS[i]);CHKERRQ(ierr);
2388a381b04SJed Brown   }
239*a17b68daSJed Brown   for (j=0; j<s; j++) w[j] = -h*bt[j];
2408a381b04SJed Brown   ierr = VecMAXPY(ts->vec_sol,s,w,YdotI);CHKERRQ(ierr);
2418a381b04SJed Brown   for (j=0; j<s; j++) w[j] = h*b[j];
2428a381b04SJed Brown   ierr = VecMAXPY(ts->vec_sol,s,w,YdotRHS);CHKERRQ(ierr);
2438a381b04SJed Brown 
2448a381b04SJed Brown   ts->ptime          += ts->time_step;
2458a381b04SJed Brown   ts->next_time_step  = ts->time_step;
2468a381b04SJed Brown   ts->steps++;
2478a381b04SJed Brown   PetscFunctionReturn(0);
2488a381b04SJed Brown }
2498a381b04SJed Brown 
2508a381b04SJed Brown /*------------------------------------------------------------*/
2518a381b04SJed Brown #undef __FUNCT__
2528a381b04SJed Brown #define __FUNCT__ "TSReset_ARKIMEX"
2538a381b04SJed Brown static PetscErrorCode TSReset_ARKIMEX(TS ts)
2548a381b04SJed Brown {
2558a381b04SJed Brown   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
2568a381b04SJed Brown   PetscInt        s;
2578a381b04SJed Brown   PetscErrorCode  ierr;
2588a381b04SJed Brown 
2598a381b04SJed Brown   PetscFunctionBegin;
2608a381b04SJed Brown   if (!ark->tableau) PetscFunctionReturn(0);
2618a381b04SJed Brown    s = ark->tableau->s;
2628a381b04SJed Brown   ierr = VecDestroyVecs(s,&ark->Y);CHKERRQ(ierr);
2638a381b04SJed Brown   ierr = VecDestroyVecs(s,&ark->YdotI);CHKERRQ(ierr);
2648a381b04SJed Brown   ierr = VecDestroyVecs(s,&ark->YdotRHS);CHKERRQ(ierr);
2658a381b04SJed Brown   ierr = VecDestroy(&ark->Ydot);CHKERRQ(ierr);
2668a381b04SJed Brown   ierr = VecDestroy(&ark->Work);CHKERRQ(ierr);
2678a381b04SJed Brown   ierr = VecDestroy(&ark->Z);CHKERRQ(ierr);
2688a381b04SJed Brown   ierr = PetscFree(ark->work);CHKERRQ(ierr);
2698a381b04SJed Brown   PetscFunctionReturn(0);
2708a381b04SJed Brown }
2718a381b04SJed Brown 
2728a381b04SJed Brown #undef __FUNCT__
2738a381b04SJed Brown #define __FUNCT__ "TSDestroy_ARKIMEX"
2748a381b04SJed Brown static PetscErrorCode TSDestroy_ARKIMEX(TS ts)
2758a381b04SJed Brown {
2768a381b04SJed Brown   PetscErrorCode  ierr;
2778a381b04SJed Brown 
2788a381b04SJed Brown   PetscFunctionBegin;
2798a381b04SJed Brown   ierr = TSReset_ARKIMEX(ts);CHKERRQ(ierr);
2808a381b04SJed Brown   ierr = PetscFree(ts->data);CHKERRQ(ierr);
2818a381b04SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSARKIMEXGetType_C","",PETSC_NULL);CHKERRQ(ierr);
2828a381b04SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSARKIMEXSetType_C","",PETSC_NULL);CHKERRQ(ierr);
2838a381b04SJed Brown   PetscFunctionReturn(0);
2848a381b04SJed Brown }
2858a381b04SJed Brown 
2868a381b04SJed Brown /*
2878a381b04SJed Brown   This defines the nonlinear equation that is to be solved with SNES
2888a381b04SJed Brown   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
2898a381b04SJed Brown */
2908a381b04SJed Brown #undef __FUNCT__
2918a381b04SJed Brown #define __FUNCT__ "SNESTSFormFunction_ARKIMEX"
2928a381b04SJed Brown static PetscErrorCode SNESTSFormFunction_ARKIMEX(SNES snes,Vec X,Vec F,TS ts)
2938a381b04SJed Brown {
2948a381b04SJed Brown   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
2958a381b04SJed Brown   PetscErrorCode ierr;
2968a381b04SJed Brown 
2978a381b04SJed Brown   PetscFunctionBegin;
2988a381b04SJed Brown   ierr = VecAXPBYPCZ(ark->Ydot,-ark->shift,ark->shift,0,ark->Z,X);CHKERRQ(ierr); /* Ydot = shift*(X-Z) */
29931f6fcc0SJed Brown   ierr = TSComputeIFunction(ts,ark->stage_time,X,ark->Ydot,F,PETSC_TRUE);CHKERRQ(ierr);
3008a381b04SJed Brown   PetscFunctionReturn(0);
3018a381b04SJed Brown }
3028a381b04SJed Brown 
3038a381b04SJed Brown #undef __FUNCT__
3048a381b04SJed Brown #define __FUNCT__ "SNESTSFormJacobian_ARKIMEX"
3058a381b04SJed Brown static PetscErrorCode SNESTSFormJacobian_ARKIMEX(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts)
3068a381b04SJed Brown {
3078a381b04SJed Brown   TS_ARKIMEX       *ark = (TS_ARKIMEX*)ts->data;
3088a381b04SJed Brown   PetscErrorCode ierr;
3098a381b04SJed Brown 
3108a381b04SJed Brown   PetscFunctionBegin;
3118a381b04SJed Brown   /* ark->Ydot has already been computed in SNESTSFormFunction_ARKIMEX (SNES guarantees this) */
3128a381b04SJed Brown   ierr = TSComputeIJacobian(ts,ark->stage_time,X,ark->Ydot,ark->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr);
3138a381b04SJed Brown   PetscFunctionReturn(0);
3148a381b04SJed Brown }
3158a381b04SJed Brown 
3168a381b04SJed Brown #undef __FUNCT__
3178a381b04SJed Brown #define __FUNCT__ "TSSetUp_ARKIMEX"
3188a381b04SJed Brown static PetscErrorCode TSSetUp_ARKIMEX(TS ts)
3198a381b04SJed Brown {
3208a381b04SJed Brown   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
3218a381b04SJed Brown   ARKTableau     tab  = ark->tableau;
3228a381b04SJed Brown   PetscInt       s = tab->s;
3238a381b04SJed Brown   PetscErrorCode ierr;
3248a381b04SJed Brown 
3258a381b04SJed Brown   PetscFunctionBegin;
3268a381b04SJed Brown   if (!ark->tableau) {
3278a381b04SJed Brown     ierr = TSSetType(ts,TSARKIMEXDefault);CHKERRQ(ierr);
3288a381b04SJed Brown   }
3298a381b04SJed Brown   ierr = VecDuplicateVecs(ts->vec_sol,s,&ark->Y);CHKERRQ(ierr);
3308a381b04SJed Brown   ierr = VecDuplicateVecs(ts->vec_sol,s,&ark->YdotI);CHKERRQ(ierr);
3318a381b04SJed Brown   ierr = VecDuplicateVecs(ts->vec_sol,s,&ark->YdotRHS);CHKERRQ(ierr);
3328a381b04SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ark->Ydot);CHKERRQ(ierr);
3338a381b04SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ark->Work);CHKERRQ(ierr);
3348a381b04SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ark->Z);CHKERRQ(ierr);
3358a381b04SJed Brown   ierr = PetscMalloc(s*sizeof(ark->work[0]),&ark->work);CHKERRQ(ierr);
3368a381b04SJed Brown   PetscFunctionReturn(0);
3378a381b04SJed Brown }
3388a381b04SJed Brown /*------------------------------------------------------------*/
3398a381b04SJed Brown 
3408a381b04SJed Brown #undef __FUNCT__
3418a381b04SJed Brown #define __FUNCT__ "TSSetFromOptions_ARKIMEX"
3428a381b04SJed Brown static PetscErrorCode TSSetFromOptions_ARKIMEX(TS ts)
3438a381b04SJed Brown {
3448a381b04SJed Brown   PetscErrorCode ierr;
3458a381b04SJed Brown   char           arktype[256];
3468a381b04SJed Brown 
3478a381b04SJed Brown   PetscFunctionBegin;
3488a381b04SJed Brown   ierr = PetscOptionsHead("ARKIMEX ODE solver options");CHKERRQ(ierr);
3498a381b04SJed Brown   {
3508a381b04SJed Brown     ARKTableauLink link;
3518a381b04SJed Brown     PetscInt count,choice;
3528a381b04SJed Brown     PetscBool flg;
3538a381b04SJed Brown     const char **namelist;
3548a381b04SJed Brown     ierr = PetscStrncpy(arktype,TSARKIMEXDefault,sizeof arktype);CHKERRQ(ierr);
3558a381b04SJed Brown     for (link=ARKTableauList,count=0; link; link=link->next,count++) ;
3568a381b04SJed Brown     ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr);
3578a381b04SJed Brown     for (link=ARKTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
3588a381b04SJed Brown     ierr = PetscOptionsEList("-ts_arkimex_type","Family of ARK IMEX method","TSARKIMEXSetType",(const char*const*)namelist,count,arktype,&choice,&flg);CHKERRQ(ierr);
3598a381b04SJed Brown     ierr = TSARKIMEXSetType(ts,flg ? namelist[choice] : arktype);CHKERRQ(ierr);
3608a381b04SJed Brown     ierr = PetscFree(namelist);CHKERRQ(ierr);
3618a381b04SJed Brown   }
3628a381b04SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
3638a381b04SJed Brown   PetscFunctionReturn(0);
3648a381b04SJed Brown }
3658a381b04SJed Brown 
3668a381b04SJed Brown #undef __FUNCT__
3678a381b04SJed Brown #define __FUNCT__ "PetscFormatRealArray"
3688a381b04SJed Brown static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
3698a381b04SJed Brown {
3708a381b04SJed Brown   int i,left,count;
3718a381b04SJed Brown   char *p;
3728a381b04SJed Brown 
3738a381b04SJed Brown   PetscFunctionBegin;
3748a381b04SJed Brown   for (i=0,p=buf,left=(int)len; i<n; i++) {
3758a381b04SJed Brown     count = snprintf(p,left,fmt,x[i]);
3768a381b04SJed Brown     if (count < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"snprintf()");
3778a381b04SJed Brown     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
3788a381b04SJed Brown     left -= count;
3798a381b04SJed Brown     p += count;
3808a381b04SJed Brown     *p++ = ' ';
3818a381b04SJed Brown   }
3828a381b04SJed Brown   p[i ? 0 : -1] = 0;
3838a381b04SJed Brown   PetscFunctionReturn(0);
3848a381b04SJed Brown }
3858a381b04SJed Brown 
3868a381b04SJed Brown #undef __FUNCT__
3878a381b04SJed Brown #define __FUNCT__ "TSView_ARKIMEX"
3888a381b04SJed Brown static PetscErrorCode TSView_ARKIMEX(TS ts,PetscViewer viewer)
3898a381b04SJed Brown {
3908a381b04SJed Brown   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
3918a381b04SJed Brown   ARKTableau     tab = ark->tableau;
3928a381b04SJed Brown   PetscBool      iascii;
3938a381b04SJed Brown   PetscErrorCode ierr;
3948a381b04SJed Brown 
3958a381b04SJed Brown   PetscFunctionBegin;
3968a381b04SJed Brown   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3978a381b04SJed Brown   if (iascii) {
3988a381b04SJed Brown     const TSARKIMEXType arktype;
3998a381b04SJed Brown     char buf[512];
4008a381b04SJed Brown     ierr = TSARKIMEXGetType(ts,&arktype);CHKERRQ(ierr);
4018a381b04SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  ARK IMEX %s\n",arktype);CHKERRQ(ierr);
4028a381b04SJed Brown     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,tab->ct);CHKERRQ(ierr);
40331f6fcc0SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Stiff abscissa       ct = %s\n",buf);CHKERRQ(ierr);
40431f6fcc0SJed Brown     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,tab->c);CHKERRQ(ierr);
40531f6fcc0SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Nonstiff abscissa     c = %s\n",buf);CHKERRQ(ierr);
4068a381b04SJed Brown   } else {
4078a381b04SJed Brown     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for TS_ARKIMEX",((PetscObject)viewer)->type_name);
4088a381b04SJed Brown   }
4098a381b04SJed Brown   PetscFunctionReturn(0);
4108a381b04SJed Brown }
4118a381b04SJed Brown 
4128a381b04SJed Brown #undef __FUNCT__
4138a381b04SJed Brown #define __FUNCT__ "TSARKIMEXSetType"
4148a381b04SJed Brown /*@C
4158a381b04SJed Brown   TSARKIMEXSetType - Set the type of ARK IMEX scheme
4168a381b04SJed Brown 
4178a381b04SJed Brown   Logically collective
4188a381b04SJed Brown 
4198a381b04SJed Brown   Input Parameter:
4208a381b04SJed Brown +  ts - timestepping context
4218a381b04SJed Brown -  arktype - type of ARK-IMEX scheme
4228a381b04SJed Brown 
4238a381b04SJed Brown   Level: intermediate
4248a381b04SJed Brown 
4258a381b04SJed Brown .seealso: TSARKIMEXGetType()
4268a381b04SJed Brown @*/
4278a381b04SJed Brown PetscErrorCode TSARKIMEXSetType(TS ts,const TSARKIMEXType arktype)
4288a381b04SJed Brown {
4298a381b04SJed Brown   PetscErrorCode ierr;
4308a381b04SJed Brown 
4318a381b04SJed Brown   PetscFunctionBegin;
4328a381b04SJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4338a381b04SJed Brown   ierr = PetscTryMethod(ts,"TSARKIMEXSetType_C",(TS,const TSARKIMEXType),(ts,arktype));CHKERRQ(ierr);
4348a381b04SJed Brown   PetscFunctionReturn(0);
4358a381b04SJed Brown }
4368a381b04SJed Brown 
4378a381b04SJed Brown #undef __FUNCT__
4388a381b04SJed Brown #define __FUNCT__ "TSARKIMEXGetType"
4398a381b04SJed Brown /*@C
4408a381b04SJed Brown   TSARKIMEXGetType - Get the type of ARK IMEX scheme
4418a381b04SJed Brown 
4428a381b04SJed Brown   Logically collective
4438a381b04SJed Brown 
4448a381b04SJed Brown   Input Parameter:
4458a381b04SJed Brown .  ts - timestepping context
4468a381b04SJed Brown 
4478a381b04SJed Brown   Output Parameter:
4488a381b04SJed Brown .  arktype - type of ARK-IMEX scheme
4498a381b04SJed Brown 
4508a381b04SJed Brown   Level: intermediate
4518a381b04SJed Brown 
4528a381b04SJed Brown .seealso: TSARKIMEXGetType()
4538a381b04SJed Brown @*/
4548a381b04SJed Brown PetscErrorCode TSARKIMEXGetType(TS ts,const TSARKIMEXType *arktype)
4558a381b04SJed Brown {
4568a381b04SJed Brown   PetscErrorCode ierr;
4578a381b04SJed Brown 
4588a381b04SJed Brown   PetscFunctionBegin;
4598a381b04SJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4608a381b04SJed Brown   ierr = PetscUseMethod(ts,"TSARKIMEXGetType_C",(TS,const TSARKIMEXType*),(ts,arktype));CHKERRQ(ierr);
4618a381b04SJed Brown   PetscFunctionReturn(0);
4628a381b04SJed Brown }
4638a381b04SJed Brown 
4648a381b04SJed Brown EXTERN_C_BEGIN
4658a381b04SJed Brown #undef __FUNCT__
4668a381b04SJed Brown #define __FUNCT__ "TSARKIMEXGetType_ARKIMEX"
4678a381b04SJed Brown PetscErrorCode  TSARKIMEXGetType_ARKIMEX(TS ts,const TSARKIMEXType *arktype)
4688a381b04SJed Brown {
4698a381b04SJed Brown   TS_ARKIMEX *ark = (TS_ARKIMEX*)ts->data;
4708a381b04SJed Brown   PetscErrorCode ierr;
4718a381b04SJed Brown 
4728a381b04SJed Brown   PetscFunctionBegin;
4738a381b04SJed Brown   if (!ark->tableau) {ierr = TSARKIMEXSetType(ts,TSARKIMEXDefault);CHKERRQ(ierr);}
4748a381b04SJed Brown   *arktype = ark->tableau->name;
4758a381b04SJed Brown   PetscFunctionReturn(0);
4768a381b04SJed Brown }
4778a381b04SJed Brown #undef __FUNCT__
4788a381b04SJed Brown #define __FUNCT__ "TSARKIMEXSetType_ARKIMEX"
4798a381b04SJed Brown PetscErrorCode  TSARKIMEXSetType_ARKIMEX(TS ts,const TSARKIMEXType arktype)
4808a381b04SJed Brown {
4818a381b04SJed Brown   TS_ARKIMEX *ark = (TS_ARKIMEX*)ts->data;
4828a381b04SJed Brown   PetscErrorCode ierr;
4838a381b04SJed Brown   PetscBool match;
4848a381b04SJed Brown   ARKTableauLink link;
4858a381b04SJed Brown 
4868a381b04SJed Brown   PetscFunctionBegin;
4878a381b04SJed Brown   if (ark->tableau) {
4888a381b04SJed Brown     ierr = PetscStrcmp(ark->tableau->name,arktype,&match);CHKERRQ(ierr);
4898a381b04SJed Brown     if (match) PetscFunctionReturn(0);
4908a381b04SJed Brown   }
4918a381b04SJed Brown   for (link = ARKTableauList; link; link=link->next) {
4928a381b04SJed Brown     ierr = PetscStrcmp(link->tab.name,arktype,&match);CHKERRQ(ierr);
4938a381b04SJed Brown     if (match) {
4948a381b04SJed Brown       ierr = TSReset_ARKIMEX(ts);CHKERRQ(ierr);
4958a381b04SJed Brown       ark->tableau = &link->tab;
4968a381b04SJed Brown       PetscFunctionReturn(0);
4978a381b04SJed Brown     }
4988a381b04SJed Brown   }
4998a381b04SJed Brown   SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",arktype);
5008a381b04SJed Brown   PetscFunctionReturn(0);
5018a381b04SJed Brown }
5028a381b04SJed Brown EXTERN_C_END
5038a381b04SJed Brown 
5048a381b04SJed Brown /* ------------------------------------------------------------ */
5058a381b04SJed Brown /*MC
5068a381b04SJed Brown       TSARKIMEX - ODE solver using Additive Runge-Kutta IMEX schemes
5078a381b04SJed Brown 
5088a381b04SJed Brown   Level: beginner
5098a381b04SJed Brown 
5108a381b04SJed Brown .seealso:  TSCreate(), TS, TSSetType()
5118a381b04SJed Brown 
5128a381b04SJed Brown M*/
5138a381b04SJed Brown EXTERN_C_BEGIN
5148a381b04SJed Brown #undef __FUNCT__
5158a381b04SJed Brown #define __FUNCT__ "TSCreate_ARKIMEX"
5168a381b04SJed Brown PetscErrorCode  TSCreate_ARKIMEX(TS ts)
5178a381b04SJed Brown {
5188a381b04SJed Brown   TS_ARKIMEX       *th;
5198a381b04SJed Brown   PetscErrorCode ierr;
5208a381b04SJed Brown 
5218a381b04SJed Brown   PetscFunctionBegin;
5228a381b04SJed Brown #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
5238a381b04SJed Brown   ierr = TSARKIMEXInitializePackage(PETSC_NULL);CHKERRQ(ierr);
5248a381b04SJed Brown #endif
5258a381b04SJed Brown 
5268a381b04SJed Brown   ts->ops->reset          = TSReset_ARKIMEX;
5278a381b04SJed Brown   ts->ops->destroy        = TSDestroy_ARKIMEX;
5288a381b04SJed Brown   ts->ops->view           = TSView_ARKIMEX;
5298a381b04SJed Brown   ts->ops->setup          = TSSetUp_ARKIMEX;
5308a381b04SJed Brown   ts->ops->step           = TSStep_ARKIMEX;
5318a381b04SJed Brown   ts->ops->setfromoptions = TSSetFromOptions_ARKIMEX;
5328a381b04SJed Brown   ts->ops->snesfunction   = SNESTSFormFunction_ARKIMEX;
5338a381b04SJed Brown   ts->ops->snesjacobian   = SNESTSFormJacobian_ARKIMEX;
5348a381b04SJed Brown 
5358a381b04SJed Brown   ierr = PetscNewLog(ts,TS_ARKIMEX,&th);CHKERRQ(ierr);
5368a381b04SJed Brown   ts->data = (void*)th;
5378a381b04SJed Brown 
5388a381b04SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSARKIMEXGetType_C","TSARKIMEXGetType_ARKIMEX",TSARKIMEXGetType_ARKIMEX);CHKERRQ(ierr);
5398a381b04SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSARKIMEXSetType_C","TSARKIMEXSetType_ARKIMEX",TSARKIMEXSetType_ARKIMEX);CHKERRQ(ierr);
5408a381b04SJed Brown   PetscFunctionReturn(0);
5418a381b04SJed Brown }
5428a381b04SJed Brown EXTERN_C_END
543