xref: /petsc/src/ts/impls/implicit/sundials/sundials.c (revision 2c8230830407b9e2ff23c3823118e2aee86be698)
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     Reference: sundials-2.3.0/examples/cvode/parallel/cvkryx_p.c
8 */
9 #include "sundials.h"  /*I "petscts.h" I*/
10 
11 /*
12       TSPrecond_Sundials - function that we provide to SUNDIALS to
13                         evaluate the preconditioner.
14 */
15 #undef __FUNCT__
16 #define __FUNCT__ "TSPrecond_Sundials"
17 PetscErrorCode TSPrecond_Sundials(realtype tn,N_Vector y,N_Vector fy,
18                     booleantype jok,booleantype *jcurPtr,
19                     realtype _gamma,void *P_data,
20                     N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
21 {
22   TS             ts = (TS) P_data;
23   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
24   PC             pc = cvode->pc;
25   PetscErrorCode ierr;
26   Mat            Jac = ts->B;
27   Vec            yy = cvode->w1;
28   PetscScalar    one = 1.0,gm;
29   MatStructure   str = DIFFERENT_NONZERO_PATTERN;
30   PetscScalar    *y_data;
31 
32   PetscFunctionBegin;
33   /* This allows us to construct preconditioners in-place if we like */
34   ierr = MatSetUnfactored(Jac);CHKERRQ(ierr);
35 
36   /* jok - TRUE means reuse current Jacobian else recompute Jacobian */
37   if (jok) {
38     ierr     = MatCopy(cvode->pmat,Jac,str);CHKERRQ(ierr);
39     *jcurPtr = FALSE;
40   } else {
41     /* make PETSc vector yy point to SUNDIALS vector y */
42     y_data = (PetscScalar *) N_VGetArrayPointer(y);
43     ierr   = VecPlaceArray(yy,y_data); CHKERRQ(ierr);
44 
45     /* compute the Jacobian */
46     ierr = TSComputeRHSJacobian(ts,ts->ptime,yy,&Jac,&Jac,&str);CHKERRQ(ierr);
47     ierr = VecResetArray(yy); CHKERRQ(ierr);
48 
49     /* copy the Jacobian matrix */
50     if (!cvode->pmat) {
51       ierr = MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);CHKERRQ(ierr);
52       ierr = PetscLogObjectParent(ts,cvode->pmat);CHKERRQ(ierr);
53     } else {
54       ierr = MatCopy(Jac,cvode->pmat,str);CHKERRQ(ierr);
55     }
56     *jcurPtr = TRUE;
57   }
58 
59   /* construct I-gamma*Jac  */
60   gm   = -_gamma;
61   ierr = MatScale(Jac,gm);CHKERRQ(ierr);
62   ierr = MatShift(Jac,one);CHKERRQ(ierr);
63 
64   ierr = PCSetOperators(pc,Jac,Jac,str);CHKERRQ(ierr);
65   PetscFunctionReturn(0);
66 }
67 
68 /*
69      TSPSolve_Sundials -  routine that we provide to Sundials that applies the preconditioner.
70 */
71 #undef __FUNCT__
72 #define __FUNCT__ "TSPSolve_Sundials"
73 PetscErrorCode TSPSolve_Sundials(realtype tn,N_Vector y,N_Vector fy,N_Vector r,N_Vector z,
74                                  realtype _gamma,realtype delta,int lr,void *P_data,N_Vector vtemp)
75 {
76   TS              ts = (TS) P_data;
77   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
78   PC              pc = cvode->pc;
79   Vec             rr = cvode->w1,zz = cvode->w2;
80   PetscErrorCode  ierr;
81   PetscScalar     *r_data,*z_data;
82 
83   PetscFunctionBegin;
84   /* Make the PETSc work vectors rr and zz point to the arrays in the SUNDIALS vectors r and z respectively*/
85   r_data  = (PetscScalar *) N_VGetArrayPointer(r);
86   z_data  = (PetscScalar *) N_VGetArrayPointer(z);
87   ierr = VecPlaceArray(rr,r_data); CHKERRQ(ierr);
88   ierr = VecPlaceArray(zz,z_data); CHKERRQ(ierr);
89 
90   /* Solve the Px=r and put the result in zz */
91   ierr = PCApply(pc,rr,zz); CHKERRQ(ierr);
92   ierr = VecResetArray(rr); CHKERRQ(ierr);
93   ierr = VecResetArray(zz); CHKERRQ(ierr);
94   PetscFunctionReturn(0);
95 }
96 
97 /*
98         TSFunction_Sundials - routine that we provide to Sundials that applies the right hand side.
99 */
100 #undef __FUNCT__
101 #define __FUNCT__ "TSFunction_Sundials"
102 int TSFunction_Sundials(realtype t,N_Vector y,N_Vector ydot,void *ctx)
103 {
104   TS              ts = (TS) ctx;
105   MPI_Comm        comm = ((PetscObject)ts)->comm;
106   TS_Sundials     *cvode = (TS_Sundials*)ts->data;
107   Vec             yy = cvode->w1,yyd = cvode->w2;
108   PetscScalar     *y_data,*ydot_data;
109   PetscErrorCode  ierr;
110 
111   PetscFunctionBegin;
112   /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/
113   y_data     = (PetscScalar *) N_VGetArrayPointer(y);
114   ydot_data  = (PetscScalar *) N_VGetArrayPointer(ydot);
115   ierr = VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr);
116   ierr = VecPlaceArray(yyd,ydot_data); CHKERRABORT(comm,ierr);
117 
118   /* now compute the right hand side function */
119   ierr = TSComputeRHSFunction(ts,t,yy,yyd); CHKERRABORT(comm,ierr);
120   ierr = VecResetArray(yy); CHKERRABORT(comm,ierr);
121   ierr = VecResetArray(yyd); CHKERRABORT(comm,ierr);
122   PetscFunctionReturn(0);
123 }
124 
125 /*
126        TSStep_Sundials_Nonlinear - Calls Sundials to integrate the ODE.
127 */
128 #undef __FUNCT__
129 #define __FUNCT__ "TSStep_Sundials_Nonlinear"
130 /*
131     TSStep_Sundials_Nonlinear -
132 
133    steps - number of time steps
134    time - time that integrater is  terminated.
135 */
136 PetscErrorCode TSStep_Sundials_Nonlinear(TS ts,int *steps,double *time)
137 {
138   TS_Sundials  *cvode = (TS_Sundials*)ts->data;
139   Vec          sol = ts->vec_sol;
140   PetscErrorCode ierr;
141   int          i,max_steps = ts->max_steps,flag;
142   long int     its;
143   realtype     t,tout;
144   PetscScalar  *y_data;
145   void         *mem;
146 
147   PetscFunctionBegin;
148   /* Call CVodeCreate to create the solver memory */
149   mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
150   if (!mem) SETERRQ(1,"CVodeCreate() fails");
151   flag = CVodeSetFdata(mem,ts);
152   if (flag) SETERRQ(1,"CVodeSetFdata() fails");
153 
154   /*
155      Call CVodeMalloc to initialize the integrator memory:
156      mem is the pointer to the integrator memory returned by CVodeCreate
157      f       is the user's right hand side function in y'=f(t,y)
158      T0      is the initial time
159      u       is the initial dependent variable vector
160      CV_SS   specifies scalar relative and absolute tolerances
161      reltol  is the relative tolerance
162      &abstol is a pointer to the scalar absolute tolerance
163   */
164   flag = CVodeMalloc(mem,TSFunction_Sundials,ts->ptime,cvode->y,CV_SS,cvode->reltol,&cvode->abstol);
165   if (flag) SETERRQ(1,"CVodeMalloc() fails");
166 
167   /* initialize the number of steps */
168   *steps = -ts->steps;
169   ierr   = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr);
170 
171   /* call CVSpgmr to use GMRES as the linear solver.        */
172   /* setup the ode integrator with the given preconditioner */
173   flag  = CVSpgmr(mem,PREC_LEFT,0);
174   if (flag) SETERRQ(1,"CVSpgmr() fails");
175 
176   flag = CVSpilsSetGSType(mem, MODIFIED_GS);
177   if (flag) SETERRQ(1,"CVSpgmrSetGSType() fails");
178 
179   /* Set preconditioner setup and solve routines Precond and PSolve,
180      and the pointer to the user-defined block data */
181   flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials,ts);
182   if (flag) SETERRQ(1,"CVSpgmrSetPreconditioner() fails");
183 
184   tout = ts->max_time;
185   ierr = VecGetArray(ts->vec_sol,&y_data);CHKERRQ(ierr);
186   N_VSetArrayPointer((realtype *)y_data,cvode->y);
187   ierr = VecRestoreArray(ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
188   for (i = 0; i < max_steps; i++) {
189     if (ts->ptime >= ts->max_time) break;
190     ierr = CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);CHKERRQ(ierr);
191     if (ts->ops->postupdate){
192       ierr = (*ts->ops->postupdate)(ts,ts->ptime,PETSC_NULL);CHKERRQ(ierr);
193     }
194     if (t > ts->max_time && cvode->exact_final_time) {
195       /* interpolate to final requested time */
196       ierr = CVodeGetDky(mem,tout,0,cvode->y);CHKERRQ(ierr);
197       t = tout;
198     }
199     ts->time_step = t - ts->ptime;
200     ts->ptime     = t;
201 
202     /* copy the solution from cvode->y to cvode->update and sol */
203     ierr = VecPlaceArray(cvode->w1,y_data); CHKERRQ(ierr);
204     ierr = VecCopy(cvode->w1,cvode->update);CHKERRQ(ierr);
205     ierr = VecResetArray(cvode->w1); CHKERRQ(ierr);
206     ierr = VecCopy(cvode->update,sol);CHKERRQ(ierr);
207     ierr = CVodeGetNumNonlinSolvIters(mem,&its);CHKERRQ(ierr);
208     ts->nonlinear_its = its;
209     ierr = CVSpilsGetNumLinIters(mem, &its);
210     ts->linear_its = its;
211     ts->steps++;
212     ierr = TSMonitor(ts,ts->steps,t,sol);CHKERRQ(ierr);
213   }
214   cvode->mem = mem;
215   *steps    += ts->steps;
216   *time      = t;
217   PetscFunctionReturn(0);
218 }
219 
220 #undef __FUNCT__
221 #define __FUNCT__ "TSDestroy_Sundials"
222 PetscErrorCode TSDestroy_Sundials(TS ts)
223 {
224   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
225   PetscErrorCode ierr;
226 
227   PetscFunctionBegin;
228   if (cvode->pmat)   {ierr = MatDestroy(cvode->pmat);CHKERRQ(ierr);}
229   if (cvode->pc)     {ierr = PCDestroy(cvode->pc);CHKERRQ(ierr);}
230   if (cvode->update) {ierr = VecDestroy(cvode->update);CHKERRQ(ierr);}
231   if (cvode->func)   {ierr = VecDestroy(cvode->func);CHKERRQ(ierr);}
232   if (cvode->rhs)    {ierr = VecDestroy(cvode->rhs);CHKERRQ(ierr);}
233   if (cvode->w1)     {ierr = VecDestroy(cvode->w1);CHKERRQ(ierr);}
234   if (cvode->w2)     {ierr = VecDestroy(cvode->w2);CHKERRQ(ierr);}
235   ierr = MPI_Comm_free(&(cvode->comm_sundials));CHKERRQ(ierr);
236   if (cvode->mem) {CVodeFree(&cvode->mem);}
237   ierr = PetscFree(cvode);CHKERRQ(ierr);
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "TSSetUp_Sundials_Nonlinear"
243 PetscErrorCode TSSetUp_Sundials_Nonlinear(TS ts)
244 {
245   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
246   PetscErrorCode ierr;
247   int            glosize,locsize,i;
248   PetscScalar    *y_data,*parray;
249 
250   PetscFunctionBegin;
251   ierr = PCSetFromOptions(cvode->pc);CHKERRQ(ierr);
252   /* get the vector size */
253   ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr);
254   ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr);
255 
256   /* allocate the memory for N_Vec y */
257   cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
258   if (!cvode->y) SETERRQ(1,"cvode->y is not allocated");
259 
260   /* initialize N_Vec y */
261   ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr);
262   y_data = (PetscScalar *) N_VGetArrayPointer(cvode->y);
263   for (i = 0; i < locsize; i++) y_data[i] = parray[i];
264   /*ierr = PetscMemcpy(y_data,parray,locsize*sizeof(PETSC_SCALAR)); CHKERRQ(ierr);*/
265   ierr = VecRestoreArray(ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
266   ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr);
267   ierr = VecDuplicate(ts->vec_sol,&cvode->func);CHKERRQ(ierr);
268   ierr = PetscLogObjectParent(ts,cvode->update);CHKERRQ(ierr);
269   ierr = PetscLogObjectParent(ts,cvode->func);CHKERRQ(ierr);
270 
271   /*
272       Create work vectors for the TSPSolve_Sundials() routine. Note these are
273     allocated with zero space arrays because the actual array space is provided
274     by Sundials and set using VecPlaceArray().
275   */
276   ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr);
277   ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr);
278   ierr = PetscLogObjectParent(ts,cvode->w1);CHKERRQ(ierr);
279   ierr = PetscLogObjectParent(ts,cvode->w2);CHKERRQ(ierr);
280   PetscFunctionReturn(0);
281 }
282 
283 /* type of CVODE linear multistep method */
284 const char *TSSundialsLmmTypes[] = {"","adams","bdf","TSSundialsLmmType","SUNDIALS_",0};
285 /* type of G-S orthogonalization used by CVODE linear solver */
286 const char *TSSundialsGramSchmidtTypes[] = {"","modified","classical","TSSundialsGramSchmidtType","SUNDIALS_",0};
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "TSSetFromOptions_Sundials_Nonlinear"
290 PetscErrorCode TSSetFromOptions_Sundials_Nonlinear(TS ts)
291 {
292   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
293   PetscErrorCode ierr;
294   int            indx;
295   PetscTruth     flag;
296 
297   PetscFunctionBegin;
298   ierr = PetscOptionsHead("SUNDIALS ODE solver options");CHKERRQ(ierr);
299     ierr = PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);CHKERRQ(ierr);
300     if (flag) {
301       ierr = TSSundialsSetType(ts,(TSSundialsLmmType)indx);CHKERRQ(ierr);
302     }
303     ierr = PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);CHKERRQ(ierr);
304     if (flag) {
305       ierr = TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);CHKERRQ(ierr);
306     }
307     ierr = PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);CHKERRQ(ierr);
308     ierr = PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);CHKERRQ(ierr);
309     ierr = PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);CHKERRQ(ierr);
310     ierr = PetscOptionsInt("-ts_sundials_gmres_restart","Number of GMRES orthogonalization directions","TSSundialsSetGMRESRestart",cvode->restart,&cvode->restart,&flag);CHKERRQ(ierr);
311     ierr = PetscOptionsName("-ts_sundials_exact_final_time","Allow SUNDIALS to stop near the final time, not exactly on it","TSSundialsSetExactFinalTime",&flag);CHKERRQ(ierr);
312     if (flag) cvode->exact_final_time = PETSC_TRUE;
313   ierr = PetscOptionsTail();CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "TSView_Sundials"
319 PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
320 {
321   TS_Sundials    *cvode = (TS_Sundials*)ts->data;
322   PetscErrorCode ierr;
323   char           *type;
324   char           atype[] = "Adams";
325   char           btype[] = "BDF: backward differentiation formula";
326   PetscTruth     iascii,isstring;
327   long int       nsteps,its,nfevals,nlinsetups,nfails,itmp;
328   PetscInt       qlast,qcur;
329   PetscReal      hinused,hlast,hcur,tcur;
330 
331   PetscFunctionBegin;
332   if (cvode->cvode_type == SUNDIALS_ADAMS) {type = atype;}
333   else                                     {type = btype;}
334 
335   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
336   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
337   if (iascii) {
338     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");CHKERRQ(ierr);
339     ierr = PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);CHKERRQ(ierr);
340     ierr = PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);CHKERRQ(ierr);
341     ierr = PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);CHKERRQ(ierr);
342     ierr = PetscViewerASCIIPrintf(viewer,"Sundials GMRES max iterations (same as restart in SUNDIALS) %D\n",cvode->restart);CHKERRQ(ierr);
343     if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
344       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
345     } else {
346       ierr = PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");CHKERRQ(ierr);
347     }
348 
349     ierr = CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
350                                    &nlinsetups,&nfails,&qlast,&qcur,
351                                    &hinused,&hlast,&hcur,&tcur);CHKERRQ(ierr);
352     ierr = PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);CHKERRQ(ierr);
353     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);CHKERRQ(ierr);
354     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);CHKERRQ(ierr);
355     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);CHKERRQ(ierr);
356 
357     ierr = CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);CHKERRQ(ierr);
358     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);CHKERRQ(ierr);
359     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);CHKERRQ(ierr);
360 
361     ierr = CVSpilsGetNumLinIters(cvode->mem, &its);CHKERRQ(ierr); /* its = no. of calls to TSPrecond_Sundials() */
362     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);CHKERRQ(ierr);
363     ierr = CVSpilsGetNumConvFails(cvode->mem,&itmp);CHKERRQ(ierr);
364     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);CHKERRQ(ierr);
365     ierr = CVSpilsGetNumPrecEvals(cvode->mem,&itmp);CHKERRQ(ierr);
366     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);CHKERRQ(ierr);
367     ierr = CVSpilsGetNumPrecSolves(cvode->mem,&itmp);CHKERRQ(ierr);
368     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);CHKERRQ(ierr);
369     ierr = CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);CHKERRQ(ierr);
370     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);CHKERRQ(ierr);
371     ierr = CVSpilsGetNumRhsEvals(cvode->mem,&itmp);CHKERRQ(ierr);
372     ierr = PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);CHKERRQ(ierr);
373   } else if (isstring) {
374     ierr = PetscViewerStringSPrintf(viewer,"Sundials type %s",type);CHKERRQ(ierr);
375   } else {
376     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by TS Sundials",((PetscObject)viewer)->type_name);
377   }
378   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
379   ierr = PCView(cvode->pc,viewer);CHKERRQ(ierr);
380   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
381   PetscFunctionReturn(0);
382 }
383 
384 
385 /* --------------------------------------------------------------------------*/
386 EXTERN_C_BEGIN
387 #undef __FUNCT__
388 #define __FUNCT__ "TSSundialsSetType_Sundials"
389 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
390 {
391   TS_Sundials *cvode = (TS_Sundials*)ts->data;
392 
393   PetscFunctionBegin;
394   cvode->cvode_type = type;
395   PetscFunctionReturn(0);
396 }
397 EXTERN_C_END
398 
399 EXTERN_C_BEGIN
400 #undef __FUNCT__
401 #define __FUNCT__ "TSSundialsSetGMRESRestart_Sundials"
402 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart_Sundials(TS ts,int restart)
403 {
404   TS_Sundials *cvode = (TS_Sundials*)ts->data;
405 
406   PetscFunctionBegin;
407   cvode->restart = restart;
408   PetscFunctionReturn(0);
409 }
410 EXTERN_C_END
411 
412 EXTERN_C_BEGIN
413 #undef __FUNCT__
414 #define __FUNCT__ "TSSundialsSetLinearTolerance_Sundials"
415 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
416 {
417   TS_Sundials *cvode = (TS_Sundials*)ts->data;
418 
419   PetscFunctionBegin;
420   cvode->linear_tol = tol;
421   PetscFunctionReturn(0);
422 }
423 EXTERN_C_END
424 
425 EXTERN_C_BEGIN
426 #undef __FUNCT__
427 #define __FUNCT__ "TSSundialsSetGramSchmidtType_Sundials"
428 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
429 {
430   TS_Sundials *cvode = (TS_Sundials*)ts->data;
431 
432   PetscFunctionBegin;
433   cvode->gtype = type;
434   PetscFunctionReturn(0);
435 }
436 EXTERN_C_END
437 
438 EXTERN_C_BEGIN
439 #undef __FUNCT__
440 #define __FUNCT__ "TSSundialsSetTolerance_Sundials"
441 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
442 {
443   TS_Sundials *cvode = (TS_Sundials*)ts->data;
444 
445   PetscFunctionBegin;
446   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
447   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
448   PetscFunctionReturn(0);
449 }
450 EXTERN_C_END
451 
452 EXTERN_C_BEGIN
453 #undef __FUNCT__
454 #define __FUNCT__ "TSSundialsGetPC_Sundials"
455 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC_Sundials(TS ts,PC *pc)
456 {
457   TS_Sundials *cvode = (TS_Sundials*)ts->data;
458 
459   PetscFunctionBegin;
460   *pc = cvode->pc;
461   PetscFunctionReturn(0);
462 }
463 EXTERN_C_END
464 
465 EXTERN_C_BEGIN
466 #undef __FUNCT__
467 #define __FUNCT__ "TSSundialsGetIterations_Sundials"
468 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
469 {
470   PetscFunctionBegin;
471   if (nonlin) *nonlin = ts->nonlinear_its;
472   if (lin)    *lin    = ts->linear_its;
473   PetscFunctionReturn(0);
474 }
475 EXTERN_C_END
476 
477 EXTERN_C_BEGIN
478 #undef __FUNCT__
479 #define __FUNCT__ "TSSundialsSetExactFinalTime_Sundials"
480 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime_Sundials(TS ts,PetscTruth s)
481 {
482   TS_Sundials *cvode = (TS_Sundials*)ts->data;
483 
484   PetscFunctionBegin;
485   cvode->exact_final_time = s;
486   PetscFunctionReturn(0);
487 }
488 EXTERN_C_END
489 /* -------------------------------------------------------------------------------------------*/
490 
491 #undef __FUNCT__
492 #define __FUNCT__ "TSSundialsGetIterations"
493 /*@C
494    TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.
495 
496    Not Collective
497 
498    Input parameters:
499 .    ts     - the time-step context
500 
501    Output Parameters:
502 +   nonlin - number of nonlinear iterations
503 -   lin    - number of linear iterations
504 
505    Level: advanced
506 
507    Notes:
508     These return the number since the creation of the TS object
509 
510 .keywords: non-linear iterations, linear iterations
511 
512 .seealso: TSSundialsSetType(), TSSundialsSetGMRESRestart(),
513           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
514           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
515           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
516           TSSundialsSetExactFinalTime()
517 
518 @*/
519 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
520 {
521   PetscErrorCode ierr,(*f)(TS,int*,int*);
522 
523   PetscFunctionBegin;
524   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetIterations_C",(void (**)(void))&f);CHKERRQ(ierr);
525   if (f) {
526     ierr = (*f)(ts,nonlin,lin);CHKERRQ(ierr);
527   }
528   PetscFunctionReturn(0);
529 }
530 
531 #undef __FUNCT__
532 #define __FUNCT__ "TSSundialsSetType"
533 /*@
534    TSSundialsSetType - Sets the method that Sundials will use for integration.
535 
536    Collective on TS
537 
538    Input parameters:
539 +    ts     - the time-step context
540 -    type   - one of  SUNDIALS_ADAMS or SUNDIALS_BDF
541 
542    Level: intermediate
543 
544 .keywords: Adams, backward differentiation formula
545 
546 .seealso: TSSundialsGetIterations(),  TSSundialsSetGMRESRestart(),
547           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
548           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
549           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
550           TSSundialsSetExactFinalTime()
551 @*/
552 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetType(TS ts,TSSundialsLmmType type)
553 {
554   PetscErrorCode ierr,(*f)(TS,TSSundialsLmmType);
555 
556   PetscFunctionBegin;
557   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetType_C",(void (**)(void))&f);CHKERRQ(ierr);
558   if (f) {
559     ierr = (*f)(ts,type);CHKERRQ(ierr);
560   }
561   PetscFunctionReturn(0);
562 }
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "TSSundialsSetGMRESRestart"
566 /*@
567    TSSundialsSetGMRESRestart - Sets the dimension of the Krylov space used by
568        GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
569        this is ALSO the maximum number of GMRES steps that will be used.
570 
571    Collective on TS
572 
573    Input parameters:
574 +    ts      - the time-step context
575 -    restart - number of direction vectors (the restart size).
576 
577    Level: advanced
578 
579 .keywords: GMRES, restart
580 
581 .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
582           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
583           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
584           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
585           TSSundialsSetExactFinalTime()
586 
587 @*/
588 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGMRESRestart(TS ts,int restart)
589 {
590   PetscErrorCode ierr,(*f)(TS,int);
591 
592   PetscFunctionBegin;
593   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGMRESRestart_C",(void (**)(void))&f);CHKERRQ(ierr);
594   if (f) {
595     ierr = (*f)(ts,restart);CHKERRQ(ierr);
596   }
597   PetscFunctionReturn(0);
598 }
599 
600 #undef __FUNCT__
601 #define __FUNCT__ "TSSundialsSetLinearTolerance"
602 /*@
603    TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
604        system by SUNDIALS.
605 
606    Collective on TS
607 
608    Input parameters:
609 +    ts     - the time-step context
610 -    tol    - the factor by which the tolerance on the nonlinear solver is
611              multiplied to get the tolerance on the linear solver, .05 by default.
612 
613    Level: advanced
614 
615 .keywords: GMRES, linear convergence tolerance, SUNDIALS
616 
617 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
618           TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
619           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
620           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
621           TSSundialsSetExactFinalTime()
622 
623 @*/
624 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetLinearTolerance(TS ts,double tol)
625 {
626   PetscErrorCode ierr,(*f)(TS,double);
627 
628   PetscFunctionBegin;
629   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",(void (**)(void))&f);CHKERRQ(ierr);
630   if (f) {
631     ierr = (*f)(ts,tol);CHKERRQ(ierr);
632   }
633   PetscFunctionReturn(0);
634 }
635 
636 #undef __FUNCT__
637 #define __FUNCT__ "TSSundialsSetGramSchmidtType"
638 /*@
639    TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
640         in GMRES method by SUNDIALS linear solver.
641 
642    Collective on TS
643 
644    Input parameters:
645 +    ts  - the time-step context
646 -    type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS
647 
648    Level: advanced
649 
650 .keywords: Sundials, orthogonalization
651 
652 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
653           TSSundialsSetLinearTolerance(),  TSSundialsSetTolerance(),
654           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
655           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
656           TSSundialsSetExactFinalTime()
657 
658 @*/
659 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
660 {
661   PetscErrorCode ierr,(*f)(TS,TSSundialsGramSchmidtType);
662 
663   PetscFunctionBegin;
664   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",(void (**)(void))&f);CHKERRQ(ierr);
665   if (f) {
666     ierr = (*f)(ts,type);CHKERRQ(ierr);
667   }
668   PetscFunctionReturn(0);
669 }
670 
671 #undef __FUNCT__
672 #define __FUNCT__ "TSSundialsSetTolerance"
673 /*@
674    TSSundialsSetTolerance - Sets the absolute and relative tolerance used by
675                          Sundials for error control.
676 
677    Collective on TS
678 
679    Input parameters:
680 +    ts  - the time-step context
681 .    aabs - the absolute tolerance
682 -    rel - the relative tolerance
683 
684      See the Cvode/Sundials users manual for exact details on these parameters. Essentially
685     these regulate the size of the error for a SINGLE timestep.
686 
687    Level: intermediate
688 
689 .keywords: Sundials, tolerance
690 
691 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
692           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(),
693           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
694           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
695           TSSundialsSetExactFinalTime()
696 
697 @*/
698 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetTolerance(TS ts,double aabs,double rel)
699 {
700   PetscErrorCode ierr,(*f)(TS,double,double);
701 
702   PetscFunctionBegin;
703   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetTolerance_C",(void (**)(void))&f);CHKERRQ(ierr);
704   if (f) {
705     ierr = (*f)(ts,aabs,rel);CHKERRQ(ierr);
706   }
707   PetscFunctionReturn(0);
708 }
709 
710 #undef __FUNCT__
711 #define __FUNCT__ "TSSundialsGetPC"
712 /*@
713    TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.
714 
715    Input Parameter:
716 .    ts - the time-step context
717 
718    Output Parameter:
719 .    pc - the preconditioner context
720 
721    Level: advanced
722 
723 .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
724           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
725           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
726           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
727 @*/
728 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsGetPC(TS ts,PC *pc)
729 {
730   PetscErrorCode ierr,(*f)(TS,PC *);
731 
732   PetscFunctionBegin;
733   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetPC_C",(void (**)(void))&f);CHKERRQ(ierr);
734   if (f) {
735     ierr = (*f)(ts,pc);CHKERRQ(ierr);
736   } else {
737     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"TS must be of Sundials type to extract the PC");
738   }
739 
740   PetscFunctionReturn(0);
741 }
742 
743 #undef __FUNCT__
744 #define __FUNCT__ "TSSundialsSetExactFinalTime"
745 /*@
746    TSSundialsSetExactFinalTime - Determines if Sundials interpolates solution to the
747       exact final time requested by the user or just returns it at the final time
748       it computed. (Defaults to true).
749 
750    Input Parameter:
751 +   ts - the time-step context
752 -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE
753 
754    Level: beginner
755 
756 .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
757           TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
758           TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
759           TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
760 @*/
761 PetscErrorCode PETSCTS_DLLEXPORT TSSundialsSetExactFinalTime(TS ts,PetscTruth ft)
762 {
763   PetscErrorCode ierr,(*f)(TS,PetscTruth);
764 
765   PetscFunctionBegin;
766   ierr = PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetExactFinalTime_C",(void (**)(void))&f);CHKERRQ(ierr);
767   if (f) {
768     ierr = (*f)(ts,ft);CHKERRQ(ierr);
769   }
770   PetscFunctionReturn(0);
771 }
772 
773 /* -------------------------------------------------------------------------------------------*/
774 /*MC
775       TS_Sundials - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)
776 
777    Options Database:
778 +    -ts_sundials_type <bdf,adams>
779 .    -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
780 .    -ts_sundials_atol <tol> - Absolute tolerance for convergence
781 .    -ts_sundials_rtol <tol> - Relative tolerance for convergence
782 .    -ts_sundials_linear_tolerance <tol>
783 .    -ts_sundials_gmres_restart <restart> - Number of GMRES orthogonalization directions
784 -    -ts_sundials_not_exact_final_time -Allow SUNDIALS to stop near the final time, not exactly on it
785 
786     Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply
787            only PETSc PC options
788 
789     Level: beginner
790 
791 .seealso:  TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetGMRESRestart(), TSSundialsSetLinearTolerance(),
792            TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSundialsSetExactFinalTime()
793 
794 M*/
795 EXTERN_C_BEGIN
796 #undef __FUNCT__
797 #define __FUNCT__ "TSCreate_Sundials"
798 PetscErrorCode PETSCTS_DLLEXPORT TSCreate_Sundials(TS ts)
799 {
800   TS_Sundials *cvode;
801   PetscErrorCode ierr;
802 
803   PetscFunctionBegin;
804   ts->ops->destroy         = TSDestroy_Sundials;
805   ts->ops->view            = TSView_Sundials;
806 
807   if (ts->problem_type != TS_NONLINEAR) {
808     SETERRQ(PETSC_ERR_SUP,"Only support for nonlinear problems");
809   }
810   ts->ops->setup           = TSSetUp_Sundials_Nonlinear;
811   ts->ops->step            = TSStep_Sundials_Nonlinear;
812   ts->ops->setfromoptions  = TSSetFromOptions_Sundials_Nonlinear;
813 
814   ierr = PetscNewLog(ts,TS_Sundials,&cvode);CHKERRQ(ierr);
815   ierr = PCCreate(((PetscObject)ts)->comm,&cvode->pc);CHKERRQ(ierr);
816   ierr = PetscLogObjectParent(ts,cvode->pc);CHKERRQ(ierr);
817   ts->data          = (void*)cvode;
818   cvode->cvode_type = SUNDIALS_BDF;
819   cvode->gtype      = SUNDIALS_CLASSICAL_GS;
820   cvode->restart    = 5;
821   cvode->linear_tol = .05;
822 
823   cvode->exact_final_time = PETSC_FALSE;
824 
825   ierr = MPI_Comm_dup(((PetscObject)ts)->comm,&(cvode->comm_sundials));CHKERRQ(ierr);
826   /* set tolerance for Sundials */
827   cvode->reltol = 1e-6;
828   cvode->abstol = 1e-6;
829 
830   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetType_C","TSSundialsSetType_Sundials",
831                     TSSundialsSetType_Sundials);CHKERRQ(ierr);
832   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGMRESRestart_C",
833                     "TSSundialsSetGMRESRestart_Sundials",
834                     TSSundialsSetGMRESRestart_Sundials);CHKERRQ(ierr);
835   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetLinearTolerance_C",
836                     "TSSundialsSetLinearTolerance_Sundials",
837                      TSSundialsSetLinearTolerance_Sundials);CHKERRQ(ierr);
838   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",
839                     "TSSundialsSetGramSchmidtType_Sundials",
840                      TSSundialsSetGramSchmidtType_Sundials);CHKERRQ(ierr);
841   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetTolerance_C",
842                     "TSSundialsSetTolerance_Sundials",
843                      TSSundialsSetTolerance_Sundials);CHKERRQ(ierr);
844   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetPC_C",
845                     "TSSundialsGetPC_Sundials",
846                      TSSundialsGetPC_Sundials);CHKERRQ(ierr);
847   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetIterations_C",
848                     "TSSundialsGetIterations_Sundials",
849                      TSSundialsGetIterations_Sundials);CHKERRQ(ierr);
850   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetExactFinalTime_C",
851                     "TSSundialsSetExactFinalTime_Sundials",
852                      TSSundialsSetExactFinalTime_Sundials);CHKERRQ(ierr);
853   PetscFunctionReturn(0);
854 }
855 EXTERN_C_END
856 
857 
858 
859 
860 
861 
862 
863 
864 
865 
866