xref: /petsc/src/ts/impls/implicit/sundials/sundials.c (revision 99a14227db32e09bdaad407e56fdbfd3ed7e9701)
1 #define PETSCTS_DLL
2 
3 /*
4     Provides a PETSc interface to SUNDIALS/CVODE solver.
5     The interface to PVODE (old version of CVODE) was originally contributed
6     by Liyang Xu. It has been redone by Hong Zhang and Dinesh Kaushik.
7 
8     Reference: sundials-2.4.0/examples/cvode/parallel/cvDiurnal_kry_p.c
9 */
10 #include "sundials.h"  /*I "petscts.h" I*/
11 
12 /*
13       TSPrecond_Sundials - function that we provide to SUNDIALS to
14                         evaluate the preconditioner.
15 */
16 #undef __FUNCT__
17 #define __FUNCT__ "TSPrecond_Sundials"
18 PetscErrorCode TSPrecond_Sundials(realtype tn,N_Vector y,N_Vector fy,
19                     booleantype jok,booleantype *jcurPtr,
20                     realtype _gamma,void *P_data,
21                     N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
22 {
23   TS             ts = (TS) P_data;
24   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
25   PC             pc = cvode->pc;
26   PetscErrorCode ierr;
27   Mat            Jac = ts->B;
28   Vec            yy = cvode->w1;
29   PetscScalar    one = 1.0,gm;
30   MatStructure   str = DIFFERENT_NONZERO_PATTERN;
31   PetscScalar    *y_data;
32 
33   PetscFunctionBegin;
34   /* This allows us to construct preconditioners in-place if we like */
35   ierr = MatSetUnfactored(Jac);CHKERRQ(ierr);
36 
37   /* jok - TRUE means reuse current Jacobian else recompute Jacobian */
38   if (jok) {
39     ierr     = MatCopy(cvode->pmat,Jac,str);CHKERRQ(ierr);
40     *jcurPtr = FALSE;
41   } else {
42     /* make PETSc vector yy point to SUNDIALS vector y */
43     y_data = (PetscScalar *) N_VGetArrayPointer(y);
44     ierr   = VecPlaceArray(yy,y_data); CHKERRQ(ierr);
45 
46     /* compute the Jacobian */
47     ierr = TSComputeRHSJacobian(ts,ts->ptime,yy,&Jac,&Jac,&str);CHKERRQ(ierr);
48     ierr = VecResetArray(yy); CHKERRQ(ierr);
49 
50     /* copy the Jacobian matrix */
51     if (!cvode->pmat) {
52       ierr = MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);CHKERRQ(ierr);
53       ierr = PetscLogObjectParent(ts,cvode->pmat);CHKERRQ(ierr);
54     } else {
55       ierr = MatCopy(Jac,cvode->pmat,str);CHKERRQ(ierr);
56     }
57     *jcurPtr = TRUE;
58   }
59 
60   /* construct I-gamma*Jac  */
61   gm   = -_gamma;
62   ierr = MatScale(Jac,gm);CHKERRQ(ierr);
63   ierr = MatShift(Jac,one);CHKERRQ(ierr);
64 
65   ierr = PCSetOperators(pc,Jac,Jac,str);CHKERRQ(ierr);
66   PetscFunctionReturn(0);
67 }
68 
69 /*
70      TSPSolve_Sundials -  routine that we provide to Sundials that applies the preconditioner.
71 */
72 #undef __FUNCT__
73 #define __FUNCT__ "TSPSolve_Sundials"
74 PetscErrorCode TSPSolve_Sundials(realtype tn,N_Vector y,N_Vector fy,N_Vector r,N_Vector z,
75                                  realtype _gamma,realtype delta,int lr,void *P_data,N_Vector vtemp)
76 {
77   TS              ts = (TS) P_data;
78   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
79   PC              pc = cvode->pc;
80   Vec             rr = cvode->w1,zz = cvode->w2;
81   PetscErrorCode  ierr;
82   PetscScalar     *r_data,*z_data;
83 
84   PetscFunctionBegin;
85   /* Make the PETSc work vectors rr and zz point to the arrays in the SUNDIALS vectors r and z respectively*/
86   r_data  = (PetscScalar *) N_VGetArrayPointer(r);
87   z_data  = (PetscScalar *) N_VGetArrayPointer(z);
88   ierr = VecPlaceArray(rr,r_data); CHKERRQ(ierr);
89   ierr = VecPlaceArray(zz,z_data); CHKERRQ(ierr);
90 
91   /* Solve the Px=r and put the result in zz */
92   ierr = PCApply(pc,rr,zz); CHKERRQ(ierr);
93   ierr = VecResetArray(rr); CHKERRQ(ierr);
94   ierr = VecResetArray(zz); CHKERRQ(ierr);
95   PetscFunctionReturn(0);
96 }
97 
98 /*
99         TSFunction_Sundials - routine that we provide to Sundials that applies the right hand side.
100 */
101 #undef __FUNCT__
102 #define __FUNCT__ "TSFunction_Sundials"
103 int TSFunction_Sundials(realtype t,N_Vector y,N_Vector ydot,void *ctx)
104 {
105   TS              ts = (TS) ctx;
106   MPI_Comm        comm = ((PetscObject)ts)->comm;
107   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
108   Vec             yy = cvode->w1,yyd = cvode->w2;
109   PetscScalar     *y_data,*ydot_data;
110   PetscErrorCode  ierr;
111 
112   PetscFunctionBegin;
113   /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/
114   y_data     = (PetscScalar *) N_VGetArrayPointer(y);
115   ydot_data  = (PetscScalar *) N_VGetArrayPointer(ydot);
116   ierr = VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr);
117   ierr = VecPlaceArray(yyd,ydot_data); CHKERRABORT(comm,ierr);
118 
119   /* now compute the right hand side function */
120   ierr = TSComputeRHSFunction(ts,t,yy,yyd); CHKERRABORT(comm,ierr);
121   ierr = VecResetArray(yy); CHKERRABORT(comm,ierr);
122   ierr = VecResetArray(yyd); CHKERRABORT(comm,ierr);
123   PetscFunctionReturn(0);
124 }
125 
126 /*
127        TSStep_Sundials_Nonlinear - Calls Sundials to integrate the ODE.
128 */
129 #undef __FUNCT__
130 #define __FUNCT__ "TSStep_Sundials_Nonlinear"
131 PetscErrorCode TSStep_Sundials_Nonlinear(TS ts,int *steps,double *time)
132 {
133   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
134   Vec            sol = ts->vec_sol;
135   PetscErrorCode ierr;
136   PetscInt       i,max_steps = ts->max_steps,flag;
137   long int       its,nsteps;
138   realtype       t,tout;
139   PetscScalar    *y_data;
140   void           *mem;
141 
142   PetscFunctionBegin;
143   mem  = cvode->mem;
144   tout = ts->max_time;
145   ierr = VecGetArray(ts->vec_sol,&y_data);CHKERRQ(ierr);
146   N_VSetArrayPointer((realtype *)y_data,cvode->y);
147   ierr = VecRestoreArray(ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
148   for (i = 0; i < max_steps; i++) {
149     if (ts->ptime >= ts->max_time) break;
150     ierr = TSPreStep(ts);CHKERRQ(ierr);
151     if (cvode->monitorstep){
152       flag = CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);
153     } else {
154       flag = CVode(mem,tout,cvode->y,&t,CV_NORMAL);
155     }
156 
157     if (flag){ /* display error message */
158       switch (flag){
159       case CV_ILL_INPUT:
160         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_ILL_INPUT");
161         break;
162       case CV_TOO_CLOSE:
163         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_CLOSE");
164         break;
165       case CV_TOO_MUCH_WORK: {
166         PetscReal      tcur;
167         ierr = CVodeGetNumSteps(mem,&nsteps);CHKERRQ(ierr);
168         ierr = CVodeGetCurrentTime(mem,&tcur);CHKERRQ(ierr);
169         SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_MUCH_WORK. At t=%G, nsteps %D exceeds mxstep %D. Increase '-ts_max_steps <>' or modify TSSetDuration()",tcur,nsteps,ts->max_steps);
170       } break;
171       case CV_TOO_MUCH_ACC:
172         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_TOO_MUCH_ACC");
173         break;
174       case CV_ERR_FAILURE:
175         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_ERR_FAILURE");
176         break;
177       case CV_CONV_FAILURE:
178         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_CONV_FAILURE");
179         break;
180       case CV_LINIT_FAIL:
181         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LINIT_FAIL");
182         break;
183       case CV_LSETUP_FAIL:
184         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LSETUP_FAIL");
185         break;
186       case CV_LSOLVE_FAIL:
187         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_LSOLVE_FAIL");
188         break;
189       case CV_RHSFUNC_FAIL:
190         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_RHSFUNC_FAIL");
191         break;
192       case CV_FIRST_RHSFUNC_ERR:
193         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_FIRST_RHSFUNC_ERR");
194         break;
195       case CV_REPTD_RHSFUNC_ERR:
196         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_REPTD_RHSFUNC_ERR");
197         break;
198       case CV_UNREC_RHSFUNC_ERR:
199         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_UNREC_RHSFUNC_ERR");
200         break;
201       case CV_RTFUNC_FAIL:
202         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, CV_RTFUNC_FAIL");
203         break;
204       default:
205         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVode() fails, flag %d",flag);
206       }
207     }
208 
209     if (t > ts->max_time && cvode->exact_final_time) {
210       /* interpolate to final requested time */
211       ierr = CVodeGetDky(mem,tout,0,cvode->y);CHKERRQ(ierr);
212       t = tout;
213     }
214     ts->time_step = t - ts->ptime;
215     ts->ptime     = t;
216 
217     /* copy the solution from cvode->y to cvode->update and sol */
218     ierr = VecPlaceArray(cvode->w1,y_data); CHKERRQ(ierr);
219     ierr = VecCopy(cvode->w1,cvode->update);CHKERRQ(ierr);
220     ierr = VecResetArray(cvode->w1); CHKERRQ(ierr);
221     ierr = VecCopy(cvode->update,sol);CHKERRQ(ierr);
222     ierr = CVodeGetNumNonlinSolvIters(mem,&its);CHKERRQ(ierr);
223     ts->nonlinear_its = its;
224     ierr = CVSpilsGetNumLinIters(mem, &its);
225     ts->linear_its = its;
226     ts->steps++;
227     ierr = TSPostStep(ts);CHKERRQ(ierr);
228     ierr = TSMonitor(ts,ts->steps,t,sol);CHKERRQ(ierr);
229   }
230   ierr = CVodeGetNumSteps(mem,&nsteps);CHKERRQ(ierr);
231   *steps = nsteps;
232   *time  = t;
233   PetscFunctionReturn(0);
234 }
235 
236 #undef __FUNCT__
237 #define __FUNCT__ "TSDestroy_Sundials"
238 PetscErrorCode TSDestroy_Sundials(TS ts)
239 {
240   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
241   PetscErrorCode ierr;
242 
243   PetscFunctionBegin;
244   if (cvode->pmat)   {ierr = MatDestroy(cvode->pmat);CHKERRQ(ierr);}
245   if (cvode->pc)     {ierr = PCDestroy(cvode->pc);CHKERRQ(ierr);}
246   if (cvode->update) {ierr = VecDestroy(cvode->update);CHKERRQ(ierr);}
247   if (cvode->func)   {ierr = VecDestroy(cvode->func);CHKERRQ(ierr);}
248   if (cvode->rhs)    {ierr = VecDestroy(cvode->rhs);CHKERRQ(ierr);}
249   if (cvode->w1)     {ierr = VecDestroy(cvode->w1);CHKERRQ(ierr);}
250   if (cvode->w2)     {ierr = VecDestroy(cvode->w2);CHKERRQ(ierr);}
251   ierr = MPI_Comm_free(&(cvode->comm_sundials));CHKERRQ(ierr);
252   if (cvode->mem) {CVodeFree(&cvode->mem);}
253   ierr = PetscFree(cvode);CHKERRQ(ierr);
254   PetscFunctionReturn(0);
255 }
256 
257 #undef __FUNCT__
258 #define __FUNCT__ "TSSetUp_Sundials_Nonlinear"
259 PetscErrorCode TSSetUp_Sundials_Nonlinear(TS ts)
260 {
261   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
262   PetscErrorCode ierr;
263   PetscInt       glosize,locsize,i,flag;
264   PetscScalar    *y_data,*parray;
265   void           *mem;
266   const PCType   pctype;
267   PetscTruth     pcnone;
268   Vec            sol = ts->vec_sol;
269 
270   PetscFunctionBegin;
271   ierr = PCSetFromOptions(cvode->pc);CHKERRQ(ierr);
272 
273   /* get the vector size */
274   ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr);
275   ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr);
276 
277   /* allocate the memory for N_Vec y */
278   cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
279   if (!cvode->y) SETERRQ(PETSC_COMM_SELF,1,"cvode->y is not allocated");
280 
281   /* initialize N_Vec y: copy ts->vec_sol to cvode->y */
282   ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr);
283   y_data = (PetscScalar *) N_VGetArrayPointer(cvode->y);
284   for (i = 0; i < locsize; i++) y_data[i] = parray[i];
285   /*ierr = PetscMemcpy(y_data,parray,locsize*sizeof(PETSC_SCALAR)); CHKERRQ(ierr);*/
286   ierr = VecRestoreArray(ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
287   ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr);
288   ierr = VecDuplicate(ts->vec_sol,&cvode->func);CHKERRQ(ierr);
289   ierr = PetscLogObjectParent(ts,cvode->update);CHKERRQ(ierr);
290   ierr = PetscLogObjectParent(ts,cvode->func);CHKERRQ(ierr);
291 
292   /*
293     Create work vectors for the TSPSolve_Sundials() routine. Note these are
294     allocated with zero space arrays because the actual array space is provided
295     by Sundials and set using VecPlaceArray().
296   */
297   ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr);
298   ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr);
299   ierr = PetscLogObjectParent(ts,cvode->w1);CHKERRQ(ierr);
300   ierr = PetscLogObjectParent(ts,cvode->w2);CHKERRQ(ierr);
301 
302   /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */
303   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
304   if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails");
305   cvode->mem = mem;
306 
307   /* Set the pointer to user-defined data */
308   flag = CVodeSetUserData(mem, ts);
309   if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails");
310 
311   /* Sundials may choose to use a smaller initial step, but will never use a larger step. */
312   flag = CVodeSetInitStep(mem,(realtype)ts->initial_time_step);
313   if (flag) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_LIB,"CVodeSetInitStep() failed");
314   if (cvode->mindt > 0) {
315     flag = CVodeSetMinStep(mem,(realtype)cvode->mindt);
316     if (flag){
317       if (flag == CV_MEM_NULL){
318         SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL");
319       } else if (flag == CV_ILL_INPUT){
320         SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_LIB,"CVodeSetMinStep() failed, hmin is nonpositive or it exceeds the maximum allowable step size");
321       } else {
322         SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_LIB,"CVodeSetMinStep() failed");
323       }
324     }
325   }
326   if (cvode->maxdt > 0) {
327     flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt);
328     if (flag) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_LIB,"CVodeSetMaxStep() failed");
329   }
330 
331   /* Call CVodeInit to initialize the integrator memory and specify the
332    * user's right hand side function in u'=f(t,u), the inital time T0, and
333    * the initial dependent variable vector cvode->y */
334   flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y);
335   if (flag){
336     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag);
337   }
338 
339   /* specifies scalar relative and absolute tolerances */
340   flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol);
341   if (flag){
342     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag);
343   }
344 
345   /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */
346   flag = CVodeSetMaxNumSteps(mem,ts->max_steps);
347   ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr);
348 
349   /* call CVSpgmr to use GMRES as the linear solver.        */
350   /* setup the ode integrator with the given preconditioner */
351   ierr = PCGetType(cvode->pc,&pctype);CHKERRQ(ierr);
352   ierr = PetscTypeCompare((PetscObject)cvode->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,0);
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 *TSSundialsLmmTypes[] = {"","adams","bdf","TSSundialsLmmType","SUNDIALS_",0};
373 /* type of G-S orthogonalization used by CVODE linear solver */
374 const char *TSSundialsGramSchmidtTypes[] = {"","modified","classical","TSSundialsGramSchmidtType","SUNDIALS_",0};
375 
376 #undef __FUNCT__
377 #define __FUNCT__ "TSSetFromOptions_Sundials_Nonlinear"
378 PetscErrorCode TSSetFromOptions_Sundials_Nonlinear(TS ts)
379 {
380   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
381   PetscErrorCode ierr;
382   int            indx;
383   PetscTruth     flag;
384 
385   PetscFunctionBegin;
386   ierr = PetscOptionsHead("SUNDIALS ODE solver options");CHKERRQ(ierr);
387     ierr = PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);CHKERRQ(ierr);
388     if (flag) {
389       ierr = TSSundialsSetType(ts,(TSSundialsLmmType)indx);CHKERRQ(ierr);
390     }
391     ierr = PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);CHKERRQ(ierr);
392     if (flag) {
393       ierr = TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);CHKERRQ(ierr);
394     }
395     ierr = PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);CHKERRQ(ierr);
396     ierr = PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);CHKERRQ(ierr);
397     ierr = PetscOptionsReal("-ts_sundials_mindt","Minimum step size","TSSundialsSetMinTimeStep",cvode->mindt,&cvode->mindt,PETSC_NULL);CHKERRQ(ierr);
398     ierr = PetscOptionsReal("-ts_sundials_maxdt","Maximum step size","TSSundialsSetMaxTimeStep",cvode->maxdt,&cvode->maxdt,PETSC_NULL);CHKERRQ(ierr);
399     ierr = PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);CHKERRQ(ierr);
400     ierr = PetscOptionsInt("-ts_sundials_gmres_restart","Number of GMRES orthogonalization directions","TSSundialsSetGMRESRestart",cvode->restart,&cvode->restart,&flag);CHKERRQ(ierr);
401     ierr = PetscOptionsTruth("-ts_sundials_exact_final_time","Interpolate output to stop exactly at the final time","TSSundialsSetExactFinalTime",cvode->exact_final_time,&cvode->exact_final_time,PETSC_NULL);CHKERRQ(ierr);
402     ierr = PetscOptionsTruth("-ts_sundials_monitor_steps","Monitor SUNDIALS internel steps","TSSundialsMonitorInternalSteps",cvode->monitorstep,&cvode->monitorstep,PETSC_NULL);CHKERRQ(ierr);
403   ierr = PetscOptionsTail();CHKERRQ(ierr);
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "TSView_Sundials"
409 PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
410 {
411   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
412   PetscErrorCode ierr;
413   char           *type;
414   char           atype[] = "Adams";
415   char           btype[] = "BDF: backward differentiation formula";
416   PetscTruth     iascii,isstring;
417   long int       nsteps,its,nfevals,nlinsetups,nfails,itmp;
418   PetscInt       qlast,qcur;
419   PetscReal      hinused,hlast,hcur,tcur,tolsfac;
420 
421   PetscFunctionBegin;
422   if (cvode->cvode_type == SUNDIALS_ADAMS) {type = atype;}
423   else                                     {type = btype;}
424 
425   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
426   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
427   if (iascii) {
428     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");CHKERRQ(ierr);
429     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);CHKERRQ(ierr);
430     ierr = PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);CHKERRQ(ierr);
431     ierr = PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);CHKERRQ(ierr);
432     ierr = PetscViewerASCIIPrintf(viewer,"Sundials GMRES max iterations (same as restart in SUNDIALS) %D\n",cvode->restart);CHKERRQ(ierr);
433     if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
434       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
435     } else {
436       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
437     }
438     if (cvode->mindt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials minimum time step %g\n",cvode->mindt);CHKERRQ(ierr);}
439     if (cvode->maxdt > 0) {ierr = PetscViewerASCIIPrintf(viewer,"Sundials maximum time step %g\n",cvode->maxdt);CHKERRQ(ierr);}
440 
441     /* Outputs from CVODE, CVSPILS */
442     ierr = CVodeGetTolScaleFactor(cvode->mem,&tolsfac);CHKERRQ(ierr);
443     ierr = PetscViewerASCIIPrintf(viewer,"Sundials suggested factor for tolerance scaling %g\n",tolsfac);CHKERRQ(ierr);
444     ierr = CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
445                                    &nlinsetups,&nfails,&qlast,&qcur,
446                                    &hinused,&hlast,&hcur,&tcur);CHKERRQ(ierr);
447     ierr = PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);CHKERRQ(ierr);
448     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);CHKERRQ(ierr);
449     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);CHKERRQ(ierr);
450     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);CHKERRQ(ierr);
451 
452     ierr = CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);CHKERRQ(ierr);
453     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);CHKERRQ(ierr);
454     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);CHKERRQ(ierr);
455 
456     ierr = CVSpilsGetNumLinIters(cvode->mem, &its);CHKERRQ(ierr); /* its = no. of calls to TSPrecond_Sundials() */
457     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);CHKERRQ(ierr);
458     ierr = CVSpilsGetNumConvFails(cvode->mem,&itmp);CHKERRQ(ierr);
459     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);CHKERRQ(ierr);
460     ierr = CVSpilsGetNumPrecEvals(cvode->mem,&itmp);CHKERRQ(ierr);
461     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);CHKERRQ(ierr);
462     ierr = CVSpilsGetNumPrecSolves(cvode->mem,&itmp);CHKERRQ(ierr);
463     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);CHKERRQ(ierr);
464     ierr = CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);CHKERRQ(ierr);
465     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);CHKERRQ(ierr);
466     ierr = CVSpilsGetNumRhsEvals(cvode->mem,&itmp);CHKERRQ(ierr);
467     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);CHKERRQ(ierr);
468   } else if (isstring) {
469     ierr = PetscViewerStringSPrintf(viewer,"Sundials type %s",type);CHKERRQ(ierr);
470   } else {
471     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by TS Sundials",((PetscObject)viewer)->type_name);
472   }
473   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
474   ierr = PCView(cvode->pc,viewer);CHKERRQ(ierr);
475   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
476   PetscFunctionReturn(0);
477 }
478 
479 
480 /* --------------------------------------------------------------------------*/
481 EXTERN_C_BEGIN
482 #undef __FUNCT__
483 #define __FUNCT__ "TSSundialsSetType_Sundials"
484 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
485 {
486   TS_Sundials *cvode = (TS_Sundials*)ts->data;
487 
488   PetscFunctionBegin;
489   cvode->cvode_type = type;
490   PetscFunctionReturn(0);
491 }
492 EXTERN_C_END
493 
494 EXTERN_C_BEGIN
495 #undef __FUNCT__
496 #define __FUNCT__ "TSSundialsSetGMRESRestart_Sundials"
497 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart_Sundials(TS ts,int restart)
498 {
499   TS_Sundials *cvode = (TS_Sundials*)ts->data;
500 
501   PetscFunctionBegin;
502   cvode->restart = restart;
503   PetscFunctionReturn(0);
504 }
505 EXTERN_C_END
506 
507 EXTERN_C_BEGIN
508 #undef __FUNCT__
509 #define __FUNCT__ "TSSundialsSetLinearTolerance_Sundials"
510 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
511 {
512   TS_Sundials *cvode = (TS_Sundials*)ts->data;
513 
514   PetscFunctionBegin;
515   cvode->linear_tol = tol;
516   PetscFunctionReturn(0);
517 }
518 EXTERN_C_END
519 
520 EXTERN_C_BEGIN
521 #undef __FUNCT__
522 #define __FUNCT__ "TSSundialsSetGramSchmidtType_Sundials"
523 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
524 {
525   TS_Sundials *cvode = (TS_Sundials*)ts->data;
526 
527   PetscFunctionBegin;
528   cvode->gtype = type;
529   PetscFunctionReturn(0);
530 }
531 EXTERN_C_END
532 
533 EXTERN_C_BEGIN
534 #undef __FUNCT__
535 #define __FUNCT__ "TSSundialsSetTolerance_Sundials"
536 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
537 {
538   TS_Sundials *cvode = (TS_Sundials*)ts->data;
539 
540   PetscFunctionBegin;
541   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
542   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
543   PetscFunctionReturn(0);
544 }
545 EXTERN_C_END
546 
547 EXTERN_C_BEGIN
548 #undef __FUNCT__
549 #define __FUNCT__ "TSSundialsSetMinTimeStep_Sundials"
550 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetMinTimeStep_Sundials(TS ts,PetscReal mindt)
551 {
552   TS_Sundials *cvode = (TS_Sundials*)ts->data;
553 
554   PetscFunctionBegin;
555   cvode->mindt = mindt;
556   PetscFunctionReturn(0);
557 }
558 EXTERN_C_END
559 
560 EXTERN_C_BEGIN
561 #undef __FUNCT__
562 #define __FUNCT__ "TSSundialsSetMaxTimeStep_Sundials"
563 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetMaxTimeStep_Sundials(TS ts,PetscReal maxdt)
564 {
565   TS_Sundials *cvode = (TS_Sundials*)ts->data;
566 
567   PetscFunctionBegin;
568   cvode->maxdt = maxdt;
569   PetscFunctionReturn(0);
570 }
571 EXTERN_C_END
572 
573 EXTERN_C_BEGIN
574 #undef __FUNCT__
575 #define __FUNCT__ "TSSundialsGetPC_Sundials"
576 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC_Sundials(TS ts,PC *pc)
577 {
578   TS_Sundials *cvode = (TS_Sundials*)ts->data;
579 
580   PetscFunctionBegin;
581   *pc = cvode->pc;
582   PetscFunctionReturn(0);
583 }
584 EXTERN_C_END
585 
586 EXTERN_C_BEGIN
587 #undef __FUNCT__
588 #define __FUNCT__ "TSSundialsGetIterations_Sundials"
589 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
590 {
591   PetscFunctionBegin;
592   if (nonlin) *nonlin = ts->nonlinear_its;
593   if (lin)    *lin    = ts->linear_its;
594   PetscFunctionReturn(0);
595 }
596 EXTERN_C_END
597 
598 EXTERN_C_BEGIN
599 #undef __FUNCT__
600 #define __FUNCT__ "TSSundialsSetExactFinalTime_Sundials"
601 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime_Sundials(TS ts,PetscTruth s)
602 {
603   TS_Sundials *cvode = (TS_Sundials*)ts->data;
604 
605   PetscFunctionBegin;
606   cvode->exact_final_time = s;
607   PetscFunctionReturn(0);
608 }
609 EXTERN_C_END
610 
611 EXTERN_C_BEGIN
612 #undef __FUNCT__
613 #define __FUNCT__ "TSSundialsMonitorInternalSteps_Sundials"
614 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsMonitorInternalSteps_Sundials(TS ts,PetscTruth s)
615 {
616   TS_Sundials *cvode = (TS_Sundials*)ts->data;
617 
618   PetscFunctionBegin;
619   cvode->monitorstep = s;
620   PetscFunctionReturn(0);
621 }
622 EXTERN_C_END
623 /* -------------------------------------------------------------------------------------------*/
624 
625 #undef __FUNCT__
626 #define __FUNCT__ "TSSundialsGetIterations"
627 /*@C
628    TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.
629 
630    Not Collective
631 
632    Input parameters:
633 .    ts     - the time-step context
634 
635    Output Parameters:
636 +   nonlin - number of nonlinear iterations
637 -   lin    - number of linear iterations
638 
639    Level: advanced
640 
641    Notes:
642     These return the number since the creation of the TS object
643 
644 .keywords: non-linear iterations, linear iterations
645 
646 .seealso: TSSundialsSetType(), TSSundialsSetGMRESRestart(),
647           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
648           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
649           TSSundialsSetLinearTolerance(), TSSundialsGetPC(), TSSundialsSetExactFinalTime()
650 
651 @*/
652 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
653 {
654   PetscErrorCode ierr,(*f)(TS,int*,int*);
655 
656   PetscFunctionBegin;
657   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetIterations_C",(void (**)(void))&f);CHKERRQ(ierr);
658   if (f) {
659     ierr = (*f)(ts,nonlin,lin);CHKERRQ(ierr);
660   }
661   PetscFunctionReturn(0);
662 }
663 
664 #undef __FUNCT__
665 #define __FUNCT__ "TSSundialsSetType"
666 /*@
667    TSSundialsSetType - Sets the method that Sundials will use for integration.
668 
669    Logically Collective on TS
670 
671    Input parameters:
672 +    ts     - the time-step context
673 -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF
674 
675    Level: intermediate
676 
677 .keywords: Adams, backward differentiation formula
678 
679 .seealso: TSSundialsGetIterations(),  TSSundialsSetGMRESRestart(),
680           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
681           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
682           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
683           TSSundialsSetExactFinalTime()
684 @*/
685 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType(TS ts,TSSundialsLmmType type)
686 {
687   PetscErrorCode ierr,(*f)(TS,TSSundialsLmmType);
688 
689   PetscFunctionBegin;
690   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetType_C",(void (**)(void))&f);CHKERRQ(ierr);
691   if (f) {
692     ierr = (*f)(ts,type);CHKERRQ(ierr);
693   }
694   PetscFunctionReturn(0);
695 }
696 
697 #undef __FUNCT__
698 #define __FUNCT__ "TSSundialsSetGMRESRestart"
699 /*@
700    TSSundialsSetGMRESRestart - Sets the dimension of the Krylov space used by
701        GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
702        this is ALSO the maximum number of GMRES steps that will be used.
703 
704    Logically Collective on TS
705 
706    Input parameters:
707 +    ts      - the time-step context
708 -    restart - number of direction vectors (the restart size).
709 
710    Level: advanced
711 
712 .keywords: GMRES, restart
713 
714 .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
715           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
716           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
717           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
718           TSSundialsSetExactFinalTime()
719 
720 @*/
721 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart(TS ts,int restart)
722 {
723   PetscErrorCode ierr,(*f)(TS,int);
724 
725   PetscFunctionBegin;
726   PetscValidLogicalCollectiveInt(ts,restart,2);
727   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGMRESRestart_C",(void (**)(void))&f);CHKERRQ(ierr);
728   if (f) {
729     ierr = (*f)(ts,restart);CHKERRQ(ierr);
730   }
731   PetscFunctionReturn(0);
732 }
733 
734 #undef __FUNCT__
735 #define __FUNCT__ "TSSundialsSetLinearTolerance"
736 /*@
737    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
738        system by SUNDIALS.
739 
740    Logically Collective on TS
741 
742    Input parameters:
743 +    ts     - the time-step context
744 -    tol    - the factor by which the tolerance on the nonlinear solver is
745              multiplied to get the tolerance on the linear solver, .05 by default.
746 
747    Level: advanced
748 
749 .keywords: GMRES, linear convergence tolerance, SUNDIALS
750 
751 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
752           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
753           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
754           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
755           TSSundialsSetExactFinalTime()
756 
757 @*/
758 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance(TS ts,double tol)
759 {
760   PetscErrorCode ierr,(*f)(TS,double);
761 
762   PetscFunctionBegin;
763   PetscValidLogicalCollectiveReal(ts,tol,2);
764   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",(void (**)(void))&f);CHKERRQ(ierr);
765   if (f) {
766     ierr = (*f)(ts,tol);CHKERRQ(ierr);
767   }
768   PetscFunctionReturn(0);
769 }
770 
771 #undef __FUNCT__
772 #define __FUNCT__ "TSSundialsSetGramSchmidtType"
773 /*@
774    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
775         in GMRES method by SUNDIALS linear solver.
776 
777    Logically Collective on TS
778 
779    Input parameters:
780 +    ts  - the time-step context
781 -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS
782 
783    Level: advanced
784 
785 .keywords: Sundials, orthogonalization
786 
787 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
788           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
789           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
790           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
791           TSSundialsSetExactFinalTime()
792 
793 @*/
794 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
795 {
796   PetscErrorCode ierr,(*f)(TS,TSSundialsGramSchmidtType);
797 
798   PetscFunctionBegin;
799   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",(void (**)(void))&f);CHKERRQ(ierr);
800   if (f) {
801     ierr = (*f)(ts,type);CHKERRQ(ierr);
802   }
803   PetscFunctionReturn(0);
804 }
805 
806 #undef __FUNCT__
807 #define __FUNCT__ "TSSundialsSetTolerance"
808 /*@
809    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by
810                          Sundials for error control.
811 
812    Logically Collective on TS
813 
814    Input parameters:
815 +    ts  - the time-step context
816 .    aabs - the absolute tolerance
817 -    rel - the relative tolerance
818 
819      See the Cvode/Sundials users manual for exact details on these parameters. Essentially
820     these regulate the size of the error for a SINGLE timestep.
821 
822    Level: intermediate
823 
824 .keywords: Sundials, tolerance
825 
826 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
827           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(),
828           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
829           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
830           TSSundialsSetExactFinalTime()
831 
832 @*/
833 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance(TS ts,double aabs,double rel)
834 {
835   PetscErrorCode ierr,(*f)(TS,double,double);
836 
837   PetscFunctionBegin;
838   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetTolerance_C",(void (**)(void))&f);CHKERRQ(ierr);
839   if (f) {
840     ierr = (*f)(ts,aabs,rel);CHKERRQ(ierr);
841   }
842   PetscFunctionReturn(0);
843 }
844 
845 #undef __FUNCT__
846 #define __FUNCT__ "TSSundialsGetPC"
847 /*@
848    TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.
849 
850    Input Parameter:
851 .    ts - the time-step context
852 
853    Output Parameter:
854 .    pc - the preconditioner context
855 
856    Level: advanced
857 
858 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
859           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
860           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
861           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
862 @*/
863 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC(TS ts,PC *pc)
864 {
865   PetscErrorCode ierr,(*f)(TS,PC *);
866 
867   PetscFunctionBegin;
868   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetPC_C",(void (**)(void))&f);CHKERRQ(ierr);
869   if (f) {
870     ierr = (*f)(ts,pc);CHKERRQ(ierr);
871   } else {
872     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TS must be of Sundials type to extract the PC");
873   }
874 
875   PetscFunctionReturn(0);
876 }
877 
878 #undef __FUNCT__
879 #define __FUNCT__ "TSSundialsSetExactFinalTime"
880 /*@
881    TSSundialsSetExactFinalTime - Determines if Sundials interpolates solution to the
882       exact final time requested by the user or just returns it at the final time
883       it computed. (Defaults to true).
884 
885    Input Parameter:
886 +   ts - the time-step context
887 -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE
888 
889    Level: beginner
890 
891 .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
892           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
893           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
894           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
895 @*/
896 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime(TS ts,PetscTruth ft)
897 {
898   PetscErrorCode ierr,(*f)(TS,PetscTruth);
899 
900   PetscFunctionBegin;
901   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetExactFinalTime_C",(void (**)(void))&f);CHKERRQ(ierr);
902   if (f) {
903     ierr = (*f)(ts,ft);CHKERRQ(ierr);
904   }
905   PetscFunctionReturn(0);
906 }
907 
908 #undef __FUNCT__
909 #define __FUNCT__ "TSSundialsSetMinTimeStep"
910 /*@
911    TSSundialsSetMinTimeStep - Smallest time step to be chosen by the adaptive controller.
912 
913    Input Parameter:
914 +   ts - the time-step context
915 -   mindt - lowest time step if positive, negative to deactivate
916 
917    Note:
918    Sundials will error if it is not possible to keep the estimated truncation error below
919    the tolerance set with TSSundialsSetTolerance() without going below this step size.
920 
921    Level: beginner
922 
923 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
924 @*/
925 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetMinTimeStep(TS ts,PetscReal mindt)
926 {
927   PetscErrorCode ierr,(*f)(TS,PetscReal);
928 
929   PetscFunctionBegin;
930   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetMinTimeStep_C",(void(**)(void))&f);CHKERRQ(ierr);
931   if (f) {ierr = (*f)(ts,mindt);CHKERRQ(ierr);}
932   PetscFunctionReturn(0);
933 }
934 
935 #undef __FUNCT__
936 #define __FUNCT__ "TSSundialsSetMaxTimeStep"
937 /*@
938    TSSundialsSetMaxTimeStep - Largest time step to be chosen by the adaptive controller.
939 
940    Input Parameter:
941 +   ts - the time-step context
942 -   maxdt - lowest time step if positive, negative to deactivate
943 
944    Level: beginner
945 
946 .seealso: TSSundialsSetType(), TSSundialsSetTolerance(),
947 @*/
948 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetMaxTimeStep(TS ts,PetscReal maxdt)
949 {
950   PetscErrorCode ierr,(*f)(TS,PetscReal);
951 
952   PetscFunctionBegin;
953   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",(void(**)(void))&f);CHKERRQ(ierr);
954   if (f) {ierr = (*f)(ts,maxdt);CHKERRQ(ierr);}
955   PetscFunctionReturn(0);
956 }
957 
958 #undef __FUNCT__
959 #define __FUNCT__ "TSSundialsMonitorInternalSteps"
960 /*@
961    TSSundialsMonitorInternalSteps - Monitor Sundials internal steps (Defaults to false).
962 
963    Input Parameter:
964 +   ts - the time-step context
965 -   ft - PETSC_TRUE if monitor, else PETSC_FALSE
966 
967    Level: beginner
968 
969 .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
970           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
971           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
972           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
973 @*/
974 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsMonitorInternalSteps(TS ts,PetscTruth ft)
975 {
976   PetscErrorCode ierr,(*f)(TS,PetscTruth);
977 
978   PetscFunctionBegin;
979   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",(void (**)(void))&f);CHKERRQ(ierr);
980   if (f) {
981     ierr = (*f)(ts,ft);CHKERRQ(ierr);
982   }
983   PetscFunctionReturn(0);
984 }
985 /* -------------------------------------------------------------------------------------------*/
986 /*MC
987       TSSUNDIALS - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)
988 
989    Options Database:
990 +    -ts_sundials_type <bdf,adams>
991 .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
992 .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
993 .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
994 .    -ts_sundials_linear_tolerance <tol>
995 .    -ts_sundials_gmres_restart <restart> - Number of GMRES orthogonalization directions
996 .    -ts_sundials_exact_final_time - Interpolate output to stop exactly at the final time
997 -    -ts_sundials_monitor_steps - Monitor SUNDIALS internel steps
998 
999 
1000     Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply
1001            only PETSc PC options
1002 
1003     Level: beginner
1004 
1005 .seealso:  TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetGMRESRestart(), TSSundialsSetLinearTolerance(),
1006            TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSundialsSetExactFinalTime()
1007 
1008 M*/
1009 EXTERN_C_BEGIN
1010 #undef __FUNCT__
1011 #define __FUNCT__ "TSCreate_Sundials"
1012 PetscErrorCode PETSCTS_DLLEXPORT TSCreate_Sundials(TS ts)
1013 {
1014   TS_Sundials *cvode;
1015   PetscErrorCode ierr;
1016 
1017   PetscFunctionBegin;
1018   if (ts->problem_type != TS_NONLINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only support for nonlinear problems");
1019   ts->ops->destroy        = TSDestroy_Sundials;
1020   ts->ops->view           = TSView_Sundials;
1021   ts->ops->setup          = TSSetUp_Sundials_Nonlinear;
1022   ts->ops->step           = TSStep_Sundials_Nonlinear;
1023   ts->ops->setfromoptions = TSSetFromOptions_Sundials_Nonlinear;
1024 
1025   ierr = PetscNewLog(ts,TS_Sundials,&cvode);CHKERRQ(ierr);
1026   ierr = PCCreate(((PetscObject)ts)->comm,&cvode->pc);CHKERRQ(ierr);
1027   ierr = PetscLogObjectParent(ts,cvode->pc);CHKERRQ(ierr);
1028   ts->data          = (void*)cvode;
1029   cvode->cvode_type = SUNDIALS_BDF;
1030   cvode->gtype      = SUNDIALS_CLASSICAL_GS;
1031   cvode->restart    = 5;
1032   cvode->linear_tol = .05;
1033 
1034   cvode->exact_final_time = PETSC_TRUE;
1035   cvode->monitorstep      = PETSC_FALSE;
1036 
1037   ierr = MPI_Comm_dup(((PetscObject)ts)->comm,&(cvode->comm_sundials));CHKERRQ(ierr);
1038 
1039   cvode->mindt = -1.;
1040   cvode->maxdt = -1.;
1041 
1042   /* set tolerance for Sundials */
1043   cvode->reltol = 1e-6;
1044   cvode->abstol = 1e-6;
1045 
1046   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetType_C","TSSundialsSetType_Sundials",
1047                     TSSundialsSetType_Sundials);CHKERRQ(ierr);
1048   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGMRESRestart_C",
1049                     "TSSundialsSetGMRESRestart_Sundials",
1050                     TSSundialsSetGMRESRestart_Sundials);CHKERRQ(ierr);
1051   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetLinearTolerance_C",
1052                     "TSSundialsSetLinearTolerance_Sundials",
1053                      TSSundialsSetLinearTolerance_Sundials);CHKERRQ(ierr);
1054   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",
1055                     "TSSundialsSetGramSchmidtType_Sundials",
1056                      TSSundialsSetGramSchmidtType_Sundials);CHKERRQ(ierr);
1057   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetTolerance_C",
1058                     "TSSundialsSetTolerance_Sundials",
1059                      TSSundialsSetTolerance_Sundials);CHKERRQ(ierr);
1060   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetMinTimeStep_C",
1061                     "TSSundialsSetMinTimeStep_Sundials",
1062                      TSSundialsSetMinTimeStep_Sundials);CHKERRQ(ierr);
1063   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetMaxTimeStep_C",
1064                     "TSSundialsSetMaxTimeStep_Sundials",
1065                      TSSundialsSetMaxTimeStep_Sundials);CHKERRQ(ierr);
1066   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetPC_C",
1067                     "TSSundialsGetPC_Sundials",
1068                      TSSundialsGetPC_Sundials);CHKERRQ(ierr);
1069   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetIterations_C",
1070                     "TSSundialsGetIterations_Sundials",
1071                      TSSundialsGetIterations_Sundials);CHKERRQ(ierr);
1072   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetExactFinalTime_C",
1073                     "TSSundialsSetExactFinalTime_Sundials",
1074                      TSSundialsSetExactFinalTime_Sundials);CHKERRQ(ierr);
1075   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsMonitorInternalSteps_C",
1076                     "TSSundialsMonitorInternalSteps_Sundials",
1077                      TSSundialsMonitorInternalSteps_Sundials);CHKERRQ(ierr);
1078 
1079   PetscFunctionReturn(0);
1080 }
1081 EXTERN_C_END
1082