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