You are on page 1of 12

Диференчна схема за задачата на ОДУ от 2-ри ред, апроксимираща с грешка OIh2 M и

решена с метода на прогонката

ü Персонална информация

Име Светлин Анков


Ф.№ 31 082
ад. гр. 2
вариант 14

ü Условие на задачата

ü Общ вид на разглежданата задача

u'' HxL − q HxL u HxL = f HxL, x ∈ Ha, bL, q HxL ≥ 0 (1)


α1 u HaL + β1 u' HaL = μ1 (2)
α2 u HbL + β2 u' HbL = μ2 (3)

ü Условие на задачата за конкретния вариант

Имаме:

, q HxL = 3 x, f HxL = 2 sin HxL + I3 x2 + xM cos HxL


π
a = 0, b =
2
(4)
α1 = 0, β1 = 1, μ1 = 1
α2 = 1, β2 = 0, μ2 = 0

Или след заместване:

u'' HxL − 3 x u HxL = 2 sin HxL + I3 x3 + xM cos HxL, x ∈ 0, , q HxL ≥ 0


π
(5)

u' H0L = 1
2
(6)
π
u =0 (7)
2

ü Брой интервали

N = 10
2 ОДУ 2-ри ред

ü Извеждане на диференчната схема

ü Апроксимация на основното уравнение (ОДУ – 2-ри ред)

втори ред, имаща грешка OIh2 M:


За целта единствено апроксимираме втората производна в уравнението използвайки централна крайна разлика от

u'' Hxi L = + O Ih2 M


ui+1 − 2 ui + ui−1
(8)
h2
Замествайки в уравнението (1), получавамe апроксимацията:
yi+1 − 2 yi + yi−1
− qi yi = fi , i = 1, ..., n − 1 (9)
h2
Видно е, че (9) има смисъл само за точки от мрежата, т.е. валидно е за всички вътрешни точки от нея. За y0 и yn трябва
друг подход. Е, тях ще намерим от граничните условия. За целта трябва да апроксимираме отново с грешка OIh2 M.

Нека първоначално апроксимираме u'0 с forward разлика с грешка O(h):

+ O HhL
u1 − u0
u'0 = (10)
h
По-точно за грешката имаме:

0 + O Ih M − u0 − u0 = 0 + O Ih M
u1 − u0 1 h2 h
Ψ0 = − u'0 = u0 + h u'0 + u'' 3 '
u'' 2
(11)
h h 2 2

Т.е.:

0 + O Ih M
u1 − u0 h
u'0 = − u'' 2 (12)
h 2
Предвид началния вид на уравнението (1) за u''0 имаме:

u''
0 = q0 u0 + f0 (13)

Заместваме в (12):

Hq0 u0 + f0 L + O Ih2 M
u1 − u0 h
u'0 = − (14)
h 2
Т.е. получихме апроксимация за u'0 с грешка OIh2 M. Остава да заместим в граничното условие (2):

Hq0 y0 + f0 L = μ1
y1 − y0 h
α1 y0 + β1 − (15)
h 2
Светлин Анков 3

Правим същото и за второто гранично условие, но този път използваме backward разлика:

+ O HhL
un − un−1
u'n = (16)
h
Тогава:

n + O Ih M n + O Ih M
un − un−1 1 h2 h
Ψn = − u'n = un − un − h u'n + u'' 3
− u'n = − u'' 2
(17)
h h 2 2

Т.е.:

n + O Ih M
un − un−1 h
u'n = + u'' 2 (18)
h 2
За u''n от (1) имаме:

u''
n = qn un + fn (19)

Заместваме в (18):

Hqn un + fn L + O Ih2 M
un − un−1 h
u'n = + (20)
h 2
Последно заместмаме в граничното условие (2):

Hqn yn + fn L = μ2
yn − yn−1 h
α2 yn + β2 + (21)
h 2

ü Формули на апроксимиращата система, готови за решение с метода на прогонката.

След известно подреждане на коефициенти получаваме следното представяне, готово за директно решение с метода на
прогонката.

ai yi−1 + + =
Iα1 − β1 h − β1 2 q0 M
ci yi
Iβ1 h M y1
bi yi+1 fi
1 h 1 h
y0 + = μ1 + β1 f0 , i=0
I h2 M yi−1 I− h2 − qi M yi I h2 M yi+1
2
1 2 1 (22)
+ + = fi , i = 1, ..., n − 1
I−β2 h M yn−1 Iβ2 h + β2 2 qn + α2 M
1 1 h h
+ yn = μ2 − β2 2
fn , i=n

Т.е. имаме:
f0 , ..., fn , брой : n + 1
c0 , ..., cn , брой : n + 1
b0 , ..., bn−1 , брой : n , bn = 0
a1 , ..., an , брой : n , a0 = 0
4 ОДУ 2-ри ред

ü Реализация

ü Метод на прогонката

Получаваме данните във вид на вектори (не като матрица), което има смисъл предвид специализираността на метода.
Друг е въпроса, че този метод, представляващ модификация на този на Гаус, може да бъде използван за
по-икономичното решаване на n-диагонална матрица, където представянето на данните като вектори (а не като sparse
матрица например) вероятно ще е по-неудобно. Също тук са пропуснати известна доза проверки за валидност на
началните данни – практика срещана във функционалното програмиране.
H∗ Изчистваме символа преди да го въведем. Когато сменяме
сигнатурите на функциите би имало проблеми, ако не го направим ∗L
ClearAll@tridiagD;

H∗ Информация за функцията. Извиква се с ?tridiag ∗L


tridiag::usage = "tridiag@a, b, c, fD връща решението на тридиагонална система, където:

– a е вектор с числата от диагонала под главния, записани отгоре−надолу;


– c е вектор с числата от главния диагонал, записани отгоре−надолу;
– b е вектор с числата от диагонала над главния диагонал, записани отгоре−надолу;
– f е вектор с числата от дясната страна на системата, записани отгоре−надолу.

Изисквания

1. Векторите c и f трябва да имат еднаква размерност, да кажем: n + 1.


2. Векторите a и b трябва да имат еднаква размерност, а именно: n.

Пример

tridiag@8a1, a2<, 8b0, b1<, 8c0, c1, c2<, 8f0, f1, f2<D решава системата

ê c0 b0 0 \\ ê f0 \\
» a1 c1 b1 » = » f1 »
\\ 0 a2 c2 ê \\ f2 ê
";

H∗ Съобщение за грешка при лошо подадени данни ∗L


tridiag::badinput = "Моля, подавайте данните във вид на вектори с нужните размерности:
– f и c: n + 1
– a и b: n

За повече информация: ?tridiag";

H∗ Дефиниция на функцията. Функцията работи само за вектори от числа. ∗L


tridiag@a_ ê; VectorQ@a, NumberQD True, b_ ê; VectorQ@b, NumberQD True,
c_ ê; VectorQ@c, NumberQD True, f_ ê; VectorQ@f, NumberQD TrueD :=
Светлин Анков 5

H∗ Модул − променливите остават локални ∗L


ModuleB
8
H∗ долните ще wrap−ват индексите∗L
aa, bb, cc, ff,
H∗ долните са познатите коефициенти от формулите∗L
α, β,
H∗ хубаво е работните променливи да се държат локални ∗L
n, y, i
<,
n = Length@fD;

H∗ Проверка за размерността на векторите ∗L


If@Length@cD ≠ n Í Length@aD ≠ n − 1 Í Length@bD ≠ n − 1,
Message@tridiag::badinputD;
Return@D;
D;

H∗
Тъй като в Mathematica всичко е изрази Hвключително и списъците, т.е. векторитеL,
нулевият елемент на един израз е запазен за главата му и следователно
индексите на елементите на един вектор започват от единица. С цел
да не усложняваме излишно индексите сме въвели wrapping функции,
които оправят този проблем. Необходимо е да дефинираме и стойност за a0 =0,
тъй като тя се използва от формулите.
∗L

aa@0D = 0;
aa@i_D := aPiT;
bb@i_D := bPi + 1T;
cc@i_D := cPi + 1T;
ff@i_D := fPi + 1T;

H∗ дефинираме началните стойности за α и β ∗L

bb@0D
α@0D = − ;
cc@0D
ff@0D
β@0D = ;
cc@0D

H∗
По−странният синтаксис се обяснява с употребата на динамично програмиране.
Тъй като стойностите на α и β се изчисляват рекурентно,
неколкократно пресмятане би било излишно.
При този подход стойностите веднъж пресметнати няма да се пресмятат отново.
6 ОДУ 2-ри ред

Коефициентите са променени,
поради необходимостта аргумента да е от вида i, а не i + 1.
∗L
bb@i − 1D
α@i_D := α@iD = − ;
cc@i − 1D + aa@i − 1D α@i − 1D

ff@i − 1D − aa@i − 1D β@i − 1D


β@i_D := β@iD = ;
cc@i − 1D + aa@i − 1D α@i − 1D

H∗ Запомняме стойността за y ∗L
y@nD = β@nD;

H∗ Не много красиво от функционална гледна точка,


но тук използването на цикъл е съвсем на място. ∗L
For@i = n − 1, i ≥ 0, i −−,
y@iD = α@iD y@i + 1D + β@iD;
D;

H∗
Връщаме стойностите във вид на вектор
Hкоито досега са били във вид на конкретни стойности за функцияL.
∗L
Array@y, nD
F

H∗ Вариант на функцията, удобен за списъци от вектори ∗L


tridiag@x_ListD :=
If@Length@xD ≠ 4,
Message@tridiag::badinputD,
tridiag@xP1T, xP2T, xP3T, xP4TD
D;
Светлин Анков 7

ü Диференчна схема

H∗ Изтриваме символа преди да го въведем. Когато сменяме


сигнатурите на функциите би имало проблеми, ако не го направим ∗L
ClearAll@diffode2D;

H∗ Информация за функцията. Извиква се с ?diffode2 ∗L


diffode2::usage = "
Диференчна схема смятаща гранично ОДЕ от 2−ри ред с грека OHh2 L.

Сигнатура:
diffode2@qHxL,fHxL,8x0 ,xn <,8α1 ,β1 ,μ1 <,8α2 ,β2 ,μ2 <,nD
n – брой интервали

Изпозлва метода на прогонката HtridiagL,


за да реши тридиагоналната система,
получена след формирането на диференчната схема.
";

diffode2@q_, fx_, 8x0_, xn_<, 8α1_, β1_, μ1_<, 8α2_, β2_, μ2_<, n_D :=
H∗ името на входния параметър за f е fx,
за да ползвам f за коефициентите от 3−диаг. системата. ∗L

ModuleB

:
H∗ a,b,c,f → коефициенти в тридиагоналната система;
h−стъпка ∗L
xn − x0
a, b, c, f, h = ,

H∗ символи за временни сметки ∗L


n

t1, i
>,

H∗ за i = 0 ∗L
β1 h
c@0D = α1 − − β1 q@x0D;
h 2
β1
b@0D = ;
h
h
f@0D = μ1 + β1 fx@x0D;
2

H∗ за i = 1, ..., n−1 ∗L
H∗ Тъй като всички стойности са константи,
най−ефективно е по следния начин: ∗L
8 ОДУ 2-ри ред

1
a@i_D = b@i_D = ;
h2
H∗ остава да въведем неконстантните стойности за c,
2
но преди това да сметним константната стойност ∗L
h2
2
t1 = ;
h2

For@i = 1, i < n, i ++,


c@iD = − t1 − q@x0 + i hD;
f@iD = fx@x0 + i hD;
D;

H∗ за i = n ∗L
β2
a@nD = − ;
h
β2 h
c@nD = α2 + + β2 q@xnD;
h 2
h
f@nD = μ2 − β2 fx@xnD;

H∗ Връщаме резултата, ползвайки tridiag, за да решим системата. ∗L


2

tridiag@
Array@a, n, 1D, Array@b, n, 0D, Array@c, n + 1, 0D, Array@f, n + 1, 0D
D
H∗ 8Array@a,n,1D,Array@b,n,0D,Array@c,n+1,0D,Array@f,n+1,0D< ∗L
F
Светлин Анков 9

ü Метод на Рунге за практическа оценка на грешката

H∗ Изтриваме символа преди да го въведем. Когато сменяме


сигнатурите на функциите би имало проблеми, ако не го направим ∗L
ClearAll@rungeEstErrorD;

H∗ Информация за функцията. Извиква се с ?rungeEstError ∗L


rungeEstError::usage = "
rungeEstError@yh ,y h ,y h D извежда реда на сходимост в общите точки
2 4

при дадени мрежи от решения yh ,y h ,y h ";


2 4

rungeEstError::badinput =
"Моля, въвеждайте данните във вида:
rungeEstError@yh ,y h ,y h D,
2 4

където съответните мрежи трябва да имат съответния брой елементи:


− yh : n+1
− y h : 2n + 1
2

− y h : 4n + 1";
4

rungeEstError@yh_, yh2_, yh4_D :=


ModuleB
8n = Length@yhD, i, α, ω<,

H∗ Проверка за валидност на входните данни ∗L


If@
VectorQ@yh, NumberQD False
Í VectorQ@yh2, NumberQD False
Í VectorQ@yh4, NumberQD False,
Message@rungeEstError::badinputD;
Return@D;
D;

H∗ Проверка за валидност на броя елементи ∗L


If@n < 1 Í H2 Hn − 1L + 1 ≠ Length@yh2DL Í H4 Hn − 1L + 1 ≠ Length@yh4DL,
Message@rungeEstError::badinputD;
Return@D;
D;

H∗ Да оправим индексите с един wrapper∗L


ω@i_, h_D := h Hi − 1L + 1;

ForBi = 1, i ≤ n, i ++,
α@iD =
IfByh2Pω@i, 2DT − yh4Pω@i, 4DT 0,
0,
FF
yhPω@i,1DT−yh2Pω@i,2DT
LogBAbsB
yh2Pω@i,2DT−yh4Pω@i,4DT

Log@2D
F;

F;
Array@α, nD
F
10 ОДУ 2-ри ред

Output функция

Нека за улеснение и прегледност напишем и функция, печатаща резултата в приличен вид.

ClearAll@diffode2printD;

diffode2print@q_, fx_, 8x0_, xn_<,


8α1_, β1_, μ1_<, 8α2_, β2_, μ2_<, n_Integer ê; 0 ≤ n < ∞D :=
ModuleB8α, yh, yh2, yh4, u, h<,
Style@"\nOutput за ОДУ, 2−ри ред", "Subsubtitle"D êê Print;
H∗ Тъй като искаме u да остане локално, то ще се наложи да го заместваме със стринг,
тъй като в противен случай ще го видим с
локалното му уникално име Hнещо от рода на u$603 и т.н.L ∗L
Print@TraditionalForm@u ''@xD − q@xD u@xD ê. u → "u"D, " = ", TraditionalForm@fx@xDD,
", x ∈ H", TraditionalForm@x0D, ", ", TraditionalForm@xnD, "L"D;
Print@TraditionalForm@α1 u@x0D + β1 u '@x0D ê. u → "u"D, " = ", TraditionalForm@μ1DD;
Print@TraditionalForm@α2 u@xnD + β2 u '@xnD ê. u → "u"D, " = ", TraditionalForm@μ2DD;
Print@"Интервали: ", nD;
Print@D;
yh = diffode2@q, fx, 8x0, xn<, 8α1, β1, μ1<, 8α2, β2, μ2<, nD êê N;
yh2 = diffode2@q, fx, 8x0, xn<, 8α1, β1, μ1<, 8α2, β2, μ2<, 2 nD êê N;
yh4 = diffode2@q, fx, 8x0, xn<, 8α1, β1, μ1<, 8α2, β2, μ2<, 4 nD êê N;
α = rungeEstError@yh, yh2, yh4D êê N;
xn − x0
h= ;

tableData = 8
n

Table@x0 + i h, 8i, 0, n<D êê N,


yh,
Table@yh2@@2 Hi − 1L + 1DD, 8i, 1, n + 1<D,
Table@yh4@@4 Hi − 1L + 1DD, 8i, 1, n + 1<D,
α
< êê Transpose;

NumberFormB

TableFormB
tableData,
TableHeadings → :None, :"xi ", "yh ", "y h ", "y h ", "αi ">>

F,
2 4

88, 8<
F

F;
Светлин Анков 11

ü Резултати

ü Проверка на метода

Преди да изведем крайните резултати, нека проверим дали методът не прави логически грешки, т.е. дали наистина
работи. За целта ще решим задачата с Mathematica и с diffode2 и ще сравним резултата. Нека търсим решение на
нашата задача в 30 точки:
soldiffode2 =

&, I2 Sin@ D + I3 + M Cos@ DM &, :0, >, 80, 1, 1<, 81, 0, 0<, 30F êê N
π
2
diffode2B3
2
8− 1.8702, − 1.81784, − 1.76581, − 1.71435, − 1.66362, − 1.61371, − 1.56461, − 1.51627,
− 1.46857, − 1.42132, − 1.37432, − 1.3273, − 1.27997, − 1.23201, − 1.18309, − 1.13285,
− 1.08094, − 1.02701, − 0.970692, − 0.911654, − 0.849558, − 0.784086, − 0.714936,
− 0.641826, − 0.564497, − 0.48271, − 0.396247, − 0.304912, − 0.208529, − 0.10694, 0.<

Същото използвайки adaptive Runge-Kutta (извинявам се за неудобния запис, но резултатът от NDSolve е малко
необичаен (във вид на InterpolatingFunction)).

solRG = ModuleB
8y, t1<,

2 Sin@xD + Cos@xD I3 x2 + xM, y '@0D 1, yB F


π
t1 = NDSolveB:y ''@xD − 3 x y@xD 0>,
2
y@xD, :x, 0, >, Method −> "ExplicitRungeKutta"F;
π
2

TableBEvaluate@y@xD ê. t1D@@1DD, :x, 0, π ê 2, >F


π 1
2 30
F

9− 1.86984, − 1.81754, − 1.76556, − 1.71415, − 1.66346, − 1.61358, − 1.56451, − 1.51618,


− 1.4685, − 1.42127, − 1.37427, − 1.32726, − 1.27993, − 1.23197, − 1.18304, − 1.1328,

− 0.564448, − 0.482666, − 0.39621, − 0.304883, − 0.208509, − 0.106929, − 1.86845 × 10−12 =


− 1.08089, − 1.02695, − 0.970637, − 0.911598, − 0.849501, − 0.784029, − 0.71488, − 0.641773,

Да видим каква е разликата между получените резултати:

Max@Abs@soldiffode2 − solRGDD

0.000352618

Наистина съвсем убедителна.


12 ОДУ 2-ри ред

ü Крайни резултати за конкретната задача

Е, вече уверени в правотата на написания код, можем да изведем крайния резултат.

&, I2 Sin@ D + I3 + M Cos@ DM &, :0, >, 80, 1, 1<, 81, 0, 0<, 10F
π
2
diffode2printB3
2

Output за ОДУ, 2-ри ред

u HxL − 3 x u@xD = I3 x2 + xM cosHxL + 2 sinHxL, x ∈ H0, L


π
2
u H0L = 1

uB F = 0
π
2
Интервали: 10

xi yh yh yh αi
2 4

0.00000000 −1.87300670 −1.87063620 −1.87004160 1.99509400


0.15707963 −1.71592710 −1.71459650 −1.71426190 1.99121090
0.31415927 −1.56544740 −1.56474210 −1.56456440 1.98889650
0.47123890 −1.42180210 −1.42139980 −1.42129870 1.99276370
0.62831853 −1.28034240 −1.28003050 −1.27995270 2.00420050
0.78539816 −1.13324060 −1.13290960 −1.13282750 2.01222760
0.94247780 −0.97113769 −0.97076151 −0.97066836 2.01384780
1.09955740 −0.78454560 −0.78415704 −0.78406078 2.01316400
1.25663710 −0.56489275 −0.56455874 −0.56447595 2.01247770
1.41371670 −0.30515005 −0.30494905 −0.30489924 2.01276050
1.57079630 0.00000000 0.00000000 0.00000000 0.00000000

You might also like