Текст подпрограммы и версий
de42r_c.zip , de42d_c.zip , de48r_c.zip , de48d_c.zip
Тексты тестовых примеров
tde42r_c.zip , tde42d_c.zip , tde48r_c.zip , tde48d_c.zip

Подпрограмма:  de42r_c (версия de48r_c)

Назначение

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

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

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

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

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

По значению решения  YX в узле  Xn вычисляется значение этого решения в узле  Xn + H. При этом, если  Xn является началом  XN интервала интегрирования, то для вычисления решения в   XN + H требуется еще и значение производной решения в  XN. Вместе с решением подпрограмма определяет также всю информацию, необходимую для вычисления приближенного решения в любом следующем узле.

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

Березин И.С., Жидков Н.П. Методы вычислений, т.2, Физматгиз, М., 1960.

Бахвалов H.C., Численные методы, т.1, "Hаука", 1975.

Жоголев E.A. Программа интегрирования систем обыкновенных дифференциальных уравнений второго порядка методом Штермера. Сб. "Вычислительные методы и программирование", вып. 1, Изд - во МГУ, 1962.

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

    int de42r_c (S_fp f, integer *m, integer *jstart, real *hmin,
                 real *hmax, real *eps, real *p, real *yx, real *x, real *dy,
                 real *h, logical *bul, real *delty, real *df, real *rfn, real *rf,
                 real *yp, real *dyp, integer *ierr)

Параметры

f - имя подпрограммы вычисления значений правой части дифференциальных уравнений. Первый оператор подпрограммы должен иметь вид:
 

int f (float *x, float *y, float *dy, int *m)

Здесь:  x, y  -  значения независимой и зависимой переменных, соответственно; вычисленное значение правой части должно быть помещено в  dy; в случае системы уравнений, т.е. когда  m ≠ 1, параметры  y и  dy представляют одномерные массивы длиной  m (тип параметров  x, y, dy: вещественный);

m - количество уравнений в системе (тип: целый);
jstart - целый указатель режима использования подпрограммы имеющий следующие значения:
0 - первое обращение к подпрограмме должно быть выполнено с нулевым значением   jstart;
+1 - выполнить один шаг интегрирования системы дифференциальных уравнений для значений независимой и зависимой переменных и шага интегрирования, заданных параметрами  x, yx и  h, соответственно;
-1 - повторить последний шаг интегрирования с новыми значениями праметров  h и / или  hmin;
  на выходе из подпрограммы  jstart полагается равным + 1;
hmin - минимальное значение абсолютной величины шага, котоpое разрешается использовать при интегрировании данной системы уравнений (тип: вещественный);
hmax - максимальное значение абсолютной величины шага, котоpое разрешается использовать при интегрировании данной системы уравнений (тип: вещественный);
eps - допустимая меpа погрешности, с которой требуется вычислить все компоненты решения (тип: вещественный);
p - граница перехода, используемая при оценке меры погрешности приближенного решения (тип: вещественный);
x, yx - заданные вещественные значения аргумента и решения в нем; в результате работы подпрограммы в  x получается новое значение аргумента, а в  yx  -  соответствующее значение решения; в случае системы уравнений, т.е. когда  m ≠ 1,  yx задается одномерным массивом длины  m;
dy - одномерный вещественный рабочий массив длины  m; при первом обращении к подпрограмме (т.е. со значением  jstart = 0) в этом массиве задается значение производной pешения в начальном узле интервала интегрирования;
h - вещественная переменная, содержащая значение шага интегрирования; если для этого значения шага точность приближенного значения достигается, то именно он и реализуется подрограммой, иначе этот шаг уменьшается подпрограммой до тех пор, пока не будет достигнута заданная точность  eps; на выходе из подпрограммы  h содержит pекомендуемое подпрограммой значение следующего шага интегрирования, определяемое ею с целью достижения более экономного способа интегрирования;
bul - логическая переменная, значение которой при обращении к подпрограмме полагается равным TRUE_, если заданный в  h шаг выводит в конец интервала интегрирования, и FALSE_ в противном случае; в результате работы подпрограммы  bul pавно FALSE_, если вместо исходного шага интегрирования был реализован меньший шаг; в противном случае, т.е. когда был выполнен именно заданный при обращении в  h шаг, значение паpаметpа  bul не меняется;
       delty -
       rfn, rf  
       yp, dyp  
одномерные вещественные рабочие массивы длины  m;
df - двумерный вещественный рабочий массив размеpа  m * 5, в котоpом запоминаются значения правой части системы и ее разностей до четвертого порядка включительно, умноженные на  h 2 / 12;
ierr - целая переменная, служащая для сообщения об ошибках, обнаруженных в процессе работы подпрограммы; при этом:
ierr=65 - когда интегрирование системы выполнено с заданным в  hmin минимальным шагом, но требуемая точность полученного при этом значения  yx решения не достигнута; в этом случае последний шаг интегрирования системы можно повторить обращением к программе с новыми значениями параметров  h и   hmin и со значением  jstart = -1;
ierr=66 - когда решение не может быть вычислено с требуемой точностью   eps при первом обращении к подпрограмме (т.е. со значением   jstart = 0); в этом случае интегрирование системы можно начать сначала обращением к подпрограмме с новыми значениями параметpов  h и  hmin и со значением   jstart = 0.

Версии

de42d_c - выполнение одного шага численного интегрирования системы обыкновенных дифференциальных уpавнений второго порядка методом Штермера с повышенной точностью. При этом параметры  hmin, hmax, eps, p, yx, x, dy, h, delty, df, rfn, rf, yp, dyp и параметры  x, y и  dy в подпрограмме  f должны иметь тип double.
de48r_c - назначение этой подпрограммы такое же, как и подпрограммы de42r_c, но схема организации вычислений в ней несколько иная, чем в de42r_c, а именно: во - первых, исправленное и предсказанное значения решения вычисляются через значения некоторой промежуточной переменной, введение которой позволяет уменьшить вычислительную погрешность в приближенном значении решения, во - вторых, для вычисления приближенного решения на одном шаге используется на одно вычисление правой части уравнения больше, чем в подпрограмме de42r_c. Таким образом обеспечивается возможность вычислить решение уравнения более точно, чем в de42r_c.
de48d_c - тоже, что и de48r_c, но все вычисления ведутся с удвоенным числом значащих цифр; при этом параметры  hmin, hmax, eps, p, yx, x, dy, h, delty, df, rfn, rf, yp, dyp и параметры  x, y и  dy в подпрограмме  f должны иметь тип double.

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

de34r_c - построение начальных значений при интегрировании системы обыкновенных дифференциальных уравнений второго порядка методом Штермера с контролем точности.
de34d_c - построение начальных значений с повышенной точностью при интегрировании системы обыкновенных дифференциальных уравнений второго порядка методом Штермера с контролем точности.
       de18r_c -
       de18d_c  
построение начальных значений при интегрировании системы обыкновенных дифференциальных уравнений второго порядка методом Штермера, преобразованным к виду, где влияние вычислительной погрешности меньше.
      utde12_c -
      utde13_c  
      utde16_c  
      utde17_c  
подпрограммы выдачи диагностических сообщений.
 

Подпрограммы de34r_c и utde12_c вызываются при работе подпрограммы de42r_c, а подпрограммы de34d_c и utde13_c - при работе подпрограммы de42d_c.

Подпрограммы de18r_c и utde16_c вызываются при работе подпрограммы de48r_c, подпрограммы de18d_c и utde17_c - при pаботе de48d_c.

Kpоме того, de42r_c и de42d_c используют рабочие подпрограммы de28rs_c, de42rp_c и de28ds_c, de42dp_c.

Подпрограммы de48r_c и de48d_c используют рабочие подпрограммы de48rp_c и de48dp_c, соответственно.

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

 

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

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

При многократном использовании подпрограммы или ее веpсий для вычисления решения системы уравнений на отрезке необходимо выполнять следующие требования:

- значения параметров  m, yx, x и значения рабочих массивов, задаваемых параметрами  dy, df, yp, dyp не должны изменяться в вызывающей программе между последовательными обращениями к подпрограмме или ее версиям;

- значение параметра  hmax не должно быть слишком большим, т.к. в противном случае величина шага интегрирования может достичь таких размеров, которые приведут к абсолютной неустойчивости численного метода.

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

     y1'' = - y1   ,
     y2'' = - y2   ;

     y1 (3/4 π) = √2 / 2   ,      y2 (3/4 π) = - √2 / 2   ,
     y1' (3/4 π) = - √2 / 2   ,   y2' (3/4 π) = - √2 / 2   .

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

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

    /* Local variables */
    extern int de42r_c(U_fp, int *, int *, float *, float *, float *,
                       float *, float *, float *, float *, float *,
                       logical *, float *, float *, float *, float *,
                       float *, float *, int *);
    static float hmin, hmax;
    static int ierr;
    extern int f_c();
    static float h__;
    static int m;
    static float p, x, y[2], delty[2], y1, y2, df[10];
    static int ih;
    static float rf[2], dy[2], yp[2];
    static int jstart;
    static logical bul;
    static float rfn[2], eps, dyp[2];

    h__ = -.01f;
    hmin = 1e-5f;
    m = 2;
    x = 2.3561947499999998f;
    y[0] = (float)sqrt(2.f) / 2.f;
    y[1] = -y[0];
    eps = 1e-4f;
    dy[0] = y[1];
    dy[1] = -y[0];
    ih = 0;
    bul = FALSE_;
    jstart = 0;
    p = 100.f;
    hmax = .1f;
l6:
    de42r_c((U_fp)f_c, &m, &jstart, &hmin, &hmax, &eps, &p, y, &x, dy, &h__,
            &bul, delty, df, rfn, rf, yp, dyp, &ierr);
    ++ih;
    y1 = (float)sin(x);
    y2 = (float)cos(x);

    printf("\n %16.7e %16.7e %16.7e \n", x, y[0], y[1]);
    printf("\n %16.7e %16.7e %16.7e \n\n", h__, y1, y2);
    if (ih == 1) {
        goto l6;
    }
    if (ih == 5) {
        goto l20;
    }
    jstart = -1;
    if (ih == 4) {
        goto l8;
    }
    if (ih == 3) {
        goto l7;
    }
    h__ = .005f;
    h__ = -h__;
    goto l6;
l7:
    h__ = .02f;
    goto l6;
l8:
    h__ = .01f;
    goto l6;
/* l53: */
    if (ierr != 0) {
        goto l20;
    }
l20:
    return 0;
} /* main */

int f_c(float *x, float *y, float *dy, int *m)
{
    /* Parameter adjustments */
    --dy;
    --y;

    /* Function Body */
    dy[1] = -y[1];
    dy[2] = -y[2];
    return 0;
} /* f_c */


Результаты:

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

                   x                            y(1)                              y(2)
       2.346194490 + 00      7.141423761 - 01      - 7.000004762 - 01

                   h__                          y1                                 y2
     - 1.000000000 - 02      7.141423761 - 01      - 7.000004762 - 01

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

                   x                            y(1)                              y(2)
       2.336194490 + 00      7.211065574 - 01      - 6.928241717 - 01

                   h__                          y1                                 y2
     - 1.000000000 - 02      7.211065574 - 01      - 6.928241717 - 01

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

                   x                           y(1)                               y(2)
       2.341194490 + 00      7.176334371 - 01      - 6.964210292 - 01

                   h__                         y1                                  y2
     - 5.000000000 - 03      7.176334371 - 01      - 6.964210292 - 01

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

                   x                           y(1)                               y(2)
       2.366194490 + 00      7.000004762 - 01      - 7.141423761 - 01

                   h__                         y1                                  y2
       2.000000000 - 02      7.000004762 - 01      - 7.141423761 - 01

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

                   x                           y(1)                                y(2)
       2.356194490 + 00      7.071067812 - 01      - 7.071067812 - 01

                   h__                         y1                                   y2
       1.000000000 - 02      7.071067812 - 01      - 7.071067812 - 01