static int PrepareNextRun(void *cvode_mem, int lmm, int miter, long int mu, long int ml) { int flag = CV_SUCCESS; printf("\n\n-------------------------------------------------------------"); printf("\n\nLinear Multistep Method : "); if (lmm == CV_ADAMS) { printf("ADAMS\n"); } else { printf("BDF\n"); } printf("Iteration : "); if (miter == FUNC) { printf("FUNCTIONAL\n"); } else { printf("NEWTON\n"); printf("Linear Solver : "); switch(miter) { case DENSE_USER : printf("Dense, User-Supplied Jacobian\n"); flag = CVDense(cvode_mem, P1_NEQ); check_flag(&flag, "CVDense", 1); if(flag != CV_SUCCESS) break; flag = CVDenseSetJacFn(cvode_mem, Jac1, NULL); check_flag(&flag, "CVDenseSetJacFn", 1); break; case DENSE_DQ : printf("Dense, Difference Quotient Jacobian\n"); flag = CVDenseSetJacFn(cvode_mem, NULL, NULL); check_flag(&flag, "CVDenseSetJacFn", 1); break; case DIAG : printf("Diagonal Jacobian\n"); flag = CVDiag(cvode_mem); check_flag(&flag, "CVDiag", 1); break; case BAND_USER : printf("Band, User-Supplied Jacobian\n"); flag = CVBand(cvode_mem, P2_NEQ, mu, ml); check_flag(&flag, "CVBand", 1); if(flag != CV_SUCCESS) break; flag = CVBandSetJacFn(cvode_mem, Jac2, NULL); check_flag(&flag, "CVBandSetJacFn", 1); break; case BAND_DQ : printf("Band, Difference Quotient Jacobian\n"); flag = CVBandSetJacFn(cvode_mem, NULL, NULL); check_flag(&flag, "CVBandSetJacFn", 1); break; } } return(flag); }
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"); } }
void FCV_DIAG(int *ier) { if (CV_cvodemem == NULL) { *ier = -1; return; } *ier = CVDiag(CV_cvodemem); CV_ls = CV_LS_DIAG; return; }
int CVDiagB(void *cvadj_mem) { 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 = CVDiag(cvode_mem); 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"); } }
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); } }
int CVDiagB(void *cvode_mem, int which) { CVodeMem cv_mem; CVadjMem ca_mem; CVodeBMem cvB_mem; void *cvodeB_mem; int flag; /* Check if cvode_mem exists */ if (cvode_mem == NULL) { cvProcessError(NULL, CVDIAG_MEM_NULL, "CVSDIAG", "CVDiagB", MSGDG_CVMEM_NULL); return(CVDIAG_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Was ASA initialized? */ if (cv_mem->cv_adjMallocDone == FALSE) { cvProcessError(cv_mem, CVDIAG_NO_ADJ, "CVSDIAG", "CVDiagB", MSGDG_NO_ADJ); return(CVDIAG_NO_ADJ); } ca_mem = cv_mem->cv_adj_mem; /* Check which */ if ( which >= ca_mem->ca_nbckpbs ) { cvProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVSDIAG", "CVDiagB", MSGDG_BAD_WHICH); return(CVDIAG_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); flag = CVDiag(cvodeB_mem); return(flag); }
void integrate() { integer i, N, flag; real tr, t; N = RHS.N; for (i = 1; i <= 2 * N; i++) Ith(y, i) = Ith(ystart, i); /* Initialize ODE solver */ cvode_mem = CVodeMalloc(2 * N, derivs, Ith(tlist, 1), y, (method == 0) ? ADAMS : BDF, (itertype == 0) ? FUNCTIONAL : NEWTON, (nabstol == 1) ? SS : SV, &reltol, abstolp, NULL, NULL, TRUE, iopt, ropt, NULL); if (cvode_mem == NULL) { fatal_error("CVodeMalloc failed.\n"); } /* Call CVDiag */ CVDiag(cvode_mem); fwrite(N_VDATA(y), sizeof(real), 2 * N, op); for (i = 2; i <= ntimes; i++) { tr = Ith(tlist, i); flag = CVode1(cvode_mem, tr, y, &t, NORMAL); if (flag != SUCCESS) { sprintf(errmsg, "CVode failed, flag=%d.\n", flag); fatal_error(errmsg); } fwrite(N_VDATA(y), sizeof(real), 2 * N, op); progress += NHASH; while (progress >= ntimes - 1) { fprintf(stderr, "#"); progress -= ntimes - 1; } } fprintf(stderr, "\n"); CVodeFree(cvode_mem); }
void sdesim(integer itraj, integer ntraj) /* Integrate a stochastic differential equation */ { integer flag, indx, i, j, k, l, m, N; real t, xnorm2; real temp, tempr, tempi, tl, tmp; top = Ith(tlist, 1); head = 0; N = RHS.N; for (j = 1; j <= 2 * N; j++) Ith(y, j) = Ith(ystart, j); /* Initialize ODE solver */ ropt[HMAX] = dt; cvode_mem = CVodeMalloc(2 * N, derivs, Ith(tlist, 1), y, (method == 0) ? ADAMS : BDF, (itertype == 0) ? FUNCTIONAL : NEWTON, (nabstol == 1) ? SS : SV, &reltol, abstolp, NULL, NULL, TRUE, iopt, ropt, NULL); if (cvode_mem == NULL) { fatal_error("CVodeMalloc failed.\n"); } /* Call CVDiag */ CVDiag(cvode_mem); if (nopers == 0) fwrite(&itraj, sizeof(integer), 1, op); if (photocurflag) fwrite(&itraj, sizeof(integer), 1, php); if (clrecflag) { temp = itraj; fwrite(&temp, sizeof(real), 1, cp); temp = 0.0; fwrite(&temp, sizeof(real), 1, cp); } m = 1; tl = Ith(tlist, 1); if (nopers == 0) /* Write the wave function */ fwrite(N_VDATA(y), sizeof(real), 2 * N, op); else /* Record operator expectations in * accumulation buffer */ operAccum(N_VDATA(y) - 1, q, N, tl, 1); for (i = 2; i <= ntimes; i++) { for (k = 1; k <= nhomodyne; k++) /* Initialize buffers for * photocurrent records */ h**o[k] = 0; for (k = 1; k <= nheterodyne; k++) heteror[k] = heteroi[k] = 0; for (l = 1; l <= refine; l++) { for (k = 1; k <= nhomodyne; k++) Ith(homnoise, k) = gennor(0.0, namplr); for (k = 1; k <= nheterodyne; k++) { Ith(hetnoiser, k) = gennor(0.0, namplc); Ith(hetnoisei, k) = gennor(0.0, namplc); } tl = Ith(tlist, i - 1) + (l - 1) * dt; flag = CVodeRestart(cvode_mem, tl, y); if (flag != SUCCESS) { sprintf(errmsg, "CVodeRestart failed, flag=%d.\n", flag); fatal_error(errmsg); } flag = CVode(cvode_mem, tl + dt, y, &t, NORMAL); if (flag != SUCCESS) { sprintf(errmsg, "CVode failed, flag=%d.\n", flag); fatal_error(errmsg); } /* Evaluate photocurrent during the previous interval */ xnorm2 = norm2(N_VDATA(y) - 1, N); for (k = 1; k <= nhomodyne; k++) { FSmul(&homodyne[k], tl, N_VDATA(y) - 1, q); /* Calculate homodyne * terms */ inprod(N_VDATA(y) - 1, q, N, &tempr, &tempi); temp = 2 * tempr / xnorm2; if (photocurflag) { h**o[k] += (temp + Ith(homnoise, k)); if (l == refine) { tmp = h**o[k] / refine; fwrite(&tmp, sizeof(real), 1, php); } } } for (k = 1; k <= nheterodyne; k++) { FSmul(&heterodyne[k], tl, N_VDATA(y) - 1, q); /* Calculate heterodyne * terms */ inprod(N_VDATA(y) - 1, q, N, &tempr, &tempi); tempr = tempr / xnorm2; tempi = -tempi / xnorm2; if (photocurflag) { heteror[k] += (tempr + Ith(hetnoiser, k)); heteroi[k] += (tempi + Ith(hetnoisei, k)); if (l == refine) { tmp = heteror[k] / refine; fwrite(&tmp, sizeof(real), 1, php); tmp = heteroi[k] / refine; fwrite(&tmp, sizeof(real), 1, php); } } } } /* Normalize the wave function */ xnorm2 = 1. / sqrt(norm2(N_VDATA(y) - 1, N)); for (j = 1; j <= 2 * N; j++) pl[j] = Ith(y, j) * xnorm2; if (nopers == 0) fwrite(&pl[1], sizeof(real), 2 * N, op); else operAccum(pl, q, N, tl, i); if (xnorm2 < 1e-6 || xnorm2 > 1e6) { /* Restart integrator if norm * is too large or small */ CVodeFree(cvode_mem); ropt[HMAX] = dt; for (j = 1; j <= 2 * N; j++) Ith(y, j) = pl[j]; cvode_mem = CVodeMalloc(2 * N, derivs, Ith(tlist, 1), y, (method == 0) ? ADAMS : BDF, (itertype == 0) ? FUNCTIONAL : NEWTON, (nabstol == 1) ? SS : SV, &reltol, abstolp, NULL, NULL, TRUE, iopt, ropt, NULL); if (cvode_mem == NULL) { fatal_error("CVodeMalloc failed.\n"); } /* Call CVDiag */ CVDiag(cvode_mem); } progress += NHASH; while (progress >= (ntimes - 1) * ntraj) { fprintf(stderr, "#"); progress -= (ntimes - 1) * ntraj; } } CVodeFree(cvode_mem); }
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); } }
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); }
real docollapse(real tl, real nl, real tr, real nr, real thresh) /* Find the time of collapse, update the wave function and restart the integrator */ { integer j, flag, k; real tc, nc, temp, sum, t; for (k=1;k<=5;k++) { tc = tl + log(nl / thresh) / log(nl / nr) * (tr - tl); flag = CVode1(cvode_mem, tc, y, &t, NORMAL); if (flag != SUCCESS) { sprintf(errmsg, "CVode failed, flag=%d.\n", flag); fatal_error(errmsg); } nc = norm2(N_VDATA(y) - 1, N); if (fabs(thresh - nc) < THRESHTOL * fabs(thresh)) break; else if (nc < thresh) { nr = nc; tr = tc; } else { nl = nc; tl = tc; } } /* if (k>5) printf("\nWarning: Norm^2 of wavefunction does not attain threshold %f / %f\n" "Increase accuracy of integrator.\n",nc,thresh);*/ /* Collapse occurs at tc, apply appropriate operator and restart * integrator */ sum = 0.0; for (j = 1; j <= ncollapses; j++) { FSmul(&collapses[j], tc, N_VDATA(y) - 1, N_VDATA(q) - 1); sum += (Cprobs[j] = norm2(N_VDATA(q) - 1, N)); } thresh = genunf(0.0, 1.0); /* To determine which collapse occured */ for (j = 1; j <= ncollapses; j++) { thresh -= Cprobs[j] / sum; if (thresh <= 0) break; } if (clrecflag) { /* Write out classical record */ fwrite(&tc, sizeof(real), 1, cp); temp = j; fwrite(&temp, sizeof(real), 1, cp); } /* Apply the collapse and normalize */ FSmul(&collapses[j], tc, N_VDATA(y) - 1, N_VDATA(q) - 1); sum = sqrt(norm2(N_VDATA(q) - 1, N)); for (j = 1; j <= 2 * N; j++) Ith(y, j) = Ith(q, j) / sum; /* Replace the integrator, since we have a new initial condition */ CVodeFree(cvode_mem); cvode_mem = CVodeMalloc(2 * N, derivs, tc, y, (method == 0) ? ADAMS : BDF, (itertype == 0) ? FUNCTIONAL : NEWTON, (nabstol == 1) ? SS : SV, &reltol, abstolp, NULL, NULL, TRUE, iopt, ropt, NULL); if (cvode_mem == NULL) { fatal_error("CVodeMalloc failed.\n"); } /* Call CVDiag */ CVDiag(cvode_mem); return tc; }
int cvode_init(solver_props *props){ assert(props->statesize > 0); cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem)); unsigned int modelid; props->mem = mem; for(modelid=0; modelid<props->num_models; modelid++){ // Set location to store the value of the next states mem[modelid].next_states = &(props->next_states[modelid*props->statesize]); mem[modelid].props = props; // Set the modelid on a per memory structure basis mem[modelid].modelid = modelid; // Create intial value vector // This is done to avoid having the change the internal indexing within the flows and for the output_buffer mem[modelid].y0 = N_VMake_Serial(props->statesize, mem[modelid].next_states); // Create data structure for solver // mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON); mem[modelid].cvmem = CVodeCreate(props->cvode.lmm, props->cvode.iter); // Initialize CVODE if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, mem[modelid].y0) != CV_SUCCESS){ PRINTF( "Couldn't initialize CVODE"); } // Set CVODE error handler if(CVodeSetErrHandlerFn(mem[modelid].cvmem, cvode_err_handler, mem)){ PRINTF( "Couldn't set CVODE error handler"); } // Set solver tolerances if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){ PRINTF( "Could not set CVODE tolerances"); } // Set maximum order if(CVodeSetMaxOrd(mem[modelid].cvmem, props->cvode.max_order) != CV_SUCCESS) { PRINTF( "Could not set CVODE maximum order"); } // Set linear solver switch (props->cvode.solv) { case CVODE_DENSE: if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){ PRINTF( "Could not set CVODE DENSE linear solver"); } break; case CVODE_DIAG: if(CVDiag(mem[modelid].cvmem) != CV_SUCCESS){ PRINTF( "Could not set CVODE DIAG linear solver"); } break; case CVODE_BAND: if(CVBand(mem[modelid].cvmem, mem[modelid].props->statesize, mem[modelid].props->cvode.upperhalfbw, mem[modelid].props->cvode.lowerhalfbw) != CV_SUCCESS){ PRINTF( "Could not set CVODE BAND linear solver"); } break; default: PRINTF( "No valid CVODE solver passed"); } // Set user data to contain pointer to memory structure for use in model_flows if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){ PRINTF( "CVODE failed to initialize user data"); } } return 0; }
void FCV_DIAG(int *ier) { *ier = CVDiag(CV_cvodemem); CV_ls = 3; }
int main(int argc, char *argv[]) { realtype dx, reltol, abstol, t, tout, umax; N_Vector u; UserData data; void *cvode_mem; int iout, retval, my_pe, npes; sunindextype local_N, nperpe, nrem, my_base; long int nst; MPI_Comm comm; u = NULL; data = NULL; cvode_mem = NULL; /* Get processor number, total number of pe's, and my_pe. */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &my_pe); /* Set local vector length. */ nperpe = NEQ/npes; nrem = NEQ - npes*nperpe; local_N = (my_pe < nrem) ? nperpe+1 : nperpe; my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem; data = (UserData) malloc(sizeof *data); /* Allocate data memory */ if(check_retval((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1); data->comm = comm; data->npes = npes; data->my_pe = my_pe; u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */ if(check_retval((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1); reltol = ZERO; /* Set the tolerances */ abstol = ATOL; dx = data->dx = XMAX/((realtype)(MX+1)); /* Set grid coefficients in data */ data->hdcoef = RCONST(1.0)/(dx*dx); data->hacoef = RCONST(0.5)/(RCONST(2.0)*dx); SetIC(u, dx, local_N, my_base); /* Initialize u vector */ /* Call CVodeCreate to create the solver memory and specify the * Adams-Moulton LMM */ cvode_mem = CVodeCreate(CV_ADAMS); if(check_retval((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1); retval = CVodeSetUserData(cvode_mem, data); if(check_retval(&retval, "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. */ retval = CVodeInit(cvode_mem, f, T0, u); if(check_retval(&retval, "CVodeInit", 1, my_pe)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ retval = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_retval(&retval, "CVodeSStolerances", 1, my_pe)) return(1); /* Call CVDiag to create and attach CVODE-specific diagonal linear solver */ retval = CVDiag(cvode_mem); if(check_retval(&retval, "CVDiag", 1, my_pe)) return(1); if (my_pe == 0) PrintIntro(npes); umax = N_VMaxNorm(u); if (my_pe == 0) { t = T0; PrintData(t, umax, 0); } /* In loop over output points, call CVode, print results, test for error */ for (iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { retval = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_retval(&retval, "CVode", 1, my_pe)) break; umax = N_VMaxNorm(u); retval = CVodeGetNumSteps(cvode_mem, &nst); check_retval(&retval, "CVodeGetNumSteps", 1, my_pe); if (my_pe == 0) PrintData(t, umax, nst); } if (my_pe == 0) PrintFinalStats(cvode_mem); /* Print some final statistics */ N_VDestroy_Parallel(u); /* Free the u vector */ CVodeFree(&cvode_mem); /* Free the integrator memory */ free(data); /* Free user data */ MPI_Finalize(); return(0); }
int dynamixMain (int argc, char * argv[]) { //// DECLARING VARIABLES // Struct of parameters PARAMETERS p; // CVode variables void * cvode_mem = NULL; // pointer to block of CVode memory N_Vector y, yout; // arrays of populations // arrays for energetic parameters realtype ** V = NULL; // pointer to k-c coupling constants realtype * Vbridge = NULL; // pointer to array of bridge coupling constants. // first element [0] is Vkb1, last [Nb] is VcbN realtype * Vnobridge = NULL; // coupling constant when there is no bridge //// Setting defaults for parameters to be read from input //// done setting defaults int flag; realtype * k_pops = NULL; // pointers to arrays of populations realtype * l_pops = NULL; realtype * c_pops = NULL; realtype * b_pops = NULL; realtype * ydata = NULL; // pointer to ydata (contains all populations) realtype * wavefunction = NULL; // (initial) wavefunction realtype * dm = NULL; // density matrix realtype * dmt = NULL; // density matrix in time realtype * wfnt = NULL; // density matrix in time realtype * k_energies = NULL; // pointers to arrays of energies realtype * c_energies = NULL; realtype * b_energies = NULL; realtype * l_energies = NULL; realtype t0 = 0.0; // initial time realtype t = 0; realtype tret = 0; // time returned by the solver time_t startRun; // time at start of log time_t endRun; // time at end of log struct tm * currentTime = NULL; // time structure for localtime #ifdef DEBUG FILE * realImaginary; // file containing real and imaginary parts of the wavefunction #endif FILE * log; // log file with run times realtype * tkprob = NULL; // total probability in k, l, c, b states at each timestep realtype * tlprob = NULL; realtype * tcprob = NULL; realtype * tbprob = NULL; double ** allprob = NULL; // populations in all states at all times realtype * times = NULL; realtype * qd_est = NULL; realtype * qd_est_diag = NULL; std::string inputFile = "ins/parameters.in"; // name of input file std::string cEnergiesInput = "ins/c_energies.in"; std::string cPopsInput = "ins/c_pops.in"; std::string bEnergiesInput = "ins/b_energies.in"; std::string VNoBridgeInput = "ins/Vnobridge.in"; std::string VBridgeInput = "ins/Vbridge.in"; std::map<const std::string, bool> outs; // map of output file names to bool // default output directory p.outputDir = "outs/"; double summ = 0; // sum variable // ---- process command line flags ---- // opterr = 0; int c; std::string insDir; /* process command line options */ while ((c = getopt(argc, argv, "i:o:")) != -1) { switch (c) { case 'i': // check that it ends in a slash std::cerr << "[dynamix]: assigning input directory" << std::endl; insDir = optarg; if (strcmp(&(insDir.at(insDir.length() - 1)), "/")) { std::cerr << "ERROR: option -i requires argument (" << insDir << ") to have a trailing slash (/)." << std::endl; return 1; } else { // ---- assign input files ---- // inputFile = insDir + "parameters.in"; cEnergiesInput = insDir + "c_energies.in"; cPopsInput = insDir + "c_pops.in"; bEnergiesInput = insDir + "b_energies.in"; VNoBridgeInput = insDir + "Vnobridge.in"; VBridgeInput = insDir + "Vbridge.in"; } break; case 'o': std::cerr << "[dynamix]: assigning output directory" << std::endl; p.outputDir = optarg; break; case '?': if (optopt == 'i') { fprintf(stderr, "Option -%c requires a directory argument.\n", optopt); } else if (isprint(optopt)) { fprintf(stderr, "Unknown option -%c.\n", optopt); } else { fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); } return 1; default: continue; } } optind = 1; // reset global variable counter for the next time this is run std::cerr << "[dynamix]: ARGUMENTS" << std::endl; for (int ii = 0; ii < argc; ii++) { std::cerr << "[dynamix]: " << argv[ii] << std::endl; } //// ASSIGN PARAMETERS FROM INPUT FILE // ---- TODO create output directory if it does not exist ---- // flag = mkdir(p.outputDir.c_str(), 0755); std::cerr << "Looking for inputs in all the " << inputFile << " places" << std::endl; assignParams(inputFile.c_str(), &p); // Decide which output files to make #ifdef DEBUG std::cout << "Assigning outputs as specified in " << inputFile << "\n"; #endif assignOutputs(inputFile.c_str(), outs, &p); #ifdef DEBUG // print out which outputs will be made for (std::map<const std::string, bool>::iterator it = outs.begin(); it != outs.end(); it++) { std::cout << "Output file: " << it->first << " will be created.\n"; } #endif // OPEN LOG FILE; PUT IN START TIME // if (isOutput(outs, "log.out")) { log = fopen("log.out", "w"); // note that this file is closed at the end of the program } time(&startRun); currentTime = localtime(&startRun); if (isOutput(outs, "log.out")) { fprintf(log, "Run started at %s\n", asctime(currentTime)); } if (isOutput(outs, "log.out")) { // make a note about the laser intensity. fprintf(log,"The laser intensity is %.5e W/cm^2.\n\n",pow(p.pumpAmpl,2)*3.5094452e16); } //// READ DATA FROM INPUTS p.Nc = numberOfValuesInFile(cEnergiesInput.c_str()); p.Nb = numberOfValuesInFile(bEnergiesInput.c_str()); k_pops = new realtype [p.Nk]; c_pops = new realtype [p.Nc]; b_pops = new realtype [p.Nb]; l_pops = new realtype [p.Nl]; k_energies = new realtype [p.Nk]; c_energies = new realtype [p.Nc]; b_energies = new realtype [p.Nb]; l_energies = new realtype [p.Nl]; if (numberOfValuesInFile(cPopsInput.c_str()) != p.Nc) { fprintf(stderr, "ERROR [Inputs]: c_pops and c_energies not the same length.\n"); return -1; } readArrayFromFile(c_energies, cEnergiesInput.c_str(), p.Nc); if (p.bridge_on) { if (p.bridge_on && (p.Nb < 1)) { std::cerr << "\nERROR: bridge_on but no bridge states. The file b_energies.in is probably empty.\n"; return -1; } p.Vbridge.resize(p.Nb+1); readArrayFromFile(b_energies, bEnergiesInput.c_str(), p.Nb); readVectorFromFile(p.Vbridge, VBridgeInput.c_str(), p.Nb + 1); #ifdef DEBUG std::cout << "COUPLINGS:"; for (int ii = 0; ii < p.Nb+1; ii++) { std::cout << " " << p.Vbridge[ii]; } std::cout << std::endl; #endif } else { p.Nb = 0; p.Vnobridge.resize(1); readVectorFromFile(p.Vnobridge, VNoBridgeInput.c_str(), 1); } #ifdef DEBUG std::cout << "\nDone reading things from inputs.\n"; #endif //// PREPROCESS DATA FROM INPUTS // check torsion parameters, set up torsion spline if (p.torsion) { #ifdef DEBUG std::cout << "Torsion is on." << std::endl; #endif // error checking if (p.torsionSite > p.Nb) { std::cerr << "ERROR: torsion site (" << p.torsionSite << ") is larger than number of bridge sites (" << p.Nb << ")." << std::endl; exit(-1); } else if (p.torsionSite < 0) { std::cerr << "ERROR: torsion site is less than zero." << std::endl; exit(-1); } if (!fileExists(p.torsionFile)) { std::cerr << "ERROR: torsion file " << p.torsionFile << " does not exist." << std::endl; } // create spline p.torsionV = new Spline(p.torsionFile.c_str()); if (p.torsionV->getFirstX() != 0.0) { std::cerr << "ERROR: time in " << p.torsionFile << " should start at 0.0." << std::endl; exit(-1); } if (p.torsionV->getLastX() < p.tout) { std::cerr << "ERROR: time in " << p.torsionFile << " should be >= tout." << std::endl; exit(-1); } } // set number of processors for OpenMP //omp_set_num_threads(p.nproc); mkl_set_num_threads(p.nproc); p.NEQ = p.Nk+p.Nc+p.Nb+p.Nl; // total number of equations set p.NEQ2 = p.NEQ*p.NEQ; // number of elements in DM #ifdef DEBUG std::cout << "\nTotal number of states: " << p.NEQ << std::endl; std::cout << p.Nk << " bulk, " << p.Nc << " QD, " << p.Nb << " bridge, " << p.Nl << " bulk VB.\n"; #endif tkprob = new realtype [p.numOutputSteps+1]; // total population on k, b, c at each timestep tcprob = new realtype [p.numOutputSteps+1]; tbprob = new realtype [p.numOutputSteps+1]; tlprob = new realtype [p.numOutputSteps+1]; allprob = new double * [p.numOutputSteps+1]; for (int ii = 0; ii <= p.numOutputSteps; ii++) { allprob[ii] = new double [p.NEQ]; } // assign times. p.times.resize(p.numOutputSteps+1); for (int ii = 0; ii <= p.numOutputSteps; ii++) { p.times[ii] = float(ii)/p.numOutputSteps*p.tout; } qd_est = new realtype [p.numOutputSteps+1]; qd_est_diag = new realtype [p.numOutputSteps+1]; p.Ik = 0; // set index start positions for each type of state p.Ic = p.Nk; p.Ib = p.Ic+p.Nc; p.Il = p.Ib+p.Nb; // assign bulk conduction and valence band energies // for RTA, bulk and valence bands have parabolic energies if (p.rta) { buildParabolicBand(k_energies, p.Nk, p.kBandEdge, CONDUCTION, &p); buildParabolicBand(l_energies, p.Nl, p.lBandTop, VALENCE, &p); } else { buildContinuum(k_energies, p.Nk, p.kBandEdge, p.kBandTop); buildContinuum(l_energies, p.Nl, p.kBandEdge - p.valenceBand - p.bulk_gap, p.kBandEdge - p.bulk_gap); } // calculate band width p.kBandWidth = k_energies[p.Nk - 1] - k_energies[0]; //// BUILD INITIAL WAVEFUNCTION // bridge states (empty to start) initializeArray(b_pops, p.Nb, 0.0); // coefficients in bulk and other states depend on input conditions in bulk if (!p.rta) { #ifdef DEBUG std::cout << "\ninitializing k_pops\n"; #endif if (p.bulk_constant) { initializeArray(k_pops, p.Nk, 0.0); #ifdef DEBUG std::cout << "\ninitializing k_pops with constant probability in range of states\n"; #endif initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0); initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } else if (p.bulk_Gauss) { buildKPopsGaussian(k_pops, k_energies, p.kBandEdge, p.bulkGaussSigma, p.bulkGaussMu, p.Nk); // populate k states with FDD initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } else if (p.qd_pops) { readArrayFromFile(c_pops, cPopsInput.c_str(), p.Nc); // QD populations from file initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(k_pops, p.Nk, 0.0); // populate k states (all zero to start off) } else { initializeArray(k_pops, p.Nk, 0.0); // populate k states (all zero to start off) initializeArray(l_pops, p.Nl, 1.0); // populate l states (all populated to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } #ifdef DEBUG std::cout << "\nThis is k_pops:\n"; for (int ii = 0; ii < p.Nk; ii++) { std::cout << k_pops[ii] << std::endl; } std::cout << "\n"; #endif } // with RTA, use different set of switches else { // bulk valence band if (p.VBPopFlag == POP_EMPTY) { #ifdef DEBUG std::cout << "Initializing empty valence band" << std::endl; #endif initializeArray(l_pops, p.Nl, 0.0); } else if (p.VBPopFlag == POP_FULL) { #ifdef DEBUG std::cout << "Initializing full valence band" << std::endl; #endif initializeArray(l_pops, p.Nl, 1.0); } else { std::cerr << "ERROR: unrecognized VBPopFlag " << p.VBPopFlag << std::endl; } // bulk conduction band if (p.CBPopFlag == POP_EMPTY) { #ifdef DEBUG std::cout << "Initializing empty conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 0.0); } else if (p.CBPopFlag == POP_FULL) { #ifdef DEBUG std::cout << "Initializing full conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 1.0); } else if (p.CBPopFlag == POP_CONSTANT) { #ifdef DEBUG std::cout << "Initializing constant distribution in conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 0.0); initializeArray(k_pops, p.Nk, 1e-1); // FIXME initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0); } else if (p.CBPopFlag == POP_GAUSSIAN) { #ifdef DEBUG std::cout << "Initializing Gaussian in conduction band" << std::endl; #endif buildKPopsGaussian(k_pops, k_energies, p.kBandEdge, p.bulkGaussSigma, p.bulkGaussMu, p.Nk); } else { std::cerr << "ERROR: unrecognized CBPopFlag " << p.CBPopFlag << std::endl; } //// QD if (p.QDPopFlag == POP_EMPTY) { initializeArray(c_pops, p.Nc, 0.0); } else if (p.QDPopFlag == POP_FULL) { initializeArray(c_pops, p.Nc, 1.0); } else { std::cerr << "ERROR: unrecognized QDPopFlag " << p.QDPopFlag << std::endl; } } // create empty wavefunction wavefunction = new realtype [2*p.NEQ]; initializeArray(wavefunction, 2*p.NEQ, 0.0); // assign real parts of wavefunction coefficients (imaginary are zero) for (int ii = 0; ii < p.Nk; ii++) { wavefunction[p.Ik + ii] = k_pops[ii]; } for (int ii = 0; ii < p.Nc; ii++) { wavefunction[p.Ic + ii] = c_pops[ii]; } for (int ii = 0; ii < p.Nb; ii++) { wavefunction[p.Ib + ii] = b_pops[ii]; } for (int ii = 0; ii < p.Nl; ii++) { wavefunction[p.Il + ii] = l_pops[ii]; } if (isOutput(outs, "psi_start.out")) { outputWavefunction(wavefunction, p.NEQ); } // Give all coefficients a random phase if (p.random_phase) { float phi; // set the seed if (p.random_seed == -1) { srand(time(NULL)); } else { srand(p.random_seed); } for (int ii = 0; ii < p.NEQ; ii++) { phi = 2*3.1415926535*(float)rand()/(float)RAND_MAX; wavefunction[ii] = wavefunction[ii]*cos(phi); wavefunction[ii + p.NEQ] = wavefunction[ii + p.NEQ]*sin(phi); } } #ifdef DEBUG // print out details of wavefunction coefficients std::cout << std::endl; for (int ii = 0; ii < p.Nk; ii++) { std::cout << "starting wavefunction: Re[k(" << ii << ")] = " << wavefunction[p.Ik + ii] << std::endl; } for (int ii = 0; ii < p.Nc; ii++) { std::cout << "starting wavefunction: Re[c(" << ii << ")] = " << wavefunction[p.Ic + ii] << std::endl; } for (int ii = 0; ii < p.Nb; ii++) { std::cout << "starting wavefunction: Re[b(" << ii << ")] = " << wavefunction[p.Ib + ii] << std::endl; } for (int ii = 0; ii < p.Nl; ii++) { std::cout << "starting wavefunction: Re[l(" << ii << ")] = " << wavefunction[p.Il + ii] << std::endl; } for (int ii = 0; ii < p.Nk; ii++) { std::cout << "starting wavefunction: Im[k(" << ii << ")] = " << wavefunction[p.Ik + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nc; ii++) { std::cout << "starting wavefunction: Im[c(" << ii << ")] = " << wavefunction[p.Ic + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nb; ii++) { std::cout << "starting wavefunction: Im[b(" << ii << ")] = " << wavefunction[p.Ib + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nl; ii++) { std::cout << "starting wavefunction: Im[l(" << ii << ")] = " << wavefunction[p.Il + ii + p.NEQ] << std::endl; } std::cout << std::endl; summ = 0; for (int ii = 0; ii < 2*p.NEQ; ii++) { summ += pow(wavefunction[ii],2); } std::cout << "\nTotal population is " << summ << "\n\n"; #endif //// ASSEMBLE ARRAY OF ENERGIES // TODO TODO p.energies.resize(p.NEQ); for (int ii = 0; ii < p.Nk; ii++) { p.energies[p.Ik + ii] = k_energies[ii]; } for (int ii = 0; ii < p.Nc; ii++) { p.energies[p.Ic + ii] = c_energies[ii]; } for (int ii = 0; ii < p.Nb; ii++) { p.energies[p.Ib + ii] = b_energies[ii]; } for (int ii = 0; ii < p.Nl; ii++) { p.energies[p.Il + ii] = l_energies[ii]; } #ifdef DEBUG for (int ii = 0; ii < p.NEQ; ii++) { std::cout << "p.energies[" << ii << "] is " << p.energies[ii] << "\n"; } #endif //// ASSIGN COUPLING CONSTANTS V = new realtype * [p.NEQ]; for (int ii = 0; ii < p.NEQ; ii++) { V[ii] = new realtype [p.NEQ]; } buildCoupling(V, &p, outs); if (isOutput(outs, "log.out")) { // make a note in the log about system timescales double tau = 0; // fundamental system timescale if (p.Nk == 1) { fprintf(log, "\nThe timescale (tau) is undefined (Nk == 1).\n"); } else { if (p.bridge_on) { if (p.scale_bubr) { tau = 1.0/(2*p.Vbridge[0]*M_PI); } else { tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vbridge[0],2)*M_PI); } } else { if (p.scale_buqd) { tau = 1.0/(2*p.Vnobridge[0]*M_PI); } else { tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vnobridge[0],2)*M_PI); } } fprintf(log, "\nThe timescale (tau) is %.9e a.u.\n", tau); } } //// CREATE DENSITY MATRIX if (! p.wavefunction) { // Create the initial density matrix dm = new realtype [2*p.NEQ2]; initializeArray(dm, 2*p.NEQ2, 0.0); #pragma omp parallel for for (int ii = 0; ii < p.NEQ; ii++) { // diagonal part dm[p.NEQ*ii + ii] = pow(wavefunction[ii],2) + pow(wavefunction[ii + p.NEQ],2); if (p.coherent) { // off-diagonal part for (int jj = 0; jj < ii; jj++) { // real part of \rho_{ii,jj} dm[p.NEQ*ii + jj] = wavefunction[ii]*wavefunction[jj] + wavefunction[ii+p.NEQ]*wavefunction[jj+p.NEQ]; // imaginary part of \rho_{ii,jj} dm[p.NEQ*ii + jj + p.NEQ2] = wavefunction[ii]*wavefunction[jj+p.NEQ] - wavefunction[jj]*wavefunction[ii+p.NEQ]; // real part of \rho_{jj,ii} dm[p.NEQ*jj + ii] = dm[p.NEQ*ii + jj]; // imaginary part of \rho_{jj,ii} dm[p.NEQ*jj + ii + p.NEQ2] = -1*dm[p.NEQ*ii + jj + p.NEQ*p.NEQ]; } } } // Create the array to store the density matrix in time dmt = new realtype [2*p.NEQ2*(p.numOutputSteps+1)]; initializeArray(dmt, 2*p.NEQ2*(p.numOutputSteps+1), 0.0); #ifdef DEBUG2 // print out density matrix std::cout << "\nDensity matrix without normalization:\n\n"; for (int ii = 0; ii < p.NEQ; ii++) { for (int jj = 0; jj < p.NEQ; jj++) { fprintf(stdout, "(%+.1e,%+.1e) ", dm[p.NEQ*ii + jj], dm[p.NEQ*ii + jj + p.NEQ2]); } fprintf(stdout, "\n"); } #endif // Normalize the DM so that populations add up to 1. // No normalization if RTA is on. if (!p.rta) { summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { // assume here that diagonal elements are all real summ += dm[p.NEQ*ii + ii]; } if ( summ == 0.0 ) { std::cerr << "\nFATAL ERROR [populations]: total population is 0!\n"; return -1; } if (summ != 1.0) { // the variable 'summ' is now a multiplicative normalization factor summ = 1.0/summ; for (int ii = 0; ii < 2*p.NEQ2; ii++) { dm[ii] *= summ; } } #ifdef DEBUG std::cout << "\nThe normalization factor for the density matrix is " << summ << "\n\n"; #endif } // Error checking for total population; recount population first summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += dm[p.NEQ*ii + ii]; } if ( fabs(summ-1.0) > 1e-12 && (!p.rta)) { std::cerr << "\nWARNING [populations]: After normalization, total population is not 1, it is " << summ << "!\n"; } #ifdef DEBUG std::cout << "\nAfter normalization, the sum of the populations in the density matrix is " << summ << "\n\n"; #endif // Add initial DM to parameters. p.startDM.resize(2*p.NEQ2); memcpy(&(p.startDM[0]), &(dm[0]), 2*p.NEQ2*sizeof(double)); } // wavefunction else { // Create the array to store the wavefunction in time wfnt = new realtype [2*p.NEQ*(p.numOutputSteps+1)]; initializeArray(wfnt, 2*p.NEQ*(p.numOutputSteps+1), 0.0); // normalize summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2); } #ifdef DEBUG std::cout << "Before normalization, the total population is " << summ << std::endl; #endif summ = 1.0/sqrt(summ); for (int ii = 0; ii < 2*p.NEQ; ii++) { wavefunction[ii] *= summ; } // check total population summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2); } #ifdef DEBUG std::cout << "After normalization, the total population is " << summ << std::endl; #endif if (fabs(summ - 1.0) > 1e-12) { std::cerr << "WARNING: wavefunction not normalized! Total density is " << summ << std::endl; } // Add initial wavefunction to parameters. p.startWfn.resize(2*p.NEQ); memcpy(&(p.startWfn[0]), &(wavefunction[0]), 2*p.NEQ*sizeof(double)); } //// BUILD HAMILTONIAN // //TODO TODO #ifdef DEBUG fprintf(stderr, "Building Hamiltonian.\n"); #endif realtype * H = NULL; H = new realtype [p.NEQ2]; for (int ii = 0; ii < p.NEQ2; ii++) { H[ii] = 0.0; } buildHamiltonian(H, p.energies, V, &p); // add Hamiltonian to p p.H.resize(p.NEQ2); for (int ii = 0; ii < p.NEQ2; ii++) { p.H[ii] = H[ii]; } // create sparse version of H p.H_sp.resize(p.NEQ2); p.H_cols.resize(p.NEQ2); p.H_rowind.resize(p.NEQ2 + 1); int job [6] = {0, 0, 0, 2, p.NEQ2, 1}; int info = 0; mkl_ddnscsr(&job[0], &(p.NEQ), &(p.NEQ), &(p.H)[0], &(p.NEQ), &(p.H_sp)[0], &(p.H_cols)[0], &(p.H_rowind)[0], &info); //// SET UP CVODE VARIABLES #ifdef DEBUG std::cout << "\nCreating N_Vectors.\n"; if (p.wavefunction) { std::cout << "\nProblem size is " << 2*p.NEQ << " elements.\n"; } else { std::cout << "\nProblem size is " << 2*p.NEQ2 << " elements.\n"; } #endif // Creates N_Vector y with initial populations which will be used by CVode// if (p.wavefunction) { y = N_VMake_Serial(2*p.NEQ, wavefunction); } else { y = N_VMake_Serial(2*p.NEQ2, dm); } // put in t = 0 information if (! p.wavefunction) { updateDM(y, dmt, 0, &p); } else { updateWfn(y, wfnt, 0, &p); } // the vector yout has the same dimensions as y yout = N_VClone(y); #ifdef DEBUG realImaginary = fopen("real_imaginary.out", "w"); #endif // Make plot files makePlots(outs, &p); // only do propagation if not just making plots if (! p.justPlots) { // Make outputs independent of time propagation computeGeneralOutputs(outs, &p); // create CVode object // this is a stiff problem, I guess? #ifdef DEBUG std::cout << "\nCreating cvode_mem object.\n"; #endif cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); flag = CVodeSetUserData(cvode_mem, (void *) &p); #ifdef DEBUG std::cout << "\nInitializing CVode solver.\n"; #endif // initialize CVode solver // if (p.wavefunction) { //flag = CVodeInit(cvode_mem, &RHS_WFN, t0, y); flag = CVodeInit(cvode_mem, &RHS_WFN_SPARSE, t0, y); } else { if (p.kinetic) { flag = CVodeInit(cvode_mem, &RHS_DM_RELAX, t0, y); } else if (p.rta) { flag = CVodeInit(cvode_mem, &RHS_DM_RTA, t0, y); //flag = CVodeInit(cvode_mem, &RHS_DM_RTA_BLAS, t0, y); } else if (p.dephasing) { flag = CVodeInit(cvode_mem, &RHS_DM_dephasing, t0, y); } else { //flag = CVodeInit(cvode_mem, &RHS_DM, t0, y); flag = CVodeInit(cvode_mem, &RHS_DM_BLAS, t0, y); } } #ifdef DEBUG std::cout << "\nSpecifying integration tolerances.\n"; #endif // specify integration tolerances // flag = CVodeSStolerances(cvode_mem, p.reltol, p.abstol); #ifdef DEBUG std::cout << "\nAttaching linear solver module.\n"; #endif // attach linear solver module // if (p.wavefunction) { flag = CVDense(cvode_mem, 2*p.NEQ); } else { // Diagonal approximation to the Jacobian saves memory for large systems flag = CVDiag(cvode_mem); } //// CVODE TIME PROPAGATION #ifdef DEBUG std::cout << "\nAdvancing the solution in time.\n"; #endif for (int ii = 1; ii <= p.numsteps; ii++) { t = (p.tout*((double) ii)/((double) p.numsteps)); flag = CVode(cvode_mem, t, yout, &tret, 1); #ifdef DEBUGf std::cout << std::endl << "CVode flag at step " << ii << ": " << flag << std::endl; #endif if ((ii % (p.numsteps/p.numOutputSteps) == 0) || (ii == p.numsteps)) { // show progress in stdout if (p.progressStdout) { fprintf(stdout, "\r%-.2lf percent done", ((double)ii/((double)p.numsteps))*100); fflush(stdout); } // show progress in a file if (p.progressFile) { std::ofstream progressFile("progress.tmp"); progressFile << ((double)ii/((double)p.numsteps))*100 << " percent done." << std::endl; progressFile.close(); } if (p.wavefunction) { updateWfn(yout, wfnt, ii*p.numOutputSteps/p.numsteps, &p); } else { updateDM(yout, dmt, ii*p.numOutputSteps/p.numsteps, &p); } } } #ifdef DEBUG fclose(realImaginary); #endif //// MAKE FINAL OUTPUTS // finalize log file // time(&endRun); currentTime = localtime(&endRun); if (isOutput(outs, "log.out")) { fprintf(log, "Final status of 'flag' variable: %d\n\n", flag); fprintf(log, "Run ended at %s\n", asctime(currentTime)); fprintf(log, "Run took %.3g seconds.\n", difftime(endRun, startRun)); fclose(log); // note that the log file is opened after variable declaration } if (p.progressStdout) { printf("\nRun took %.3g seconds.\n", difftime(endRun, startRun)); } // Compute density outputs. #ifdef DEBUG std::cout << "Computing outputs..." << std::endl; #endif if (p.wavefunction) { computeWfnOutput(wfnt, outs, &p); } else { computeDMOutput(dmt, outs, &p); } #ifdef DEBUG std::cout << "done computing outputs" << std::endl; #endif // do analytical propagation if (p.analytical && (! p.bridge_on)) { computeAnalyticOutputs(outs, &p); } } //// CLEAN UP #ifdef DEBUG fprintf(stdout, "Deallocating N_Vectors.\n"); #endif // deallocate memory for N_Vectors // N_VDestroy_Serial(y); N_VDestroy_Serial(yout); #ifdef DEBUG fprintf(stdout, "Freeing CVode memory.\n"); #endif // free solver memory // CVodeFree(&cvode_mem); #ifdef DEBUG fprintf(stdout, "Freeing memory in main.\n"); #endif // delete all these guys delete [] tkprob; delete [] tlprob; delete [] tcprob; delete [] tbprob; for (int ii = 0; ii <= p.numOutputSteps; ii++) { delete [] allprob[ii]; } delete [] allprob; delete [] k_pops; delete [] c_pops; delete [] b_pops; delete [] l_pops; if (p.bridge_on) { delete [] Vbridge; } else { delete [] Vnobridge; } delete [] k_energies; delete [] c_energies; delete [] b_energies; delete [] l_energies; delete [] wavefunction; delete [] H; for (int ii = 0; ii < p.NEQ; ii++) { delete [] V[ii]; } delete [] V; if (p.wavefunction) { delete [] wfnt; } else { delete [] dm; delete [] dmt; } delete [] times; delete [] qd_est; delete [] qd_est_diag; std::cout << "whoo" << std::endl; return 0; }
void mcwfalg(integer itraj, integer ntraj) { integer i, N, exflag, flag; real eps = 1.0e-6, t, temp; real nl, nr, na, tl, tr, taim, thresh; double sum = 0.0; N = RHS.N; for (i = 1; i <= 2 * N; i++) Ith(y, i) = Ith(ystart, i); /* Initialize ODE solver */ cvode_mem = CVodeMalloc(2 * N, derivs, Ith(tlist, 1), y, (method == 0) ? ADAMS : BDF, (itertype == 0) ? FUNCTIONAL : NEWTON, (nabstol == 1) ? SS : SV, &reltol, abstolp, NULL, NULL, TRUE, iopt, ropt, NULL); if (cvode_mem == NULL) { fatal_error("CVodeMalloc failed.\n"); } /* Call CVDiag */ CVDiag(cvode_mem); q = N_VNew(2 * N, NULL); thresh = genunf(0.0, 1.0); /* Generate target value of norm^2 */ if (nopers == 0) fwrite(&itraj, sizeof(integer), 1, op); if (clrecflag) { temp = itraj; fwrite(&temp, sizeof(real), 1, cp); temp = 0.0; fwrite(&temp, sizeof(real), 1, cp); } tr = Ith(tlist, 1); nr = norm2(N_VDATA(y) - 1, N); if (nopers == 0) fwrite(N_VDATA(y), sizeof(real), 2 * N, op); else operAccum(N_VDATA(y) - 1, N_VDATA(q) - 1, N, tr, 1); for (i = 2; i <= ntimes;) { taim = Ith(tlist, i); tl = tr; nl = nr; flag = CVode1(cvode_mem, taim, y, &tr, ONE_STEP); if (flag != SUCCESS) { sprintf(errmsg, "CVode failed, flag=%d.\n", flag); fatal_error(errmsg); } nr = norm2(N_VDATA(y) - 1, N); for (; i <= ntimes;) { if (tr < taim) { if (nr < thresh) { tr = docollapse(tl, nl, tr, nr, thresh); /* A collapse has * occured */ nr = 1.0; thresh = genunf(0.0, 1.0); /* Generate target value of * norm^2 */ } break; } else { flag = CVode1(cvode_mem, taim, y, &t, NORMAL); /* Interpolate */ if (flag != SUCCESS) { sprintf(errmsg, "CVode failed, flag=%d.\n", flag); fatal_error(errmsg); } na = norm2(N_VDATA(y) - 1, N); if (na < thresh) { tr = docollapse(tl, nl, taim, na, thresh); /* A collapse has * occured */ nr = 1.0; thresh = genunf(0.0, 1.0); /* Generate target value of * norm^2 */ break; } else { /* Write out results */ tl = taim; nl = na; if (nopers == 0) fwrite(N_VDATA(y), sizeof(real), 2 * N, op); else operAccum(N_VDATA(y) - 1, N_VDATA(q) - 1, N, taim, i); i += 1; progress += NHASH; while (progress >= (ntimes - 1) * ntraj) { fprintf(stderr, "#"); progress -= (ntimes - 1) * ntraj; } taim = Ith(tlist, i); } } } } CVodeFree(cvode_mem); }
/* * 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::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); }