xref: /petsc/src/ts/impls/implicit/sundials/sundials.c (revision 8ebe3e4e9e00d86ece2e9fcd0cc84910b0ad437c)
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   ierr = VecGetArray(X,&x_data);CHKERRQ(ierr);
219 
220   /* Initialize N_Vec y with x_data */
221   if (cvode->use_dense) {
222     PetscMPIInt size;
223 
224     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr);
225     if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"TSSUNDIALS only supports a dense solve in the serial case");
226     y = N_VMake_Serial(locsize,(realtype*)x_data);
227   } else {
228     y = N_VMake_Parallel(cvode->comm_sundials,locsize,glosize,(realtype*)x_data);
229   }
230 
231   if (!y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Interpolated y is not allocated");
232 
233   ierr = CVodeGetDky(cvode->mem,t,0,y);CHKERRQ(ierr);
234   ierr = VecRestoreArray(X,&x_data);CHKERRQ(ierr);
235   PetscFunctionReturn(0);
236 }
237 
238 PetscErrorCode TSReset_Sundials(TS ts)
239 {
240   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
241   PetscErrorCode ierr;
242 
243   PetscFunctionBegin;
244   ierr = VecDestroy(&cvode->update);CHKERRQ(ierr);
245   ierr = VecDestroy(&cvode->ydot);CHKERRQ(ierr);
246   ierr = VecDestroy(&cvode->w1);CHKERRQ(ierr);
247   ierr = VecDestroy(&cvode->w2);CHKERRQ(ierr);
248   if (cvode->mem) CVodeFree(&cvode->mem);
249   PetscFunctionReturn(0);
250 }
251 
252 PetscErrorCode TSDestroy_Sundials(TS ts)
253 {
254   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
255   PetscErrorCode ierr;
256 
257   PetscFunctionBegin;
258   ierr = TSReset_Sundials(ts);CHKERRQ(ierr);
259   ierr = MPI_Comm_free(&(cvode->comm_sundials));CHKERRMPI(ierr);
260   ierr = PetscFree(ts->data);CHKERRQ(ierr);
261   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetType_C",NULL);CHKERRQ(ierr);
262   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxl_C",NULL);CHKERRQ(ierr);
263   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",NULL);CHKERRQ(ierr);
264   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",NULL);CHKERRQ(ierr);
265   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetTolerance_C",NULL);CHKERRQ(ierr);
266   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMinTimeStep_C",NULL);CHKERRQ(ierr);
267   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",NULL);CHKERRQ(ierr);
268   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetPC_C",NULL);CHKERRQ(ierr);
269   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetIterations_C",NULL);CHKERRQ(ierr);
270   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",NULL);CHKERRQ(ierr);
271   PetscFunctionReturn(0);
272 }
273 
274 PetscErrorCode TSSetUp_Sundials(TS ts)
275 {
276   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
277   PetscErrorCode ierr;
278   PetscInt       glosize,locsize,i,flag;
279   PetscScalar    *y_data,*parray;
280   void           *mem;
281   PC             pc;
282   PCType         pctype;
283   PetscBool      pcnone;
284 
285   PetscFunctionBegin;
286   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");
287 
288   /* get the vector size */
289   ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr);
290   ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr);
291 
292   /* allocate the memory for N_Vec y */
293   if (cvode->use_dense) {
294     PetscMPIInt size;
295 
296     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr);
297     if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"TSSUNDIALS only supports a dense solve in the serial case");
298     cvode->y = N_VNew_Serial(locsize);
299   } else {
300     cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
301   }
302   if (!cvode->y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"cvode->y is not allocated");
303 
304   /* initialize N_Vec y: copy ts->vec_sol to cvode->y */
305   ierr   = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr);
306   y_data = (PetscScalar*) N_VGetArrayPointer(cvode->y);
307   for (i = 0; i < locsize; i++) y_data[i] = parray[i];
308   ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr);
309 
310   ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr);
311   ierr = VecDuplicate(ts->vec_sol,&cvode->ydot);CHKERRQ(ierr);
312   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->update);CHKERRQ(ierr);
313   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->ydot);CHKERRQ(ierr);
314 
315   /*
316     Create work vectors for the TSPSolve_Sundials() routine. Note these are
317     allocated with zero space arrays because the actual array space is provided
318     by Sundials and set using VecPlaceArray().
319   */
320   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,NULL,&cvode->w1);CHKERRQ(ierr);
321   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,NULL,&cvode->w2);CHKERRQ(ierr);
322   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w1);CHKERRQ(ierr);
323   ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w2);CHKERRQ(ierr);
324 
325   /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */
326   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
327   if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails");
328   cvode->mem = mem;
329 
330   /* Set the pointer to user-defined data */
331   flag = CVodeSetUserData(mem, ts);
332   if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails");
333 
334   /* Sundials may choose to use a smaller initial step, but will never use a larger step. */
335   flag = CVodeSetInitStep(mem,(realtype)ts->time_step);
336   if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetInitStep() failed");
337   if (cvode->mindt > 0) {
338     flag = CVodeSetMinStep(mem,(realtype)cvode->mindt);
339     if (flag) {
340       if (flag == CV_MEM_NULL) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL");
341       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");
342       else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed");
343     }
344   }
345   if (cvode->maxdt > 0) {
346     flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt);
347     if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMaxStep() failed");
348   }
349 
350   /* Call CVodeInit to initialize the integrator memory and specify the
351    * user's right hand side function in u'=f(t,u), the initial time T0, and
352    * the initial dependent variable vector cvode->y */
353   flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y);
354   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag);
355 
356   /* specifies scalar relative and absolute tolerances */
357   flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol);
358   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag);
359 
360   /* Specify max order of BDF / ADAMS method */
361   if (cvode->maxord != PETSC_DEFAULT) {
362     flag = CVodeSetMaxOrd(mem,cvode->maxord);
363     if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetMaxOrd() fails, flag %d",flag);
364   }
365 
366   /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */
367   flag = CVodeSetMaxNumSteps(mem,ts->max_steps);
368   if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetMaxNumSteps() fails, flag %d",flag);
369 
370   if (cvode->use_dense) {
371     /* call CVDense to use a dense linear solver. */
372     PetscMPIInt size;
373 
374     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr);
375     if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"TSSUNDIALS only supports a dense solve in the serial case");
376     flag = CVDense(mem,locsize);
377     if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVDense() fails, flag %d",flag);
378   } else {
379     /* call CVSpgmr to use GMRES as the linear solver.        */
380     /* setup the ode integrator with the given preconditioner */
381     ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
382     ierr = PCGetType(pc,&pctype);CHKERRQ(ierr);
383     ierr = PetscObjectTypeCompare((PetscObject)pc,PCNONE,&pcnone);CHKERRQ(ierr);
384     if (pcnone) {
385       flag = CVSpgmr(mem,PREC_NONE,0);
386       if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag);
387     } else {
388       flag = CVSpgmr(mem,PREC_LEFT,cvode->maxl);
389       if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag);
390 
391       /* Set preconditioner and solve routines Precond and PSolve,
392          and the pointer to the user-defined block data */
393       flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials);
394       if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag);
395     }
396   }
397   PetscFunctionReturn(0);
398 }
399 
400 /* type of CVODE linear multistep method */
401 const char *const TSSundialsLmmTypes[] = {"","ADAMS","BDF","TSSundialsLmmType","SUNDIALS_",NULL};
402 /* type of G-S orthogonalization used by CVODE linear solver */
403 const char *const TSSundialsGramSchmidtTypes[] = {"","MODIFIED","CLASSICAL","TSSundialsGramSchmidtType","SUNDIALS_",NULL};
404 
405 PetscErrorCode TSSetFromOptions_Sundials(PetscOptionItems *PetscOptionsObject,TS ts)
406 {
407   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
408   PetscErrorCode ierr;
409   int            indx;
410   PetscBool      flag;
411   PC             pc;
412 
413   PetscFunctionBegin;
414   ierr = PetscOptionsHead(PetscOptionsObject,"SUNDIALS ODE solver options");CHKERRQ(ierr);
415   ierr = PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);CHKERRQ(ierr);
416   if (flag) {
417     ierr = TSSundialsSetType(ts,(TSSundialsLmmType)indx);CHKERRQ(ierr);
418   }
419   ierr = PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);CHKERRQ(ierr);
420   if (flag) {
421     ierr = TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);CHKERRQ(ierr);
422   }
423   ierr = PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,NULL);CHKERRQ(ierr);
424   ierr = PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,NULL);CHKERRQ(ierr);
425   ierr = PetscOptionsReal("-ts_sundials_mindt","Minimum step size","TSSundialsSetMinTimeStep",cvode->mindt,&cvode->mindt,NULL);CHKERRQ(ierr);
426   ierr = PetscOptionsReal("-ts_sundials_maxdt","Maximum step size","TSSundialsSetMaxTimeStep",cvode->maxdt,&cvode->maxdt,NULL);CHKERRQ(ierr);
427   ierr = PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,NULL);CHKERRQ(ierr);
428   ierr = PetscOptionsInt("-ts_sundials_maxord","Max Order for BDF/Adams method","TSSundialsSetMaxOrd",cvode->maxord,&cvode->maxord,NULL);CHKERRQ(ierr);
429   ierr = PetscOptionsInt("-ts_sundials_maxl","Max dimension of the Krylov subspace","TSSundialsSetMaxl",cvode->maxl,&cvode->maxl,NULL);CHKERRQ(ierr);
430   ierr = PetscOptionsBool("-ts_sundials_monitor_steps","Monitor SUNDIALS internal steps","TSSundialsMonitorInternalSteps",cvode->monitorstep,&cvode->monitorstep,NULL);CHKERRQ(ierr);
431   ierr = PetscOptionsBool("-ts_sundials_use_dense","Use dense internal solver in SUNDIALS (serial only)","TSSundialsSetUseDense",cvode->use_dense,&cvode->use_dense,NULL);CHKERRQ(ierr);
432   ierr = PetscOptionsTail();CHKERRQ(ierr);
433   ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
434   ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
435   PetscFunctionReturn(0);
436 }
437 
438 PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
439 {
440   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
441   PetscErrorCode ierr;
442   char           *type;
443   char           atype[] = "Adams";
444   char           btype[] = "BDF: backward differentiation formula";
445   PetscBool      iascii,isstring;
446   long int       nsteps,its,nfevals,nlinsetups,nfails,itmp;
447   PetscInt       qlast,qcur;
448   PetscReal      hinused,hlast,hcur,tcur,tolsfac;
449   PC             pc;
450 
451   PetscFunctionBegin;
452   if (cvode->cvode_type == SUNDIALS_ADAMS) type = atype;
453   else                                     type = btype;
454 
455   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
456   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
457   if (iascii) {
458     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrator does not use SNES!\n");CHKERRQ(ierr);
459     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrator type %s\n",type);CHKERRQ(ierr);
460     ierr = PetscViewerASCIIPrintf(viewer,"Sundials maxord %D\n",cvode->maxord);CHKERRQ(ierr);
461     ierr = PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",(double)cvode->abstol,(double)cvode->reltol);CHKERRQ(ierr);
462     if (cvode->use_dense) {
463       ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrator using a dense linear solve\n");CHKERRQ(ierr);
464     } else {
465       ierr = PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",(double)cvode->linear_tol);CHKERRQ(ierr);
466       ierr = PetscViewerASCIIPrintf(viewer,"Sundials max dimension of Krylov subspace %D\n",cvode->maxl);CHKERRQ(ierr);
467       if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
468         ierr = PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
469       } else {
470         ierr = PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
471       }
472     }
473     if (cvode->mindt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials minimum time step %g\n",(double)cvode->mindt);CHKERRQ(ierr);}
474     if (cvode->maxdt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials maximum time step %g\n",(double)cvode->maxdt);CHKERRQ(ierr);}
475 
476     /* Outputs from CVODE, CVSPILS */
477     ierr = CVodeGetTolScaleFactor(cvode->mem,&tolsfac);CHKERRQ(ierr);
478     ierr = PetscViewerASCIIPrintf(viewer,"Sundials suggested factor for tolerance scaling %g\n",tolsfac);CHKERRQ(ierr);
479     ierr = CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
480                                    &nlinsetups,&nfails,&qlast,&qcur,
481                                    &hinused,&hlast,&hcur,&tcur);CHKERRQ(ierr);
482     ierr = PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);CHKERRQ(ierr);
483     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);CHKERRQ(ierr);
484     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);CHKERRQ(ierr);
485     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);CHKERRQ(ierr);
486 
487     ierr = CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);CHKERRQ(ierr);
488     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);CHKERRQ(ierr);
489     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);CHKERRQ(ierr);
490     if (!cvode->use_dense) {
491       ierr = CVSpilsGetNumLinIters(cvode->mem, &its);CHKERRQ(ierr); /* its = no. of calls to TSPrecond_Sundials() */
492       ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);CHKERRQ(ierr);
493       ierr = CVSpilsGetNumConvFails(cvode->mem,&itmp);CHKERRQ(ierr);
494       ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);CHKERRQ(ierr);
495 
496       ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr);
497       ierr = PCView(pc,viewer);CHKERRQ(ierr);
498       ierr = CVSpilsGetNumPrecEvals(cvode->mem,&itmp);CHKERRQ(ierr);
499       ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);CHKERRQ(ierr);
500       ierr = CVSpilsGetNumPrecSolves(cvode->mem,&itmp);CHKERRQ(ierr);
501       ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);CHKERRQ(ierr);
502     }
503     ierr = CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);CHKERRQ(ierr);
504     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);CHKERRQ(ierr);
505     ierr = CVSpilsGetNumRhsEvals(cvode->mem,&itmp);CHKERRQ(ierr);
506     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);CHKERRQ(ierr);
507   } else if (isstring) {
508     ierr = PetscViewerStringSPrintf(viewer,"Sundials type %s",type);CHKERRQ(ierr);
509   }
510   PetscFunctionReturn(0);
511 }
512 
513 /* --------------------------------------------------------------------------*/
514 PetscErrorCode  TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
515 {
516   TS_Sundials *cvode = (TS_Sundials*)ts->data;
517 
518   PetscFunctionBegin;
519   cvode->cvode_type = type;
520   PetscFunctionReturn(0);
521 }
522 
523 PetscErrorCode  TSSundialsSetMaxl_Sundials(TS ts,PetscInt maxl)
524 {
525   TS_Sundials *cvode = (TS_Sundials*)ts->data;
526 
527   PetscFunctionBegin;
528   cvode->maxl = maxl;
529   PetscFunctionReturn(0);
530 }
531 
532 PetscErrorCode  TSSundialsSetLinearTolerance_Sundials(TS ts,PetscReal tol)
533 {
534   TS_Sundials *cvode = (TS_Sundials*)ts->data;
535 
536   PetscFunctionBegin;
537   cvode->linear_tol = tol;
538   PetscFunctionReturn(0);
539 }
540 
541 PetscErrorCode  TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
542 {
543   TS_Sundials *cvode = (TS_Sundials*)ts->data;
544 
545   PetscFunctionBegin;
546   cvode->gtype = type;
547   PetscFunctionReturn(0);
548 }
549 
550 PetscErrorCode  TSSundialsSetTolerance_Sundials(TS ts,PetscReal aabs,PetscReal rel)
551 {
552   TS_Sundials *cvode = (TS_Sundials*)ts->data;
553 
554   PetscFunctionBegin;
555   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
556   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
557   PetscFunctionReturn(0);
558 }
559 
560 PetscErrorCode  TSSundialsSetMinTimeStep_Sundials(TS ts,PetscReal mindt)
561 {
562   TS_Sundials *cvode = (TS_Sundials*)ts->data;
563 
564   PetscFunctionBegin;
565   cvode->mindt = mindt;
566   PetscFunctionReturn(0);
567 }
568 
569 PetscErrorCode  TSSundialsSetMaxTimeStep_Sundials(TS ts,PetscReal maxdt)
570 {
571   TS_Sundials *cvode = (TS_Sundials*)ts->data;
572 
573   PetscFunctionBegin;
574   cvode->maxdt = maxdt;
575   PetscFunctionReturn(0);
576 }
577 
578 PetscErrorCode  TSSundialsSetUseDense_Sundials(TS ts,PetscBool use_dense)
579 {
580   TS_Sundials *cvode = (TS_Sundials*)ts->data;
581 
582   PetscFunctionBegin;
583   cvode->use_dense = use_dense;
584   PetscFunctionReturn(0);
585 }
586 
587 PetscErrorCode  TSSundialsGetPC_Sundials(TS ts,PC *pc)
588 {
589   SNES           snes;
590   KSP            ksp;
591   PetscErrorCode ierr;
592 
593   PetscFunctionBegin;
594   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
595   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
596   ierr = KSPGetPC(ksp,pc);CHKERRQ(ierr);
597   PetscFunctionReturn(0);
598 }
599 
600 PetscErrorCode  TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
601 {
602   PetscFunctionBegin;
603   if (nonlin) *nonlin = ts->snes_its;
604   if (lin)    *lin    = ts->ksp_its;
605   PetscFunctionReturn(0);
606 }
607 
608 PetscErrorCode  TSSundialsMonitorInternalSteps_Sundials(TS ts,PetscBool s)
609 {
610   TS_Sundials *cvode = (TS_Sundials*)ts->data;
611 
612   PetscFunctionBegin;
613   cvode->monitorstep = s;
614   PetscFunctionReturn(0);
615 }
616 /* -------------------------------------------------------------------------------------------*/
617 
618 /*@C
619    TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.
620 
621    Not Collective
622 
623    Input Parameter:
624 .    ts     - the time-step context
625 
626    Output Parameters:
627 +   nonlin - number of nonlinear iterations
628 -   lin    - number of linear iterations
629 
630    Level: advanced
631 
632    Notes:
633     These return the number since the creation of the TS object
634 
635 .seealso: TSSundialsSetType(), TSSundialsSetMaxl(),
636           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
637           TSSundialsGetIterations(), TSSundialsSetType(),
638           TSSundialsSetLinearTolerance(), TSSundialsGetPC(), TSSetExactFinalTime()
639 
640 @*/
641 PetscErrorCode  TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
642 {
643   PetscErrorCode ierr;
644 
645   PetscFunctionBegin;
646   ierr = PetscUseMethod(ts,"TSSundialsGetIterations_C",(TS,int*,int*),(ts,nonlin,lin));CHKERRQ(ierr);
647   PetscFunctionReturn(0);
648 }
649 
650 /*@
651    TSSundialsSetType - Sets the method that Sundials will use for integration.
652 
653    Logically Collective on TS
654 
655    Input Parameters:
656 +    ts     - the time-step context
657 -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF
658 
659    Level: intermediate
660 
661 .seealso: TSSundialsGetIterations(),  TSSundialsSetMaxl(),
662           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
663           TSSundialsGetIterations(), TSSundialsSetType(),
664           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
665           TSSetExactFinalTime()
666 @*/
667 PetscErrorCode  TSSundialsSetType(TS ts,TSSundialsLmmType type)
668 {
669   PetscErrorCode ierr;
670 
671   PetscFunctionBegin;
672   ierr = PetscTryMethod(ts,"TSSundialsSetType_C",(TS,TSSundialsLmmType),(ts,type));CHKERRQ(ierr);
673   PetscFunctionReturn(0);
674 }
675 
676 /*@
677    TSSundialsSetMaxord - Sets the maximum order for BDF/Adams method used by SUNDIALS.
678 
679    Logically Collective on TS
680 
681    Input Parameters:
682 +    ts      - the time-step context
683 -    maxord  - maximum order of BDF / Adams method
684 
685    Level: advanced
686 
687 .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
688           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
689           TSSundialsGetIterations(), TSSundialsSetType(),
690           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
691           TSSetExactFinalTime()
692 
693 @*/
694 PetscErrorCode  TSSundialsSetMaxord(TS ts,PetscInt maxord)
695 {
696   PetscErrorCode ierr;
697 
698   PetscFunctionBegin;
699   PetscValidLogicalCollectiveInt(ts,maxord,2);
700   ierr = PetscTryMethod(ts,"TSSundialsSetMaxOrd_C",(TS,PetscInt),(ts,maxord));CHKERRQ(ierr);
701   PetscFunctionReturn(0);
702 }
703 
704 /*@
705    TSSundialsSetMaxl - Sets the dimension of the Krylov space used by
706        GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
707        this is the maximum number of GMRES steps that will be used.
708 
709    Logically Collective on TS
710 
711    Input Parameters:
712 +    ts      - the time-step context
713 -    maxl - number of direction vectors (the dimension of Krylov subspace).
714 
715    Level: advanced
716 
717 .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
718           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
719           TSSundialsGetIterations(), TSSundialsSetType(),
720           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
721           TSSetExactFinalTime()
722 
723 @*/
724 PetscErrorCode  TSSundialsSetMaxl(TS ts,PetscInt maxl)
725 {
726   PetscErrorCode ierr;
727 
728   PetscFunctionBegin;
729   PetscValidLogicalCollectiveInt(ts,maxl,2);
730   ierr = PetscTryMethod(ts,"TSSundialsSetMaxl_C",(TS,PetscInt),(ts,maxl));CHKERRQ(ierr);
731   PetscFunctionReturn(0);
732 }
733 
734 /*@
735    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
736        system by SUNDIALS.
737 
738    Logically Collective on TS
739 
740    Input Parameters:
741 +    ts     - the time-step context
742 -    tol    - the factor by which the tolerance on the nonlinear solver is
743              multiplied to get the tolerance on the linear solver, .05 by default.
744 
745    Level: advanced
746 
747 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
748           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
749           TSSundialsGetIterations(), TSSundialsSetType(),
750           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
751           TSSetExactFinalTime()
752 
753 @*/
754 PetscErrorCode  TSSundialsSetLinearTolerance(TS ts,PetscReal tol)
755 {
756   PetscErrorCode ierr;
757 
758   PetscFunctionBegin;
759   PetscValidLogicalCollectiveReal(ts,tol,2);
760   ierr = PetscTryMethod(ts,"TSSundialsSetLinearTolerance_C",(TS,PetscReal),(ts,tol));CHKERRQ(ierr);
761   PetscFunctionReturn(0);
762 }
763 
764 /*@
765    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
766         in GMRES method by SUNDIALS linear solver.
767 
768    Logically Collective on TS
769 
770    Input Parameters:
771 +    ts  - the time-step context
772 -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS
773 
774    Level: advanced
775 
776 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
777           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
778           TSSundialsGetIterations(), TSSundialsSetType(),
779           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
780           TSSetExactFinalTime()
781 
782 @*/
783 PetscErrorCode  TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
784 {
785   PetscErrorCode ierr;
786 
787   PetscFunctionBegin;
788   ierr = PetscTryMethod(ts,"TSSundialsSetGramSchmidtType_C",(TS,TSSundialsGramSchmidtType),(ts,type));CHKERRQ(ierr);
789   PetscFunctionReturn(0);
790 }
791 
792 /*@
793    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by
794                          Sundials for error control.
795 
796    Logically Collective on TS
797 
798    Input Parameters:
799 +    ts  - the time-step context
800 .    aabs - the absolute tolerance
801 -    rel - the relative tolerance
802 
803      See the Cvode/Sundials users manual for exact details on these parameters. Essentially
804     these regulate the size of the error for a SINGLE timestep.
805 
806    Level: intermediate
807 
808 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESMaxl(),
809           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(),
810           TSSundialsGetIterations(), TSSundialsSetType(),
811           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
812           TSSetExactFinalTime()
813 
814 @*/
815 PetscErrorCode  TSSundialsSetTolerance(TS ts,PetscReal aabs,PetscReal rel)
816 {
817   PetscErrorCode ierr;
818 
819   PetscFunctionBegin;
820   ierr = PetscTryMethod(ts,"TSSundialsSetTolerance_C",(TS,PetscReal,PetscReal),(ts,aabs,rel));CHKERRQ(ierr);
821   PetscFunctionReturn(0);
822 }
823 
824 /*@
825    TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.
826 
827    Input Parameter:
828 .    ts - the time-step context
829 
830    Output Parameter:
831 .    pc - the preconditioner context
832 
833    Level: advanced
834 
835 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
836           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
837           TSSundialsGetIterations(), TSSundialsSetType(),
838           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
839 @*/
840 PetscErrorCode  TSSundialsGetPC(TS ts,PC *pc)
841 {
842   PetscErrorCode ierr;
843 
844   PetscFunctionBegin;
845   ierr = PetscUseMethod(ts,"TSSundialsGetPC_C",(TS,PC*),(ts,pc));CHKERRQ(ierr);
846   PetscFunctionReturn(0);
847 }
848 
849 /*@
850    TSSundialsSetMinTimeStep - Smallest time step to be chosen by the adaptive controller.
851 
852    Input Parameters:
853 +   ts - the time-step context
854 -   mindt - lowest time step if positive, negative to deactivate
855 
856    Note:
857    Sundials will error if it is not possible to keep the estimated truncation error below
858    the tolerance set with TSSundialsSetTolerance() without going below this step size.
859 
860    Level: beginner
861 
862 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
863 @*/
864 PetscErrorCode  TSSundialsSetMinTimeStep(TS ts,PetscReal mindt)
865 {
866   PetscErrorCode ierr;
867 
868   PetscFunctionBegin;
869   ierr = PetscTryMethod(ts,"TSSundialsSetMinTimeStep_C",(TS,PetscReal),(ts,mindt));CHKERRQ(ierr);
870   PetscFunctionReturn(0);
871 }
872 
873 /*@
874    TSSundialsSetMaxTimeStep - Largest time step to be chosen by the adaptive controller.
875 
876    Input Parameters:
877 +   ts - the time-step context
878 -   maxdt - lowest time step if positive, negative to deactivate
879 
880    Level: beginner
881 
882 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
883 @*/
884 PetscErrorCode  TSSundialsSetMaxTimeStep(TS ts,PetscReal maxdt)
885 {
886   PetscErrorCode ierr;
887 
888   PetscFunctionBegin;
889   ierr = PetscTryMethod(ts,"TSSundialsSetMaxTimeStep_C",(TS,PetscReal),(ts,maxdt));CHKERRQ(ierr);
890   PetscFunctionReturn(0);
891 }
892 
893 /*@
894    TSSundialsMonitorInternalSteps - Monitor Sundials internal steps (Defaults to false).
895 
896    Input Parameters:
897 +   ts - the time-step context
898 -   ft - PETSC_TRUE if monitor, else PETSC_FALSE
899 
900    Level: beginner
901 
902 .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetMaxl(),
903           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
904           TSSundialsGetIterations(), TSSundialsSetType(),
905           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
906 @*/
907 PetscErrorCode  TSSundialsMonitorInternalSteps(TS ts,PetscBool ft)
908 {
909   PetscErrorCode ierr;
910 
911   PetscFunctionBegin;
912   ierr = PetscTryMethod(ts,"TSSundialsMonitorInternalSteps_C",(TS,PetscBool),(ts,ft));CHKERRQ(ierr);
913   PetscFunctionReturn(0);
914 }
915 
916 /*@
917    TSSundialsSetUseDense - Set a flag to use a dense linear solver in SUNDIALS (serial only)
918 
919    Logically Collective
920 
921    Input Parameters:
922 +    ts         - the time-step context
923 -    use_dense  - PETSC_TRUE to use the dense solver
924 
925    Level: advanced
926 
927 .seealso: TSSUNDIALS
928 
929 @*/
930 PetscErrorCode  TSSundialsSetUseDense(TS ts,PetscBool use_dense)
931 {
932   PetscErrorCode ierr;
933 
934   PetscFunctionBegin;
935   PetscValidLogicalCollectiveInt(ts,use_dense,2);
936   ierr = PetscTryMethod(ts,"TSSundialsSetUseDense_C",(TS,PetscBool),(ts,use_dense));CHKERRQ(ierr);
937   PetscFunctionReturn(0);
938 }
939 
940 /* -------------------------------------------------------------------------------------------*/
941 /*MC
942       TSSUNDIALS - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)
943 
944    Options Database:
945 +    -ts_sundials_type <bdf,adams> -
946 .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
947 .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
948 .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
949 .    -ts_sundials_linear_tolerance <tol> -
950 .    -ts_sundials_maxl <maxl> - Max dimension of the Krylov subspace
951 .    -ts_sundials_monitor_steps - Monitor SUNDIALS internal steps
952 -    -ts_sundials_use_dense - Use a dense linear solver within CVODE (serial only)
953 
954     Notes:
955     This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply,
956            only PETSc PC options.
957 
958     Level: beginner
959 
960 .seealso:  TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetMaxl(), TSSundialsSetLinearTolerance(),
961            TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSetExactFinalTime()
962 
963 M*/
964 PETSC_EXTERN PetscErrorCode TSCreate_Sundials(TS ts)
965 {
966   TS_Sundials    *cvode;
967   PetscErrorCode ierr;
968   PC             pc;
969 
970   PetscFunctionBegin;
971   ts->ops->reset          = TSReset_Sundials;
972   ts->ops->destroy        = TSDestroy_Sundials;
973   ts->ops->view           = TSView_Sundials;
974   ts->ops->setup          = TSSetUp_Sundials;
975   ts->ops->step           = TSStep_Sundials;
976   ts->ops->interpolate    = TSInterpolate_Sundials;
977   ts->ops->setfromoptions = TSSetFromOptions_Sundials;
978   ts->default_adapt_type  = TSADAPTNONE;
979 
980   ierr = PetscNewLog(ts,&cvode);CHKERRQ(ierr);
981 
982   ts->usessnes = PETSC_TRUE;
983 
984   ts->data           = (void*)cvode;
985   cvode->cvode_type  = SUNDIALS_BDF;
986   cvode->gtype       = SUNDIALS_CLASSICAL_GS;
987   cvode->maxl        = 5;
988   cvode->maxord      = PETSC_DEFAULT;
989   cvode->linear_tol  = .05;
990   cvode->monitorstep = PETSC_TRUE;
991   cvode->use_dense   = PETSC_FALSE;
992 
993   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)ts),&(cvode->comm_sundials));CHKERRMPI(ierr);
994 
995   cvode->mindt = -1.;
996   cvode->maxdt = -1.;
997 
998   /* set tolerance for Sundials */
999   cvode->reltol = 1e-6;
1000   cvode->abstol = 1e-6;
1001 
1002   /* set PCNONE as default pctype */
1003   ierr = TSSundialsGetPC_Sundials(ts,&pc);CHKERRQ(ierr);
1004   ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
1005 
1006   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetType_C",TSSundialsSetType_Sundials);CHKERRQ(ierr);
1007   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxl_C",TSSundialsSetMaxl_Sundials);CHKERRQ(ierr);
1008   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",TSSundialsSetLinearTolerance_Sundials);CHKERRQ(ierr);
1009   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",TSSundialsSetGramSchmidtType_Sundials);CHKERRQ(ierr);
1010   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetTolerance_C",TSSundialsSetTolerance_Sundials);CHKERRQ(ierr);
1011   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMinTimeStep_C",TSSundialsSetMinTimeStep_Sundials);CHKERRQ(ierr);
1012   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",TSSundialsSetMaxTimeStep_Sundials);CHKERRQ(ierr);
1013   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetPC_C",TSSundialsGetPC_Sundials);CHKERRQ(ierr);
1014   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsGetIterations_C",TSSundialsGetIterations_Sundials);CHKERRQ(ierr);
1015   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",TSSundialsMonitorInternalSteps_Sundials);CHKERRQ(ierr);
1016   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSSundialsSetUseDense_C",TSSundialsSetUseDense_Sundials);CHKERRQ(ierr);
1017   PetscFunctionReturn(0);
1018 }
1019