Текст подпрограммы и версий
de04r_c.zip , de04d_c.zip
Тексты тестовых примеров
tde04r_c.zip , tde04d_c.zip

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

Назначение

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

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

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

(1)                         Y ' (X)   =   A(X) * Y(X) + φ(X) ,

                                 Y   =   ( y1,..., yM ) , 
                                 A(X)   =   ( ai j(X) ) ,     i, j  =  1, ..., M ,
                                φ(X)    =   ( φ1(X), ... , φM(X) ) 

Предполагается, что среди характеристических корней матрицы A(X) имеются большие по модулю корни, а функция  φ(x) является достаточно малой. По заданному значению решения YX в узле  xn  вычисляется значение этого решения в узле  xn + H  . Вычисление производится по методу Лоусона.

Метод Лоусона заключается в следующем. Исходная система уравнений с помощью замены искомой функции Y (x) на  [ xn, xn + H ] по формуле

                             Y(x)  =  exp [ ( x - xn ) A0 ] Z(x),

где A0 - некоторая постоянная матрица, преобразуется в систему уравнений относительно новой неизвестной функции Z (X):

(2)  Z ' (x)  =  A1(x) Z(x)  +  φ1(x)  =  exp [ - ( x - xn ) A0 ] { A(x) - A0 }
                                   exp [ ( x - xn ) A0 ] Z(x) + exp [ ( - ( x - xn ) A0 ] φ(x) 

Данное преобразование выполняется самой подпрограммой. В качестве матрицы A0 подпрограмма выбирает матрицу A0 = A (xn + H /2). Если шаг H достаточно мал, то преобразование позволяет уменьшить характеристические корни матрицы A1 (x) по сравнению с характеристическими корнями исходной матрицы A (x). Это приводит к уменьшению константы Липшица системы (2) по сравнению с константой Липшица системы (1). Для решения системы (2) применяются формулы классического метода Рунге - Кутта четвертого порядка точности, причем одновременно с решением (2) производится обратное преобразование от функции Z (x) к функции Y (x).

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

J.Douglas Louson. Generalized Runge - Kutta processes for stable systems with large Lipshitz constants, SIAM Journal on Numerical Analisys. - 1967. - Vol 4, No 3.

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

    int de04r_c (S_fp fa, S_fp fi, integer *m, integer *jstart,
            real *hmin, real *eps, real *p, real *yx, real *x, real *h,
            logical *bul, real *xp, real *yp, real *a, real *e1, real *e2,
            real *e3, real *w1, real *r1, real *r2, real *r3, real *r4,
            real *r5, real *r6, real *yd, integer *ierr)

Параметры

fa - подпрограмма вычисления матрицы системы A(x) в точке x. Первый оператор подпрограммы должен иметь вид:
   int fa(float *a, float *x, int *m).
Здесь a - двумерный массив размера m*m, в котором помещается матрица системы, вычисленная при значении аргумента x (тип параметров a, x: вещественный);
fi - подпрограмма вычисления неоднородности правой части системы  φ (x) в любой точке x. Первый оператор подпрограммы должен иметь вид:
   int fi(float *g, float *x, int *m).
Здесь g - одномерный массив длины m, в который помещается неоднородность правой части системы, вычисленная при значении аргумента x (тип параметров g, x: вещественный);
m - количество уравнений в системе (тип: целый);
jstart - целый указатель режима использования подпрограммы, имеющий следующие значения:
0,+1 - выполнить один шаг интегрирования системы дифференциальных уравнений для значений независимой и зависимой переменных и шага интегрирования, заданных параметрами x, yx, и h, соответственно;
-1 - повторить последний шаг интегрирования с новыми значениями параметров h и/или hmin; на выходе из подпрограммы jstart полагается равным  + 1;
hmin - минимальное значение абсолютной величины шага, которое разрешается использовать при интегрировании данной системы уравнений (тип: вещественный);
eps - допустимая мера погрешности, с которой требуется вычислить все компоненты решения (тип: вещественный);
p - граница перехода, используемая при оценке меры погрешности решения (тип: вещественный);
yx, x - заданные вещественные значение решения и соответствующее ему значение аргумента; в результате работы подпрограммы в x получается новое значение аргумента, в yx - соответствующее значение решения; в случае системы уравнений, т.е. когда m ≠ 1, yx задается одномерным массивом длины m;
h - вещественная переменная, содержащая значение шага интегрирования; если для этого значения шага точность приближенного решения достигается, то именно он и реализуется подпрограммой, иначе этот шаг уменьшается подпрограммой до тех пор, пока не будет достигнута заданная точность eps; на выходе из подпрограммы h содержит рекомендуемое подпрограммой значение следующего шага интегрирования, определяемое ею с целью достижения более экономного способа интегрирования;
bul - логическая переменная, значение которой при обращении к подпрограмме полагается равным TRUE_, если заданный в h шаг выводит в конец интервала интегрирования, и FALSE_ в противном случае; в результате работы подпрограммы bul равно FALSE_, если вместо исходного шага интегрирования был реализован меньший шаг; в противном случае, т.е. когда был выполнен именно заданный при обращении в h шаг, значение параметры bul не меняется;
xp, yp - вещественная рабочая переменная и одномерный рабочий массив длины m, соответственно; значения параметров xp, yp на выходе из подпрограммы равны тем значениям, которые имели параметры x, yx при входе в нее (т.е. предыдущий узел и решение в нем);
       a, e1 -
         e2, e3, 
         w1  
вещественные двумерные рабочие массивы размера m*m;
       r1, r2 -
       r3, r4, 
         r5, r6, 
         yd  
вещественные одномерные рабочие массивы длины m;
ierr - целая переменная, значение которой в результате работы подпрограммы полагается равным 65, если какая - нибудь компонента решения не может быть вычислена с требуемой точностью eps; в этом случае последний шаг интегрирования системы можно повторить обращением к подпрограмме с новыми значениями параметров h, hmin и значением jstart = - 1

Версии

de04d_c - выполнение одного шага численного интегрирования линейной устойчивой системы обыкновенных дифференциальных уравнений первого порядка с большой константой Липшица методом Лоусона с удвоенным числом значащих цифр. При этом параметры hmin, eps, p, yx, x, h, xp, yp, a, e1, e2, e3, w1, r1, r2, r3, r4, r5, r6, yd и параметры a, g, x в подпрограммах fa и fi должны иметь тип double.

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

ame2r_c - подпрограмма вычисления матричной экспоненты; вызывается при работе подпрограммы de04r_c;
ame2d_c - подпрограмма вычисления матричной экспоненты; вызывается при работе подпрограммы de04d_c;
utde20_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de04r_c;
utde21_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de04d_c
 

Кроме того при работе подпрограмм de04r_c и de04d_c вызываются подпрограммы de04rd_c, de04rm_c, de04rp_c, de04rq_c и de04dd_c, de04dm_c, de04dp_c, de04dq_c соответственно.

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

 

Данная подпрограмма предназначена для интегрирования линейных систем, имеющих малую неоднородность φ (x).

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

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

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

После работы подпрограммы в массиве r1 содержится значение оценки погрешности на шаге, вычисленной по правилу Рунге.

Данная подпрограмма и ее версия предназначены также для интегрирования жестких дифференциальных уравнений (1).

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

        y1'  =  - ( 2 + x ) y1 /( 1 + x )  +  20 x y2 ,
        y1(0)  =  0 ,
        y2'  =  -20 x y1  +  ( 2  + x ) y2 /( 1 + x ) ,
        y2(0) = 1 . 

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

int main(void)
{
    /* Local variables */
    extern int de04r_c(U_fp, U_fp, int *, int *, float *, float *,
                       float *, float *, float *, float *, logical *,
                       float *, float *, float *, float *, float *,
                       float *, float *, float *, float *, float *,
                       float *, float *, float *, float *, int *);
    static float hmin;
    static int ierr;
    static float a[4] /* was [2][2] */, h__;
    static int m;
    static float p, x, e1[4] /* was [2][2] */, e2[4] /* was [2][2] */,
                       e3[4] /* was [2][2] */, r1[2], r2[2], r3[2], r4[2],
                      r5[2], w1[4] /* was [2][2] */, r6[2];
    extern int fa_c(), fi_c();
    static int ih;
    static float yd[2], xp, yp[2], yx[2];
    static int jstart;
    static logical bul;
    static float eps;

    m = 2;
    x = 0.f;
    yx[0] = 0.f;
    yx[1] = 1.f;
    hmin = 1e-10f;
    eps = 1e-7f;
    p = 100.f;
    jstart = 1;
    h__ = .01f;
    ih = 0;
l1000:
    ++ih;
    de04r_c((U_fp)fa_c, (U_fp)fi_c, &m, &jstart, &hmin, &eps, &p, yx, &x,
            &h__, &bul, &xp, yp, a, e1, e2, e3, w1, r1, r2, r3, r4, r5, r6,
            yd, &ierr);

    printf("\n %16.7e %16.7e %16.7e \n", x, yx[0], yx[1]);
    printf("\n %16.7e %16.7e %16.7e \n\n", h__, r1[0], r1[1]);
    switch (ih) {
        case 1:  goto l101;
        case 2:  goto l102;
        case 3:  goto l103;
        case 4:  goto l104;
        case 5:  goto l105;
        case 6:  goto l106;
        case 7:  goto l107;
    }
l101:
    eps = 1e-7f;
    goto l1000;
l102:
    eps = 1.f;
    goto l1000;
l103:
    jstart = -1;
    h__ = .01f;
    eps = 1e-5f;
    goto l1000;
l104:
    jstart = -1;
    h__ = -1e-4f;
    eps = .01f;
    goto l1000;
l105:
    h__ = 1.f;
    eps = 1e-7f;
    goto l1000;
l106:
    eps = 1e-4f;
    goto l1000;
l107:
    return 0;
} /* main */

int fa_c(float *a, float *x, int *m)
{
#define a_ref(a_1,a_2) a[(a_2)*2 + a_1]

    /* Parameter adjustments */
    a -= 3;

    /* Function Body */
    a_ref(1, 1) = -(*x + 2.f) / (*x + 1.f);
    a_ref(1, 2) = *x * 20.f;
    a_ref(2, 1) = -a_ref(1, 2);
    a_ref(2, 2) = a_ref(1, 1);
    return 0;
} /* fa_c */


int fi_c(float *r1, float *x, int *m)
{
    /* Parameter adjustments */
    --r1;

    /* Function Body */
    r1[1] = 0.f;
    r1[2] = 0.f;
    return 0;
} /* fi_c */


  Результаты: 

   После первого обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         1.000000000001-02     9.802471967628-04     9.802468700200-01 
                 h__                                 r1(1)                            r1(2) 
         2.000000000001-02     0.000000000000+00     6.063298011814-14 

   после второго обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         3.000000000000-02     8.479506692396-03     9.421419716109-01 
                 h__                                 r1(1)                            r1(2) 
         4.000000000002-02     1.231607408649-14     1.333925562599-12 

   после третьего обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         6.999999999994-02     4.268132414620-02     8.703501915807-01 
                 h__                                 r1(1)                            r1(2) 
         8.000000000004-02     1.970571853839-12     3.565219230945-11 

   после четвертого обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         3.999999999996-02     1.478074532271-02     9.237177506848-01 
                 h__                                 r1(1)                            r1(2) 
         2.000000000001-02     0.000000000000+00     6.063298011814-14 

   после пятого обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         2.990000000000-02     8.424732657545-03     9.423281849631-01 
                 h__                                 r1(1)                            r1(2) 
        -2.000000000004-04     0.000000000000+00     6.063298011814-14 

   после шестого обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         6.115000000000-02     3.314040588361-02     8.858545422663-01 
                 h__                                 r1(1)                            r1(2) 
         3.125000000000-02     4.395891058563-13     1.097456940137-11 

   после седьмого обращения к подпрограмме
                 x                                   yx(1)                           yx(2) 
         9.240000000000-02     7.117143016819-02     8.315812963056-01 
                 h__                                 r1(1)                            r1(2) 
         6.250000000000-02     7.80649190203-13      8.852415097246-12