Ejemplo n.º 1
0
void ForwardEulerSolver::solve(double &pVoi, double pVoiEnd) const
{
    // Y_n+1 = Y_n + h * f(t_n, Y_n)

    double voiStart = pVoi;

    int stepNumber = 0;
    double realStep = mStep;

    while (!qFuzzyCompare(pVoi, pVoiEnd)) {
        // Check that the time step is correct

        if (pVoi+realStep > pVoiEnd) {
            realStep = pVoiEnd-pVoi;
        }

        // Compute f(t_n, Y_n)

        mComputeRates(pVoi, mConstants, mRates, mStates, mAlgebraic);

        // Compute Y_n+1

        for (int i = 0; i < mRatesStatesCount; ++i) {
            mStates[i] += realStep*mRates[i];
        }

        // Advance through time

        if (!qFuzzyCompare(realStep, mStep)) {
            pVoi = pVoiEnd;
        } else {
            pVoi = voiStart+(++stepNumber)*mStep;
        }
    }
}
Ejemplo n.º 2
0
void CvodeSolver::solve(double &pVoi, const double &pVoiEnd) const
{
    // Solve the model

    CVode(mSolver, pVoiEnd, mStatesVector, &pVoi, CV_NORMAL);

    // Compute the rates one more time to get up-to-date values for the rates
    // Note: another way of doing this would be to copy the contents of the
    //       calculated rates in rhsFunction, but that's bound to be more time
    //       consuming since a call to CVode is likely to generate at least a
    //       few calls to rhsFunction, so that would be quite a few memory
    //       transfers while here we 'only' compute the rates one more time,
    //       so...

    mComputeRates(pVoiEnd, mConstants, mRates,
                  N_VGetArrayPointer_Serial(mStatesVector), mAlgebraic);
}
Ejemplo n.º 3
0
void FourthOrderRungeKuttaSolver::solve(double &pVoi,
                                        const double &pVoiEnd) const
{
    // k1 = h * f(t_n, Y_n)
    // k2 = h * f(t_n + h / 2, Y_n + k1 / 2)
    // k3 = h * f(t_n + h / 2, Y_n + k2 / 2)
    // k4 = h * f(t_n + h, Y_n + k3)
    // Y_n+1 = Y_n + k1 / 6 + k2 / 3 + k3 / 3 + k4 / 6

    // Note: the algorithm hereafter doesn't compute k1, k2, k3 and k4 as such
    //       and this simply for performance reasons...

    static const double OneOverThree = 1.0/3.0;
    static const double OneOverSix   = 1.0/6.0;

    double voiStart = pVoi;

    int stepNumber = 0;
    double realStep = mStep;
    double realHalfStep = 0.5*realStep;

    while (pVoi != pVoiEnd) {
        // Check that the time step is correct

        if (pVoi+realStep > pVoiEnd) {
            realStep = pVoiEnd-pVoi;
            realHalfStep = 0.5*realStep;
        }

        // Compute f(t_n, Y_n)

        mComputeRates(pVoi, mConstants, mRates, mStates, mAlgebraic);

        // Compute k1 and Yk1

        for (int i = 0; i < mRatesStatesCount; ++i) {
            mK1[i]    = mRates[i];
            mYk123[i] = mStates[i]+realHalfStep*mK1[i];
        }

        // Compute f(t_n + h / 2, Y_n + k1 / 2)

        mComputeRates(pVoi+realHalfStep, mConstants, mRates, mYk123, mAlgebraic);

        // Compute k2 and Yk2

        for (int i = 0; i < mRatesStatesCount; ++i) {
            mK23[i]   = mRates[i];
            mYk123[i] = mStates[i]+realHalfStep*mK23[i];
        }

        // Compute f(t_n + h / 2, Y_n + k2 / 2)

        mComputeRates(pVoi+realHalfStep, mConstants, mRates, mYk123, mAlgebraic);

        // Compute k3 and Yk3

        for (int i = 0; i < mRatesStatesCount; ++i) {
            mK23[i]   += mRates[i];
            mYk123[i]  = mStates[i]+realStep*mK23[i];
        }

        // Compute f(t_n + h, Y_n + k3)

        mComputeRates(pVoi+realStep, mConstants, mRates, mYk123, mAlgebraic);

        // Compute k4 and therefore Y_n+1

        for (int i = 0; i < mRatesStatesCount; ++i)
            mStates[i] += realStep*(OneOverSix*(mK1[i]+mRates[i])+OneOverThree*mK23[i]);

        // Advance through time

        if (realStep != mStep)
            pVoi = pVoiEnd;
        else
            pVoi = voiStart+(++stepNumber)*mStep;
    }
}