Esempio n. 1
0
TimeDiscretizedODESystem<ODESystemTag::FirstOrderImplicitQuasilinear,
                         NonlinearSolverTag::Picard>::
    TimeDiscretizedODESystem(ODE& ode, TimeDisc& time_discretization)
    : _ode(ode),
      _time_disc(time_discretization),
      _mat_trans(createMatrixTranslator<ODETag>(time_discretization))
{
    _M = &NumLib::GlobalMatrixProvider::provider.getMatrix(
        ode.getMatrixSpecifications(), _M_id);
    _K = &NumLib::GlobalMatrixProvider::provider.getMatrix(
        ode.getMatrixSpecifications(), _K_id);
    _b = &NumLib::GlobalVectorProvider::provider.getVector(
        ode.getMatrixSpecifications(), _b_id);
}
Esempio n. 2
0
    Solution run_test(ODE& ode, TimeDisc& timeDisc,
                              const unsigned num_timesteps)
    {
        using ODE_ = ODE;
        using ODET = ODETraits<ODE>;

        Solution sol;

        const int process_id = 0;
        NumLib::TimeDiscretizedODESystem<ODE_::ODETag, NLTag>
                ode_sys(process_id, ode, timeDisc);

        auto linear_solver = createLinearSolver();
        auto conv_crit = std::make_unique<NumLib::ConvergenceCriterionDeltaX>(
            _tol, boost::none, MathLib::VecNormType::NORM2);
        auto nonlinear_solver =
            std::make_unique<NLSolver>(*linear_solver, _maxiter);

        NumLib::TimeLoopSingleODE<NLTag> loop(ode_sys, std::move(linear_solver),
                                              std::move(nonlinear_solver),
                                              std::move(conv_crit));

        const double t0      = ODET::t0;
        const double t_end   = ODET::t_end;
        const double delta_t = (num_timesteps == 0) ? -1.0
                                                    : ((t_end-t0) / num_timesteps);

        DBUG("Running test with %u timesteps of size %g s.", num_timesteps,
             delta_t);

        // initial condition
        GlobalVector x0(ode.getMatrixSpecifications(process_id).nrows);
        ODET::setIC(x0);

        sol.ts.push_back(t0);
        sol.solutions.push_back(x0);

        auto cb = [&sol](const double t, GlobalVector const& x) {
            sol.ts.push_back(t);
            sol.solutions.push_back(x);
        };

        if (num_timesteps > 0)
        {
            EXPECT_TRUE(loop.loop(t0, x0, t_end, delta_t, cb));
        }

        for (auto& x :  sol.solutions)
            MathLib::LinAlg::setLocalAccessibleVector(x);

        return sol;
    }
Esempio n. 3
0
File: RK.C Progetto: Brzous/WindFOAM
Foam::RK::RK(ODE& ode)
:
    ODESolver(ode),
    yTemp_(ode.nEqns()),
    ak2_(ode.nEqns()),
    ak3_(ode.nEqns()),
    ak4_(ode.nEqns()),
    ak5_(ode.nEqns()),
    ak6_(ode.nEqns()),
    yErr_(ode.nEqns()),
    yTemp2_(ode.nEqns())
{}
Esempio n. 4
0
    void run_test(ODE& ode, TimeDisc& timeDisc, const unsigned num_timesteps)
    {
        using ODE_ = ODE;
        using ODET = ODETraits<ODE>;

        NumLib::TimeDiscretizedODESystem<ODE_::ODETag, NLTag>
                ode_sys(ode, timeDisc);

        auto linear_solver = std::unique_ptr<GlobalLinearSolver>{
            new GlobalLinearSolver{"", nullptr}};
        auto conv_crit = std::unique_ptr<NumLib::ConvergenceCriterion>(
            new NumLib::ConvergenceCriterionDeltaX(
                _tol, boost::none, MathLib::VecNormType::NORM2));
        std::unique_ptr<NLSolver> nonlinear_solver(
            new NLSolver(*linear_solver, _maxiter));

        NumLib::TimeLoopSingleODE<NLTag> loop(ode_sys, std::move(linear_solver),
                                              std::move(nonlinear_solver),
                                              std::move(conv_crit));

        const double t0      = ODET::t0;
        const double t_end   = ODET::t_end;
        const double delta_t = (num_timesteps == 0) ? -1.0
                                                    : ((t_end-t0) / num_timesteps);

        INFO("Running test %s with %u timesteps of size %g s.",
             _file_name_part.c_str(), num_timesteps, delta_t);
        init_file(delta_t);

        // initial condition
        Vector x0(ode.getMatrixSpecifications().nrows);
        ODET::setIC(x0);

        write(t0, x0, x0);

        auto cb = [this](const double t, Vector const& x) {
            loopCallback<ODE>(t, x);
        };

        if (num_timesteps > 0)
            EXPECT_TRUE(loop.loop(t0, x0, t_end, delta_t, cb));
    }
Esempio n. 5
0
void Foam::ODESolver::solve
(
    const ODE& ode,
    const scalar xStart,
    const scalar xEnd,
    scalarField& y,
    const scalar eps,
    scalar& hEst
) const
{
    const label MAXSTP = 10000;

    scalar x = xStart;
    scalar h = hEst;
    scalar hNext = 0;
    scalar hPrev = 0;

    for (label nStep=0; nStep<MAXSTP; nStep++)
    {
        ode.derivatives(x, y, dydx_);

        for (label i=0; i<n_; i++)
        {
            yScale_[i] = mag(y[i]) + mag(dydx_[i]*h) + SMALL;
        }

        if ((x + h - xEnd)*(x + h - xStart) > 0.0)
        {
            h = xEnd - x;
            hPrev = hNext;
        }

        hNext = 0;
        scalar hDid;
        solve(ode, x, y, dydx_, eps, yScale_, h, hDid, hNext);

        if ((x - xEnd)*(xEnd - xStart) >= 0.0)
        {
            if (hPrev != 0)
            {
                hEst = hPrev;
            }
            else
            {
                hEst = hNext;
            }

            return;
        }

        h = hNext;
    }

    FatalErrorIn
    (
        "ODESolver::solve"
        "(const ODE& ode, const scalar xStart, const scalar xEnd,"
        "scalarField& yStart, const scalar eps, scalar& hEst) const"
    )   << "Too many integration steps"
        << exit(FatalError);
}
Esempio n. 6
0
Foam::ODESolver::ODESolver(const ODE& ode)
:
    n_(ode.nEqns()),
    yScale_(n_),
    dydx_(n_)
{}
Esempio n. 7
0
void Foam::SIBS::SIMPR
(
    const ODE& ode,
    const scalar xStart,
    const scalarField& y,
    const scalarField& dydx,
    const scalarField& dfdx,
    const scalarSquareMatrix& dfdy,
    const scalar deltaX,
    const label nSteps,
    scalarField& yEnd
) const
{
    scalar h = deltaX/nSteps;

    scalarSquareMatrix a(n_);
    for (register label i=0; i<n_; i++)
    {
        for (register label j=0; j<n_; j++)
        {
            a[i][j] = -h*dfdy[i][j];
        }
        ++a[i][i];
    }

    labelList pivotIndices(n_);
    LUDecompose(a, pivotIndices);

    for (register label i=0; i<n_; i++)
    {
        yEnd[i] = h*(dydx[i] + h*dfdx[i]);
    }

    LUBacksubstitute(a, pivotIndices, yEnd);

    scalarField del(yEnd);
    scalarField ytemp(n_);

    for (register label i=0; i<n_; i++)
    {
        ytemp[i] = y[i] + del[i];
    }

    scalar x = xStart + h;

    ode.derivatives(x, ytemp, yEnd);

    for (register label nn=2; nn<=nSteps; nn++)
    {
        for (register label i=0; i<n_; i++)
        {
            yEnd[i] = h*yEnd[i] - del[i];
        }

        LUBacksubstitute(a, pivotIndices, yEnd);

        for (register label i=0; i<n_; i++)
        {
            ytemp[i] += (del[i] += 2.0*yEnd[i]);
        }

        x += h;

        ode.derivatives(x, ytemp, yEnd);
    }
    for (register label i=0; i<n_; i++)
    {
        yEnd[i] = h*yEnd[i] - del[i];
    }

    LUBacksubstitute(a, pivotIndices, yEnd);

    for (register label i=0; i<n_; i++)
    {
        yEnd[i] += ytemp[i];
    }
}
Esempio n. 8
0
void Foam::SIBS::solve
(
    const ODE& ode,
    scalar& x,
    scalarField& y,
    scalarField& dydx,
    const scalar eps,
    const scalarField& yScale,
    const scalar hTry,
    scalar& hDid,
    scalar& hNext
) const
{
    bool exitflag = false;

    if (eps != epsOld_)
    {
        hNext = xNew_ = -GREAT;
        scalar eps1 = safe1*eps;
        a_[0] = nSeq_[0] + 1;

        for (register label k=0; k<kMaxX_; k++)
        {
            a_[k + 1] = a_[k] + nSeq_[k + 1];
        }

        for (register label iq = 1; iq<kMaxX_; iq++)
        {
            for (register label k=0; k<iq; k++)
            {
                alpha_[k][iq] =
                    pow(eps1, (a_[k + 1] - a_[iq + 1])
                   /((a_[iq + 1] - a_[0] + 1.0)*(2*k + 3)));
            }
        }

        epsOld_ = eps;
        a_[0] += n_;

        for (register label k=0; k<kMaxX_; k++)
        {
            a_[k + 1] = a_[k] + nSeq_[k + 1];
        }

        for (kOpt_ = 1; kOpt_<kMaxX_ - 1; kOpt_++)
        {
            if (a_[kOpt_ + 1] > a_[kOpt_]*alpha_[kOpt_ - 1][kOpt_])
            {
                break;
            }
        }

        kMax_ = kOpt_;
    }

    label k=0;
    scalar h = hTry;
    yTemp_ = y;

    ode.jacobian(x, y, dfdx_, dfdy_);

    if (x != xNew_ || h != hNext)
    {
        first_ = 1;
        kOpt_ = kMax_;
    }

    label km=0;
    label reduct=0;
    scalar maxErr = SMALL;

    for (;;)
    {
        scalar red = 1.0;

        for (k=0; k <= kMax_; k++)
        {
            xNew_ = x + h;

            if (xNew_ == x)
            {
                FatalErrorIn("ODES::SIBS")
                    << "step size underflow"
                    << exit(FatalError);
            }

            SIMPR(ode, x, yTemp_, dydx, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
            scalar xest = sqr(h/nSeq_[k]);

            polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_);

            if (k != 0)
            {
                maxErr = SMALL;
                for (register label i=0; i<n_; i++)
                {
                    maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
                }
                maxErr /= eps;
                km = k - 1;
                err_[km] = pow(maxErr/safe1, 1.0/(2*km + 3));
            }

            if (k != 0 && (k >= kOpt_ - 1 || first_))
            {
                if (maxErr < 1.0)
                {
                    exitflag = true;
                    break;
                }

                if (k == kMax_ || k == kOpt_ + 1)
                {
                    red = safe2/err_[km];
                    break;
                }
                else if (k == kOpt_ && alpha_[kOpt_ - 1][kOpt_] < err_[km])
                {
                    red = 1.0/err_[km];
                    break;
                }
                else if (kOpt_ == kMax_ && alpha_[km][kMax_ - 1] < err_[km])
                {
                    red = alpha_[km][kMax_ - 1]*safe2/err_[km];
                    break;
                }
                else if (alpha_[km][kOpt_] < err_[km])
                {
                    red = alpha_[km][kOpt_ - 1]/err_[km];
                    break;
                }
            }
        }

        if (exitflag)
        {
            break;
        }

        red = min(red, redMin);
        red = max(red, redMax);
        h *= red;
        reduct = 1;
    }

    x = xNew_;
    hDid = h;
    first_=0;
    scalar wrkmin = GREAT;
    scalar scale = 1.0;

    for (register label kk=0; kk<=km; kk++)
    {
        scalar fact = max(err_[kk], scaleMX);
        scalar work = fact*a_[kk + 1];
        if (work < wrkmin)
        {
            scale = fact;
            wrkmin = work;
            kOpt_ = kk + 1;
        }
    }

    hNext = h/scale;

    if (kOpt_ >= k && kOpt_ != kMax_ && !reduct)
    {
        scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX);
        if (a_[kOpt_ + 1]*fact <= wrkmin)
        {
            hNext = h/fact;
            kOpt_++;
        }
    }
}
Esempio n. 9
0
void Foam::KRR4::solve
(
    const ODE& ode,
    scalar& x,
    scalarField& y,
    scalarField& dydx,
    const scalar eps,
    const scalarField& yScale,
    const scalar hTry,
    scalar& hDid,
    scalar& hNext
) const
{
    scalar xTemp = x;
    yTemp_ = y;
    dydxTemp_ = dydx;

    ode.jacobian(xTemp, yTemp_, dfdx_, dfdy_);

    scalar h = hTry;

    for (register label jtry=0; jtry<maxtry; jtry++)
    {
        for (register label i=0; i<n_; i++)
        {
            for (register label j=0; j<n_; j++)
            {
                a_[i][j] = -dfdy_[i][j];
            }

            a_[i][i] += 1.0/(gamma*h);
        }

        LUDecompose(a_, pivotIndices_);

        for (register label i=0; i<n_; i++)
        {
            g1_[i] = dydxTemp_[i] + h*c1X*dfdx_[i];
        }

        LUBacksubstitute(a_, pivotIndices_, g1_);

        for (register label i=0; i<n_; i++)
        {
            y[i] = yTemp_[i] + a21*g1_[i];
        }

        x = xTemp + a2X*h;
        ode.derivatives(x, y, dydx_);

        for (register label i=0; i<n_; i++)
        {
            g2_[i] = dydx_[i] + h*c2X*dfdx_[i] + c21*g1_[i]/h;
        }

        LUBacksubstitute(a_, pivotIndices_, g2_);

        for (register label i=0; i<n_; i++)
        {
            y[i] = yTemp_[i] + a31*g1_[i] + a32*g2_[i];
        }

        x = xTemp + a3X*h;
        ode.derivatives(x, y, dydx_);

        for (register label i=0; i<n_; i++)
        {
            g3_[i] = dydx[i] + h*c3X*dfdx_[i] + (c31*g1_[i] + c32*g2_[i])/h;
        }

        LUBacksubstitute(a_, pivotIndices_, g3_);

        for (register label i=0; i<n_; i++)
        {
            g4_[i] = dydx_[i] + h*c4X*dfdx_[i]
                + (c41*g1_[i] + c42*g2_[i] + c43*g3_[i])/h;
        }

        LUBacksubstitute(a_, pivotIndices_, g4_);

        for (register label i=0; i<n_; i++)
        {
            y[i] = yTemp_[i] + b1*g1_[i] + b2*g2_[i] + b3*g3_[i] + b4*g4_[i];
            yErr_[i] = e1*g1_[i] + e2*g2_[i] + e3*g3_[i] + e4*g4_[i];
        }

        x = xTemp + h;

        if (x == xTemp)
        {
            FatalErrorIn("ODES::KRR4")
                << "stepsize not significant"
                << exit(FatalError);
        }

        scalar maxErr = 0.0;
        for (register label i=0; i<n_; i++)
        {
            maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
        }
        maxErr /= eps;

        if (maxErr <= 1.0)
        {
            hDid = h;
            hNext = (maxErr > errcon ? safety*h*pow(maxErr, pgrow) : grow*h);
            return;
        }
        else
        {
            hNext = safety*h*pow(maxErr, pshrink);
            h = (h >= 0.0 ? max(hNext, shrink*h) : min(hNext, shrink*h));
        }
    }

    FatalErrorIn("ODES::KRR4")
        << "exceeded maxtry"
        << exit(FatalError);
}
Esempio n. 10
0
Foam::ODESolver::ODESolver(ODE& ode)
:
    ode_(ode),
    yScale_(ode.nEqns()),
    dydx_(ode.nEqns())
{}