Actual source code: sundials.c
1: #define PETSCTS_DLL
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
11: /*
12: TSPrecond_Sundials - function that we provide to SUNDIALS to
13: evaluate the preconditioner.
14: */
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;
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:
33: /* This allows us to construct preconditioners in-place if we like */
34: MatSetUnfactored(Jac);
35:
36: /* jok - TRUE means reuse current Jacobian else recompute Jacobian */
37: if (jok) {
38: MatCopy(cvode->pmat,Jac,str);
39: *jcurPtr = FALSE;
40: } else {
41: /* make PETSc vector yy point to SUNDIALS vector y */
42: y_data = (PetscScalar *) N_VGetArrayPointer(y);
43: VecPlaceArray(yy,y_data);
45: /* compute the Jacobian */
46: TSComputeRHSJacobian(ts,ts->ptime,yy,&Jac,&Jac,&str);
47: VecResetArray(yy);
49: /* copy the Jacobian matrix */
50: if (!cvode->pmat) {
51: MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);
52: PetscLogObjectParent(ts,cvode->pmat);
53: } else {
54: MatCopy(Jac,cvode->pmat,str);
55: }
56: *jcurPtr = TRUE;
57: }
58:
59: /* construct I-gamma*Jac */
60: gm = -_gamma;
61: MatScale(Jac,gm);
62: MatShift(Jac,one);
63:
64: PCSetOperators(pc,Jac,Jac,str);
65: return(0);
66: }
68: /*
69: TSPSolve_Sundials - routine that we provide to Sundials that applies the preconditioner.
70: */
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;
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: VecPlaceArray(rr,r_data);
88: VecPlaceArray(zz,z_data);
90: /* Solve the Px=r and put the result in zz */
91: PCApply(pc,rr,zz);
92: VecResetArray(rr);
93: VecResetArray(zz);
94: return(0);
95: }
97: /*
98: TSFunction_Sundials - routine that we provide to Sundials that applies the right hand side.
99: */
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;
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: VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr);
116: VecPlaceArray(yyd,ydot_data); CHKERRABORT(comm,ierr);
118: /* now compute the right hand side function */
119: TSComputeRHSFunction(ts,t,yy,yyd); CHKERRABORT(comm,ierr);
120: VecResetArray(yy); CHKERRABORT(comm,ierr);
121: VecResetArray(yyd); CHKERRABORT(comm,ierr);
122: return(0);
123: }
125: /*
126: TSStep_Sundials_Nonlinear - Calls Sundials to integrate the ODE.
127: */
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;
141: PetscInt i,max_steps = ts->max_steps,flag;
142: long int its;
143: realtype t,tout;
144: PetscScalar *y_data;
145: void *mem;
146: const PCType pctype;
147: PetscTruth pcnone;
150: /* Call CVodeCreate to create the solver memory */
151: mem = CVodeCreate(cvode->cvode_type, CV_NEWTON);
152: if (!mem) SETERRQ(1,"CVodeCreate() fails");
153: flag = CVodeSetFdata(mem,ts);
154: if (flag) SETERRQ(1,"CVodeSetFdata() fails");
156: /*
157: Call CVodeMalloc to initialize the integrator memory:
158: mem is the pointer to the integrator memory returned by CVodeCreate
159: f is the user's right hand side function in y'=f(t,y)
160: T0 is the initial time
161: u is the initial dependent variable vector
162: CV_SS specifies scalar relative and absolute tolerances
163: reltol is the relative tolerance
164: &abstol is a pointer to the scalar absolute tolerance
165: */
166: flag = CVodeMalloc(mem,TSFunction_Sundials,ts->ptime,cvode->y,CV_SS,cvode->reltol,&cvode->abstol);
167: if (flag) SETERRQ(1,"CVodeMalloc() fails");
169: /* initialize the number of steps */
170: *steps = -ts->steps;
171: TSMonitor(ts,ts->steps,ts->ptime,sol);
173: /* call CVSpgmr to use GMRES as the linear solver. */
174: /* setup the ode integrator with the given preconditioner */
175: PCGetType(cvode->pc,&pctype);
176: PetscTypeCompare((PetscObject)cvode->pc,PCNONE,&pcnone);
177: if (pcnone){
178: flag = CVSpgmr(mem,PREC_NONE,0);
179: } else {
180: flag = CVSpgmr(mem,PREC_LEFT,0);
181: }
182: if (flag) SETERRQ(1,"CVSpgmr() fails");
183:
184: /* Set preconditioner setup and solve routines Precond and PSolve,
185: and the pointer to the user-defined block data */
186: flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials,ts);
187: if (flag) SETERRQ(1,"CVSpgmrSetPreconditioner() fails");
189: flag = CVSpilsSetGSType(mem, MODIFIED_GS);
190: if (flag) SETERRQ(1,"CVSpgmrSetGSType() fails");
192: tout = ts->max_time;
193: VecGetArray(ts->vec_sol,&y_data);
194: N_VSetArrayPointer((realtype *)y_data,cvode->y);
195: VecRestoreArray(ts->vec_sol,PETSC_NULL);
196: for (i = 0; i < max_steps; i++) {
197: if (ts->ptime >= ts->max_time) break;
198: CVode(mem,tout,cvode->y,&t,CV_ONE_STEP);
199: if (ts->ops->postupdate){
200: (*ts->ops->postupdate)(ts,ts->ptime,PETSC_NULL);
201: }
202: if (t > ts->max_time && cvode->exact_final_time) {
203: /* interpolate to final requested time */
204: CVodeGetDky(mem,tout,0,cvode->y);
205: t = tout;
206: }
207: ts->time_step = t - ts->ptime;
208: ts->ptime = t;
210: /* copy the solution from cvode->y to cvode->update and sol */
211: VecPlaceArray(cvode->w1,y_data);
212: VecCopy(cvode->w1,cvode->update);
213: VecResetArray(cvode->w1);
214: VecCopy(cvode->update,sol);
215: CVodeGetNumNonlinSolvIters(mem,&its);
216: ts->nonlinear_its = its;
217: CVSpilsGetNumLinIters(mem, &its);
218: ts->linear_its = its;
219: ts->steps++;
220: TSMonitor(ts,ts->steps,t,sol);
221: }
222: cvode->mem = mem;
223: *steps += ts->steps;
224: *time = t;
225: return(0);
226: }
230: PetscErrorCode TSDestroy_Sundials(TS ts)
231: {
232: TS_Sundials *cvode = (TS_Sundials*)ts->data;
236: if (cvode->pmat) {MatDestroy(cvode->pmat);}
237: if (cvode->pc) {PCDestroy(cvode->pc);}
238: if (cvode->update) {VecDestroy(cvode->update);}
239: if (cvode->func) {VecDestroy(cvode->func);}
240: if (cvode->rhs) {VecDestroy(cvode->rhs);}
241: if (cvode->w1) {VecDestroy(cvode->w1);}
242: if (cvode->w2) {VecDestroy(cvode->w2);}
243: MPI_Comm_free(&(cvode->comm_sundials));
244: if (cvode->mem) {CVodeFree(&cvode->mem);}
245: PetscFree(cvode);
246: return(0);
247: }
251: PetscErrorCode TSSetUp_Sundials_Nonlinear(TS ts)
252: {
253: TS_Sundials *cvode = (TS_Sundials*)ts->data;
255: int glosize,locsize,i;
256: PetscScalar *y_data,*parray;
259: PCSetFromOptions(cvode->pc);
260: /* get the vector size */
261: VecGetSize(ts->vec_sol,&glosize);
262: VecGetLocalSize(ts->vec_sol,&locsize);
264: /* allocate the memory for N_Vec y */
265: cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize);
266: if (!cvode->y) SETERRQ(1,"cvode->y is not allocated");
268: /* initialize N_Vec y */
269: VecGetArray(ts->vec_sol,&parray);
270: y_data = (PetscScalar *) N_VGetArrayPointer(cvode->y);
271: for (i = 0; i < locsize; i++) y_data[i] = parray[i];
272: /*PetscMemcpy(y_data,parray,locsize*sizeof(PETSC_SCALAR)); */
273: VecRestoreArray(ts->vec_sol,PETSC_NULL);
274: VecDuplicate(ts->vec_sol,&cvode->update);
275: VecDuplicate(ts->vec_sol,&cvode->func);
276: PetscLogObjectParent(ts,cvode->update);
277: PetscLogObjectParent(ts,cvode->func);
279: /*
280: Create work vectors for the TSPSolve_Sundials() routine. Note these are
281: allocated with zero space arrays because the actual array space is provided
282: by Sundials and set using VecPlaceArray().
283: */
284: VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w1);
285: VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w2);
286: PetscLogObjectParent(ts,cvode->w1);
287: PetscLogObjectParent(ts,cvode->w2);
288: return(0);
289: }
291: /* type of CVODE linear multistep method */
292: const char *TSSundialsLmmTypes[] = {"","adams","bdf","TSSundialsLmmType","SUNDIALS_",0};
293: /* type of G-S orthogonalization used by CVODE linear solver */
294: const char *TSSundialsGramSchmidtTypes[] = {"","modified","classical","TSSundialsGramSchmidtType","SUNDIALS_",0};
298: PetscErrorCode TSSetFromOptions_Sundials_Nonlinear(TS ts)
299: {
300: TS_Sundials *cvode = (TS_Sundials*)ts->data;
302: int indx;
303: PetscTruth flag;
306: PetscOptionsHead("SUNDIALS ODE solver options");
307: PetscOptionsEList("-ts_sundials_type","Scheme","TSSundialsSetType",TSSundialsLmmTypes,3,TSSundialsLmmTypes[cvode->cvode_type],&indx,&flag);
308: if (flag) {
309: TSSundialsSetType(ts,(TSSundialsLmmType)indx);
310: }
311: PetscOptionsEList("-ts_sundials_gramschmidt_type","Type of orthogonalization","TSSundialsSetGramSchmidtType",TSSundialsGramSchmidtTypes,3,TSSundialsGramSchmidtTypes[cvode->gtype],&indx,&flag);
312: if (flag) {
313: TSSundialsSetGramSchmidtType(ts,(TSSundialsGramSchmidtType)indx);
314: }
315: PetscOptionsReal("-ts_sundials_atol","Absolute tolerance for convergence","TSSundialsSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);
316: PetscOptionsReal("-ts_sundials_rtol","Relative tolerance for convergence","TSSundialsSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);
317: PetscOptionsReal("-ts_sundials_linear_tolerance","Convergence tolerance for linear solve","TSSundialsSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);
318: PetscOptionsInt("-ts_sundials_gmres_restart","Number of GMRES orthogonalization directions","TSSundialsSetGMRESRestart",cvode->restart,&cvode->restart,&flag);
319: PetscOptionsName("-ts_sundials_exact_final_time","Allow SUNDIALS to stop near the final time, not exactly on it","TSSundialsSetExactFinalTime",&flag);
320: if (flag) cvode->exact_final_time = PETSC_TRUE;
321: PetscOptionsTail();
322: return(0);
323: }
327: PetscErrorCode TSView_Sundials(TS ts,PetscViewer viewer)
328: {
329: TS_Sundials *cvode = (TS_Sundials*)ts->data;
331: char *type;
332: char atype[] = "Adams";
333: char btype[] = "BDF: backward differentiation formula";
334: PetscTruth iascii,isstring;
335: long int nsteps,its,nfevals,nlinsetups,nfails,itmp;
336: PetscInt qlast,qcur;
337: PetscReal hinused,hlast,hcur,tcur,tolsfac;
340: if (cvode->cvode_type == SUNDIALS_ADAMS) {type = atype;}
341: else {type = btype;}
343: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
344: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
345: if (iascii) {
346: PetscViewerASCIIPrintf(viewer,"Sundials integrater does not use SNES!\n");
347: PetscViewerASCIIPrintf(viewer,"Sundials integrater type %s\n",type);
348: PetscViewerASCIIPrintf(viewer,"Sundials abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);
349: PetscViewerASCIIPrintf(viewer,"Sundials linear solver tolerance factor %g\n",cvode->linear_tol);
350: PetscViewerASCIIPrintf(viewer,"Sundials GMRES max iterations (same as restart in SUNDIALS) %D\n",cvode->restart);
351: if (cvode->gtype == SUNDIALS_MODIFIED_GS) {
352: PetscViewerASCIIPrintf(viewer,"Sundials using modified Gram-Schmidt for orthogonalization in GMRES\n");
353: } else {
354: PetscViewerASCIIPrintf(viewer,"Sundials using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");
355: }
356:
357: /* Outputs from CVODE, CVSPILS */
358: CVodeGetTolScaleFactor(cvode->mem,&tolsfac);
359: PetscViewerASCIIPrintf(viewer,"Sundials suggested factor for tolerance scaling %g\n",tolsfac);
360: CVodeGetIntegratorStats(cvode->mem,&nsteps,&nfevals,
361: &nlinsetups,&nfails,&qlast,&qcur,
362: &hinused,&hlast,&hcur,&tcur);
363: PetscViewerASCIIPrintf(viewer,"Sundials cumulative number of internal steps %D\n",nsteps);
364: PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to rhs function %D\n",nfevals);
365: PetscViewerASCIIPrintf(viewer,"Sundials no. of calls to linear solver setup function %D\n",nlinsetups);
366: PetscViewerASCIIPrintf(viewer,"Sundials no. of error test failures %D\n",nfails);
368: CVodeGetNonlinSolvStats(cvode->mem,&its,&nfails);
369: PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear solver iterations %D\n",its);
370: PetscViewerASCIIPrintf(viewer,"Sundials no. of nonlinear convergence failure %D\n",nfails);
372: CVSpilsGetNumLinIters(cvode->mem, &its); /* its = no. of calls to TSPrecond_Sundials() */
373: PetscViewerASCIIPrintf(viewer,"Sundials no. of linear iterations %D\n",its);
374: CVSpilsGetNumConvFails(cvode->mem,&itmp);
375: PetscViewerASCIIPrintf(viewer,"Sundials no. of linear convergence failures %D\n",itmp);
376: CVSpilsGetNumPrecEvals(cvode->mem,&itmp);
377: PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner evaluations %D\n",itmp);
378: CVSpilsGetNumPrecSolves(cvode->mem,&itmp);
379: PetscViewerASCIIPrintf(viewer,"Sundials no. of preconditioner solves %D\n",itmp);
380: CVSpilsGetNumJtimesEvals(cvode->mem,&itmp);
381: PetscViewerASCIIPrintf(viewer,"Sundials no. of Jacobian-vector product evaluations %D\n",itmp);
382: CVSpilsGetNumRhsEvals(cvode->mem,&itmp);
383: PetscViewerASCIIPrintf(viewer,"Sundials no. of rhs calls for finite diff. Jacobian-vector evals %D\n",itmp);
384: } else if (isstring) {
385: PetscViewerStringSPrintf(viewer,"Sundials type %s",type);
386: } else {
387: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by TS Sundials",((PetscObject)viewer)->type_name);
388: }
389: PetscViewerASCIIPushTab(viewer);
390: PCView(cvode->pc,viewer);
391: PetscViewerASCIIPopTab(viewer);
392: return(0);
393: }
396: /* --------------------------------------------------------------------------*/
400: PetscErrorCode TSSundialsSetType_Sundials(TS ts,TSSundialsLmmType type)
401: {
402: TS_Sundials *cvode = (TS_Sundials*)ts->data;
403:
405: cvode->cvode_type = type;
406: return(0);
407: }
413: PetscErrorCode TSSundialsSetGMRESRestart_Sundials(TS ts,int restart)
414: {
415: TS_Sundials *cvode = (TS_Sundials*)ts->data;
416:
418: cvode->restart = restart;
419: return(0);
420: }
426: PetscErrorCode TSSundialsSetLinearTolerance_Sundials(TS ts,double tol)
427: {
428: TS_Sundials *cvode = (TS_Sundials*)ts->data;
429:
431: cvode->linear_tol = tol;
432: return(0);
433: }
439: PetscErrorCode TSSundialsSetGramSchmidtType_Sundials(TS ts,TSSundialsGramSchmidtType type)
440: {
441: TS_Sundials *cvode = (TS_Sundials*)ts->data;
442:
444: cvode->gtype = type;
445: return(0);
446: }
452: PetscErrorCode TSSundialsSetTolerance_Sundials(TS ts,double aabs,double rel)
453: {
454: TS_Sundials *cvode = (TS_Sundials*)ts->data;
455:
457: if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
458: if (rel != PETSC_DECIDE) cvode->reltol = rel;
459: return(0);
460: }
466: PetscErrorCode TSSundialsGetPC_Sundials(TS ts,PC *pc)
467: {
468: TS_Sundials *cvode = (TS_Sundials*)ts->data;
471: *pc = cvode->pc;
472: return(0);
473: }
479: PetscErrorCode TSSundialsGetIterations_Sundials(TS ts,int *nonlin,int *lin)
480: {
482: if (nonlin) *nonlin = ts->nonlinear_its;
483: if (lin) *lin = ts->linear_its;
484: return(0);
485: }
487:
491: PetscErrorCode TSSundialsSetExactFinalTime_Sundials(TS ts,PetscTruth s)
492: {
493: TS_Sundials *cvode = (TS_Sundials*)ts->data;
494:
496: cvode->exact_final_time = s;
497: return(0);
498: }
500: /* -------------------------------------------------------------------------------------------*/
504: /*@C
505: TSSundialsGetIterations - Gets the number of nonlinear and linear iterations used so far by Sundials.
507: Not Collective
509: Input parameters:
510: . ts - the time-step context
512: Output Parameters:
513: + nonlin - number of nonlinear iterations
514: - lin - number of linear iterations
516: Level: advanced
518: Notes:
519: These return the number since the creation of the TS object
521: .keywords: non-linear iterations, linear iterations
523: .seealso: TSSundialsSetType(), TSSundialsSetGMRESRestart(),
524: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
525: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
526: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
527: TSSundialsSetExactFinalTime()
529: @*/
530: PetscErrorCode TSSundialsGetIterations(TS ts,int *nonlin,int *lin)
531: {
532: PetscErrorCode ierr,(*f)(TS,int*,int*);
533:
535: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetIterations_C",(void (**)(void))&f);
536: if (f) {
537: (*f)(ts,nonlin,lin);
538: }
539: return(0);
540: }
544: /*@
545: TSSundialsSetType - Sets the method that Sundials will use for integration.
547: Collective on TS
549: Input parameters:
550: + ts - the time-step context
551: - type - one of SUNDIALS_ADAMS or SUNDIALS_BDF
553: Level: intermediate
555: .keywords: Adams, backward differentiation formula
557: .seealso: TSSundialsGetIterations(), TSSundialsSetGMRESRestart(),
558: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
559: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
560: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
561: TSSundialsSetExactFinalTime()
562: @*/
563: PetscErrorCode TSSundialsSetType(TS ts,TSSundialsLmmType type)
564: {
565: PetscErrorCode ierr,(*f)(TS,TSSundialsLmmType);
566:
568: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetType_C",(void (**)(void))&f);
569: if (f) {
570: (*f)(ts,type);
571: }
572: return(0);
573: }
577: /*@
578: TSSundialsSetGMRESRestart - Sets the dimension of the Krylov space used by
579: GMRES in the linear solver in SUNDIALS. SUNDIALS DOES NOT use restarted GMRES so
580: this is ALSO the maximum number of GMRES steps that will be used.
582: Collective on TS
584: Input parameters:
585: + ts - the time-step context
586: - restart - number of direction vectors (the restart size).
588: Level: advanced
590: .keywords: GMRES, restart
592: .seealso: TSSundialsGetIterations(), TSSundialsSetType(),
593: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
594: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
595: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
596: TSSundialsSetExactFinalTime()
598: @*/
599: PetscErrorCode TSSundialsSetGMRESRestart(TS ts,int restart)
600: {
601: PetscErrorCode ierr,(*f)(TS,int);
604: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGMRESRestart_C",(void (**)(void))&f);
605: if (f) {
606: (*f)(ts,restart);
607: }
608: return(0);
609: }
613: /*@
614: TSSundialsSetLinearTolerance - Sets the tolerance used to solve the linear
615: system by SUNDIALS.
617: Collective on TS
619: Input parameters:
620: + ts - the time-step context
621: - tol - the factor by which the tolerance on the nonlinear solver is
622: multiplied to get the tolerance on the linear solver, .05 by default.
624: Level: advanced
626: .keywords: GMRES, linear convergence tolerance, SUNDIALS
628: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
629: TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
630: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
631: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
632: TSSundialsSetExactFinalTime()
634: @*/
635: PetscErrorCode TSSundialsSetLinearTolerance(TS ts,double tol)
636: {
637: PetscErrorCode ierr,(*f)(TS,double);
638:
640: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetLinearTolerance_C",(void (**)(void))&f);
641: if (f) {
642: (*f)(ts,tol);
643: }
644: return(0);
645: }
649: /*@
650: TSSundialsSetGramSchmidtType - Sets type of orthogonalization used
651: in GMRES method by SUNDIALS linear solver.
653: Collective on TS
655: Input parameters:
656: + ts - the time-step context
657: - type - either SUNDIALS_MODIFIED_GS or SUNDIALS_CLASSICAL_GS
659: Level: advanced
661: .keywords: Sundials, orthogonalization
663: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
664: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(),
665: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
666: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
667: TSSundialsSetExactFinalTime()
669: @*/
670: PetscErrorCode TSSundialsSetGramSchmidtType(TS ts,TSSundialsGramSchmidtType type)
671: {
672: PetscErrorCode ierr,(*f)(TS,TSSundialsGramSchmidtType);
673:
675: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",(void (**)(void))&f);
676: if (f) {
677: (*f)(ts,type);
678: }
679: return(0);
680: }
684: /*@
685: TSSundialsSetTolerance - Sets the absolute and relative tolerance used by
686: Sundials for error control.
688: Collective on TS
690: Input parameters:
691: + ts - the time-step context
692: . aabs - the absolute tolerance
693: - rel - the relative tolerance
695: See the Cvode/Sundials users manual for exact details on these parameters. Essentially
696: these regulate the size of the error for a SINGLE timestep.
698: Level: intermediate
700: .keywords: Sundials, tolerance
702: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
703: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(),
704: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
705: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC(),
706: TSSundialsSetExactFinalTime()
708: @*/
709: PetscErrorCode TSSundialsSetTolerance(TS ts,double aabs,double rel)
710: {
711: PetscErrorCode ierr,(*f)(TS,double,double);
712:
714: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetTolerance_C",(void (**)(void))&f);
715: if (f) {
716: (*f)(ts,aabs,rel);
717: }
718: return(0);
719: }
723: /*@
724: TSSundialsGetPC - Extract the PC context from a time-step context for Sundials.
726: Input Parameter:
727: . ts - the time-step context
729: Output Parameter:
730: . pc - the preconditioner context
732: Level: advanced
734: .seealso: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
735: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
736: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
737: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance()
738: @*/
739: PetscErrorCode TSSundialsGetPC(TS ts,PC *pc)
740: {
741: PetscErrorCode ierr,(*f)(TS,PC *);
744: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsGetPC_C",(void (**)(void))&f);
745: if (f) {
746: (*f)(ts,pc);
747: } else {
748: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"TS must be of Sundials type to extract the PC");
749: }
751: return(0);
752: }
756: /*@
757: TSSundialsSetExactFinalTime - Determines if Sundials interpolates solution to the
758: exact final time requested by the user or just returns it at the final time
759: it computed. (Defaults to true).
761: Input Parameter:
762: + ts - the time-step context
763: - ft - PETSC_TRUE if interpolates, else PETSC_FALSE
765: Level: beginner
767: .seealso:TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
768: TSSundialsSetLinearTolerance(), TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(),
769: TSSundialsGetIterations(), TSSundialsSetType(), TSSundialsSetGMRESRestart(),
770: TSSundialsSetLinearTolerance(), TSSundialsSetTolerance(), TSSundialsGetPC()
771: @*/
772: PetscErrorCode TSSundialsSetExactFinalTime(TS ts,PetscTruth ft)
773: {
774: PetscErrorCode ierr,(*f)(TS,PetscTruth);
777: PetscObjectQueryFunction((PetscObject)ts,"TSSundialsSetExactFinalTime_C",(void (**)(void))&f);
778: if (f) {
779: (*f)(ts,ft);
780: }
781: return(0);
782: }
784: /* -------------------------------------------------------------------------------------------*/
785: /*MC
786: TS_Sundials - ODE solver using the LLNL CVODE/SUNDIALS package (now called SUNDIALS)
788: Options Database:
789: + -ts_sundials_type <bdf,adams>
790: . -ts_sundials_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
791: . -ts_sundials_atol <tol> - Absolute tolerance for convergence
792: . -ts_sundials_rtol <tol> - Relative tolerance for convergence
793: . -ts_sundials_linear_tolerance <tol>
794: . -ts_sundials_gmres_restart <restart> - Number of GMRES orthogonalization directions
795: - -ts_sundials_not_exact_final_time -Allow SUNDIALS to stop near the final time, not exactly on it
797: Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply
798: only PETSc PC options
800: Level: beginner
802: .seealso: TSCreate(), TS, TSSetType(), TSSundialsSetType(), TSSundialsSetGMRESRestart(), TSSundialsSetLinearTolerance(),
803: TSSundialsSetGramSchmidtType(), TSSundialsSetTolerance(), TSSundialsGetPC(), TSSundialsGetIterations(), TSSundialsSetExactFinalTime()
805: M*/
809: PetscErrorCode TSCreate_Sundials(TS ts)
810: {
811: TS_Sundials *cvode;
815: ts->ops->destroy = TSDestroy_Sundials;
816: ts->ops->view = TSView_Sundials;
818: if (ts->problem_type != TS_NONLINEAR) {
819: SETERRQ(PETSC_ERR_SUP,"Only support for nonlinear problems");
820: }
821: ts->ops->setup = TSSetUp_Sundials_Nonlinear;
822: ts->ops->step = TSStep_Sundials_Nonlinear;
823: ts->ops->setfromoptions = TSSetFromOptions_Sundials_Nonlinear;
825: PetscNewLog(ts,TS_Sundials,&cvode);
826: PCCreate(((PetscObject)ts)->comm,&cvode->pc);
827: PetscLogObjectParent(ts,cvode->pc);
828: ts->data = (void*)cvode;
829: cvode->cvode_type = SUNDIALS_BDF;
830: cvode->gtype = SUNDIALS_CLASSICAL_GS;
831: cvode->restart = 5;
832: cvode->linear_tol = .05;
834: cvode->exact_final_time = PETSC_FALSE;
836: MPI_Comm_dup(((PetscObject)ts)->comm,&(cvode->comm_sundials));
837: /* set tolerance for Sundials */
838: cvode->reltol = 1e-6;
839: cvode->abstol = 1e-6;
841: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetType_C","TSSundialsSetType_Sundials",
842: TSSundialsSetType_Sundials);
843: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGMRESRestart_C",
844: "TSSundialsSetGMRESRestart_Sundials",
845: TSSundialsSetGMRESRestart_Sundials);
846: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetLinearTolerance_C",
847: "TSSundialsSetLinearTolerance_Sundials",
848: TSSundialsSetLinearTolerance_Sundials);
849: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetGramSchmidtType_C",
850: "TSSundialsSetGramSchmidtType_Sundials",
851: TSSundialsSetGramSchmidtType_Sundials);
852: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetTolerance_C",
853: "TSSundialsSetTolerance_Sundials",
854: TSSundialsSetTolerance_Sundials);
855: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetPC_C",
856: "TSSundialsGetPC_Sundials",
857: TSSundialsGetPC_Sundials);
858: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsGetIterations_C",
859: "TSSundialsGetIterations_Sundials",
860: TSSundialsGetIterations_Sundials);
861: PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSSundialsSetExactFinalTime_C",
862: "TSSundialsSetExactFinalTime_Sundials",
863: TSSundialsSetExactFinalTime_Sundials);
864: return(0);
865: }