1*0bb9014aSEmil Constantinescu /* 2*0bb9014aSEmil Constantinescu * eimex.c 3*0bb9014aSEmil Constantinescu * 4*0bb9014aSEmil Constantinescu * Created on: Jun 21, 2012 5*0bb9014aSEmil Constantinescu * Written by Hong Zhang (zhang@vt.edu), Virginia Tech 6*0bb9014aSEmil Constantinescu * Emil Constantinescu (emconsta@mcs.anl.gov), Argonne National Laboratory 7*0bb9014aSEmil Constantinescu */ 8*0bb9014aSEmil Constantinescu /* 9*0bb9014aSEmil Constantinescu Code for timestepping with Extrapolated IMEX methods 10*0bb9014aSEmil Constantinescu 11*0bb9014aSEmil Constantinescu Notes: 12*0bb9014aSEmil Constantinescu The general system is written as 13*0bb9014aSEmil Constantinescu 14*0bb9014aSEmil Constantinescu G(t,X,Xdot) = F(t,X) 15*0bb9014aSEmil Constantinescu 16*0bb9014aSEmil Constantinescu where G represents the stiff part of the physics and F represents the non-stiff part. 17*0bb9014aSEmil Constantinescu This method is designed to be linearly implicit on G and can use an approximate and lagged Jacobian. 18*0bb9014aSEmil Constantinescu 19*0bb9014aSEmil Constantinescu Another common form for the system is 20*0bb9014aSEmil Constantinescu 21*0bb9014aSEmil Constantinescu y'=f(x)+g(x) 22*0bb9014aSEmil Constantinescu 23*0bb9014aSEmil Constantinescu The relationship between F,G and f,g is 24*0bb9014aSEmil Constantinescu 25*0bb9014aSEmil Constantinescu G = y'-g(x), F = f(x) 26*0bb9014aSEmil Constantinescu 27*0bb9014aSEmil Constantinescu References 28*0bb9014aSEmil Constantinescu E. Constantinescu and A. Sandu, Extrapolated implicit-explicit time stepping, SIAM Journal on Scientific 29*0bb9014aSEmil Constantinescu Computing, 31 (2010), pp. 4452–4477. 30*0bb9014aSEmil Constantinescu 31*0bb9014aSEmil Constantinescu */ 32*0bb9014aSEmil Constantinescu #include <petsc-private/tsimpl.h> /*I "petscts.h" I*/ 33*0bb9014aSEmil Constantinescu 34*0bb9014aSEmil Constantinescu static const PetscInt TSEIMEXDefault = 3; 35*0bb9014aSEmil Constantinescu 36*0bb9014aSEmil Constantinescu typedef struct { 37*0bb9014aSEmil Constantinescu PetscInt row_ind; /* Return the term T[row_ind][col_ind]*/ 38*0bb9014aSEmil Constantinescu PetscInt col_ind; /* Return the term T[row_ind][col_ind]*/ 39*0bb9014aSEmil Constantinescu PetscInt nstages; /* Numbers of stages in current scheme*/ 40*0bb9014aSEmil Constantinescu PetscInt max_rows; /* Maximum number of rows */ 41*0bb9014aSEmil Constantinescu PetscInt *N; /* Harmonic sequence N[max_rows] */ 42*0bb9014aSEmil Constantinescu Vec Y; /* States computed during the step, used to complete the step */ 43*0bb9014aSEmil Constantinescu Vec Z; /* For shift*(Y-Z) */ 44*0bb9014aSEmil Constantinescu Vec *T; /* Working table, size determined by nstages */ 45*0bb9014aSEmil Constantinescu Vec YdotRHS; /* f(x) Work vector holding YdotRHS during residual evaluation */ 46*0bb9014aSEmil Constantinescu Vec YdotI; /* xdot-g(x) Work vector holding YdotI = G(t,x,xdot) when xdot =0 */ 47*0bb9014aSEmil Constantinescu Vec Ydot; /* f(x)+g(x) Work vector*/ 48*0bb9014aSEmil Constantinescu Vec VecSolPrev; /* Work vector holding the solution from the previous step (used for interpolation)*/ 49*0bb9014aSEmil Constantinescu // PetscScalar *work; /* Scalar work space of length number of stages, used to prepare VecMAXPY() */ 50*0bb9014aSEmil Constantinescu PetscReal shift; 51*0bb9014aSEmil Constantinescu PetscReal ctime; 52*0bb9014aSEmil Constantinescu PetscBool recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */ 53*0bb9014aSEmil Constantinescu PetscBool ord_adapt; /*order adapativity*/ 54*0bb9014aSEmil Constantinescu TSStepStatus status; 55*0bb9014aSEmil Constantinescu } TS_EIMEX; 56*0bb9014aSEmil Constantinescu 57*0bb9014aSEmil Constantinescu /* This function is pure */ 58*0bb9014aSEmil Constantinescu static PetscInt Map(PetscInt i, PetscInt j, PetscInt s) 59*0bb9014aSEmil Constantinescu { 60*0bb9014aSEmil Constantinescu return ((2*s-j+1)*j/2+i-j); 61*0bb9014aSEmil Constantinescu } 62*0bb9014aSEmil Constantinescu 63*0bb9014aSEmil Constantinescu 64*0bb9014aSEmil Constantinescu #undef __FUNCT__ 65*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEvaluateStep_EIMEX" 66*0bb9014aSEmil Constantinescu static PetscErrorCode TSEvaluateStep_EIMEX(TS ts,PetscInt order,Vec X,PetscBool *done) 67*0bb9014aSEmil Constantinescu { 68*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 69*0bb9014aSEmil Constantinescu const PetscInt ns = ext->nstages; 70*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 71*0bb9014aSEmil Constantinescu PetscFunctionBegin; 72*0bb9014aSEmil Constantinescu ierr = VecCopy(ext->T[Map(ext->row_ind,ext->col_ind,ns)],X);CHKERRQ(ierr); 73*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 74*0bb9014aSEmil Constantinescu } 75*0bb9014aSEmil Constantinescu 76*0bb9014aSEmil Constantinescu 77*0bb9014aSEmil Constantinescu #undef __FUNCT__ 78*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSStage_EIMEX" 79*0bb9014aSEmil Constantinescu static PetscErrorCode TSStage_EIMEX(TS ts,PetscInt istage) 80*0bb9014aSEmil Constantinescu { 81*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 82*0bb9014aSEmil Constantinescu PetscReal h; 83*0bb9014aSEmil Constantinescu Vec Y=ext->Y, Z=ext->Z; 84*0bb9014aSEmil Constantinescu SNES snes; 85*0bb9014aSEmil Constantinescu TSAdapt adapt; 86*0bb9014aSEmil Constantinescu PetscInt i,its,lits; 87*0bb9014aSEmil Constantinescu PetscBool accept; 88*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 89*0bb9014aSEmil Constantinescu 90*0bb9014aSEmil Constantinescu PetscFunctionBegin; 91*0bb9014aSEmil Constantinescu ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 92*0bb9014aSEmil Constantinescu h = ts->time_step/ext->N[istage];/*step size for the istage-th stage*/ 93*0bb9014aSEmil Constantinescu ext->shift = 1./h; 94*0bb9014aSEmil Constantinescu ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */ 95*0bb9014aSEmil Constantinescu ierr = VecCopy(ext->VecSolPrev,Y);CHKERRQ(ierr); /*Take the previous solution as intial step*/ 96*0bb9014aSEmil Constantinescu 97*0bb9014aSEmil Constantinescu for(i=0; i<ext->N[istage]; i++){ 98*0bb9014aSEmil Constantinescu ext->ctime = ts->ptime + h*i; 99*0bb9014aSEmil Constantinescu ierr = VecCopy(Y,Z);CHKERRQ(ierr);/*Save the solution of the previous substep*/ 100*0bb9014aSEmil Constantinescu ierr = SNESSolve(snes,PETSC_NULL,Y);CHKERRQ(ierr); 101*0bb9014aSEmil Constantinescu ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 102*0bb9014aSEmil Constantinescu ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 103*0bb9014aSEmil Constantinescu ts->snes_its += its; ts->ksp_its += lits; 104*0bb9014aSEmil Constantinescu ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 105*0bb9014aSEmil Constantinescu ierr = TSAdaptCheckStage(adapt,ts,&accept);CHKERRQ(ierr); 106*0bb9014aSEmil Constantinescu } 107*0bb9014aSEmil Constantinescu 108*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 109*0bb9014aSEmil Constantinescu } 110*0bb9014aSEmil Constantinescu 111*0bb9014aSEmil Constantinescu 112*0bb9014aSEmil Constantinescu #undef __FUNCT__ 113*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSStep_EIMEX" 114*0bb9014aSEmil Constantinescu static PetscErrorCode TSStep_EIMEX(TS ts) 115*0bb9014aSEmil Constantinescu { 116*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 117*0bb9014aSEmil Constantinescu const PetscInt ns = ext->nstages; 118*0bb9014aSEmil Constantinescu Vec *T=ext->T, Y=ext->Y; 119*0bb9014aSEmil Constantinescu 120*0bb9014aSEmil Constantinescu SNES snes; 121*0bb9014aSEmil Constantinescu PetscInt i,j; 122*0bb9014aSEmil Constantinescu PetscBool accept = PETSC_FALSE; 123*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 124*0bb9014aSEmil Constantinescu PetscReal alpha,local_error; 125*0bb9014aSEmil Constantinescu PetscFunctionBegin; 126*0bb9014aSEmil Constantinescu 127*0bb9014aSEmil Constantinescu ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 128*0bb9014aSEmil Constantinescu ierr = SNESSetType(snes,"ksponly"); CHKERRQ(ierr); 129*0bb9014aSEmil Constantinescu ext->status = TS_STEP_INCOMPLETE; 130*0bb9014aSEmil Constantinescu 131*0bb9014aSEmil Constantinescu ierr = VecCopy(ts->vec_sol,ext->VecSolPrev);CHKERRQ(ierr); 132*0bb9014aSEmil Constantinescu 133*0bb9014aSEmil Constantinescu /* Apply n_j steps of the base method to obtain solutions of T(j,1),1<=j<=s*/ 134*0bb9014aSEmil Constantinescu for(j=0; j<ns; j++){ 135*0bb9014aSEmil Constantinescu ierr = TSStage_EIMEX(ts,j);CHKERRQ(ierr); 136*0bb9014aSEmil Constantinescu ierr = VecCopy(Y,T[j]); CHKERRQ(ierr); 137*0bb9014aSEmil Constantinescu } 138*0bb9014aSEmil Constantinescu 139*0bb9014aSEmil Constantinescu for(i=1;i<ns;i++){ 140*0bb9014aSEmil Constantinescu for(j=i;j<ns;j++){ 141*0bb9014aSEmil Constantinescu alpha = -(PetscReal)ext->N[j]/ext->N[j-i]; 142*0bb9014aSEmil Constantinescu ierr = VecAXPBYPCZ(T[Map(j,i,ns)],alpha,1.0,0,T[Map(j,i-1,ns)], 143*0bb9014aSEmil Constantinescu T[Map(j-1,i-1,ns)]);/*T[j][i]=alpha*T[j][i-1]+T[j-1][i-1]*/ 144*0bb9014aSEmil Constantinescu alpha = 1.0/(1.0 + alpha); 145*0bb9014aSEmil Constantinescu ierr = VecScale(T[Map(j,i,ns)],alpha);CHKERRQ(ierr); 146*0bb9014aSEmil Constantinescu } 147*0bb9014aSEmil Constantinescu } 148*0bb9014aSEmil Constantinescu 149*0bb9014aSEmil Constantinescu ierr = TSEvaluateStep(ts,ns,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);/*update ts solution */ 150*0bb9014aSEmil Constantinescu 151*0bb9014aSEmil Constantinescu if(ext->ord_adapt && ext->nstages < ext->max_rows){ 152*0bb9014aSEmil Constantinescu accept = PETSC_FALSE; 153*0bb9014aSEmil Constantinescu while(!accept && ext->nstages < ext->max_rows){ 154*0bb9014aSEmil Constantinescu ierr = TSErrorNormWRMS(ts,T[Map(ext->nstages-1,ext->nstages-2,ext->nstages)],&local_error);CHKERRQ(ierr); 155*0bb9014aSEmil Constantinescu accept = (local_error < 1.0)? PETSC_TRUE : PETSC_FALSE; 156*0bb9014aSEmil Constantinescu 157*0bb9014aSEmil Constantinescu if(!accept){/* add one more stage*/ 158*0bb9014aSEmil Constantinescu ierr = TSStage_EIMEX(ts,ext->nstages);CHKERRQ(ierr); 159*0bb9014aSEmil Constantinescu ext->nstages++; ext->row_ind++; ext->col_ind++; 160*0bb9014aSEmil Constantinescu /*T table need to be recycled*/ 161*0bb9014aSEmil Constantinescu ierr = VecDuplicateVecs(ts->vec_sol,(1+ext->nstages)*ext->nstages/2,&ext->T);CHKERRQ(ierr); 162*0bb9014aSEmil Constantinescu for(i=0; i<ext->nstages-1; i++){ 163*0bb9014aSEmil Constantinescu for(j=0; j<=i; j++){ 164*0bb9014aSEmil Constantinescu ierr = VecCopy(T[Map(i,j,ext->nstages-1)],ext->T[Map(i,j,ext->nstages)]);CHKERRQ(ierr); 165*0bb9014aSEmil Constantinescu } 166*0bb9014aSEmil Constantinescu } 167*0bb9014aSEmil Constantinescu ierr = VecDestroyVecs(ext->nstages*(ext->nstages-1)/2,&T);CHKERRQ(ierr); 168*0bb9014aSEmil Constantinescu T = ext->T; /*reset the pointer*/ 169*0bb9014aSEmil Constantinescu /*recycling finished, store the new solution*/ 170*0bb9014aSEmil Constantinescu ierr = VecCopy(Y,T[ext->nstages-1]); CHKERRQ(ierr); 171*0bb9014aSEmil Constantinescu /*extrapolation for the newly added stage*/ 172*0bb9014aSEmil Constantinescu for(i=1;i<ext->nstages;i++){ 173*0bb9014aSEmil Constantinescu alpha = -(PetscReal)ext->N[ext->nstages-1]/ext->N[ext->nstages-1-i]; 174*0bb9014aSEmil Constantinescu ierr = VecAXPBYPCZ(T[Map(ext->nstages-1,i,ext->nstages)],alpha,1.0,0,T[Map(ext->nstages-1,i-1,ext->nstages)],T[Map(ext->nstages-1-1,i-1,ext->nstages)]);/*T[ext->nstages-1][i]=alpha*T[ext->nstages-1][i-1]+T[ext->nstages-1-1][i-1]*/ 175*0bb9014aSEmil Constantinescu alpha = 1.0/(1.0 + alpha); 176*0bb9014aSEmil Constantinescu ierr = VecScale(T[Map(ext->nstages-1,i,ext->nstages)],alpha);CHKERRQ(ierr); 177*0bb9014aSEmil Constantinescu } 178*0bb9014aSEmil Constantinescu /*update ts solution */ 179*0bb9014aSEmil Constantinescu ierr = TSEvaluateStep(ts,ext->nstages,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr); 180*0bb9014aSEmil Constantinescu }/*end if !accept*/ 181*0bb9014aSEmil Constantinescu }/*end while*/ 182*0bb9014aSEmil Constantinescu 183*0bb9014aSEmil Constantinescu if(ext->nstages == ext->max_rows){ 184*0bb9014aSEmil Constantinescu ierr = PetscInfo(ts,"Max number of rows has been used\n");CHKERRQ(ierr); 185*0bb9014aSEmil Constantinescu } 186*0bb9014aSEmil Constantinescu }/*end if ext->ord_adapt*/ 187*0bb9014aSEmil Constantinescu 188*0bb9014aSEmil Constantinescu ts->ptime += ts->time_step; 189*0bb9014aSEmil Constantinescu ts->steps++; 190*0bb9014aSEmil Constantinescu ext->status = TS_STEP_COMPLETE; 191*0bb9014aSEmil Constantinescu 192*0bb9014aSEmil Constantinescu if (ext->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED; 193*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 194*0bb9014aSEmil Constantinescu } 195*0bb9014aSEmil Constantinescu 196*0bb9014aSEmil Constantinescu 197*0bb9014aSEmil Constantinescu /*cubic Hermit spline*/ 198*0bb9014aSEmil Constantinescu #undef __FUNCT__ 199*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSInterpolate_EIMEX" 200*0bb9014aSEmil Constantinescu static PetscErrorCode TSInterpolate_EIMEX(TS ts,PetscReal itime,Vec X) 201*0bb9014aSEmil Constantinescu { 202*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 203*0bb9014aSEmil Constantinescu PetscReal t,a,b; 204*0bb9014aSEmil Constantinescu Vec Y0=ext->VecSolPrev,Y1=ext->Y, 205*0bb9014aSEmil Constantinescu Ydot=ext->Ydot,YdotI=ext->YdotI; 206*0bb9014aSEmil Constantinescu const PetscReal h = ts->time_step_prev; 207*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 208*0bb9014aSEmil Constantinescu PetscScalar *x; 209*0bb9014aSEmil Constantinescu PetscFunctionBegin; 210*0bb9014aSEmil Constantinescu t = (itime -ts->ptime + h)/h; 211*0bb9014aSEmil Constantinescu /*YdotI = -f(x)-g(x)*/ 212*0bb9014aSEmil Constantinescu 213*0bb9014aSEmil Constantinescu ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); 214*0bb9014aSEmil Constantinescu ierr = TSComputeIFunction(ts,ts->ptime-h,Y0,Ydot,YdotI,PETSC_FALSE);CHKERRQ(ierr); 215*0bb9014aSEmil Constantinescu 216*0bb9014aSEmil Constantinescu a = 2.0*pow(t,3) - 3.0*t*t + 1.0; 217*0bb9014aSEmil Constantinescu b = -(pow(t,3) - 2.0*t*t + t)*h; 218*0bb9014aSEmil Constantinescu ierr = VecAXPBYPCZ(X,a,b,0.0,Y0,YdotI);CHKERRQ(ierr); 219*0bb9014aSEmil Constantinescu 220*0bb9014aSEmil Constantinescu ierr = TSComputeIFunction(ts,ts->ptime,Y1,Ydot,YdotI,PETSC_FALSE);CHKERRQ(ierr); 221*0bb9014aSEmil Constantinescu a = -2.0*pow(t,3)+3.0*t*t; 222*0bb9014aSEmil Constantinescu b = -(pow(t,3) - t*t)*h; 223*0bb9014aSEmil Constantinescu ierr = VecAXPBYPCZ(X,a,b,1.0,Y1,YdotI);CHKERRQ(ierr); 224*0bb9014aSEmil Constantinescu 225*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 226*0bb9014aSEmil Constantinescu } 227*0bb9014aSEmil Constantinescu 228*0bb9014aSEmil Constantinescu 229*0bb9014aSEmil Constantinescu #undef __FUNCT__ 230*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSReset_EIMEX" 231*0bb9014aSEmil Constantinescu static PetscErrorCode TSReset_EIMEX(TS ts) 232*0bb9014aSEmil Constantinescu { 233*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 234*0bb9014aSEmil Constantinescu PetscInt ns; 235*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 236*0bb9014aSEmil Constantinescu 237*0bb9014aSEmil Constantinescu PetscFunctionBegin; 238*0bb9014aSEmil Constantinescu ns = ext->nstages; 239*0bb9014aSEmil Constantinescu ierr = VecDestroyVecs((1+ns)*ns/2,&ext->T);CHKERRQ(ierr); 240*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->Y);CHKERRQ(ierr); 241*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->Z);CHKERRQ(ierr); 242*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->YdotRHS);CHKERRQ(ierr); 243*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->YdotI);CHKERRQ(ierr); 244*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->Ydot);CHKERRQ(ierr); 245*0bb9014aSEmil Constantinescu ierr = VecDestroy(&ext->VecSolPrev);CHKERRQ(ierr); 246*0bb9014aSEmil Constantinescu ierr = PetscFree(ext->N);CHKERRQ(ierr); 247*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 248*0bb9014aSEmil Constantinescu } 249*0bb9014aSEmil Constantinescu 250*0bb9014aSEmil Constantinescu #undef __FUNCT__ 251*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSDestroy_EIMEX" 252*0bb9014aSEmil Constantinescu static PetscErrorCode TSDestroy_EIMEX(TS ts) 253*0bb9014aSEmil Constantinescu { 254*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 255*0bb9014aSEmil Constantinescu 256*0bb9014aSEmil Constantinescu PetscFunctionBegin; 257*0bb9014aSEmil Constantinescu ierr = TSReset_EIMEX(ts);CHKERRQ(ierr); 258*0bb9014aSEmil Constantinescu ierr = PetscFree(ts->data);CHKERRQ(ierr); 259*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetMaxRows_C","",PETSC_NULL);CHKERRQ(ierr); 260*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetRowCol_C","",PETSC_NULL);CHKERRQ(ierr); 261*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetOrdAdapt_C","",PETSC_NULL);CHKERRQ(ierr); 262*0bb9014aSEmil Constantinescu 263*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 264*0bb9014aSEmil Constantinescu } 265*0bb9014aSEmil Constantinescu 266*0bb9014aSEmil Constantinescu 267*0bb9014aSEmil Constantinescu #undef __FUNCT__ 268*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXGetVecs" 269*0bb9014aSEmil Constantinescu static PetscErrorCode TSEIMEXGetVecs(TS ts,DM dm,Vec *Z,Vec *Ydot,Vec *YdotI, Vec *YdotRHS) 270*0bb9014aSEmil Constantinescu { 271*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 272*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 273*0bb9014aSEmil Constantinescu 274*0bb9014aSEmil Constantinescu PetscFunctionBegin; 275*0bb9014aSEmil Constantinescu if (Z) { 276*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 277*0bb9014aSEmil Constantinescu ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_Z",Z);CHKERRQ(ierr); 278*0bb9014aSEmil Constantinescu } else *Z = ext->Z; 279*0bb9014aSEmil Constantinescu } 280*0bb9014aSEmil Constantinescu if (Ydot) { 281*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 282*0bb9014aSEmil Constantinescu ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_Ydot",Ydot);CHKERRQ(ierr); 283*0bb9014aSEmil Constantinescu } else *Ydot = ext->Ydot; 284*0bb9014aSEmil Constantinescu } 285*0bb9014aSEmil Constantinescu if (YdotI) { 286*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 287*0bb9014aSEmil Constantinescu ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_YdotI",YdotI);CHKERRQ(ierr); 288*0bb9014aSEmil Constantinescu } else *YdotI = ext->YdotI; 289*0bb9014aSEmil Constantinescu } 290*0bb9014aSEmil Constantinescu if (YdotRHS) { 291*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 292*0bb9014aSEmil Constantinescu ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_YdotRHS",YdotRHS);CHKERRQ(ierr); 293*0bb9014aSEmil Constantinescu } else *YdotRHS = ext->YdotRHS; 294*0bb9014aSEmil Constantinescu } 295*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 296*0bb9014aSEmil Constantinescu } 297*0bb9014aSEmil Constantinescu 298*0bb9014aSEmil Constantinescu 299*0bb9014aSEmil Constantinescu #undef __FUNCT__ 300*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXRestoreVecs" 301*0bb9014aSEmil Constantinescu static PetscErrorCode TSEIMEXRestoreVecs(TS ts,DM dm,Vec *Z,Vec *Ydot,Vec *YdotI,Vec *YdotRHS) 302*0bb9014aSEmil Constantinescu { 303*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 304*0bb9014aSEmil Constantinescu 305*0bb9014aSEmil Constantinescu PetscFunctionBegin; 306*0bb9014aSEmil Constantinescu if (Z) { 307*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 308*0bb9014aSEmil Constantinescu ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_Z",Z);CHKERRQ(ierr); 309*0bb9014aSEmil Constantinescu } 310*0bb9014aSEmil Constantinescu } 311*0bb9014aSEmil Constantinescu if (Ydot) { 312*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 313*0bb9014aSEmil Constantinescu ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_Ydot",Ydot);CHKERRQ(ierr); 314*0bb9014aSEmil Constantinescu } 315*0bb9014aSEmil Constantinescu } 316*0bb9014aSEmil Constantinescu if (YdotI) { 317*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 318*0bb9014aSEmil Constantinescu ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_YdotI",YdotI);CHKERRQ(ierr); 319*0bb9014aSEmil Constantinescu } 320*0bb9014aSEmil Constantinescu } 321*0bb9014aSEmil Constantinescu if (YdotRHS) { 322*0bb9014aSEmil Constantinescu if (dm && dm != ts->dm) { 323*0bb9014aSEmil Constantinescu ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_YdotRHS",YdotRHS);CHKERRQ(ierr); 324*0bb9014aSEmil Constantinescu } 325*0bb9014aSEmil Constantinescu } 326*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 327*0bb9014aSEmil Constantinescu } 328*0bb9014aSEmil Constantinescu 329*0bb9014aSEmil Constantinescu 330*0bb9014aSEmil Constantinescu /* 331*0bb9014aSEmil Constantinescu This defines the nonlinear equation that is to be solved with SNES 332*0bb9014aSEmil Constantinescu Fn[t0+Theta*dt, U, (U-U0)*shift] = 0 333*0bb9014aSEmil Constantinescu In the case of Backward Euler, Fn = (U-U0)/h-g(t1,U)) 334*0bb9014aSEmil Constantinescu Since FormIFunction calculates G = ydot - g(t,y), ydot will be set to (U-U0)/h 335*0bb9014aSEmil Constantinescu */ 336*0bb9014aSEmil Constantinescu #undef __FUNCT__ 337*0bb9014aSEmil Constantinescu #define __FUNCT__ "SNESTSFormFunction_EIMEX" 338*0bb9014aSEmil Constantinescu static PetscErrorCode SNESTSFormFunction_EIMEX(SNES snes,Vec X,Vec G,TS ts) 339*0bb9014aSEmil Constantinescu { 340*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 341*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 342*0bb9014aSEmil Constantinescu Vec Ydot,Z; 343*0bb9014aSEmil Constantinescu DM dm,dmsave; 344*0bb9014aSEmil Constantinescu 345*0bb9014aSEmil Constantinescu PetscFunctionBegin; 346*0bb9014aSEmil Constantinescu ierr = VecZeroEntries(G);CHKERRQ(ierr); 347*0bb9014aSEmil Constantinescu 348*0bb9014aSEmil Constantinescu ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 349*0bb9014aSEmil Constantinescu ierr = TSEIMEXGetVecs(ts,dm,&Z,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 350*0bb9014aSEmil Constantinescu ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); 351*0bb9014aSEmil Constantinescu dmsave = ts->dm; 352*0bb9014aSEmil Constantinescu ts->dm = dm; 353*0bb9014aSEmil Constantinescu ierr = TSComputeIFunction(ts,ext->ctime,X,Ydot,G,PETSC_FALSE);CHKERRQ(ierr); 354*0bb9014aSEmil Constantinescu /* PETSC_FALSE indicates non-imex, adding explicit RHS to the implicit I function. */ 355*0bb9014aSEmil Constantinescu ierr = VecCopy(G,Ydot);CHKERRQ(ierr); 356*0bb9014aSEmil Constantinescu ts->dm = dmsave; 357*0bb9014aSEmil Constantinescu ierr = TSEIMEXRestoreVecs(ts,dm,&Z,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 358*0bb9014aSEmil Constantinescu 359*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 360*0bb9014aSEmil Constantinescu } 361*0bb9014aSEmil Constantinescu 362*0bb9014aSEmil Constantinescu /* 363*0bb9014aSEmil Constantinescu This defined the Jacobian matrix for SNES. Jn = (I/h-g'(t,y)) 364*0bb9014aSEmil Constantinescu */ 365*0bb9014aSEmil Constantinescu #undef __FUNCT__ 366*0bb9014aSEmil Constantinescu #define __FUNCT__ "SNESTSFormJacobian_EIMEX" 367*0bb9014aSEmil Constantinescu static PetscErrorCode SNESTSFormJacobian_EIMEX(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts) 368*0bb9014aSEmil Constantinescu { 369*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 370*0bb9014aSEmil Constantinescu Vec Ydot; 371*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 372*0bb9014aSEmil Constantinescu DM dm,dmsave; 373*0bb9014aSEmil Constantinescu PetscFunctionBegin; 374*0bb9014aSEmil Constantinescu ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 375*0bb9014aSEmil Constantinescu ierr = TSEIMEXGetVecs(ts,dm,PETSC_NULL,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 376*0bb9014aSEmil Constantinescu /* ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);*/ 377*0bb9014aSEmil Constantinescu /* ext->Ydot have already been computed in SNESTSFormFunction_EIMEX (SNES guarantees this) */ 378*0bb9014aSEmil Constantinescu dmsave = ts->dm; 379*0bb9014aSEmil Constantinescu ts->dm = dm; 380*0bb9014aSEmil Constantinescu ierr = TSComputeIJacobian(ts,ts->ptime,X,Ydot,ext->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr); 381*0bb9014aSEmil Constantinescu ts->dm = dmsave; 382*0bb9014aSEmil Constantinescu ierr = TSEIMEXRestoreVecs(ts,dm,PETSC_NULL,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 383*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 384*0bb9014aSEmil Constantinescu } 385*0bb9014aSEmil Constantinescu 386*0bb9014aSEmil Constantinescu #undef __FUNCT__ 387*0bb9014aSEmil Constantinescu #define __FUNCT__ "DMCoarsenHook_TSEIMEX" 388*0bb9014aSEmil Constantinescu static PetscErrorCode DMCoarsenHook_TSEIMEX(DM fine,DM coarse,void *ctx) 389*0bb9014aSEmil Constantinescu { 390*0bb9014aSEmil Constantinescu 391*0bb9014aSEmil Constantinescu PetscFunctionBegin; 392*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 393*0bb9014aSEmil Constantinescu } 394*0bb9014aSEmil Constantinescu 395*0bb9014aSEmil Constantinescu #undef __FUNCT__ 396*0bb9014aSEmil Constantinescu #define __FUNCT__ "DMRestrictHook_TSEIMEX" 397*0bb9014aSEmil Constantinescu static PetscErrorCode DMRestrictHook_TSEIMEX(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 398*0bb9014aSEmil Constantinescu { 399*0bb9014aSEmil Constantinescu TS ts = (TS)ctx; 400*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 401*0bb9014aSEmil Constantinescu Vec Z,Z_c; 402*0bb9014aSEmil Constantinescu 403*0bb9014aSEmil Constantinescu PetscFunctionBegin; 404*0bb9014aSEmil Constantinescu ierr = TSEIMEXGetVecs(ts,fine,&Z,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 405*0bb9014aSEmil Constantinescu ierr = TSEIMEXGetVecs(ts,coarse,&Z_c,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 406*0bb9014aSEmil Constantinescu ierr = MatRestrict(restrct,Z,Z_c);CHKERRQ(ierr); 407*0bb9014aSEmil Constantinescu ierr = VecPointwiseMult(Z_c,rscale,Z_c);CHKERRQ(ierr); 408*0bb9014aSEmil Constantinescu ierr = TSEIMEXRestoreVecs(ts,fine,&Z,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 409*0bb9014aSEmil Constantinescu ierr = TSEIMEXRestoreVecs(ts,coarse,&Z_c,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 410*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 411*0bb9014aSEmil Constantinescu } 412*0bb9014aSEmil Constantinescu 413*0bb9014aSEmil Constantinescu 414*0bb9014aSEmil Constantinescu #undef __FUNCT__ 415*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSSetUp_EIMEX" 416*0bb9014aSEmil Constantinescu static PetscErrorCode TSSetUp_EIMEX(TS ts) 417*0bb9014aSEmil Constantinescu { 418*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 419*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 420*0bb9014aSEmil Constantinescu DM dm; 421*0bb9014aSEmil Constantinescu PetscFunctionBegin; 422*0bb9014aSEmil Constantinescu 423*0bb9014aSEmil Constantinescu if (!ext->N){ /*ext->max_rows not set*/ 424*0bb9014aSEmil Constantinescu ierr = TSEIMEXSetMaxRows(ts,TSEIMEXDefault);CHKERRQ(ierr); 425*0bb9014aSEmil Constantinescu } 426*0bb9014aSEmil Constantinescu if(-1 == ext->row_ind && -1 == ext->col_ind){ 427*0bb9014aSEmil Constantinescu ierr = TSEIMEXSetRowCol(ts,ext->max_rows,ext->max_rows);CHKERRQ(ierr); 428*0bb9014aSEmil Constantinescu }else{/*ext->row_ind and col_ind already set*/ 429*0bb9014aSEmil Constantinescu if(ext->ord_adapt){ 430*0bb9014aSEmil Constantinescu ierr = PetscInfo(ts,"Order adaptivity is enabled and TSEIMEXSetRowCol or -ts_eimex_row_col option will take no effect\n");CHKERRQ(ierr); 431*0bb9014aSEmil Constantinescu } 432*0bb9014aSEmil Constantinescu } 433*0bb9014aSEmil Constantinescu 434*0bb9014aSEmil Constantinescu if(ext->ord_adapt){ 435*0bb9014aSEmil Constantinescu ext->nstages = 2; /*Start with the 2-stage scheme*/ 436*0bb9014aSEmil Constantinescu ierr = TSEIMEXSetRowCol(ts,ext->nstages,ext->nstages);CHKERRQ(ierr); 437*0bb9014aSEmil Constantinescu }else{ 438*0bb9014aSEmil Constantinescu ext->nstages = ext->max_rows; /*by default nstages is the same as max_rows, this can be changed by setting order adaptivity */ 439*0bb9014aSEmil Constantinescu } 440*0bb9014aSEmil Constantinescu 441*0bb9014aSEmil Constantinescu ierr = VecDuplicateVecs(ts->vec_sol,(1+ext->nstages)*ext->nstages/2,&ext->T);CHKERRQ(ierr);/*full T table*/ 442*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->YdotI);CHKERRQ(ierr); 443*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->YdotRHS);CHKERRQ(ierr); 444*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->Ydot);CHKERRQ(ierr); 445*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->VecSolPrev);CHKERRQ(ierr); 446*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->Y);CHKERRQ(ierr); 447*0bb9014aSEmil Constantinescu ierr = VecDuplicate(ts->vec_sol,&ext->Z);CHKERRQ(ierr); 448*0bb9014aSEmil Constantinescu ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 449*0bb9014aSEmil Constantinescu if (dm) { 450*0bb9014aSEmil Constantinescu ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSEIMEX,DMRestrictHook_TSEIMEX,ts);CHKERRQ(ierr); 451*0bb9014aSEmil Constantinescu } 452*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 453*0bb9014aSEmil Constantinescu } 454*0bb9014aSEmil Constantinescu 455*0bb9014aSEmil Constantinescu #undef __FUNCT__ 456*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSSetFromOptions_EIMEX" 457*0bb9014aSEmil Constantinescu static PetscErrorCode TSSetFromOptions_EIMEX(TS ts) 458*0bb9014aSEmil Constantinescu { 459*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 460*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 461*0bb9014aSEmil Constantinescu PetscInt tindex[2]={TSEIMEXDefault,TSEIMEXDefault}; 462*0bb9014aSEmil Constantinescu PetscInt np = 2, nrows=TSEIMEXDefault; 463*0bb9014aSEmil Constantinescu PetscFunctionBegin; 464*0bb9014aSEmil Constantinescu ierr = PetscOptionsHead("EIMEX ODE solver options");CHKERRQ(ierr); 465*0bb9014aSEmil Constantinescu { 466*0bb9014aSEmil Constantinescu PetscBool flg; 467*0bb9014aSEmil Constantinescu flg = PETSC_FALSE; 468*0bb9014aSEmil Constantinescu ierr = PetscOptionsInt("-ts_eimex_max_rows","Define the maximum number of rows used","TSEIMEXSetMaxRows",nrows,&nrows,&flg);CHKERRQ(ierr); /*default value 3*/ 469*0bb9014aSEmil Constantinescu if(flg){ 470*0bb9014aSEmil Constantinescu ierr = TSEIMEXSetMaxRows(ts,nrows);CHKERRQ(ierr); 471*0bb9014aSEmil Constantinescu } 472*0bb9014aSEmil Constantinescu ierr = PetscOptionsIntArray("-ts_eimex_row_col","Return the specific term in the T table","TSEIMEXSetRowCol",tindex,&np,&flg);CHKERRQ(ierr); 473*0bb9014aSEmil Constantinescu if(flg){ 474*0bb9014aSEmil Constantinescu ierr = TSEIMEXSetRowCol(ts,tindex[0],tindex[1]);CHKERRQ(ierr); 475*0bb9014aSEmil Constantinescu } 476*0bb9014aSEmil Constantinescu ierr = PetscOptionsBool("-ts_eimex_order_adapt","Solve the problem with adaptive order","TSEIMEXSetOrdAdapt",ext->ord_adapt,&ext->ord_adapt,PETSC_NULL);CHKERRQ(ierr); 477*0bb9014aSEmil Constantinescu ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr); 478*0bb9014aSEmil Constantinescu 479*0bb9014aSEmil Constantinescu /*prevent users from changing SNESType*/ 480*0bb9014aSEmil Constantinescu } 481*0bb9014aSEmil Constantinescu ierr = PetscOptionsTail();CHKERRQ(ierr); 482*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 483*0bb9014aSEmil Constantinescu } 484*0bb9014aSEmil Constantinescu 485*0bb9014aSEmil Constantinescu #undef __FUNCT__ 486*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSView_EIMEX" 487*0bb9014aSEmil Constantinescu static PetscErrorCode TSView_EIMEX(TS ts,PetscViewer viewer) 488*0bb9014aSEmil Constantinescu { 489*0bb9014aSEmil Constantinescu /* TS_EIMEX *ext = (TS_EIMEX*)ts->data;*/ 490*0bb9014aSEmil Constantinescu PetscBool iascii; 491*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 492*0bb9014aSEmil Constantinescu 493*0bb9014aSEmil Constantinescu PetscFunctionBegin; 494*0bb9014aSEmil Constantinescu ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 495*0bb9014aSEmil Constantinescu if (iascii) { 496*0bb9014aSEmil Constantinescu ierr = PetscViewerASCIIPrintf(viewer," EIMEX\n");CHKERRQ(ierr); 497*0bb9014aSEmil Constantinescu } 498*0bb9014aSEmil Constantinescu ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr); 499*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 500*0bb9014aSEmil Constantinescu } 501*0bb9014aSEmil Constantinescu 502*0bb9014aSEmil Constantinescu 503*0bb9014aSEmil Constantinescu #undef __FUNCT__ 504*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetMaxRows" 505*0bb9014aSEmil Constantinescu /*@C 506*0bb9014aSEmil Constantinescu TSEIMEXSetMaxRows - Set the maximum number of rows for EIMEX schemes 507*0bb9014aSEmil Constantinescu 508*0bb9014aSEmil Constantinescu Logically collective 509*0bb9014aSEmil Constantinescu 510*0bb9014aSEmil Constantinescu Input Parameter: 511*0bb9014aSEmil Constantinescu + ts - timestepping context 512*0bb9014aSEmil Constantinescu - nrows - maximum number of rows 513*0bb9014aSEmil Constantinescu 514*0bb9014aSEmil Constantinescu Level: intermediate 515*0bb9014aSEmil Constantinescu 516*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetRowCol(), TSEIMEXSetOrdAdapt(), TSEIMEX 517*0bb9014aSEmil Constantinescu @*/ 518*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetMaxRows(TS ts, PetscInt nrows) 519*0bb9014aSEmil Constantinescu { 520*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 521*0bb9014aSEmil Constantinescu PetscFunctionBegin; 522*0bb9014aSEmil Constantinescu PetscValidHeaderSpecific(ts,TS_CLASSID,1); 523*0bb9014aSEmil Constantinescu ierr = PetscTryMethod(ts,"TSEIMEXSetMaxRows_C",(TS,PetscInt),(ts,nrows));CHKERRQ(ierr); 524*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 525*0bb9014aSEmil Constantinescu } 526*0bb9014aSEmil Constantinescu 527*0bb9014aSEmil Constantinescu 528*0bb9014aSEmil Constantinescu #undef __FUNCT__ 529*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetRowCol" 530*0bb9014aSEmil Constantinescu /*@C 531*0bb9014aSEmil Constantinescu TSEIMEXSetRowCol - Set the type index in the T table for the return value 532*0bb9014aSEmil Constantinescu 533*0bb9014aSEmil Constantinescu Logically collective 534*0bb9014aSEmil Constantinescu 535*0bb9014aSEmil Constantinescu Input Parameter: 536*0bb9014aSEmil Constantinescu + ts - timestepping context 537*0bb9014aSEmil Constantinescu - tindex - index in the T table 538*0bb9014aSEmil Constantinescu 539*0bb9014aSEmil Constantinescu Level: intermediate 540*0bb9014aSEmil Constantinescu 541*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetMaxRows(), TSEIMEXSetOrdAdapt(), TSEIMEX 542*0bb9014aSEmil Constantinescu @*/ 543*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetRowCol(TS ts, PetscInt row, PetscInt col) 544*0bb9014aSEmil Constantinescu { 545*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 546*0bb9014aSEmil Constantinescu PetscFunctionBegin; 547*0bb9014aSEmil Constantinescu PetscValidHeaderSpecific(ts,TS_CLASSID,1); 548*0bb9014aSEmil Constantinescu ierr = PetscTryMethod(ts,"TSEIMEXSetRowCol_C",(TS,PetscInt, PetscInt),(ts,row,col));CHKERRQ(ierr); 549*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 550*0bb9014aSEmil Constantinescu } 551*0bb9014aSEmil Constantinescu 552*0bb9014aSEmil Constantinescu 553*0bb9014aSEmil Constantinescu #undef __FUNCT__ 554*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetOrdAdapt" 555*0bb9014aSEmil Constantinescu /*@C 556*0bb9014aSEmil Constantinescu TSEIMEXSetOrdAdapt - Set the order adaptativity 557*0bb9014aSEmil Constantinescu 558*0bb9014aSEmil Constantinescu Logically collective 559*0bb9014aSEmil Constantinescu 560*0bb9014aSEmil Constantinescu Input Parameter: 561*0bb9014aSEmil Constantinescu + ts - timestepping context 562*0bb9014aSEmil Constantinescu - tindex - index in the T table 563*0bb9014aSEmil Constantinescu 564*0bb9014aSEmil Constantinescu Level: intermediate 565*0bb9014aSEmil Constantinescu 566*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetRowCol(), TSEIMEXSetOrdAdapt(), TSEIMEX 567*0bb9014aSEmil Constantinescu @*/ 568*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetOrdAdapt(TS ts, PetscBool flg) 569*0bb9014aSEmil Constantinescu { 570*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 571*0bb9014aSEmil Constantinescu PetscFunctionBegin; 572*0bb9014aSEmil Constantinescu PetscValidHeaderSpecific(ts,TS_CLASSID,1); 573*0bb9014aSEmil Constantinescu ierr = PetscTryMethod(ts,"TSEIMEXSetOrdAdapt_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 574*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 575*0bb9014aSEmil Constantinescu } 576*0bb9014aSEmil Constantinescu 577*0bb9014aSEmil Constantinescu 578*0bb9014aSEmil Constantinescu EXTERN_C_BEGIN 579*0bb9014aSEmil Constantinescu #undef __FUNCT__ 580*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetMaxRows_EIMEX" 581*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetMaxRows_EIMEX(TS ts,PetscInt nrows) 582*0bb9014aSEmil Constantinescu { 583*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 584*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 585*0bb9014aSEmil Constantinescu PetscInt i; 586*0bb9014aSEmil Constantinescu 587*0bb9014aSEmil Constantinescu PetscFunctionBegin; 588*0bb9014aSEmil Constantinescu if (nrows < 0 || nrows > 100) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Max number of rows (current value %D) should be an integer number between 1 and 100\n",nrows); 589*0bb9014aSEmil Constantinescu if(ext->N){ 590*0bb9014aSEmil Constantinescu ierr = PetscFree(ext->N);CHKERRQ(ierr); 591*0bb9014aSEmil Constantinescu } 592*0bb9014aSEmil Constantinescu ext->max_rows = nrows; 593*0bb9014aSEmil Constantinescu ierr = PetscMalloc(nrows*sizeof(PetscInt),&ext->N);CHKERRQ(ierr); 594*0bb9014aSEmil Constantinescu for(i=0;i<nrows;i++) ext->N[i]=i+1; 595*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 596*0bb9014aSEmil Constantinescu } 597*0bb9014aSEmil Constantinescu 598*0bb9014aSEmil Constantinescu #undef __FUNCT__ 599*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetRowCol_EIMEX" 600*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetRowCol_EIMEX(TS ts,PetscInt row,PetscInt col) 601*0bb9014aSEmil Constantinescu { 602*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 603*0bb9014aSEmil Constantinescu 604*0bb9014aSEmil Constantinescu PetscFunctionBegin; 605*0bb9014aSEmil Constantinescu if (row < 1 || col < 1) SETERRQ2(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The row or column index (current value %d,%d) should not be less than 1 \n",row,col); 606*0bb9014aSEmil Constantinescu if (row > ext->max_rows || col > ext->max_rows) SETERRQ3(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The row or column index (current value %d,%d) exceeds the maximum number of rows %d\n",row,col,ext->max_rows); 607*0bb9014aSEmil Constantinescu if (col > row) SETERRQ2(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The column index (%d) exceeds the row index (%d)\n",col,row); 608*0bb9014aSEmil Constantinescu 609*0bb9014aSEmil Constantinescu ext->row_ind = row - 1; 610*0bb9014aSEmil Constantinescu ext->col_ind = col - 1; /*Array index in C starts from 0*/ 611*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 612*0bb9014aSEmil Constantinescu } 613*0bb9014aSEmil Constantinescu 614*0bb9014aSEmil Constantinescu #undef __FUNCT__ 615*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetOrdAdapt_EIMEX" 616*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetOrdAdapt_EIMEX(TS ts,PetscBool flg) 617*0bb9014aSEmil Constantinescu { 618*0bb9014aSEmil Constantinescu TS_EIMEX *ext = (TS_EIMEX*)ts->data; 619*0bb9014aSEmil Constantinescu PetscFunctionBegin; 620*0bb9014aSEmil Constantinescu ext->ord_adapt = flg; 621*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 622*0bb9014aSEmil Constantinescu } 623*0bb9014aSEmil Constantinescu EXTERN_C_END 624*0bb9014aSEmil Constantinescu 625*0bb9014aSEmil Constantinescu /* ------------------------------------------------------------ */ 626*0bb9014aSEmil Constantinescu /*MC 627*0bb9014aSEmil Constantinescu TSEIMEX - ODE solver using extrapolated IMEX schemes 628*0bb9014aSEmil Constantinescu These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction(). 629*0bb9014aSEmil Constantinescu 630*0bb9014aSEmil Constantinescu Notes: 631*0bb9014aSEmil Constantinescu The default is a 3-stage scheme, it can be changed with TSEIMEXSetMaxRows() or -ts_eimex_max_rows 632*0bb9014aSEmil Constantinescu 633*0bb9014aSEmil Constantinescu This method currently only works with ODE, for which the stiff part G(t,X,Xdot) has the form Xdot + Ghat(t,X). 634*0bb9014aSEmil Constantinescu 635*0bb9014aSEmil Constantinescu Level: beginner 636*0bb9014aSEmil Constantinescu 637*0bb9014aSEmil Constantinescu .seealso: TSCreate(), TS 638*0bb9014aSEmil Constantinescu M*/ 639*0bb9014aSEmil Constantinescu EXTERN_C_BEGIN 640*0bb9014aSEmil Constantinescu #undef __FUNCT__ 641*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSCreate_EIMEX" 642*0bb9014aSEmil Constantinescu PetscErrorCode TSCreate_EIMEX(TS ts) 643*0bb9014aSEmil Constantinescu { 644*0bb9014aSEmil Constantinescu TS_EIMEX *ext; 645*0bb9014aSEmil Constantinescu PetscErrorCode ierr; 646*0bb9014aSEmil Constantinescu 647*0bb9014aSEmil Constantinescu PetscFunctionBegin; 648*0bb9014aSEmil Constantinescu 649*0bb9014aSEmil Constantinescu ts->ops->reset = TSReset_EIMEX; 650*0bb9014aSEmil Constantinescu ts->ops->destroy = TSDestroy_EIMEX; 651*0bb9014aSEmil Constantinescu ts->ops->view = TSView_EIMEX; 652*0bb9014aSEmil Constantinescu ts->ops->setup = TSSetUp_EIMEX; 653*0bb9014aSEmil Constantinescu ts->ops->step = TSStep_EIMEX; 654*0bb9014aSEmil Constantinescu ts->ops->interpolate = TSInterpolate_EIMEX; 655*0bb9014aSEmil Constantinescu ts->ops->evaluatestep = TSEvaluateStep_EIMEX; 656*0bb9014aSEmil Constantinescu ts->ops->setfromoptions = TSSetFromOptions_EIMEX; 657*0bb9014aSEmil Constantinescu ts->ops->snesfunction = SNESTSFormFunction_EIMEX; 658*0bb9014aSEmil Constantinescu ts->ops->snesjacobian = SNESTSFormJacobian_EIMEX; 659*0bb9014aSEmil Constantinescu 660*0bb9014aSEmil Constantinescu ierr = PetscNewLog(ts,TS_EIMEX,&ext);CHKERRQ(ierr); 661*0bb9014aSEmil Constantinescu ts->data = (void*)ext; 662*0bb9014aSEmil Constantinescu 663*0bb9014aSEmil Constantinescu ext->ord_adapt = PETSC_FALSE; /*By default, no order adapativity*/ 664*0bb9014aSEmil Constantinescu ext->row_ind = -1; 665*0bb9014aSEmil Constantinescu ext->col_ind = -1; 666*0bb9014aSEmil Constantinescu ext->max_rows = TSEIMEXDefault; 667*0bb9014aSEmil Constantinescu ext->nstages = TSEIMEXDefault; 668*0bb9014aSEmil Constantinescu 669*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetMaxRows_C","TSEIMEXSetMaxRows_EIMEX",TSEIMEXSetMaxRows_EIMEX);CHKERRQ(ierr); 670*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetRowCol_C","TSEIMEXSetRowCol_EIMEX",TSEIMEXSetRowCol_EIMEX);CHKERRQ(ierr); 671*0bb9014aSEmil Constantinescu ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetOrdAdapt_C","TSEIMEXSetOrdAdapt_EIMEX",TSEIMEXSetOrdAdapt_EIMEX);CHKERRQ(ierr); 672*0bb9014aSEmil Constantinescu PetscFunctionReturn(0); 673*0bb9014aSEmil Constantinescu } 674*0bb9014aSEmil Constantinescu EXTERN_C_END 675*0bb9014aSEmil Constantinescu 676