void CVodeInt::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; if (m_y) { N_VFree(nv(m_y)); // free solution vector if already allocated } m_y = reinterpret_cast<void*>(N_VNew(m_neq, 0)); // allocate solution vector // check abs tolerance array size if (m_itol == 1 && m_nabs < m_neq) throw CVodeErr("not enough absolute tolerance values specified."); func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y))); // set options m_iopt[MXSTEP] = m_maxsteps; m_iopt[MAXORD] = m_maxord; m_ropt[HMAX] = m_hmax; if (m_cvode_mem) CVodeFree(m_cvode_mem); // pass a pointer to func in m_data m_data = (void*)&func; if (m_itol) { m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, nv(m_abstol), m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } else { m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, &m_abstols, m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } if (!m_cvode_mem) throw CVodeErr("CVodeMalloc failed."); if (m_type == DENSE + NOJAC) { CVDense(m_cvode_mem, NULL, NULL); } else if (m_type == DENSE + JAC) { CVDense(m_cvode_mem, cvode_jac, NULL); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0, NULL, NULL, NULL); } else { throw CVodeErr("unsupported option"); } }
int CVSpgmrB(void *cvadj_mem, int pretypeB, int maxlB) { CVadjMem ca_mem; void *cvode_mem; int flag; if (cvadj_mem == NULL) return(CV_ADJMEM_NULL); ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *) ca_mem->cvb_mem; flag = CVSpgmr(cvode_mem, pretypeB, maxlB); return(flag); }
void CVodeInt::reinitialize(double t0, FuncEval& func) { m_t0 = t0; func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y))); // set options m_iopt[MXSTEP] = m_maxsteps; m_iopt[MAXORD] = m_maxord; m_ropt[HMAX] = m_hmax; //if (m_cvode_mem) CVodeFree(m_cvode_mem); // pass a pointer to func in m_data m_data = (void*)&func; int result; if (m_itol) { result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, nv(m_abstol), m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } else { result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, &m_abstols, m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } if (result != 0) throw CVodeErr("CVReInit failed."); if (m_type == DENSE + NOJAC) { CVDense(m_cvode_mem, NULL, NULL); } else if (m_type == DENSE + JAC) { CVDense(m_cvode_mem, cvode_jac, NULL); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0, NULL, NULL, NULL); } else { throw CVodeErr("unsupported option"); } }
int CVBBDSpgmr(void *cvode_mem, int pretype, int maxl, void *bbd_data) { int flag; if ( bbd_data == NULL ) { fprintf(stderr, MSGBBDP_NO_PDATA); return(CV_PDATA_NULL); } flag = CVSpgmr(cvode_mem, pretype, maxl); if(flag != CVSPGMR_SUCCESS) return(flag); flag = CVSpgmrSetPreconditioner(cvode_mem, CVBBDPrecSetup, CVBBDPrecSolve, bbd_data); if(flag != CVSPGMR_SUCCESS) return(flag); return(CVSPGMR_SUCCESS); }
void CVodesIntegrator::applyOptions() { if (m_type == DENSE + NOJAC) { sd_size_t N = static_cast<sd_size_t>(m_neq); #if SUNDIALS_USE_LAPACK CVLapackDense(m_cvode_mem, N); #else CVDense(m_cvode_mem, N); #endif } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else if (m_type == BAND + NOJAC) { sd_size_t N = static_cast<sd_size_t>(m_neq); long int nu = m_mupper; long int nl = m_mlower; #if SUNDIALS_USE_LAPACK CVLapackBand(m_cvode_mem, N, nu, nl); #else CVBand(m_cvode_mem, N, nu, nl); #endif } else { throw CanteraError("CVodesIntegrator::applyOptions", "unsupported option"); } if (m_maxord > 0) { CVodeSetMaxOrd(m_cvode_mem, m_maxord); } if (m_maxsteps > 0) { CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); } if (m_hmax > 0) { CVodeSetMaxStep(m_cvode_mem, m_hmax); } if (m_hmin > 0) { CVodeSetMinStep(m_cvode_mem, m_hmin); } if (m_maxErrTestFails > 0) { CVodeSetMaxErrTestFails(m_cvode_mem, m_maxErrTestFails); } }
void FCV_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier) { /* pretype the preconditioner type maxl the maximum Krylov dimension gstype the Gram-Schmidt process type delt the linear convergence tolerance factor */ *ier = CVSpgmr(CV_cvodemem, *pretype, *maxl); if (*ier != CVSPGMR_SUCCESS) return; *ier = CVSpgmrSetGSType(CV_cvodemem, *gstype); if (*ier != CVSPGMR_SUCCESS) return; *ier = CVSpgmrSetDelt(CV_cvodemem, *delt); if (*ier != CVSPGMR_SUCCESS) return; CV_ls = 4; }
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); }
int CVBPSpgmr(void *cvode_mem, int pretype, int maxl, void *p_data) { int flag; if ( p_data == NULL ) { fprintf(stderr, MSGBP_NO_PDATA); return(CV_PDATA_NULL); } flag = CVSpgmr(cvode_mem, pretype, maxl); if(flag != CVSPGMR_SUCCESS) return(flag); flag = CVSpgmrSetPrecData(cvode_mem, p_data); if(flag != CVSPGMR_SUCCESS) return(flag); flag = CVSpgmrSetPrecSetupFn(cvode_mem, CVBandPrecSetup); if(flag != CVSPGMR_SUCCESS) return(flag); flag = CVSpgmrSetPrecSolveFn(cvode_mem, CVBandPrecSolve); if(flag != CVSPGMR_SUCCESS) return(flag); return(CVSPGMR_SUCCESS); }
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); }
void CvodeSolver::initialize(const double &pVoiStart, const int &pRatesStatesCount, double *pConstants, double *pRates, double *pStates, double *pAlgebraic, ComputeRatesFunction pComputeRates) { if (!mSolver) { // Retrieve some of the CVODE properties double maximumStep = MaximumStepDefaultValue; int maximumNumberOfSteps = MaximumNumberOfStepsDefaultValue; QString integrationMethod = IntegrationMethodDefaultValue; QString iterationType = IterationTypeDefaultValue; QString linearSolver = LinearSolverDefaultValue; QString preconditioner = PreconditionerDefaultValue; int upperHalfBandwidth = UpperHalfBandwidthDefaultValue; int lowerHalfBandwidth = LowerHalfBandwidthDefaultValue; double relativeTolerance = RelativeToleranceDefaultValue; double absoluteTolerance = AbsoluteToleranceDefaultValue; if (mProperties.contains(MaximumStepId)) { maximumStep = mProperties.value(MaximumStepId).toDouble(); } else { emit error(QObject::tr("the 'maximum step' property value could not be retrieved")); return; } if (mProperties.contains(MaximumNumberOfStepsId)) { maximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsId).toInt(); } else { emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved")); return; } if (mProperties.contains(IntegrationMethodId)) { integrationMethod = mProperties.value(IntegrationMethodId).toString(); } else { emit error(QObject::tr("the 'integration method' property value could not be retrieved")); return; } if (mProperties.contains(IterationTypeId)) { iterationType = mProperties.value(IterationTypeId).toString(); if (!iterationType.compare(NewtonIteration)) { // We are dealing with a Newton iteration, so retrieve and check // its linear solver if (mProperties.contains(LinearSolverId)) { linearSolver = mProperties.value(LinearSolverId).toString(); bool needUpperAndLowerHalfBandwidths = false; if ( !linearSolver.compare(DenseLinearSolver) || !linearSolver.compare(DiagonalLinearSolver)) { // We are dealing with a dense/diagonal linear solver, // so nothing more to do } else if (!linearSolver.compare(BandedLinearSolver)) { // We are dealing with a banded linear solver, so we // need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear // solver, so retrieve and check its preconditioner if (mProperties.contains(PreconditionerId)) { preconditioner = mProperties.value(PreconditionerId).toString(); } else { emit error(QObject::tr("the 'preconditioner' property value could not be retrieved")); return; } if (!preconditioner.compare(BandedPreconditioner)) { // We are dealing with a banded preconditioner, so // we need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } } if (needUpperAndLowerHalfBandwidths) { if (mProperties.contains(UpperHalfBandwidthId)) { upperHalfBandwidth = mProperties.value(UpperHalfBandwidthId).toInt(); if ( (upperHalfBandwidth < 0) || (upperHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'upper half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'upper half-bandwidth' property value could not be retrieved")); return; } if (mProperties.contains(LowerHalfBandwidthId)) { lowerHalfBandwidth = mProperties.value(LowerHalfBandwidthId).toInt(); if ( (lowerHalfBandwidth < 0) || (lowerHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'lower half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'lower half-bandwidth' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'linear solver' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'iteration type' property value could not be retrieved")); return; } if (mProperties.contains(RelativeToleranceId)) { relativeTolerance = mProperties.value(RelativeToleranceId).toDouble(); if (relativeTolerance < 0) { emit error(QObject::tr("the 'relative tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved")); return; } if (mProperties.contains(AbsoluteToleranceId)) { absoluteTolerance = mProperties.value(AbsoluteToleranceId).toDouble(); if (absoluteTolerance < 0) { emit error(QObject::tr("the 'absolute tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved")); return; } if (mProperties.contains(InterpolateSolutionId)) { mInterpolateSolution = mProperties.value(InterpolateSolutionId).toBool(); } else { emit error(QObject::tr("the 'interpolate solution' property value could not be retrieved")); return; } // Initialise the ODE solver itself OpenCOR::Solver::OdeSolver::initialize(pVoiStart, pRatesStatesCount, pConstants, pRates, pStates, pAlgebraic, pComputeRates); // Create the states vector mStatesVector = N_VMake_Serial(pRatesStatesCount, pStates); // Create the CVODE solver bool newtonIteration = !iterationType.compare(NewtonIteration); mSolver = CVodeCreate(!integrationMethod.compare(BdfMethod)?CV_BDF:CV_ADAMS, newtonIteration?CV_NEWTON:CV_FUNCTIONAL); // Use our own error handler CVodeSetErrHandlerFn(mSolver, errorHandler, this); // Initialise the CVODE solver CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector); // Set some user data mUserData = new CvodeSolverUserData(pConstants, pAlgebraic, pComputeRates); CVodeSetUserData(mSolver, mUserData); // Set the maximum step CVodeSetMaxStep(mSolver, maximumStep); // Set the maximum number of steps CVodeSetMaxNumSteps(mSolver, maximumNumberOfSteps); // Set the linear solver, if needed if (newtonIteration) { if (!linearSolver.compare(DenseLinearSolver)) { CVDense(mSolver, pRatesStatesCount); } else if (!linearSolver.compare(BandedLinearSolver)) { CVBand(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else if (!linearSolver.compare(DiagonalLinearSolver)) { CVDiag(mSolver); } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear solver if (!preconditioner.compare(BandedPreconditioner)) { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_LEFT, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_LEFT, 0); else CVSptfqmr(mSolver, PREC_LEFT, 0); CVBandPrecInit(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_NONE, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_NONE, 0); else CVSptfqmr(mSolver, PREC_NONE, 0); } } } // Set the relative and absolute tolerances CVodeSStolerances(mSolver, relativeTolerance, absoluteTolerance); } else { // Reinitialise the CVODE object CVodeReInit(mSolver, pVoiStart, mStatesVector); } }
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); }
/* Main Function */ int main(int argc, char *argv[]) { char *filename = "shalehills"; /* Input file name prefix */ char *StateFile; /* Output file name string */ char *FluxFile; char *ETISFile; char *QFile; Model_Data mData; /* Model Data */ Control_Data cData; /* Solver Control Data */ N_Vector CV_Y; /* State Variables Vector */ M_Env machEnv; /* Machine Environments */ realtype ropt[OPT_SIZE]; /* Optional real type and integer type */ long int iopt[OPT_SIZE]; /* vecter for Message Passing to solver */ void *cvode_mem; /* Model Data Pointer */ int flag; /* flag to test return value */ FILE *res_state_file; /* Output file for States */ FILE *res_flux_file; /* Output file for Flux */ FILE *res_etis_file; /* Output file for ET and IS */ FILE *res_q_file; int N; /* Problem size */ int i; /* loop index */ realtype t; /* simulation time */ realtype NextPtr, StepSize; /* stress period & step size */ clock_t start, end_r, end_s; /* system clock at points */ realtype cputime_r, cputime_s; /* for duration in realtype */ /* allocate memory for model data structure */ mData = (Model_Data)malloc(sizeof *mData); start = clock(); /* get user specified file name in command line */ if(argc >= 2) { filename = (char *)malloc(strlen(argv[1])*sizeof(char)); strcpy(filename, argv[1]); } printf("\nBelt up! PIHM 1.0 is starting ... \n"); /* read in 7 input files with "filename" as prefix */ read_alloc(filename, mData, &cData); /* problem size */ N = 3*mData->NumEle + mData->NumRiv; /* initial machine environment variable */ machEnv = M_EnvInit_Serial(N); /* initial state variable depending on machine*/ CV_Y = N_VNew(N, machEnv); /* initialize mode data structure */ initialize(filename, mData, &cData, CV_Y); if(cData.Debug == 1) {PrintModelData(mData);} end_r = clock(); cputime_r = (end_r - start)/(realtype)CLOCKS_PER_SEC; printf("\nSolving ODE system ... \n"); /* initial control parameter for CVODE solver. Otherwise the default value by C could cause problems. */ for(i=0; i<OPT_SIZE; i++) { ropt[i] = 0.0; iopt[i] = 0; } /* set user specified control parameter */ ropt[H0] = cData.InitStep; ropt[HMAX] = cData.MaxStep; /* allocate memory for solver */ cvode_mem = CVodeMalloc(N, f, cData.StartTime, CV_Y, BDF, NEWTON, SS, &cData.reltol, &cData.abstol, mData, NULL, TRUE, iopt, ropt, machEnv); if(cvode_mem == NULL) {printf("CVodeMalloc failed. \n"); return(1);} if(cData.Solver == 1) { /* using dense direct solver */ flag = CVDense(cvode_mem, NULL, NULL); if(flag != SUCCESS) {printf("CVDense failed. \n"); return(1);} } else if(cData.Solver == 2) { /* using iterative solver */ flag = CVSpgmr(cvode_mem, NONE, cData.GSType, cData.MaxK, cData.delt, NULL, NULL, mData, NULL, NULL); if (flag != SUCCESS) {printf("CVSpgmr failed."); return(1);} } /*allocate and copy to get output file name */ StateFile = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(StateFile, filename); FluxFile = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(FluxFile, filename); ETISFile = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ETISFile, filename); QFile = (char *)malloc((strlen(filename)+2)*sizeof(char)); strcpy(QFile, filename); /* open output file */ if (cData.res_out == 1) {res_state_file = fopen(strcat(StateFile, ".res"), "w");} if (cData.flux_out == 1) {res_flux_file = fopen(strcat(FluxFile, ".flux"), "w");} if (cData.etis_out == 1) {res_etis_file = fopen(strcat(ETISFile, ".etis"), "w");} if (cData.q_out == 1) {res_q_file = fopen(strcat(QFile, ".q"), "w");} /* print header of output file */ if (cData.res_out == 1) {FPrintYheader(res_state_file, mData);} if (cData.etis_out == 1) {FPrintETISheader(res_etis_file, mData);} if (cData.q_out == 1) {FPrintETISheader(res_q_file, mData);} printf("\n"); /* set start time */ t = cData.StartTime; /* start solver in loops */ for(i=0; i<cData.NumSteps; i++) { /* prompt information in non-verbose mode */ if (cData.Verbose != 1) { printf(" Running: %-4.1f%% ... ", (100*(i+1)/((realtype) cData.NumSteps))); fflush(stdout); } /* inner loops to next output points with ET step size control */ while(t < cData.Tout[i+1]) { if (t + cData.ETStep >= cData.Tout[i+1]) { NextPtr = cData.Tout[i+1]; } else { NextPtr = t + cData.ETStep; } StepSize = NextPtr - t; /* calculate Interception Storage */ calIS(t, StepSize, mData); /* solving ODE system */ flag = CVode(cvode_mem, NextPtr, CV_Y, &t, NORMAL); /* calculate ET and adjust states variables*/ calET(t, StepSize, CV_Y, mData); } if(cData.Verbose == 1) {PrintVerbose(i, t, iopt, ropt);} /* uncomment it if user need it verbose mode */ /* if(cData.Verbose == 1) {PrintY(mData, CV_Y, t);} */ /* print out results to files at every output time */ if (cData.res_out == 1) {FPrintY(mData, CV_Y, t, res_state_file);} if (cData.flux_out == 1) {FPrintFlux(mData, t, res_flux_file);} if (cData.etis_out == 1) {FPrintETIS(mData, t, res_etis_file);} if (cData.q_out == 1) {FPrintQ(mData, t, res_q_file);} if (cData.Verbose != 1) {printf("\r");} if(flag != SUCCESS) {printf("CVode failed, flag = %d. \n", flag); return(flag);} /* clear buffer */ fflush(stdout); } /* free memory */ /* N_VFree(CV_Y); CVodeFree(cvode_mem); M_EnvFree_Serial(machEnv); */ /* capture time */ end_s = clock(); cputime_s = (end_s - end_r)/(realtype)CLOCKS_PER_SEC; /* print out simulation statistics */ PrintFarewell(cData, iopt, ropt, cputime_r, cputime_s); if (cData.res_out == 1) {FPrintFarewell(cData, res_state_file, iopt, ropt, cputime_r, cputime_s);} /* close output files */ if (cData.res_out == 1) {fclose(res_state_file);} if (cData.flux_out == 1) {fclose(res_flux_file);} if (cData.etis_out == 1) {fclose(res_etis_file);} if (cData.q_out == 1) {fclose(res_q_file);} free(mData); return 0; }
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(int argc, char *argv[]) { ProblemData d; MPI_Comm comm; int npes, npes_needed; int myId; long int neq, l_neq; void *cvode_mem; N_Vector y, q; realtype abstol, reltol, abstolQ, reltolQ; long int mudq, mldq, mukeep, mlkeep; int indexB; N_Vector yB, qB; realtype abstolB, reltolB, abstolQB, reltolQB; long int mudqB, mldqB, mukeepB, mlkeepB; realtype tret, *qdata, G; int ncheckpnt, flag; booleantype output; /* Initialize MPI and set Ids */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_rank(comm, &myId); /* Check number of processes */ npes_needed = NPX * NPY; #ifdef USE3D npes_needed *= NPZ; #endif MPI_Comm_size(comm, &npes); if (npes_needed != npes) { if (myId == 0) fprintf(stderr,"I need %d processes but I only got %d\n", npes_needed, npes); MPI_Abort(comm, EXIT_FAILURE); } /* Test if matlab output is requested */ if (argc > 1) output = TRUE; else output = FALSE; /* Allocate and set problem data structure */ d = (ProblemData) malloc(sizeof *d); SetData(d, comm, npes, myId, &neq, &l_neq); if (myId == 0) PrintHeader(); /*-------------------------- Forward integration phase --------------------------*/ /* Allocate space for y and set it with the I.C. */ y = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, y); /* Allocate and initialize qB (local contribution to cost) */ q = N_VNew_Parallel(comm, 1, npes); N_VConst(ZERO, q); /* Create CVODES object, attach user data, and allocate space */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); flag = CVodeSetUserData(cvode_mem, d); flag = CVodeInit(cvode_mem, f, ti, y); abstol = ATOL; reltol = RTOL; flag = CVodeSStolerances(cvode_mem, reltol, abstol); /* attach linear solver */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); /* Attach preconditioner and linear solver modules */ mudq = mldq = d->l_m[0]+1; mukeep = mlkeep = 2; flag = CVBBDPrecInit(cvode_mem, l_neq, mudq, mldq, mukeep, mlkeep, ZERO, f_local, NULL); /* Initialize quadrature calculations */ abstolQ = ATOL_Q; reltolQ = RTOL_Q; flag = CVodeQuadInit(cvode_mem, fQ, q); flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ); flag = CVodeSetQuadErrCon(cvode_mem, TRUE); /* Allocate space for the adjoint calculation */ flag = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE); /* Integrate forward in time while storing check points */ if (myId == 0) printf("Begin forward integration... "); flag = CVodeF(cvode_mem, tf, y, &tret, CV_NORMAL, &ncheckpnt); if (myId == 0) printf("done. "); /* Extract quadratures */ flag = CVodeGetQuad(cvode_mem, &tret, q); qdata = NV_DATA_P(q); MPI_Allreduce(&qdata[0], &G, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm); #if defined(SUNDIALS_EXTENDED_PRECISION) if (myId == 0) printf(" G = %Le\n",G); #elif defined(SUNDIALS_DOUBLE_PRECISION) if (myId == 0) printf(" G = %e\n",G); #else if (myId == 0) printf(" G = %e\n",G); #endif /* Print statistics for forward run */ if (myId == 0) PrintFinalStats(cvode_mem); /*-------------------------- Backward integration phase --------------------------*/ /* Allocate and initialize yB */ yB = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, yB); /* Allocate and initialize qB (gradient) */ qB = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, qB); /* Create and allocate backward CVODE memory */ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB); flag = CVodeSetUserDataB(cvode_mem, indexB, d); flag = CVodeInitB(cvode_mem, indexB, fB, tf, yB); abstolB = ATOL_B; reltolB = RTOL_B; flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); /* Attach preconditioner and linear solver modules */ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0); mudqB = mldqB = d->l_m[0]+1; mukeepB = mlkeepB = 2; flag = CVBBDPrecInitB(cvode_mem, indexB, l_neq, mudqB, mldqB, mukeepB, mlkeepB, ZERO, fB_local, NULL); /* Initialize quadrature calculations */ abstolQB = ATOL_QB; reltolQB = RTOL_QB; flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB); flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolQB, abstolQB); flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE); /* Integrate backwards */ if (myId == 0) printf("Begin backward integration... "); flag = CVodeB(cvode_mem, ti, CV_NORMAL); if (myId == 0) printf("done.\n"); /* Extract solution */ flag = CVodeGetB(cvode_mem, indexB, &tret, yB); /* Extract quadratures */ flag = CVodeGetQuadB(cvode_mem, indexB, &tret, qB); /* Print statistics for backward run */ if (myId == 0) { PrintFinalStats(CVodeGetAdjCVodeBmem(cvode_mem, indexB)); } /* Process 0 collects the gradient components and prints them */ if (output) { OutputGradient(myId, qB, d); if (myId == 0) printf("Wrote matlab file 'grad.m'.\n"); } /* Free memory */ N_VDestroy_Parallel(y); N_VDestroy_Parallel(q); N_VDestroy_Parallel(qB); N_VDestroy_Parallel(yB); CVodeFree(&cvode_mem); MPI_Finalize(); return(0); }
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, 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() { M_Env machEnv; realtype abstol, reltol, t, tout, ropt[OPT_SIZE]; long int iopt[OPT_SIZE]; N_Vector y; UserData data; CVBandPreData bpdata; void *cvode_mem; int ml, mu, iout, flag, jpre; /* Initialize serial machine environment */ machEnv = M_EnvInit_Serial(NEQ); /* Allocate and initialize y, and set problem data and tolerances */ y = N_VNew(NEQ, machEnv); data = (UserData) malloc(sizeof *data); InitUserData(data); SetInitialProfiles(y, data->dx, data->dz); abstol = ATOL; reltol = RTOL; /* Call CVodeMalloc to initialize CVODE: NEQ is the problem size = number of equations f is the user's right hand side function in y'=f(t,y) T0 is the initial time y is the initial dependent variable vector BDF specifies the Backward Differentiation Formula NEWTON specifies a Newton iteration SS specifies scalar relative and absolute tolerances &reltol and &abstol are pointers to the scalar tolerances data is the pointer to the user-defined block of coefficients FALSE indicates there are no optional inputs in iopt and ropt iopt and ropt arrays communicate optional integer and real input/output A pointer to CVODE problem memory is returned and stored in cvode_mem. */ cvode_mem = CVodeMalloc(NEQ, f, T0, y, BDF, NEWTON, SS, &reltol, &abstol, data, NULL, FALSE, iopt, ropt, machEnv); if (cvode_mem == NULL) { printf("CVodeMalloc failed."); return(1); } /* Call CVBandPreAlloc to initialize band preconditioner */ ml = mu = 2; bpdata = CVBandPreAlloc (NEQ, f, data, mu, ml, cvode_mem); /* Call CVSpgmr to specify the CVODE linear solver CVSPGMR with left preconditioning, modified Gram-Schmidt orthogonalization, default values for the maximum Krylov dimension maxl and the tolerance parameter delt, preconditioner setup and solve routines CVBandPrecond and CVBandPSolve, the pointer to the user-defined block data, and NULL for the user jtimes routine and Jacobian data pointer. */ flag = CVSpgmr(cvode_mem, LEFT, MODIFIED_GS, 0, 0.0, CVBandPrecond, CVBandPSolve, bpdata, NULL, NULL); if (flag != SUCCESS) { printf("CVSpgmr failed."); return(1); } printf("2-species diurnal advection-diffusion problem, %d by %d mesh\n", MX, MZ); printf("SPGMR solver; band preconditioner; mu = %d, ml = %d\n\n", mu, ml); /* Loop over jpre (= LEFT, RIGHT), and solve the problem */ for (jpre = LEFT; jpre <= RIGHT; jpre++) { /* On second run, re-initialize y, CVODE, CVBANDPRE, and CVSPGMR */ if (jpre == RIGHT) { SetInitialProfiles(y, data->dx, data->dz); flag = CVReInit(cvode_mem, f, T0, y, BDF, NEWTON, SS, &reltol, &abstol, data, NULL, FALSE, iopt, ropt, machEnv); if (flag != SUCCESS) { printf("CVReInit failed."); return(1); } flag = CVReInitBandPre(bpdata, NEQ, f, data, mu, ml); flag = CVReInitSpgmr(cvode_mem, jpre, MODIFIED_GS, 0, 0.0, CVBandPrecond, CVBandPSolve, bpdata, NULL, NULL); if (flag != SUCCESS) { printf("CVReInitSpgmr failed."); return(1); } printf("\n\n-------------------------------------------------------"); printf("------------\n"); } printf("\n\nPreconditioner type is: jpre = %s\n\n", (jpre == LEFT) ? "LEFT" : "RIGHT"); /* 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, y, &t, NORMAL); PrintOutput(iopt, ropt, y, t); if (flag != SUCCESS) { printf("CVode failed, flag = %d.\n", flag); break; } } /* Print final statistics */ PrintFinalStats(iopt); } /* End of jpre loop */ /* Free memory */ N_VFree(y); free(data); CVBandPreFree(bpdata); CVodeFree(cvode_mem); M_EnvFree_Serial(machEnv); return(0); }
/* Main Function */ int main(int argc, char *argv[]) { char tmpLName[11],tmpFName[11]; /* rivFlux File names */ Model_Data mData; /* Model Data */ Control_Data cData; /* Solver Control Data */ N_Vector CV_Y; /* State Variables Vector */ void *cvode_mem; /* Model Data Pointer */ int flag; /* flag to test return value */ FILE *Ofile[22]; /* Output file */ char *ofn[22]; FILE *iproj; /* Project File */ int N; /* Problem size */ int i,j,k; /* loop index */ realtype t; /* simulation time */ realtype NextPtr, StepSize; /* stress period & step size */ clock_t start, end_r, end_s; /* system clock at points */ realtype cputime_r, cputime_s; /* for duration in realtype */ char *filename; /* Project Input Name */ if(argc!=2) { iproj=fopen("projectName.txt","r"); if(iproj==NULL) { printf("\t\nUsage ./pihm project_name"); printf("\t\n OR "); printf("\t\nUsage ./pihm, and have a file in the current directory named projectName.txt with the project name in it"); exit(0); } else { filename = (char *)malloc(15*sizeof(char)); fscanf(iproj,"%s",filename); } } else { /* get user specified file name in command line */ filename = (char *)malloc(strlen(argv[1])*sizeof(char)); strcpy(filename,argv[1]); } /* Open Output Files */ ofn[0] = (char *)malloc((strlen(filename)+3)*sizeof(char)); strcpy(ofn[0], filename); Ofile[0]=fopen(strcat(ofn[0], ".GW"),"w"); ofn[1] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[1], filename); Ofile[1]=fopen(strcat(ofn[1], ".surf"),"w"); ofn[2] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[2], filename); Ofile[2]=fopen(strcat(ofn[2], ".et0"),"w"); ofn[3] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[3], filename); Ofile[3]=fopen(strcat(ofn[3], ".et1"),"w"); ofn[4] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[4], filename); Ofile[4]=fopen(strcat(ofn[4], ".et2"),"w"); ofn[5] = (char *)malloc((strlen(filename)+3)*sizeof(char)); strcpy(ofn[5], filename); Ofile[5]=fopen(strcat(ofn[5], ".is"),"w"); ofn[6] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[6], filename); Ofile[6]=fopen(strcat(ofn[6], ".snow"),"w"); for(i=0;i<11;i++) { sprintf(tmpLName,".rivFlx%d",i); strcpy(tmpFName,filename); strcat(tmpFName,tmpLName); Ofile[7+i]=fopen(tmpFName,"w"); } ofn[18] = (char *)malloc((strlen(filename)+6)*sizeof(char)); strcpy(ofn[18], filename); Ofile[18]=fopen(strcat(ofn[18], ".stage"),"w"); ofn[19] = (char *)malloc((strlen(filename)+6)*sizeof(char)); strcpy(ofn[19], filename); Ofile[19]=fopen(strcat(ofn[19], ".unsat"),"w"); ofn[20] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[20], filename); Ofile[20]=fopen(strcat(ofn[20], ".Rech"),"w"); /* allocate memory for model data structure */ mData = (Model_Data)malloc(sizeof *mData); printf("\n ... PIHM 2.0 is starting ... \n"); /* read in 9 input files with "filename" as prefix */ read_alloc(filename, mData, &cData); /* if(mData->UnsatMode ==1) { } */ if(mData->UnsatMode ==2) { /* problem size */ N = 3*mData->NumEle + 2*mData->NumRiv; mData->DummyY=(realtype *)malloc((3*mData->NumEle+2*mData->NumRiv)*sizeof(realtype)); } /* initial state variable depending on machine*/ CV_Y = N_VNew_Serial(N); /* initialize mode data structure */ initialize(filename, mData, &cData, CV_Y); printf("\nSolving ODE system ... \n"); /* allocate memory for solver */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(cvode_mem == NULL) {printf("CVodeMalloc failed. \n"); return(1);} flag = CVodeSetFdata(cvode_mem, mData); flag = CVodeSetInitStep(cvode_mem,cData.InitStep); flag = CVodeSetStabLimDet(cvode_mem,TRUE); flag = CVodeSetMaxStep(cvode_mem,cData.MaxStep); flag = CVodeMalloc(cvode_mem, f, cData.StartTime, CV_Y, CV_SS, cData.reltol, &cData.abstol); flag = CVSpgmr(cvode_mem, PREC_NONE, 0); flag = CVSpgmrSetGSType(cvode_mem, MODIFIED_GS); /* set start time */ t = cData.StartTime; start = clock(); /* start solver in loops */ for(i=0; i<cData.NumSteps; i++) { /* if (cData.Verbose != 1) { printf(" Running: %-4.1f%% ... ", (100*(i+1)/((realtype) cData.NumSteps))); fflush(stdout); } */ /* inner loops to next output points with ET step size control */ while(t < cData.Tout[i+1]) { if (t + cData.ETStep >= cData.Tout[i+1]) { NextPtr = cData.Tout[i+1]; } else { NextPtr = t + cData.ETStep; } StepSize = NextPtr - t; /* calculate Interception Storage */ is_sm_et(t, StepSize, mData,CV_Y); printf("\n Tsteps = %f ",t); flag = CVode(cvode_mem, NextPtr, CV_Y, &t, CV_NORMAL); update(t,mData); } PrintData(Ofile,&cData,mData, CV_Y,t); } /* Free memory */ N_VDestroy_Serial(CV_Y); /* Free integrator memory */ CVodeFree(cvode_mem); free(mData); 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 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)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetFdata(cvode_mem, data); if(check_flag(&flag, "CVodeSetFdata", 1)) return(1); /* Call CVodeMalloc to initialize the integrator memory: f is the user's right hand side function in u'=f(t,u) 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)) 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 modified Gram-Schmidt orthogonalization, preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpgmrSetGSType(cvode_mem, MODIFIED_GS); if(check_flag(&flag, "CVSpgmrSetGSType", 1)) return(1); flag = CVSpgmrSetPreconditioner(cvode_mem, Precond, PSolve, data); if(check_flag(&flag, "CVSpgmrSetPreconditioner", 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(int argc, char *argv[]) { UserData data; void *cvode_mem; realtype abstol, reltol, t, tout; N_Vector u; int iout, my_pe, npes, flag, jpre; long int neq, local_N, mudq, mldq, mukeep, mlkeep; MPI_Comm comm; data = NULL; cvode_mem = NULL; u = 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 */ data = (UserData) malloc(sizeof *data); if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1); InitUserData(my_pe, local_N, comm, data); /* Allocate and initialize u, and set tolerances */ u = N_VNew_Parallel(comm, local_N, neq); if(check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1); SetInitialProfiles(u, data); 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, my_pe)) MPI_Abort(comm, 1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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, my_pe)) 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, my_pe)) return(1); /* Call CVSpgmr to specify the linear solver CVSPGMR with left preconditioning and the default maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVBBDSpgmr", 1, my_pe)) MPI_Abort(comm, 1); /* Initialize BBD preconditioner */ mudq = mldq = NVARS*MXSUB; mukeep = mlkeep = NVARS; flag = CVBBDPrecInit(cvode_mem, local_N, mudq, mldq, mukeep, mlkeep, ZERO, flocal, NULL); if(check_flag(&flag, "CVBBDPrecAlloc", 1, my_pe)) MPI_Abort(comm, 1); /* Print heading */ if (my_pe == 0) PrintIntro(npes, mudq, mldq, mukeep, mlkeep); /* Loop over jpre (= PREC_LEFT, PREC_RIGHT), and solve the problem */ for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) { /* On second run, re-initialize u, the integrator, CVBBDPRE, and CVSPGMR */ if (jpre == PREC_RIGHT) { SetInitialProfiles(u, data); flag = CVodeReInit(cvode_mem, T0, u); if(check_flag(&flag, "CVodeReInit", 1, my_pe)) MPI_Abort(comm, 1); flag = CVBBDPrecReInit(cvode_mem, mudq, mldq, ZERO); if(check_flag(&flag, "CVBBDPrecReInit", 1, my_pe)) MPI_Abort(comm, 1); flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT); check_flag(&flag, "CVSpilsSetPrecType", 1, my_pe); if (my_pe == 0) { printf("\n\n-------------------------------------------------------"); printf("------------\n"); } } if (my_pe == 0) { printf("\n\nPreconditioner type is: jpre = %s\n\n", (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT"); } /* 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); } /* End of jpre loop */ /* Free memory */ N_VDestroy_Parallel(u); free(data); CVodeFree(&cvode_mem); MPI_Finalize(); return(0); }
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); }
void CVodesIntegrator::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; if (m_y) { N_VDestroy_Serial(nv(m_y)); // free solution vector if already allocated } m_y = reinterpret_cast<void*>(N_VNew_Serial(m_neq)); // allocate solution vector for (int i=0; i<m_neq; i++) { NV_Ith_S(nv(m_y), i) = 0.0; } // check abs tolerance array size if (m_itol == CV_SV && m_nabs < m_neq) throw CVodesErr("not enough absolute tolerance values specified."); func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y))); if (m_cvode_mem) CVodeFree(&m_cvode_mem); /* * Specify the method and the iteration type: * Cantera Defaults: * CV_BDF - Use BDF methods * CV_NEWTON - use newton's method */ m_cvode_mem = CVodeCreate(m_method, m_iter); if (!m_cvode_mem) throw CVodesErr("CVodeCreate failed."); int flag = 0; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) if (m_itol == CV_SV) { // vector atol flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, nv(m_abstol)); } else { // scalar atol flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, &m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeMalloc input argument."); } else throw CVodesErr("CVodeMalloc failed."); } #elif defined(SUNDIALS_VERSION_24) flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y)); if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } if (m_itol == CV_SV) { flag = CVodeSVtolerances(m_cvode_mem, m_reltol, nv(m_abstol)); } else { flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } #else printf("unknown sundials verson\n"); exit(-1); #endif if (m_type == DENSE + NOJAC) { long int N = m_neq; CVDense(m_cvode_mem, N); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else if (m_type == BAND + NOJAC) { long int N = m_neq; long int nu = m_mupper; long int nl = m_mlower; CVBand(m_cvode_mem, N, nu, nl); } else { throw CVodesErr("unsupported option"); } // pass a pointer to func in m_data m_fdata = new FuncData(&func, func.nparams()); //m_data = (void*)&func; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) flag = CVodeSetFdata(m_cvode_mem, (void*)m_fdata); if (flag != CV_SUCCESS) { throw CVodesErr("CVodeSetFdata failed."); } #elif defined(SUNDIALS_VERSION_24) flag = CVodeSetUserData(m_cvode_mem, (void*)m_fdata); if (flag != CV_SUCCESS) { throw CVodesErr("CVodeSetUserData failed."); } #endif if (func.nparams() > 0) { sensInit(t0, func); flag = CVodeSetSensParams(m_cvode_mem, DATA_PTR(m_fdata->m_pars), NULL, NULL); } // set options if (m_maxord > 0) flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord); if (m_maxsteps > 0) flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); if (m_hmax > 0) flag = CVodeSetMaxStep(m_cvode_mem, m_hmax); }
/* * Functions to use CVODES * */ struct Integrator* CreateIntegrator(struct Simulation* sim, class ExecutableModel* em) { if (!(sim && em)) { ERROR("CreateIntegrator","Invalid arguments when creating integrator"); return((struct Integrator*)NULL); } int flag,mlmm,miter; struct Integrator* integrator = (struct Integrator*)malloc(sizeof(struct Integrator)); integrator->y = NULL; integrator->cvode_mem = NULL; integrator->simulation = simulationClone(sim); // FIXME: really need to handle this properly, but for now simply grabbing a handle. integrator->em = em; /* Check for errors in the simulation */ if (simulationGetATolLength(integrator->simulation) < 1) { ERROR("CreateIntegrator","Absolute tolerance(s) not set\n"); DestroyIntegrator(&integrator); return(NULL); } /* Would be good if we didn't require the specification of the tabulation step size, but for now it is required so we should check that it has a sensible value */ if (!simulationIsBvarTabStepSet(integrator->simulation)) { ERROR("CreateIntegrator","Tabulation step size must be set\n"); DestroyIntegrator(&integrator); return(NULL); } /* start and end also needs to be set */ if (!simulationIsBvarStartSet(integrator->simulation)) { ERROR("CreateIntegrator","Bound variable interval start must be set\n"); DestroyIntegrator(&integrator); return(NULL); } if (!simulationIsBvarEndSet(integrator->simulation)) { ERROR("CreateIntegrator","Bound variable interval end must be set\n"); DestroyIntegrator(&integrator); return(NULL); } /* Create serial vector of length NR for I.C. */ integrator->y = N_VNew_Serial(em->nRates); if (check_flag((void *)(integrator->y),"N_VNew_Serial",0)) { DestroyIntegrator(&integrator); return(NULL); } /* Initialize y */ realtype* yD = NV_DATA_S(integrator->y); int i; for (i=0;i<(em->nRates);i++) yD[i] = (realtype)(em->states[i]); /* adjust parameters accordingly */ switch (simulationGetMultistepMethod(integrator->simulation)) { case ADAMS: { mlmm = CV_ADAMS; break; } case BDF: { mlmm = CV_BDF; break; } default: { ERROR("CreateIntegrator","Invalid multistep method choice\n"); DestroyIntegrator(&integrator); return(NULL); } } switch (simulationGetIterationMethod(integrator->simulation)) { case FUNCTIONAL: { miter = CV_FUNCTIONAL; break; } case NEWTON: { miter = CV_NEWTON; break; } default: { ERROR("CreateIntegrator","Invalid iteration method choice\n"); DestroyIntegrator(&integrator); return(NULL); } } /* Call CVodeCreate to create the solver memory: A pointer to the integrator problem memory is returned and stored in cvode_mem. */ integrator->cvode_mem = CVodeCreate(mlmm,miter); if (check_flag((void *)(integrator->cvode_mem),"CVodeCreate",0)) { DestroyIntegrator(&integrator); return(NULL); } /* 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) tStart is the initial time y is the initial dependent variable vector CV_SS specifies scalar relative and absolute tolerances reltol the scalar relative tolerance &abstol is the absolute tolerance vector */ flag = CVodeInit(integrator->cvode_mem,f, simulationGetBvarStart(integrator->simulation),integrator->y); if (check_flag(&flag,"CVodeMalloc",1)) { DestroyIntegrator(&integrator); return(NULL); } double* atol = simulationGetATol(integrator->simulation); if (simulationGetATolLength(integrator->simulation) == 1) { flag = CVodeSStolerances(integrator->cvode_mem,simulationGetRTol(integrator->simulation),atol[0]); if (check_flag(&flag,"CVodeSStolerances",1)) { DestroyIntegrator(&integrator); return(NULL); } } else { ERROR("CreateIntegrator", "array abstol not supported yet."); DestroyIntegrator(&integrator); return(NULL); } free(atol); /* if using Newton iteration need a linear solver */ if (simulationGetIterationMethod(integrator->simulation) == NEWTON) { switch (simulationGetLinearSolver(integrator->simulation)) { case DENSE: { /* Call CVDense to specify the CVDENSE dense linear solver */ flag = CVDense(integrator->cvode_mem,em->nRates); if (check_flag(&flag,"CVDense",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case BAND: { /* Call CVBand to specify the CVBAND linear solver */ long int upperBW = em->nRates - 1; /* FIXME: This probably doesn't make */ long int lowerBW = em->nRates - 1; /* any sense, but should do until I */ /* fix it */ flag = CVBand(integrator->cvode_mem,em->nRates,upperBW,lowerBW); if (check_flag(&flag,"CVBand",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case DIAG: { /* Call CVDiag to specify the CVDIAG linear solver */ flag = CVDiag(integrator->cvode_mem); if (check_flag(&flag,"CVDiag",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPGMR: { /* Call CVSpgmr to specify the linear solver CVSPGMR with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSpgmr",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPBCG: { /* Call CVSpbcg to specify the linear solver CVSPBCG with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSpbcg(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSpbcg",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPTFQMR: { /* Call CVSptfqmr to specify the linear solver CVSPTFQMR with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSptfqmr(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSptfqmr",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; default: { ERROR("CreateIntegrator", "Must specify a valid linear solver when using " "Newton iteration\n"); DestroyIntegrator(&integrator); return(NULL); } } } /* Pass through the executable model to f */ // FIXME: really need to handle this properly, but for now simply grabbing a handle. flag = CVodeSetUserData(integrator->cvode_mem,(void*)(em)); if (check_flag(&flag,"CVodeSetUserData",1)) { DestroyIntegrator(&integrator); return(NULL); } /* Set the maximum time step size if it looks valid */ double mxD = simulationGetBvarMaxStep(integrator->simulation); double tbD = simulationGetBvarTabStep(integrator->simulation); double maxStep; if (simulationIsBvarMaxStepSet(integrator->simulation)) { flag = CVodeSetMaxStep(integrator->cvode_mem, (realtype)mxD); maxStep = mxD; if (check_flag(&flag,"CVodeSetMaxStep (max)",1)) { DestroyIntegrator(&integrator); return(NULL); } } else { flag = CVodeSetMaxStep(integrator->cvode_mem, (realtype)tbD); maxStep = tbD; if (check_flag(&flag,"CVodeSetMaxStep (tab)",1)) { DestroyIntegrator(&integrator); return(NULL); } } simulationSetBvarMaxStep(integrator->simulation,maxStep); simulationSetBvarMaxStep(sim,maxStep); /* try and make a sensible guess at the maximal number of steps to get to tout to take into account case where we simply want to integrate over a large time period in small steps (why?) */ double tout = simulationGetBvarStart(integrator->simulation)+ simulationGetBvarTabStep(integrator->simulation); if (simulationIsBvarEndSet(integrator->simulation)) { double end = simulationGetBvarEnd(integrator->simulation); if (tout > end) tout = end; } long int maxsteps = (long int)ceil(tout/maxStep) * 100; if (maxsteps < 500) maxsteps = 500; /* default value */ flag = CVodeSetMaxNumSteps(integrator->cvode_mem,maxsteps); if (check_flag(&flag,"CVodeSetMaxNumSteps",1)) { DestroyIntegrator(&integrator); return(NULL); } return(integrator); }
void CVodesIntegrator::reinitialize(double t0, FuncEval& func) { m_t0 = t0; //try { func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y))); //} //catch (CanteraError) { //showErrors(); //error("Teminating execution"); //} int result, flag; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) if (m_itol == CV_SV) { result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, nv(m_abstol)); } else { result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, &m_abstols); } if (result != CV_SUCCESS) { throw CVodesErr("CVodeReInit failed. result = "+int2str(result)); } #elif defined(SUNDIALS_VERSION_24) result = CVodeReInit(m_cvode_mem, m_t0, nv(m_y)); if (result != CV_SUCCESS) { throw CVodesErr("CVodeReInit failed. result = "+int2str(result)); } #endif if (m_type == DENSE + NOJAC) { long int N = m_neq; CVDense(m_cvode_mem, N); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == BAND + NOJAC) { long int N = m_neq; long int nu = m_mupper; long int nl = m_mlower; CVBand(m_cvode_mem, N, nu, nl); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else { throw CVodesErr("unsupported option"); } // set options if (m_maxord > 0) flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord); if (m_maxsteps > 0) flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); if (m_hmax > 0) flag = CVodeSetMaxStep(m_cvode_mem, m_hmax); }
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); }
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 main() { realtype abstol, reltol, t, tout; N_Vector u; UserData data; void *cvode_mem; int flag, iout, jpre; long int ml, mu; u = NULL; data = NULL; cvode_mem = NULL; /* Allocate and initialize u, and set problem data and tolerances */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); data = (UserData) malloc(sizeof *data); if(check_flag((void *)data, "malloc", 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); /* Call CVBandPreInit to initialize band preconditioner */ ml = mu = 2; flag = CVBandPrecInit(cvode_mem, NEQ, mu, ml); if(check_flag(&flag, "CVBandPrecInit", 0)) return(1); PrintIntro(mu, ml); /* Loop over jpre (= PREC_LEFT, PREC_RIGHT), and solve the problem */ for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) { /* On second run, re-initialize u, the solver, and CVSPGMR */ if (jpre == PREC_RIGHT) { SetInitialProfiles(u, data->dx, data->dy); flag = CVodeReInit(cvode_mem, T0, u); if(check_flag(&flag, "CVodeReInit", 1)) return(1); flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT); check_flag(&flag, "CVSpilsSetPrecType", 1); printf("\n\n-------------------------------------------------------"); printf("------------\n"); } printf("\n\nPreconditioner type is: jpre = %s\n\n", (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT"); /* 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); check_flag(&flag, "CVode", 1); PrintOutput(cvode_mem, u, t); if (flag != CV_SUCCESS) { break; } } /* Print final statistics */ PrintFinalStats(cvode_mem); } /* End of jpre loop */ /* Free memory */ N_VDestroy_Serial(u); free(data); CVodeFree(&cvode_mem); return(0); }
int main(int argc, char *argv[]) { realtype abstol=ATOL, reltol=RTOL, t; N_Vector c; WebData wdata; void *cvode_mem; int flag; void *cvadj_mem; int ncheck; realtype reltolB=RTOL, abstolB=ATOL; N_Vector cB; c = NULL; cB = NULL; wdata = NULL; cvode_mem = NULL; cvadj_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/CVodeMalloc for forward run */ printf("\nCreate and allocate CVODE memory for forward run\n"); cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); wdata->cvode_memF = cvode_mem; /* Used in Precond */ flag = CVodeSetFdata(cvode_mem, wdata); if(check_flag(&flag, "CVodeSetFdata", 1)) return(1); flag = CVodeMalloc(cvode_mem, f, T0, c, CV_SS, reltol, &abstol); if(check_flag(&flag, "CVodeMalloc", 1)) return(1); /* Call CVSpgmr for forward run */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpgmrSetPreconditioner(cvode_mem, Precond, PSolve, wdata); if(check_flag(&flag, "CVSpgmrSetPreconditioner", 1)) return(1); /* Set-up adjoint calculations */ printf("\nAllocate global memory\n"); cvadj_mem = CVadjMalloc(cvode_mem, NSTEPS); if(check_flag((void *)cvadj_mem, "CVadjMalloc", 0)) return(1); wdata->cvadj_mem = cvadj_mem; /* Perform forward run */ printf("\nForward integration ... "); flag = CVodeF(cvadj_mem, TOUT, c, &t, CV_NORMAL, &ncheck); if(check_flag(&flag, "CVodeF", 1)) return(1); printf("done (ncheck = %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(cvadj_mem, CV_BDF, CV_NEWTON); if(check_flag(&flag, "CVodeCreateB", 1)) return(1); flag = CVodeSetFdataB(cvadj_mem, wdata); if(check_flag(&flag, "CVodeSetFdataB", 1)) return(1); flag = CVodeMallocB(cvadj_mem, fB, TOUT, cB, CV_SS, reltolB, &abstolB); if(check_flag(&flag, "CVodeMallocB", 1)) return(1); /* Call CVSpgmr */ flag = CVSpgmrB(cvadj_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmrB", 1)) return(1); flag = CVSpgmrSetPreconditionerB(cvadj_mem, PrecondB, PSolveB, wdata); if(check_flag(&flag, "CVSpgmrSetPreconditionerB", 1)) return(1); /* Perform backward integration */ printf("\nBackward integration\n"); flag = CVodeB(cvadj_mem, T0, cB, &t, CV_NORMAL); if(check_flag(&flag, "CVodeB", 1)) return(1); PrintOutput(cB, NS, MXNS, wdata); /* Free all memory */ CVodeFree(cvode_mem); CVadjFree(cvadj_mem); N_VDestroy_Serial(c); N_VDestroy_Serial(cB); FreeUserData(wdata); return(0); }