Текст подпрограммы и версий
de21r_c.zip , de21d_c.zip , de24r_c.zip , de24d_c.zip
Тексты тестовых примеров
tde21r_c.zip , tde21d_c.zip , tde24r_c.zip , tde24d_c.zip

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

Назначение

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

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

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

          Y' = F (X, Y) ,

          Y = ( y1, ..., yM ) ,
          F = ( f1 (X, y1,..., yM),..., fM (X, y1,..., yM) )     методом Гира.

Метод Гира для нежесткой системы является многошаговым предсказывающе - исправляющим методом Адамса, записанным в форме Нордсика, при этом предсказание и исправление имеют один и тот же порядок.

B случае, когда система уравнений является жесткой, интегрирование осуществляется специальным методом основанным на методе типа Адамса и использующим якобиан ( ∂F/∂Y ) системы, который вычисляется подпрограммой по формулам численного дифференцирования.

По заданному значению YX решения в узле Xn вычисляется значение этого решения в узле Xn + H. Считается, что решение в узле Xn + H вычислено с требуемой точностью EPS, если выполняется следующее соотношение:

                M   
             (  ∑ ( eI / YPM(I) )2 )1/2  ≤  EPS  ,
                I=1 

где eI - вычисляемая подпрограммой оценка абсолютной погрешности приближенного значения I - й компоненты решения в узле Xn + H, YPM (I) - задается при обращении к подпрограмме и, по существу, позволяет использовать разный тип погрешности для каждой компоненты. Если, например, YPM(I) = 1, то для I - ой компоненты YX(I) решения будет использоваться абсолютная погрешность; если YPM (I) = | YX (I) | ≠ 0 , где YX(I) - значение I - й компоненты YX(I) в узле Xn, то для этой компоненты берется отношение абсолютной погрешности приближенного ее значения в узле Xn + H к абсолютной величине приближенного значения этой компоненты в предыдущем узле Хn. Значение H может быть меньше или pавно значению шага интегрирования, задаваемому пользователем при обращении к подпрограмме.

Gear C.W., The automatic integration of ordinary differential equations. Communications of the ACM, 14, 3 (March 1971), 176-179.

Gear C.W., Numerical initial value problems in ordinary differential equations, Prentice - Hall, Englewood Cliffs, N.J., 1971.

Gear C.W., The automatic integration of stiff ordinary differential equations. Information Processing 68, A.J.H.

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

    int de21r_c (S_fp f, integer *m, integer *istifj,
                 integer *iorder, integer *jstart, real *hmin, real *hmax, real *eps,
                 real *yx, real *x, real *h, logical *bul, real *ypm, real *delty,
                 real *rab, real *yp, 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 - количество уравнений в системе (тип: целый);
istifj - целый указатель метода численного интегрирования:
istifj=0 - интегрирование системы ведется методом Адамса;
istifj=1 - интегрирование ведется специальным методом, предназначенным для жестких систем;
iorder - целая переменная, указывающая максимальный допустимый порядок метода; iorder должен быть не больше 7 для метода Адамса и не больше 6 для метода интегрирования жестких систем;
jstart - целый указатель режима использования подпрограммы, имеющий следующие значения:
0 - первое обращение к подпрограмме должно быть выполнено с нулевым значением jstart;
+1 - выполнить один шаг интегрирования системы дифференциальных уравнений для значений независимой и зависимой переменных и шага интегрирования, заданных параметрами x, yx и h ,соответственно;
-1 - повторить последний шаг интегрирования с новыми значениями параметров h и/или hmin;
  на выходе из подпрограммы jstart pавен текущему порядку метода;
hmin - минимальное значение абсолютной величины шага, котоpое разрешается использовать при интегрировании данной системы уравнений; это значение должно быть много меньше среднего ожидаемого шага интегрирования при первом обращении к подпрограмме с jstart = 0 (тип: вещественный);
hmax - максимальное значение абсолютной величины шага, котоpое разрешается использовать при интегрировании данной системы уравнений (тип: вещественный);
eps - требуемая точность вычисления решения; размер шага интегрирования и порядок метода выбираются в подпрограмме автоматически таким образом, чтобы вычисляемые ею оценки абсолютных погрешностей всех компонент решения, деленные на ypm (i), были не больше eps в евклидовой ноpме (тип: вещественный);
x, yx - начальные вещественные значения аргумента и решения уравнений в нем; в результате работы подпрограммы в x получается новое значение аpгумента, а в yx - соответствующее значение pешения; в случае системы уравнений, т.е. когда m ≠ 1 , yx задается одномерным массивом длины m;
h - вещественная переменная, содержащая значение шага интегрирования; если для этого значения шага точность приближенного решения достигается, то именно он и реализуется подпрограммой, иначе этот шаг уменьшается подпрограммой до тех пор, пока не будет достигнута заданная точность; на выходе из подпрограммы h содержит рекомендуемое подпрограммой значение следующего шага интегрирования, определяемое ею с целью достижения наиболее экономного способа интегрирования;
bul - логическая переменная, значение которой при обращении к подпрограмме полагается равным TRUE_, если заданный в H шаг выводит в конец интервала интегрирования, и FALSE_ в противном случае; в результате работы подпрограммы bul pавно FALSE_, если вместо исходного шага интегрирования был реализован меньший шаг; в противном случае, т.е. когда был выполнен именно заданный при обращении в h шаг, значение параметра bul не меняется;
ypm - одномерный вещественный массив длины m; значение ypm, котоpое он имеет на входе в подпрограмму, используется при вычислении погрешности приближенного решения; считается, что приближенное решение достигает требуемой точности, если евклидова ноpма вектоpа, составленного из абсолютных погрешностей вычисленных значений всех компонент решения, деленных на соответствующие элементы массива ypm (т.е. абсолютная погрешность i - й компоненты делится на i - й элемент ypm(i)), не превосходит eps; в pезультате работы подпрограммы значение i - го элемента ypm (i) сохраняется, если вновь вычисленное значение i - й компоненты yx (i) решения не превосходит по абсолютной величине исходного значения ypm (i), и заменяется на абсолютную величину нового значения, если она больше первоначального значения ypm (i); если на входе в подпрограмму ypm (i) = 1, то для i - ой компоненты решения yx (i) будет использоваться абсолютная погрешность; если на входе ypm (i) = | yx (i) | ≠ 0, то для i - й компоненты берется отношение абсолютной погрешности приближенного ее значения в узле X + H к абсолютной величине значения этой компоненты в предыдущем узле X;
delty - одномерный вещественный рабочий массив длины m;
rab - одномерный вещественный рабочий массив; при интегрировании нежесткой системы уравнений rab имеет размер 17*m, при интегрировании жесткой системы - m*(m + 17);
yp - двумерный вещественный рабочий массив размера 8*m;
ierr - целая переменная, служащая для сообщения об ошибках, обнаруженных в процессе работы подпрограммы; при этом:
ierr= 1 - когда неправильно задан параметр iorder, а именно, когда iorder превосходит максимальный допустимый порядок метода; в этом случае интегрирование ведется методом Гира порядка не выше 7 для нежесткой системы и не выше 6 для жесткой;
ierr=65 - когда интегрирование системы выполнено с заданным минимальным шагом, но требуемая точность полученного при этом значения yx решения не достигнута; в этом случае последний шаг интегрирования системы можно повторить обращением к подпрограмме с новыми значениями параметров h и hmin и со значением jstart = - 1;
ierr=66 - когда приближенное значение решения не может быть вычислено, т.к. итерационный процесс его определения не сходится для шагов интегрирования h, больших заданного минимального значения hmin;
ierr=67 - когда требуемая точность eps вычисления приближенного решения меньше той, которая может быть достигнута для данной задачи при тех размерах шага интегрирования, начальное значение которого задано параметром h;
  при ierr = 66 и 67 значения параметров x и yx сохраняются, а в h засылается то значение шага интегрирования, котоpое было на выходе в предыдущем обращении к подпрограмме; в этом случае интегрирование системы можно повторить обращением к подпрограмме с новыми значениями параметров h и hmin, если ierr = 66, и параметра h, если ierr = 67;
ierr=68 - когда приближенное значение решения для жесткой системы не может быть вычислено с заданной точностью; в этом случае значения x и yx сохраняются, а в h засылается то значение шага интегрирования, котоpое было на выходе в предыдущем обращении к подпрограмме; для достижения требуемой точности следует воспользоваться версиями подпрограммы de21d_c, de24r_c, или de24d_c.

Версии

de21d_c - выполнение одного шага численного интегрирования нежесткой и жесткой систем обыкновенных дифференциальных уравнений первого порядка методом Гира с повышенной точностью. При этом параметры hmin, hmax, eps, yx, x, h, ypm, delty, rab, yp и параметры x, y и dy в подпрограмме f должны иметь тип double.
de24r_c - выполнение одного шага численного интегрирования жесткой системы обыкновенных дифференциальных уравнений первого порядка методом Гира с контролем точности. Первый оператор подпрограммы имеет вид:
int de24r_c (S_fp f, S_fp fj, integer *m, integer *iorder, integer *jstart, real *hmin, real *hmax, real *eps, real *yx, real *x, real *h, logical *bul, real *ypm, real *delty, real *rab, real *yp, integer *ierr)
Здесь: fj - имя подпрограммы вычисления якобиана правой части системы; первый оператор этой подпрограммы имеет вид:
int fj (float *x, float *y, float *z, int *m)
Здесь: x, y - значения независимой и зависимой переменных, соответственно, причем y представляет одномерный массив длины m; вычисленное значение якобиана должно быть помещено в двумерный массив z размера m*m, при этом частная производная от правой части i - ого уравнения по j - ой переменной y (j) запоминается в элементе z (i, j) (тип параметров x, y и z: вещественный). Остальные параметры подпрограммы de24r_c имеют тот же смысл, что и одноименные параметры подпрограммы de21r_c.
de24d_c - выполнение одного шага численного интегрирования жесткой системы обыкновенных дифференциальных уравнений первого порядка методом Гира с повышенной точностью. Первый оператор подпрограммы имеет тот же вид, что и в подпрограмме de24r_c; при этом паметры hmin, hmax, eps, yx, x, h, ypm, delty, rab, yp и параметры x, y, dy и z в подпрограммах f и fj должны иметь тип double.

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

utde12_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de21r_c и de24r_c.
utde13_c - подпрограмма выдачи диагностических сообщений при работе подпрограмм de21d_c и de24d_c.
  Kpоме того, de21r_c, de24r_c и de21d_c, de24d_c используют pабочие подпрограммы de21ru_c, de21rp_c и de21du_c, de21dp_c, соответственно.

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

 

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

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

Значение hmin должно быть много меньше ожидаемого среднего шага интегрирования при первом обращении к подпрограмме, т.к. при первом обращении к подпрограмме используется метод первого порядка.

При многократном использовании подпрограммы или ее веpсий для вычисления решения системы уравнений на отрезке значения параметров m, istifj, eps, yx, x и значения рабочих массивов, задаваемых параметрами ypm, delty, rab, yp, не должны изменяться в вызывающей программе между последовательными обращениями к подпрограмме de21r_c или ее версиям.

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

         y1'  =   y3
         y2'  =   y4
         y3'  =  - ( 1 - 0.002 x ) y1 / ( y12  +  y22 )3/2
         y4'  =  - ( 1 - 0.002 x ) y2 / ( y12  +  y22 )3/2  ,

        y1(0)  =  0.09411764706 ,     y2(0)  =  0 ,     y3(0)  =  0 ,     y4(0)  =  4.5 

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

int main(void)
{
    /* System generated locals */
    int i__1;

    /* Local variables */
    extern int de21r_c(U_fp, int *, int *, int *, int *, float *, float *,
                       float *, float *, float *, float *, logical *,
                       float *, float *, float *, float *, int *);
    static float hmin, hmax;
    static int ierr;
    extern int f_c();
    static float h__;
    static int i__, m;
    static float x, y[4], delty[4], yp[32];
    static int iorder, istifj, jstart;
    static float rab[68];
    static logical bul;
    static float eps, ypm[4];

    bul = FALSE_;
    m = 4;
    x = 0.f;
    h__ = .01f;
    y[0] = .09411764706f;
    y[1] = 0.f;
    y[2] = 0.f;
    y[3] = 4.5f;
    iorder = 4;
    jstart = 0;
    hmax = .1f;
    hmin = 1e-18f;
    eps = 1e-5f;
    istifj = 0;
    i__1 = m;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L10: */
        ypm[i__ - 1] = 1.f;
    }
    de21r_c((U_fp)f_c, &m, &istifj, &iorder, &jstart, &hmin, &hmax, &eps, y,
            &x, &h__, &bul, ypm, delty, rab, yp, &ierr);

    printf("\n %16.7e \n", x);
    printf("\n %16.7e %16.7e ", y[0], y[1]);
    printf("\n %16.7e %16.7e \n", y[2], y[3]);
    printf("\n %16.7e \n", h__);
    printf("\n %16.7e %16.7e ", delty[0], delty[1]);
    printf("\n %16.7e %16.7e \n", delty[2], delty[3]);
    printf("\n %5i \n", ierr);
    return 0;
} /* main */

int f_c(float *x, float *y, float *dy, int *m)
{
    /* Builtin functions */
    double sqrt(double);

    /* Local variables */
    static float r__, r2;

    /* Parameter adjustments */
    --dy;
    --y;

    /* Function Body */
    r2 = y[1] * y[1] + y[2] * y[2];
    r2 *= (float)sqrt(r2);
    r__ = -(1.f - *x * .002f) / r2;
    dy[1] = y[3];
    dy[2] = y[4];
    dy[3] = r__ * y[1];
    dy[4] = r__ * y[2];
    return 0;
} /* f_c */


Результаты:

          x  =   4.057708603-05
          h  =   4.057708603-05

          y(1)  =   9.411746119-02
          y(2)  =   1.825965265-04
          y(3)  =  -4.580764462-03
          y(4)  =   4.499991113

          ierr  =   0