void FCV_SPILSSETPREC(int *flag, int *ier) { if (*flag == 0) { *ier = CVSpilsSetPreconditioner(CV_cvodemem, NULL, NULL); } else { *ier = CVSpilsSetPreconditioner(CV_cvodemem, FCVPSet, FCVPSol); } }
void FCV_SPILSSETPREC(int *flag, int *ier) { CVodeMem cv_mem; if (*flag == 0) { *ier = CVSpilsSetPreconditioner(CV_cvodemem, NULL, NULL, NULL); } else { cv_mem = (CVodeMem) CV_cvodemem; *ier = CVSpilsSetPreconditioner(CV_cvodemem, FCVPSet, FCVPSol, cv_mem->cv_f_data); } }
int CVSpilsSetPreconditionerB(void *cvadj_mem, CVSpilsPrecSetupFnB psetB, CVSpilsPrecSolveFnB psolveB, void *P_dataB) { CVadjMem ca_mem; CVSpilsMemB cvspilsB_mem; CVodeMem cvB_mem; int flag; if (cvadj_mem == NULL) { CVProcessError(NULL, CVSPILS_ADJMEM_NULL, "CVSPILS", "CVSpilsSetPreconditionerB", MSGS_CAMEM_NULL); return(CVSPILS_ADJMEM_NULL); } ca_mem = (CVadjMem) cvadj_mem; cvB_mem = ca_mem->cvb_mem; if (lmemB == NULL) { CVProcessError(cvB_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditonerB", MSGS_LMEMB_NULL); return(CVSPILS_LMEMB_NULL); } cvspilsB_mem = (CVSpilsMemB) lmemB; pset_B = psetB; psolve_B = psolveB; P_data_B = P_dataB; flag = CVSpilsSetPreconditioner(cvB_mem, CVAspilsPrecSetup, CVAspilsPrecSolve, cvadj_mem); return(flag); }
int CVSpilsSetPreconditionerB(void *cvode_mem, int which, CVSpilsPrecSetupFnB psetB, CVSpilsPrecSolveFnB psolveB) { CVodeMem cv_mem; CVadjMem ca_mem; CVodeBMem cvB_mem; CVSpilsMemB cvspilsB_mem; void *cvodeB_mem; int flag; /* Check if cvode_mem exists */ if (cvode_mem == NULL) { cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_CVMEM_NULL); return(CVSPILS_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Was ASA initialized? */ if (cv_mem->cv_adjMallocDone == FALSE) { cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_NO_ADJ); return(CVSPILS_NO_ADJ); } ca_mem = cv_mem->cv_adj_mem; /* Check which */ if ( which >= ca_mem->ca_nbckpbs ) { cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_BAD_WHICH); return(CVSPILS_ILL_INPUT); } /* Find the CVodeBMem entry in the linked list corresponding to which */ cvB_mem = ca_mem->cvB_mem; while (cvB_mem != NULL) { if ( which == cvB_mem->cv_index ) break; cvB_mem = cvB_mem->cv_next; } cvodeB_mem = (void *) (cvB_mem->cv_mem); if (cvB_mem->cv_lmem == NULL) { cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditonerB", MSGS_LMEMB_NULL); return(CVSPILS_LMEMB_NULL); } cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); pset_B = psetB; psolve_B = psolveB; flag = CVSpilsSetPreconditioner(cvodeB_mem, cvSpilsPrecSetupBWrapper, cvSpilsPrecSolveBWrapper); return(flag); }
int CVBPSpgmr(void *cvode_mem, int pretype, int maxl, void *p_data) { CVodeMem cv_mem; int flag; flag = CVSpgmr(cvode_mem, pretype, maxl); if(flag != CVSPILS_SUCCESS) return(flag); cv_mem = (CVodeMem) cvode_mem; if ( p_data == NULL ) { CVProcessError(cv_mem, CVBANDPRE_PDATA_NULL, "CVBANDPRE", "CVBPSpgmr", MSGBP_PDATA_NULL); return(CVBANDPRE_PDATA_NULL); } flag = CVSpilsSetPreconditioner(cvode_mem, CVBandPrecSetup, CVBandPrecSolve, p_data); if(flag != CVSPILS_SUCCESS) return(flag); return(CVSPILS_SUCCESS); }
PetscErrorCode TSSetUp_Sundials(TS ts) { TS_Sundials *cvode = (TS_Sundials*)ts->data; PetscErrorCode ierr; PetscInt glosize,locsize,i,flag; PetscScalar *y_data,*parray; void *mem; PC pc; PCType pctype; PetscBool pcnone; PetscFunctionBegin; /* get the vector size */ ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr); ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr); /* allocate the memory for N_Vec y */ cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize); if (!cvode->y) SETERRQ(PETSC_COMM_SELF,1,"cvode->y is not allocated"); /* initialize N_Vec y: copy ts->vec_sol to cvode->y */ ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr); y_data = (PetscScalar*) N_VGetArrayPointer(cvode->y); for (i = 0; i < locsize; i++) y_data[i] = parray[i]; ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->ydot);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->update);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->ydot);CHKERRQ(ierr); /* Create work vectors for the TSPSolve_Sundials() routine. Note these are allocated with zero space arrays because the actual array space is provided by Sundials and set using VecPlaceArray(). */ ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr); ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w1);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w2);CHKERRQ(ierr); /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */ mem = CVodeCreate(cvode->cvode_type, CV_NEWTON); if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails"); cvode->mem = mem; /* Set the pointer to user-defined data */ flag = CVodeSetUserData(mem, ts); if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails"); /* Sundials may choose to use a smaller initial step, but will never use a larger step. */ flag = CVodeSetInitStep(mem,(realtype)ts->time_step); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetInitStep() failed"); if (cvode->mindt > 0) { flag = CVodeSetMinStep(mem,(realtype)cvode->mindt); if (flag) { if (flag == CV_MEM_NULL) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL"); 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"); else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed"); } } if (cvode->maxdt > 0) { flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMaxStep() failed"); } /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector cvode->y */ flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag); /* specifies scalar relative and absolute tolerances */ flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag); /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */ flag = CVodeSetMaxNumSteps(mem,ts->max_steps); /* call CVSpgmr to use GMRES as the linear solver. */ /* setup the ode integrator with the given preconditioner */ ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr); ierr = PCGetType(pc,&pctype);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCNONE,&pcnone);CHKERRQ(ierr); if (pcnone) { flag = CVSpgmr(mem,PREC_NONE,0); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); } else { flag = CVSpgmr(mem,PREC_LEFT,cvode->maxl); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); /* Set preconditioner and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag); } flag = CVSpilsSetGSType(mem, MODIFIED_GS); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmrSetGSType() fails, flag %d",flag); PetscFunctionReturn(0); }
int main() { realtype abstol=ATOL, reltol=RTOL, t, tout; N_Vector c; WebData wdata; void *cvode_mem; booleantype firstrun; int jpre, gstype, flag; int ns, mxns, iout; c = NULL; wdata = NULL; cvode_mem = NULL; /* Initializations */ c = N_VNew_Serial(NEQ); if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1); wdata = AllocUserData(); if(check_flag((void *)wdata, "AllocUserData", 2)) return(1); InitUserData(wdata); ns = wdata->ns; mxns = wdata->mxns; /* Print problem description */ PrintIntro(); /* Loop over jpre and gstype (four cases) */ for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) { for (gstype = MODIFIED_GS; gstype <= CLASSICAL_GS; gstype++) { /* Initialize c and print heading */ CInit(c, wdata); PrintHeader(jpre, gstype); /* Call CVodeInit or CVodeReInit, then CVSpgmr to set up problem */ firstrun = (jpre == PREC_LEFT) && (gstype == MODIFIED_GS); if (firstrun) { cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); wdata->cvode_mem = cvode_mem; flag = CVodeSetUserData(cvode_mem, wdata); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeInit(cvode_mem, f, T0, c); if(check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); flag = CVSpgmr(cvode_mem, jpre, MAXL); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpilsSetGSType(cvode_mem, gstype); if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1); flag = CVSpilsSetEpsLin(cvode_mem, DELT); if(check_flag(&flag, "CVSpilsSetEpsLin", 1)) return(1); flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); } else { flag = CVodeReInit(cvode_mem, T0, c); if(check_flag(&flag, "CVodeReInit", 1)) return(1); flag = CVSpilsSetPrecType(cvode_mem, jpre); check_flag(&flag, "CVSpilsSetPrecType", 1); flag = CVSpilsSetGSType(cvode_mem, gstype); if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1); } /* Print initial values */ if (firstrun) PrintAllSpecies(c, ns, mxns, T0); /* Loop over output points, call CVode, print sample solution values. */ tout = T1; for (iout = 1; iout <= NOUT; iout++) { flag = CVode(cvode_mem, tout, c, &t, CV_NORMAL); PrintOutput(cvode_mem, t); if (firstrun && (iout % 3 == 0)) PrintAllSpecies(c, ns, mxns, t); if(check_flag(&flag, "CVode", 1)) break; if (tout > RCONST(0.9)) tout += DTOUT; else tout *= TOUT_MULT; } /* Print final statistics, and loop for next case */ PrintFinalStats(cvode_mem); } } /* Free all memory */ CVodeFree(&cvode_mem); N_VDestroy_Serial(c); FreeUserData(wdata); return(0); }
int CVBBDPrecInit(void *cvode_mem, int Nlocal, int mudq, int mldq, int mukeep, int mlkeep, realtype dqrely, CVLocalFn gloc, CVCommFn cfn) { CVodeMem cv_mem; CVSpilsMem cvspils_mem; CVBBDPrecData pdata; int muk, mlk, storage_mu; int flag; if (cvode_mem == NULL) { CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_NULL); return(CVSPILS_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Test if one of the SPILS linear solvers has been attached */ if (cv_mem->cv_lmem == NULL) { CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_LMEM_NULL); return(CVSPILS_LMEM_NULL); } cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; /* Test if the NVECTOR package is compatible with the BLOCK BAND preconditioner */ if(vec_tmpl->ops->nvgetarraypointer == NULL) { CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_BAD_NVECTOR); return(CVSPILS_ILL_INPUT); } /* Allocate data memory */ pdata = NULL; pdata = (CVBBDPrecData) malloc(sizeof *pdata); if (pdata == NULL) { CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Set pointers to gloc and cfn; load half-bandwidths */ pdata->cvode_mem = cvode_mem; pdata->gloc = gloc; pdata->cfn = cfn; pdata->mudq = MIN(Nlocal-1, MAX(0,mudq)); pdata->mldq = MIN(Nlocal-1, MAX(0,mldq)); muk = MIN(Nlocal-1, MAX(0,mukeep)); mlk = MIN(Nlocal-1, MAX(0,mlkeep)); pdata->mukeep = muk; pdata->mlkeep = mlk; /* Allocate memory for saved Jacobian */ pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk); if (pdata->savedJ == NULL) { free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Allocate memory for preconditioner matrix */ storage_mu = MIN(Nlocal-1, muk + mlk); pdata->savedP = NULL; pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu); if (pdata->savedP == NULL) { DestroyMat(pdata->savedJ); free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Allocate memory for pivots */ pdata->pivots = NULL; pdata->pivots = NewIntArray(Nlocal); if (pdata->savedJ == NULL) { DestroyMat(pdata->savedP); DestroyMat(pdata->savedJ); free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Set pdata->dqrely based on input dqrely (0 implies default). */ pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround); /* Store Nlocal to be used in CVBBDPrecSetup */ pdata->n_local = Nlocal; /* Set work space sizes and initialize nge */ pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2); pdata->ipwsize = Nlocal; pdata->nge = 0; /* Overwrite the P_data field in the SPILS memory */ cvspils_mem->s_P_data = pdata; /* Attach the pfree function */ cvspils_mem->s_pfree = CVBBDPrecFree; /* Attach preconditioner solve and setup functions */ flag = CVSpilsSetPreconditioner(cvode_mem, CVBBDPrecSetup, CVBBDPrecSolve); return(flag); }
int main(int argc, char *argv[]) { void *cvode_mem; UserData data; realtype abstol, reltol, t, tout; N_Vector y; int iout, flag; realtype *pbar; int is, *plist; N_Vector *uS; booleantype sensi, err_con; int sensi_meth; pbar = NULL; plist = NULL; uS = NULL; y = NULL; data = NULL; cvode_mem = NULL; /* Process arguments */ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con); /* Problem parameters */ data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); /* Initial states */ y = N_VNew_Serial(NEQ); if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1); SetInitialProfiles(y, data->dx, data->dz); /* Tolerances */ abstol=ATOL; reltol=RTOL; /* Create CVODES object */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeSetFdata(cvode_mem, data); if(check_flag(&flag, "CVodeSetFdata", 1)) return(1); flag = CVodeSetMaxNumSteps(cvode_mem, 2000); if(check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return(1); /* Allocate CVODES memory */ flag = CVodeMalloc(cvode_mem, f, T0, y, CV_SS, reltol, &abstol); if(check_flag(&flag, "CVodeMalloc", 1)) return(1); /* Attach CVSPGMR linear solver */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve, data); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); printf("\n2-species diurnal advection-diffusion problem\n"); /* Forward sensitivity analysis */ if(sensi) { plist = (int *) malloc(NS * sizeof(int)); if(check_flag((void *)plist, "malloc", 2)) return(1); for(is=0; is<NS; is++) plist[is] = is; pbar = (realtype *) malloc(NS * sizeof(realtype)); if(check_flag((void *)pbar, "malloc", 2)) return(1); for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]]; uS = N_VCloneVectorArray_Serial(NS, y); if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1); for(is=0;is<NS;is++) N_VConst(ZERO,uS[is]); flag = CVodeSensMalloc(cvode_mem, NS, sensi_meth, uS); if(check_flag(&flag, "CVodeSensMalloc", 1)) return(1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1); flag = CVodeSetSensRho(cvode_mem, ZERO); if(check_flag(&flag, "CVodeSetSensRho", 1)) return(1); flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist); if(check_flag(&flag, "CVodeSetSensParams", 1)) return(1); printf("Sensitivity: YES "); if(sensi_meth == CV_SIMULTANEOUS) printf("( SIMULTANEOUS +"); else if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +"); else printf("( STAGGERED1 +"); if(err_con) printf(" FULL ERROR CONTROL )"); else printf(" PARTIAL ERROR CONTROL )"); } else { printf("Sensitivity: NO "); } /* In loop over output points, call CVode, print results, test for error */ printf("\n\n"); printf("========================================================================\n"); printf(" T Q H NST Bottom left Top right \n"); printf("========================================================================\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1)) break; PrintOutput(cvode_mem, t, y); if (sensi) { flag = CVodeGetSens(cvode_mem, t, uS); if(check_flag(&flag, "CVodeGetSens", 1)) break; PrintOutputS(uS); } printf("------------------------------------------------------------------------\n"); } /* Print final statistics */ PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy_Serial(y); if (sensi) { N_VDestroyVectorArray_Serial(uS, NS); free(pbar); free(plist); } FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
int main(int argc, char *argv[]) { realtype abstol, reltol, t, tout; N_Vector u; UserData data; PreconData predata; void *cvode_mem; int iout, flag, my_pe, npes; long int neq, local_N; MPI_Comm comm; u = NULL; data = NULL; predata = NULL; cvode_mem = NULL; /* Set problem size neq */ neq = NVARS*MX*MY; /* Get processor number and total number of pe's */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &my_pe); if (npes != NPEX*NPEY) { if (my_pe == 0) fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n", npes,NPEX*NPEY); MPI_Finalize(); return(1); } /* Set local length */ local_N = NVARS*MXSUB*MYSUB; /* Allocate and load user data block; allocate preconditioner block */ data = (UserData) malloc(sizeof *data); if (check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1); InitUserData(my_pe, comm, data); predata = AllocPreconData (data); /* Allocate u, and set initial values and tolerances */ u = N_VNew_Parallel(comm, local_N, neq); if (check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1); SetInitialProfiles(u, data); abstol = ATOL; reltol = RTOL; /* Call CVodeCreate to create the solver memory: CV_BDF specifies the Backward Differentiation Formula CV_NEWTON specifies a Newton iteration A pointer to the integrator memory is returned and stored in cvode_mem. */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1); /* Set the pointer to user-defined data */ flag = CVodeSetFdata(cvode_mem, data); if (check_flag(&flag, "CVodeSetFdata", 1, my_pe)) MPI_Abort(comm, 1); /* Call CVodeMalloc to initialize the integrator memory: cvode_mem is the pointer to the integrator memory returned by CVodeCreate f is the user's right hand side function in y'=f(t,y) T0 is the initial time u is the initial dependent variable vector CV_SS specifies scalar relative and absolute tolerances reltol is the relative tolerance &abstol is a pointer to the scalar absolute tolerance */ flag = CVodeMalloc(cvode_mem, f, T0, u, CV_SS, reltol, &abstol); if (check_flag(&flag, "CVodeMalloc", 1, my_pe)) MPI_Abort(comm, 1); /* Call CVSpgmr to specify the linear solver CVSPGMR with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if (check_flag(&flag, "CVSpgmr", 1, my_pe)) MPI_Abort(comm, 1); /* Set preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve, predata); if (check_flag(&flag, "CVSpilsSetPreconditioner", 1, my_pe)) MPI_Abort(comm, 1); if (my_pe == 0) printf("\n2-species diurnal advection-diffusion problem\n\n"); /* In loop over output points, call CVode, print results, test for error */ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if (check_flag(&flag, "CVode", 1, my_pe)) break; PrintOutput(cvode_mem, my_pe, comm, u, t); } /* Print final statistics */ if (my_pe == 0) PrintFinalStats(cvode_mem); /* Free memory */ N_VDestroy_Parallel(u); free(data); FreePreconData(predata); CVodeFree(&cvode_mem); MPI_Finalize(); return(0); }
int main() { realtype abstol, reltol, t, tout; N_Vector u; UserData data; void *cvode_mem; int iout, flag; u = NULL; data = NULL; cvode_mem = NULL; /* Allocate memory, and set problem data, initial values, tolerances */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); abstol=ATOL; reltol=RTOL; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Call CVSpgmr to specify the linear solver CVSPGMR * with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); /* set the JAcobian-times-vector function */ flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv); if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1); /* Set the preconditioner solve and setup functions */ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /* In loop over output points, call CVode, print results, test for error */ printf(" \n2-species diurnal advection-diffusion problem\n\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); PrintOutput(cvode_mem, u, t); if(check_flag(&flag, "CVode", 1)) break; } PrintFinalStats(cvode_mem); /* Free memory */ N_VDestroy_Serial(u); FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
int main(void) { realtype abstol, reltol, t, tout; N_Vector u; UserData data; void *cvode_mem; int linsolver, iout, flag; u = NULL; data = NULL; cvode_mem = NULL; /* Allocate memory, and set problem data, initial values, tolerances */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); abstol=ATOL; reltol=RTOL; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */ for (linsolver = 0; linsolver < 3; ++linsolver) { if (linsolver != 0) { /* Re-initialize user data */ InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); /* Re-initialize CVode for the solution of the same problem, but using a different linear solver module */ flag = CVodeReInit(cvode_mem, T0, u); if (check_flag(&flag, "CVodeReInit", 1)) return(1); } /* Attach a linear solver module */ switch(linsolver) { /* (a) SPGMR */ case(USE_SPGMR): /* Print header */ printf(" -------"); printf(" \n| SPGMR |\n"); printf(" -------\n"); /* Call CVSpgmr to specify the linear solver CVSPGMR with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); /* Set modified Gram-Schmidt orthogonalization, preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS); if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1); break; /* (b) SPBCG */ case(USE_SPBCG): /* Print header */ printf(" -------"); printf(" \n| SPBCG |\n"); printf(" -------\n"); /* Call CVSpbcg to specify the linear solver CVSPBCG with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpbcg(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpbcg", 1)) return(1); break; /* (c) SPTFQMR */ case(USE_SPTFQMR): /* Print header */ printf(" ---------"); printf(" \n| SPTFQMR |\n"); printf(" ---------\n"); /* Call CVSptfqmr to specify the linear solver CVSPTFQMR with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSptfqmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSptfqmr", 1)) return(1); break; } /* Set preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /* In loop over output points, call CVode, print results, test for error */ printf(" \n2-species diurnal advection-diffusion problem\n\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); PrintOutput(cvode_mem, u, t); if(check_flag(&flag, "CVode", 1)) break; } PrintFinalStats(cvode_mem, linsolver); } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */ /* Free memory */ N_VDestroy_Serial(u); FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
PetscErrorCode TSSetUp_Sundials_Nonlinear(TS ts) { TS_Sundials *cvode = (TS_Sundials*)ts->data; PetscErrorCode ierr; PetscInt glosize,locsize,i,flag; PetscScalar *y_data,*parray; void *mem; const PCType pctype; PetscTruth pcnone; Vec sol = ts->vec_sol; PetscFunctionBegin; ierr = PCSetFromOptions(cvode->pc);CHKERRQ(ierr); /* get the vector size */ ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr); ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr); /* allocate the memory for N_Vec y */ cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize); if (!cvode->y) SETERRQ(1,"cvode->y is not allocated"); /* initialize N_Vec y: copy ts->vec_sol to cvode->y */ ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr); y_data = (PetscScalar *) N_VGetArrayPointer(cvode->y); for (i = 0; i < locsize; i++) y_data[i] = parray[i]; /*ierr = PetscMemcpy(y_data,parray,locsize*sizeof(PETSC_SCALAR)); CHKERRQ(ierr);*/ ierr = VecRestoreArray(ts->vec_sol,PETSC_NULL);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->func);CHKERRQ(ierr); ierr = PetscLogObjectParent(ts,cvode->update);CHKERRQ(ierr); ierr = PetscLogObjectParent(ts,cvode->func);CHKERRQ(ierr); /* Create work vectors for the TSPSolve_Sundials() routine. Note these are allocated with zero space arrays because the actual array space is provided by Sundials and set using VecPlaceArray(). */ ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr); ierr = VecCreateMPIWithArray(((PetscObject)ts)->comm,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr); ierr = PetscLogObjectParent(ts,cvode->w1);CHKERRQ(ierr); ierr = PetscLogObjectParent(ts,cvode->w2);CHKERRQ(ierr); /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */ mem = CVodeCreate(cvode->cvode_type, CV_NEWTON); if (!mem) SETERRQ(PETSC_ERR_MEM,"CVodeCreate() fails"); cvode->mem = mem; /* Set the pointer to user-defined data */ flag = CVodeSetUserData(mem, ts); if (flag) SETERRQ(PETSC_ERR_LIB,"CVodeSetUserData() fails"); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector cvode->y */ flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y); if (flag){ SETERRQ1(PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag); } flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol); if (flag){ SETERRQ1(PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag); } /* initialize the number of steps */ ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr); /* call CVSpgmr to use GMRES as the linear solver. */ /* setup the ode integrator with the given preconditioner */ ierr = PCGetType(cvode->pc,&pctype);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)cvode->pc,PCNONE,&pcnone);CHKERRQ(ierr); if (pcnone){ flag = CVSpgmr(mem,PREC_NONE,0); if (flag) SETERRQ1(PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); } else { flag = CVSpgmr(mem,PREC_LEFT,0); if (flag) SETERRQ1(PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); /* Set preconditioner and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials); if (flag) SETERRQ1(PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag); } flag = CVSpilsSetGSType(mem, MODIFIED_GS); if (flag) SETERRQ1(PETSC_ERR_LIB,"CVSpgmrSetGSType() fails, flag %d",flag); PetscFunctionReturn(0); }
int CVBandPrecInit(void *cvode_mem, int N, int mu, int ml) { CVodeMem cv_mem; CVSpilsMem cvspils_mem; CVBandPrecData pdata; int mup, mlp, storagemu; int flag; if (cvode_mem == NULL) { CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_NULL); return(CVSPILS_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Test if one of the SPILS linear solvers has been attached */ if (cv_mem->cv_lmem == NULL) { CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_LMEM_NULL); return(CVSPILS_LMEM_NULL); } cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; /* Test if the NVECTOR package is compatible with the BAND preconditioner */ if(vec_tmpl->ops->nvgetarraypointer == NULL) { CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInit", MSGBP_BAD_NVECTOR); return(CVSPILS_ILL_INPUT); } pdata = NULL; pdata = (CVBandPrecData) malloc(sizeof *pdata); /* Allocate data memory */ if (pdata == NULL) { CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Load pointers and bandwidths into pdata block. */ pdata->cvode_mem = cvode_mem; pdata->N = N; pdata->mu = mup = MIN(N-1, MAX(0,mu)); pdata->ml = mlp = MIN(N-1, MAX(0,ml)); /* Initialize nfeBP counter */ pdata->nfeBP = 0; /* Allocate memory for saved banded Jacobian approximation. */ pdata->savedJ = NULL; pdata->savedJ = NewBandMat(N, mup, mlp, mup); if (pdata->savedJ == NULL) { free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Allocate memory for banded preconditioner. */ storagemu = MIN(N-1, mup+mlp); pdata->savedP = NULL; pdata->savedP = NewBandMat(N, mup, mlp, storagemu); if (pdata->savedP == NULL) { DestroyMat(pdata->savedJ); free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Allocate memory for pivot array. */ pdata->pivots = NULL; pdata->pivots = NewIntArray(N); if (pdata->savedJ == NULL) { DestroyMat(pdata->savedP); DestroyMat(pdata->savedJ); free(pdata); pdata = NULL; CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); return(CVSPILS_MEM_FAIL); } /* Overwrite the P_data field in the SPILS memory */ cvspils_mem->s_P_data = pdata; /* Attach the pfree function */ cvspils_mem->s_pfree = CVBandPrecFree; /* Attach preconditioner solve and setup functions */ flag = CVSpilsSetPreconditioner(cvode_mem, CVBandPrecSetup, CVBandPrecSolve); return(flag); }
int Solver::init(rhsfunc f, int argc, char **argv, bool restarting, int nout, real tstep) { #ifdef CHECK int msg_point = msg_stack.push("Initialising CVODE solver"); #endif /// Call the generic initialisation first if(GenericSolver::init(f, argc, argv, restarting, nout, tstep)) return 1; // Save nout and tstep for use in run NOUT = nout; TIMESTEP = tstep; output.write("Initialising SUNDIALS' CVODE solver\n"); // Set the rhs solver function func = f; // Calculate number of variables (in generic_solver) int local_N = getLocalN(); // Get total problem size int neq; if(MPI_Allreduce(&local_N, &neq, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD)) { output.write("\tERROR: MPI_Allreduce failed!\n"); return 1; } output.write("\t3d fields = %d, 2d fields = %d neq=%d, local_N=%d\n", n3Dvars(), n2Dvars(), neq, local_N); // Allocate memory if((uvec = N_VNew_Parallel(MPI_COMM_WORLD, local_N, neq)) == NULL) bout_error("ERROR: SUNDIALS memory allocation failed\n"); // Put the variables into uvec if(save_vars(NV_DATA_P(uvec))) bout_error("\tERROR: Initial variable value not set\n"); /// Get options real abstol, reltol; int maxl; int mudq, mldq; int mukeep, mlkeep; bool use_precon, use_jacobian; real max_timestep; bool adams_moulton, func_iter; // Time-integration method options.setSection("solver"); options.get("mudq", mudq, n3Dvars()*(MXSUB+2)); options.get("mldq", mldq, n3Dvars()*(MXSUB+2)); options.get("mukeep", mukeep, n3Dvars()+n2Dvars()); options.get("mlkeep", mlkeep, n3Dvars()+n2Dvars()); options.get("ATOL", abstol, 1.0e-12); options.get("RTOL", reltol, 1.0e-5); options.get("maxl", maxl, 5); options.get("use_precon", use_precon, false); options.get("use_jacobian", use_jacobian, false); options.get("max_timestep", max_timestep, -1.); int mxsteps; // Maximum number of steps to take between outputs options.get("pvode_mxstep", mxsteps, 500); options.get("adams_moulton", adams_moulton, false); int lmm = CV_BDF; if(adams_moulton) { // By default use functional iteration for Adams-Moulton lmm = CV_ADAMS; output.write("\tUsing Adams-Moulton implicit multistep method\n"); options.get("func_iter", func_iter, true); }else { output.write("\tUsing BDF method\n"); // Use Newton iteration for BDF options.get("func_iter", func_iter, false); } int iter = CV_NEWTON; if(func_iter) iter = CV_FUNCTIONAL; // Call CVodeCreate if((cvode_mem = CVodeCreate(lmm, iter)) == NULL) bout_error("ERROR: CVodeCreate failed\n"); if( CVodeSetUserData(cvode_mem, this) < 0 ) // For callbacks, need pointer to solver object bout_error("ERROR: CVodeSetUserData failed\n"); if( CVodeInit(cvode_mem, cvode_rhs, simtime, uvec) < 0 ) bout_error("ERROR: CVodeInit failed\n"); if( CVodeSStolerances(cvode_mem, reltol, abstol) < 0 ) bout_error("ERROR: CVodeSStolerances failed\n"); CVodeSetMaxNumSteps(cvode_mem, mxsteps); if(max_timestep > 0.0) { // Setting a maximum timestep CVodeSetMaxStep(cvode_mem, max_timestep); } /// Newton method can include Preconditioners and Jacobian function if(!func_iter) { output.write("\tUsing Newton iteration\n"); /// Set Preconditioner if(use_precon) { if( CVSpgmr(cvode_mem, PREC_LEFT, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); if(prefunc == NULL) { output.write("\tUsing BBD preconditioner\n"); if( CVBBDPrecInit(cvode_mem, local_N, mudq, mldq, mukeep, mlkeep, ZERO, cvode_bbd_rhs, NULL) ) bout_error("ERROR: CVBBDPrecInit failed\n"); }else { output.write("\tUsing user-supplied preconditioner\n"); if( CVSpilsSetPreconditioner(cvode_mem, NULL, cvode_pre) ) bout_error("ERROR: CVSpilsSetPreconditioner failed\n"); } }else { // Not using preconditioning output.write("\tNo preconditioning\n"); if( CVSpgmr(cvode_mem, PREC_NONE, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); } /// Set Jacobian-vector multiplication function if((use_jacobian) && (jacfunc != NULL)) { output.write("\tUsing user-supplied Jacobian function\n"); if( CVSpilsSetJacTimesVecFn(cvode_mem, cvode_jac) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpilsSetJacTimesVecFn failed\n"); }else output.write("\tUsing difference quotient approximation for Jacobian\n"); }else { output.write("\tUsing Functional iteration\n"); } #ifdef CHECK msg_stack.pop(msg_point); #endif return(0); }
int main(int argc, char *argv[]) { realtype abstol=ATOL, reltol=RTOL, t; N_Vector c; WebData wdata; void *cvode_mem; int flag, ncheck; int indexB; realtype reltolB=RTOL, abstolB=ATOL; N_Vector cB; c = NULL; cB = NULL; wdata = NULL; cvode_mem = NULL; /* Allocate and initialize user data */ wdata = AllocUserData(); if(check_flag((void *)wdata, "AllocUserData", 2)) return(1); InitUserData(wdata); /* Set-up forward problem */ /* Initializations */ c = N_VNew_Serial(NEQ+1); if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1); CInit(c, wdata); /* Call CVodeCreate/CVodeInit for forward run */ printf("\nCreate and allocate CVODES memory for forward run\n"); cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); wdata->cvode_mem = cvode_mem; /* Used in Precond */ flag = CVodeSetUserData(cvode_mem, wdata); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeInit(cvode_mem, f, T0, c); if(check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if(check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Call CVSpgmr for forward run */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /* Set-up adjoint calculations */ printf("\nAllocate global memory\n"); flag = CVodeAdjInit(cvode_mem, NSTEPS, CV_HERMITE); if(check_flag(&flag, "CVadjInit", 1)) return(1); /* Perform forward run */ printf("\nForward integration\n"); flag = CVodeF(cvode_mem, TOUT, c, &t, CV_NORMAL, &ncheck); if(check_flag(&flag, "CVodeF", 1)) return(1); printf("\nncheck = %d\n", ncheck); #if defined(SUNDIALS_EXTENDED_PRECISION) printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %Lf \n\n", ISPEC, NV_DATA_S(c)[NEQ]); #else printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %f \n\n", ISPEC, NV_DATA_S(c)[NEQ]); #endif /* Set-up backward problem */ /* Allocate cB */ cB = N_VNew_Serial(NEQ); if(check_flag((void *)cB, "N_VNew_Serial", 0)) return(1); /* Initialize cB = 0 */ N_VConst(ZERO, cB); /* Create and allocate CVODES memory for backward run */ printf("\nCreate and allocate CVODES memory for backward run\n"); flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB); if(check_flag(&flag, "CVodeCreateB", 1)) return(1); flag = CVodeSetUserDataB(cvode_mem, indexB, wdata); if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1); flag = CVodeSetMaxNumStepsB(cvode_mem, indexB, 1000); if(check_flag(&flag, "CVodeSetMaxNumStepsB", 1)) return(1); flag = CVodeInitB(cvode_mem, indexB, fB, TOUT, cB); if(check_flag(&flag, "CVodeInitB", 1)) return(1); flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1); wdata->indexB = indexB; /* Call CVSpgmr */ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmrB", 1)) return(1); flag = CVSpilsSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB); if(check_flag(&flag, "CVSpilsSetPreconditionerB", 1)) return(1); /* Perform backward integration */ printf("\nBackward integration\n"); flag = CVodeB(cvode_mem, T0, CV_NORMAL); if(check_flag(&flag, "CVodeB", 1)) return(1); flag = CVodeGetB(cvode_mem, indexB, &t, cB); if(check_flag(&flag, "CVodeGetB", 1)) return(1); PrintOutput(cB, NS, MXNS, wdata); /* Free all memory */ CVodeFree(&cvode_mem); N_VDestroy_Serial(c); N_VDestroy_Serial(cB); FreeUserData(wdata); return(0); }