Example #1
0
        protected void rkck(List <double> y,
                            List <double> dydx,
                            ref double x,
                            double h,
                            ref List <double> yout,
                            ref List <double> yerr,
                            OdeFct derivs)
        {
            int           n     = y.Count;
            List <double> ak2   = new List <double>(n),
                          ak3   = new List <double>(n),
                          ak4   = new List <double>(n),
                          ak5   = new List <double>(n),
                          ak6   = new List <double>(n),
                          ytemp = new List <double>(n);

            // first step
            for (int i = 0; i < n; i++)
            {
                ytemp[i] = y[i] + b21 * h * dydx[i];
            }

            // second step
            ak2 = derivs(x + a2 * h, ytemp);
            for (int i = 0; i < n; i++)
            {
                ytemp[i] = y[i] + h * (b31 * dydx[i] + b32 * ak2[i]);
            }

            // third step
            ak3 = derivs(x + a3 * h, ytemp);
            for (int i = 0; i < n; i++)
            {
                ytemp[i] = y[i] + h * (b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
            }

            // fourth step
            ak4 = derivs(x + a4 * h, ytemp);
            for (int i = 0; i < n; i++)
            {
                ytemp[i] = y[i] + h * (b51 * dydx[i] + b52 * ak2[i] + b53 * ak3[i] + b54 * ak4[i]);
            }

            // fifth step
            ak5 = derivs(x + a5 * h, ytemp);
            for (int i = 0; i < n; i++)
            {
                ytemp[i] = y[i] + h * (b61 * dydx[i] + b62 * ak2[i] + b63 * ak3[i] + b64 * ak4[i] + b65 * ak5[i]);
            }

            // sixth step
            ak6 = derivs(x + a6 * h, ytemp);
            for (int i = 0; i < n; i++)
            {
                yout[i] = y[i] + h * (c1 * dydx[i] + c3 * ak3[i] + c4 * ak4[i] + c6 * ak6[i]);
                yerr[i] = h * (dc1 * dydx[i] + dc3 * ak3[i] + dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i]);
            }
        }
Example #2
0
        /*! Integrate the ode from \f$ x1 \f$ to \f$ x2 \f$ with
         *  initial value condition \f$ f(x1)=y1 \f$.
         *
         *  The ode is given by a function \f$ F: R \times K^n
         *  \rightarrow K^n \f$ as \f$ f'(x) = F(x,f(x)) \f$, $K=R,
         *  C$ */
        public List <double> value(OdeFct ode,
                                   List <double> y1,
                                   double x1,
                                   double x2)
        {
            int           n = y1.Count;
            List <double> y = new List <double>(y1);
            List <double> yScale = new List <double>(n);
            double        x = x1;
            double        h = h1_ * (x1 <= x2 ? 1 : -1);
            double        hnext = 0, hdid = 0;

            for (int nstp = 1; nstp <= ADAPTIVERK_MAXSTP; nstp++)
            {
                List <double> dydx = ode(x, y);
                for (int i = 0; i < n; i++)
                {
                    yScale[i] = Math.Abs(y[i]) + Math.Abs(dydx[i] * h) + ADAPTIVERK_TINY;
                }
                if ((x + h - x2) * (x + h - x1) > 0.0)
                {
                    h = x2 - x;
                }
                rkqs(y, dydx, ref x, h, eps_, yScale, ref hdid, ref hnext, ode);

                if ((x - x2) * (x2 - x1) >= 0.0)
                {
                    return(y);
                }

                if (Math.Abs(hnext) <= hmin_)
                {
                    Utils.QL_FAIL("Step size (" + hnext + ") too small ("
                                  + hmin_ + " min) in AdaptiveRungeKutta");
                }
                h = hnext;
            }
            Utils.QL_FAIL("Too many steps (" + ADAPTIVERK_MAXSTP
                          + ") in AdaptiveRungeKutta");
            return(null);
        }
Example #3
0
        protected void rkqs(List <double> y,
                            List <double> dydx,
                            ref double x,
                            double htry,
                            double eps,
                            List <double> yScale,
                            ref double hdid,
                            ref double hnext,
                            OdeFct derivs)
        {
            int           n = y.Count;
            double        errmax, xnew;
            List <double> yerr = new List <double>(n), ytemp = new List <double>(n);

            double h = htry;

            for (;;)
            {
                rkck(y, dydx, ref x, h, ref ytemp, ref yerr, derivs);
                errmax = 0.0;
                for (int i = 0; i < n; i++)
                {
                    errmax = Math.Max(errmax, Math.Abs(yerr[i] / yScale[i]));
                }
                errmax /= eps;
                if (errmax > 1.0)
                {
                    double htemp1 = ADAPTIVERK_SAFETY * h * Math.Pow(errmax, ADAPTIVERK_PSHRINK);
                    double htemp2 = h / 10;
                    // These would be std::min and std::max, of course,
                    // but VC++14 had problems inlining them and caused
                    // the wrong results to be calculated.  The problem
                    // seems to be fixed in update 3, but let's keep this
                    // implementation for compatibility.
                    double max_positive = htemp1 > htemp2 ? htemp1 : htemp2;
                    double max_negative = htemp1 < htemp2 ? htemp1 : htemp2;
                    h    = ((h >= 0.0) ? max_positive : max_negative);
                    xnew = x + h;
                    if (xnew.IsEqual(x))
                    {
                        Utils.QL_FAIL("Stepsize underflow (" + h + " at x = " + x
                                      + ") in AdaptiveRungeKutta::rkqs");
                    }
                    continue;
                }
                else
                {
                    if (errmax > ADAPTIVERK_ERRCON)
                    {
                        hnext = ADAPTIVERK_SAFETY * h * Math.Pow(errmax, ADAPTIVERK_PGROW);
                    }
                    else
                    {
                        hnext = 5.0 * h;
                    }
                    x += (hdid = h);
                    for (int i = 0; i < n; i++)
                    {
                        y[i] = ytemp[i];
                    }
                    break;
                }
            }
        }