Actual source code: sundials.c

  1: #define PETSCTS_DLL

  3: /*
  4:     Provides a PETSc interface to SUNDIALS. Alan Hindmarsh's parallel ODE
  5:     solver.
  6:     The interface to PVODE (old version of CVODE) was originally contributed 
  7:     by Liyang Xu. It has been redone by Hong Zhang and Dinesh Kaushik.
  8: */

 10: #include "src/ts/impls/implicit/sundials/sundials.h"  /*I "petscts.h" I*/    

 12: /*
 13:       TSPrecond_Sundials - function that we provide to SUNDIALS to
 14:                         evaluate the preconditioner.
 15: */
 18: PetscErrorCode TSPrecond_Sundials(realtype tn,N_Vector y,N_Vector fy,
 19:                     booleantype jok,booleantype *jcurPtr,
 20:                     realtype _gamma,void *P_data,
 21:                     N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
 22: {
 23:   TS             ts = (TS) P_data;
 24:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
 25:   PC             pc = cvode->pc;
 27:   Mat            Jac = ts->B;
 28:   Vec            yy = cvode->w1;
 29:   PetscScalar    one = 1.0,gm;
 30:   MatStructure   str = DIFFERENT_NONZERO_PATTERN;
 31:   PetscScalar    *y_data;
 32: 
 34:   /* This allows us to construct preconditioners in-place if we like */
 35:   MatSetUnfactored(Jac);
 36: 
 37:   /* jok - TRUE means reuse current Jacobian else recompute Jacobian */
 38:   if (jok) {
 39:     MatCopy(cvode->pmat,Jac,str);
 40:     *jcurPtr = FALSE;
 41:   } else {
 42:     /* make PETSc vector yy point to SUNDIALS vector y */
 43:     y_data = (PetscScalar *) N_VGetArrayPointer(y);
 44:     VecPlaceArray(yy,y_data);
 45:     /* compute the Jacobian */
 46:     TSComputeRHSJacobian(ts,ts->ptime,yy,&Jac,&Jac,&str);
 47:     VecResetArray(yy);
 48:     /* copy the Jacobian matrix */
 49:     if (!cvode->pmat) {
 50:       MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);
 51:       PetscLogObjectParent(ts,cvode->pmat);
 52:     }
 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,
 74:                                  N_Vector r,N_Vector z,
 75:                                  realtype _gamma,realtype delta,
 76:                                  int lr,void *P_data,N_Vector vtemp)
 77: {
 78:   TS              ts = (TS) P_data;
 79:   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
 80:   PC              pc = cvode->pc;
 81:   Vec             rr = cvode->w1,zz = cvode->w2;
 82:   PetscErrorCode  ierr;
 83:   PetscScalar     *r_data,*z_data;

 86:   /* Make the PETSc work vectors rr and zz point to the arrays in the SUNDIALS vectors r and z respectively*/
 87:   r_data  = (PetscScalar *) N_VGetArrayPointer(r);
 88:   z_data  = (PetscScalar *) N_VGetArrayPointer(z);
 89:   VecPlaceArray(rr,r_data);
 90:   VecPlaceArray(zz,z_data);
 91:   /* Solve the Px=r and put the result in zz */
 92:   PCApply(pc,rr,zz);
 93:   VecResetArray(rr);
 94:   VecResetArray(zz);
 95:   cvode->linear_solves++;
 96:   return(0);
 97: }

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

114:   /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/
115:   y_data     = (PetscScalar *) N_VGetArrayPointer(y);
116:   ydot_data  = (PetscScalar *) N_VGetArrayPointer(ydot);
117:   VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr)
118:   VecPlaceArray(yyd,ydot_data); CHKERRABORT(comm,ierr)
119:   /* now compute the right hand side function */
120:   TSComputeRHSFunction(ts,t,yy,yyd); CHKERRABORT(comm,ierr);
121:   VecResetArray(yy); CHKERRABORT(comm,ierr);
122:   VecResetArray(yyd); CHKERRABORT(comm,ierr);
123:   PetscFunctionReturnVoid();
124: }

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

149:   /* 
150:      Call CVodeCreate to create the solver memory:
151:      CV_ADAMS   specifies the Adams Method
152:      CV_FUNCTIONAL  specifies functional iteration  
153:      A pointer to the integrator memory is returned and stored in cvode_mem.
154:   */
155:   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
156:   if (!mem) SETERRQ(1,"CVodeCreate() fails");
157:   flag = CVodeSetFdata(mem,ts);
158:   if (flag) SETERRQ(1,"CVodeSetFdata() fails");

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

173:   /* initialize the number of steps */
174:   *steps = -ts->steps;
175:   TSMonitor(ts,ts->steps,ts->ptime,sol);

177:   /* call CVSpgmr to use GMRES as the linear solver. */
178:   /* setup the ode integrator with the given preconditioner */
179:   /* flag  = CVSpgmr(mem,PREC_LEFT,cvode->restart); */
180:   flag  = CVSpgmr(mem,PREC_LEFT,0);
181:   if (flag) SETERRQ(1,"CVSpgmr() fails");
182:   flag = CVSpgmrSetGSType(mem,MODIFIED_GS);
183:   if (flag) SETERRQ(1,"CVSpgmrSetGSType() fails");

185:   /* Set preconditioner setup and solve routines Precond and PSolve, 
186:      and the pointer to the user-defined block data */
187:   flag = CVSpgmrSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials,ts);
188:   if (flag) SETERRQ(1,"CVSpgmrSetPreconditioner() fails");

190:   tout = ts->max_time;
191:   VecGetArray(ts->vec_sol,&y_data);
192:   N_VSetArrayPointer((realtype *)y_data,cvode->y);
193:   VecRestoreArray(ts->vec_sol,PETSC_NULL);
194:   for (i = 0; i < max_steps; i++) {
195:     if (ts->ptime >= ts->max_time) break;
196:     CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);
197:     CVodeGetNumNonlinSolvIters(mem,&its);
198:     cvode->nonlinear_solves += its;

200:     if (t > ts->max_time && cvode->exact_final_time) {
201:       /* interpolate to final requested time */
202:       CVodeGetDky(mem,tout,0,cvode->y);
203:       t = tout;
204:     }
205:     ts->time_step = t - ts->ptime;
206:     ts->ptime     = t;

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

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

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

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

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

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

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

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

290: PetscErrorCode TSSetFromOptions_Sundials_Nonlinear(TS ts)
291: {
292:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
294:   int            indx;
295:   const char     *btype[] = {"bdf","adams"},*otype[] = {"modified","unmodified"};
296:   PetscTruth     flag;

299:   PetscOptionsHead("SUNDIALS ODE solver options");
300:     PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",btype,2,"bdf",&indx,&flag);
301:     if (flag) {
302:       TSSundialsSetType(ts,(TSSundialsType)indx);
303:     }
304:     PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",otype,2,"unmodified",&indx,&flag);
305:     if (flag) {
306:       TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);
307:     }
308:     PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);
309:     PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);
310:     PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);
311:     PetscOptionsInt("-ts_sundials_gmres_restart","Number of GMRES orthogonalization directions","TSSundialsSetGMRESRestart",cvode->restart,&cvode->restart,&flag);
312:     PetscOptionsName("-ts_sundials_exact_final_time","Allow SUNDIALS to stop near the final time, not exactly on it","TSSundialsSetExactFinalTime",&cvode->exact_final_time);
313:   PetscOptionsTail();
314:   return(0);
315: }

319: PetscErrorCode TSPrintHelp_Sundials(TS ts,char *p)
320: {

324:   (*PetscHelpPrintf)(ts->comm," Options for TSSUNDIALS integrater:\n");
325:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_type <bdf,adams>: integration approach\n",p);
326:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_atol aabs: absolute tolerance of ODE solution\n",p);
327:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_rtol rel: relative tolerance of ODE solution\n",p);
328:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_gramschmidt_type <unmodified,modified>\n");
329:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_gmres_restart <restart_size> (also max. GMRES its)\n");
330:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_linear_tolerance <tol>\n");
331:   (*PetscHelpPrintf)(ts->comm," -ts_sundials_not_exact_final_time\n");
332:   return(0);
333: }

337: PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
338: {
339:   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
341:   char           *type;
342:   char            atype[] = "Adams";
343:   char            btype[] = "BDF: backward differentiation formula";
344:   PetscTruth     iascii,isstring;

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

350:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
351:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
352:   if (iascii) {
353:     PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");
354:     PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);
355:     PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);
356:     PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);
357:     PetscViewerASCIIPrintf(viewer,"Sundials GMRES max iterations (same as restart in SUNDIALS) %D\n",cvode->restart);
358:     if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
359:       PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");
360:     } else {
361:       PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");
362:     }
363:   } else if (isstring) {
364:     PetscViewerStringSPrintf(viewer,"Sundials type %s",type);
365:   } else {
366:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by TS Sundials",((PetscObject)viewer)->type_name);
367:   }
368:   PetscViewerASCIIPushTab(viewer);
369:   PCView(cvode->pc,viewer);
370:   PetscViewerASCIIPopTab(viewer);
371:   return(0);
372: }


375: /* --------------------------------------------------------------------------*/
379: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType_Sundials(TS ts,TSSundialsType type)
380: {
381:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
382: 
384:   cvode->cvode_type = type;
385:   return(0);
386: }

392: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart_Sundials(TS ts,int restart)
393: {
394:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
395: 
397:   cvode->restart = restart;
398:   return(0);
399: }

405: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
406: {
407:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
408: 
410:   cvode->linear_tol = tol;
411:   return(0);
412: }

418: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
419: {
420:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
421: 
423:   cvode->gtype = type;
424:   return(0);
425: }

431: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
432: {
433:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
434: 
436:   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
437:   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
438:   return(0);
439: }

445: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC_Sundials(TS ts,PC *pc)
446: {
447:   TS_Sundials *cvode = (TS_Sundials*)ts->data;

450:   *pc = cvode->pc;
451:   return(0);
452: }

458: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
459: {
460:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
461: 
463:   if (nonlin) *nonlin = cvode->nonlinear_solves;
464:   if (lin)    *lin    = cvode->linear_solves;
465:   return(0);
466: }
468: 
472: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime_Sundials(TS ts,PetscTruth s)
473: {
474:   TS_Sundials *cvode = (TS_Sundials*)ts->data;
475: 
477:   cvode->exact_final_time = s;
478:   return(0);
479: }
481: /* -------------------------------------------------------------------------------------------*/

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

488:    Not Collective

490:    Input parameters:
491: .    ts     - the time-step context

493:    Output Parameters:
494: +   nonlin - number of nonlinear iterations
495: -   lin    - number of linear iterations

497:    Level: advanced

499:    Notes:
500:     These return the number since the creation of the TS object

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

504: .seealso: TSSundialsSetType(), TSSundialsSetGMRESRestart(),
505:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
506:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
507:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
508:           TSSundialsSetExactFinalTime()

510: @*/
511: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
512: {
513:   PetscErrorCode ierr,(*f)(TS,int*,int*);
514: 
516:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetIterations_C",(void (**)(void))&f);
517:   if (f) {
518:     (*f)(ts,nonlin,lin);
519:   }
520:   return(0);
521: }

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

528:    Collective on TS

530:    Input parameters:
531: +    ts     - the time-step context
532: -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF

534:    Level: intermediate

536: .keywords: Adams, backward differentiation formula

538: .seealso: TSSundialsGetIterations(),  TSSundialsSetGMRESRestart(),
539:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
540:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
541:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
542:           TSSundialsSetExactFinalTime()
543: @*/
544: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType(TS ts,TSSundialsType type)
545: {
546:   PetscErrorCode ierr,(*f)(TS,TSSundialsType);
547: 
549:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetType_C",(void (**)(void))&f);
550:   if (f) {
551:     (*f)(ts,type);
552:   }
553:   return(0);
554: }

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

563:    Collective on TS

565:    Input parameters:
566: +    ts      - the time-step context
567: -    restart - number of direction vectors (the restart size).

569:    Level: advanced

571: .keywords: GMRES, restart

573: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), 
574:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
575:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
576:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
577:           TSSundialsSetExactFinalTime()

579: @*/
580: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart(TS ts,int restart)
581: {
582:   PetscErrorCode ierr,(*f)(TS,int);

585:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGMRESRestart_C",(void (**)(void))&f);
586:   if (f) {
587:     (*f)(ts,restart);
588:   }
589:   return(0);
590: }

594: /*@
595:    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
596:        system by SUNDIALS.

598:    Collective on TS

600:    Input parameters:
601: +    ts     - the time-step context
602: -    tol    - the factor by which the tolerance on the nonlinear solver is
603:              multiplied to get the tolerance on the linear solver, .05 by default.

605:    Level: advanced

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

609: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
610:           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
611:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
612:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
613:           TSSundialsSetExactFinalTime()

615: @*/
616: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance(TS ts,double tol)
617: {
618:   PetscErrorCode ierr,(*f)(TS,double);
619: 
621:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",(void (**)(void))&f);
622:   if (f) {
623:     (*f)(ts,tol);
624:   }
625:   return(0);
626: }

630: /*@
631:    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
632:         in GMRES method by SUNDIALS linear solver.

634:    Collective on TS

636:    Input parameters:
637: +    ts  - the time-step context
638: -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS

640:    Level: advanced

642: .keywords: Sundials, orthogonalization

644: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
645:           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
646:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
647:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
648:           TSSundialsSetExactFinalTime()

650: @*/
651: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
652: {
653:   PetscErrorCode ierr,(*f)(TS,TSSundialsGramSchmidtType);
654: 
656:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",(void (**)(void))&f);
657:   if (f) {
658:     (*f)(ts,type);
659:   }
660:   return(0);
661: }

665: /*@
666:    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by 
667:                          Sundials for error control.

669:    Collective on TS

671:    Input parameters:
672: +    ts  - the time-step context
673: .    aabs - the absolute tolerance  
674: -    rel - the relative tolerance

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

679:    Level: intermediate

681: .keywords: Sundials, tolerance

683: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
684:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), 
685:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
686:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
687:           TSSundialsSetExactFinalTime()

689: @*/
690: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance(TS ts,double aabs,double rel)
691: {
692:   PetscErrorCode ierr,(*f)(TS,double,double);
693: 
695:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetTolerance_C",(void (**)(void))&f);
696:   if (f) {
697:     (*f)(ts,aabs,rel);
698:   }
699:   return(0);
700: }

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

707:    Input Parameter:
708: .    ts - the time-step context

710:    Output Parameter:
711: .    pc - the preconditioner context

713:    Level: advanced

715: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
716:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
717:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
718:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
719: @*/
720: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC(TS ts,PC *pc)
721: {
722:   PetscErrorCode ierr,(*f)(TS,PC *);

725:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetPC_C",(void (**)(void))&f);
726:   if (f) {
727:     (*f)(ts,pc);
728:   } else {
729:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"TS must be of Sundials type to extract the PC");
730:   }

732:   return(0);
733: }

737: /*@
738:    TSSundialsSetExactFinalTime - Determines if Sundials interpolates solution to the 
739:       exact final time requested by the user or just returns it at the final time
740:       it computed. (Defaults to true).

742:    Input Parameter:
743: +   ts - the time-step context
744: -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE

746:    Level: beginner

748: .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
749:           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
750:           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
751:           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC() 
752: @*/
753: PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime(TS ts,PetscTruth ft)
754: {
755:   PetscErrorCode ierr,(*f)(TS,PetscTruth);

758:   PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetExactFinalTime_C",(void (**)(void))&f);
759:   if (f) {
760:     (*f)(ts,ft);
761:   }
762:   return(0);
763: }

765: /* -------------------------------------------------------------------------------------------*/
766: /*MC
767:       TS_Sundials - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)

769:    Options Database:
770: +    -ts_sundials_type <bdf,adams>
771: .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
772: .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
773: .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
774: .    -ts_sundials_linear_tolerance <tol> 
775: .    -ts_sundials_gmres_restart <restart> - Number of GMRES orthogonalization directions
776: -    -ts_sundials_not_exact_final_time -Allow SUNDIALS to stop near the final time, not exactly on it

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

781:     Level: beginner

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

786: M*/
790: PetscErrorCode PETSCTS_DLLEXPORT TSCreate_Sundials(TS ts)
791: {
792:   TS_Sundials *cvode;

796:   ts->ops->destroy         = TSDestroy_Sundials;
797:   ts->ops->view            = TSView_Sundials;

799:   if (ts->problem_type != TS_NONLINEAR) {
800:     SETERRQ(PETSC_ERR_SUP,"Only support for nonlinear problems");
801:   }
802:   ts->ops->setup           = TSSetUp_Sundials_Nonlinear;
803:   ts->ops->step            = TSStep_Sundials_Nonlinear;
804:   ts->ops->setfromoptions  = TSSetFromOptions_Sundials_Nonlinear;

806:   PetscNew(TS_Sundials,&cvode);
807:   PCCreate(ts->comm,&cvode->pc);
808:   PetscLogObjectParent(ts,cvode->pc);
809:   ts->data          = (void*)cvode;
810:   cvode->cvode_type = CV_BDF;
811:   cvode->gtype      = SUNDIALS_UNMODIFIED_GS;
812:   cvode->restart    = 5;
813:   cvode->linear_tol = .05;

815:   cvode->exact_final_time = PETSC_FALSE;

817:   MPI_Comm_dup(ts->comm,&(cvode->comm_sundials));
818:   /* set tolerance for Sundials */
819:   cvode->abstol = 1e-6;
820:   cvode->reltol = 1e-6;

822:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetType_C","TSSundialsSetType_Sundials",
823:                     TSSundialsSetType_Sundials);
824:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGMRESRestart_C",
825:                     "TSSundialsSetGMRESRestart_Sundials",
826:                     TSSundialsSetGMRESRestart_Sundials);
827:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetLinearTolerance_C",
828:                     "TSSundialsSetLinearTolerance_Sundials",
829:                      TSSundialsSetLinearTolerance_Sundials);
830:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",
831:                     "TSSundialsSetGramSchmidtType_Sundials",
832:                      TSSundialsSetGramSchmidtType_Sundials);
833:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetTolerance_C",
834:                     "TSSundialsSetTolerance_Sundials",
835:                      TSSundialsSetTolerance_Sundials);
836:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetPC_C",
837:                     "TSSundialsGetPC_Sundials",
838:                      TSSundialsGetPC_Sundials);
839:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetIterations_C",
840:                     "TSSundialsGetIterations_Sundials",
841:                      TSSundialsGetIterations_Sundials);
842:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetExactFinalTime_C",
843:                     "TSSundialsSetExactFinalTime_Sundials",
844:                      TSSundialsSetExactFinalTime_Sundials);
845:   return(0);
846: }