Beispiel #1
0
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);
}
Beispiel #2
0
  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");
    }
  }
Beispiel #3
0
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);
}
Beispiel #5
0
  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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
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);
    }
}
Beispiel #11
0
  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);
  }
Beispiel #12
0
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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
void FCV_DIAG(int *ier)
{
  *ier = CVDiag(CV_cvodemem);

  CV_ls = 3;
}
Beispiel #15
0
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);
}
Beispiel #16
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;
}
Beispiel #17
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);
}
Beispiel #18
0
/*
 * 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);
}
Beispiel #19
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);
  }