xref: /petsc/src/ts/impls/implicit/sundials/sundials.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1 /*
2     Provides a PETSc interface to SUNDIALS/CVODE solver.
3     The interface to PVODE (old version of CVODE) was originally contributed
4     by Liyang Xu. It has been redone by Hong Zhang and Dinesh Kaushik.
5 
6     Reference: sundials-2.4.0/examples/cvode/parallel/cvDiurnal_kry_p.c
7 */
8 #include <../src/ts/impls/implicit/sundials/sundials.h>  /*I "petscts.h" I*/
9 
10 /*
11       TSPrecond_Sundials - function that we provide to SUNDIALS to
12                         evaluate the preconditioner.
13 */
14 PetscErrorCode TSPrecond_Sundials(realtype tn,N_Vector y,N_Vector fy,booleantype jok,booleantype *jcurPtr,
15                                   realtype _gamma,void *P_data,N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
16 {
17   TS             ts     = (TS) P_data;
18   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
19   PC             pc;
20   PetscErrorCode ierr;
21   Mat            J,P;
22   Vec            yy  = cvode->w1,yydot = cvode->ydot;
23   PetscReal      gm  = (PetscReal)_gamma;
24   PetscScalar    *y_data;
25 
26   PetscFunctionBegin;
27   ierr   = TSGetIJacobian(ts,&J,&P,NULL,NULL);CHKERRQ(ierr);
28   y_data = (PetscScalar*) N_VGetArrayPointer(y);
29   ierr   = VecPlaceArray(yy,y_data);CHKERRQ(ierr);
30   ierr   = VecZeroEntries(yydot);CHKERRQ(ierr); /* The Jacobian is independent of Ydot for ODE which is all that CVode works for */
31   /* compute the shifted Jacobian   (1/gm)*I + Jrest */
32   ierr     = TSComputeIJacobian(ts,ts->ptime,yy,yydot,1/gm,J,P,PETSC_FALSE);CHKERRQ(ierr);
33   ierr     = VecResetArray(yy);CHKERRQ(ierr);
34   ierr     = MatScale(P,gm);CHKERRQ(ierr); /* turn into I-gm*Jrest, J is not used by Sundials  */
35   *jcurPtr = TRUE;
36   ierr     = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
37   ierr     = PCSetOperators(pc,J,P);CHKERRQ(ierr);
38   PetscFunctionReturn(0);
39 }
40 
41 /*
42      TSPSolve_Sundials -  routine that we provide to Sundials that applies the preconditioner.
43 */
44 PetscErrorCode TSPSolve_Sundials(realtype tn,N_Vector y,N_Vector fy,N_Vector r,N_Vector z,
45                                  realtype _gamma,realtype delta,int lr,void *P_data,N_Vector vtemp)
46 {
47   TS             ts     = (TS) P_data;
48   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
49   PC             pc;
50   Vec            rr = cvode->w1,zz = cvode->w2;
51   PetscErrorCode ierr;
52   PetscScalar    *r_data,*z_data;
53 
54   PetscFunctionBegin;
55   /* Make the PETSc work vectors rr and zz point to the arrays in the SUNDIALS vectors r and z respectively*/
56   r_data = (PetscScalar*) N_VGetArrayPointer(r);
57   z_data = (PetscScalar*) N_VGetArrayPointer(z);
58   ierr   = VecPlaceArray(rr,r_data);CHKERRQ(ierr);
59   ierr   = VecPlaceArray(zz,z_data);CHKERRQ(ierr);
60 
61   /* Solve the Px=r and put the result in zz */
62   ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
63   ierr = PCApply(pc,rr,zz);CHKERRQ(ierr);
64   ierr = VecResetArray(rr);CHKERRQ(ierr);
65   ierr = VecResetArray(zz);CHKERRQ(ierr);
66   PetscFunctionReturn(0);
67 }
68 
69 /*
70         TSFunction_Sundials - routine that we provide to Sundials that applies the right hand side.
71 */
72 int TSFunction_Sundials(realtype t,N_Vector y,N_Vector ydot,void *ctx)
73 {
74   TS             ts = (TS) ctx;
75   DM             dm;
76   DMTS           tsdm;
77   TSIFunction    ifunction;
78   MPI_Comm       comm;
79   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
80   Vec            yy     = cvode->w1,yyd = cvode->w2,yydot = cvode->ydot;
81   PetscScalar    *y_data,*ydot_data;
82   PetscErrorCode ierr;
83 
84   PetscFunctionBegin;
85   ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
86   /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/
87   y_data    = (PetscScalar*) N_VGetArrayPointer(y);
88   ydot_data = (PetscScalar*) N_VGetArrayPointer(ydot);
89   ierr      = VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr);
90   ierr      = VecPlaceArray(yyd,ydot_data);CHKERRABORT(comm,ierr);
91 
92   /* Now compute the right hand side function, via IFunction unless only the more efficient RHSFunction is set */
93   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
94   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
95   ierr = DMTSGetIFunction(dm,&ifunction,NULL);CHKERRQ(ierr);
96   if (!ifunction) {
97     ierr = TSComputeRHSFunction(ts,t,yy,yyd);CHKERRQ(ierr);
98   } else {                      /* If rhsfunction is also set, this computes both parts and shifts them to the right */
99     ierr = VecZeroEntries(yydot);CHKERRQ(ierr);
100     ierr = TSComputeIFunction(ts,t,yy,yydot,yyd,PETSC_FALSE);CHKERRABORT(comm,ierr);
101     ierr = VecScale(yyd,-1.);CHKERRQ(ierr);
102   }
103   ierr = VecResetArray(yy);CHKERRABORT(comm,ierr);
104   ierr = VecResetArray(yyd);CHKERRABORT(comm,ierr);
105   PetscFunctionReturn(0);
106 }
107 
108 /*
109        TSStep_Sundials - Calls Sundials to integrate the ODE.
110 */
111 PetscErrorCode TSStep_Sundials(TS ts)
112 {
113   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
114   PetscErrorCode ierr;
115   PetscInt       flag;
116   long int       nits,lits,nsteps;
117   realtype       t,tout;
118   PetscScalar    *y_data;
119   void           *mem;
120 
121   PetscFunctionBegin;
122   mem  = cvode->mem;
123   tout = ts->max_time;
124   ierr = VecGetArray(ts->vec_sol,&y_data);CHKERRQ(ierr);
125   N_VSetArrayPointer((realtype*)y_data,cvode->y);
126   ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr);
127 
128   /* We would like to TSPreStage() and TSPostStage()
129    * before each stage solve but CVode does not appear to support this. */
130   if (cvode->monitorstep)
131     flag = CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);
132   else
133     flag = CVode(mem,tout,cvode->y,&t,CV_NORMAL);
134 
135   if (flag) { /* display error message */
136     switch (flag) {
137       case CV_ILL_INPUT:
138         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_ILL_INPUT");
139         break;
140       case CV_TOO_CLOSE:
141         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_CLOSE");
142         break;
143       case CV_TOO_MUCH_WORK: {
144         PetscReal tcur;
145         ierr = CVodeGetNumSteps(mem,&nsteps);CHKERRQ(ierr);
146         ierr = CVodeGetCurrentTime(mem,&tcur);CHKERRQ(ierr);
147         SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_MUCH_WORK. At t=%g, nsteps %D exceeds maxstep %D. Increase '-ts_max_steps <>' or modify TSSetMaxSteps()",(double)tcur,nsteps,ts->max_steps);
148       } break;
149       case CV_TOO_MUCH_ACC:
150         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_MUCH_ACC");
151         break;
152       case CV_ERR_FAILURE:
153         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_ERR_FAILURE");
154         break;
155       case CV_CONV_FAILURE:
156         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_CONV_FAILURE");
157         break;
158       case CV_LINIT_FAIL:
159         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LINIT_FAIL");
160         break;
161       case CV_LSETUP_FAIL:
162         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LSETUP_FAIL");
163         break;
164       case CV_LSOLVE_FAIL:
165         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LSOLVE_FAIL");
166         break;
167       case CV_RHSFUNC_FAIL:
168         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_RHSFUNC_FAIL");
169         break;
170       case CV_FIRST_RHSFUNC_ERR:
171         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_FIRST_RHSFUNC_ERR");
172         break;
173       case CV_REPTD_RHSFUNC_ERR:
174         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_REPTD_RHSFUNC_ERR");
175         break;
176       case CV_UNREC_RHSFUNC_ERR:
177         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_UNREC_RHSFUNC_ERR");
178         break;
179       case CV_RTFUNC_FAIL:
180         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_RTFUNC_FAIL");
181         break;
182       default:
183         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, flag %d",flag);
184     }
185   }
186 
187   /* log inner nonlinear and linear iterations */
188   ierr = CVodeGetNumNonlinSolvIters(mem,&nits);CHKERRQ(ierr);
189   ierr = CVSpilsGetNumLinIters(mem,&lits);CHKERRQ(ierr);
190   ts->snes_its += nits; ts->ksp_its = lits;
191 
192   /* copy the solution from cvode->y to cvode->update and sol */
193   ierr = VecPlaceArray(cvode->w1,y_data);CHKERRQ(ierr);
194   ierr = VecCopy(cvode->w1,cvode->update);CHKERRQ(ierr);
195   ierr = VecResetArray(cvode->w1);CHKERRQ(ierr);
196   ierr = VecCopy(cvode->update,ts->vec_sol);CHKERRQ(ierr);
197 
198   ts->time_step = t - ts->ptime;
199   ts->ptime = t;
200 
201   ierr = CVodeGetNumSteps(mem,&nsteps);CHKERRQ(ierr);
202   if (!cvode->monitorstep) ts->steps += nsteps - 1; /* TSStep() increments the step counter by one */
203   PetscFunctionReturn(0);
204 }
205 
206 static PetscErrorCode TSInterpolate_Sundials(TS ts,PetscReal t,Vec X)
207 {
208   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
209   N_Vector       y;
210   PetscErrorCode ierr;
211   PetscScalar    *x_data;
212   PetscInt       glosize,locsize;
213 
214   PetscFunctionBegin;
215   /* get the vector size */
216   ierr = VecGetSize(X,&glosize);CHKERRQ(ierr);
217   ierr = VecGetLocalSize(X,&locsize);CHKERRQ(ierr);
218 
219   /* allocate the memory for N_Vec y */
220   y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
221   if (!y) SETERRQ(PETSC_COMM_SELF,1,"Interpolated y is not allocated");
222 
223   ierr = VecGetArray(X,&x_data);CHKERRQ(ierr);
224   N_VSetArrayPointer((realtype*)x_data,y);
225   ierr = CVodeGetDky(cvode->mem,t,0,y);CHKERRQ(ierr);
226   ierr = VecRestoreArray(X,&x_data);CHKERRQ(ierr);
227   PetscFunctionReturn(0);
228 }
229 
230 PetscErrorCode TSReset_Sundials(TS ts)
231 {
232   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
233   PetscErrorCode ierr;
234 
235   PetscFunctionBegin;
236   ierr = VecDestroy(&cvode->update);CHKERRQ(ierr);
237   ierr = VecDestroy(&cvode->ydot);CHKERRQ(ierr);
238   ierr = VecDestroy(&cvode->w1);CHKERRQ(ierr);
239   ierr = VecDestroy(&cvode->w2);CHKERRQ(ierr);
240   if (cvode->mem) CVodeFree(&cvode->mem);
241   PetscFunctionReturn(0);
242 }
243 
244 PetscErrorCode TSDestroy_Sundials(TS ts)
245 {
246   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
247   PetscErrorCode ierr;
248 
249   PetscFunctionBegin;
250   ierr = TSReset_Sundials(ts);CHKERRQ(ierr);
251   ierr = MPI_Comm_free(&(cvode->comm_sundials));CHKERRQ(ierr);
252   ierr = PetscFree(ts->data);CHKERRQ(ierr);
253   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetType_C",NULL);CHKERRQ(ierr);
254   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxl_C",NULL);CHKERRQ(ierr);
255   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",NULL);CHKERRQ(ierr);
256   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",NULL);CHKERRQ(ierr);
257   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetTolerance_C",NULL);CHKERRQ(ierr);
258   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMinTimeStep_C",NULL);CHKERRQ(ierr);
259   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",NULL);CHKERRQ(ierr);
260   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetPC_C",NULL);CHKERRQ(ierr);
261   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetIterations_C",NULL);CHKERRQ(ierr);
262   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",NULL);CHKERRQ(ierr);
263   PetscFunctionReturn(0);
264 }
265 
266 PetscErrorCode TSSetUp_Sundials(TS ts)
267 {
268   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
269   PetscErrorCode ierr;
270   PetscInt       glosize,locsize,i,flag;
271   PetscScalar    *y_data,*parray;
272   void           *mem;
273   PC             pc;
274   PCType         pctype;
275   PetscBool      pcnone;
276 
277   PetscFunctionBegin;
278   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for exact final time option 'MATCHSTEP' when using Sundials");
279 
280   /* get the vector size */
281   ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr);
282   ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr);
283 
284   /* allocate the memory for N_Vec y */
285   cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
286   if (!cvode->y) SETERRQ(PETSC_COMM_SELF,1,"cvode->y is not allocated");
287 
288   /* initialize N_Vec y: copy ts->vec_sol to cvode->y */
289   ierr   = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr);
290   y_data = (PetscScalar*) N_VGetArrayPointer(cvode->y);
291   for (i = 0; i < locsize; i++) y_data[i] = parray[i];
292   ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr);
293 
294   ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr);
295   ierr = VecDuplicate(ts->vec_sol,&cvode->ydot);CHKERRQ(ierr);
296   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->update);CHKERRQ(ierr);
297   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->ydot);CHKERRQ(ierr);
298 
299   /*
300     Create work vectors for the TSPSolve_Sundials() routine. Note these are
301     allocated with zero space arrays because the actual array space is provided
302     by Sundials and set using VecPlaceArray().
303   */
304   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr);
305   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr);
306   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w1);CHKERRQ(ierr);
307   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w2);CHKERRQ(ierr);
308 
309   /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */
310   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
311   if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails");
312   cvode->mem = mem;
313 
314   /* Set the pointer to user-defined data */
315   flag = CVodeSetUserData(mem, ts);
316   if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails");
317 
318   /* Sundials may choose to use a smaller initial step, but will never use a larger step. */
319   flag = CVodeSetInitStep(mem,(realtype)ts->time_step);
320   if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetInitStep() failed");
321   if (cvode->mindt > 0) {
322     flag = CVodeSetMinStep(mem,(realtype)cvode->mindt);
323     if (flag) {
324       if (flag == CV_MEM_NULL) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL");
325       else if (flag == CV_ILL_INPUT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, hmin is nonpositive or it exceeds the maximum allowable step size");
326       else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed");
327     }
328   }
329   if (cvode->maxdt > 0) {
330     flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt);
331     if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMaxStep() failed");
332   }
333 
334   /* Call CVodeInit to initialize the integrator memory and specify the
335    * user's right hand side function in u'=f(t,u), the inital time T0, and
336    * the initial dependent variable vector cvode->y */
337   flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y);
338   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag);
339 
340   /* specifies scalar relative and absolute tolerances */
341   flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol);
342   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag);
343 
344   /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */
345   flag = CVodeSetMaxNumSteps(mem,ts->max_steps);
346   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetMaxNumSteps() fails, flag %d",flag);
347 
348   /* call CVSpgmr to use GMRES as the linear solver.        */
349   /* setup the ode integrator with the given preconditioner */
350   ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
351   ierr = PCGetType(pc,&pctype);CHKERRQ(ierr);
352   ierr = PetscObjectTypeCompare((PetscObject)pc,PCNONE,&pcnone);CHKERRQ(ierr);
353   if (pcnone) {
354     flag = CVSpgmr(mem,PREC_NONE,0);
355     if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag);
356   } else {
357     flag = CVSpgmr(mem,PREC_LEFT,cvode->maxl);
358     if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag);
359 
360     /* Set preconditioner and solve routines Precond and PSolve,
361      and the pointer to the user-defined block data */
362     flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials);
363     if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag);
364   }
365 
366   flag = CVSpilsSetGSType(mem, MODIFIED_GS);
367   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmrSetGSType() fails, flag %d",flag);
368   PetscFunctionReturn(0);
369 }
370 
371 /* type of CVODE linear multistep method */
372 const char *const TSSundialsLmmTypes[] = {"","ADAMS","BDF","TSSundialsLmmType","SUNDIALS_",0};
373 /* type of G-S orthogonalization used by CVODE linear solver */
374 const char *const TSSundialsGramSchmidtTypes[] = {"","MODIFIED","CLASSICAL","TSSundialsGramSchmidtType","SUNDIALS_",0};
375 
376 PetscErrorCode TSSetFromOptions_Sundials(PetscOptionItems *PetscOptionsObject,TS ts)
377 {
378   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
379   PetscErrorCode ierr;
380   int            indx;
381   PetscBool      flag;
382   PC             pc;
383 
384   PetscFunctionBegin;
385   ierr = PetscOptionsHead(PetscOptionsObject,"SUNDIALS ODE solver options");CHKERRQ(ierr);
386   ierr = PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);CHKERRQ(ierr);
387   if (flag) {
388     ierr = TSSundialsSetType(ts,(TSSundialsLmmType)indx);CHKERRQ(ierr);
389   }
390   ierr = PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);CHKERRQ(ierr);
391   if (flag) {
392     ierr = TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);CHKERRQ(ierr);
393   }
394   ierr = PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,NULL);CHKERRQ(ierr);
395   ierr = PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,NULL);CHKERRQ(ierr);
396   ierr = PetscOptionsReal("-ts_sundials_mindt","Minimum step size","TSSundialsSetMinTimeStep",cvode->mindt,&cvode->mindt,NULL);CHKERRQ(ierr);
397   ierr = PetscOptionsReal("-ts_sundials_maxdt","Maximum step size","TSSundialsSetMaxTimeStep",cvode->maxdt,&cvode->maxdt,NULL);CHKERRQ(ierr);
398   ierr = PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,NULL);CHKERRQ(ierr);
399   ierr = PetscOptionsInt("-ts_sundials_maxl","Max dimension of the Krylov subspace","TSSundialsSetMaxl",cvode->maxl,&cvode->maxl,NULL);CHKERRQ(ierr);
400   ierr = PetscOptionsBool("-ts_sundials_monitor_steps","Monitor SUNDIALS internal steps","TSSundialsMonitorInternalSteps",cvode->monitorstep,&cvode->monitorstep,NULL);CHKERRQ(ierr);
401   ierr = PetscOptionsTail();CHKERRQ(ierr);
402   ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
403   ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
404   PetscFunctionReturn(0);
405 }
406 
407 PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
408 {
409   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
410   PetscErrorCode ierr;
411   char           *type;
412   char           atype[] = "Adams";
413   char           btype[] = "BDF: backward differentiation formula";
414   PetscBool      iascii,isstring;
415   long int       nsteps,its,nfevals,nlinsetups,nfails,itmp;
416   PetscInt       qlast,qcur;
417   PetscReal      hinused,hlast,hcur,tcur,tolsfac;
418   PC             pc;
419 
420   PetscFunctionBegin;
421   if (cvode->cvode_type == SUNDIALS_ADAMS) type = atype;
422   else                                     type = btype;
423 
424   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
425   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
426   if (iascii) {
427     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");CHKERRQ(ierr);
428     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);CHKERRQ(ierr);
429     ierr = PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);CHKERRQ(ierr);
430     ierr = PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);CHKERRQ(ierr);
431     ierr = PetscViewerASCIIPrintf(viewer,"Sundials max dimension of Krylov subspace %D\n",cvode->maxl);CHKERRQ(ierr);
432     if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
433       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
434     } else {
435       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
436     }
437     if (cvode->mindt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials minimum time step %g\n",cvode->mindt);CHKERRQ(ierr);}
438     if (cvode->maxdt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials maximum time step %g\n",cvode->maxdt);CHKERRQ(ierr);}
439 
440     /* Outputs from CVODE, CVSPILS */
441     ierr = CVodeGetTolScaleFactor(cvode->mem,&tolsfac);CHKERRQ(ierr);
442     ierr = PetscViewerASCIIPrintf(viewer,"Sundials suggested factor for tolerance scaling %g\n",tolsfac);CHKERRQ(ierr);
443     ierr = CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
444                                    &nlinsetups,&nfails,&qlast,&qcur,
445                                    &hinused,&hlast,&hcur,&tcur);CHKERRQ(ierr);
446     ierr = PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);CHKERRQ(ierr);
447     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);CHKERRQ(ierr);
448     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);CHKERRQ(ierr);
449     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);CHKERRQ(ierr);
450 
451     ierr = CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);CHKERRQ(ierr);
452     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);CHKERRQ(ierr);
453     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);CHKERRQ(ierr);
454 
455     ierr = CVSpilsGetNumLinIters(cvode->mem, &its);CHKERRQ(ierr); /* its = no. of calls to TSPrecond_Sundials() */
456     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);CHKERRQ(ierr);
457     ierr = CVSpilsGetNumConvFails(cvode->mem,&itmp);CHKERRQ(ierr);
458     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);CHKERRQ(ierr);
459 
460     ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
461     ierr = PCView(pc,viewer);CHKERRQ(ierr);
462     ierr = CVSpilsGetNumPrecEvals(cvode->mem,&itmp);CHKERRQ(ierr);
463     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);CHKERRQ(ierr);
464     ierr = CVSpilsGetNumPrecSolves(cvode->mem,&itmp);CHKERRQ(ierr);
465     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);CHKERRQ(ierr);
466 
467     ierr = CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);CHKERRQ(ierr);
468     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);CHKERRQ(ierr);
469     ierr = CVSpilsGetNumRhsEvals(cvode->mem,&itmp);CHKERRQ(ierr);
470     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);CHKERRQ(ierr);
471   } else if (isstring) {
472     ierr = PetscViewerStringSPrintf(viewer,"Sundials type %s",type);CHKERRQ(ierr);
473   }
474   PetscFunctionReturn(0);
475 }
476 
477 
478 /* --------------------------------------------------------------------------*/
479 PetscErrorCode  TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
480 {
481   TS_Sundials *cvode = (TS_Sundials*)ts->data;
482 
483   PetscFunctionBegin;
484   cvode->cvode_type = type;
485   PetscFunctionReturn(0);
486 }
487 
488 PetscErrorCode  TSSundialsSetMaxl_Sundials(TS ts,PetscInt maxl)
489 {
490   TS_Sundials *cvode = (TS_Sundials*)ts->data;
491 
492   PetscFunctionBegin;
493   cvode->maxl = maxl;
494   PetscFunctionReturn(0);
495 }
496 
497 PetscErrorCode  TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
498 {
499   TS_Sundials *cvode = (TS_Sundials*)ts->data;
500 
501   PetscFunctionBegin;
502   cvode->linear_tol = tol;
503   PetscFunctionReturn(0);
504 }
505 
506 PetscErrorCode  TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
507 {
508   TS_Sundials *cvode = (TS_Sundials*)ts->data;
509 
510   PetscFunctionBegin;
511   cvode->gtype = type;
512   PetscFunctionReturn(0);
513 }
514 
515 PetscErrorCode  TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
516 {
517   TS_Sundials *cvode = (TS_Sundials*)ts->data;
518 
519   PetscFunctionBegin;
520   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
521   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
522   PetscFunctionReturn(0);
523 }
524 
525 PetscErrorCode  TSSundialsSetMinTimeStep_Sundials(TS ts,PetscReal mindt)
526 {
527   TS_Sundials *cvode = (TS_Sundials*)ts->data;
528 
529   PetscFunctionBegin;
530   cvode->mindt = mindt;
531   PetscFunctionReturn(0);
532 }
533 
534 PetscErrorCode  TSSundialsSetMaxTimeStep_Sundials(TS ts,PetscReal maxdt)
535 {
536   TS_Sundials *cvode = (TS_Sundials*)ts->data;
537 
538   PetscFunctionBegin;
539   cvode->maxdt = maxdt;
540   PetscFunctionReturn(0);
541 }
542 PetscErrorCode  TSSundialsGetPC_Sundials(TS ts,PC *pc)
543 {
544   SNES           snes;
545   KSP            ksp;
546   PetscErrorCode ierr;
547 
548   PetscFunctionBegin;
549   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
550   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
551   ierr = KSPGetPC(ksp,pc);CHKERRQ(ierr);
552   PetscFunctionReturn(0);
553 }
554 
555 PetscErrorCode  TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
556 {
557   PetscFunctionBegin;
558   if (nonlin) *nonlin = ts->snes_its;
559   if (lin)    *lin    = ts->ksp_its;
560   PetscFunctionReturn(0);
561 }
562 
563 PetscErrorCode  TSSundialsMonitorInternalSteps_Sundials(TS ts,PetscBool s)
564 {
565   TS_Sundials *cvode = (TS_Sundials*)ts->data;
566 
567   PetscFunctionBegin;
568   cvode->monitorstep = s;
569   PetscFunctionReturn(0);
570 }
571 /* -------------------------------------------------------------------------------------------*/
572 
573 /*@C
574    TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.
575 
576    Not Collective
577 
578    Input parameters:
579 .    ts     - the time-step context
580 
581    Output Parameters:
582 +   nonlin - number of nonlinear iterations
583 -   lin    - number of linear iterations
584 
585    Level: advanced
586 
587    Notes:
588     These return the number since the creation of the TS object
589 
590 .keywords: non-linear iterations, linear iterations
591 
592 .seealso: TSSundialsSetType(), TSSundialsSetMaxl(),
593           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
594           TSSundialsGetIterations(), TSSundialsSetType(),
595           TSSundialsSetLinearTolerance(), TSSundialsGetPC(), TSSetExactFinalTime()
596 
597 @*/
598 PetscErrorCode  TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
599 {
600   PetscErrorCode ierr;
601 
602   PetscFunctionBegin;
603   ierr = PetscUseMethod(ts,"TSSundialsGetIterations_C",(TS,int*,int*),(ts,nonlin,lin));CHKERRQ(ierr);
604   PetscFunctionReturn(0);
605 }
606 
607 /*@
608    TSSundialsSetType - Sets the method that Sundials will use for integration.
609 
610    Logically Collective on TS
611 
612    Input parameters:
613 +    ts     - the time-step context
614 -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF
615 
616    Level: intermediate
617 
618 .keywords: Adams, backward differentiation formula
619 
620 .seealso: TSSundialsGetIterations(),  TSSundialsSetMaxl(),
621           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
622           TSSundialsGetIterations(), TSSundialsSetType(),
623           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
624           TSSetExactFinalTime()
625 @*/
626 PetscErrorCode  TSSundialsSetType(TS ts,TSSundialsLmmType type)
627 {
628   PetscErrorCode ierr;
629 
630   PetscFunctionBegin;
631   ierr = PetscTryMethod(ts,"TSSundialsSetType_C",(TS,TSSundialsLmmType),(ts,type));CHKERRQ(ierr);
632   PetscFunctionReturn(0);
633 }
634 
635 /*@
636    TSSundialsSetMaxl - Sets the dimension of the Krylov space used by
637        GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
638        this is the maximum number of GMRES steps that will be used.
639 
640    Logically Collective on TS
641 
642    Input parameters:
643 +    ts      - the time-step context
644 -    maxl - number of direction vectors (the dimension of Krylov subspace).
645 
646    Level: advanced
647 
648 .keywords: GMRES
649 
650 .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
651           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
652           TSSundialsGetIterations(), TSSundialsSetType(),
653           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
654           TSSetExactFinalTime()
655 
656 @*/
657 PetscErrorCode  TSSundialsSetMaxl(TS ts,PetscInt maxl)
658 {
659   PetscErrorCode ierr;
660 
661   PetscFunctionBegin;
662   PetscValidLogicalCollectiveInt(ts,maxl,2);
663   ierr = PetscTryMethod(ts,"TSSundialsSetMaxl_C",(TS,PetscInt),(ts,maxl));CHKERRQ(ierr);
664   PetscFunctionReturn(0);
665 }
666 
667 /*@
668    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
669        system by SUNDIALS.
670 
671    Logically Collective on TS
672 
673    Input parameters:
674 +    ts     - the time-step context
675 -    tol    - the factor by which the tolerance on the nonlinear solver is
676              multiplied to get the tolerance on the linear solver, .05 by default.
677 
678    Level: advanced
679 
680 .keywords: GMRES, linear convergence tolerance, SUNDIALS
681 
682 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
683           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
684           TSSundialsGetIterations(), TSSundialsSetType(),
685           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
686           TSSetExactFinalTime()
687 
688 @*/
689 PetscErrorCode  TSSundialsSetLinearTolerance(TS ts,double tol)
690 {
691   PetscErrorCode ierr;
692 
693   PetscFunctionBegin;
694   PetscValidLogicalCollectiveReal(ts,tol,2);
695   ierr = PetscTryMethod(ts,"TSSundialsSetLinearTolerance_C",(TS,double),(ts,tol));CHKERRQ(ierr);
696   PetscFunctionReturn(0);
697 }
698 
699 /*@
700    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
701         in GMRES method by SUNDIALS linear solver.
702 
703    Logically Collective on TS
704 
705    Input parameters:
706 +    ts  - the time-step context
707 -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS
708 
709    Level: advanced
710 
711 .keywords: Sundials, orthogonalization
712 
713 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
714           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
715           TSSundialsGetIterations(), TSSundialsSetType(),
716           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
717           TSSetExactFinalTime()
718 
719 @*/
720 PetscErrorCode  TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
721 {
722   PetscErrorCode ierr;
723 
724   PetscFunctionBegin;
725   ierr = PetscTryMethod(ts,"TSSundialsSetGramSchmidtType_C",(TS,TSSundialsGramSchmidtType),(ts,type));CHKERRQ(ierr);
726   PetscFunctionReturn(0);
727 }
728 
729 /*@
730    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by
731                          Sundials for error control.
732 
733    Logically Collective on TS
734 
735    Input parameters:
736 +    ts  - the time-step context
737 .    aabs - the absolute tolerance
738 -    rel - the relative tolerance
739 
740      See the Cvode/Sundials users manual for exact details on these parameters. Essentially
741     these regulate the size of the error for a SINGLE timestep.
742 
743    Level: intermediate
744 
745 .keywords: Sundials, tolerance
746 
747 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESMaxl(),
748           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(),
749           TSSundialsGetIterations(), TSSundialsSetType(),
750           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
751           TSSetExactFinalTime()
752 
753 @*/
754 PetscErrorCode  TSSundialsSetTolerance(TS ts,double aabs,double rel)
755 {
756   PetscErrorCode ierr;
757 
758   PetscFunctionBegin;
759   ierr = PetscTryMethod(ts,"TSSundialsSetTolerance_C",(TS,double,double),(ts,aabs,rel));CHKERRQ(ierr);
760   PetscFunctionReturn(0);
761 }
762 
763 /*@
764    TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.
765 
766    Input Parameter:
767 .    ts - the time-step context
768 
769    Output Parameter:
770 .    pc - the preconditioner context
771 
772    Level: advanced
773 
774 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
775           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
776           TSSundialsGetIterations(), TSSundialsSetType(),
777           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
778 @*/
779 PetscErrorCode  TSSundialsGetPC(TS ts,PC *pc)
780 {
781   PetscErrorCode ierr;
782 
783   PetscFunctionBegin;
784   ierr = PetscUseMethod(ts,"TSSundialsGetPC_C",(TS,PC*),(ts,pc));CHKERRQ(ierr);
785   PetscFunctionReturn(0);
786 }
787 
788 /*@
789    TSSundialsSetMinTimeStep - Smallest time step to be chosen by the adaptive controller.
790 
791    Input Parameter:
792 +   ts - the time-step context
793 -   mindt - lowest time step if positive, negative to deactivate
794 
795    Note:
796    Sundials will error if it is not possible to keep the estimated truncation error below
797    the tolerance set with TSSundialsSetTolerance() without going below this step size.
798 
799    Level: beginner
800 
801 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
802 @*/
803 PetscErrorCode  TSSundialsSetMinTimeStep(TS ts,PetscReal mindt)
804 {
805   PetscErrorCode ierr;
806 
807   PetscFunctionBegin;
808   ierr = PetscTryMethod(ts,"TSSundialsSetMinTimeStep_C",(TS,PetscReal),(ts,mindt));CHKERRQ(ierr);
809   PetscFunctionReturn(0);
810 }
811 
812 /*@
813    TSSundialsSetMaxTimeStep - Largest time step to be chosen by the adaptive controller.
814 
815    Input Parameter:
816 +   ts - the time-step context
817 -   maxdt - lowest time step if positive, negative to deactivate
818 
819    Level: beginner
820 
821 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
822 @*/
823 PetscErrorCode  TSSundialsSetMaxTimeStep(TS ts,PetscReal maxdt)
824 {
825   PetscErrorCode ierr;
826 
827   PetscFunctionBegin;
828   ierr = PetscTryMethod(ts,"TSSundialsSetMaxTimeStep_C",(TS,PetscReal),(ts,maxdt));CHKERRQ(ierr);
829   PetscFunctionReturn(0);
830 }
831 
832 /*@
833    TSSundialsMonitorInternalSteps - Monitor Sundials internal steps (Defaults to false).
834 
835    Input Parameter:
836 +   ts - the time-step context
837 -   ft - PETSC_TRUE if monitor, else PETSC_FALSE
838 
839    Level: beginner
840 
841 .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
842           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
843           TSSundialsGetIterations(), TSSundialsSetType(),
844           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
845 @*/
846 PetscErrorCode  TSSundialsMonitorInternalSteps(TS ts,PetscBool ft)
847 {
848   PetscErrorCode ierr;
849 
850   PetscFunctionBegin;
851   ierr = PetscTryMethod(ts,"TSSundialsMonitorInternalSteps_C",(TS,PetscBool),(ts,ft));CHKERRQ(ierr);
852   PetscFunctionReturn(0);
853 }
854 /* -------------------------------------------------------------------------------------------*/
855 /*MC
856       TSSUNDIALS - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)
857 
858    Options Database:
859 +    -ts_sundials_type <bdf,adams> -
860 .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
861 .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
862 .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
863 .    -ts_sundials_linear_tolerance <tol> -
864 .    -ts_sundials_maxl <maxl> - Max dimension of the Krylov subspace
865 -    -ts_sundials_monitor_steps - Monitor SUNDIALS internal steps
866 
867 
868     Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply,
869            only PETSc PC options.
870 
871     Level: beginner
872 
873 .seealso:  TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetMaxl(), TSSundialsSetLinearTolerance(),
874            TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSetExactFinalTime()
875 
876 M*/
877 PETSC_EXTERN PetscErrorCode TSCreate_Sundials(TS ts)
878 {
879   TS_Sundials    *cvode;
880   PetscErrorCode ierr;
881   PC             pc;
882 
883   PetscFunctionBegin;
884   ts->ops->reset          = TSReset_Sundials;
885   ts->ops->destroy        = TSDestroy_Sundials;
886   ts->ops->view           = TSView_Sundials;
887   ts->ops->setup          = TSSetUp_Sundials;
888   ts->ops->step           = TSStep_Sundials;
889   ts->ops->interpolate    = TSInterpolate_Sundials;
890   ts->ops->setfromoptions = TSSetFromOptions_Sundials;
891   ts->default_adapt_type  = TSADAPTNONE;
892 
893   ierr = PetscNewLog(ts,&cvode);CHKERRQ(ierr);
894 
895   ts->usessnes = PETSC_TRUE;
896 
897   ts->data           = (void*)cvode;
898   cvode->cvode_type  = SUNDIALS_BDF;
899   cvode->gtype       = SUNDIALS_CLASSICAL_GS;
900   cvode->maxl        = 5;
901   cvode->linear_tol  = .05;
902   cvode->monitorstep = PETSC_TRUE;
903 
904   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)ts),&(cvode->comm_sundials));CHKERRQ(ierr);
905 
906   cvode->mindt = -1.;
907   cvode->maxdt = -1.;
908 
909   /* set tolerance for Sundials */
910   cvode->reltol = 1e-6;
911   cvode->abstol = 1e-6;
912 
913   /* set PCNONE as default pctype */
914   ierr = TSSundialsGetPC_Sundials(ts,&pc);CHKERRQ(ierr);
915   ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
916 
917   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetType_C",TSSundialsSetType_Sundials);CHKERRQ(ierr);
918   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxl_C",TSSundialsSetMaxl_Sundials);CHKERRQ(ierr);
919   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",TSSundialsSetLinearTolerance_Sundials);CHKERRQ(ierr);
920   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",TSSundialsSetGramSchmidtType_Sundials);CHKERRQ(ierr);
921   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetTolerance_C",TSSundialsSetTolerance_Sundials);CHKERRQ(ierr);
922   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMinTimeStep_C",TSSundialsSetMinTimeStep_Sundials);CHKERRQ(ierr);
923   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",TSSundialsSetMaxTimeStep_Sundials);CHKERRQ(ierr);
924   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetPC_C",TSSundialsGetPC_Sundials);CHKERRQ(ierr);
925   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetIterations_C",TSSundialsGetIterations_Sundials);CHKERRQ(ierr);
926   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",TSSundialsMonitorInternalSteps_Sundials);CHKERRQ(ierr);
927   PetscFunctionReturn(0);
928 }
929