Exemple #1
0
    public static int general_driver(
        Func <Func <double, vector, vector>, double,
              vector, double, vector[]> stepper,
        Func <double, vector, vector> f,
        double a,
        ref vector y,
        double b,
        double h,         // Starting step size
        double acc,
        double eps,
        List <double> ts = null,
        List <vector> ys = null
        )
    {
        // The current posistion, set to starting condition:
        double t  = a;
        vector yt = y;         // Not needed?

        if (ts != null)
        {
            ts.Add(t);
        }
        if (ys != null)
        {
            ys.Add(yt);
        }
        vector err = new vector(y.size);

        vector[] res;
        // Step untill less than one step is needed:
        int steps = 0;

        while (t < b - h)
        {
            steps++;
            //Write($"\nStep nr. {steps}, h = {h}\n");
            // Do the step:
            res = stepper(f, t, y, h);
            yt  = res[0];
            err = res[1];
            // Calculate the current step tolerance:
            vector tau_is = (acc + eps * yt.abs()) * Sqrt(h / (b - a));

            // Asses if the error of the step is within the tolerance
            // and calculate the ratio of the tolerance and the error
            // for each entry.
            bool   errAccepted = true;
            vector tolRatios   = new vector(err.size);
            for (int i = 0; i < tau_is.size; i++)
            {
                if (Abs(err[i]) > Abs(tau_is[i]))
                {
                    errAccepted = false;
                }
                tolRatios[i] = Abs(tau_is[i]) / Abs(err[i]);
            }

            // Is error estimate lower than tolerance?
            // Then step is accepted, t and yt
            if (errAccepted)
            {
                // Update t and y:
                t += h;
                y  = yt;
                if (ts != null)
                {
                    ts.Add(t);
                }
                if (ys != null)
                {
                    ys.Add(yt);
                }
            }
            else
            {
                // Don't change t and yt.
            }
            // Update h: (vector.min() is a new method I implemented myself)
            double h_factor = Pow(tolRatios.min(), 0.25) * 0.95;
            h = (h_factor < 2)?h_factor * h:2 * h;
        }
        // Do the final step to reach b: (For now, there is a chance that
        // the error gets too large in this step... But test this code
        // first)
        double h_final = b - t;

        res = stepper(f, t, y, h_final);
        yt  = res[0];
        err = res[1];
        y   = yt;
        if (ts != null)
        {
            ts.Add(t + h_final);
        }
        if (ys != null)
        {
            ys.Add(yt);
        }
        return(steps);
    }