Nickolay.info. Алгоритмы. Краевая задача для дифференциального уравнения 2 порядка

Вот здесь уже есть немало примеров на реализацию численных методов в Excel.

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

Для дифференциального уравнения второго порядка

поставлена краевая задача:
Здесь u(t) -искомое решение, A, B - краевые условия,заданные функции коэффициентов. Введем на отрезке [a,b] разностную сетку (t0, t1, t2, ..., tM,), ti=a+τ*i, i=0,1,...,M, τ=(b-a)/M, M – параметр задачи (число шагов сетки). Заменим уравнение разностной схемой

Собирая коэффициенты при yi, yi+1 , yi-1, получим следующую СЛАУ на вектор неизвестных (y0, y1, y2, ..., yM):

(k1—k2/τ)y0 + k2 y1/τ =A

AAi yi-1 - CCiyi + BBiyi+1 = FFi, i=1,2,...,M-1

(l1+l2/τ) yM - l2 yM-1 /τ=B,

где CCi = 2 - g(ti) τ2 , AAi = 1 - p(ti) τ/2, BBi = 1 + p(ti) τ/2, FFi = τ2f(ti).

Система решается методом прогонки, в котором решение отыскивается в виде yii+1yi+1i+1, i=0,1,…,M-1. Алгоритм состоит из следующих шагов.

1. Поскольку y01y11, и из первого уравнения y0 = (A - k2 y1/τ) / (k1—k2/τ), то α1 = - k2/ [ τ (k1—k2/τ) ], β1 = A/(k1—k2/τ)

2. Следующие прогоночные коэффициенты ai, bi определяются по рекурентным формулам (прямой ход метода прогонки с трёхдиагональной матрицей):
αi+1=, β i+1= i=1,2,...,M-1.

3. Для определения решения на правой границе отрезка воспользуемся последним уравнением системы (l1+l2/τ) yM - l2yM-1 /τ=B и соотношением yM-1M yM + βM, откуда yM определяется как решение системы двух линейных алгебраических уравнений.

4. Обратный ход метода прогонки для определения решения.

yii+1yi+1i+1, i = M-1,M-2, ..., 0.

Теперь напишем программу решения краевой задачи для ОДУ второго порядка с помощью конечно-разностного метода. Это программа будет тестовой, то есть, содержит функцию yt(t), определяющую точное решение.

Уравнение:

Точное решение:
ut(t) = cos(sin(t)) + C1 sin(sin(t)), C1=(10 - cos(sin(1)))/sin(sin(1)).

Программа для заданного константой M будет выдавать на экран таблицу со столбцами
i ti yi u(ti) |u(ti)-yi|,
также по последнему столбцу определяется максимальная погрешность.

Метод показывает первый порядок аппроксимации, то есть, при увеличении числа узлов в 2 раза точность решения также повышается примерно в 2 раза. Возможно, здесь чуть-чуть иначе вычисляются α1 и β1, но с посчитанной ниже задачей в Excel совпало.

program odu2test;
{Решение тестовой задачи с известным точным решением yt(t)}
const n=10; {Число точек}
      a=0;  {Границы интервала}
      b=1;
      {Краевые условия}
      k1=1; k2=0; a1=1;
      l1=1; l2=0; b1=10;
type vec=array [0..n] of real;
var
 h,eps,epsmax:real;
 al,bet,t,u,aa,bb,cc,ff:vec;
 i,j:integer;

{Функция коэффициентов при 1-й производной u'(t)}
function p(t:real):real;
begin
 p:=sin(t)/cos(t);
end;
{Функция коэффициентов при u(t)}
function g(t:real):real;
begin
 g:=sqr(cos(t));
end;
{Функция правой части уравнения}
function f(t:real):real;
begin
 f:=0;
end;
{Точное решение yt(t)}
function yt(t:real):real;
var c1:real;
begin
 c1:=(10-cos(sin(1)))/sin(sin(1));
 yt:=cos(sin(t))+c1*sin(sin(t));
end;

begin
 {Вычисление шага сетки}
 h:=(b-a)/n;
 {Формирование векторов коэффициентов для 3-диагональной СЛАУ}
 for i:=0 to n do begin
  t[i]:=a+h*i;
  aa[i]:=1-p(t[i])*h/2;
  bb[i]:=1+p(t[i])*h/2;
  cc[i]:=2-g(t[i])*h*h;
  ff[i]:=h*h*f(t[i]);
 end;
 {Краевое условие при t=a}
 al[1]:=k2/(k2-k1*h);
 bet[1]:=-(a1*h)/(k2-k1*h);
 {Прямой ход метода прогонки}
 for i:=1 to n-1 do begin
  al[i+1]:=bb[i]/(CC[i]-al[i]*aa[i]);
  bet[i+1]:=(aa[i]*bet[i]-ff[i])/(cc[i]-al[i]*aa[i]);
 end;
 {Решение на правой границе отрезка}
 u[n]:=(l2*bet[n]+b1*h)/(l2+h*l1-l2*al[n]);
 {Обратный ход метода прогонки}
 for i:=n-1 downto 0 do
  u[i]:=al[i+1]*u[i+1]+bet[i+1];
 {Вывод таблицы и определение макс.погрешности}
 writeln('i':4,'t[i]':10,'y[i]':10,'yt(t[i])':10,'Погрешн.':10);
 for i:=0 to n do begin
  eps:=abs(u[i]-yt(t[i]));
  if eps>epsmax then epsmax:=eps;
  writeln (i:4,t[i]:10:4,u[i]:10:4,yt(t[i]):10:4,eps);
 end;
 writeln ('Максимальная погрешность=',epsmax);
 reset (input); readln;
end.

Используя эту программу, можно решить и другую аналогичную краевую задачу, изменив в нашей программке всего несколько строчек. Например, такую:
Уравнение , интервал [1.1,1.4], краевое условие при t=a имеет вид u-2u ′ =-1, краевое условие при t=b имеет вид u=4. Вроде бы, должно получиться так:

program odu2my;
const n=10; {Число точек}
      a=1.1;  {Границы интервала}
      b=1.4;
      {Краевые условия}
      k1=1; k2=-2; a1=-1;
      l1=1; l2=0; b1=4;
type vec=array [0..n] of real;
var
 h:real;
 al,bet,t,u,aa,bb,cc,ff:vec;
 i,j:integer;

{Функция коэффициентов при 1-й производной u'(t)}
function p(t:real):real;
begin
 p:=-1;
end;
{Функция коэффициентов при u(t)}
function g(t:real):real;
begin
 g:=2/t;
end;
{Функция правой части уравнения}
function f(t:real):real;
begin
 f:=t+0.4;
end;

begin
 {Вычисление шага сетки}
 h:=(b-a)/n;
 {Формирование векторов коэффициентов для 3-диагональной СЛАУ}
 for i:=0 to n do begin
  t[i]:=a+h*i;
  aa[i]:=1-p(t[i])*h/2;
  bb[i]:=1+p(t[i])*h/2;
  cc[i]:=2-g(t[i])*h*h;
  ff[i]:=h*h*f(t[i]);
 end;
 {Краевое условие при t=a}
 al[1]:=k2/(k2-k1*h);
 bet[1]:=-(a1*h)/(k2-k1*h);
 {Прямой ход метода прогонки}
 for i:=1 to n-1 do begin
  al[i+1]:=bb[i]/(CC[i]-al[i]*aa[i]);
  bet[i+1]:=(aa[i]*bet[i]-ff[i])/(cc[i]-al[i]*aa[i]);
 end;
 {Решение на правой границе отрезка}
 u[n]:=(l2*bet[n]+b1*h)/(l2+h*l1-l2*al[n]);
 {Обратный ход метода прогонки}
 for i:=n-1 downto 0 do
  u[i]:=al[i+1]*u[i+1]+bet[i+1];
 {Вывод таблицы и определение макс.погрешности}
 writeln('i':4,'t[i]':10,'y[i]':10);
 for i:=0 to n do writeln (i:4,t[i]:10:4,u[i]:10:4);
 reset (input); readln;
end.

Ниже то же самое посчитано в Excel для 10, 20 и 40 узлов сетки, в файле серым фоном обозначены ячейки с формулами и константами, которые являются входными данными, жёлтым - формулы, которые считаются иначе, чем соседние формулы выше и/или ниже.

 odu2.xls (56 Кб, Excel XP/2003)

Рейтинг@Mail.ru

вверх гостевая; E-mail