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