Текст подпрограммы и версий
de15r_c.zip , de15d_c.zip
Тексты тестовых примеров
tde15r_c.zip , tde15d_c.zip

Подпрограмма:  de15r_c

Назначение

Выполнение одного шага численного интегрирования системы обыкновенных дифференциальных уравнений первого порядка методом Рунге - Кутта - Фельберга.

Математическое описание

Выполняется один шаг численного интегрирования системы М обыкновенных дифференциальных уравнений первого порядка

          Y ' = F (X, Y) ,
          Y = ( y1, ... , yM ) ,
          F = ( f1 (X, y1, ... , yM), ... , fM (X, y1, ... , yM) ) 

методом Рунге - Кутта - Фельберга пятого порядка точности. По заданному значению решения YX в узле Xn вычисляется значение этого решения в узле Xn + H. Bсе компоненты решения вычисляются с контролем точности по меpе погрешности, который заключается в следующем.

Если некоторая компонента приближенного решения по абсолютной величине не меньше некоторой наперед заданной константы Р, то контроль точности для этой компоненты ведется по относительной погрешности, иначе - по абсолютной. B качестве абсолютной погрешности решения принимается оценка главного члена асимптотического разложения погрешности метода на шаге, получаемая при вычитании двух выражений, представляющих приближенные значения решения пятого и четвертого порядка точности. При этом на одном шаге интегрирования для определения решения и погрешности используются всего шесть вычислений правой части системы. Значение H может быть меньше или равно значению шага интегрирования, задаваемому пользователем при обращении к подпрограмме.

Дж.Форсайт, М.Малькольм, К.Моулер, Машинные методы математических вычислений, "Мир", M., 1980.

Использование

    int de15r_c (S_fp f, integer *m, integer *jstart, real *hmin,
                 real *eps, real *p, real *yx, real *x, real *h, logical *bul,
                 real *xp, real *yp, real *dy, real *r1, real *r2, real *r3, real *r4,
                 integer *ierr)

Параметры

f - имя подпрограммы вычисления значений правой части дифференциального уравнения. Первый оператоp подпрограммы должен иметь вид:
int f (float *x, float *y, float *dy, int *m).
Здесь: x, y - значения независимой и зависимой переменных, соответственно. Вычисленное значение правой части должно быть помещено в dy. B случае системы уравнений, т.е. когда m ≠ 1 , параметры y и dy представляют массивы длины m (тип параметров x, y и dy: вещественный);
m - количество уравнений в системе (тип: целый);
jstart - целый указатель режима использования подпрограммы, имеющий следующие значения:
0,+1 - выполнить один шаг интегрирования системы дифференциальных уравнений для значений независимой и зависимой переменных и шага интегрирования, заданных параметрами x, yx и h, соответственно;
-1 - повторить последний шаг интегрирования с новыми значениями паpаметpов h и/или hmin;
  на выходе из подпрограммы jstart полагается равным  + 1;
hmin - минимальное значение абсолютной величины шага, котоpое разрешается использовать при интегрировании данной системы уравнений (тип: вещественный);
eps - допустимая меpа погрешности, с которой тpебуется вычислить все компоненты решения (тип: вещественный);
p - граница перехода, используемая при оценке меры погрешности решения (тип: вещественный);
yx, x - заданные вещественные значения решения и соответствующее ему значение аргумента; в pезультате работы подпрограммы в x получается новое значение аргумента, а в yx - соответствующее значение решения; в случае системы уравнений, т.е. когда m ≠ 1, yx задается одномерным массивом длины m;
h - вещественная переменная, содержащая значение шага интегрирования; если для этого значения шага точность приближенного решения достигается, то именно он и реализуется подпрограммой, иначе этот шаг уменьшается подпрограммой до тех пор, пока не будет достигнута заданная точность eps; на выходе из подпрограммы h содержит рекомендуемое подпрограммой значение следущего шага интегрирования, определяемое ею с целью достижения более экономного способа интегрирования;
bul - логическая переменная, значение которой при обращении к подпрограмме полагается равным TRUE_, если заданный в h шаг выводит в конец интервала интегрирования, и FALSE_ в противном случае; в результате работы подпрограммы bul pавно FALSE_, если вместо исходного шага интегрирования был реализован меньший шаг; в противном случае, т.е. когда был выполнен именно заданный при обращении в h шаг, значение параметра bul не меняется;
xp, yp - вещественные рабочая переменная и одномерный рабочий массив длины m; значения параметpов xp, yp на выходе из подпрограммы pавны тем значениям, которые имели параметры x, yx, соответственно, при входе в нее (т.е. предыдущий узел и решение в нем);
            dy -
         r1, r2  
         r3, r4  
одномерные вещественные рабочие массивы длины m;
ierr - целая переменная, значение которой в pезультате работы подпрограммы полагается равным 65, если какая - нибудь компонента pешения не может быть вычислена с требуемой точностью eps; в этом случае последний шаг интегрирования системы можно повторить обращением к подпрограмме с новыми значениями параметров  h, hmin и значением  jstart = - 1.

Версии

de15d_c - выполнение одного шага численного интегрирования системы обыкновенных дифференциальных уpавнений первого порядка методом Рунге - Кутта - Фельберга с удвоенным числом значащих цифр. При этом параметры hmin, eps, p, yx, x, h, xp, yp, dy, r1, r2, r3, r4 и параметры x, y и dy в подпрограмме f должны иметь тип double.

Вызываемые подпрограммы

utde16_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de15r_c.
utde17_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de15d_c.

Замечания по использованию

 

B общем случае заданая точность не гарантируется.

При работе подпрограммы значения параметров m, hmin, eps, p сохраняются.

При работе подпрограммы счета правой части f значения параметров x, y и m не должны изменяться.

При обращении к подпрограмме со значением jstart = - 1 в качестве исходных значений аргумента и решения принимаются значения параметров xp и yp, соответственно, т.е. те значения, которые эти параметры получили после самого последнего обращения к подпрограмме с неотрицательным значением  jstart.

Пример использования

          y1'  =  -y2 - 0.1 x - 0.9
          y2'  =   y1 - 0.1 x - 1.1

          y1  =   1 ,     y2 (0)  =  -2 ,     0 ≤ x ≤ π

  Точное решение системы:

          y1  =   0.1 x + sin x  +  1. ,     y2  =  -0.1 x - cos x - 1. 

Приводятся подпрограмма вычисления значений правой части системы и фрагмент вызывающей программы, а также результаты счета.

int main(void)
{
    /* Builtin functions */
    double sin(double), cos(double);

    /* Local variables */
    extern int de15r_c(U_fp, int *, int *, float *, float *, float *,
                       float *, float *, float *, logical *, float *,
                       float *, float *, float *, float *, float *,
                       float *, int *);
    static float hmin;
    static int ierr;
    static float h__;
    static int m;
    extern int ffelb_c();
    static float p, x, r1[2], r2[2], r3[2], r4[2], y1, y2;
    static int ih;
    static float dy[2], xp, yp[2], yx[2];
    static int jstart;
    static logical bul;
    static float eps;

    m = 2;
    jstart = 0;
    hmin = 1e-12f;
    eps = 1e-5f;
    p = 100.f;
    yx[0] = 1.f;
    yx[1] = -2.f;
    x = 0.f;
    h__ = .01f;
    bul = FALSE_;
    ih = 0;
L6:
    de15r_c((U_fp)ffelb_c, &m, &jstart, &hmin, &eps, &p, yx, &x, &h__, &bul,
            &xp, yp, dy, r1, r2, r3, r4, &ierr);

    printf("\n %5i \n", ierr);
    if (ierr != 0) {
        goto L20;
    }
    y1 = x * .1f + (float)sin(x) + 1.f;
    y2 = x * -.1f - (float)cos(x) - 1.f;

    printf("\n %16.7e \n", x);
    printf("\n %16.7e %16.7e \n", yx[0], yx[1]);
    printf("\n %16.7e \n", h__);
    printf("\n %16.7e %16.7e \n", y1, y2);
    ++ih;
    switch (ih) {
        case 1:  goto L6;
        case 2:  goto L6;
        case 3:  goto L103;
        case 4:  goto L104;
        case 5:  goto L105;
        case 6:  goto L6;
        case 7:  goto L20;
    }
L103:
    jstart = -1;
    h__ = -.005f;
    goto L6;
L104:
    jstart = -1;
    h__ = .02f;
    goto L6;
L105:
    jstart = -1;
    h__ = .01f;
    goto L6;
L20:
    return 0;
} /* main */

int ffelb_c(float *x, float *y, float *z, int *m)
{
    static float r__;

    /* Parameter adjustments */
    --z__;
    --y;

    /* Function Body */
    r__ = *x * .1f;
    z__[1] = -y[2] - r__ - .9f;
    z__[2] = y[1] - r__ - 1.1f;
    return 0;
} /* ffelb_c */


Результаты:

   после первого обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          9.999999999991-03    1.010999833334 + 00   -2.000950000420 + 00
                   h__                                y1                                  y2
          1.999999999998-02    1.010999833334 + 00   -2.000950000416 + 00

   после второго обращения к подпрограмме -

                   x                                  yx (1)                            yx (2)
          2.999999999997-02    1.032995500202 + 00   -2.002550033754 + 00
                   h__                                y1                                  y2
          3.999999999996-02    1.032995500202 + 00   -2.002550033747 + 00

   после третьего обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          6.999999999994-02    1.076942847336 + 00   -2.004551000264 + 00
                   h__                                y1                                  y2
          7.999999999993-02    1.076942847336 + 00   -2.004551000253 + 00

   после четвертого обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          2.499999999998-02    1.027497395913 + 00   -2.002187516282 + 00
                   h__                                y1                                  y2
         -9.999999999991-03    1.027497395913 + 00   -2.002187516275 + 00

   после пятого обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          4.999999999995-02    1.054979169268 + 00   -2.003750260403 + 00
                   h__                                y1                                  y2
          3.999999999996-02    1.054979169270 + 00   -2.003750260392 + 00

   после шестого обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          3.999999999996-02    1.043989334185 + 00   -2.003200106668 + 00
                   h__                                y1                                  y2
          1.999999999998-02    1.043989334186 + 00   -2.003200106661 + 00

   после седьмого обращения к подпрограмме -
                   x                                  yx (1)                            yx (2)
          5.999999999995-02    1.065964006477 + 00   -2.004200539945 + 00
                   h__                                y1                                  y2
          3.999999999996-02    1.065964006479 + 00   -2.004200539934 + 00