Actual source code: sundials.c

  1: #define PETSCTS_DLL

  3: /*
  4:     Provides a PETSc interface to SUNDIALS/CVODE solver.
  5:     The interface to PVODE (old version of CVODE) was originally contributed 
  6:     by Liyang Xu. It has been redone by Hong Zhang and Dinesh Kaushik.
  7:     Reference: sundials-2.3.0/examples/cvode/parallel/cvkryx_p.c
  8: */
 9:  #include sundials.h

 11: /*
 12:       TSPrecond_Sundials - function that we provide to SUNDIALS to
 13:                         evaluate the preconditioner.
 14: */
 17: PetscErrorCode TSPrecond_Sundials(realtype tn,N_Vector y,N_Vector fy,
 18:                     booleantype jok,booleantype *jcurPtr,
 19:                     realtype _gamma,void *P_data,
 20:                     N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
 21: {
 22:   TS             ts = (TS) P_data;
 23:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
 24:   PC             pc = cvode->pc;
 26:   Mat            Jac = ts->B;
 27:   Vec            yy = cvode->w1;
 28:   PetscScalar    one = 1.0,gm;
 29:   MatStructure   str = DIFFERENT_NONZERO_PATTERN;
 30:   PetscScalar    *y_data;
 31: 
 33:   /* This allows us to construct preconditioners in-place if we like */
 34:   MatSetUnfactored(Jac);
 35: 
 36:   /* jok - TRUE means reuse current Jacobian else recompute Jacobian */
 37:   if (jok) {
 38:     MatCopy(cvode->pmat,Jac,str);
 39:     *jcurPtr = FALSE;
 40:   } else {
 41:     /* make PETSc vector yy point to SUNDIALS vector y */
 42:     y_data = (PetscScalar *) N_VGetArrayPointer(y);
 43:     VecPlaceArray(yy,y_data);

 45:     /* compute the Jacobian */
 46:     TSComputeRHSJacobian(ts,ts->ptime,yy,&Jac,&Jac,&str);
 47:     VecResetArray(yy);

 49:     /* copy the Jacobian matrix */
 50:     if (!cvode->pmat) {
 51:       MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);
 52:       PetscLogObjectParent(ts,cvode->pmat);
 53:     } else {
 54:       MatCopy(Jac,cvode->pmat,str);
 55:     }
 56:     *jcurPtr = TRUE;
 57:   }
 58: 
 59:   /* construct I-gamma*Jac  */
 60:   gm   = -_gamma;
 61:   MatScale(Jac,gm);
 62:   MatShift(Jac,one);
 63: 
 64:   PCSetOperators(pc,Jac,Jac,str);
 65:   return(0);
 66: }

 68: /*
 69:      TSPSolve_Sundials -  routine that we provide to Sundials that applies the preconditioner.
 70: */
 73: PetscErrorCode TSPSolve_Sundials(realtype tn,N_Vector y,N_Vector fy,N_Vector r,N_Vector z,
 74:                                  realtype _gamma,realtype delta,int lr,void *P_data,N_Vector vtemp)
 75: {
 76:   TS              ts = (TS) P_data;
 77:   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
 78:   PC              pc = cvode->pc;
 79:   Vec             rr = cvode->w1,zz = cvode->w2;
 80:   PetscErrorCode  ierr;
 81:   PetscScalar     *r_data,*z_data;

 84:   /* Make the PETSc work vectors rr and zz point to the arrays in the SUNDIALS vectors r and z respectively*/
 85:   r_data  = (PetscScalar *) N_VGetArrayPointer(r);
 86:   z_data  = (PetscScalar *) N_VGetArrayPointer(z);
 87:   VecPlaceArray(rr,r_data);
 88:   VecPlaceArray(zz,z_data);

 90:   /* Solve the Px=r and put the result in zz */
 91:   PCApply(pc,rr,zz);
 92:   VecResetArray(rr);
 93:   VecResetArray(zz);
 94:   return(0);
 95: }

 97: /*
 98:         TSFunction_Sundials - routine that we provide to Sundials that applies the right hand side.
 99: */
102: int TSFunction_Sundials(realtype t,N_Vector y,N_Vector ydot,void *ctx)
103: {
104:   TS              ts = (TS) ctx;
105:   MPI_Comm        comm = ((PetscObject)ts)->comm;
106:   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
107:   Vec             yy = cvode->w1,yyd = cvode->w2;
108:   PetscScalar     *y_data,*ydot_data;
109:   PetscErrorCode  ierr;

112:   /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/
113:   y_data     = (PetscScalar *) N_VGetArrayPointer(y);
114:   ydot_data  = (PetscScalar *) N_VGetArrayPointer(ydot);
115:   VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr);
116:   VecPlaceArray(yyd,ydot_data); CHKERRABORT(comm,ierr);

118:   /* now compute the right hand side function */
119:   TSComputeRHSFunction(ts,t,yy,yyd); CHKERRABORT(comm,ierr);
120:   VecResetArray(yy); CHKERRABORT(comm,ierr);
121:   VecResetArray(yyd); CHKERRABORT(comm,ierr);
122:   return(0);
123: }

125: /*
126:        TSStep_Sundials_Nonlinear - Calls Sundials to integrate the ODE.
127: */
130: /* 
131:     TSStep_Sundials_Nonlinear - 
132:   
133:    steps - number of time steps
134:    time - time that integrater is  terminated. 
135: */
136: PetscErrorCode TSStep_Sundials_Nonlinear(TS ts,int *steps,double *time)
137: {
138:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
139:   Vec            sol = ts->vec_sol;
141:   PetscInt       i,max_steps = ts->max_steps,flag;
142:   long int       its;
143:   realtype       t,tout;
144:   PetscScalar    *y_data;
145:   void           *mem;
146:   const PCType   pctype;
147:   PetscTruth     pcnone;

150:   /* Call CVodeCreate to create the solver memory */
151:   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
152:   if (!mem) SETERRQ(1,"CVodeCreate() fails");
153:   flag = CVodeSetFdata(mem,ts);
154:   if (flag) SETERRQ(1,"CVodeSetFdata() fails");

156:   /* 
157:      Call CVodeMalloc to initialize the integrator memory: 
158:      mem is the pointer to the integrator memory returned by CVodeCreate
159:      f       is the user's right hand side function in y'=f(t,y)
160:      T0      is the initial time
161:      u       is the initial dependent variable vector
162:      CV_SS   specifies scalar relative and absolute tolerances
163:      reltol  is the relative tolerance
164:      &abstol is a pointer to the scalar absolute tolerance
165:   */
166:   flag = CVodeMalloc(mem,TSFunction_Sundials,ts->ptime,cvode->y,CV_SS,cvode->reltol,&cvode->abstol);
167:   if (flag) SETERRQ(1,"CVodeMalloc() fails");

169:   /* initialize the number of steps */
170:   *steps = -ts->steps;
171:   TSMonitor(ts,ts->steps,ts->ptime,sol);

173:   /* call CVSpgmr to use GMRES as the linear solver.        */
174:   /* setup the ode integrator with the given preconditioner */
175:   PCGetType(cvode->pc,&pctype);
176:   PetscTypeCompare((PetscObject)cvode->pc,PCNONE,&pcnone);
177:   if (pcnone){
178:     flag  = CVSpgmr(mem,PREC_NONE,0);
179:   } else {
180:     flag  = CVSpgmr(mem,PREC_LEFT,0);
181:   }
182:   if (flag) SETERRQ(1,"CVSpgmr() fails");
183: 
184:   /* Set preconditioner setup and solve routines Precond and PSolve, 
185:      and the pointer to the user-defined block data */
186:   flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials,ts);
187:   if (flag) SETERRQ(1,"CVSpgmrSetPreconditioner() fails");

189:   flag = CVSpilsSetGSType(mem, MODIFIED_GS);
190:   if (flag) SETERRQ(1,"CVSpgmrSetGSType() fails");

192:   tout = ts->max_time;
193:   VecGetArray(ts->vec_sol,&y_data);
194:   N_VSetArrayPointer((realtype *)y_data,cvode->y);
195:   VecRestoreArray(ts->vec_sol,PETSC_NULL);
196:   for (i = 0; i < max_steps; i++) {
197:     if (ts->ptime >= ts->max_time) break;
198:     CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);
199:     if (ts->ops->postupdate){
200:       (*ts->ops->postupdate)(ts,ts->ptime,PETSC_NULL);
201:     }
202:     if (t > ts->max_time && cvode->exact_final_time) {
203:       /* interpolate to final requested time */
204:       CVodeGetDky(mem,tout,0,cvode->y);
205:       t = tout;
206:     }
207:     ts->time_step = t - ts->ptime;
208:     ts->ptime     = t;

210:     /* copy the solution from cvode->y to cvode->update and sol */
211:     VecPlaceArray(cvode->w1,y_data);
212:     VecCopy(cvode->w1,cvode->update);
213:     VecResetArray(cvode->w1);
214:     VecCopy(cvode->update,sol);
215:     CVodeGetNumNonlinSolvIters(mem,&its);
216:     ts->nonlinear_its = its;
217:     CVSpilsGetNumLinIters(mem, &its);
218:     ts->linear_its = its;
219:     ts->steps++;
220:     TSMonitor(ts,ts->steps,t,sol);
221:   }
222:   cvode->mem = mem;
223:   *steps    += ts->steps;
224:   *time      = t;
225:   return(0);
226: }

230: PetscErrorCode TSDestroy_Sundials(TS ts)
231: {
232:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;

236:   if (cvode->pmat)   {MatDestroy(cvode->pmat);}
237:   if (cvode->pc)     {PCDestroy(cvode->pc);}
238:   if (cvode->update) {VecDestroy(cvode->update);}
239:   if (cvode->func)   {VecDestroy(cvode->func);}
240:   if (cvode->rhs)    {VecDestroy(cvode->rhs);}
241:   if (cvode->w1)     {VecDestroy(cvode->w1);}
242:   if (cvode->w2)     {VecDestroy(cvode->w2);}
243:   MPI_Comm_free(&(cvode->comm_sundials));
244:   if (cvode->mem) {CVodeFree(&cvode->mem);}
245:   PetscFree(cvode);
246:   return(0);
247: }

251: PetscErrorCode TSSetUp_Sundials_Nonlinear(TS ts)
252: {
253:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
255:   int            glosize,locsize,i;
256:   PetscScalar    *y_data,*parray;

259:   PCSetFromOptions(cvode->pc);
260:   /* get the vector size */
261:   VecGetSize(ts->vec_sol,&glosize);
262:   VecGetLocalSize(ts->vec_sol,&locsize);

264:   /* allocate the memory for N_Vec y */
265:   cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
266:   if (!cvode->y) SETERRQ(1,"cvode->y is not allocated");

268:   /* initialize N_Vec y */
269:   VecGetArray(ts->vec_sol,&parray);
270:   y_data = (PetscScalar *) N_VGetArrayPointer(cvode->y);
271:   for (i = 0; i < locsize; i++) y_data[i] = parray[i];
272:   /*PetscMemcpy(y_data,parray,locsize*sizeof(PETSC_SCALAR)); */
273:   VecRestoreArray(ts->vec_sol,PETSC_NULL);
274:   VecDuplicate(ts->vec_sol,&cvode->update);
275:   VecDuplicate(ts->vec_sol,&cvode->func);
276:   PetscLogObjectParent(ts,cvode->update);
277:   PetscLogObjectParent(ts,cvode->func);

279:   /* 
280:       Create work vectors for the TSPSolve_Sundials() routine. Note these are
281:     allocated with zero space arrays because the actual array space is provided 
282:     by Sundials and set using VecPlaceArray().
283:   */
284:   VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w1);
285:   VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w2);
286:   PetscLogObjectParent(ts,cvode->w1);
287:   PetscLogObjectParent(ts,cvode->w2);
288:   return(0);
289: }

291: /* type of CVODE linear multistep method */
292: const char *TSSundialsLmmTypes[] = {"","adams","bdf","TSSundialsLmmType","SUNDIALS_",0};
293: /* type of G-S orthogonalization used by CVODE linear solver */
294: const char *TSSundialsGramSchmidtTypes[] = {"","modified","classical","TSSundialsGramSchmidtType","SUNDIALS_",0};

298: PetscErrorCode TSSetFromOptions_Sundials_Nonlinear(TS ts)
299: {
300:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
302:   int            indx;
303:   PetscTruth     flag;

306:   PetscOptionsHead("SUNDIALS ODE solver options");
307:     PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);
308:     if (flag) {
309:       TSSundialsSetType(ts,(TSSundialsLmmType)indx);
310:     }
311:     PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);
312:     if (flag) {
313:       TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);
314:     }
315:     PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);
316:     PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);
317:     PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);
318:     PetscOptionsInt("-ts_sundials_gmres_restart","Number of GMRES orthogonalization directions","TSSundialsSetGMRESRestart",cvode->restart,&cvode->restart,&flag);
319:     PetscOptionsName("-ts_sundials_exact_final_time","Allow SUNDIALS to stop near the final time, not exactly on it","TSSundialsSetExactFinalTime",&flag);
320:     if (flag) cvode->exact_final_time = PETSC_TRUE;
321:   PetscOptionsTail();
322:   return(0);
323: }

327: PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
328: {
329:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
331:   char           *type;
332:   char           atype[] = "Adams";
333:   char           btype[] = "BDF: backward differentiation formula";
334:   PetscTruth     iascii,isstring;
335:   long int       nsteps,its,nfevals,nlinsetups,nfails,itmp;
336:   PetscInt       qlast,qcur;
337:   PetscReal      hinused,hlast,hcur,tcur,tolsfac;

340:   if (cvode->cvode_type == SUNDIALS_ADAMS) {type = atype;}
341:   else                                     {type = btype;}

343:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
344:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
345:   if (iascii) {
346:     PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");
347:     PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);
348:     PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);
349:     PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);
350:     PetscViewerASCIIPrintf(viewer,"Sundials GMRES max iterations (same as restart in SUNDIALS) %D\n",cvode->restart);
351:     if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
352:       PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");
353:     } else {
354:       PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");
355:     }
356: 
357:     /* Outputs from CVODE, CVSPILS */
358:     CVodeGetTolScaleFactor(cvode->mem,&tolsfac);
359:     PetscViewerASCIIPrintf(viewer,"Sundials suggested factor for tolerance scaling %g\n",tolsfac);
360:     CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
361:                                    &nlinsetups,&nfails,&qlast,&qcur,
362:                                    &hinused,&hlast,&hcur,&tcur);
363:     PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);
364:     PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);
365:     PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);
366:     PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);

368:     CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);
369:     PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);
370:     PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);

372:     CVSpilsGetNumLinIters(cvode->mem, &its); /* its = no. of calls to TSPrecond_Sundials() */
373:     PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);
374:     CVSpilsGetNumConvFails(cvode->mem,&itmp);
375:     PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);
376:     CVSpilsGetNumPrecEvals(cvode->mem,&itmp);
377:     PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);
378:     CVSpilsGetNumPrecSolves(cvode->mem,&itmp);
379:     PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);
380:     CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);
381:     PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);
382:     CVSpilsGetNumRhsEvals(cvode->mem,&itmp);
383:     PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);
384:   } else if (isstring) {
385:     PetscViewerStringSPrintf(viewer,"Sundials type %s",type);
386:   } else {
387:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by TS Sundials",((PetscObject)viewer)->type_name);
388:   }
389:   PetscViewerASCIIPushTab(viewer);
390:   PCView(cvode->pc,viewer);
391:   PetscViewerASCIIPopTab(viewer);
392:   return(0);
393: }


396: /* --------------------------------------------------------------------------*/
400: PetscErrorCode  TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
401: {
402:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
403: 
405:   cvode->cvode_type = type;
406:   return(0);
407: }

413: PetscErrorCode  TSSundialsSetGMRESRestart_Sundials(TS ts,int restart)
414: {
415:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
416: 
418:   cvode->restart = restart;
419:   return(0);
420: }

426: PetscErrorCode  TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
427: {
428:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
429: 
431:   cvode->linear_tol = tol;
432:   return(0);
433: }

439: PetscErrorCode  TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
440: {
441:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
442: 
444:   cvode->gtype = type;
445:   return(0);
446: }

452: PetscErrorCode  TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
453: {
454:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
455: 
457:   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
458:   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
459:   return(0);
460: }

466: PetscErrorCode  TSSundialsGetPC_Sundials(TS ts,PC *pc)
467: {
468:   TS_Sundials *cvode = (TS_Sundials*)ts->data;

471:   *pc = cvode->pc;
472:   return(0);
473: }

479: PetscErrorCode  TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
480: {
482:   if (nonlin) *nonlin = ts->nonlinear_its;
483:   if (lin)    *lin    = ts->linear_its;
484:   return(0);
485: }
487: 
491: PetscErrorCode  TSSundialsSetExactFinalTime_Sundials(TS ts,PetscTruth s)
492: {
493:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
494: 
496:   cvode->exact_final_time = s;
497:   return(0);
498: }
500: /* -------------------------------------------------------------------------------------------*/

504: /*@C
505:    TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.

507:    Not Collective

509:    Input parameters:
510: .    ts     - the time-step context

512:    Output Parameters:
513: +   nonlin - number of nonlinear iterations
514: -   lin    - number of linear iterations

516:    Level: advanced

518:    Notes:
519:     These return the number since the creation of the TS object

521: .keywords: non-linear iterations, linear iterations

523: .seealso: TSSundialsSetType(), TSSundialsSetGMRESRestart(),
524:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
525:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
526:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
527:           TSSundialsSetExactFinalTime()

529: @*/
530: PetscErrorCode  TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
531: {
532:   PetscErrorCode ierr,(*f)(TS,int*,int*);
533: 
535:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetIterations_C",(void (**)(void))&f);
536:   if (f) {
537:     (*f)(ts,nonlin,lin);
538:   }
539:   return(0);
540: }

544: /*@
545:    TSSundialsSetType - Sets the method that Sundials will use for integration.

547:    Collective on TS

549:    Input parameters:
550: +    ts     - the time-step context
551: -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF

553:    Level: intermediate

555: .keywords: Adams, backward differentiation formula

557: .seealso: TSSundialsGetIterations(),  TSSundialsSetGMRESRestart(),
558:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
559:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
560:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
561:           TSSundialsSetExactFinalTime()
562: @*/
563: PetscErrorCode  TSSundialsSetType(TS ts,TSSundialsLmmType type)
564: {
565:   PetscErrorCode ierr,(*f)(TS,TSSundialsLmmType);
566: 
568:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetType_C",(void (**)(void))&f);
569:   if (f) {
570:     (*f)(ts,type);
571:   }
572:   return(0);
573: }

577: /*@
578:    TSSundialsSetGMRESRestart - Sets the dimension of the Krylov space used by 
579:        GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
580:        this is ALSO the maximum number of GMRES steps that will be used.

582:    Collective on TS

584:    Input parameters:
585: +    ts      - the time-step context
586: -    restart - number of direction vectors (the restart size).

588:    Level: advanced

590: .keywords: GMRES, restart

592: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), 
593:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
594:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
595:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
596:           TSSundialsSetExactFinalTime()

598: @*/
599: PetscErrorCode  TSSundialsSetGMRESRestart(TS ts,int restart)
600: {
601:   PetscErrorCode ierr,(*f)(TS,int);

604:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGMRESRestart_C",(void (**)(void))&f);
605:   if (f) {
606:     (*f)(ts,restart);
607:   }
608:   return(0);
609: }

613: /*@
614:    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
615:        system by SUNDIALS.

617:    Collective on TS

619:    Input parameters:
620: +    ts     - the time-step context
621: -    tol    - the factor by which the tolerance on the nonlinear solver is
622:              multiplied to get the tolerance on the linear solver, .05 by default.

624:    Level: advanced

626: .keywords: GMRES, linear convergence tolerance, SUNDIALS

628: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
629:           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
630:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
631:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
632:           TSSundialsSetExactFinalTime()

634: @*/
635: PetscErrorCode  TSSundialsSetLinearTolerance(TS ts,double tol)
636: {
637:   PetscErrorCode ierr,(*f)(TS,double);
638: 
640:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",(void (**)(void))&f);
641:   if (f) {
642:     (*f)(ts,tol);
643:   }
644:   return(0);
645: }

649: /*@
650:    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
651:         in GMRES method by SUNDIALS linear solver.

653:    Collective on TS

655:    Input parameters:
656: +    ts  - the time-step context
657: -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS

659:    Level: advanced

661: .keywords: Sundials, orthogonalization

663: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
664:           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
665:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
666:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
667:           TSSundialsSetExactFinalTime()

669: @*/
670: PetscErrorCode  TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
671: {
672:   PetscErrorCode ierr,(*f)(TS,TSSundialsGramSchmidtType);
673: 
675:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",(void (**)(void))&f);
676:   if (f) {
677:     (*f)(ts,type);
678:   }
679:   return(0);
680: }

684: /*@
685:    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by 
686:                          Sundials for error control.

688:    Collective on TS

690:    Input parameters:
691: +    ts  - the time-step context
692: .    aabs - the absolute tolerance  
693: -    rel - the relative tolerance

695:      See the Cvode/Sundials users manual for exact details on these parameters. Essentially
696:     these regulate the size of the error for a SINGLE timestep.

698:    Level: intermediate

700: .keywords: Sundials, tolerance

702: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
703:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), 
704:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
705:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
706:           TSSundialsSetExactFinalTime()

708: @*/
709: PetscErrorCode  TSSundialsSetTolerance(TS ts,double aabs,double rel)
710: {
711:   PetscErrorCode ierr,(*f)(TS,double,double);
712: 
714:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetTolerance_C",(void (**)(void))&f);
715:   if (f) {
716:     (*f)(ts,aabs,rel);
717:   }
718:   return(0);
719: }

723: /*@
724:    TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.

726:    Input Parameter:
727: .    ts - the time-step context

729:    Output Parameter:
730: .    pc - the preconditioner context

732:    Level: advanced

734: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
735:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
736:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
737:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
738: @*/
739: PetscErrorCode  TSSundialsGetPC(TS ts,PC *pc)
740: {
741:   PetscErrorCode ierr,(*f)(TS,PC *);

744:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetPC_C",(void (**)(void))&f);
745:   if (f) {
746:     (*f)(ts,pc);
747:   } else {
748:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"TS must be of Sundials type to extract the PC");
749:   }

751:   return(0);
752: }

756: /*@
757:    TSSundialsSetExactFinalTime - Determines if Sundials interpolates solution to the 
758:       exact final time requested by the user or just returns it at the final time
759:       it computed. (Defaults to true).

761:    Input Parameter:
762: +   ts - the time-step context
763: -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE

765:    Level: beginner

767: .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
768:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
769:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
770:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC() 
771: @*/
772: PetscErrorCode  TSSundialsSetExactFinalTime(TS ts,PetscTruth ft)
773: {
774:   PetscErrorCode ierr,(*f)(TS,PetscTruth);

777:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetExactFinalTime_C",(void (**)(void))&f);
778:   if (f) {
779:     (*f)(ts,ft);
780:   }
781:   return(0);
782: }

784: /* -------------------------------------------------------------------------------------------*/
785: /*MC
786:       TS_Sundials - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)

788:    Options Database:
789: +    -ts_sundials_type <bdf,adams>
790: .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
791: .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
792: .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
793: .    -ts_sundials_linear_tolerance <tol> 
794: .    -ts_sundials_gmres_restart <restart> - Number of GMRES orthogonalization directions
795: -    -ts_sundials_not_exact_final_time -Allow SUNDIALS to stop near the final time, not exactly on it

797:     Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply
798:            only PETSc PC options

800:     Level: beginner

802: .seealso:  TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetGMRESRestart(), TSSundialsSetLinearTolerance(),
803:            TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSundialsSetExactFinalTime()

805: M*/
809: PetscErrorCode  TSCreate_Sundials(TS ts)
810: {
811:   TS_Sundials *cvode;

815:   ts->ops->destroy         = TSDestroy_Sundials;
816:   ts->ops->view            = TSView_Sundials;

818:   if (ts->problem_type != TS_NONLINEAR) {
819:     SETERRQ(PETSC_ERR_SUP,"Only support for nonlinear problems");
820:   }
821:   ts->ops->setup           = TSSetUp_Sundials_Nonlinear;
822:   ts->ops->step            = TSStep_Sundials_Nonlinear;
823:   ts->ops->setfromoptions  = TSSetFromOptions_Sundials_Nonlinear;

825:   PetscNewLog(ts,TS_Sundials,&cvode);
826:   PCCreate(((PetscObject)ts)->comm,&cvode->pc);
827:   PetscLogObjectParent(ts,cvode->pc);
828:   ts->data          = (void*)cvode;
829:   cvode->cvode_type = SUNDIALS_BDF;
830:   cvode->gtype      = SUNDIALS_CLASSICAL_GS;
831:   cvode->restart    = 5;
832:   cvode->linear_tol = .05;

834:   cvode->exact_final_time = PETSC_FALSE;

836:   MPI_Comm_dup(((PetscObject)ts)->comm,&(cvode->comm_sundials));
837:   /* set tolerance for Sundials */
838:   cvode->reltol = 1e-6;
839:   cvode->abstol = 1e-6;

841:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetType_C","TSSundialsSetType_Sundials",
842:                     TSSundialsSetType_Sundials);
843:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGMRESRestart_C",
844:                     "TSSundialsSetGMRESRestart_Sundials",
845:                     TSSundialsSetGMRESRestart_Sundials);
846:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetLinearTolerance_C",
847:                     "TSSundialsSetLinearTolerance_Sundials",
848:                      TSSundialsSetLinearTolerance_Sundials);
849:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",
850:                     "TSSundialsSetGramSchmidtType_Sundials",
851:                      TSSundialsSetGramSchmidtType_Sundials);
852:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetTolerance_C",
853:                     "TSSundialsSetTolerance_Sundials",
854:                      TSSundialsSetTolerance_Sundials);
855:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetPC_C",
856:                     "TSSundialsGetPC_Sundials",
857:                      TSSundialsGetPC_Sundials);
858:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetIterations_C",
859:                     "TSSundialsGetIterations_Sundials",
860:                      TSSundialsGetIterations_Sundials);
861:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetExactFinalTime_C",
862:                     "TSSundialsSetExactFinalTime_Sundials",
863:                      TSSundialsSetExactFinalTime_Sundials);
864:   return(0);
865: }