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