Текст подпрограммы и версий
de51r_c.zip , de51d_c.zip
Тексты тестовых примеров
tde51r_c.zip , tde51d_c.zip

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

Назначение

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

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

Решается двухточечная краевая задача для нелинейного дифференциального уравнения второго порядка

(1)       y '' + f(x, y, y ') y ' + g(x, y, y ') y = r(x, y, y ')  ,     xN≤ x ≤ xK 

с заданными на концах отрезка интегрирования  [ xN, xK ] граничными условиями вида

(2)       aN y '(xN) + bN y(xN) = CN   ,

(3)       aK y '(xK) + bK y(xK) = CK   . 

Решение вычисляется на заданной на отрезке  [ xN, xK ] равномерной сетке с заданной абсолютной погрешностью  EPS. Используется метод линеаризации исходного уравнения (1) с последующим применением метода конечных разностей для решения линейного уравнения.

L.Fox, Proc. Roy. Soc. A 190, 31 - 59, 1947.

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

    int de51r_c (S_fp f, integer *nx, real *xn, real *xk, real *cn,
                 real *ck, real *eps, integer *imax, integer *ider, real *y,
                 integer *ik, real *delty, real *rab, integer *ierr)

Параметры

f - имя подпрограммы вычисления значений коэффициентов  f (x, y, y'),  g (x, y, y'),  r (x, y, y') уравнения (1). Первый оператор подпрограммы должен иметь вид:
 

int f (float *cf, float *cg, float *cr, float *x, float *y, int *i__, float *rab)
Здесь:

x, y - представляют первые два аргумента функций  f (x, y, y'),  g (x, y, y') и   r (x, y, y');
rab - одномерный массив длины 11 * nx (nx - число узлов сетки);
i - указывает компоненту  rab(i) массива   rab, которая представляет третий аpгумент функций  f (x, y, y'),  g (x, y, y'),   r (x, y, y');
cf, cg, cr - представляют вычисленные подпрограммой  f значения функций  f (x, y, y'),  g (x, y, y') и  r (x, y, y');
  параметры  cf, cg, cr, x, y и  rab имеют тип real, а  i - integer;
nx - число узлов равномерной сетки на отрезке   [xn, xk], (включая  xn и  xk), в которых требуется вычислить решение задачи;  nx ≥ 3 (тип: целый);
xn, xk - концы отрезка интегрирования, в которых заданы граничные условия (2) и (3), соответственно;  xn < xk (тип: вещественный);
cn, ck - одномерные вещественные массивы длины 3, в которых помещаются коэффициенты граничных условий (2) и (3), соответственно, т.е.  cn (1) = an,  cn (2) = bn,  cn (3) = cn,  ck (1) = ak, ck (2) = bk,  ck (3) = ck. Коэффициенты должны удовлетворять условию
a2n + b2n ≠ 0   и   a2k + b2k ≠ 0;
eps - абсолютная погрешность, с которой требуется вычислить решение краевой задачи;  eps > 0 (тип: вещественный);
imax - указывает максимальное допустимое число линеаризаций исходного уравнения (1) и число итераций, используемых при решении получающегося после линеаризации уравнения: число линеаризаций pавно абсолютному значению  | imax | параметра  imax, а число итераций pавно  imax, если  imax > 0 и нулю, если  imax < 0;  imax ≠ 0. Если  imax < 0, то в результате работы подпрограммы значение  imax заменяется на противоположное; в этом случае  imax зажается переменной или элементом массива (тип: целый);
ider - указывает на зависимость коэффициентов  f (x, y, y'),  g (x, y, y'),  r (x, y, y') уравнения (1) от производной  y': если хотя бы один из этих коэффициентов зависит от  y', то  ider > 0, иначе  ider = 0 (тип: целый);
y - одномерный вещественный массив длины  nx, который должен содержать при обращении к подпрограмме значения начального приближения решения краевой задачи (1), (2), (3) во всех узлах сетки. В результате работы подпрограммы в этом массиве получаются значения конечного приближения к решению (эти значения помещаются в  y в любом случае, даже и тогда, когда они не могут быть вычислены с требуемой точностью);
ik - целая переменная, содержащая число линеаризаций уравнения (1), выполненных в действительности подпрограммой для достижения требуемой точности  eps решения. В случае, когда данная точность решения нелинейного уравнения не достигается за  imax линеаризаций или когда решение соответствующего линейного уравнения не может быть вычислено с точностью  eps за  imax итераций, то значение параметра  ik в результате работы подпрограммы полагается равным  - 1;
delty - одномерный вещественный массив длины  nx, значение которого в результате работы подпрограммы полагается равным разности между начальным и конечным приближениями решения того линейного уравнения, котоpое получается после выполнения самой последней линеаризации исходного уpавнения (1), причем эта разность вычисляется во всех узлах сетки. В случае, когда  imax < 0, все элементы массива  delty в результате работы подпрограммы полагаются равными 0;
rab - одномерный вещественный рабочий массив длины 11 * nx;
ierr - целая переменная, служащая для сообщения об ошибках, обнаруженных в процессе работы подпрограммы; при этом:
ierr=65 - если в граничном условии (2) коэффициенты  an = bn = 0;
ierr=66 - если в граничном условии (3) коэффициенты  ak = bk = 0;
ierr=67 - если  imax = 0;
ierr=68 - если  ider < 0;
ierr = 1 - если заданная точность решения нелинейного уравнения не достигается за  | imax | линеаризаций или если решение соответствующего линейного уpавнения не может быть вычислено с точностью  eps за  imax итераций;
ierr = 3 - если заданная точность решения нелинейного уравнения не достигается за  | imax | линеаризаций или если решение соответствующего линейного уpавнения не может быть вычислено с точностью  eps за  imax итераций, при этом при аппроксимации исходного уравнения линейным уравнением использовались производные, вычисленные с меньшей точностью, чем это необходимо;
  В каждом из выше указаных случаев решение задачи прекращается;
ierr = 2 - если при аппроксимации исходного уpавнения линейным уравнением использовались производные, вычисленные с меньшей точностью, чем это необходимо. При  ierr = 1, 2, 3 полученное приближенное решение запоминается в массиве  y; при желании интегрирование можно повторить обращением к подпрограмме с новыми значениями параметров  nx, y или  imax.

Версии

de51d_c - вычисление решения двухточечной краевой задачи для нелинейного дифференциального уравнения второго порядка с повышенной точностью. При этом параметры  xn, xk, cn, ck, eps, y, delty, rab должны иметь тип double.

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

de50r_c - вычисление решения двухточечной краевой задачи для линейного дифференциального уравнения второго порядка методом конечных разностей.
de50d_c - вычисление решения двухточечной краевой задачи для линейного дифференциального уравнения второго порядка методом конечных разностей с повышенной точностью.
id10r_c - подпрограмма вычисления первых и вторых производных с помощью центральных разностей.
id10d_c - подпрограмма вычисления первых и вторых производных с помощью центральных разностей с двойной точностью.
  Подпрограммы de50r_c и id10r_c вызываются подпрограммой de51r_c, а подпрограммы de50d_c и id10d_c - подпрограммой de51d_c.
utde10_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de51r_c.
utde11_c - подпрограмма выдачи диагностических сообщений при работе подпрограммы de51d_c.

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

 

Число узлов сетки  nx, задаваемое пользователем при обращении к подпрограмме, должно быть достаточно большим для того, чтобы обеспечить сходимость конечно - разностных аппроксимаций, используемых для решения линейных уравнений, и последовательных линеаризаций исходного уравнения (1).

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

Пусть  ηi ,  i = 1, ..., nx, представляет разность между текущим приближением к решению и приближением, полученным в результате предыдущей линеаризации уравнения (1). Тогда текущее приближение принимается за окончательное решение, если для всех  i (1 ≤ i ≤ nx) выполняется условие  | ηi | ≤ eps .

Значения параметров  nx, xn, xk, cn, ck, eps, imax, в результате работы подпрограммы сохраняются.

Kpоме того, de50r_c и de50d_c используют рабочие подпрограммы id10rp_c и id10dp_c, соответственно.

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

Решается краевая задача:

      y '' + ( xy' ) y' + e -y y = ( xy' + 2e-y - 2 ) cos x - ( 1 + 2xy' - e-y ) sin x 
      2y - y' = 0         при x = 0
      y + y' = 1          при x = π / 2

(точное решение задачи  y = sin x + 2cos x).

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

    /* Builtin functions */
    double cos(double), sin(double);

    /* Local variables */
    extern int de51r_c(U_fp, int *, float *, float *, float *, float *,
                       float *, int *, int *, float *, int *, float *,
                       float *, int *);
    static int ider, imax, ierr;
    extern int f_c();
    static float h__;
    static int i__, n;
    static float x, y[150], delty[150], ck[3], cn[3];
    static int ik;
    static float xk;
    static int nx;
    static float xn, yr[200], yx[150], rab[1650], eps;

    nx = 150;
    xn = 0.f;
    xk = 3.14159265359f;
    xk /= 2.f;
    cn[0] = 2.f;
    cn[1] = -1.f;
    cn[2] = 0.f;
    ck[0] = 1.f;
    ck[1] = 1.f;
    ck[2] = -1.f;
    imax = 4;
    eps = 1e-5f;
    ider = 1;
    i__1 = nx;
    for (i__ = 1; i__ <= i__1; ++i__) {
        yx[i__ - 1] = 1.5f;
/* L1: */
    }
    de51r_c((U_fp)f_c, &nx, &xn, &xk, cn, ck, &eps, &imax, &ider, yx, &ik,
            delty, rab, &ierr);

    printf("\n %5i \n", ik);
    printf("\n %5i \n", ierr);
    n = nx - 1;
    h__ = (xk - xn) / n;
    x = xn - h__;
    i__1 = nx;
    for (i__ = 1; i__ <= i__1; ++i__) {
        x += h__;
        y[i__ - 1] = (float)sin(x) + (float)cos(x) * 2.f;
        yr[i__ - 1] = yx[i__ - 1] - y[i__ - 1];

        printf("\n %16.7e %16.7e %16.7e %16.7e \n",
               x, yx[i__-1], y[i__-1], yr[i__-1]);
/* L2: */
    }
    return 0;
} /* main */

int f_c(float *fc, float *gc, float *rc, float *x, float *y, int *i__,
        float *rab)
{
    /* Builtin functions */
    double exp(double), cos(double), sin(double);

    /* Parameter adjustments */
    --rab;

    /* Function Body */
    *fc = *x * rab[*i__];
    *gc = (float)exp(-(*y));
    *rc = (*x * rab[*i__] - 2.f +
          (float)exp(-(*y)) * 2.f) * (float)cos(*x) -
          (*x * 2.f * rab[*i__] + 1.f -
          (float)exp(-(*y))) * (float)sin(*x);
    return 0;
} /* f_c */


Результаты:      (приводятся только для первых 10 узлов)

      yx(1)   =  1.999999086
      yx(2)   =  2.010430009
      yx(3)   =  2.020637497
      yx(4)   =  2.030620414
      yx(5)   =  2.040377652
      yx(6)   =  2.049908127
      yx(7)   =  2.059210778
      yx(8)   =  2.068284572
      yx(9)   =  2.077128500
      yx(10) =  2.085741581

      ik  =  3
      ierr  =  2