Actual source code: petscpvode.c

  1: #define PETSCTS_DLL

  3: /*
  4:     Provides a PETSc interface to PVODE. Alan Hindmarsh's parallel ODE
  5:    solver.
  6: */

  8: #include "src/ts/impls/implicit/pvode/petscpvode.h"  /*I "petscts.h" I*/    

 12: /*@C
 13:    TSPVodeGetParameters - Extract "iopt" and "ropt" PVODE parameters

 15:    Input Parameter:
 16: .    ts - the time-step context

 18:    Output Parameters:
 19: +   opt_size - size of the parameter arrays (will be set to PVODE value OPT_SIZE)
 20: .   iopt - the integer parameters
 21: -   ropt - the double paramters


 24:    Level: advanced
 25: g
 26:    Notes: You may pass PETSC_NULL for any value you do not desire

 28:           PETSc initializes these array with the default PVODE values of 0, you may 
 29:           change them before calling the TS solver.

 31:           See the PVODE include file cvode.h for the definitions of the fields

 33:     Suggested by: Timothy William Chevalier

 35: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
 36:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
 37:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
 38:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance()
 39: @*/
 40: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeGetParameters(TS ts,int *opt_size,long int *iopt[],double *ropt[])
 41: {
 42:   TS_PVode     *cvode = (TS_PVode*)ts->data;

 45:   if (opt_size) *opt_size = OPT_SIZE;
 46:   if (iopt)     *iopt     = cvode->iopt;
 47:   if (ropt)     *ropt     = cvode->ropt;
 48:   return(0);
 49: }

 51: /*
 52:       TSPrecond_PVode - function that we provide to PVODE to
 53:                         evaluate the preconditioner.

 55:     Contributed by: Liyang Xu

 57: */
 60: PetscErrorCode TSPrecond_PVode(integertype N,realtype tn,N_Vector y,N_Vector fy,booleantype jok,
 61:                     booleantype *jcurPtr,realtype _gamma,N_Vector ewt,realtype h,
 62:                     realtype uround,long int *nfePtr,void *P_data,
 63:                     N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
 64: {
 65:   TS           ts = (TS) P_data;
 66:   TS_PVode     *cvode = (TS_PVode*)ts->data;
 67:   PC           pc = cvode->pc;
 69:   Mat          Jac = ts->B;
 70:   Vec          tmpy = cvode->w1;
 71:   PetscScalar  one = 1.0,gm;
 72:   MatStructure str = DIFFERENT_NONZERO_PATTERN;
 73: 
 75:   /* This allows us to construct preconditioners in-place if we like */
 76:   MatSetUnfactored(Jac);

 78:   /*
 79:        jok - TRUE means reuse current Jacobian else recompute Jacobian
 80:   */
 81:   if (jok) {
 82:     MatCopy(cvode->pmat,Jac,SAME_NONZERO_PATTERN);
 83:     str      = SAME_NONZERO_PATTERN;
 84:     *jcurPtr = FALSE;
 85:   } else {
 86:     /* make PETSc vector tmpy point to PVODE vector y */
 87:     VecPlaceArray(tmpy,N_VGetData(y));

 89:     /* compute the Jacobian */
 90:     TSComputeRHSJacobian(ts,ts->ptime,tmpy,&Jac,&Jac,&str);

 92:     /* copy the Jacobian matrix */
 93:     if (!cvode->pmat) {
 94:       MatDuplicate(Jac,MAT_COPY_VALUES,&cvode->pmat);
 95:       PetscLogObjectParent(ts,cvode->pmat);
 96:     }
 97:     MatCopy(Jac,cvode->pmat,SAME_NONZERO_PATTERN);

 99:     *jcurPtr = TRUE;
100:   }

102:   /* construct I-gamma*Jac  */
103:   gm   = -_gamma;
104:   MatScale(Jac,gm);
105:   MatShift(Jac,one);
106: 
107:   PCSetOperators(pc,Jac,Jac,str);
108:   return(0);
109: }

111: /*
112:      TSPSolve_PVode -  routine that we provide to PVode that applies the preconditioner.
113:       
114:     Contributed by: Liyang Xu

116: */
119: PetscErrorCode TSPSolve_PVode(integertype N,realtype tn,N_Vector y,N_Vector fy,N_Vector vtemp,
120:                    realtype _gamma,N_Vector ewt,realtype delta,long int *nfePtr,
121:                    N_Vector r,int lr,void *P_data,N_Vector z)
122: {
123:   TS       ts = (TS) P_data;
124:   TS_PVode *cvode = (TS_PVode*)ts->data;
125:   PC       pc = cvode->pc;
126:   Vec      rr = cvode->w1,xx = cvode->w2;

130:   /*
131:       Make the PETSc work vectors rr and xx point to the arrays in the PVODE vectors 
132:   */
133:   VecPlaceArray(rr,N_VGetData(r));
134:   VecPlaceArray(xx,N_VGetData(z));

136:   /* 
137:       Solve the Px=r and put the result in xx 
138:   */
139:   PCApply(pc,rr,xx);
140:   cvode->linear_solves++;


143:   return(0);
144: }

146: /*
147:         TSFunction_PVode - routine that we provide to PVode that applies the right hand side.
148:       
149:     Contributed by: Liyang Xu
150: */
153: void TSFunction_PVode(int N,double t,N_Vector y,N_Vector ydot,void *ctx)
154: {
155:   TS        ts = (TS) ctx;
156:   TS_PVode *cvode = (TS_PVode*)ts->data;
157:   Vec       tmpx = cvode->w1,tmpy = cvode->w2;

161:   /*
162:       Make the PETSc work vectors tmpx and tmpy point to the arrays in the PVODE vectors 
163:   */
164:   VecPlaceArray(tmpx,N_VGetData(y));
165:   if (ierr) {
166:     (*PetscErrorPrintf)("TSFunction_PVode:Could not place array. Error code %d",(int)ierr);
167:   }
168:   VecPlaceArray(tmpy,N_VGetData(ydot));
169:   if (ierr) {
170:     (*PetscErrorPrintf)("TSFunction_PVode:Could not place array. Error code %d",(int)ierr);
171:   }

173:   /* now compute the right hand side function */
174:   TSComputeRHSFunction(ts,t,tmpx,tmpy);
175:   if (ierr) {
176:     (*PetscErrorPrintf)("TSFunction_PVode:Could not compute RHS function. Error code %d",(int)ierr);
177:   }
178: }

180: /*
181:        TSStep_PVode_Nonlinear - Calls PVode to integrate the ODE.

183:     Contributed by: Liyang Xu
184: */
187: /* 
188:     TSStep_PVode_Nonlinear - 
189:   
190:    steps - number of time steps
191:    time - time that integrater is  terminated. 

193: */
194: PetscErrorCode TSStep_PVode_Nonlinear(TS ts,int *steps,double *time)
195: {
196:   TS_PVode  *cvode = (TS_PVode*)ts->data;
197:   Vec       sol = ts->vec_sol;
198:   int       ierr;
199:   int i,max_steps = ts->max_steps,flag;
200:   double    t,tout;
201:   realtype  *tmp;

204:   /* initialize the number of steps */
205:   *steps = -ts->steps;
206:   TSMonitor(ts,ts->steps,ts->ptime,sol);

208:   /* call CVSpgmr to use GMRES as the linear solver. */
209:   /* setup the ode integrator with the given preconditioner */
210:   CVSpgmr(cvode->mem,LEFT,cvode->gtype,cvode->restart,cvode->linear_tol,TSPrecond_PVode,TSPSolve_PVode,ts,0,0);

212:   tout = ts->max_time;
213:   for (i=0; i<max_steps; i++) {
214:     if (ts->ptime >= tout) break;
215:     VecGetArray(ts->vec_sol,&tmp);
216:     N_VSetData(tmp,cvode->y);
217:     flag = CVode(cvode->mem,tout,cvode->y,&t,ONE_STEP);
218:     cvode->nonlinear_solves += cvode->iopt[NNI];
219:     VecRestoreArray(ts->vec_sol,PETSC_NULL);
220:     if (flag != SUCCESS) SETERRQ(PETSC_ERR_LIB,"PVODE failed");

222:     if (t > tout && cvode->exact_final_time) {
223:       /* interpolate to final requested time */
224:       VecGetArray(ts->vec_sol,&tmp);
225:       N_VSetData(tmp,cvode->y);
226:       flag = CVodeDky(cvode->mem,tout,0,cvode->y);
227:       VecRestoreArray(ts->vec_sol,PETSC_NULL);
228:       if (flag != SUCCESS) SETERRQ(PETSC_ERR_LIB,"PVODE interpolation to final time failed");
229:       t = tout;
230:     }

232:     ts->time_step = t - ts->ptime;
233:     ts->ptime     = t;

235:     /*
236:        copy the solution from cvode->y to cvode->update and sol 
237:     */
238:     VecPlaceArray(cvode->w1,N_VGetData(cvode->y));
239:     VecCopy(cvode->w1,cvode->update);
240:     VecCopy(cvode->update,sol);
241: 
242:     ts->steps++;
243:     TSMonitor(ts,ts->steps,t,sol);
244:     ts->nonlinear_its = cvode->iopt[NNI];
245:     ts->linear_its    = cvode->iopt[SPGMR_NLI];
246:   }

248:   *steps           += ts->steps;
249:   *time             = t;

251:   return(0);
252: }

254: /*

256:     Contributed by: Liyang Xu
257: */
260: PetscErrorCode TSDestroy_PVode(TS ts)
261: {
262:   TS_PVode *cvode = (TS_PVode*)ts->data;

266:   if (cvode->pmat)   {MatDestroy(cvode->pmat);}
267:   if (cvode->pc)     {PCDestroy(cvode->pc);}
268:   if (cvode->update) {VecDestroy(cvode->update);}
269:   if (cvode->func)   {VecDestroy(cvode->func);}
270:   if (cvode->rhs)    {VecDestroy(cvode->rhs);}
271:   if (cvode->w1)     {VecDestroy(cvode->w1);}
272:   if (cvode->w2)     {VecDestroy(cvode->w2);}
273:   MPI_Comm_free(&(cvode->comm_pvode));
274:   PetscFree(cvode);
275:   return(0);
276: }

278: /*

280:     Contributed by: Liyang Xu
281: */
284: PetscErrorCode TSSetUp_PVode_Nonlinear(TS ts)
285: {
286:   TS_PVode    *cvode = (TS_PVode*)ts->data;
288:   int M,locsize;
289:   M_Env       machEnv;
290:   realtype    *tmp;

293:   PCSetFromOptions(cvode->pc);
294:   /* get the vector size */
295:   VecGetSize(ts->vec_sol,&M);
296:   VecGetLocalSize(ts->vec_sol,&locsize);

298:   /* allocate the memory for machEnv */
299:   /* machEnv = PVInitMPI(cvode->>comm_pvode,locsize,M);  */
300:   machEnv = M_EnvInit_Parallel(cvode->comm_pvode, locsize, M, 0, 0);


303:   /* allocate the memory for N_Vec y */
304:   cvode->y         = N_VNew(M,machEnv);
305:   VecGetArray(ts->vec_sol,&tmp);
306:   N_VSetData(tmp,cvode->y);
307:   VecRestoreArray(ts->vec_sol,PETSC_NULL);

309:   /* initializing vector update and func */
310:   VecDuplicate(ts->vec_sol,&cvode->update);
311:   VecDuplicate(ts->vec_sol,&cvode->func);
312:   PetscLogObjectParent(ts,cvode->update);
313:   PetscLogObjectParent(ts,cvode->func);

315:   /* 
316:       Create work vectors for the TSPSolve_PVode() routine. Note these are
317:     allocated with zero space arrays because the actual array space is provided 
318:     by PVode and set using VecPlaceArray().
319:   */
320:   VecCreateMPIWithArray(ts->comm,locsize,PETSC_DECIDE,0,&cvode->w1);
321:   VecCreateMPIWithArray(ts->comm,locsize,PETSC_DECIDE,0,&cvode->w2);
322:   PetscLogObjectParent(ts,cvode->w1);
323:   PetscLogObjectParent(ts,cvode->w2);

325:   /* allocate memory for PVode */
326:   VecGetArray(ts->vec_sol,&tmp);
327:   N_VSetData(tmp,cvode->y);
328:   cvode->mem = CVodeMalloc(M,TSFunction_PVode,ts->ptime,cvode->y,cvode->cvode_type,
329:                            NEWTON,SS,&cvode->reltol,&cvode->abstol,ts,NULL,TRUE,cvode->iopt,
330:                            cvode->ropt,machEnv);
331:   VecRestoreArray(ts->vec_sol,PETSC_NULL);
332:   return(0);
333: }

335: /*

337:     Contributed by: Liyang Xu
338: */
341: PetscErrorCode TSSetFromOptions_PVode_Nonlinear(TS ts)
342: {
343:   TS_PVode   *cvode = (TS_PVode*)ts->data;
345:   int indx;
346:   const char *btype[] = {"bdf","adams"},*otype[] = {"modified","unmodified"};
347:   PetscTruth flag;

350:   PetscOptionsHead("PVODE ODE solver options");
351:     PetscOptionsEList("-ts_pvode_type","Scheme","TSPVodeSetType",btype,2,"bdf",&indx,&flag);
352:     if (flag) {
353:       TSPVodeSetType(ts,(TSPVodeType)indx);
354:     }
355:     PetscOptionsEList("-ts_pvode_gramschmidt_type","Type of orthogonalization","TSPVodeSetGramSchmidtType",otype,2,"unmodified",&indx,&flag);
356:     if (flag) {
357:       TSPVodeSetGramSchmidtType(ts,(TSPVodeGramSchmidtType)indx);
358:     }
359:     PetscOptionsReal("-ts_pvode_atol","Absolute tolerance for convergence","TSPVodeSetTolerance",cvode->abstol,&cvode->abstol,PETSC_NULL);
360:     PetscOptionsReal("-ts_pvode_rtol","Relative tolerance for convergence","TSPVodeSetTolerance",cvode->reltol,&cvode->reltol,PETSC_NULL);
361:     PetscOptionsReal("-ts_pvode_linear_tolerance","Convergence tolerance for linear solve","TSPVodeSetLinearTolerance",cvode->linear_tol,&cvode->linear_tol,&flag);
362:     PetscOptionsInt("-ts_pvode_gmres_restart","Number of GMRES orthogonalization directions","TSPVodeSetGMRESRestart",cvode->restart,&cvode->restart,&flag);
363:     PetscOptionsName("-ts_pvode_not_exact_final_time","Allow PVODE to stop near the final time, not exactly on it","TSPVodeSetExactFinalTime",&cvode->exact_final_time);
364:   PetscOptionsTail();

366:   return(0);
367: }

369: /*

371:     Contributed by: Liyang Xu
372: */
375: PetscErrorCode TSPrintHelp_PVode(TS ts,char *p)
376: {

380:   (*PetscHelpPrintf)(ts->comm," Options for TSPVODE integrater:\n");
381:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_type <bdf,adams>: integration approach\n",p);
382:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_atol aabs: absolute tolerance of ODE solution\n",p);
383:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_rtol rel: relative tolerance of ODE solution\n",p);
384:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_gramschmidt_type <unmodified,modified>\n");
385:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_gmres_restart <restart_size> (also max. GMRES its)\n");
386:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_linear_tolerance <tol>\n");
387:   (*PetscHelpPrintf)(ts->comm," -ts_pvode_not_exact_final_time\n");

389:   return(0);
390: }

392: /*

394:     Contributed by: Liyang Xu
395: */
398: PetscErrorCode TSView_PVode(TS ts,PetscViewer viewer)
399: {
400:   TS_PVode   *cvode = (TS_PVode*)ts->data;
402:   char       *type;
403:   PetscTruth iascii,isstring;

406:   if (cvode->cvode_type == PVODE_ADAMS) {type = "Adams";}
407:   else                                  {type = "BDF: backward differentiation formula";}

409:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
410:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
411:   if (iascii) {
412:     PetscViewerASCIIPrintf(viewer,"PVode integrater does not use SNES!\n");
413:     PetscViewerASCIIPrintf(viewer,"PVode integrater type %s\n",type);
414:     PetscViewerASCIIPrintf(viewer,"PVode abs tol %g rel tol %g\n",cvode->abstol,cvode->reltol);
415:     PetscViewerASCIIPrintf(viewer,"PVode linear solver tolerance factor %g\n",cvode->linear_tol);
416:     PetscViewerASCIIPrintf(viewer,"PVode GMRES max iterations (same as restart in PVODE) %D\n",cvode->restart);
417:     if (cvode->gtype == PVODE_MODIFIED_GS) {
418:       PetscViewerASCIIPrintf(viewer,"PVode using modified Gram-Schmidt for orthogonalization in GMRES\n");
419:     } else {
420:       PetscViewerASCIIPrintf(viewer,"PVode using unmodified (classical) Gram-Schmidt for orthogonalization in GMRES\n");
421:     }
422:   } else if (isstring) {
423:     PetscViewerStringSPrintf(viewer,"Pvode type %s",type);
424:   } else {
425:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by TS PVode",((PetscObject)viewer)->type_name);
426:   }
427:   PetscViewerASCIIPushTab(viewer);
428:   PCView(cvode->pc,viewer);
429:   PetscViewerASCIIPopTab(viewer);

431:   return(0);
432: }


435: /* --------------------------------------------------------------------------*/
439: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetType_PVode(TS ts,TSPVodeType type)
440: {
441:   TS_PVode *cvode = (TS_PVode*)ts->data;
442: 
444:   cvode->cvode_type = type;
445:   return(0);
446: }

452: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetGMRESRestart_PVode(TS ts,int restart)
453: {
454:   TS_PVode *cvode = (TS_PVode*)ts->data;
455: 
457:   cvode->restart = restart;
458:   return(0);
459: }

465: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetLinearTolerance_PVode(TS ts,double tol)
466: {
467:   TS_PVode *cvode = (TS_PVode*)ts->data;
468: 
470:   cvode->linear_tol = tol;
471:   return(0);
472: }

478: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetGramSchmidtType_PVode(TS ts,TSPVodeGramSchmidtType type)
479: {
480:   TS_PVode *cvode = (TS_PVode*)ts->data;
481: 
483:   cvode->gtype = type;

485:   return(0);
486: }

492: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetTolerance_PVode(TS ts,double aabs,double rel)
493: {
494:   TS_PVode *cvode = (TS_PVode*)ts->data;
495: 
497:   if (aabs != PETSC_DECIDE) cvode->abstol = aabs;
498:   if (rel != PETSC_DECIDE)  cvode->reltol = rel;
499:   return(0);
500: }

506: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeGetPC_PVode(TS ts,PC *pc)
507: {
508:   TS_PVode *cvode = (TS_PVode*)ts->data;

511:   *pc = cvode->pc;

513:   return(0);
514: }

520: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeGetIterations_PVode(TS ts,int *nonlin,int *lin)
521: {
522:   TS_PVode *cvode = (TS_PVode*)ts->data;
523: 
525:   if (nonlin) *nonlin = cvode->nonlinear_solves;
526:   if (lin)    *lin    = cvode->linear_solves;
527:   return(0);
528: }
530: 
534: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetExactFinalTime_PVode(TS ts,PetscTruth s)
535: {
536:   TS_PVode *cvode = (TS_PVode*)ts->data;
537: 
539:   cvode->exact_final_time = s;
540:   return(0);
541: }
543: /* -------------------------------------------------------------------------------------------*/

547: /*@C
548:    TSPVodeGetIterations - Gets the number of nonlinear and linear iterations used so far by PVode.

550:    Not Collective

552:    Input parameters:
553: .    ts     - the time-step context

555:    Output Parameters:
556: +   nonlin - number of nonlinear iterations
557: -   lin    - number of linear iterations

559:    Level: advanced

561:    Notes:
562:     These return the number since the creation of the TS object

564: .keywords: non-linear iterations, linear iterations

566: .seealso: TSPVodeSetType(), TSPVodeSetGMRESRestart(),
567:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
568:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
569:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
570:           TSPVodeSetExactFinalTime()

572: @*/
573: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeGetIterations(TS ts,int *nonlin,int *lin)
574: {
575:   PetscErrorCode ierr,(*f)(TS,int*,int*);
576: 
578:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeGetIterations_C",(void (**)(void))&f);
579:   if (f) {
580:     (*f)(ts,nonlin,lin);
581:   }
582:   return(0);
583: }

587: /*@
588:    TSPVodeSetType - Sets the method that PVode will use for integration.

590:    Collective on TS

592:    Input parameters:
593: +    ts     - the time-step context
594: -    type   - one of  PVODE_ADAMS or PVODE_BDF

596:     Contributed by: Liyang Xu

598:    Level: intermediate

600: .keywords: Adams, backward differentiation formula

602: .seealso: TSPVodeGetIterations(),  TSPVodeSetGMRESRestart(),
603:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
604:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
605:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
606:           TSPVodeSetExactFinalTime()
607: @*/
608: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetType(TS ts,TSPVodeType type)
609: {
610:   PetscErrorCode ierr,(*f)(TS,TSPVodeType);
611: 
613:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetType_C",(void (**)(void))&f);
614:   if (f) {
615:     (*f)(ts,type);
616:   }
617:   return(0);
618: }

622: /*@
623:    TSPVodeSetGMRESRestart - Sets the dimension of the Krylov space used by 
624:        GMRES in the linear solver in PVODE. PVODE DOES NOT use restarted GMRES so
625:        this is ALSO the maximum number of GMRES steps that will be used.

627:    Collective on TS

629:    Input parameters:
630: +    ts      - the time-step context
631: -    restart - number of direction vectors (the restart size).

633:    Level: advanced

635: .keywords: GMRES, restart

637: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), 
638:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
639:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
640:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
641:           TSPVodeSetExactFinalTime()

643: @*/
644: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetGMRESRestart(TS ts,int restart)
645: {
646:   PetscErrorCode ierr,(*f)(TS,int);

649:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetGMRESRestart_C",(void (**)(void))&f);
650:   if (f) {
651:     (*f)(ts,restart);
652:   }

654:   return(0);
655: }

659: /*@
660:    TSPVodeSetLinearTolerance - Sets the tolerance used to solve the linear
661:        system by PVODE.

663:    Collective on TS

665:    Input parameters:
666: +    ts     - the time-step context
667: -    tol    - the factor by which the tolerance on the nonlinear solver is
668:              multiplied to get the tolerance on the linear solver, .05 by default.

670:    Level: advanced

672: .keywords: GMRES, linear convergence tolerance, PVODE

674: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
675:           TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
676:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
677:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
678:           TSPVodeSetExactFinalTime()

680: @*/
681: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetLinearTolerance(TS ts,double tol)
682: {
683:   PetscErrorCode ierr,(*f)(TS,double);
684: 
686:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetLinearTolerance_C",(void (**)(void))&f);
687:   if (f) {
688:     (*f)(ts,tol);
689:   }
690:   return(0);
691: }

695: /*@
696:    TSPVodeSetGramSchmidtType - Sets type of orthogonalization used
697:         in GMRES method by PVODE linear solver.

699:    Collective on TS

701:    Input parameters:
702: +    ts  - the time-step context
703: -    type - either PVODE_MODIFIED_GS or PVODE_CLASSICAL_GS

705:    Level: advanced

707: .keywords: PVode, orthogonalization

709: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
710:           TSPVodeSetLinearTolerance(),  TSPVodeSetTolerance(),
711:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
712:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
713:           TSPVodeSetExactFinalTime()

715: @*/
716: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetGramSchmidtType(TS ts,TSPVodeGramSchmidtType type)
717: {
718:   PetscErrorCode ierr,(*f)(TS,TSPVodeGramSchmidtType);
719: 
721:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetGramSchmidtType_C",(void (**)(void))&f);
722:   if (f) {
723:     (*f)(ts,type);
724:   }
725:   return(0);
726: }

730: /*@
731:    TSPVodeSetTolerance - Sets the absolute and relative tolerance used by 
732:                          PVode for error control.

734:    Collective on TS

736:    Input parameters:
737: +    ts  - the time-step context
738: .    aabs - the absolute tolerance  
739: -    rel - the relative tolerance

741:     Contributed by: Liyang Xu

743:      See the Cvode/Pvode users manual for exact details on these parameters. Essentially
744:     these regulate the size of the error for a SINGLE timestep.

746:    Level: intermediate

748: .keywords: PVode, tolerance

750: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
751:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), 
752:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
753:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC(),
754:           TSPVodeSetExactFinalTime()

756: @*/
757: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetTolerance(TS ts,double aabs,double rel)
758: {
759:   PetscErrorCode ierr,(*f)(TS,double,double);
760: 
762:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetTolerance_C",(void (**)(void))&f);
763:   if (f) {
764:     (*f)(ts,aabs,rel);
765:   }
766:   return(0);
767: }

771: /*@
772:    TSPVodeGetPC - Extract the PC context from a time-step context for PVode.

774:    Input Parameter:
775: .    ts - the time-step context

777:    Output Parameter:
778: .    pc - the preconditioner context

780:    Level: advanced

782:     Contributed by: Liyang Xu

784: .seealso: TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
785:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
786:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
787:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance()
788: @*/
789: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeGetPC(TS ts,PC *pc)
790: {
791:   PetscErrorCode ierr,(*f)(TS,PC *);

794:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeGetPC_C",(void (**)(void))&f);
795:   if (f) {
796:     (*f)(ts,pc);
797:   } else {
798:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"TS must be of PVode type to extract the PC");
799:   }

801:   return(0);
802: }

806: /*@
807:    TSPVodeSetExactFinalTime - Determines if PVode interpolates solution to the 
808:       exact final time requested by the user or just returns it at the final time
809:       it computed. (Defaults to true).

811:    Input Parameter:
812: +   ts - the time-step context
813: -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE

815:    Level: beginner

817: .seealso:TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
818:           TSPVodeSetLinearTolerance(), TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(),
819:           TSPVodeGetIterations(), TSPVodeSetType(), TSPVodeSetGMRESRestart(),
820:           TSPVodeSetLinearTolerance(), TSPVodeSetTolerance(), TSPVodeGetPC() 
821: @*/
822: PetscErrorCode PETSCTS_DLLEXPORT TSPVodeSetExactFinalTime(TS ts,PetscTruth ft)
823: {
824:   PetscErrorCode ierr,(*f)(TS,PetscTruth);

827:   PetscObjectQueryFunction((PetscObject)ts,"TSPVodeSetExactFinalTime_C",(void (**)(void))&f);
828:   if (f) {
829:     (*f)(ts,ft);
830:   }

832:   return(0);
833: }

835: /* -------------------------------------------------------------------------------------------*/
836: /*MC
837:       TS_PVode - ODE solver using the LLNL CVODE/PVODE package (now called SUNDIALS)

839:    Options Database:
840: +    -ts_pvode_type <bdf,adams>
841: .    -ts_pvode_gramschmidt_type <modified, classical> - type of orthogonalization inside GMRES
842: .    -ts_pvode_atol <tol> - Absolute tolerance for convergence
843: .    -ts_pvode_rtol <tol> - Relative tolerance for convergence
844: .    -ts_pvode_linear_tolerance <tol> 
845: .    -ts_pvode_gmres_restart <restart> - Number of GMRES orthogonalization directions
846: -    -ts_pvode_not_exact_final_time -Allow PVODE to stop near the final time, not exactly on it

848:     Notes: This uses its own nonlinear solver and Krylov method so PETSc SNES and KSP options do not apply
849:            only PETSc PC options

851:     Contributed by: Liyang Xu

853:     Level: beginner

855: .seealso:  TSCreate(), TS, TSSetType(), TSPVodeSetType(), TSPVodeSetGMRESRestart(), TSPVodeSetLinearTolerance(),
856:            TSPVodeSetGramSchmidtType(), TSPVodeSetTolerance(), TSPVodeGetPC(), TSPVodeGetIterations(), TSPVodeSetExactFinalTime()

858: M*/
862: PetscErrorCode PETSCTS_DLLEXPORT TSCreate_PVode(TS ts)
863: {
864:   TS_PVode *cvode;

868:   ts->ops->destroy         = TSDestroy_PVode;
869:   ts->ops->view            = TSView_PVode;

871:   if (ts->problem_type != TS_NONLINEAR) {
872:     SETERRQ(PETSC_ERR_SUP,"Only support for nonlinear problems");
873:   }
874:   ts->ops->setup           = TSSetUp_PVode_Nonlinear;
875:   ts->ops->step            = TSStep_PVode_Nonlinear;
876:   ts->ops->setfromoptions  = TSSetFromOptions_PVode_Nonlinear;

878:   PetscNew(TS_PVode,&cvode);
879:   PCCreate(ts->comm,&cvode->pc);
880:   PetscLogObjectParent(ts,cvode->pc);
881:   ts->data          = (void*)cvode;
882:   cvode->cvode_type = BDF;
883:   cvode->gtype      = PVODE_UNMODIFIED_GS;
884:   cvode->restart    = 5;
885:   cvode->linear_tol = .05;

887:   cvode->exact_final_time = PETSC_TRUE;

889:   MPI_Comm_dup(ts->comm,&(cvode->comm_pvode));
890:   /* set tolerance for PVode */
891:   cvode->abstol = 1e-6;
892:   cvode->reltol = 1e-6;

894:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetType_C","TSPVodeSetType_PVode",
895:                     TSPVodeSetType_PVode);
896:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetGMRESRestart_C",
897:                     "TSPVodeSetGMRESRestart_PVode",
898:                     TSPVodeSetGMRESRestart_PVode);
899:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetLinearTolerance_C",
900:                     "TSPVodeSetLinearTolerance_PVode",
901:                      TSPVodeSetLinearTolerance_PVode);
902:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetGramSchmidtType_C",
903:                     "TSPVodeSetGramSchmidtType_PVode",
904:                      TSPVodeSetGramSchmidtType_PVode);
905:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetTolerance_C",
906:                     "TSPVodeSetTolerance_PVode",
907:                      TSPVodeSetTolerance_PVode);
908:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeGetPC_C",
909:                     "TSPVodeGetPC_PVode",
910:                      TSPVodeGetPC_PVode);
911:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeGetIterations_C",
912:                     "TSPVodeGetIterations_PVode",
913:                      TSPVodeGetIterations_PVode);
914:   PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPVodeSetExactFinalTime_C",
915:                     "TSPVodeSetExactFinalTime_PVode",
916:                      TSPVodeSetExactFinalTime_PVode);
917:   return(0);
918: }