1d2567f34SHong Zhang /* 2d2567f34SHong Zhang Code for timestepping with implicit Runge-Kutta method 3d2567f34SHong Zhang 4d2567f34SHong Zhang Notes: 5d2567f34SHong Zhang The general system is written as 6d2567f34SHong Zhang 7d2567f34SHong Zhang F(t,U,Udot) = 0 8d2567f34SHong Zhang 9d2567f34SHong Zhang */ 10d2567f34SHong Zhang #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 11d2567f34SHong Zhang #include <petscdm.h> 12d2567f34SHong Zhang #include <petscdt.h> 13d2567f34SHong Zhang 14d2567f34SHong Zhang static TSIRKType TSIRKDefault = TSIRKGAUSS; 15d2567f34SHong Zhang static PetscBool TSIRKRegisterAllCalled; 16d2567f34SHong Zhang static PetscBool TSIRKPackageInitialized; 17d2567f34SHong Zhang static PetscFunctionList TSIRKList; 18d2567f34SHong Zhang 19d2567f34SHong Zhang struct _IRKTableau{ 20d2567f34SHong Zhang PetscReal *A,*b,*c; 21d2567f34SHong Zhang PetscScalar *A_inv,*A_inv_rowsum,*I_s; 22d2567f34SHong Zhang PetscReal *binterp; /* Dense output formula */ 23d2567f34SHong Zhang }; 24d2567f34SHong Zhang 25d2567f34SHong Zhang typedef struct _IRKTableau *IRKTableau; 26d2567f34SHong Zhang 27d2567f34SHong Zhang typedef struct { 28d2567f34SHong Zhang char *method_name; 29d2567f34SHong Zhang PetscInt order; /* Classical approximation order of the method */ 30d2567f34SHong Zhang PetscInt nstages; /* Number of stages */ 31d2567f34SHong Zhang PetscBool stiffly_accurate; 32d2567f34SHong Zhang PetscInt pinterp; /* Interpolation order */ 33d2567f34SHong Zhang IRKTableau tableau; 34d2567f34SHong Zhang Vec U0; /* Backup vector */ 35d2567f34SHong Zhang Vec Z; /* Combined stage vector */ 36d2567f34SHong Zhang Vec *Y; /* States computed during the step */ 37d2567f34SHong Zhang Vec Ydot; /* Work vector holding time derivatives during residual evaluation */ 38d2567f34SHong Zhang Vec U; /* U is used to compute Ydot = shift(Y-U) */ 39d2567f34SHong Zhang Vec *YdotI; /* Work vectors to hold the residual evaluation */ 40d2567f34SHong Zhang Mat TJ; /* KAIJ matrix for the Jacobian of the combined system */ 41d2567f34SHong Zhang PetscScalar *work; /* Scalar work */ 42d2567f34SHong Zhang TSStepStatus status; 43d2567f34SHong Zhang PetscBool rebuild_completion; 44d2567f34SHong Zhang PetscReal ccfl; 45d2567f34SHong Zhang } TS_IRK; 46d2567f34SHong Zhang 47d2567f34SHong Zhang /*@C 48d2567f34SHong Zhang TSIRKTableauCreate - create the tableau for TSIRK and provide the entries 49d2567f34SHong Zhang 50d2567f34SHong Zhang Not Collective 51d2567f34SHong Zhang 52d2567f34SHong Zhang Input Parameters: 53d2567f34SHong Zhang + ts - timestepping context 54d2567f34SHong Zhang . nstages - number of stages, this is the dimension of the matrices below 55d2567f34SHong Zhang . A - stage coefficients (dimension nstages*nstages, row-major) 56d2567f34SHong Zhang . b - step completion table (dimension nstages) 57d2567f34SHong Zhang . c - abscissa (dimension nstages) 5802024617SSatish Balay . binterp - coefficients of the interpolation formula (dimension nstages) 59d2567f34SHong Zhang . A_inv - inverse of A (dimension nstages*nstages, row-major) 60d2567f34SHong Zhang . A_inv_rowsum - row sum of the inverse of A (dimension nstages) 6102024617SSatish Balay - I_s - identity matrix (dimension nstages*nstages) 62d2567f34SHong Zhang 63d2567f34SHong Zhang Level: advanced 64d2567f34SHong Zhang 65d2567f34SHong Zhang .seealso: TSIRK, TSIRKRegister() 66d2567f34SHong Zhang @*/ 67d2567f34SHong Zhang PetscErrorCode TSIRKTableauCreate(TS ts,PetscInt nstages,const PetscReal *A,const PetscReal *b,const PetscReal *c,const PetscReal *binterp,const PetscScalar *A_inv,const PetscScalar *A_inv_rowsum,const PetscScalar *I_s) 68d2567f34SHong Zhang { 69d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 70d2567f34SHong Zhang IRKTableau tab = irk->tableau; 71d2567f34SHong Zhang PetscErrorCode ierr; 72d2567f34SHong Zhang 73d2567f34SHong Zhang PetscFunctionBegin; 74d2567f34SHong Zhang irk->order = nstages; 75d2567f34SHong Zhang ierr = PetscMalloc3(PetscSqr(nstages),&tab->A,PetscSqr(nstages),&tab->A_inv,PetscSqr(nstages),&tab->I_s);CHKERRQ(ierr); 76d2567f34SHong Zhang ierr = PetscMalloc4(nstages,&tab->b,nstages,&tab->c,nstages,&tab->binterp,nstages,&tab->A_inv_rowsum);CHKERRQ(ierr); 77d2567f34SHong Zhang ierr = PetscArraycpy(tab->A,A,PetscSqr(nstages));CHKERRQ(ierr); 78d2567f34SHong Zhang ierr = PetscArraycpy(tab->b,b,nstages);CHKERRQ(ierr); 79d2567f34SHong Zhang ierr = PetscArraycpy(tab->c,c,nstages);CHKERRQ(ierr); 80d2567f34SHong Zhang /* optional coefficient arrays */ 81d2567f34SHong Zhang if (binterp) { 82d2567f34SHong Zhang ierr = PetscArraycpy(tab->binterp,binterp,nstages);CHKERRQ(ierr); 83d2567f34SHong Zhang } 84d2567f34SHong Zhang if (A_inv) { 85d2567f34SHong Zhang ierr = PetscArraycpy(tab->A_inv,A_inv,PetscSqr(nstages));CHKERRQ(ierr); 86d2567f34SHong Zhang } 87d2567f34SHong Zhang if (A_inv_rowsum) { 88d2567f34SHong Zhang ierr = PetscArraycpy(tab->A_inv_rowsum,A_inv_rowsum,nstages);CHKERRQ(ierr); 89d2567f34SHong Zhang } 90d2567f34SHong Zhang if (I_s) { 91d2567f34SHong Zhang ierr = PetscArraycpy(tab->I_s,I_s,PetscSqr(nstages));CHKERRQ(ierr); 92d2567f34SHong Zhang } 93d2567f34SHong Zhang PetscFunctionReturn(0); 94d2567f34SHong Zhang } 95d2567f34SHong Zhang 96d2567f34SHong Zhang /* Arrays should be freed with PetscFree3(A,b,c) */ 97d2567f34SHong Zhang static PetscErrorCode TSIRKCreate_Gauss(TS ts) 98d2567f34SHong Zhang { 99d2567f34SHong Zhang PetscInt nstages; 100d2567f34SHong Zhang PetscReal *gauss_A_real,*gauss_b,*b,*gauss_c; 101d2567f34SHong Zhang PetscScalar *gauss_A,*gauss_A_inv,*gauss_A_inv_rowsum,*I_s; 102d2567f34SHong Zhang PetscScalar *G0,*G1; 103d2567f34SHong Zhang PetscInt i,j; 104d2567f34SHong Zhang Mat G0mat,G1mat,Amat; 105d2567f34SHong Zhang PetscErrorCode ierr; 106d2567f34SHong Zhang 107d2567f34SHong Zhang PetscFunctionBegin; 108d2567f34SHong Zhang ierr = TSIRKGetNumStages(ts,&nstages);CHKERRQ(ierr); 109d2567f34SHong Zhang ierr = PetscMalloc3(PetscSqr(nstages),&gauss_A_real,nstages,&gauss_b,nstages,&gauss_c);CHKERRQ(ierr); 110d2567f34SHong Zhang ierr = PetscMalloc4(PetscSqr(nstages),&gauss_A,PetscSqr(nstages),&gauss_A_inv,nstages,&gauss_A_inv_rowsum,PetscSqr(nstages),&I_s);CHKERRQ(ierr); 111d2567f34SHong Zhang ierr = PetscMalloc3(nstages,&b,PetscSqr(nstages),&G0,PetscSqr(nstages),&G1);CHKERRQ(ierr); 112d2567f34SHong Zhang ierr = PetscDTGaussQuadrature(nstages,0.,1.,gauss_c,b);CHKERRQ(ierr); 113d2567f34SHong Zhang for (i=0; i<nstages; i++) gauss_b[i] = b[i]; /* copy to possibly-complex array */ 114d2567f34SHong Zhang 115d2567f34SHong Zhang /* A^T = G0^{-1} G1 */ 116d2567f34SHong Zhang for (i=0; i<nstages; i++) { 117d2567f34SHong Zhang for (j=0; j<nstages; j++) { 118d2567f34SHong Zhang G0[i*nstages+j] = PetscPowRealInt(gauss_c[i],j); 119d2567f34SHong Zhang G1[i*nstages+j] = PetscPowRealInt(gauss_c[i],j+1)/(j+1); 120d2567f34SHong Zhang } 121d2567f34SHong Zhang } 122d2567f34SHong Zhang /* The arrays above are row-aligned, but we create dense matrices as the transpose */ 123d2567f34SHong Zhang ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,G0,&G0mat);CHKERRQ(ierr); 124d2567f34SHong Zhang ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,G1,&G1mat);CHKERRQ(ierr); 125d2567f34SHong Zhang ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,gauss_A,&Amat);CHKERRQ(ierr); 126d2567f34SHong Zhang ierr = MatLUFactor(G0mat,NULL,NULL,NULL);CHKERRQ(ierr); 127d2567f34SHong Zhang ierr = MatMatSolve(G0mat,G1mat,Amat);CHKERRQ(ierr); 128d2567f34SHong Zhang ierr = MatTranspose(Amat,MAT_INPLACE_MATRIX,&Amat);CHKERRQ(ierr); 129d2567f34SHong Zhang for (i=0; i<nstages; i++) 130d2567f34SHong Zhang for (j=0; j<nstages; j++) 131d2567f34SHong Zhang gauss_A_real[i*nstages+j] = PetscRealPart(gauss_A[i*nstages+j]); 132d2567f34SHong Zhang 133d2567f34SHong Zhang ierr = MatDestroy(&G0mat);CHKERRQ(ierr); 134d2567f34SHong Zhang ierr = MatDestroy(&G1mat);CHKERRQ(ierr); 135d2567f34SHong Zhang ierr = MatDestroy(&Amat);CHKERRQ(ierr); 136d2567f34SHong Zhang ierr = PetscFree3(b,G0,G1);CHKERRQ(ierr); 137d2567f34SHong Zhang 138d2567f34SHong Zhang {/* Invert A */ 139d2567f34SHong Zhang /* PETSc does not provide a routine to calculate the inverse of a general matrix. 140d2567f34SHong Zhang * To get the inverse of A, we form a sequential BAIJ matrix from it, consisting of a single block with block size 141d2567f34SHong Zhang * equal to the dimension of A, and then use MatInvertBlockDiagonal(). */ 142d2567f34SHong Zhang Mat A_baij; 143d2567f34SHong Zhang PetscInt idxm[1]={0},idxn[1]={0}; 144d2567f34SHong Zhang const PetscScalar *A_inv; 145d2567f34SHong Zhang 146d2567f34SHong Zhang ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF,nstages,nstages,nstages,1,NULL,&A_baij);CHKERRQ(ierr); 147d2567f34SHong Zhang ierr = MatSetOption(A_baij,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 148d2567f34SHong Zhang ierr = MatSetValuesBlocked(A_baij,1,idxm,1,idxn,gauss_A,INSERT_VALUES);CHKERRQ(ierr); 149d2567f34SHong Zhang ierr = MatAssemblyBegin(A_baij,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 150d2567f34SHong Zhang ierr = MatAssemblyEnd(A_baij,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 151d2567f34SHong Zhang ierr = MatInvertBlockDiagonal(A_baij,&A_inv);CHKERRQ(ierr); 152d2567f34SHong Zhang ierr = PetscMemcpy(gauss_A_inv,A_inv,nstages*nstages*sizeof(PetscScalar));CHKERRQ(ierr); 153d2567f34SHong Zhang ierr = MatDestroy(&A_baij);CHKERRQ(ierr); 154d2567f34SHong Zhang } 155d2567f34SHong Zhang 156d2567f34SHong Zhang /* Compute row sums A_inv_rowsum and identity I_s */ 157d2567f34SHong Zhang for (i=0; i<nstages; i++) { 158d2567f34SHong Zhang gauss_A_inv_rowsum[i] = 0; 159d2567f34SHong Zhang for (j=0; j<nstages; j++) { 160d2567f34SHong Zhang gauss_A_inv_rowsum[i] += gauss_A_inv[i+nstages*j]; 161d2567f34SHong Zhang I_s[i+nstages*j] = 1.*(i == j); 162d2567f34SHong Zhang } 163d2567f34SHong Zhang } 164d2567f34SHong Zhang ierr = TSIRKTableauCreate(ts,nstages,gauss_A_real,gauss_b,gauss_c,NULL,gauss_A_inv,gauss_A_inv_rowsum,I_s);CHKERRQ(ierr); 165d2567f34SHong Zhang ierr = PetscFree3(gauss_A_real,gauss_b,gauss_c);CHKERRQ(ierr); 166d2567f34SHong Zhang ierr = PetscFree4(gauss_A,gauss_A_inv,gauss_A_inv_rowsum,I_s);CHKERRQ(ierr); 167d2567f34SHong Zhang PetscFunctionReturn(0); 168d2567f34SHong Zhang } 169d2567f34SHong Zhang 170d2567f34SHong Zhang /*@C 171d2567f34SHong Zhang TSIRKRegister - adds a TSIRK implementation 172d2567f34SHong Zhang 173d2567f34SHong Zhang Not Collective 174d2567f34SHong Zhang 175d2567f34SHong Zhang Input Parameters: 176d2567f34SHong Zhang + sname - name of user-defined IRK scheme 177d2567f34SHong Zhang - function - function to create method context 178d2567f34SHong Zhang 179d2567f34SHong Zhang Notes: 180d2567f34SHong Zhang TSIRKRegister() may be called multiple times to add several user-defined families. 181d2567f34SHong Zhang 182d2567f34SHong Zhang Sample usage: 183d2567f34SHong Zhang .vb 184d2567f34SHong Zhang TSIRKRegister("my_scheme",MySchemeCreate); 185d2567f34SHong Zhang .ve 186d2567f34SHong Zhang 187d2567f34SHong Zhang Then, your scheme can be chosen with the procedural interface via 188d2567f34SHong Zhang $ TSIRKSetType(ts,"my_scheme") 189d2567f34SHong Zhang or at runtime via the option 190d2567f34SHong Zhang $ -ts_irk_type my_scheme 191d2567f34SHong Zhang 192d2567f34SHong Zhang Level: advanced 193d2567f34SHong Zhang 194d2567f34SHong Zhang .seealso: TSIRKRegisterAll() 195d2567f34SHong Zhang @*/ 196d2567f34SHong Zhang PetscErrorCode TSIRKRegister(const char sname[],PetscErrorCode (*function)(TS)) 197d2567f34SHong Zhang { 198d2567f34SHong Zhang PetscErrorCode ierr; 199d2567f34SHong Zhang 200d2567f34SHong Zhang PetscFunctionBegin; 201d2567f34SHong Zhang ierr = TSIRKInitializePackage();CHKERRQ(ierr); 202d2567f34SHong Zhang ierr = PetscFunctionListAdd(&TSIRKList,sname,function);CHKERRQ(ierr); 203d2567f34SHong Zhang PetscFunctionReturn(0); 204d2567f34SHong Zhang } 205d2567f34SHong Zhang 206d2567f34SHong Zhang /*@C 207d2567f34SHong Zhang TSIRKRegisterAll - Registers all of the implicit Runge-Kutta methods in TSIRK 208d2567f34SHong Zhang 209d2567f34SHong Zhang Not Collective, but should be called by all processes which will need the schemes to be registered 210d2567f34SHong Zhang 211d2567f34SHong Zhang Level: advanced 212d2567f34SHong Zhang 213d2567f34SHong Zhang .seealso: TSIRKRegisterDestroy() 214d2567f34SHong Zhang @*/ 215d2567f34SHong Zhang PetscErrorCode TSIRKRegisterAll(void) 216d2567f34SHong Zhang { 217d2567f34SHong Zhang PetscErrorCode ierr; 218d2567f34SHong Zhang 219d2567f34SHong Zhang PetscFunctionBegin; 220d2567f34SHong Zhang if (TSIRKRegisterAllCalled) PetscFunctionReturn(0); 221d2567f34SHong Zhang TSIRKRegisterAllCalled = PETSC_TRUE; 222d2567f34SHong Zhang 223d2567f34SHong Zhang ierr = TSIRKRegister(TSIRKGAUSS,TSIRKCreate_Gauss);CHKERRQ(ierr); 224d2567f34SHong Zhang PetscFunctionReturn(0); 225d2567f34SHong Zhang } 226d2567f34SHong Zhang 227d2567f34SHong Zhang /*@C 228d2567f34SHong Zhang TSIRKRegisterDestroy - Frees the list of schemes that were registered by TSIRKRegister(). 229d2567f34SHong Zhang 230d2567f34SHong Zhang Not Collective 231d2567f34SHong Zhang 232d2567f34SHong Zhang Level: advanced 233d2567f34SHong Zhang 234d2567f34SHong Zhang .seealso: TSIRKRegister(), TSIRKRegisterAll() 235d2567f34SHong Zhang @*/ 236d2567f34SHong Zhang PetscErrorCode TSIRKRegisterDestroy(void) 237d2567f34SHong Zhang { 238d2567f34SHong Zhang PetscFunctionBegin; 239d2567f34SHong Zhang TSIRKRegisterAllCalled = PETSC_FALSE; 240d2567f34SHong Zhang PetscFunctionReturn(0); 241d2567f34SHong Zhang } 242d2567f34SHong Zhang 243d2567f34SHong Zhang /*@C 244d2567f34SHong Zhang TSIRKInitializePackage - This function initializes everything in the TSIRK package. It is called 245d2567f34SHong Zhang from TSInitializePackage(). 246d2567f34SHong Zhang 247d2567f34SHong Zhang Level: developer 248d2567f34SHong Zhang 249d2567f34SHong Zhang .seealso: PetscInitialize() 250d2567f34SHong Zhang @*/ 251d2567f34SHong Zhang PetscErrorCode TSIRKInitializePackage(void) 252d2567f34SHong Zhang { 253d2567f34SHong Zhang PetscErrorCode ierr; 254d2567f34SHong Zhang 255d2567f34SHong Zhang PetscFunctionBegin; 256d2567f34SHong Zhang if (TSIRKPackageInitialized) PetscFunctionReturn(0); 257d2567f34SHong Zhang TSIRKPackageInitialized = PETSC_TRUE; 258d2567f34SHong Zhang ierr = TSIRKRegisterAll();CHKERRQ(ierr); 259d2567f34SHong Zhang ierr = PetscRegisterFinalize(TSIRKFinalizePackage);CHKERRQ(ierr); 260d2567f34SHong Zhang PetscFunctionReturn(0); 261d2567f34SHong Zhang } 262d2567f34SHong Zhang 263d2567f34SHong Zhang /*@C 264d2567f34SHong Zhang TSIRKFinalizePackage - This function destroys everything in the TSIRK package. It is 265d2567f34SHong Zhang called from PetscFinalize(). 266d2567f34SHong Zhang 267d2567f34SHong Zhang Level: developer 268d2567f34SHong Zhang 269d2567f34SHong Zhang .seealso: PetscFinalize() 270d2567f34SHong Zhang @*/ 271d2567f34SHong Zhang PetscErrorCode TSIRKFinalizePackage(void) 272d2567f34SHong Zhang { 273d2567f34SHong Zhang PetscErrorCode ierr; 274d2567f34SHong Zhang 275d2567f34SHong Zhang PetscFunctionBegin; 276d2567f34SHong Zhang ierr = PetscFunctionListDestroy(&TSIRKList);CHKERRQ(ierr); 277d2567f34SHong Zhang TSIRKPackageInitialized = PETSC_FALSE; 278d2567f34SHong Zhang PetscFunctionReturn(0); 279d2567f34SHong Zhang } 280d2567f34SHong Zhang 281d2567f34SHong Zhang /* 282d2567f34SHong Zhang This function can be called before or after ts->vec_sol has been updated. 283d2567f34SHong Zhang */ 284d2567f34SHong Zhang static PetscErrorCode TSEvaluateStep_IRK(TS ts,PetscInt order,Vec U,PetscBool *done) 285d2567f34SHong Zhang { 286d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 287d2567f34SHong Zhang IRKTableau tab = irk->tableau; 288d2567f34SHong Zhang Vec *YdotI = irk->YdotI; 289d2567f34SHong Zhang PetscScalar *w = irk->work; 290d2567f34SHong Zhang PetscReal h; 291d2567f34SHong Zhang PetscInt j; 292d2567f34SHong Zhang PetscErrorCode ierr; 293d2567f34SHong Zhang 294d2567f34SHong Zhang PetscFunctionBegin; 295d2567f34SHong Zhang switch (irk->status) { 296d2567f34SHong Zhang case TS_STEP_INCOMPLETE: 297d2567f34SHong Zhang case TS_STEP_PENDING: 298d2567f34SHong Zhang h = ts->time_step; break; 299d2567f34SHong Zhang case TS_STEP_COMPLETE: 300d2567f34SHong Zhang h = ts->ptime - ts->ptime_prev; break; 301d2567f34SHong Zhang default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 302d2567f34SHong Zhang } 303d2567f34SHong Zhang 304d2567f34SHong Zhang ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 305d2567f34SHong Zhang for (j=0; j<irk->nstages; j++) w[j] = h*tab->b[j]; 306d2567f34SHong Zhang ierr = VecMAXPY(U,irk->nstages,w,YdotI);CHKERRQ(ierr); 307d2567f34SHong Zhang PetscFunctionReturn(0); 308d2567f34SHong Zhang } 309d2567f34SHong Zhang 310d2567f34SHong Zhang static PetscErrorCode TSRollBack_IRK(TS ts) 311d2567f34SHong Zhang { 312d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 313d2567f34SHong Zhang PetscErrorCode ierr; 314d2567f34SHong Zhang 315d2567f34SHong Zhang PetscFunctionBegin; 316d2567f34SHong Zhang ierr = VecCopy(irk->U0,ts->vec_sol);CHKERRQ(ierr); 317d2567f34SHong Zhang PetscFunctionReturn(0); 318d2567f34SHong Zhang } 319d2567f34SHong Zhang 320d2567f34SHong Zhang static PetscErrorCode TSStep_IRK(TS ts) 321d2567f34SHong Zhang { 322d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 323d2567f34SHong Zhang IRKTableau tab = irk->tableau; 324d2567f34SHong Zhang PetscScalar *A_inv = tab->A_inv,*A_inv_rowsum = tab->A_inv_rowsum; 325d2567f34SHong Zhang const PetscInt nstages = irk->nstages; 326d2567f34SHong Zhang SNES snes; 327d2567f34SHong Zhang PetscInt i,j,its,lits,bs; 328d2567f34SHong Zhang TSAdapt adapt; 329d2567f34SHong Zhang PetscInt rejections = 0; 330d2567f34SHong Zhang PetscBool accept = PETSC_TRUE; 331d2567f34SHong Zhang PetscReal next_time_step = ts->time_step; 332d2567f34SHong Zhang PetscErrorCode ierr; 333d2567f34SHong Zhang 334d2567f34SHong Zhang PetscFunctionBegin; 335d2567f34SHong Zhang if (!ts->steprollback) { 336d2567f34SHong Zhang ierr = VecCopy(ts->vec_sol,irk->U0);CHKERRQ(ierr); 337d2567f34SHong Zhang } 338d2567f34SHong Zhang ierr = VecGetBlockSize(ts->vec_sol,&bs);CHKERRQ(ierr); 339d2567f34SHong Zhang for (i=0; i<nstages; i++) { 340d2567f34SHong Zhang ierr = VecStrideScatter(ts->vec_sol,i*bs,irk->Z,INSERT_VALUES);CHKERRQ(ierr); 341d2567f34SHong Zhang } 342d2567f34SHong Zhang 343d2567f34SHong Zhang irk->status = TS_STEP_INCOMPLETE; 344d2567f34SHong Zhang while (!ts->reason && irk->status != TS_STEP_COMPLETE) { 345d2567f34SHong Zhang ierr = VecCopy(ts->vec_sol,irk->U);CHKERRQ(ierr); 346d2567f34SHong Zhang ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 347d2567f34SHong Zhang ierr = SNESSolve(snes,NULL,irk->Z);CHKERRQ(ierr); 348d2567f34SHong Zhang ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 349d2567f34SHong Zhang ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 350d2567f34SHong Zhang ts->snes_its += its; ts->ksp_its += lits; 351d2567f34SHong Zhang ierr = VecStrideGatherAll(irk->Z,irk->Y,INSERT_VALUES);CHKERRQ(ierr); 352d2567f34SHong Zhang for (i=0; i<nstages; i++) { 353d2567f34SHong Zhang ierr = VecZeroEntries(irk->YdotI[i]);CHKERRQ(ierr); 354d2567f34SHong Zhang for (j=0; j<nstages; j++) { 355d2567f34SHong Zhang ierr = VecAXPY(irk->YdotI[i],A_inv[i+j*nstages]/ts->time_step,irk->Y[j]);CHKERRQ(ierr); 356d2567f34SHong Zhang } 357d2567f34SHong Zhang ierr = VecAXPY(irk->YdotI[i],-A_inv_rowsum[i]/ts->time_step,irk->U);CHKERRQ(ierr); 358d2567f34SHong Zhang } 359d2567f34SHong Zhang irk->status = TS_STEP_INCOMPLETE; 360d2567f34SHong Zhang ierr = TSEvaluateStep_IRK(ts,irk->order,ts->vec_sol,NULL);CHKERRQ(ierr); 361d2567f34SHong Zhang irk->status = TS_STEP_PENDING; 362d2567f34SHong Zhang ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 363d2567f34SHong Zhang ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 364d2567f34SHong Zhang irk->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 365d2567f34SHong Zhang if (!accept) { 366d2567f34SHong Zhang ierr = TSRollBack_IRK(ts);CHKERRQ(ierr); 367d2567f34SHong Zhang ts->time_step = next_time_step; 368d2567f34SHong Zhang goto reject_step; 369d2567f34SHong Zhang } 370d2567f34SHong Zhang 371d2567f34SHong Zhang ts->ptime += ts->time_step; 372d2567f34SHong Zhang ts->time_step = next_time_step; 373d2567f34SHong Zhang break; 374d2567f34SHong Zhang reject_step: 375d2567f34SHong Zhang ts->reject++; accept = PETSC_FALSE; 376d2567f34SHong Zhang if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 377d2567f34SHong Zhang ts->reason = TS_DIVERGED_STEP_REJECTED; 378d2567f34SHong Zhang ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 379d2567f34SHong Zhang } 380d2567f34SHong Zhang } 381d2567f34SHong Zhang PetscFunctionReturn(0); 382d2567f34SHong Zhang } 383d2567f34SHong Zhang 384d2567f34SHong Zhang static PetscErrorCode TSInterpolate_IRK(TS ts,PetscReal itime,Vec U) 385d2567f34SHong Zhang { 386d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 387d2567f34SHong Zhang PetscInt nstages = irk->nstages,pinterp = irk->pinterp,i,j; 388d2567f34SHong Zhang PetscReal h; 389d2567f34SHong Zhang PetscReal tt,t; 390d2567f34SHong Zhang PetscScalar *bt; 391d2567f34SHong Zhang const PetscReal *B = irk->tableau->binterp; 392d2567f34SHong Zhang PetscErrorCode ierr; 393d2567f34SHong Zhang 394d2567f34SHong Zhang PetscFunctionBegin; 395d2567f34SHong Zhang if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSIRK %s does not have an interpolation formula",irk->method_name); 396d2567f34SHong Zhang switch (irk->status) { 397d2567f34SHong Zhang case TS_STEP_INCOMPLETE: 398d2567f34SHong Zhang case TS_STEP_PENDING: 399d2567f34SHong Zhang h = ts->time_step; 400d2567f34SHong Zhang t = (itime - ts->ptime)/h; 401d2567f34SHong Zhang break; 402d2567f34SHong Zhang case TS_STEP_COMPLETE: 403d2567f34SHong Zhang h = ts->ptime - ts->ptime_prev; 404d2567f34SHong Zhang t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 405d2567f34SHong Zhang break; 406d2567f34SHong Zhang default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 407d2567f34SHong Zhang } 408d2567f34SHong Zhang ierr = PetscMalloc1(nstages,&bt);CHKERRQ(ierr); 409d2567f34SHong Zhang for (i=0; i<nstages; i++) bt[i] = 0; 410d2567f34SHong Zhang for (j=0,tt=t; j<pinterp; j++,tt*=t) { 411d2567f34SHong Zhang for (i=0; i<nstages; i++) { 412d2567f34SHong Zhang bt[i] += h * B[i*pinterp+j] * tt; 413d2567f34SHong Zhang } 414d2567f34SHong Zhang } 415d2567f34SHong Zhang ierr = VecMAXPY(U,nstages,bt,irk->YdotI);CHKERRQ(ierr); 416d2567f34SHong Zhang PetscFunctionReturn(0); 417d2567f34SHong Zhang } 418d2567f34SHong Zhang 419d2567f34SHong Zhang static PetscErrorCode TSIRKTableauReset(TS ts) 420d2567f34SHong Zhang { 421d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 422d2567f34SHong Zhang IRKTableau tab = irk->tableau; 423d2567f34SHong Zhang PetscErrorCode ierr; 424d2567f34SHong Zhang 425d2567f34SHong Zhang PetscFunctionBegin; 426d2567f34SHong Zhang if (!tab) PetscFunctionReturn(0); 427d2567f34SHong Zhang ierr = PetscFree3(tab->A,tab->A_inv,tab->I_s);CHKERRQ(ierr); 428d2567f34SHong Zhang ierr = PetscFree4(tab->b,tab->c,tab->binterp,tab->A_inv_rowsum);CHKERRQ(ierr); 429d2567f34SHong Zhang PetscFunctionReturn(0); 430d2567f34SHong Zhang } 431d2567f34SHong Zhang 432d2567f34SHong Zhang static PetscErrorCode TSReset_IRK(TS ts) 433d2567f34SHong Zhang { 434d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 435d2567f34SHong Zhang PetscErrorCode ierr; 436d2567f34SHong Zhang 437d2567f34SHong Zhang PetscFunctionBegin; 438d2567f34SHong Zhang ierr = TSIRKTableauReset(ts);CHKERRQ(ierr); 439d2567f34SHong Zhang if (irk->tableau) { 440d2567f34SHong Zhang ierr = PetscFree(irk->tableau);CHKERRQ(ierr); 441d2567f34SHong Zhang } 442d2567f34SHong Zhang if (irk->method_name) { 443d2567f34SHong Zhang ierr = PetscFree(irk->method_name);CHKERRQ(ierr); 444d2567f34SHong Zhang } 445d2567f34SHong Zhang if (irk->work) { 446d2567f34SHong Zhang ierr = PetscFree(irk->work);CHKERRQ(ierr); 447d2567f34SHong Zhang } 448d2567f34SHong Zhang ierr = VecDestroyVecs(irk->nstages,&irk->Y);CHKERRQ(ierr); 449d2567f34SHong Zhang ierr = VecDestroyVecs(irk->nstages,&irk->YdotI);CHKERRQ(ierr); 450d2567f34SHong Zhang ierr = VecDestroy(&irk->Ydot);CHKERRQ(ierr); 451d2567f34SHong Zhang ierr = VecDestroy(&irk->Z);CHKERRQ(ierr); 452d2567f34SHong Zhang ierr = VecDestroy(&irk->U);CHKERRQ(ierr); 453d2567f34SHong Zhang ierr = VecDestroy(&irk->U0);CHKERRQ(ierr); 454d2567f34SHong Zhang ierr = MatDestroy(&irk->TJ);CHKERRQ(ierr); 455d2567f34SHong Zhang PetscFunctionReturn(0); 456d2567f34SHong Zhang } 457d2567f34SHong Zhang 458d2567f34SHong Zhang static PetscErrorCode TSIRKGetVecs(TS ts,DM dm,Vec *U) 459d2567f34SHong Zhang { 460d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 461d2567f34SHong Zhang PetscErrorCode ierr; 462d2567f34SHong Zhang 463d2567f34SHong Zhang PetscFunctionBegin; 464d2567f34SHong Zhang if (U) { 465d2567f34SHong Zhang if (dm && dm != ts->dm) { 466d2567f34SHong Zhang ierr = DMGetNamedGlobalVector(dm,"TSIRK_U",U);CHKERRQ(ierr); 467d2567f34SHong Zhang } else *U = irk->U; 468d2567f34SHong Zhang } 469d2567f34SHong Zhang PetscFunctionReturn(0); 470d2567f34SHong Zhang } 471d2567f34SHong Zhang 472d2567f34SHong Zhang static PetscErrorCode TSIRKRestoreVecs(TS ts,DM dm,Vec *U) 473d2567f34SHong Zhang { 474d2567f34SHong Zhang PetscErrorCode ierr; 475d2567f34SHong Zhang 476d2567f34SHong Zhang PetscFunctionBegin; 477d2567f34SHong Zhang if (U) { 478d2567f34SHong Zhang if (dm && dm != ts->dm) { 479d2567f34SHong Zhang ierr = DMRestoreNamedGlobalVector(dm,"TSIRK_U",U);CHKERRQ(ierr); 480d2567f34SHong Zhang } 481d2567f34SHong Zhang } 482d2567f34SHong Zhang PetscFunctionReturn(0); 483d2567f34SHong Zhang } 484d2567f34SHong Zhang 485d2567f34SHong Zhang /* 486d2567f34SHong Zhang This defines the nonlinear equations that is to be solved with SNES 487d2567f34SHong Zhang G[e\otimes t + C*dt, Z, Zdot] = 0 488d2567f34SHong Zhang Zdot = (In \otimes S)*Z - (In \otimes Se) U 489d2567f34SHong Zhang where S = 1/(dt*A) 490d2567f34SHong Zhang */ 491d2567f34SHong Zhang static PetscErrorCode SNESTSFormFunction_IRK(SNES snes,Vec ZC,Vec FC,TS ts) 492d2567f34SHong Zhang { 493d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 494d2567f34SHong Zhang IRKTableau tab = irk->tableau; 495d2567f34SHong Zhang const PetscInt nstages = irk->nstages; 496d2567f34SHong Zhang const PetscReal *c = tab->c; 497d2567f34SHong Zhang const PetscScalar *A_inv = tab->A_inv,*A_inv_rowsum = tab->A_inv_rowsum; 498d2567f34SHong Zhang DM dm,dmsave; 499d2567f34SHong Zhang Vec U,*YdotI = irk->YdotI,Ydot = irk->Ydot,*Y = irk->Y; 500d2567f34SHong Zhang PetscReal h = ts->time_step; 501d2567f34SHong Zhang PetscInt i,j; 502d2567f34SHong Zhang PetscErrorCode ierr; 503d2567f34SHong Zhang 504d2567f34SHong Zhang PetscFunctionBegin; 505d2567f34SHong Zhang ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 506d2567f34SHong Zhang ierr = TSIRKGetVecs(ts,dm,&U);CHKERRQ(ierr); 507d2567f34SHong Zhang ierr = VecStrideGatherAll(ZC,Y,INSERT_VALUES);CHKERRQ(ierr); 508d2567f34SHong Zhang dmsave = ts->dm; 509d2567f34SHong Zhang ts->dm = dm; 510d2567f34SHong Zhang for (i=0; i<nstages; i++) { 511d2567f34SHong Zhang ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); 512d2567f34SHong Zhang for (j=0; j<nstages; j++) { 513d2567f34SHong Zhang ierr = VecAXPY(Ydot,A_inv[j*nstages+i]/h,Y[j]);CHKERRQ(ierr); 514d2567f34SHong Zhang } 515d2567f34SHong Zhang ierr = VecAXPY(Ydot,-A_inv_rowsum[i]/h,U);CHKERRQ(ierr); /* Ydot = (S \otimes In)*Z - (Se \otimes In) U */ 516d2567f34SHong Zhang ierr = TSComputeIFunction(ts,ts->ptime+ts->time_step*c[i],Y[i],Ydot,YdotI[i],PETSC_FALSE);CHKERRQ(ierr); 517d2567f34SHong Zhang } 518d2567f34SHong Zhang ierr = VecStrideScatterAll(YdotI,FC,INSERT_VALUES);CHKERRQ(ierr); 519d2567f34SHong Zhang ts->dm = dmsave; 520d2567f34SHong Zhang ierr = TSIRKRestoreVecs(ts,dm,&U);CHKERRQ(ierr); 521d2567f34SHong Zhang PetscFunctionReturn(0); 522d2567f34SHong Zhang } 523d2567f34SHong Zhang 524d2567f34SHong Zhang /* 525d2567f34SHong Zhang For explicit ODE, the Jacobian is 526d2567f34SHong Zhang JC = I_n \otimes S - J \otimes I_s 527d2567f34SHong Zhang For DAE, the Jacobian is 528d2567f34SHong Zhang JC = M_n \otimes S - J \otimes I_s 529d2567f34SHong Zhang */ 530d2567f34SHong Zhang static PetscErrorCode SNESTSFormJacobian_IRK(SNES snes,Vec ZC,Mat JC,Mat JCpre,TS ts) 531d2567f34SHong Zhang { 532d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 533d2567f34SHong Zhang IRKTableau tab = irk->tableau; 534d2567f34SHong Zhang const PetscInt nstages = irk->nstages; 535d2567f34SHong Zhang const PetscReal *c = tab->c; 536d2567f34SHong Zhang DM dm,dmsave; 537d2567f34SHong Zhang Vec *Y = irk->Y,Ydot = irk->Ydot; 538d2567f34SHong Zhang Mat J; 539d2567f34SHong Zhang PetscScalar *S; 540d2567f34SHong Zhang PetscInt i,j,bs; 541d2567f34SHong Zhang PetscErrorCode ierr; 542d2567f34SHong Zhang 543d2567f34SHong Zhang PetscFunctionBegin; 544d2567f34SHong Zhang ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 545d2567f34SHong Zhang /* irk->Ydot has already been computed in SNESTSFormFunction_IRK (SNES guarantees this) */ 546d2567f34SHong Zhang dmsave = ts->dm; 547d2567f34SHong Zhang ts->dm = dm; 548d2567f34SHong Zhang ierr = VecGetBlockSize(Y[nstages-1],&bs);CHKERRQ(ierr); 549d2567f34SHong Zhang if (ts->equation_type <= TS_EQ_ODE_EXPLICIT) { /* Support explicit formulas only */ 550d2567f34SHong Zhang ierr = VecStrideGather(ZC,(nstages-1)*bs,Y[nstages-1],INSERT_VALUES);CHKERRQ(ierr); 551d2567f34SHong Zhang ierr = MatKAIJGetAIJ(JC,&J);CHKERRQ(ierr); 552d2567f34SHong Zhang ierr = TSComputeIJacobian(ts,ts->ptime+ts->time_step*c[nstages-1],Y[nstages-1],Ydot,0,J,J,PETSC_FALSE);CHKERRQ(ierr); 553d2567f34SHong Zhang ierr = MatKAIJGetS(JC,NULL,NULL,&S);CHKERRQ(ierr); 554d2567f34SHong Zhang for (i=0; i<nstages; i++) 555d2567f34SHong Zhang for (j=0; j<nstages; j++) 556d2567f34SHong Zhang S[i+nstages*j] = tab->A_inv[i+nstages*j]/ts->time_step; 557d2567f34SHong Zhang ierr = MatKAIJRestoreS(JC,&S);CHKERRQ(ierr); 558d2567f34SHong Zhang } else 559d2567f34SHong Zhang SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSIRK %s does not support implicit formula",irk->method_name); /* ToDo: need the mass matrix for DAE */ 560d2567f34SHong Zhang ts->dm = dmsave; 561d2567f34SHong Zhang PetscFunctionReturn(0); 562d2567f34SHong Zhang } 563d2567f34SHong Zhang 564d2567f34SHong Zhang static PetscErrorCode DMCoarsenHook_TSIRK(DM fine,DM coarse,void *ctx) 565d2567f34SHong Zhang { 566d2567f34SHong Zhang PetscFunctionBegin; 567d2567f34SHong Zhang PetscFunctionReturn(0); 568d2567f34SHong Zhang } 569d2567f34SHong Zhang 570d2567f34SHong Zhang static PetscErrorCode DMRestrictHook_TSIRK(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 571d2567f34SHong Zhang { 572d2567f34SHong Zhang TS ts = (TS)ctx; 573d2567f34SHong Zhang Vec U,U_c; 574d2567f34SHong Zhang PetscErrorCode ierr; 575d2567f34SHong Zhang 576d2567f34SHong Zhang PetscFunctionBegin; 577d2567f34SHong Zhang ierr = TSIRKGetVecs(ts,fine,&U);CHKERRQ(ierr); 578d2567f34SHong Zhang ierr = TSIRKGetVecs(ts,coarse,&U_c);CHKERRQ(ierr); 579d2567f34SHong Zhang ierr = MatRestrict(restrct,U,U_c);CHKERRQ(ierr); 580d2567f34SHong Zhang ierr = VecPointwiseMult(U_c,rscale,U_c);CHKERRQ(ierr); 581d2567f34SHong Zhang ierr = TSIRKRestoreVecs(ts,fine,&U);CHKERRQ(ierr); 582d2567f34SHong Zhang ierr = TSIRKRestoreVecs(ts,coarse,&U_c);CHKERRQ(ierr); 583d2567f34SHong Zhang PetscFunctionReturn(0); 584d2567f34SHong Zhang } 585d2567f34SHong Zhang 586d2567f34SHong Zhang static PetscErrorCode DMSubDomainHook_TSIRK(DM dm,DM subdm,void *ctx) 587d2567f34SHong Zhang { 588d2567f34SHong Zhang PetscFunctionBegin; 589d2567f34SHong Zhang PetscFunctionReturn(0); 590d2567f34SHong Zhang } 591d2567f34SHong Zhang 592d2567f34SHong Zhang static PetscErrorCode DMSubDomainRestrictHook_TSIRK(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 593d2567f34SHong Zhang { 594d2567f34SHong Zhang TS ts = (TS)ctx; 595d2567f34SHong Zhang Vec U,U_c; 596d2567f34SHong Zhang PetscErrorCode ierr; 597d2567f34SHong Zhang 598d2567f34SHong Zhang PetscFunctionBegin; 599d2567f34SHong Zhang ierr = TSIRKGetVecs(ts,dm,&U);CHKERRQ(ierr); 600d2567f34SHong Zhang ierr = TSIRKGetVecs(ts,subdm,&U_c);CHKERRQ(ierr); 601d2567f34SHong Zhang 602d2567f34SHong Zhang ierr = VecScatterBegin(gscat,U,U_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 603d2567f34SHong Zhang ierr = VecScatterEnd(gscat,U,U_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 604d2567f34SHong Zhang 605d2567f34SHong Zhang ierr = TSIRKRestoreVecs(ts,dm,&U);CHKERRQ(ierr); 606d2567f34SHong Zhang ierr = TSIRKRestoreVecs(ts,subdm,&U_c);CHKERRQ(ierr); 607d2567f34SHong Zhang PetscFunctionReturn(0); 608d2567f34SHong Zhang } 609d2567f34SHong Zhang 610d2567f34SHong Zhang static PetscErrorCode TSSetUp_IRK(TS ts) 611d2567f34SHong Zhang { 612d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 613d2567f34SHong Zhang IRKTableau tab = irk->tableau; 614d2567f34SHong Zhang DM dm; 615d2567f34SHong Zhang Mat J; 616d2567f34SHong Zhang Vec R; 617d2567f34SHong Zhang const PetscInt nstages = irk->nstages; 618d2567f34SHong Zhang PetscInt vsize,bs; 619d2567f34SHong Zhang PetscErrorCode ierr; 620d2567f34SHong Zhang 621d2567f34SHong Zhang PetscFunctionBegin; 622d2567f34SHong Zhang if (!irk->work) { 623d2567f34SHong Zhang ierr = PetscMalloc1(irk->nstages,&irk->work);CHKERRQ(ierr); 624d2567f34SHong Zhang } 625d2567f34SHong Zhang if (!irk->Y) { 626d2567f34SHong Zhang ierr = VecDuplicateVecs(ts->vec_sol,irk->nstages,&irk->Y);CHKERRQ(ierr); 627d2567f34SHong Zhang } 628d2567f34SHong Zhang if (!irk->YdotI) { 629d2567f34SHong Zhang ierr = VecDuplicateVecs(ts->vec_sol,irk->nstages,&irk->YdotI);CHKERRQ(ierr); 630d2567f34SHong Zhang } 631d2567f34SHong Zhang if (!irk->Ydot) { 632d2567f34SHong Zhang ierr = VecDuplicate(ts->vec_sol,&irk->Ydot);CHKERRQ(ierr); 633d2567f34SHong Zhang } 634d2567f34SHong Zhang if (!irk->U) { 635d2567f34SHong Zhang ierr = VecDuplicate(ts->vec_sol,&irk->U);CHKERRQ(ierr); 636d2567f34SHong Zhang } 637d2567f34SHong Zhang if (!irk->U0) { 638d2567f34SHong Zhang ierr = VecDuplicate(ts->vec_sol,&irk->U0);CHKERRQ(ierr); 639d2567f34SHong Zhang } 640d2567f34SHong Zhang if (!irk->Z) { 641d2567f34SHong Zhang ierr = VecCreate(PetscObjectComm((PetscObject)ts->vec_sol),&irk->Z);CHKERRQ(ierr); 642d2567f34SHong Zhang ierr = VecGetSize(ts->vec_sol,&vsize);CHKERRQ(ierr); 643d2567f34SHong Zhang ierr = VecSetSizes(irk->Z,PETSC_DECIDE,vsize*irk->nstages);CHKERRQ(ierr); 644d2567f34SHong Zhang ierr = VecGetBlockSize(ts->vec_sol,&bs);CHKERRQ(ierr); 645d2567f34SHong Zhang ierr = VecSetBlockSize(irk->Z,irk->nstages*bs);CHKERRQ(ierr); 646d2567f34SHong Zhang ierr = VecSetFromOptions(irk->Z);CHKERRQ(ierr); 647d2567f34SHong Zhang } 648d2567f34SHong Zhang ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 649d2567f34SHong Zhang ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSIRK,DMRestrictHook_TSIRK,ts);CHKERRQ(ierr); 650d2567f34SHong Zhang ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSIRK,DMSubDomainRestrictHook_TSIRK,ts);CHKERRQ(ierr); 651d2567f34SHong Zhang 652d2567f34SHong Zhang ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 653d2567f34SHong Zhang ierr = VecDuplicate(irk->Z,&R);CHKERRQ(ierr); 654d2567f34SHong Zhang ierr = SNESSetFunction(ts->snes,R,SNESTSFormFunction,ts);CHKERRQ(ierr); 655*3397a780SHong Zhang ierr = TSGetIJacobian(ts,&J,NULL,NULL,NULL);CHKERRQ(ierr); 656d2567f34SHong Zhang if (!irk->TJ) { 657d2567f34SHong Zhang /* Create the KAIJ matrix for solving the stages */ 658d2567f34SHong Zhang ierr = MatCreateKAIJ(J,nstages,nstages,tab->A_inv,tab->I_s,&irk->TJ);CHKERRQ(ierr); 659d2567f34SHong Zhang } 660d2567f34SHong Zhang ierr = SNESSetJacobian(ts->snes,irk->TJ,irk->TJ,SNESTSFormJacobian,ts);CHKERRQ(ierr); 661d2567f34SHong Zhang ierr = VecDestroy(&R);CHKERRQ(ierr); 662d2567f34SHong Zhang PetscFunctionReturn(0); 663d2567f34SHong Zhang } 664d2567f34SHong Zhang 665d2567f34SHong Zhang static PetscErrorCode TSSetFromOptions_IRK(PetscOptionItems *PetscOptionsObject,TS ts) 666d2567f34SHong Zhang { 667d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 668d2567f34SHong Zhang char tname[256] = TSIRKGAUSS; 669d2567f34SHong Zhang PetscErrorCode ierr; 670d2567f34SHong Zhang 671d2567f34SHong Zhang PetscFunctionBegin; 672d2567f34SHong Zhang ierr = PetscOptionsHead(PetscOptionsObject,"IRK ODE solver options");CHKERRQ(ierr); 673d2567f34SHong Zhang { 674d2567f34SHong Zhang PetscBool flg1,flg2; 675d2567f34SHong Zhang ierr = PetscOptionsInt("-ts_irk_nstages","Stages of the IRK method","TSIRKSetNumStages",irk->nstages,&irk->nstages,&flg1);CHKERRQ(ierr); 676d2567f34SHong Zhang ierr = PetscOptionsFList("-ts_irk_type","Type of IRK method","TSIRKSetType",TSIRKList,irk->method_name[0] ? irk->method_name : tname,tname,sizeof(tname),&flg2);CHKERRQ(ierr); 677d2567f34SHong Zhang if (flg1 ||flg2 || !irk->method_name[0]) { /* Create the method tableau after nstages or method is set */ 678d2567f34SHong Zhang ierr = TSIRKSetType(ts,tname);CHKERRQ(ierr); 679d2567f34SHong Zhang } 680d2567f34SHong Zhang } 681d2567f34SHong Zhang ierr = PetscOptionsTail();CHKERRQ(ierr); 682d2567f34SHong Zhang PetscFunctionReturn(0); 683d2567f34SHong Zhang } 684d2567f34SHong Zhang 685d2567f34SHong Zhang static PetscErrorCode TSView_IRK(TS ts,PetscViewer viewer) 686d2567f34SHong Zhang { 687d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 688d2567f34SHong Zhang PetscBool iascii; 689d2567f34SHong Zhang PetscErrorCode ierr; 690d2567f34SHong Zhang 691d2567f34SHong Zhang PetscFunctionBegin; 692d2567f34SHong Zhang ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 693d2567f34SHong Zhang if (iascii) { 694d2567f34SHong Zhang IRKTableau tab = irk->tableau; 695d2567f34SHong Zhang TSIRKType irktype; 696d2567f34SHong Zhang char buf[512]; 697d2567f34SHong Zhang 698d2567f34SHong Zhang ierr = TSIRKGetType(ts,&irktype);CHKERRQ(ierr); 699d2567f34SHong Zhang ierr = PetscViewerASCIIPrintf(viewer," IRK type %s\n",irktype);CHKERRQ(ierr); 700d2567f34SHong Zhang ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",irk->nstages,tab->c);CHKERRQ(ierr); 701d2567f34SHong Zhang ierr = PetscViewerASCIIPrintf(viewer," Abscissa c = %s\n",buf);CHKERRQ(ierr); 702d2567f34SHong Zhang ierr = PetscViewerASCIIPrintf(viewer,"Stiffly accurate: %s\n",irk->stiffly_accurate ? "yes" : "no");CHKERRQ(ierr); 703d2567f34SHong Zhang ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",PetscSqr(irk->nstages),tab->A);CHKERRQ(ierr); 704d2567f34SHong Zhang ierr = PetscViewerASCIIPrintf(viewer," A coefficients A = %s\n",buf);CHKERRQ(ierr); 705d2567f34SHong Zhang } 706d2567f34SHong Zhang PetscFunctionReturn(0); 707d2567f34SHong Zhang } 708d2567f34SHong Zhang 709d2567f34SHong Zhang static PetscErrorCode TSLoad_IRK(TS ts,PetscViewer viewer) 710d2567f34SHong Zhang { 711d2567f34SHong Zhang PetscErrorCode ierr; 712d2567f34SHong Zhang SNES snes; 713d2567f34SHong Zhang TSAdapt adapt; 714d2567f34SHong Zhang 715d2567f34SHong Zhang PetscFunctionBegin; 716d2567f34SHong Zhang ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 717d2567f34SHong Zhang ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr); 718d2567f34SHong Zhang ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 719d2567f34SHong Zhang ierr = SNESLoad(snes,viewer);CHKERRQ(ierr); 720d2567f34SHong Zhang /* function and Jacobian context for SNES when used with TS is always ts object */ 721d2567f34SHong Zhang ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr); 722d2567f34SHong Zhang ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr); 723d2567f34SHong Zhang PetscFunctionReturn(0); 724d2567f34SHong Zhang } 725d2567f34SHong Zhang 726d2567f34SHong Zhang /*@C 727d2567f34SHong Zhang TSIRKSetType - Set the type of IRK scheme 728d2567f34SHong Zhang 729d2567f34SHong Zhang Logically collective 730d2567f34SHong Zhang 73102024617SSatish Balay Input Parameters: 732d2567f34SHong Zhang + ts - timestepping context 733d2567f34SHong Zhang - irktype - type of IRK scheme 734d2567f34SHong Zhang 735d2567f34SHong Zhang Options Database: 736d2567f34SHong Zhang . -ts_irk_type <gauss> 737d2567f34SHong Zhang 738d2567f34SHong Zhang Level: intermediate 739d2567f34SHong Zhang 740d2567f34SHong Zhang .seealso: TSIRKGetType(), TSIRK, TSIRKType, TSIRKGAUSS 741d2567f34SHong Zhang @*/ 742d2567f34SHong Zhang PetscErrorCode TSIRKSetType(TS ts,TSIRKType irktype) 743d2567f34SHong Zhang { 744d2567f34SHong Zhang PetscErrorCode ierr; 745d2567f34SHong Zhang 746d2567f34SHong Zhang PetscFunctionBegin; 747d2567f34SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 748d2567f34SHong Zhang PetscValidCharPointer(irktype,2); 749d2567f34SHong Zhang ierr = PetscTryMethod(ts,"TSIRKSetType_C",(TS,TSIRKType),(ts,irktype));CHKERRQ(ierr); 750d2567f34SHong Zhang PetscFunctionReturn(0); 751d2567f34SHong Zhang } 752d2567f34SHong Zhang 753d2567f34SHong Zhang /*@C 754d2567f34SHong Zhang TSIRKGetType - Get the type of IRK IMEX scheme 755d2567f34SHong Zhang 756d2567f34SHong Zhang Logically collective 757d2567f34SHong Zhang 758d2567f34SHong Zhang Input Parameter: 759d2567f34SHong Zhang . ts - timestepping context 760d2567f34SHong Zhang 761d2567f34SHong Zhang Output Parameter: 762d2567f34SHong Zhang . irktype - type of IRK-IMEX scheme 763d2567f34SHong Zhang 764d2567f34SHong Zhang Level: intermediate 765d2567f34SHong Zhang 766d2567f34SHong Zhang .seealso: TSIRKGetType() 767d2567f34SHong Zhang @*/ 768d2567f34SHong Zhang PetscErrorCode TSIRKGetType(TS ts,TSIRKType *irktype) 769d2567f34SHong Zhang { 770d2567f34SHong Zhang PetscErrorCode ierr; 771d2567f34SHong Zhang 772d2567f34SHong Zhang PetscFunctionBegin; 773d2567f34SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 774d2567f34SHong Zhang ierr = PetscUseMethod(ts,"TSIRKGetType_C",(TS,TSIRKType*),(ts,irktype));CHKERRQ(ierr); 775d2567f34SHong Zhang PetscFunctionReturn(0); 776d2567f34SHong Zhang } 777d2567f34SHong Zhang 778d2567f34SHong Zhang /*@C 779d2567f34SHong Zhang TSIRKSetNumStages - Set the number of stages of IRK scheme 780d2567f34SHong Zhang 781d2567f34SHong Zhang Logically collective 782d2567f34SHong Zhang 78302024617SSatish Balay Input Parameters: 784d2567f34SHong Zhang + ts - timestepping context 785d2567f34SHong Zhang - nstages - number of stages of IRK scheme 786d2567f34SHong Zhang 787d2567f34SHong Zhang Options Database: 788d2567f34SHong Zhang . -ts_irk_nstages <int>: Number of stages 789d2567f34SHong Zhang 790d2567f34SHong Zhang Level: intermediate 791d2567f34SHong Zhang 792d2567f34SHong Zhang .seealso: TSIRKGetNumStages(), TSIRK 793d2567f34SHong Zhang @*/ 794d2567f34SHong Zhang PetscErrorCode TSIRKSetNumStages(TS ts,PetscInt nstages) 795d2567f34SHong Zhang { 796d2567f34SHong Zhang PetscErrorCode ierr; 797d2567f34SHong Zhang 798d2567f34SHong Zhang PetscFunctionBegin; 799d2567f34SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 800d2567f34SHong Zhang ierr = PetscTryMethod(ts,"TSIRKSetNumStages_C",(TS,PetscInt),(ts,nstages));CHKERRQ(ierr); 801d2567f34SHong Zhang PetscFunctionReturn(0); 802d2567f34SHong Zhang } 803d2567f34SHong Zhang 804d2567f34SHong Zhang /*@C 805d2567f34SHong Zhang TSIRKGetNumStages - Get the number of stages of IRK scheme 806d2567f34SHong Zhang 807d2567f34SHong Zhang Logically collective 808d2567f34SHong Zhang 80902024617SSatish Balay Input Parameters: 810d2567f34SHong Zhang + ts - timestepping context 811d2567f34SHong Zhang - nstages - number of stages of IRK scheme 812d2567f34SHong Zhang 813d2567f34SHong Zhang Level: intermediate 814d2567f34SHong Zhang 815d2567f34SHong Zhang .seealso: TSIRKSetNumStages(), TSIRK 816d2567f34SHong Zhang @*/ 817d2567f34SHong Zhang PetscErrorCode TSIRKGetNumStages(TS ts,PetscInt *nstages) 818d2567f34SHong Zhang { 819d2567f34SHong Zhang PetscErrorCode ierr; 820d2567f34SHong Zhang 821d2567f34SHong Zhang PetscFunctionBegin; 822d2567f34SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 823d2567f34SHong Zhang PetscValidIntPointer(nstages,2); 824d2567f34SHong Zhang ierr = PetscTryMethod(ts,"TSIRKGetNumStages_C",(TS,PetscInt*),(ts,nstages));CHKERRQ(ierr); 825d2567f34SHong Zhang PetscFunctionReturn(0); 826d2567f34SHong Zhang } 827d2567f34SHong Zhang 828d2567f34SHong Zhang static PetscErrorCode TSIRKGetType_IRK(TS ts,TSIRKType *irktype) 829d2567f34SHong Zhang { 830d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 831d2567f34SHong Zhang 832d2567f34SHong Zhang PetscFunctionBegin; 833d2567f34SHong Zhang *irktype = irk->method_name; 834d2567f34SHong Zhang PetscFunctionReturn(0); 835d2567f34SHong Zhang } 836d2567f34SHong Zhang 837d2567f34SHong Zhang static PetscErrorCode TSIRKSetType_IRK(TS ts,TSIRKType irktype) 838d2567f34SHong Zhang { 839d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 840d2567f34SHong Zhang PetscErrorCode ierr,(*irkcreate)(TS); 841d2567f34SHong Zhang 842d2567f34SHong Zhang PetscFunctionBegin; 843d2567f34SHong Zhang if (irk->method_name) { 844d2567f34SHong Zhang ierr = PetscFree(irk->method_name);CHKERRQ(ierr); 845d2567f34SHong Zhang ierr = TSIRKTableauReset(ts);CHKERRQ(ierr); 846d2567f34SHong Zhang } 847d2567f34SHong Zhang ierr = PetscFunctionListFind(TSIRKList,irktype,&irkcreate);CHKERRQ(ierr); 848d2567f34SHong Zhang if (!irkcreate) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSIRK type \"%s\" given",irktype); 849d2567f34SHong Zhang ierr = (*irkcreate)(ts);CHKERRQ(ierr); 850d2567f34SHong Zhang ierr = PetscStrallocpy(irktype,&irk->method_name);CHKERRQ(ierr); 851d2567f34SHong Zhang PetscFunctionReturn(0); 852d2567f34SHong Zhang } 853d2567f34SHong Zhang 854d2567f34SHong Zhang static PetscErrorCode TSIRKSetNumStages_IRK(TS ts,PetscInt nstages) 855d2567f34SHong Zhang { 856d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 857d2567f34SHong Zhang 858d2567f34SHong Zhang PetscFunctionBegin; 859d2567f34SHong Zhang if (nstages<=0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"input argument, %d, out of range",nstages); 860d2567f34SHong Zhang irk->nstages = nstages; 861d2567f34SHong Zhang PetscFunctionReturn(0); 862d2567f34SHong Zhang } 863d2567f34SHong Zhang 864d2567f34SHong Zhang static PetscErrorCode TSIRKGetNumStages_IRK(TS ts,PetscInt *nstages) 865d2567f34SHong Zhang { 866d2567f34SHong Zhang TS_IRK *irk = (TS_IRK*)ts->data; 867d2567f34SHong Zhang 868d2567f34SHong Zhang PetscFunctionBegin; 869d2567f34SHong Zhang PetscValidIntPointer(nstages,2); 870d2567f34SHong Zhang *nstages = irk->nstages; 871d2567f34SHong Zhang PetscFunctionReturn(0); 872d2567f34SHong Zhang } 873d2567f34SHong Zhang 874d2567f34SHong Zhang static PetscErrorCode TSDestroy_IRK(TS ts) 875d2567f34SHong Zhang { 876d2567f34SHong Zhang PetscErrorCode ierr; 877d2567f34SHong Zhang 878d2567f34SHong Zhang PetscFunctionBegin; 879d2567f34SHong Zhang ierr = TSReset_IRK(ts);CHKERRQ(ierr); 880d2567f34SHong Zhang if (ts->dm) { 881d2567f34SHong Zhang ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSIRK,DMRestrictHook_TSIRK,ts);CHKERRQ(ierr); 882d2567f34SHong Zhang ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSIRK,DMSubDomainRestrictHook_TSIRK,ts);CHKERRQ(ierr); 883d2567f34SHong Zhang } 884d2567f34SHong Zhang ierr = PetscFree(ts->data);CHKERRQ(ierr); 885d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetType_C",NULL);CHKERRQ(ierr); 886d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetType_C",NULL);CHKERRQ(ierr); 887d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetNumStages_C",NULL);CHKERRQ(ierr); 888d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetNumStages_C",NULL);CHKERRQ(ierr); 889d2567f34SHong Zhang PetscFunctionReturn(0); 890d2567f34SHong Zhang } 891d2567f34SHong Zhang 892d2567f34SHong Zhang /*MC 893d2567f34SHong Zhang TSIRK - ODE and DAE solver using Implicit Runge-Kutta schemes 894d2567f34SHong Zhang 895d2567f34SHong Zhang Notes: 896d2567f34SHong Zhang 897d2567f34SHong Zhang TSIRK uses the sparse Kronecker product matrix implementation of MATKAIJ to achieve good arithmetic intensity. 898d2567f34SHong Zhang 899d2567f34SHong Zhang The default is TSIRK3, it can be changed with TSIRKSetType() or -ts_irk_type 900d2567f34SHong Zhang 901d2567f34SHong Zhang If the equation is implicit or a DAE, then TSSetEquationType() needs to be set accordingly. Refer to the manual for further information. 902d2567f34SHong Zhang 903d2567f34SHong Zhang Consider trying TSROSW if the stiff part is linear or weakly nonlinear. 904d2567f34SHong Zhang 905d2567f34SHong Zhang Level: beginner 906d2567f34SHong Zhang 907d2567f34SHong Zhang .seealso: TSCreate(), TS, TSSetType(), TSIRKSetType(), TSIRKGetType(), 908d2567f34SHong Zhang TSIRK1BEE, TSIRK2C, TSIRK2D, TSIRK2E, TSIRK3, TSIRKL2, TSIRKA2, TSIRKARS122, 909d2567f34SHong Zhang TSIRK4, TSIRK5, TSIRKPRSSP2, TSIRKARS443, TSIRKBPR3, TSIRKType, TSIRKRegister() 910d2567f34SHong Zhang 911d2567f34SHong Zhang M*/ 912d2567f34SHong Zhang PETSC_EXTERN PetscErrorCode TSCreate_IRK(TS ts) 913d2567f34SHong Zhang { 914d2567f34SHong Zhang TS_IRK *irk; 915d2567f34SHong Zhang PetscErrorCode ierr; 916d2567f34SHong Zhang 917d2567f34SHong Zhang PetscFunctionBegin; 918d2567f34SHong Zhang ierr = TSIRKInitializePackage();CHKERRQ(ierr); 919d2567f34SHong Zhang 920d2567f34SHong Zhang ts->ops->reset = TSReset_IRK; 921d2567f34SHong Zhang ts->ops->destroy = TSDestroy_IRK; 922d2567f34SHong Zhang ts->ops->view = TSView_IRK; 923d2567f34SHong Zhang ts->ops->load = TSLoad_IRK; 924d2567f34SHong Zhang ts->ops->setup = TSSetUp_IRK; 925d2567f34SHong Zhang ts->ops->step = TSStep_IRK; 926d2567f34SHong Zhang ts->ops->interpolate = TSInterpolate_IRK; 927d2567f34SHong Zhang ts->ops->evaluatestep = TSEvaluateStep_IRK; 928d2567f34SHong Zhang ts->ops->rollback = TSRollBack_IRK; 929d2567f34SHong Zhang ts->ops->setfromoptions = TSSetFromOptions_IRK; 930d2567f34SHong Zhang ts->ops->snesfunction = SNESTSFormFunction_IRK; 931d2567f34SHong Zhang ts->ops->snesjacobian = SNESTSFormJacobian_IRK; 932d2567f34SHong Zhang 933d2567f34SHong Zhang ts->usessnes = PETSC_TRUE; 934d2567f34SHong Zhang 935d2567f34SHong Zhang ierr = PetscNewLog(ts,&irk);CHKERRQ(ierr); 936d2567f34SHong Zhang ts->data = (void*)irk; 937d2567f34SHong Zhang 938d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetType_C",TSIRKSetType_IRK);CHKERRQ(ierr); 939d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetType_C",TSIRKGetType_IRK);CHKERRQ(ierr); 940d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetNumStages_C",TSIRKSetNumStages_IRK);CHKERRQ(ierr); 941d2567f34SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetNumStages_C",TSIRKGetNumStages_IRK);CHKERRQ(ierr); 942d2567f34SHong Zhang /* 3-stage IRK_Gauss is the default */ 943d2567f34SHong Zhang ierr = PetscNew(&irk->tableau);CHKERRQ(ierr); 944d2567f34SHong Zhang irk->nstages = 3; 945d2567f34SHong Zhang ierr = TSIRKSetType(ts,TSIRKDefault);CHKERRQ(ierr); 946d2567f34SHong Zhang PetscFunctionReturn(0); 947d2567f34SHong Zhang } 948