Upload
others
View
17
Download
0
Embed Size (px)
Citation preview
КИЇВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ ІМЕНІ ШЕВЧЕНКА
В.А. КАЛІОН, І.Ю. СЕМЕНОВА, М.В. ЛАВРЕНЮК
ОСНОВИ ІНФОРМАТИКИ ОБЧИСЛЮВАЛЬНИЙ ПРАКТИКУМ
НА ФОРТРАНІ
Навчальний посібник
Київ 2015
2
УДК 004(075.8) ББК 32.97я73 К11
Рецензенти: д-р фіз.-мат. наук, проф. Ю. А. Бєлов,
д-р техн. наук Ковалець І. В.
Рекомендовано до друку вченою радою механіко-математичного факультету
(протокол № 2 від 17 вересня 2015 року)
Каліон В. А., Лавренюк М.В., Семенова І.Ю.,
К17 Основи інформатики. Обчислювальний практикум на Фортрані : навчальний посібник / В. А. Каліон, М.В.Лавренюк, І.Ю.Семенова . – К. : Видавничо-поліграфічний центр "Київський університет", 2016. – 245с.
ІSBN 978-966-439-402-1
Посібник містить характерні задачі з програмування найпростіших обчислювальних методів комп’ютерної механіки на основі алгоритмічної мови Fortran. Кожен розділ посібника починається короткою теоретичною частиною. До кожного розділу підібрано низку характерних задач для виконання на лабораторних заняттях із сучасних систем програмування, які передбачені навчальним планом.
Цей посібник призначено для забезпечення проведення лабораторних занять із сучасних систем програмування для бакалаврів фізико-математичних спеціальностей вищих закладів освіти. Він також може бути використаний для проведення практичних занять з практикуму на комп’ютерах й для інших спеціальностей, де в курсі інформатики є програмування на мові Fortran.
УДК 519.682 ББК 22.253я73
ISBN 978-966-439-402-1 © Каліон В. А.,Лавренюк М. В.
,Семенова І.Ю. 2016
© Київський національний університет імені Тараса Шевченка,
ВПЦ "Київський університет", 2016
3
Передмова Ця книга написана на основі практичних занять із сучасних
систем програмування, які проводять автори для бакалаврів-механіків механіко-математичного факультету Київського національного університету імені Тараса Шевченка протягом останніх років. Книга містить основні теоретичні положення програмування класичних обчислювальних методів на алгоритмічній мові Fortran. До кожного розділу книги дібрано характерні задачі і вправи для практикумів на комп’ютері, які передбачені навчальним планом. Автори сподіваються, що виконання запропонованих задач буде сприяти закріпленню матеріалу та його більш глибокому розумінню, а також сприятиме практичному застосуванню отриманих знань. Знати – значить вміти. Посібник є другою частиною курсу структурного
програмування на алгоритмічній мові Fortran і містить матеріал, що дозволить читачу самостійно будувати алгоритми розв’язання найпростіших обчислювальних задач комп’ютерної механіки. У тому числі числові методи :
• знаходження коренів поліномів і трансцендентних рівнянь,
• розв’язання систем лінійних та нелінійних рівнянь,
• знаходження власних значень і власних векторів матриці,
• обробки числових даних,
• розв’язання задачі Коші для звичайних диференціальних рівнянь та їх систем.
Книга призначена для студентів-бакалаврів механіко-математичних факультетів університетів, а також буде корисна усім, хто цікавиться використанням алгоритмічної мови Fortran і обчислювальних методів у задачах механіки. Автори висловлюють щиру подяку за підтримку завідувачу
кафедри механіки суцільних середовищ механіко-математичного факультету Київського національного
4
університету імені Тараса Шевченка професору Лимарченку Олегу Степановичу. Автори висловлюють також подяку рецензентам :
професору КНУ імені Тараса Шевченка, доктору фізико-математичних наук, Бєлову Юрію А. та зав. відділом Інтелектуальних інформаційно-аналітичних систем ІПММС НАН України, доктору технічних наук Ковальцю Івану Васильовичу.
Київ, вересень 2014 року В.Каліон, М.Лавренюк, І.Семенова
5
Вступ Визначимо місце числових методів у системі знань.
Математика, як наука, виникла через необхідність розв’язання практичних задач: вимірювань на місцевості, будівництва, торгівлі, навігації. Внаслідок цього в давнину математика була тільки числовою, адже її метою було одержання розв’язку у вигляді числа. Тепер “чистий” математик лише ставить задачу, доводить, що її розв’язок існує і що він – єдиний, хоча з практичного погляду значно важливіше (і дорожче) одержання цього розв’язку. Числовий розв’язок задач завжди цікавив математиків.
Видатні дослідники минулого об’єднували у своїх дослідженнях вивчення явищ природи, одержання їх математичної моделі та її дослідження. Аналіз цих моделей вимагав створення спеціальних, звичайно, числових або аналітико-числових методів їх розв’язання. Назви цих методів − метод Ньютона, метод Ейлера, метод Лобачевського, метод Гаусса, метод Ерміта − свідчать про те, що їх розробкою займалися найвидатніші вчені свого часу. Сьогодні значно розширено застосування математики, що в
першу чергу, пов’язано зі створенням і розвитком засобів обчислювальної техніки. Причому прогрес у розвитку комп’ютерів не порівнянний із розвитком жодної галузі у сучасній історії техніки. Якщо, наприклад, спроектувати розвиток комп’ютерів на автомобілебудування, то наразі автомобілі мали б їздити зі швидкістю світла та витрачати на тисячу кілометрів міліграми пального. Сказане вище ілюструє взятий із Вікіпедії1 графік (рис. 1), де
похилою лінією зображено тенденцію зміни швидкодії суперкомп’ютерів-кластерів. Із рисунку видно, що швидкодія збільшується в 1000 разів приблизно кожні 10-15 років. Важливо, що тут досить суттєва частка власне програмного забезпечення і обчислювальних методів. Причому сьогодні вказана тенденція в цілому зберігається.
1 https://ru.wikipedia.org/wiki/FLOPS
6
Рис. 1. Зростання швидкодії комп’ютерів у флопсах1.
Наведемо приклад, що ілюструє вказану вище тенденцію. Розв’язання диференціальних рівнянь у частинних похідних
зводиться до розв’язання системи лінійних алгебраїчних
рівнянь (СЛАР), у кожному рядку якої 3–10 ненульових
елементів. До появи комп’ютерів такі системи розв’язували для
10–100 невідомих, зараз використовують для 1012
–1015
невідомих. Водночас при застосуванні старих методів
максимум досягнув би 108–10
10 невідомих (за тих самих витрат
комп’ютерного часу).
В наш час широке використання комп’ютерів і обчислювальних методів дозволили розшифрувати геном людини, досягнути найдальших куточків Сонячної системи, програмувати смартфони і томографи, пов’язати кожний куточок нашої планети сіткою Інтернету і т.і. Армія програмістів сьогодні є однією із чисельніших у світі і у майбутньому буде тільки зростати.
1 FLOPS (FLoating-point Operations Per Second) –кількість операцій із плаваючою крапкою за секунду.
роки
7
Розділ. 1. Числове розв’язання алгебраїчних та трансцендентних рівнянь
Науковцеві в процесі досліджень часто доводиться
розв’язувати алгебраїчні і трансцендентні рівняння, що може являти собою або самостійну задачу, або бути складовою частиною більш складної задачі. В обох випадках практична цінність числового методу значною мірою визначається швидкістю і ефективністю одержання розв’язку. Вибір підходящого алгоритму для розв’язання рівнянь
залежить від характеру розглянутої задачі. Задачі, що зводяться до розв’язання алгебраїчних і трансцендентних рівнянь, можна класифікувати по числу рівнянь, а також в залежності від передбачуваного характеру і числа розв’язків. На рис. 1 представлена схема класифікації рівнянь. Одне рівняння будемо називати лінійним, алгебраїчним або
трансцендентним в залежності від того, чи має воно один
Рис. 1. Класифікація рівнянь.
Алгебраїчні та транс-цендентні рівняння
Одне рівняння
Система рівнянь
Лінійне (один розв’язок)
Нелінійне Лінійна (один розв’язок)
Нелінійна (декілька розв’язків)
Алгебраїчне (n розв’язків)
Трансцендентне (невизначене число розв’язків)
8
розв’язок, n розв’язків або невизначене число розв’язків. Систему рівнянь будемо називати лінійною або нелінійної в залежності від математичної природи рівнянь, що входять до цієї системи. Розв’язання лінійного рівняння з одним невідомим досить
просте і тут не розглядається. Мета даного розділу − розгляд різних методів розв’язання рівнянь, що відносяться до інших чотирьох типів. 1.1. Корені нелінійного рівняння Згідно з наведеної на рис. 1 схеми нелінійні рівняння
поділяються на трансцендентні та алгебраїчні. Хоча алгоритми розв’язання трансцендентних і алгебраїчних рівнянь часто ті ж самі, у даному розділі методи їх розв’язання будуть розглядатися окремо, бо розв’язання алгебраїчних рівнянь має свої особливі властивості. І спочатку розглянемо розв’язання трансцендентних рівнянь; алгебраїчні рівняння будуть розглядаються пізніше. Як правило до трансцендентних рівнянь відносять
нелінійні рівняння, що містять тригонометричні функції або інші спеціальні функції, наприклад lg x або еx. Методи розв’язання нелінійних рівнянь такого типу поділяються на прямі та ітераційні. Перші дозволяють знайти розв’язок безпосередньо за допомогою формул і завжди забезпечують одержання точного розв’язку. Відомим прикладом тут є формули Вієта знаходження коренів квадратного рівняння. В ітераційних методах задається процедура розв’язання у вигляді багаторазового застосування деякого алгоритму. Отриманий тут розв’язок завжди є наближеним, хоча може бути як завгодно близьким до точного. Ітераційні методи найбільш зручні для реалізації на комп’ютері і тому саме їх ми будемо розглядати далі. Алгоритм кожного з розглянутих надалі методів зводиться
до відшукання дійсних коренів (нулів) рівняння f(x) = 0. Зауважимо, що хоча трансцендентні рівняння також можуть
9
мати і комплексні корені, способи їх відшукання звичайно розглядаються тільки для алгебраїчних рівнянь.
Метод половинного ділення. Алгоритм метода складається з наступних етапів. Спочатку обчислюються значення функцій у точках, що розташовані через рівні проміжки на осі Ох. Процедура ця виконується доти, поки не будуть знайдено два послідовні значення функції f(xn) та f(xn+1), які мають протилежні знаки. (Нагадаємо, що для неперервної функції зміна знака вказує на існування кореня.) Потім по формулі
1
2n n
cp
x xx + += (1.1)
обчислюється середнє значення х в інтервалі значень [xn , xn+1] та значення функції f(хср). Якщо знак f(хср) збігається зі знаком f(xn), то надалі замість
f(xn) використовується f(хср). Якщо ж f(хср) має знак, що протилежний знаку f(xn), тобто її знак збігається зі знаком
Рис. 2. Метод половинного ділення.
x1
x2
x3
f(x1)
f(x2)
f(x3)
x
y
x4
f(x4)
10
Рис. 3. Блок-схема алгоритму методу половинного ділення.
xn = xcp f(xn) = f(xcp)
Обчислення функції через рівні проміжки значення х до зміни знаку при переході від
f(xn) до f(xn+1)
Обчислення xcp й f(xcp)
Чи однакові знаки f(xср) й f(xn) ?
Так
Ні
xn+1 = xcp f(xn+1)=f(xcp)
Чи достатньо мала величина
f(xср)
Так
Ні
Stop
11
f(xn+1), то f(хср) заміняє це значення функції. В результаті інтервал, який містить значення кореня, звужується вдвоє. Якщо величина f(хср) досить близька до нуля, процес закінчується, а якщо ні, то він триває далі. На рис. 2 ця процедура показана графічно. Хоча метод половинного ділення має невисоку обчислювальну ефективність, зі збільшенням числа ітерацій він забезпечує одержання все більш точного наближеного значення кореня. Після того, як вперше знайдено інтервал, що містить
корінь, його ширина після N ітерацій зменшується в 2N разів. Блок-схема алгоритму методу половинного ділення
представлена на рис. 3. Метод хорд. В основі цього методу лежить лінійна
інтерполяція по двом значенням функції, які мають протилежні знаки. При відшуканні кореня цей метод нерідко забезпечує більш швидку збіжність, ніж попередній. Як і в методі половинного ділення спочатку визначаються значення функції в точках, що розташовані на осі Ох через рівні проміжки. Ця процедура виконується доти, поки не буде знайдена пара послідовних значень функції f(xn) та f(xn+1), які мають протилежні знаки (див. рис.4). Пряма, проведена через ці дві
Рис. 4. Метод хорд.
x1
x2
x3
f(x1)
f(x2)
f(x3)
x
y
f(x4)
x4
12
Рис. 5. Блок-схема алгоритму методу хорд.
xn = x* f(xn) = f(x*)
Обчислення функції через рівні проміжки значення х до зміни знаку при переході від
f(xn) до f(xn+1)
Обчислення x* й f(x*)
Чи однакові знаки f(x*) й f(xn) ?
Так
Ні
xn+1 = x* f(xn+1)=f(x*)
Чи достатньо мала величина
f(x*)
Так
Ні
Stop
13
точки, перетинає вісь Ох у точці
* 1
1
( )( ) ( )
n nn n
n n
x xx x f x
f x f x+
+
−= −
−. (1.2)
Це значення аргументу використовується для визначення значення функції f(х*), яке порівнюється зі значеннями функцій f(xn) та f(xn+1) і надалі використовується замість того з них, з яким воно збігається за знаком. Якщо значення f(x*) недостатньо близьке до нуля, то вся процедура повторюється доти, поки не буде досягнутий необхідний ступінь збіжності. Блок-схема алгоритму методу хорд дана на рис. 5.
Метод Ньютона. Запропонований Ньютоном метод послідовних наближень широко використовується при побудові ітераційних алгоритмів. Його популярність обумовлена швидкою збіжністю і тим, що на відміну від двох попередніх методів, для визначення інтервалу, який містить корінь, не потрібно знаходити значення функції із протилежними знаками. Замість інтерполяції по двом значенням функції в методі Ньютона здійснюється екстраполяція із використанням дотичної до кривої в даній точці (див. рис.6). В основі методу лежить розвинення функції f(x) у ряд
Тейлора
Рис. 6. Метод Ньютона.
x1
x2 x3
f(x1)
f(x2)
f(x3) x
y
14
2
( ) ( ) ( ) ( )2n n n n
hf x h f x h f x f x′ ′′+ = + + +… . (1.3)
Члени, що містять h у другій і більш високих степенях, відкидаються; використовується співвідношення xn+h ≡ xn+1. Передбачається, що перехід від xn до xn+1 наближає значення функції до нуля так, що f(xn+h) = 0. Тоді
1 ( ) ( )n n n nx x f x f x+ ′= − . (1.4) Тут xn+1 відповідає точці, де дотична до кривої в точці xn перетинає вісь Ох. Оскільки крива f(x) відмінна від прямої, то значення функції f(xn+1) швидше за все не буде в точності дорівнювати нулю. Тому вся процедура повторюється,
Рис. 7. Блок-схема алгоритму методу Ньютона.
Вибір підходящого початкового значення xn
Обчислення xn+1 й f(xn+1)
Чи достатньо мала величина
f(xn+1)
Так
Ні
Stop
xn = xn+1
15
причому замість xn використовується вже xn+1. Розрахунок припиняється при досягненні достатньо малого значення f(xn+1).
Зауваження: • Швидкість збіжності методу Ньютона у великій мірі
залежить від вдалого вибору початкової точки. • Якщо в процесі ітерацій тангенс кута нахилу дотичної
f '(x) обертається на нуль, то застосування методу неможливе.
• Можна також показати, що у випадку нескінченно великого f"(х) метод також не буде досить ефективним.
• Оскільки умова кратності коренів має вигляд f(x) = f '(x) = 0, то і в цьому випадку метод Ньютона не забезпечує збіжність. Відзначимо, що тоді використовується інший спосіб контролю збіжності, що полягає в порівнянні xn й xn+1 .
На рис. 7 показана блок-схема алгоритму методу Ньютона. Розглянемо приклад знаходження кореня рівняння
2( ) 0.5 1 ( 2) 0xf x x= − + + = при x0 = 0. Код програми: program newton use NEWTON_RAPHSON implicit none ! declare variables integer :: maxiter=100 real :: f, zero, x0 = 0.0, tol = 1.0e-5 logical success external f open(2,file='zeros.txt') call find_root( f, x0, tol, maxiter, zero, success ) if (success) then write(2,'(/,a,\)') ' Zero found is ' write(2,'(1x,f8.4)') zero else write(2,*) ' Zero is not found ' end if
16
end program newton !----------------------------------------- real function f(x) real, intent(in) :: x f = 0.5**x-1.+(x-2.)**2 end function f
Для розв’язання задачі ми скористалися підпрограмою
знаходження коренів рівняння за методом Ньютона find_root, що міститься в модулі NEWTON_RAPHSON, який знаходиться в Додатку.
Результат роботи програми Zero found is 1.2405
Метод січних. Один з недоліків методу Ньютона полягає в тому, що доводиться диференціювати функцію f(х). Якщо ж знаходження похідної складне або взагалі неможливе1, то можна скористатися деяким наближенням, яке і становить основу методу січних. Замінимо похідну f(х), яка використовується в алгоритмі методу Ньютона (1.4), різницевою формулою, яка представляє собою різницю послідовних значень функції, що віднесена до різниці значень аргументу
1
1
( ) ( )( ) n n
nn n
f x f xF x
x x−
−
−′ =−
(1.5)
одержимо наступну ітераційну формулу:
1 ( ) ( )n n n nx x f x F x+ ′= − . (1.6) Блок-схема алгоритму для цього методу та ж сама, що й
для методу Ньютона (трохи інший вигляд тільки має ітераційна формула). По суті, у методі січних для відшукання кореня використовується комбінація інтерполяції та екстраполяції. У своїй інтерполяційній частині цей метод еквівалентний методу хорд. Як і у випадку методу Ньютона, розрахунок закінчується, коли послідовні значення х збігаються з деякою прийнятною 1 Наприклад, якщо функція задана таблицею.
17
точністю або коли значення функції f(х) стає досить близьким до нуля. У випадку кратних коренів при використанні методу січних виникають ті ж труднощі, що і для методу Ньютона.
Метод простої ітерації. Перед застосуванням цього методу рівняння f(x) = 0 представимо у вигляді:
( )x g x= . (1.7) Відповідною ітераційною формулою буде
1 ( )n nx g x+ = . (1.8) Блок-схема алгоритму методу представлена на рис. 8.
Рис. 1.8. Блок-схема алгоритму методу простої ітерації.
Вибір підходящого початкового значення xn
Обчислення xn+1 = g(xn) й f(xn+1)
Чи достатньо мала величина
f(xn+1)
Так
Ні
Stop
xn = xn+1
18
Простота методу простої ітерації робить його привабливим однак не слід забувати, що і цьому методу властиві недоліки, бо він не завжди забезпечує збіжність1 . Тому для будь-якої програми, де використовується цей алгоритм, необхідно передбачати контроль збіжності і припиняти розрахунки, якщо збіжність не забезпечується. 1.2. Визначення корнів алгебраїчних рівнянь Рівняння, що містять суми цілих степенів називаються
алгебраїчними. Їхній загальний вигляд 1
1 1 0 0n nn na x a x a x a−
−+ + + + =… . (1.9) При відшуканні коренів алгебраїчних рівнянь корисно мати
на увазі деякі їхні властивості: • Алгебраїчне рівняння порядку n має n коренів, які можуть бути дійсними або комплексними.
• Якщо всі коефіцієнти аi дійсні, то всі комплексні корені утворюють комплексно-спряжені пари.
• Число додатних дійсних коренів дорівнює або менше (на ціле число) числа змін знаків у послідовності коефіцієнтів аi.
• Число від’ємних дійсних коренів дорівнює або менше (на ціле число) числа змін знаків у послідовності коефіцієнтів аi при заміні х на −х. Відомі прямі методи відшукання коренів алгебраїчних
рівнянь другої та третьої степені, однак для рівнянь більш високих степенів доводиться використовувати ітераційні методи. З точки зору “чистого” математика, знайшовши будь-який корінь алгебраїчного рівняння х* ітераційним методом, можна зменшити порядок цього рівняння, розділивши його на | х − х* |, і одержати рівняння, що має порядок (n−1). На перший погляд така можливість видасться привабливої, однак користуватися нею потрібно обережно, бо навіть невелика похибка у значенні першого знайденого кореня може привести
1 Умовою збіжності метода буде || g′(x) || ≤ 1 .
19
до нагромадження помилок для коефіцієнтів рівняння (n−1)-го степеня. Відзначимо, що ця процедура нерідко дозволяє підібрати інші корені, якщо деякі корені вже відомі. Алгоритми розв’язання трансцендентних рівнянь, що
описані вище, можна використовувати і для знаходження дійсного та комплексного коренів алгебраїчних рівнянь, якщо користувач готовий мати справу із арифметикою комплексних чисел. Покажемо це на наступному простому прикладі. Приклад 2. Знайти всі корені алгебраїчного рівняння
z4 − z3 − 4z2 + 34z − 120 = 0. Скористаємося методом Ньютона із застосуванням
арифметики комплексних чисел. Нехай початкове значення z = 4 + 4 i . Тоді код програма має вигляд:
program poly1 implicit none integer :: i=0 real test, eps complex z, f, df !----------------------------------------------------- z = (4.,4.); test = 1.; eps = 1e-6 write(*,*) 'Iteration Z(Real) Z(Imag)' do while (test > eps) i = i+1 f = z**4-z**3-4.*z**2+34.*z-120. df = 4.*z**3-3.*z**2-8.*z+34. z = z - f/df write(*,'(i5,2(8x,f8.4))') i,z test = sqrt(real(f)**2+ aimag(f)**2) end do stop end program poly1
Ітерації збігаються до кореня z1 = 1+3 i. Очевидно, що
другий корінь комплексно-спряжений цьому кореню z2 = 1−3 i. Якщо тепер задати в якості початкового значення z = 2+2 i,
20
одержимо дійсний корінь z3 = 3. Корінь, що залишився, z4 = −4 знаходимо одним з відомих методів. Той же самий результат (тільки швидше) можна одержати,
якщо скористатися процедурою ZPLRC бібліотеки IMSL1. Приклад 3. Знайти всі корені алгебраїчного рівняння z3 − 3z2 + 4z − 2 = 0. Код програми: program poly2 !----------------------------------------------------- use IMSL !----------------------------------------------------- ! declare variables integer, parameter :: ndeg=3 real coeff(ndeg+1) complex zero(ndeg) ! set values of coeff ! coeff = (-2.0 4.0 -3.0 1.0) data coeff/-2.0, 4.0, -3.0, 1.0/ !----------------------------------------------------- call zplrc (ndeg, coeff, zero) write(*,*) ‘ Zeros found are ’ write(*,*) zero stop end program poly2
Результат роботи програми Zeros found are ( 1.000, 1.000) ( 1.000,-1.000) ( 1.000, 0.000)
1 Бібліотека IMSL входить до середовища Compaq Visual Fortran 6.x, а також може бути додатково інтегрована у середовище Intel Parallel Studio XE 201x.
21
1.3. Запитання та вправи 1) Що Вам відомо про структуру бібліотеки IMSL? 2) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для розв’язання трансцендентних рівнянь?
3) Які Ви знаєте ітеративні методи розв’язання трансцендентних рівнянь?
4) Наведіть алгоритм метода простої ітерації. При яких умовах метод збігається?
5) Наведіть алгоритм метода Ньютона. При яких умовах метод збігається?
6) Наведіть алгоритм метода січних. При яких умовах метод збігається?
7) Наведіть алгоритм метода половинного ділення. 8) Наведіть алгоритм метода хорд. 9*)1 Розв’язати методом половинного ділення трансцендентне рівняння 2( ) 0.5 1 ( 2) 0xf x x= − + + = при x0 = 0. Надрукувати необхідне для цього число ітерацій.
10*) Розв’язати методом хорд трансцендентне рівняння 2( ) 0.5 1 ( 2) 0xf x x= − + + = при x0 = 0. Надрукувати
необхідне для цього число ітерацій. 11*) Розв’язати методом січних трансцендентне рівняння
2( ) 0.5 1 ( 2) 0xf x x= − + + = при x0 = 0. Надрукувати необхідне для цього число ітерацій.
1.4. Практичні завдання
Завдання 1. Знаходження коренів трансцендентних та
алгебраїчних рівнянь Мета завдання:
1. Ознайомлення із процедурами знаходження коренів трансцендентних рівнянь (методом простої ітерації,
1 Тут і надалі зірочкою позначені завдання, розв’язання яких дано в кінці посібника.
22
методом Ньютона, стандартною процедурою ZREAL із бібліотеки IMSL).
2. Ознайомлення із процедурами знаходження коренів алгебраїчних рівнянь (методом Ньютона та стандартною процедурою ZPLRC із бібліотеки IMSL).
Постановка завдання: Знаходження коренів трансцендентних рівнянь й поліномів
із використанням ітеративних методів. Знаходження коренів трансцендентних рівнянь й поліномів стандартним методом із бібліотеки IMSL. Порівняти отримані розв’язки. Методичні вказівки: При підготовці до виконання роботи спочатку потрібно
познайомитися з ітеративними методами розв’язання трансцендентних рівнянь й поліномів. Всі вищенаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. З метою знаходження початкового наближення при ітеративному знаходженні коренів, виконати табулювання функції. Для цього необхідно або запрограмувати цей крок, або скористатися можливостями програми Exel.
2. Перед розв’язанням трансцендентних рівнянь методом простої ітерації перевірити умову збіжності метода || g′(x) || ≤ 1. При виконанні умови збіжності, скориставшись результатами першого кроку й блок-схемою на рис. 2.8, запрограмувати метод простої ітерації. У випадку неможливості використання методу, відобразити це у звіті і перейти до наступного кроку.
3. Скориставшись блок-схемою на рис. 2.7 й результатами першого кроку для вибору початкового наближення, запрограмувати метод Ньютона.
4. Запрограмувати всі варіанти завдання, скориставшись стандартними процедурами ZREAL й ZPLRC. Приклади використання стандартних процедур наведено в їх описі в бібліотеці IMSL.
23
5. Порівняти отримані результати. Варіанти завдання:
№ вар
Трансцендентні рівняння
Поліноми
1
2
2 5 3 0;
( 3)cos 1, [ 2π,2π];
0,5 1 ( 2) .
x
x
x
x x x
x
+ − =− = ∈ −
+ = −
4 3 2
3 2
4 3 2
3 4 12 5 0;
2 3 12 5 0;
6 11 2 28 0.
x x x
x x x
x x x x
+ − − =+ − − =
+ + − − =
2
3
2
arctg 1 3 0;
[log ( )]( 2) 1;
sin( 3) 0,5 0.
x x
x x
x xπ
+ =− + = −+ − =
3 2
3
4 3 2
2 9 60 1 0;
12 6 0;
5 9 5 1 0.
x x x
x x
x x x x
− − + =− + =+ + + − =
3 2
2
5 3 0;
( 1) lg( 11) 1;
2 0,5 0.
x
x
x
x x
x
− =− ⋅ + =− + =
4
3 2
4 3 2
1 0;
3 3 0;
3 3 2 0.
x x
x x
x x x
− − =− + =+ + − =
4
3
3
2 5 ;
log ( 1) 1;
cos( 0,5) .
xe x
x x
x x
=⋅ + =
+ =
4 2
3
4 3 2
2 10 0;
12 6 0;
7 8 6 0.
x x
x x
x x x x
− − =− + =+ − + − =
5
1
20,5
3 2 0;
( 4) log ( 3) 1;
5sin .
x x
x x
x x
− + − =
− ⋅ − = −=
4 3 2
3 2
4 3
3 8 6 10 0;
3 24 10 0;
10 16 5 0.
x x x
x x x
x x x
+ + − =+ − − =− + + =
6
3
2
2 arctg 1 2 0;
2 1;
tg , [ π 2,π 2].
x x
x x
x x x
⋅ + =⋅ =
= ∈ −
4 2
3 2
4 3 2
18 6 0;
2 3 12 10 0;
3 4 3 0.
x x
x x x
x x x x
− + =− − + =
− − − − =
7
2
2
2
2 1 0;
0.5 1 ( 2) ;
cos2 1.
x
x
e x
x
x x
− − + =
− = += −
4 3 2
3 2
4 3 2
4 8 17 0;
2 9 21 0;
4 4 4 1 0.
x x x
x x
x x x x
+ − − =+ − =
+ + + − =
24
№ вар
Трансцендентні рівняння
Поліноми
8
2
5 6 3 0;
lg( 1) 1;
2 0,5 3 0.
x
x
x
x x
x
− + =⋅ + =
− − =
4 3 2
3 2
4 3 2
2 3 3 0;
3 2,5 0;
6 13 10 1 0.
x x x x
x x
x x x x
− − + − =− + =+ + + + =
9 2
2
arctg ( 1) 2 0;
( 2) 2 1;
20 sin 0.
x
x x
x
x x
− + =
− ⋅ =
− ⋅ =
4 3 2
3 2
4 3 2
3 4 12 1 0;
3 2 0;
4 16 8 0.
x x x
x x
x x x x
+ − + =+ − =+ − + − =
10 2
2 arctg 3 0;
2sin( π 3) 0,5 1;
2 lg 2 1.
x x
x x
x x
⋅ − + =
+ = −⋅ − = −
4 3 2
3 2
4 3 2
3 8 18 2 0;
3 3,5 0;
4 11 3 0.
x x x
x x
x x x x
− − + =+ − =− − − − =
11 2
3 2 2 0;
2 [( 2) 1] 1;
( 2) cos 1, [ 2π,2π].
x
x
x
x
x x x
+ − =⋅ − − =− ⋅ = ∈ −
4 3 2
3 2
4 2
2 8 8 1 0;
3 24 10 0;
6 12 8 0.
x x x
x x x
x x x
− + − =+ − + =− − − =
12
2
2 arctg 3 2 0;
sin( 0,5) 0,5 0;
[log ( 2)] ( 1) 1.
x x
x x
x x
⋅ − + =− − + =
+ ⋅ − =
4 3 2
3 2
4 3 2
2 8 8 1 0;
3 24 8 0;
4 4 4 0.
x x x
x x x
x x x
+ + − =− − − =+ + − =
13 2
2
3 2 5 0;
0,5 3 0;
( 2) lg( 11) 1.
x
x
x
x
x x
+ − =+ − =
− ⋅ + =
4 3 2
3 2
4 3
4 8 1 0;
2 9 10 0;
2 1 0.
x x x
x x
x x x
− − + =+ − =
+ + + =
14 3
2
2 3 1 0;
log ( 1) 2;
cos( 0,3) .
xe x
x x
x x
− + =⋅ + =
+ =
4 3 2
3 2
4 3 2
3 8 18 2 0;
3 3,5 0;
4 11 3 0.
x x x
x x
x x x x
− − + =+ − =− − − − =
15
1
20,5
3 4 0;
( 3) log ( 2) 1;
5 sin .
x x
x x
x x
− − + =− − = −
⋅ =
3 2
3 2
4 2
2 9 60 1 0;
3 3 0;
3 4 1 0.
x x x
x x
x x x
− − + =+ − =+ − − =
25
№ вар
Трансцендентні рівняння
Поліноми
16
3
2
3
arctg 1 3 0;
( 1) 2 1;
tg , [ π 2,π 2].
x
x x
x
x x x
+ =− ⋅ =
= ∈ −
4
3 2
4 3 2
1 0;
2 3 12 1 0;
3 8 5 0.
x x
x x x
x x x
− − =− − + =
+ + − =
17 2
2
1 0;
0,5 3 ( 2) ;
cos2 1, [ 2π,2π].
x
x
e x
x
x x x
+ + =− = +
⋅ = − ∈ −
4 2
3 2
4 2 2
2 10 0;
3 24 5 0;
6 11 2 28 0.
x x
x x x
x x x x
− − =− − − =− + + − =
18 2
3 2 5 0;
2 0,5 2 0;
lg( 1) 1.
x
x
x
x
x x
− + =− − =
⋅ + =
4 3 2
3 2
4 3 2
3 8 6 10 0;
4 2 0;
5 9 5 1 0.
x x x
x x
x x x x
+ + − =− + =− + − − =
19 2
2
arctg ( 1) 3 1 0;
( 2) 2 1;
20 sin 0.
x
x x
x
x x
− + − =− ⋅ =− ⋅ =
4 2
3
4 3 2
18 6 0;
12 5 0;
3 3 2 0.
x x
x x
x x x
− + =− − =− + − =
20 2
2 arcctg 3 0;
2sin( π 3) 0,5;
2 lg 2 1.
x x
x x
x x
⋅ − + =− = −
⋅ − = −
4 3 2
3 2
4 3 2
4 8 17 0;
3 24 1 0;
7 8 6 0.
x x x
x x x
x x x x
+ − − =+ − + =− − − − =
21 2
2 3 2 0;
0,5 1 ( 2) ;
( 3) cos 1, [ 2π,2π].
x
x
x
x
x x x
− + =+ = −
− ⋅ = ∈ −
4 3 2
3 2
4 2
2 3 3 0;
2 3 12 12 0;
10 16 5 0.
x x x x
x x x
x x x
− − + − =− − + =
− − + =
22
2
arcctg 2 1 0;
sin( 1) 0,5 ;
( 2) log 1.
x x
x x
x x
+ − =+ =
+ ⋅ =
4 3 2
3 2
4 3 2
3 4 12 1 0;
2 9 6 0;
3 4 3 0.
x x x
x x
x x x x
+ − + =+ − =
+ + + − =
23 2
2
3 2 3 0;
0,5 4 0;
( 2) lg( 11) 1.
x
x
x
x
x x
+ − =+ − =
− ⋅ + =
4 3 2
3 2
4 3 2
3 8 18 2 0;
3 1,5 0;
4 4 4 1 0.
x x x
x x
x x x x
− − + =− + =− − − − =
26
№ вар
Трансцендентні рівняння
Поліноми
24
3
3
2 2 3 0;
log ( 1) 1;
cos( 0,5) .
xe x
x x
x x
− + =⋅ + =
+ =
4 3 2
3 2
4 3 2
3 4 12 5 0;
3 24 10 0;
2 3 2 2 0.
x x x
x x x
x x x x
+ − − =− − + =+ + + − =
25 2
0,5
3 2 0;
( 4) log ( 3) 1;
5 sin .
x x
x x
x x
− + =− − = −
⋅ =
3 2
3 2
4 2 2
2 9 60 1 0;
3 24 3 0;
6 13 10 1 0.
x x x
x x x
x x x x
− − + =+ − − =− + − + =
26 2
3
arcctg ( 1) 2 3 0;
( 1) 2 1;
tg , [ π 2,π 2].
x
x x
x
x x x
− + − =− ⋅ =
= ∈ −
4
3
4 2
1 0;
12 10 0;
3 4 3 0.
x x
x x
x x x
− − =− − =− + − =
27
2
2
2
2 1 0;
0,5 3 ( 1) ;
cos2 1.
x
x
e x
x
x x
− − + =− = − +
⋅ = −
4 2
3 2
4 2
2 10 0;
2 9 4 0;
6 12 8 0.
x x
x x
x x x
− − =+ − =
− + − =
28 2
3 2 5 0;
2 0,5 3 0;
lg( 1) 1.
x
x
x
x
x x
− + =− − =
⋅ + =
4 3 2
3 2
4 3 2
3 8 6 10 0;
2 3 12 8 0;
4 4 4 0.
x x x
x x x
x x x
+ + − =− − + =
− + − =
29 2
2
arctg ( 1) 2 0;
20 sin 0;
( 2) 2 1.x
x x
x x
x
− + =− ⋅ =− ⋅ =
4 2
3 2
4 3
18 6 0;
3 1 0;
2 1 0.
x x
x x
x x x
− + =+ − =− − + =
30
3
2
3
arctg 1 3 0;
( 1) 2 1;
tg , [ π 2,π 2].
x
x x
x
x x x
+ =− ⋅ =
= ∈ −
4
3 2
4 3 2
1 0;
2 3 12 1 0;
3 8 5 0.
x x
x x x
x x x
− − =− − + =
+ + − =
27
Розділ 2. Методи розв’язання систем лінійних та нелінійних алгебраїчних рівнянь
Відомо, що розв’язання будь-якої крайової задачі із
використанням наближених числових методів зводиться до розв’язання системи нелінійних алгебраїчних рівнянь (СНЛАР)
( )A v v b⋅ =�� �
(2.1) або системи лінійних алгебраїчних рівнянь (СЛАР)
A v b⋅ =��
, (2.2)
де вектор { }1 2, , ,T
nv v v v=� … містить дискретні значення
невідомих, а компоненти матриці A для (2.2) і вектора b�
вважаються відомими1. Розглянемо основні методи, що використовуються для розв’язання систем (2.1) або (2.2). 2.1. Прямі методи розв’язання систем лінійних алгебраїчних
рівнянь Розглянемо розширену систему лінійних алгебраїчних
рівнянь (СЛАР) у вигляді (2.2). Методи розв’язання цієї системи поділяють на три категорії залежно від вигляду матриці A :
I. A − щільна;
II. A − розріджена;
III. A − стрічкова. Для першої групи методів найбільш характерними є метод
виключення Гаусса, а також методи факторизації, які є узагальненням методу Гаусса [5]. Розглянемо спочатку класичний метод Гаусса. Представимо
систему (2.2) у вигляді (0) (0) (0) (0)
1 2 311 12 13 1
(0) (0) (0) (0)1 2 321 22 23 2
;
;
a x a x a x b
a x a x a x b
+ + =
+ + =
1 Літера Т тут і далі вказує на процедуру транспонування.
28
(0) (0) (0) (0)1 2 331 32 33 3 .a x a x a x b+ + = (2.3)
Нехай (0)11 0a ≠ . Розділивши перший рядок в (2.12) на (0)
11a ,
маємо (1) (1) (1)
1 2 312 13 1x a x a x b+ + = , (2.4)
де (1) (0) (0) (1) (0) (0)1 1 11 1 1 11, 2,3;j ja a a j b b a= = = . (2.5)
Виключимо за допомогою (2.4) невідому х1 із другого та третього рівняння (і також наступних, якщо загальна кількість рівнянь > 3). Після перетворення маємо
(1) (1) (1)2 322 23 2
(1) (1) (1)2 332 33 3
;
,
a x a x b
a x a x b
+ =
+ = (2.6)
де (1) (0) (1) (0) (1) (0) (1) (0)1 1 1 1, ( , 2,3)ij ij i ij i ia a a a b b b a i j= − = − = . (2.7)
Нехай тепер (1)22 0a ≠ . Розділивши перший рядок в (2.6) на (1)
22a ,
маємо (2) (2)
2 323 2x a x b+ = , (2.8)
де (2) (1) (1) (2) (1) (1)2 2 22 2 2 22, 3;j ja a a j b b a= = = . (2.9)
Виключаючи за допомогою (2.8) невідому х2 із третього рівняння (і також наступних, якщо загальна кількість рівнянь > 3), маємо
(2) (2)333 3a x b= , (2.10)
де (2) (1) (2) (1) (2) (1) (2) (1)2 2 2 2, ( , 3)ij ij i ij i ia a a a b b b a i j= − = − = . (2.11)
Якщо тепер (2)33 0a ≠ , то розділивши третє рівняння на (2)
33a ,
маємо (3)
3 3x b= , (2.12)
де (3) (2) (2)3 3 33b b a= . (2.13)
Таким чином система (2.3) еквівалентна системі із верхньою трикутною матрицею
29
(1) (1) (1)1 2 312 13 1
(2) (2)2 323 2
(3)3 3
;
;
.
x a x a x b
x a x b
x b
+ + =
+ =
=
(2.14)
Із системи (2.14) невідомі визначаються у зворотному порядку (3)
3 3
(2) (2)2 32 23
(1) (1) (1)1 2 31 12 13
;
;
.
x b
x b a x
x b a x a x
=
= −
= − −
(2.15)
Процедура приведення системи (2.3) до верхньотрикутної матриці у вигляді (2.14) називається прямим ходом методу Гаусса, а визначення невідомих за (2.15) − зворотнім ходом методу Гаусса.
Зауваження:
• Обмеження ( ) 0iiia ≠ не є особливо жорстким, бо завжди
можна шляхом перестановки рядків (або стовпчиків) матриці A переставити на діагональ ненульовий елемент.
• Зважаючи на перше зауваження ми можемо суттєво
модифікувати метод Гауса, якщо в якості ( )iiia вибрати
максимальний за модулем елемент рядка за номером і. При факторизації матриця A , усі головні діагональні
мінори якої відмінні від нуля, перетворюється на матрицю такого вигляду
T A= L U⋅ ⋅ , (2.16)
де L − нижньотрикутна (ліва) матриця з одиницями на
головній діагоналі, а U − верхньотрикутна (права) матриця, T
− матриця перестановок. Матриця T A⋅ − це та ж сама матриця
A , в якій переставлені рядки. Оскільки в матриці T , яка має
порядок N×N, в кожному рядку і кожному стовпчику є рівно одна одиниця і N−1 нуль, то, звичайно, замість матриці
30
перестановок зберігають вектор, який містить всю інформацію про перестановки в матриці A .
В процесі розкладання (декомпозиції) матриці A важливо витримати послідовність кроків, оскільки наступні елементи обраховуються з врахуванням попередніх. Для i = 1:
1 1
1 1 11 11
, 1, , ;
, 1, , ( 0)
j j
j j
u a j N
l a u j N l
= =
= = ≠
…
… (2.17)
де 1 1 1, ,j j ja l u − елементи матриць , ,A L U відповідно. Далі для
i від 2 до N: 1
1
, , , ;i
ij ij ik kjk
u a l u j i N−
== − ⋅ =∑ … (2.18)
1
1
1, 1, ,
i
ji ji jk kikii
l a l u j i Nu
−
=
= − ⋅ = +
∑ … . (2.19)
Після цього замість (2.2) розв’язується дві трикутні системи рівнянь:
,Ly b U v y= =�� � �
. (2.20) Зауваження:
• Внаслідок структури матриць L та U розв’язання матрично-векторних рівнянь (2.20) зводиться до послідовних підстановок, подібних (2.15).
• Матриці зі щільною структурою маємо при дискретизації за спектральним або панельним методом, а також за методом дискретних особливостей.
• Матриці з розрідженою структурою також розв’язуються за методом Гаусса, однак, часто замість збереження всієї матриці A зберігають тільки її ненульові
елементи та їх положення у матриці A (індикаторний
масив IA ). Основна складність тут, що у процесі виключення стають відмінними від нуля ті елементи матриці A , які спочатку дорівнювали нулю. Тому для
31
розріджених матриць, що не мають стрічкової структури найкращими є методи ортогоналізації (Гівенса, Хаусхолдера, QR-алгоритм), які не додають нові ненульові елементи до матриці A [5, 22, 24].
Скористаємося методом факторизації для розв’язання
СЛАР (2.11), якщо 1 3 3 1 10
1 3 4 , 4 14
1 4 3 1 9
A= B
= −
. (2.21)
Тут стовпчики матриці B − це різні праві частини рівняння (2.11). Код програми:
program factor2 use solve_LAEA1 implicit none integer,parameter :: n=3 integer ipvt(n), j, i real a(n,n), b(n,2) data a/1.0, 1.0, 1.0, 3.0, 3.0, 4.0, 3.0, 4.0, 3.0/ data b/1.0, 4.0, -1.0, 10.0, 14.0, 9.0/ open(2,file='fact2.txt') call fact(n,a,ipvt) ! Solve for the two right-hand sides do j=1,2 call solve(n,a,ipvt,b(:,j)) end do write(*,*) 'X'; write(2,*) 'X' do i=1,n write(*,*) i,(b(i,j),j=1,2); write(2,*) i,(b(i,j),j=1,2) end do end program factor2 1 Модуль solve_LAEA знаходиться в Додатку.
32
Результат роботи програми X 1 -2.000 1.000 2 -2.000 -1.000 3 3.000 4.000 Аналогічний результат отримаємо, якщо скористатися для
факторизації підпрограмою LFTRG, а для розв’язання спрощеної системи рівнянь (2.20) підпрограмою LFSRG 1. Для симетричних матриць A існують методи, які
дозволяють отримати їх подання у вигляді добутку матриць за більш швидкою процедурою, ніж за алгоритмом факторизації, який фактично базується на методі виключення Гаусса. До таких методів “прискореної” факторизації відноситься, наприклад, метод квадратного кореня, який вдвічі швидший, ніж метод звичайної факторизації. За алгоритмом метода квадратного кореня маємо розкладання
T TT A T =U D U⋅ ⋅ ⋅ ⋅ , (2.22)
де U − верхньотрикутна (права) матриця, D − діагональна
матриця, елементи якої дорівнюють 1 або −1, T − матриця перестановок2. Процес перетворення виконується за формулами :
12
1
12
1
1
1
sign , 1,2, , ;
, 1;
1, , 1, ;
i
i ii ii kk
i
ii ii ii kk
i
ij ii ki k kjki ii
d a a d i N
u a a d i
u a u d u i j j i Nd u
−
=
−
=
−
=
= − ⋅ =
= − ⋅ >
= − ⋅ ⋅ < = + ⋅
∑
∑
∑
…
(2.23)
1 Обидві процедури належать бібліотеці IMSL [2].
2 Матриця перестановок Т, а також діагональна матриця D, за звичай не обчислюються, а замість них інформацію зберігають у відповідних векторах.
33
Розв’язок (2.2) знаходиться із розв’язання двох трикутних і однієї лінійної системи 1:
, ,TU z b D y z U x y= = =� � � �� �
. (2.24)
Зауваження. Для симетричних додатно визначених матриць A алгоритм метода квадратного кореня ще
спрощується, оскільки тоді D I≡ . В результаті розкладання
має вигляд TA=U U⋅ , де верхньотрикутна (права) матриця
U носить назву матриці Халєцького2.
Методи прогонки. Використання триточкових різницевих схем або скінченних елементів із лінійною інтерполяцією після розщеплення приводить до СЛАР із матрицею, що має тридіагональну стрічкову структуру. Розглянемо матричне рівняння:
1 1 1 1 1
2 2 2 2 2
1 1 1 1 1
0
0
i i i i i
N N N N N
N NN N N
b c a v d
a b c v d
a b c v d
a b c v d
v dc a b− − − − −
=
⋮ ⋮ ⋮
⋮ ⋮ ⋮
(2.25)
1 Для розв’язання системи (2.2) з симетричною матрицею також рекомендуємо використання підпрограм LSASF або LSLSF з бібліотеки IMSL [2]. 2 Для розв’язання СЛАР із додатно-визначеною симетричною матрицею можна також скористатися підпрограмою LSADS з бібліотеки IMSL [2].
34
Найпопулярнішим для розв’язання систем вигляду (2.25) є алгоритм прогонки (TDMA)1. Алгоритм TDMA складається із двох кроків (див. схему на рис. 2.9). Спочатку на першому кроці виконується прогонка вперед за
формулами
1 11 1
1 1
, ,c d
c db b
′ ′= = (2.26)
1
1 1
, ( 2, ).i i i ii i
i i i i i i
c d a dc d i N
b a c b a c−
− −
′−′ ′= = =′ ′− −
(2.27)
1
2
1
* * *
* * * 0 *
*
* * * *
*
0 * * * *
* * *
i
N
N
v
v
v
v
v
−
=
⋅ ⋅ ⋅
⋮⋮
⋮
1
N
v
v
⋅
⋅
⋅
⋅
⋅
11 *
1 0
...
1
*
0 1
1 *
i
N
v
v
v
+
⋅+ ⋅
⋅ ⋅
=⋅+ ⋅
⋅+ ⋅
⋱
Рис. 2.9. Схема алгоритму прогонки TDMA.
1 Спрощений варіант методу Гаусса.
Прогонка
вперед
Прогонка
назад
35
Система рівнянь (2.25) перетворюється до вигляду
1 11
2
1
1
1 0
...
1
0 1
1
i ii
N
N N
v dc
c
v dc
c
v d−
′′ ′ ⋅ ⋅ ⋅ ⋅ ′′ = ⋅ ⋅
′ ⋅ ⋅ ′
⋱
. (2.28)
Прогонка назад реалізується за формулами
1, ( 1,1)N N i i i iv d v d v c i N+′ ′ ′= = − = − . (2.29) Алгоритм прогонки (TDMA) економічний, адже потребує
лише (5N − 4) операцій (множення та ділення). Розглянемо приклад використання алгоритму TDMA. Код програми:
program band3 ! Розвязання СЛАР з тридіагональною матрицею use solve_LAEA implicit none integer, parameter :: n = 9 integer :: Er, i real :: A(n), B(n), C(n), D(n), X(n) data A/n*2.0/, B/n*1.1/,C/n*1.0/ open(2,file='band3.txt') forall(i=1:n) D(i)=A(i)+B(i)+C(i) call solve_band3(A, B, C, D, X, Er) if (Er >= 65) then write(*,*) 'Matrix of the system with singularity. Program stop.' write(2,*) 'Matrix of the system with singularity. Program stop.' stop 65 end if write(*,12) write(*,13) (i, X(i), i=1,9) write(2,12) write(2,13) (i, X(i), i=1,9)
36
12 format(' Solution:') 13 format(' X',i1,' = ',F10.7, ' X',i1,' = ',F10.7) stop end program band3 Результат роботи програми
Solution: X1 = 1.0000006 X2 = 0.9999998 X3 = 0.9999997 X4 = 1.0000007 X5 = 0.9999989 X6 = 1.0000013 X7 = 0.9999985 X8 = 1.0000013 X9 = 0.9999989 Використання скінченно-різницевих схем більш високого
порядку або скінченних елементів більш високого порядку приводить до стрічкової структури в A , коли ширина стрічки > 3. Розглянемо тепер матричне рівняння типу (2.2), у якому
ненульові елементи матриці A складають стрічку з п’яти
діагоналей { }, , , ,i i i i ie a b c f .
Модифікований алгоритм прогонки тут вже складається із трьох етапів. На першому етапі виключається перша нижня діагональ ei,
що приводить вихідну систему рівнянь до вигляду:
1 1 1 1 1
2 2 2 2
3 3 3 3
1 1 1
0
0
i ii i i i
N N N
N NN N
b c f v d
a b c f
a b c f
v da b c f
a b c
v da b− − −
⋅ ⋅ ′ ′ ′ ′ ⋅ ⋅ ⋅ ⋅⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ = ′′ ′ ′ ′
⋅ ⋅⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ′ ′ ′ ⋅ ⋅
′ ′
, (2.30)
37
де
( )
1 1 1
1 1 1
1
1
, , ,
, 3, .
i i i i i ii i i i i i
i i i
i ii i i i
i
e b e c e fa a b b c c
a a a
e df f d d i N
a
− − −
− − −
−
−
′ ′ ′′ ′ ′= − = − = −′ ′ ′
′′ ′= = − =′
(2.31)
На другому етапі виключаються елементи a′ , а на головній діагоналі залишаються тільки одиниці. В результаті маємо
1 11 1
2 2
1
1
1 0
1
0 1
1
i ii i
N
N N
v dc f
c f
v dc f
c
v d−
′′ ′′ ′′ ⋅ ⋅ ⋅ ⋅⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ = ′′′′ ′′
⋅ ⋅⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ′′ ⋅ ⋅
′′
⋱
, (2.32)
де
1 1
1 1 1
, ,i i i i i i ii i i
i i i i i i i i i
c a f d a d fc d f
b a c b a c b a c− −
− − −
′ ′ ′′ ′ ′ ′′ ′− −′′ ′′ ′′= = =′ ′ ′′ ′ ′ ′′ ′ ′ ′′− − −
, (2.33)
тут i = 2, 3,…, N. На третьому етапі розв’язок системи знаходять прогонкою назад:
1 2i i i i i iv d c v f v+ +′′ ′′ ′′= − − . (2.34) Розглянемо приклад використання алгоритму прогонки для
розв’язання СЛАР із п’ятидіагональною матрицею. Код програми:
program band5 ! Розв’язання СЛАР із п’ятидіагональною матрицею. use solve_LAEA implicit none integer, parameter :: n = 9 integer :: Er, і real :: A(n), B(n), C(n), D(n), E(n), G(n), X(n) data A/n*2.0/, B/n*1.2/, C/n*1.1/, D/n*0.9/, E/n*1.3/
38
open(2,file='band5.txt') forall(i=1:n) G(i)=A(i)+B(i)+C(i)+D(i)+E(i) call solve_band5(A, B, C, D, E, G, X, Er) if (Er >= 65) then write(*,*) 'Matrix of the system with singularity. Program stop.' write(2,*) 'Matrix of the system with singularity. Program stop.' stop 65 end if write(*,12) write(*,13) (i, X(i), i=1,9) write(2,12) write(2,13) (i, X(i), i=1,9) 12 format(' Solution:') 13 format(' X',i1,' = ',F10.7, ' X',i1,' = ',F10.7) end program band5
Результат роботи програми
Solution: X1 = 1.0000004 X2 = 0.9999997 X3 = 0.9999997 X4 = 1.0000002 X5 = 1.0000001 X6 = 1.0000000 X7 = 0.9999998 X8 = 0.9999999 X9 = 1.0000001 Зауваження:
• Щоб запобігти поганій зумовленості матриці A необхідно, щоб виконувалася умова діагональної переваги, тобто
i i ib a c> + (2.35)
для звичайного алгоритму прогонки (TDMA) або
i i i i ib a c e f> + + + (2.36)
для модифікованого алгоритму прогонки. • Різні етапи модифікованого алгоритму прогонки можна
інтерпретувати як серію операцій (прямих прогонок), які необхідні для зведення матриці A до верхньотрикутного
39
вигляду, після чого за допомогою звичайної зворотної підстановки можна знайти вектор v
�. Зрозуміло, що за
цим алгоритмом можна розв’язати систему із більш широкою стрічкою, проте при цьому переваги методу прогонки, порівнюючи, наприклад із методом Гаусса, суттєво зменшуються.
Алгоритм TDMA можна використовувати і для більш складних випадків, ніж розв’язання СЛАР із стрічковими матрицями. До таких більш складних алгоритмів відносять алгоритм розв’язання СЛАР із блочно-тридіагональною матрицею:
1 1 1 1
2 2 2 2 2
1 1 1 1 1
0
0
i i i i i
N N N N N
NN N N
b c v d
a b c v d
a b c v d
a b c v d
va b d− − − − −
=
��
��
⋮ ⋮ ⋮��
⋮ ⋮ ⋮��
��
, (2.37)
де , ,i i ia b c − субматриці розміру М×М, а ,i iv d��
−
М−компонентні субвектори [5, 13, 24]. Число М пов’язане із кількістю рівнянь, записаних у кожному вузлі сітки. Наприклад, для тривимірної течії в’язкої стисливої рідини М = 5. Таким чином, iv
� – субвектор розв’язку, що пов’язаний
із конкретним вузлом сітки, а матричне рівняння (2.2) відповідає системі, що складається з N блоків рівнянь, причому кожний блок, пов’язаний із конкретним вузлом сітки, несе у собі М рівнянь. Розв’язання системи (2.37) іде за процедурою, що
максимально наближена до процедури методу TDMA [13]. Спочатку тридіагональна матриця блоків із (2.37) перетворюється до верхньотрикутної форми за рахунок виключення субматриць ia . За аналогією із (2.26) маємо
40
( ) ( )1 1
1 1 1 11 1,c b c d b d− −
′ ′= =� �
, (2.38)
тоді як для блоку загального вигляду
( )( ) { }
1
1
1
1
, ,
.
ii i i i i i
i i i ii
b b a c c b c
d b d a d
−−
−−
′ ′ ′= − =
′ ′= −� � � (2.39)
У (2.38) та (2.39) входять явні вирази для обернених матриць. На практиці більш економічно не знаходити обернені матриці, а шукати окремі розв’язки М−компонентних субсистем. Таким чином, наприклад, матричне рівняння
i i ib c c′ ′ = (2.40)
розв’язується відносно ic′ . Після виконання операцій (2.38) і
(2.39) матриця системи (2.37) перетворюється на верхньотрикутну заміною , iic d
�, відповідно, на , iic d′ ′
�, а
субматриць ib на одиничні матриці I .
Другий етап, еквівалентний використанню формул (2.29), потребує зворотних підстановок за формулами1
1i i iiv d c v +′ ′= −�� �
. (2.41)
Зауваження. Для реалізації блочного алгоритму прогонки потрібно близько 5NM 3 / 3 операцій, що значно менше ніж (NM) 3 / 3 операцій, які необхідні для реалізації процедури виключення за Гауссом.
Методи ортогоналізації. До методів ортогоналізації відносять метод обертань Якобі, який спочатку використовувався для розв’язання повної проблеми власних чисел для симетричних матриць, і подібні йому, але придатні для довільних матриць, методи Гівенса, Хаусхолдера та QR−алгоритм [2, 3, 5, 21, 24].
1 Код процедури розв’язання СЛАР з блочно-тридіагональною
матрицею наведено у Додатку В до 2 тому монографії Д. Андерсен та інші [13].
41
Усі розглядувані далі методи також засновані на ідеї одержання нульових елементів поза діагоналлю, але тепер для цього матрицю A множать на ортогональні матриці U (тобто
на такі, що для них 1TU U −≡ ). Ціна суттєво зростаючої при
цьому обчислювальної стійкості − більш висока арифметична вартість. Як уже відмічалося вище, методи ортогоналізації спочатку розроблялися для визначення власних векторів та
власних значень матриці A . Можливість використання їх для розв’язання системи лінійних алгебраїчних рівнянь (2.2) одержала нове визнання для випадку, коли A − розріджена матриця. Особливо це стосується наведених далі методу обертань Гівенса та методу Хаусхолдера, які не дивлячись на більш високу, ніж у методу Гаусса, арифметичну вартість (для щільної A), мають незамінні переваги:
• локальний характер обчислень; • придатність для паралельних обчислень. Але спочатку ми розглянемо використанням методів
ортогоналізації для розв’язання повної проблеми власних чисел для дійсних симетричних матриць (придатний також для довільних ермітових матриць)1. 2.2. Ітераційні методи розв’язання систем лінійних
алгебраїчних рівнянь Прямі методи розв’язання СЛАР не можна застосовувати
при дуже великих N (при великій кількості рівнянь) через зростаючі похибки округлень, що пов’язано з великою кількістю арифметичних операцій. Ліквідувати ці ускладнення допомагають ітераційні методи. З їх допомогою можна
одержати, починаючи з вектора ( )0v�
, послідовність векторів ( ){ }mv�
, що збігаються до розв’язку системи
1 Див. наступний розділ 3.
42
( )lim mc
mv v→ ∞
=� �. (2.42)
Метод є збіжним, якщо (2.42) справедливе для довільного ( )0v�
. Для всіх методів, що розглядаються далі, матриця A
подається у вигляді різниці матриць A M N= − , (2.43)
де для матриці M виконується M A≈ , але вона легко
піддається числовій факторизації. Наприклад, матриця M може бути тридіагональною. Векторне рівняння (2.2) при цьому зводиться до вигляду
( ) ( )m+1 mM v = N v +b⋅ ⋅�� �
. (2.44) Формальним розв’язком для (2.44) є
( ) ( )+1 11m mv = M N v M b−− ⋅ ⋅ + ⋅�� �
(2.45)
або ( ) ( ) ( )1 1m+ m mv = v M R−− ⋅�� �
, (2.46) де введено вектор нев’язки
( ) ( )m mR = A v b⋅ −�� �
. (2.47) Відомо, що схеми (2.45) або (2.46) забезпечують сходження
до точного розв’язку, якщо спектральний радіус (тобто розмір
максимального власного числа) для матриці 1M N− ⋅ буде
менше одиниці. Останнє забезпечується вибором матриць M
та N .
Зауваження. Розв’язання системи (2.45) ітераційними методами спрощується ще й тому, що на кожному кроці розв’язується система з одними й тими самими матрицями. Звернемося до найбільш поширеного алгоритму Гаусса–
Зейделя та розглянемо його варіанти. Нехай матрицю A подано у вигляді
A= D G F− − , (2.48)
тобто нехай A є сумою діагональної матриці
43
( )0ii ii ijd a , d i j≡ ≡ ≠ ;
нижньотрикутної матриці
{ }: ( ), 0 ( )ij ij ij ijG = g g a i> j g i j≡ − ≡ ≤ ;
та верхньотрикутної матриці
{ }: ( ), 0 ( )ij ij ij ijF = f f a i< j f i j≡ − ≡ ≥ .
Нехай також на діагоналі відсутні нульові елементи, тобто 0iia ≠ . Маємо три класичні ітераційні методи:
• метод Якобі : M = D, N = G + F ,
( ) ( ) ( )m+1 mD v = b + G + F v⋅ ⋅�� �
; (2.49)
• метод Гаусса–Зейделя : M = D G− та N = F ,
( ) ( ) ( )m+1 mD G v = b + F v− ⋅�� �
; (2.50)
• метод послідовної верхньої релаксації (SOR) : 1 1
1M = D G, N = D+ Fw w
− −
,
( ) ( ) ( ) ( ) ( )1 1m+ m mD wG v = wb + w D v +wF v− −⋅ ⋅ ⋅�� � �
, (2.51)
тут w − параметр релаксації. Метод Якобі потребує найменшої кількості обчислень,
оскільки на кожному кроці розв’язується СЛАР із діагональною матрицею. Для методу Гаусса–Зейделя на кожному кроці розв’язується СЛАР із трикутною матрицею. Однак пам’яті комп’ютера для методу Якобі потрібно вдвічі більше, ніж для методу Гаусса–Зейделя. Метод послідовної верхньої релаксації є модифікацією методу Гаусса-–Зейделя з метою прискорення збіжності останнього.
Збіжність ітераційних методів: • якщо матриця A симетрична і додатно визначена, то збігаються методи Гаусса–Зейделя та SOR при 0 < w < 2;
• якщо матриця A має діагональну перевагу, тобто
44
ii iji j
a a≠
> ∑ , (2.52)
то збігаються методи Якобі та Гаусса–Зейделя.
Зауваження: • Методи Якобі та Гаусса–Зейделя мають лінійну збіжність. Якщо w = wopt , то збіжність методу SOR наближається до квадратичної. Однак визначення wopt потребує кількості операцій, яку можна порівняти із розв’язанням системи, оскільки
( )1222 1 1 µoptw
= + −
, (2.53)
де µ − найбільше власне число комплексу 1I D A−− ⋅ ( I −
одинична матриця). Якщо µ можна попередньо оцінити, то можливою стратегією є використання адаптивної процедури, яка уточнює wopt із виразу (2.53) у процесі ітерацій.
• Методи ітерацій також припускають використання адаптивних процедур прискорення або за методом Чебишова, або за методом спряжених градієнтів (CG). На відміну від схеми послідовної верхньої релаксації (SOR) тут уже немає параметрів, які необхідно підбирати емпірично.
Розглянемо послідовність кроків при застосуванні
традиційного методу спряжених градієнтів [21, 24]: ( ) ( ) ( ) ( )
( ) ( ) ( ) ( )
( ) ( ) ( )( )
1
1
1 1 1
1) λ ,
2) λ ,
3) ρ , ,
m m m m
m m m m
m m m
v v P
R R U
R R
+
+
+ + +
= +
= −
=
�� �
� � �
� �
( ) ( ) ( )
( ) ( ) ( ) ( )
1 1
1 1 1
4) α ρ ρ ,
5) α ,
m m m
m m m nP R P
+ +
+ + +
=
= +� � � (2.54)
45
( ) ( )
( )( )
( ) ( )( )
1 1
11
1 1
6) ,
ρ7) λ .
,
m m
mm
m m
U A P
P U
+ +
++
+ +
= ⋅
=
��
� �
Алгоритм (2.54) економічний, бо потребує лише одного
матрично-векторного множення на 6-му кроці. Вектор ( )mP�
визначає напрямок пошуку, причому тут ( ) ( )0 0P R=� �
, ( )0v�
− довільне початкове наближення. Важливо також відмітити, що
вектор нев’язки ( )mR�
обчислюється тут рекурсивно, а не за визначенням (2.47). Можливі подальші уточнення методу спряжених градієнтів із метою прискорення його збіжності наводяться в монографіях [22, 24]. 2.3. Особливості розв’язання систем нелінійних рівнянь
ітеративними методами Систему рівнянь (2.1) представимо у вигляді
( )v f v=� � (2.55)
або
1 2( , , , )i i nv f v v v= … , i = 1,2,…,n. (2.56) Для розв’язання цієї системи спочатку використаємо метод
простої ітерації Якобі, що аналогічний відповідному методу для системи лінійних рівнянь. Значення невідомих на k-й ітерації знайдемо з використанням їхніх значень на попередній
ітерації: ( ) ( ) ( )1 1 11 2, , ,k k k
nv v v− − −
… у вигляді
( ) ( ) ( ) ( )1 1 11 2( , , , )k k k k
i i nv f v v v− − −= … , i = 1,2,…,n. (2.57)
Систему (2.56) можна розв’язати і методом Зейделя, що нагадує метод Гаусса–Зейделя для розв’язання СЛАР.
Значення ( )kiv знаходиться з i-го рівняння системи (2.56) з
використанням вже обчислених на поточній ітерації значень невідомих. Таким чином, значення невідомих на k-й ітерації знаходитимуться не за схемою (2.57), а з виразу
46
( ) ( ) ( ) ( ) ( )1 11 1( , , , , , )k k k k k
i i i niv f v v v v− −−= … … , i = 1,2,…,n. (2.58)
Ітераційний процес для обох методів триває, доки максимальний приріст для всіх невідомих у двох послідовних ітераціях не стане малим. Зауваження:
• Умови збіжності розглянутих методів збігаються з такими для систем лінійних рівнянь. Тільки перевіряти ці умови потрібно на кожній ітерації.
• При використанні методу простої ітерації або методу Зейделя для розв’язання системи нелінійних рівнянь успіх багато в чому визначається вдалим вибором початкових наближень невідомих: вони мають бути досить близькими до точного розв’язання. У противному випадку ітераційний процес може не збігатися.
2.4. Метод Ньютона розв’язання систем нелінійних
алгебраїчних рівнянь Перепишемо матричне рівняння (2.1) у вигляді
( ) 0R A v v b= ⋅ − =�� � �
, (2.59)
де R�
− вектор нев’язки. Тоді основне формулювання алгоритму методу Ньютона має вигляд
( ) ( ) ( ) ( )1 1( )n n nnv v J R+ −= −�� �
, (2.60)
де n − номер ітерації; ( ) ( ) ( )n n njjk kJ R v= ∂ ∂ − якобіан. Введемо
вектор різниці ( ) ( ) ( )1 1n n nv v v+ +∆ = −� � � і перепишемо (2.60) у
вигляді ( ) ( ) ( )1n nnJ v R+∆ = −
��. (2.61)
Векторне рівняння (2.61) на кожній ітерації є системою
лінійних рівнянь відносно вектора поправки ( )1nv +∆� . Для одержання остаточного розв’язку на кожному кроці ітерації
( 1) ( ) ( 1)n n nv v vω+ += + ∆ , (2.62)
47
де додатково введено параметр нижньої релаксації 0 < ω ≤ 1 . Позитивною властивістю методу Ньютона є його
квадратична збіжність, тобто
( ) ( ) 21c c
n nv v v v+ − ≈ −� � � �, (2.63)
тут cv�
− точний розв’язок (2.1). Блок-схему методу Ньютона наведено на рис. 2.10. Критерій збіжності методу Ньютона можна отримати,
виходячи з таких міркувань .
1. Якщо матриця, що обернена до матриці ( )0J , має норму, яка обмежена величиною a, тобто
( )( ) 10J a
−≤ .
Рис. 2.10. Блок-схема методу Ньютона
Остаточний розв’язок
Початкове значення
v(n), n = 0
Обчислити
R(n) Перевірка
|| R(n) || < ε
Так
Ні
Обчислити та факторизувати
J(n)
Обчислити
∆v(n) = −(J(n)) –1 R(n)
Обчислити v(n+1) = v(n) + + ∆v(n)
n = n+1 “Заморозити”
48
2. Якщо перший вектор різниці ( )1v∆� має норму, що обмежена величиною b , тобто
( ) ( )( ) ( )11 00v J R b−
∆ = − − ≤��
.
3. Якщо, крім того, вектор поправки R�
має неперервні другі похідні, які задовольняють нерівність :
2
, 1
Nm
j k j k
R c
v v N=
∂≤
∂ ∂∑ для ( )1: 2v v b∀ ∆ <� �.
Нарешті, якщо визначені вище константи задовольняють співвідношення abc < 0,5, то розв’язок за методом Ньютона
( )nv�
збігатиметься до точного розв’язку cv�
: ( )clim n
nv v
→ ∞=� �
,
причому ( )c 0R v =� �
, ( ) 1c 2n nv v b −− ≤� �
.
Зауваження: • У вищенаведених виразах використовуються, відповідно,
норми: max jj
v v=� − векторна та 1
maxN
jkj k
J J=
=
∑ −
матрична. • Перевірка виконання критерію збіжності методу
Ньютона пов’язана за трудомісткістю з роботою, що сумірна з розв’язанням самого векторного рівняння (2.1).
• Основна складність використання методу Ньютона полягає у тому, що при зростанні кількості рівнянь (N)
радіус збіжності зменшується, тобто значення ( )0v�
для початкової ітерації має вибиратися дуже близьким до точного розв’язку cv
�.
• Найбільший час у методі Ньютона витрачається на
обчислення і факторізацію матриці ( )nJ . Цей час можна
зменшити “ заморожуючи” ( )nJ протягом кількох ітерацій або всього циклу обчислень. Однак в останньому випадку збіжність буде вже не квадратична, а лінійна.
49
• Другого зауваження можна уникнути, якщо зробити декілька початкових ітерацій за методом Зейделя або використати у виразі (2.62) процедуру нижньої релаксації (ω < 0,5). Однак в останньому випадку швидкість збіжності методу теж суттєво зменшується.
• Ефективність методу Ньютона виявляється найбільшою при розв’язанні невеликих систем сильно нелінійних алгебраїчних рівнянь, до яких належать повні рівняння Нав’є-Стокса, рівняння Рейнольдса або рівняння Бюргерса.
Розглянемо приклад розв’язання методом Ньютона системи
двох нелінійних рівнянь 2 3
2 2
( , ) (1 ) 0,
( , ) 1 0.
f x y y x x
g x y x y
= − − =
= + − = (2.64)
з початковим наближенням (1.0, 1.0). Код програми:
program main_Newton2 ! Roots of a system of two nonlinear equations ! f(x,y) = 0 ! g(x,y) = 0 ! Method: Open Domain (Newton-Raphson) use NEWTON_RAPHSON1 implicit none integer flag real(8) :: x, y, eps real(8) :: f, fx, fy, g, gx, gy open(2,file='Newton_2eq_rez.txt') x = 1.0d0; y = 1.0d0 eps = 1.0d-6 write (*,*) ' Two roots of a system f(x,y)=0, g(x,y)=0 ' write (*,*) ' Method - Newton-Raphson' write (*,100) x,y write (2,*) ' Two roots of a system f(x,y)=0, g(x,y)=0 ' write (2,*) ' Method - Newton-Raphson'
1 Модуль NEWTON_RAPHSON знаходиться в Додатку.
50
write (2,100) x,y call Newton2(x,y,eps,flag) ! Print solutions if (flag == 0) then write(*,*)' No roots found' write(2,*)' No roots found' stop end if write (*,101) eps, flag write (2,101) eps, flag ! Test and print solutions call fg(x,y,f,fx,fy,g,gx,gy) write (*,*)' x y f(x,y) g(x,y)' write (*,102) x, y, f, g write (2,*)' x y f(x,y) g(x,y)' write (2,102) x, y, f, g 100 format(' Guess points = ',2f6.2) 101 format(' tolerance = ',1pe12.4,/,& ' iterations = ',i3) 102 format(2f10.5,2(1pe12.3)) end program main_Newton2 subroutine fg(x,y,f,fx,fy,g,gx,gy) ! Evaluates f(x,y), g(x,y) ! and their partial derivatives implicit none real(8) :: x, y, f, fx, fy, g, gx, gy f = y*y*(1.0-x)-x**3 g = x*x + y*y -1.0 fx = (-1.0)*(y*y + 3.0*x*x) fy = 2.0*y*(1.0-x) gx = 2.0*x gy = 2.0*y end subroutine fg
Результат роботи програми Two roots of a system f(x,y)=0, g(x,y)=0
51
Method - Newton-Raphson Guess points = 1.00 1.00 tolerance = 1.0000E-06 iterations = 5 x y f(x,y) g(x,y) 0.61803 0.78615 -9.159E-16 4.441E-16 Аналогічний результат можна також отримати, якщо
скористатися стандартною процедурою знаходження розв’язків системи n нелінійних рівнянь NEQNJ з бібліотеки IMSL. 2.5. Квазіньютонівські методи Негативні сторони методу Ньютона (малий радіус
збіжності, великий час, потрібний для знаходження якобіана ( )nJ , та необхідність розв’язання системи лінійних
алгебраїчних рівнянь на кожній ітерації (факторизація ( )nJ ))
легко подолати, коли матриця ( )nJ має деякі додаткові властивості, наприклад, додатну визначеність. У цьому випадку вираз (2.60) замінюють співвідношенням
( ) ( ) ( ) ( ) ( )1n n n nnv v w H R+ = −�� �
, (2.65)
де матриця ( )nH є апроксимацією величини ( ) 1( )nJ − і систематично модифікується на кожній ітерації так, що
гранично прямує до ( ) 1( )nJ − . Важливо, що модифікація ( )nH виявляється суттєво більш економічним процесом, ніж
факторизація ( )nJ . Перепишемо рівняння (2.65) у вигляді
( ) ( ) ( ) ( )1n n n nv v w ξ+ = −�� �
. (2.66)
Тут вектор ( )nξ�
можна розглядати як такий, що визначає
напрям пошуку. Скаляр ( )nw обирають таким чином, щоб
норма ( )1nR +� була мінімальною в напрямку пошуку ( )nξ�
.
52
Остання умова при великих N дає істотно більший радіус збіжності, ніж метод Ньютона. Крім того квазіньютонівські методи дають можливість працювати з погано обумовленими матрицями Якобі. Зауважимо, що оскільки ефективність квазіньютонівських
методів визначається додатковими особливостями (наприклад, додатною визначеністю), використання цих методів для розв’язання задач обчислювальної гідромеханіки має розглядатися для кожного випадку окремо. Крім того, більшість літературних джерел, де розглядаються квазіньютонівські методи [2, 3, 5, 22, 24], пов’язує їх ефективність із використанням тільки разом із процедурою безумовної мінімізації. Повну бібліографію книг і статей, в яких детально розглядається використання квазіньютонівських методів для спеціальних задач можна знайти в монографії [22]. У цій монографії, а також у посібниках [2, 11] наведено і алгоритми деяких інших методів, що можуть використовуватися при розв’язанні нелінійних задач механіки суцільних середовищ. Так для розв’язання системи нелінійних рівнянь
квазіньютонівським методом січних в бібліотеці IMSL існує дві стандартні процедури [1]. При цьому рекомендується використати процедуру NEQBJ,
якщо якобіан задається користувачем, і процедуру NEQBF, якщо якобіан обчислюється із використанням скінченно-різницевих методів. 2.6. Запитання та вправи 1) Які Ви знаєте прямі методи розв’язання СЛАР? 2) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для розв’язання СЛАР із матрицею загального вигляду?
3) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для розв’язання СЛАР із симетричною матрицею?
4) Наведіть алгоритм метода Гаусса без вибору головного
53
елементу. 5) Наведіть алгоритм метода квадратного кореня. 6) Наведіть алгоритм метода прогонки для тридіагональної матриці.
7) Наведіть алгоритм метода прогонки для п’ятидіагональної матриці.
8) Наведіть алгоритм метода прогонки для блочно-діагональної матриці.
9) Які ви знаєте методи ортогоналізації? 10) Які ви знаєте ітераційні методи для розв’язання СЛАР? 11) В чому особливість використання ітераційних методів для розв’язання СНЛАР?
12) Наведіть алгоритм метода Ньютона для розв’язання СНЛАР?
13) Які ви знаєте квазіньютонівські методи для розв’язання СНЛАР?
14) Використовуючи QR-алгоритм розв’язати СЛАР, якщо 3 1 1 5
1 3 1 , 3
1 1 3 3
A b
= − = − −
�.
15*) Знайти обернену до заданої матриці, скориставшись
визначенням оберненої матриці 1A A I− = та стандартними процедурами розв’язання СЛАР із бібліотеки IMSL. Перевірити отриманий результат.
16*) Використовуючи квазіньютонівський метод січних розв’язати систему нелінійних рівнянь
sin( 2) 1.5,
cos( 2) 0.5,
x y
x y
+ − = + − =
при початкових значеннях невідомих (4.0,4.0). Зауваження: Скористатися процедурою із бібліотеки IMSL NEQBJ, для якої якобіан задається користувачем.
17*) За умов задачі 16, скористатися процедурою із бібліотеки IMSL NEQBF, для якої якобіан обчислюється із використанням скінченно-різницевих методів.
54
2.7. Практичні завдання Завдання 2. Розв’язання системи лінійних алгебраїчних
рівнянь Мета завдання:
1. Ознайомлення з процедурами розв’язання системи лінійних алгебраїчних рівнянь (метод факторизації, метод квадратного кореня, методи ітерацій).
2. Ознайомлення з процедурами із бібліотеки IMSL розв’язання системи лінійних алгебраїчних рівнянь (метод факторизації, метод квадратного кореня).
Постановка завдання: Розв’язання системи лінійних алгебраїчних рівнянь із
використанням прямих та ітеративних методів. Розв’язання системи лінійних алгебраїчних рівнянь із використанням стандартних методів із бібліотеки IMSL. Порівняти отримані розв’язки. Методичні вказівки: При підготовці до виконання роботи спочатку
познайомитися з прямими та ітеративними методами розв’язання системи лінійних алгебраїчних рівнянь. Всі вищенаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Розв’язати систему лінійних алгебраїчних рівнянь з довільною матрицею методом факторизації.
2. Розв’язати систему лінійних алгебраїчних рівнянь з симетричною матрицею методом квадратного кореня.
3. Розв’язати системи лінійних алгебраїчних рівнянь з 1-го та 2-го пункту методами Гаусса-Зейделя та верхньої релаксації. Зауважимо, що попередньо систему рівнянь краще привести до вигляду (2.56). Тоді для методу Якобі і Гаусса-Зейделя, відповідно, можна використати більш
55
прості алгоритми (2.57) та (2.58). Процедура верхньої релаксації виконується за формулою:
( 1) ( ) * ( )λ ( )n n nv v v v+ = + − , (2.67)
де *v − результат, який отримано за методом Якобі; λ − коефіцієнт релаксації (тут λ = 1,8).
4. Запрограмувати всі варіанти завдання, скориставшись стандартними процедурами із бібліотеки IMSL. Приклади використання стандартних процедур наведено в їх описі в бібліотеці IMSL.
5. Порівняти отримані результати. Варіанти завдання:
№ вар
Довільна матриця Симетрична матриця
1
1 2 3
1 2 3
1 2 3
3,21 4,25 2,13 5,06;
7,09 1,17 2,23 4,75;
0,43 1,40 0,62 1,05.
x x x
x x x
x x x
− + =+ − =− − = −
1 2 3
1 2 3
1 2 3
3,14 2,12 1,17 1,27;
2,12 1,32 2,45 2,13;
1,17 2,45 1,18 3,14.
x x x
x x x
x x x
− + =− + − =
− + =
2
1 2 3
1 2 3
1 2 3
0,42 1,13 7,05 6,15;
1,14 2,15 5,11 4,16;
0,71 0,81 0,02 0,17.
x x x
x x x
x x x
− + =− + = −
− + − = −
1 2 3
1 2 3
1 2 3
0,34 0,04 0,1 0,33;
0,04 0,1 0,12 0,05;
0,1 0,12 0,71 0,28.
x x x
x x x
x x x
− + =− + + = −
+ + =
3
1 2 3
1 2 3
1 2 3
2,5 3,12 4,03 7,5;
0,61 0,71 0,05 0,44;
1,03 2,05 0,88 1,16.
x x x
x x x
x x x
− − = −+ − =
− − + = −
1 2 3
1 2 3
1 2 3
0,1 0,12 0,13 0,1;
0,12 0,71 0,15 0,26;
0,13 0,15 0,63 0,38.
x x x
x x x
x x x
+ − =+ + =
− + + =
4
1 2 3
1 2 3
1 2 3
0,43 1,40 0,62 1,05;
7,09 1,17 2,23 4,75;
3,21 4,25 2,13 5,06.
x x x
x x x
x x x
− − = −+ − = −− + =
1 2 3
1 2 3
1 2 3
0,71 0,10 0,12 0,29;
0,10 0,34 0,04 0,32;
0,12 0,04 0,1 0,1.
x x x
x x x
x x x
+ + =+ − =− + = −
5
1 2 3
1 2 3
1 2 3
1,14 2,15 5,11 4,16;
0,71 0,81 0,02 0,17;
0,42 1,13 7,05 6,15.
x x x
x x x
x x x
− − = −− + − = −
− + =
1 2 3
1 2 3
1 2 3
0,93 1,42 2,55 2,48;
1,42 2,87 2,36 0,75;
2,55 2,36 1,44 1,83.
x x x
x x x
x x x
+ − =− + = −
− + − =
56
№ вар
Довільна матриця Симетрична матриця
6
1 2 3
1 2 3
1 2 3
2,5 3,12 5,03 7,5;
0,61 0,71 0,05 0,44;
1,03 2,05 0,87 1,16.
x x x
x x x
x x x
− − = −+ − =
− − + = −
1 2 3
1 2 3
1 2 3
1,42 2,15 1,07 2,48;
2,15 0,76 2,18 1,15;
1,07 2,18 1,23 0,88.
x x x
x x x
x x x
− + =− + − =
− + =
7
1 2 3
1 2 3
1 2 3
3,11 1,66 0,6 0,92;
0,60 0,78 1,87 1,65;
1,65 3,51 0,78 2,57.
x x x
x x x
x x x
− − = −+ − =
− + − =
1 2 3
1 2 3
1 2 3
2,23 0,71 0,63 1,28;
0,71 1,45 0,34 0,64;
1,07 0,34 0,77 0,87.
x x x
x x x
x x x
− + =− + + =
+ + = −
8
1 2 3
1 2 3
1 2 3
0,1 0,12 0,13 0,1;
0,12 0,71 0,15 0,26;
0,13 0,15 0,63 0,38.
x x x
x x x
x x x
+ − =+ + =
− + + =
1 2 3
1 2 3
1 2 3
2,74 1,18 1,23 0,16;
1,18 1,71 0,52 1,81;
1,23 0,52 0,62 1,25.
x x x
x x x
x x x
− + =− + − =
− + = −
9
1 2 3
1 2 3
1 2 3
0,71 0,10 0,12 0,29;
0,10 0,34 0,04 0,32;
0,12 0,04 0,1 0,1.
x x x
x x x
x x x
+ + =+ − =− + = −
1 2 3
1 2 3
1 2 3
0,78 1,08 1,35 0,57;
1,08 1,28 0,37 1,27;
1,35 0,37 2,86 0,47.
x x x
x x x
x x x
+ − =− + =
− + + =
10
1 2 3
1 2 3
1 2 3
0,34 0,04 0,1 0,33;
0,04 0,1 0,12 0,05;
0,1 0,12 0,71 0,28.
x x x
x x x
x x x
− + =− + + = −
+ + =
1 2 3
1 2 3
1 2 3
0,83 2,18 1,73 0,28;
2,18 1,41 1,03 1,18;
1,73 1,03 2,27 0,72.
x x x
x x x
x x x
+ − =− + = −
− + + =
11
1 2 3
1 2 3
1 2 3
0,12 0,43 0,14 0,17;
0,07 0,34 0,72 0,62;
1,18 0,08 0,25 1,12.
x x x
x x x
x x x
− + = −− + + =
− − =
1 2 3
1 2 3
1 2 3
1,63 1,27 0,84 1,51;
1,27 0,65 1,27 0,63;
0,84 1,27 1,21 2,15.
x x x
x x x
x x x
+ − =+ + = −
− + − =
12
1 2 3
1 2 3
1 2 3
1,17 0,53 0,84 1,15;
0,64 0,72 0,43 0,15;
0,32 0,43 0,93 0,48.
x x x
x x x
x x x
+ − =− − =+ − = −
1 2 3
1 2 3
1 2 3
1,35 0,72 1,38 0,88;
0,72 1,45 2,18 1,72;
1,38 2,18 0,93 0,72.
x x x
x x x
x x x
− + =− + − =
− + = −
13
1 2 3
1 2 3
1 2 3
0,66 1,44 0,18 1,83;
0,48 0,24 0,37 0,84;
0,86 0,43 0,64 0,64.
x x x
x x x
x x x
− − =− + = −+ + =
1 2 3
1 2 3
1 2 3
1,48 0,75 1,23 0,83;
0,75 0,96 1,64 1,12;
1,23 1,64 0,55 0,47.
x x x
x x x
x x x
+ − =− + = −
− + − =
57
№ вар
Довільна матриця Симетрична матриця
14
1 2 3
1 2 3
1 2 3
0,82 0,43 0,57 0,48;
0,35 1,12 0,48 0,52;
0,48 0,23 0,37 1,44.
x x x
x x x
x x x
+ − =− + − =
+ + =
1 2 3
1 2 3
1 2 3
2,16 3,18 1,26 1,83;
3,18 0,63 2,73 0,54;
1,26 2,73 3,15 1,72.
x x x
x x x
x x x
− + =− + − =
− + =
15
1 2 3
1 2 3
1 2 3
1,60 0,12 0,57 0,18;
0,38 0,25 0,54 0,63;
0,28 0,46 1,12 0,88.
x x x
x x x
x x x
+ + =+ − =+ − =
1 2 3
1 2 3
1 2 3
0,63 1,72 3,27 0,75;
1,72 2,27 1,62 1,27;
3,27 1,62 0,43 2,74.
x x x
x x x
x x x
− + = −− − + =
+ − =
16
1 2 3
1 2 3
1 2 3
1,16 1,30 1,14 0,43;
0,83 0,48 2,44 0,15;
2,00 0,16 1,30 1,5.
x x x
x x x
x x x
+ − =− − = −− + =
1 2 3
1 2 3
1 2 3
3,14 2,12 1,17 1,27;
2,12 1,32 2,45 2,13;
1,17 2,45 1,18 3,14.
x x x
x x x
x x x
− + =− + − =
− + =
17
1 2 3
1 2 3
1 2 3
0,1 0,04 0,13 0,15;
0,04 0,34 0,05 0,31;
0,13 0,05 0,63 0,37.
x x x
x x x
x x x
− − = −− + + =− + + =
1 2 3
1 2 3
1 2 3
0,34 0,04 0,1 0,33;
0,04 0,1 0,12 0,05;
0,1 0,12 0,71 0,28.
x x x
x x x
x x x
− + =− + + = −
+ + =
18
1 2 3
1 2 3
1 2 3
0,63 0,05 0,15 0,34;
0,05 0,34 0,10 0,32;
0,15 0,10 0,71 0,42.
x x x
x x x
x x x
+ + =+ + =+ + =
1 2 3
1 2 3
1 2 3
0,1 0,12 0,13 0,1;
0,12 0,71 0,15 0,26;
0,13 0,15 0,63 0,38.
x x x
x x x
x x x
+ − =+ + =
− + + =
19
1 2 3
1 2 3
1 2 3
1,2 0,2 0,3 0,6;
0,2 1,6 0,1 0,3;
0,3 0,1 1,5 0,4.
x x x
x x x
x x x
− + = −− + − =− + − =
1 2 3
1 2 3
1 2 3
0,71 0,10 0,12 0,29;
0,10 0,34 0,04 0,32;
0,12 0,04 0,1 0,1.
x x x
x x x
x x x
+ + =+ − =− + = −
20
1 2 3
1 2 3
1 2 3
0,3 1,2 0,2 0,6;
0,1 0,2 1,6 0,3;
1,5 0,3 0,1 0,4.
x x x
x x x
x x x
+ − = −− − + =− − + =
1 2 3
1 2 3
1 2 3
0,93 1,42 2,55 2,48;
1,42 2,87 2,36 0,75;
2,55 2,36 1,44 1,83.
x x x
x x x
x x x
+ − =− + = −
− + − =
21
1 2 3
1 2 3
1 2 3
0,20 0,44 0,81 0,74;
0,58 0,29 0,05 0,02;
0,05 0,34 0,10 0,32.
x x x
x x x
x x x
+ + =− + =+ + =
1 2 3
1 2 3
1 2 3
2,23 0,71 0,63 1,28;
0,71 1,45 0,34 0,64;
1,07 0,34 0,77 0,87.
x x x
x x x
x x x
− + =− + + =
+ + = −
58
№ вар
Довільна матриця Симетрична матриця
22
1 2 3
1 2 3
1 2 3
6,36 11,75 10 41,7;
7,42 19 11,75 49,5;
5,8 7,42 6,36 27,67.
x x x
x x x
x x x
+ + = −+ + = −
+ + = −
1 2 3
1 2 3
1 2 3
1,42 2,15 1,07 2,48;
2,15 0,76 2,18 1,15;
1,07 2,18 1,23 0,88.
x x x
x x x
x x x
− + =− + − =
− + =
23
1 2 3
1 2 3
1 2 3
0,40 0,11 0,18 0,47;
0,28 0,59 0,03 0,01;
0,02 0,24 0,10 0,22.
x x x
x x x
x x x
+ + =− + =+ + =
1 2 3
1 2 3
1 2 3
2,74 1,18 1,23 0,16;
1,18 1,71 0,52 1,81;
1,23 0,52 0,62 1,25.
x x x
x x x
x x x
− + =− + − =
− + = −
24
1 2 3
1 2 3
1 2 3
0,18 0,25 0,44 1,15;
0,42 0,35 1,12 0,86;
1,14 0,12 0,83 0,68.
x x x
x x x
x x x
+ − =− + =
+ − =
1 2 3
1 2 3
1 2 3
1,35 0,72 1,38 0,88;
0,72 1,45 2,18 1,72;
1,38 2,18 0,93 0,72.
x x x
x x x
x x x
− + =− + − =
− + = −
25
1 2 3
1 2 3
1 2 3
1,20 0,18 0,42 1,50;
0,44 0,36 0,12 1,16;
0,36 0,42 0,22 0,15.
x x x
x x x
x x x
+ − =+ + =− − =
1 2 3
1 2 3
1 2 3
0,78 1,08 1,35 0,57;
1,08 1,28 0,37 1,27;
1,35 0,37 2,86 0,47.
x x x
x x x
x x x
+ − =− + =
− + + =
26
1 2 3
1 2 3
1 2 3
0,64 0,43 0,57 0,43;
0,56 0,12 0,27 0,88;
0,63 0,83 0,43 0,12.
x x x
x x x
x x x
− + =+ − =− + = −
1 2 3
1 2 3
1 2 3
0,83 2,18 1,73 0,28;
2,18 1,41 1,03 1,18;
1,73 1,03 2,27 0,72.
x x x
x x x
x x x
+ − =− + = −
− + + =
27
1 2 3
1 2 3
1 2 3
1,60 2,18 0,72 1,15;
0,43 0,16 0,53 0,83;
0,34 0,57 0,83 0,42.
x x x
x x x
x x x
+ − =− + =+ − = −
1 2 3
1 2 3
1 2 3
1,63 1,27 0,84 1,51;
1,27 0,65 1,27 0,63;
0,84 1,27 1,21 2,15.
x x x
x x x
x x x
+ − =+ + = −
− + − =
28
1 2 3
1 2 3
1 2 3
0,80 0,13 0,63 1,15;
0,42 0,57 0,32 0,84;
0,54 0,62 0,32 0,25.
x x x
x x x
x x x
− + =+ + =+ − =
1 2 3
1 2 3
1 2 3
0,93 1,42 2,55 2,48;
1,42 2,87 2,36 0,75;
2,55 2,36 1,44 1,83.
x x x
x x x
x x x
+ − =− + = −
− + − =
29
1 2 3
1 2 3
1 2 3
1,06 0,28 0,84 0,57;
0,43 0,62 0,35 0,66;
0,37 0,75 0,64 0,38.
x x x
x x x
x x x
− + =+ − =− − = −
1 2 3
1 2 3
1 2 3
1,48 0,75 1,23 0,83;
0,75 0,96 1,64 1,12;
1,23 1,64 0,55 0,47.
x x x
x x x
x x x
+ − =− + = −
− + − =
59
№ вар
Довільна матриця Симетрична матриця
30
1 2 3
1 2 3
1 2 3
0,75 0,84 1,11 0,66;
1,12 0,14 0,45 0,83;
0,32 0,23 0,48 0,14.
x x x
x x x
x x x
− + =− + =+ − =
1 2 3
1 2 3
1 2 3
2,23 0,71 0,63 1,28;
0,71 1,45 0,34 0,64;
1,07 0,34 0,77 0,87.
x x x
x x x
x x x
− + =− + + =
+ + = −
Завдання 3. Розв’язання системи нелінійних алгебраїчних
рівнянь Мета завдання:
1. Ознайомлення з процедурами розв’язання системи нелінійних алгебраїчних рівнянь (метод Ньютона, методи ітерацій).
2. Ознайомлення з процедурами із бібліотеки IMSL розв’язання системи нелінійних алгебраїчних рівнянь (метод Ньютона-Пауелла, метод січних).
Постановка завдання: Розв’язання системи нелінійних алгебраїчних рівнянь із
використанням ітеративних методів. Розв’язання системи нелінійних алгебраїчних рівнянь із використанням стандартних методів із бібліотеки IMSL. Порівняти отримані розв’язки. Методичні вказівки: При підготовці до виконання роботи спочатку
познайомитися з методами розв’язання системи нелінійних алгебраїчних рівнянь. Всі вищенаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Розв’язати системи нелінійних алгебраїчних рівнянь методом Ньютона, скориставшись прикладом на стор.229-230.
2. Розв’язати системи лінійних алгебраїчних рівнянь методом Гаусса-Зейделя і методом верхньої релаксації. Попередньо систему рівнянь потрібно привести до вигляду (2.56). Тоді для методу Якобі і Зейделя, відповідно, можна використати
60
алгоритми (2.57) та (2.58). Процедура верхньої релаксації виконується за формулою :
( 1) ( ) * ( )λ ( )n n nv v v v+ = + − , (2.68)
де *v − результат, який отримано за методом Якобі; λ − коефіцієнт релаксації (тут λ = 1,8).
3. Запрограмувати всі варіанти завдання, скориставшись стандартними процедурами із бібліотеки IMSL. Приклади використання стандартних процедур наведено в їх описі в бібліотеці IMSL.
4. Порівняти отримані результати. Варіанти завдання:
№ вар
Перша система рівнянь
Друга система рівнянь
1
sin( 1) 1,2;
2 cos 2.
x y
x y
+ − = + =
2
2 2
tg( 0,4) ;
0,6 2 1, 0, 0.
xy x
x y x y
+ =
+ = > >
2
cos( 1) 0,5;
cos 3.
x y
x y
− + = − =
2 2
sin( ) 1,6 0;
1, 0, 0.
x y x
x y x y
+ − =
+ = > >
3
sin 2 2;
cos( 1) 0,7.
x y
x y
+ = + − =
2
2 2
tg( 0,1) ;
2 1.
xy x
x y
+ =
+ =
4
cos 1,5;
2 sin( 0,5) 1.
x y
x y
+ = − − =
2 2
sin( ) 1,2 0,2;
1.
x y x
x y
+ − =
+ =
5
sin ( 0,5) 1;
cos( 2) 0.
x y
x y
+ − = + − =
2
2 2
tg( 0,3) ;
0,9 2 1.
xy x
x y
+ =
+ =
6
cos( 0,5) 0,8;
sin 2 1,6.
x y
y x
+ + = − =
2 2
sin( ) 1,3 0;
1.
x y x
x y
+ − =
+ =
7
sin ( 1) 1,3;
sin ( 1) 0,8.
x y
x y
− + = − + =
2
2 2
tg ;
0,8 2 1.
xy x
x y
=
+ =
61
№ вар
Перша система рівнянь
Друга система рівнянь
8
2 cos( 1) 0;
sin 0,4.
y x
x y
− + = + = −
2 2
sin( ) 1,5 0,1;
1.
x y x
x y
+ − =
+ =
9
cos( 0,5) 2;
sin 2 1.
x y
y x
+ − = − =
2
2 2
tg ;
0,7 2 1.
xy x
x y
=
+ =
10
sin ( 2) 1,5;
cos( 2) 0,5.
x y
x y
+ − = + − =
2 2
sin( ) 1,2 0,1;
1.
x y x
x y
+ − =
+ =
11
sin ( 1) 1,2;
2 cos 2.
y x
y x
+ − = + =
2
2 2
tg( 0,2) ;
0,6 2 1.
xy x
x y
+ =
+ =
12
cos( 1) 0,5;
cos 3.
y x
y x
− + = − =
2 2
sin( ) 1,4 0,1;
1.
x y x
x y
+ − =
+ =
13
sin 2 2;
cos( 1) 0,7.
y x
y x
+ = + − =
2
2 2
tg( 0,4) ;
0,8 2 1.
xy x
x y
+ =
+ =
14
cos 1,5;
2 sin( 0,5) 1.
y x
y x
+ = − − =
2 2
sin( ) 1,1 0,1;
1.
x y x
x y
+ − =
+ =
15
sin ( 0,5) 1;
cos( 2) 0.
y x
y x
+ − = + − =
2
2 2
tg( 0,1) ;
0,9 2 1.
xy x
x y
+ =
+ =
16
sin( 1) 1,2;
2 cos 2.
x y
x y
+ − = + =
2
2 2
tg( 0,4) ;
0,6 2 1, 0, 0.
xy x
x y x y
+ =
+ = > >
17
cos( 1) 0,5;
cos 3.
x y
x y
− + = − =
2 2
sin( ) 1,6 0;
1, 0, 0.
x y x
x y x y
+ − =
+ = > >
18
sin 2 2;
cos( 1) 0,7.
x y
x y
+ = + − =
2
2 2
tg( 0,1) ;
2 1.
xy x
x y
+ =
+ =
19
cos 1,5;
2 sin( 0,5) 1.
x y
x y
+ = − − =
2 2
sin( ) 1,2 0,2;
1.
x y x
x y
+ − =
+ =
62
№ вар
Перша система рівнянь
Друга система рівнянь
20
sin ( 0,5) 1;
cos( 2) 0.
x y
x y
+ − = + − =
2
2 2
tg( 0,1) ;
2 1.
xy x
x y
+ =
+ =
21
cos( 0,5) 0,8;
sin 2 1,6.
x y
y x
+ + = − =
2 2
sin( ) 1,2 0,2;
1.
x y x
x y
+ − =
+ =
22
sin ( 1) 1,3;
sin ( 1) 0,8.
x y
x y
− + = − + =
2
2 2
tg( 0,3) ;
0,9 2 1.
xy x
x y
+ =
+ =
23
2 cos( 1) 0;
sin 0,4.
y x
x y
− + = + = −
2 2
sin( ) 1,3 0;
1.
x y x
x y
+ − =
+ =
24
cos( 0,5) 2;
sin 2 1.
x y
y x
+ − = − =
2
2 2
tg ;
0,8 2 1.
xy x
x y
=
+ =
25
sin ( 2) 1,5;
cos( 2) 0,5.
x y
x y
+ − = + − =
2 2
sin( ) 1,5 0,1;
1.
x y x
x y
+ − =
+ =
26
sin( 1) 1,2;
2 cos 2.
x y
x y
+ − = + =
2
2 2
tg ;
0,7 2 1.
xy x
x y
=
+ =
27
sin ( 1) 1,2;
2 cos 2.
y x
y x
+ − = + =
2 2
sin( ) 1,2 0,1;
1.
x y x
x y
+ − =
+ =
28
cos( 1) 0,5;
cos 3.
y x
y x
− + = − =
2
2 2
tg( 0,2) ;
0,6 2 1.
xy x
x y
+ =
+ =
29
sin 2 2;
cos( 1) 0,7.
y x
y x
+ = + − =
2 2
sin( ) 1,4 0,1;
1.
x y x
x y
+ − =
+ =
30
sin ( 0,5) 1;
cos( 2) 0.
y x
y x
+ − = + − =
2
2 2
tg( 0,4) ;
0,8 2 1.
xy x
x y
+ =
+ =
63
Розділ 3. Методи розв’язання задач на власні значення
Багато дослідницьких задач зводяться до розгляду систем
рівнянь, що мають єдиний розв’язок лише в тому випадку, коли відоме значення деякого їх внутрішнього параметра. Цей особливий параметр називається характеристичним або власним значенням (або власним числом) системи. Із задачами на власні значення дослідник зустрічається в різних ситуаціях. Так, для тензорів напруг власні значення визначають головні нормальні напруги, а власними векторами задаються напрямки, що пов’язані із цими значеннями. При динамічному аналізі механічних систем власні значення відповідають власним частотам коливань, а власні вектори характеризують моди цих коливань. При розрахунках конструкцій власні значення дозволяють визначати критичні навантаження, перевищення яких приводить до втрати стійкості. Алгоритми розв’язання задач на власні значення
поділяються на дві групи. Ітераційні методи дуже зручні і добре пристосовані для визначення найменшого і найбільшого з власних чисел. Методи ортогоналізації суттєво складніші, проте дозволяють визначити всі власні числа і власні вектори з потрібною точністю. У загальному випадку задача на власні числа формулюється
так:
λA v v⋅ =� �, (3.1)
де A — матриця розмірності n×n. Потрібно знайти n
скалярних значень λ і власні вектори v�
, що відповідають кожному із власних значень (чисел).
Визначення:
• Матриця A називається ортогональною, якщо TA A I= ,
де TA − транспонована матриця A, а I − одинична матриця.
• Матриці A і B подібні, якщо існує така несингулярна
матриця P , що має місце співвідношення 1B P AP−= .
64
Основні властивості власних чисел: 1. Усі n власних чисел дійсної симетричної матриці
розмірності n×n – дійсні. Це корисно пам’ятати, оскільки матриці, що зустрічаються при розрахунках, часто бувають симетричними.
2. Якщо власні числа матриці різні, то її власні вектори ортогональні. Сукупність n лінійно незалежних власних векторів утворює базис розглянутого простору. Отже, для сукупності лінійно незалежних власних векторів iv
�, де
i = 1,...,n, будь-який довільний вектор d�
у тому ж просторі можна виразити через власні вектори. Таким чином,
1
n
i ii
d a v=
=∑� �
.
3. Якщо дві матриці подібні, то їх власні числа збігаються. З
подібності матриць A і B випливає, що 1B P AP−= .
Оскільки λA v v⋅ =� �, то 1 1λP A v P v− −⋅ =� �
.
Якщо прийняти v Pd=��
, то 1 λP AP d d− ⋅ =
� �,
Таким чином, матриці A і B не тільки мають однакові власні числа, але і їх власні вектори пов’язані співвідношенням
λB d d⋅ =� �
. 4. Помноживши власний вектор матриці на скаляр,
одержимо власний вектор тієї ж матриці. Звичайно всі власні вектори нормують, розділивши кожний елемент власного вектора або на його найбільший елемент, або на суму квадратів усіх інших елементів. 3.1. Ітераційні методи знаходження власних чисел
Метод знаходження найбільшого власного числа.
Мабуть, найбільш очевидним способом розв’язання задачі на власні значення – це їх визначення із системи рівнянь
65
( )λ 0A E v− =� , (3.2)
яка має ненульовий розв’язок лише у випадку, коли
{ }det λ 0A E− = . Розкривши визначник, одержимо багаточлен
n-ї степені відносно λ, корені якого й будуть власними числами
Рис. 3.1. Блок-схема ітераційного методу знаходження
максимального власного числа.
Вибір нормованого власного вектора x(0)
Обчислення А x(n) = λ x(n+1)
Чи достатньо мала різниця x(n+1)− x(n)
Так
Ні
Stop
x(n) = x(n+1)
Нормування x(n+1) й обчислення λ
66
матриці. Для визначення коренів можна скористатися методами, що були описані раніше. На жаль, у задачах на власні значення часто зустрічається кратні корені. Оскільки описані раніше ітераційні методи у цьому випадку не гарантують одержання всіх розв’язків, то для визначення власних значень слід користуватися іншими методами. На рис. 3.1 показана блок-схема найпростішого ітераційного
методу відшукання найбільшого власного числа системи (3.1). Процедура починається із початкового вихідного
нормованого вектора (0)v�
. Цей вектор множиться ліворуч на матрицю A і результат прирівнюється добутку константи
(власне число) і нормованого вектора (1)v�
. Якщо вектор (1)v�
збігається з вектором (0)v�
, розрахунок припиняється. А якщо ні, то новий нормований вектор використовується в якості вхідного і вся процедура повторюється. Якщо процес збігається, то константа відповідає дійсному найбільшому власному числу, а нормований вектор − відповідному власному вектору. Швидкість збіжності цього ітераційного процесу залежить від того, наскільки вдало обрано початковий вектор. Якщо він близький до дійсного власного вектора, то ітерації сходяться дуже швидко. На швидкість збіжності впливає також і відношення величин двох найбільших власних чисел. Якщо воно близьке до одиниці, то збіжність буде повільною. Приклад 1. Дослідимо тривісний напружений стан елемента тіла, яке
представлене на рис. 3.2. Матриця напруг для нього має вигляд 10 5 6
5 20 4
6 4 30
× 106 Н/м2.
Якщо виходити з того, що руйнування відбудеться при максимальній напрузі, то необхідно знати величину найбільшої головної напруги, яка відповідає найбільшому власному числу матриці напруг.
67
Рис. 3.2. Тривісний напружений стан елемента тіла.
Для знаходження цієї напруги скористаємося методом
ітерацій. Код програми:
Program Eigenv ! Програма визначення власних чисел і власних ! векторів матриці напруг
Real A(3,3), X(3), R(3) Open(6,file='Eigenv.txt') A(1,1) = 1.e07; A(1,2) = 5.e06; A(2,1) = A(1,2) A(1,3) = 6.e06; A(3,1) = A(1,3); A(2,2) = 2.e07 A(2,3) = 4.e06; A(3,2) = A(2,3); A(3,3) = 3.e07 X(1) = 1.0; X(2) = 0.0; X(3) = 0.0 xold =0.0; iter = 0 write (6,100) write (6,101) write (6,102) write (6,100) write (6,104) iter, X(1), X(2), X(3)
30х106 Па
20х106 Па
4х106 Па
10х106 Па
6х106 Па
5х106 Па
68
! Основний цикл Do iter = iter +1 R = matmul(A, X) X = R Call Norml(xmax,X) write(6,103) iter, xmax, X(1), X(2), X(3) If ( abs( (xold-xmax)/xmax) <= 0.001 ) Exit xold = xmax
End Do write(6,100) stop 100 format(1x,54('-')) 101 format(2x,'Iteration',3x,'Eigenvalue',11x,'Eigenvector') 102 format(3x,'number',6x,'(n/m2)',7x,'X(1)', &
6x,'X(2)',6x,'X(3)') 103 format(1x,i5,7x,e12.5,3f10.5) 104 format(1x,i5,19x,3f10.5)
End Program Eigenv Subroutine Norml(xbig,X)
Real X(3) xbig =X(1) If (X(2) .GT. xbig) xbig = X(2) If (X(3) .GT. xbig) xbig = X(3)
! Нормування за xbig X = X / xbig Return
End Subroutine Norml Результат маємо у вигляді: ------------------------------------------------------------------------------ Iteration Eigenvalue Eigenvector Nuhber (n/m2) X(1) X(2) X(3) ----------------------------------------------------------------------------- 0 1.00000 0.00000 0.00000 1 0.10000E+08 1.00000 0.50000 0.60000 2 0.26000E+08 0.61923 0.66923 1.00000
69
3 0.36392E+08 0.42697 0.56278 1.00000 4 0.34813E+08 0.37583 0.49954 1.00000 5 0.34253E+08 0.35781 0.46331 1.00000 6 0.34000E+08 0.34984 0.44280 1.00000 7 0.33870E+08 0.34580 0.43121 1.00000 8 0.33800E+08 0.34362 0.42466 1.00000 9 0.33760E+08 0.34240 0.42094 1.00000 10 0.33738E+08 0.34171 0.41884 1.00000 ----------------------------------------------------------------------------- Відзначимо, що для досягнення необхідної точності
потрібно було виконати 10 ітерацій. Визначення найменшого власного числа методом
ітерацій. У деяких випадках доцільно шукати найменше, а не найбільше власне число. Це можна зробити, попередньо
помноживши вихідну систему на матрицю 1A− : 1 1λA A v A v− −⋅ =� �
.
Якщо обидві частини цього співвідношення помножити на 1/λ, одержимо
11λ
v A v−=� �. (3.3)
Ясно, що це вже інша задача на власне значення, для якої
воно дорівнює 1/λ, а розглянутою матрицею є 1A− . Максимум
1/λ досягається при найменшому λ. Таким чином, описана вище ітераційна процедура може бути використана для визначення найменшого власного числа нової системи.
Визначення проміжних власних чисел методом ітерацій.
Знайшовши найбільше власне число, можна визначити наступне за ним по величині, замінивши вихідну матрицю матрицею, що містить ті власні числа, що залишилися. Використаємо для цього метод, що називається методом вичерпання. Для вихідної симетричної матриці A с відомим
найбільшим власним числом λ1 і власним вектором 1v�
можна
70
скористатися принципом ортогональності власних векторів,
тобто записати 0Ti jv v =� �
при i ≠ j й 1Ti jv v =� �
при i = j.
Якщо утворити нову матрицю *A відповідно до формули *
1 1λ Ti i iA v Av v v v= −� � � � �
(3.4)
то її власні числа й власні вектори будуть пов’язані
співвідношеннями * λi i iA v v⋅ =� �.
З наведеного вище виразу для матриці *A випливає, що *
1 1λ TA A v v= − � � . Тут при i = 1 властивість ортогональності
дозволяє звести праву частину до вигляду 1 1 1λA v v⋅ −� �.
Причому за визначенням власних чисел матриці A цей вираз повинен дорівнювати нулю.
Отже, власне число λ1 матриці *A дорівнює нулю, а всі
інші її власні числа збігаються із власними числами матриці
A. Таким чином, матриця *A має власні числа 0, λ2, λ3,…, λn і
відповідні власні вектори 1 2, , , nv v v� � �
… . А, отже, в результаті
виконаних перетворень найбільше власне число *A було вилучене, і тепер, щоб знайти наступне найбільше власне
число λ2, можна застосувати до матриці *A вищенаведений
ітераційний метод. Визначивши λ2 й 2v�
, повторимо весь
процеси, використовуючи нову матрицю **A , отриману за
допомогою *A , λ2 й 2v�
і т.і. Хоча на перший погляд здається, що розглянутий процес
повинен швидко привести до мети, він має істотні недоліки, що пов’язані з особливостями “комп’ютерної арифметики”. При виконанні кожного кроку похибки у визначенні власних векторів будуть позначатися на точності визначення наступного власного вектора і викликати подальше нагромадження помилок. Тому описаний метод навряд чи може бути застосований для знаходження більш ніж трьох власних чисел, починаючи з найбільшого або найменшого.
71
Якщо потрібно одержати більше число власних чисел, слід користуватися методами обертань. 3.2. Розв’язання повної проблеми власних чисел Визначимо міру близькості матриці A до діагонального
вигляду. Нехай
( )2
1,
σ ( 1, )N
i ijj j i
A a i N= ≠
= =∑ . (3.5)
Уведемо
( ) 21 2σ + σ +…+ σN ij
i j
t A a≠
= = ∑ .
Визначення. Процедура побудови матричної послідовності
{ } 0,kA A A≡ (k = 0, 1, 2,…) буде монотонною, якщо
( ) ( )1k kt A t A −< . (3.6)
Відомо, що довільна дійсна симетрична матриця A може бути зведена до діагонального вигляду за такою процедурою:
1A U D U−= ⋅ ⋅ , (3.7)
де U – ортогональна матриця : 1U U I−⋅ = ; I − одинична
матриця; D − діагональна матриця, на діагоналі якої
знаходяться власні числа λ , 1,i i N= матриці A . Оскільки U
– ортогональна матриця, для дійсної симетричної матриці A замість рівняння (3.7) маємо еквівалентне рівняння
TU A U D⋅ ⋅ = . (3.8) Для отримання (3.8) потрібно побудувати послідовність
ортогональних перетворень, які б дозволили необмежено зменшувати модулі недіагональних елементів матриці A . Згідно з алгоритмом Якобі будуємо матричну послідовність
{ }kA :
72
( ) ( )1 φ φk kTij ijA U A U+ = , (3.9)
де
( )
1
01
( )cosφ sinφ
φ
sinφ cosφ ( )
1
0
1
( ) ( )
i
U ij
j
i j
−=
<
⋱
…
…
⋱
(3.10) − ортогональні матриці плоских обертань, для яких при
довільному ϕ маємо ( ) ( )1 φ φij ijU U I− ⋅ = .
Позначимо { }k kijA a= . Нехай максимальний за модулем
недіагональний елемент матриці kA буде kija , i < j.
Використовуючи матриці обертань ( )φk kij ijU U= , будуємо
послідовність
1 k
ij
Tk k k
ijUA A U+ = ⋅ ⋅ . (3.11)
Побудуємо матрицю { }:k k kk kij ijB b B A U= = ⋅ . Згідно з
визначенням kijU всі стовпці матриці kB , крім i-го та j-го,
збігатимуться з відповідними стовпцями матриці kA .
73
Елементи стовпців із номерами (i) та (j) обчислюються за формулами:
cosφ sinφ ,
sinφ cosφ ( 1, ).
k k k k kni n i n j
k k k k kn j n i n j
b a a
b a a n N
= +
= − + =. (3.12)
Аналогічно всі рядки матриці 1kA + , крім (i) та (j),
збігатимуться з відповідними рядками матриці kB . Елементи рядків із номерами (i) та (j) обчислюються за формулами:
1
1
cosφ sinφ ,
sinφ cosφ ( 1, ).
k k k k kin in jn
k k k k kjn in jn
a b b
a b b n N
+
+
= +
= − + = (3.13)
Із (3.12) і (3.13) одержимо
( )( )
1 cosφ sinφ sinφ cosφ
cosφ sinφ cosφ sinφ .
k k k k k k k k kij ij jj ii ij
k k k k k kji jj
a b b a a
a a
+ = + = − + ×
× + − +(3.14)
Оскільки k kij jia a≡ , спрощуємо вираз (3.14)
( )1 1cos2φ sin 2φ
2k k k k k kij ij jj iia a a a+ = + − . (3.15)
Вибираємо φk таким, щоб 1 0kija + ≡ , тоді
tg2φ 2 ( )k k k kij ii jja a a= − . (3.16)
Зауваження: • Можна побудувати нескінченно багато подібних (3.11) процедур, які задовольняють умову (3.6).
• Для зведення матриці до діагонального вигляду за методом Якобі потрібна нескінченно велика кількість кроків, оскільки під час ітерацій на місці нульових елементів можуть знову з’являтися ненульові елементи, хоч і менші за величиною.
• Основна відмінність методу Гівенса від методу Якобі полягає у побудові його алгоритму, згідно з яким одержані на попередніх кроках ітерації нульові елементи
74
зберігаються у подальшому. А перевага методу Гівенса, порівняно з методом Якобі, у тому, що всі перетворення тут відбуваються за скінченну кількість кроків.
Метод Хаусхолдера1 [2, 3, 5, 18, 22] у випадку симетричних
матриць дозволяє привести матрицю до тридіагонального вигляду, використовуючи майже вдвічі меншу кількість операцій, ніж за методами Якобі або Гівенса. Це зумовлено тим, що при його виконанні на нульові перетворюються всі елементи рядків і стовпців, які не належать до трьох головних діагоналей матриці. Особливо яскраво перевага цього методу проявляється для дуже великих матриць розрідженої структури. При використанні методу Хаусхолдера на (N − 2) основних кроках виконуються такі перетворення:
1 k
ij
Tk k k
ijPA A P+ = . (3.17)
Тут кожна матриця відображень має вигляд
22
k kk
k
TX X
P EK
= − , (3.18)
де
1, , 1
0, 1,2, , ;
, 2, , ;
,
ik
ik ki
k k k k k
x i k
x a i k N
x a S+ +
= =
= = + =
…
…
∓
(3.19)
а 1 2
2 2 2, 1
1
, 2N
k k i k k k k ki k
S a K S a S+= +
= = ∑ ∓ . (3.20)
У виразах (3.19 і 3.20) знак береться відповідно до знака елемента , 1k ka + , що дозволяє зробити значення 1,k kx +
максимальним.
1 У вітчизняній літературі – метод відображень.
75
Розглянемо тепер розв’язання повної проблеми власних чисел для довільної дійсної невиродженої квадратної матриці A за допомогою QR-алгоритму.
Лема. Довільна дійсна невироджена квадратна матриця може бути представлена у вигляді добутку ортогональної і правої трикутної матриці.
Як наслідок леми подамо матрицю A у вигляді
11A Q R= ⋅ , (3.21)
де 1
Q − ортогональна, а 1
1kR A −≡ − права трикутна матриця
для матриці A. Помноживши (3.21) праворуч на 11
Q − , маємо
11 1
R Q A−= ⋅ . (3.22)
Підставляючи (3.22) в (3.21), отримуємо з A подібну їй матрицю
1 11 1
A Q A Q−= ⋅ ⋅ . (3.23)
Побудуємо тепер послідовність матриць { }kA за правилом
1 11 1
k kk k
A Q A Q+ −+ +
= ⋅ ⋅ . (3.24)
Можна довести, що процедура типу (3.24) приводить вихідну
матрицю 0A A≡ до вигляду: 1A Q Q−= ⋅Λ⋅ , (3.25)
де 1 2 N
Q Q Q Q= … ; { }λijΛ = − права канонічна форма
Жордана, тобто λ 0ij ≡ при j < i та j > i + 1; λ λii i≡ − власні
числа матриці A , , 1λi i + дорівнюють 0 або 1.
У монографії [22] розглядається декілька можливих алгоритмів побудови послідовності ортогональних матриць { }
kQ , які приводять до бажаного результату, але мають різну
арифметичну вартість. Найчастіше використовують
76
послідовність матриць обертань (3.10) або матриць відображень (3.18).
Зауваження: • При розв’язанні задачі власних чисел для несиметричної матриці за методами Гівенса та Хаусхолдера, матриця може бути зведена лише до вигляду Гесенберга
* * * * *
* * * * *
0 * * * *
0 0 * * *
0 0 0 * *
.
• Незважаючи на те, що для методу Хаусхолдера замість матриць плоских обертань (3.10) використовують більш складні ермітові ортогональні матриці відображень (3.18), результат маємо однаковий і для проблеми власних чисел, і при розв’язанні СЛАР із розрідженою матрицею.
• При використанні методів Гівенса та Хаусхолдера для розв’язання СЛАР із розрідженою симетричною матрицею, зведена до тридіагонального вигляду матриця СЛАР у подальшому розв’язується за допомогою QR-алгоритму або прогонкою за методом TDMA.
• При використанні QR-алгоритму для розв’язання СЛАР із розрідженою матрицею на першому кроці пропонується метод Гівенса або метод Хаусхолдера, які перетворюють довільну матрицю на матрицю Гесенберга. Для матриці Гесенберга пошук QR-розвинення суттєво спрощується.
• QR-розвинення для довільної невиродженої матриці A можна використати для розв’язання СЛАР подібно до LU-розвинення :
TR v Q b⋅ = ⋅��
. (3.26)
Розглянемо приклад використання QR-алгоритму для розв’язання повної проблеми власних чисел. Код програми:
77
program QR_test_main !======================================= ! QR basic method to find the eigenvalues of matrix A(*,*) !======================================= use QR_basic_mod1 implicit none integer, parameter :: n=3 real(8), parameter :: eps=1.0e-07 real(8) :: a(n,n), e(n) integer i, j, iter ! Matrix A(*,*) data a/2.6d0,1.d0,1.6d0,1.d0,3.1d0,1.6d0,1.6d0,1.6d0,3.6d0/ ! open(2,file='QR_test_rez.txt') ! ! Print a header and the original matrix write (*,200) write (2,200) do i=1,n write (*,201) (a(i,j),j=1,n) write (2,201) (a(i,j),j=1,n) end do ! call QRbasic(a,e,eps,n,iter) ! ! Print solutions write (*,202) write (*,201) (e(i),i=1,n) write (*,205) iter write (2,202) write (2,201) (e(i),i=1,n) write (2,205) iter 200 format (' QR basic method - eigenvalues for A(n,n)',/, & ' Matrix A') 201 format (6f12.6)
1 Модуль QR_BASIC_MOD знаходиться в Додатку.
78
202 format (/,' The eigenvalues') 205 format (/,' iterations = ',i5) stop end program QR_test_main Результат роботи програми: QR basic method - eigenvalues for A(n,n) Matrix A 2.600000 1.000000 1.600000 1.000000 3.100000 1.600000 1.600000 1.600000 3.600000 The eigenvalues 5.999151 1.907700 1.393149 iterations = 18 Аналогічний результат можна отримати при використанні
програми EVCSF з бібліотеки IMSL. Перевірку точності обчислення власних чисел і власних векторів матриці тут виконує програма EPISF також з бібліотеки IMSL. 3.3. Запитання та вправи 1) Які Вам відомі алгоритми знаходження найбільшого із власних значень й власних векторів матриці методом ітерацій?
2) Які Вам відомі алгоритми знаходження найменшого із власних значень й власних векторів матриці методом ітерацій?
3) Що таке метод вичерпання і чи можна із його допомогою розв’язати повну проблему власних чисел?
4) Які Ви знаєте процедури розв’язання повної проблеми власних чисел і власних векторів?
5) Наведіть алгоритм методу Якобі розв’язання повної
79
проблеми власних чисел? 6) Наведіть алгоритм методу Гівенса розв’язання повної проблеми власних чисел?
7) Наведіть алгоритм методу Хаусхолдера розв’язання повної проблеми власних чисел?
8) Наведіть QR-алгоритм розв’язання повної проблеми власних чисел?
9) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для знаходження усіх власних значень й власних векторів матриці?
10*) Знайти найменше власне число матриці 2.6 1 1.6
1 3.1 1.6
1.6 1.6 3.6
11*) Скориставшись стандартними процедурами із бібліотеки IMSL розв’язати повну проблему власних чисел для матриці із задачі 10.
3.4. Практичні завдання Завдання 4. Знаходження власних чисел і власних
векторів симетричних матриць Мета завдання:
1. Ознайомлення з ітераційними методами знаходження власних чисел і власних векторів симетричних матриць.
2. Ознайомлення з процедурами із бібліотеки IMSL (QR−алгоритм) знаходження власних чисел і власних векторів симетричних матриць.
Постановка завдання: Знаходження власних чисел і власних векторів
симетричних матриць із використанням ітеративних методів. Знаходження власних чисел і власних векторів симетричних матриць із використанням стандартних методів із бібліотеки IMSL. Порівняти результати.
80
Методичні вказівки: При підготовці до виконання роботи спочатку потрібно
познайомитися з ітеративними методами знаходження максимального та мінімального власних чисел і власних векторів симетричних матриць. Всі нижченаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Знайти максимальне власне число і власний вектор першої матриці ітеративним методом.
2. Знайти мінімальне власне число і власний вектор другої матриці ітеративним методом.
3. Знайти всі власні числа і власні вектори першої та другої матриці, скориставшись стандартними процедурами із бібліотеки IMSL.
4. Порівняти отримані результати для першої матриці. Варіанти завдання:
№ вар
Перша матриця Друга матриця
1
2,1 1 1,1
1 2,6 1,1
1,1 1,1 3,1
1 1,5 2,5 3,5
1,5 1 2 1,6
2,5 2 1 1,7
3,5 1,6 1,7 1
2
2,4 1 1,4
1 2,9 1,4
1,4 1,4 3,1
1 1,2 2 0,5
1,2 1 0,4 1,2
2 0,4 2 1,5
0,5 1,2 1,5 1
3
1,3 0,4 0,5
0,4 1,3 0,3
0,5 0,3 1,3
1 1,2 2 0,5
1,2 1 0,5 1
2 0,5 2 1,5
0,5 1 1,5 0,5
81
№ вар
Перша матриця Друга матриця
4
2,2 1 1,2
1 2,7 1,2
1,2 1,2 3,2
2,5 1 0,5 2
1 2 1,2 0,4
0,5 1,2 1 1,5
2 0,4 1,5 1
− − −
5
1,6 0,7 0,8
0,7 1,6 0,3
0,8 0,3 1,6
2 1 1,4 0,5
1 1 0,5 1
2 0,5 2 1,2
0,5 1 1,2 0,5
6
2,5 1 1,5
1 3 1,5
1,5 1,5 3,5
2 1,2 1 1
1,2 0,5 2 1
1 2 1,5 0,2
1 1 0,2 1,5
− − − −
−
7
1,4 0,5 0,6
0,5 1,4 0,3
0,6 0,3 1,4
2 1,5 3,5 4,5
1,5 2 2 1,6
3,5 2 2 1,7
4,5 1,6 1,7 2
8
1,7 0,8 0,9
0,8 0,7 0,3
0,9 0,3 1,7
1 0,5 1,2 1
0,5 2 0,5 0
1,2 0,5 1 1,4
1 0 1,4 1
− − − −
−
9
2,3 1 1,3
1 2,8 1,3
1,3 1,3 3,3
1,2 0,5 2 1
0,5 1 0,8 2
2 0,8 1 1
1 2 1 2
82
№ вар
Перша матриця Друга матриця
10
2,6 1 1,6
1 3,1 1,6
1,6 1,6 3,6
0,5 1,2 1 0,9
1,2 2 0,5 1,2
1 0,5 1 1
0,9 1,2 1 2,2
11
3,5 1 2,5
1 4 2,5
2,5 2,5 4,5
1,2 0,5 2 1
0,5 1 0,6 2
2 0,6 1 1
1 2 1 1
12
1,8 0,9 1
0,9 1,8 0,3
1 0,3 1,8
3 1,5 4,5 5,5
1,5 3 2 1,6
4,5 2 3 1,7
5,5 1,6 1,7 3
13
1,5 0,6 0,7
0,6 1,5 0,3
0,7 0,3 1,5
1,6 1 1,4 1
1 1 0,5 2
1,4 0,5 2 1,2
1 2 1,2 0,5
14
2,7 1 1,7
1 3,2 1,7
1,7 1,7 3,7
2,4 0,5 2 1
0,5 1 0,8 2
2 0,8 1 0,5
1 2 0,5 1,2
15
1,4 1,2 1,3
1,2 0,9 0,4
1,3 0,4 0,8
− −
0,5 1,2 2 1
1,2 2 0,5 1,2
2 0,5 1 0,5
1 1,2 0,5 1,6
83
№ вар
Перша матриця Друга матриця
16
2,6 1 1,6
1 3,1 1,6
1,6 1,6 3,6
0,5 1,2 1 0,9
1,2 2 0,5 1,2
1 0,5 1 1
0,9 1,2 1 2,2
17
3,5 1 2,5
1 4 2,5
2,5 2,5 4,5
1,2 0,5 2 1
0,5 1 0,6 2
2 0,6 1 1
1 2 1 1
18
1,8 0,9 1
0,9 1,8 0,3
1 0,3 1,8
3 1,5 4,5 5,5
1,5 3 2 1,6
4,5 2 3 1,7
5,5 1,6 1,7 3
19
1,5 0,6 0,7
0,6 1,5 0,3
0,7 0,3 1,5
1,6 1 1,4 1
1 1 0,5 2
1,4 0,5 2 1,2
1 2 1,2 0,5
20
2,7 1 1,7
1 3,2 1,7
1,7 1,7 3,7
2,4 0,5 2 1
0,5 1 0,8 2
2 0,8 1 0,5
1 2 0,5 1,2
21
1,4 1,2 1,3
1,2 0,9 0,4
1,3 0,4 0,8
− −
0,5 1,2 2 1
1,2 2 0,5 1,2
2 0,5 1 0,5
1 1,2 0,5 1,6
84
№ вар
Перша матриця Друга матриця
22
2,2 1 1,2
1 2,7 1,2
1,2 1,2 3,2
2 1,5 3,5 4,5
1,5 2 2 1,6
3,5 2 2 1,7
4,5 1,6 1,7 2
23
1,6 0,7 0,8
0,7 1,6 0,3
0,8 0,3 1,6
1 0,5 1,2 1
0,5 2 0,5 0
1,2 0,5 1 1,4
1 0 1,4 1
− − − −
−
24
2,5 1 1,5
1 3 1,5
1,5 1,5 3,5
1,2 0,5 2 1
0,5 1 0,8 2
2 0,8 1 1
1 2 1 2
25
1,4 0,5 0,6
0,5 1,4 0,3
0,6 0,3 1,4
1,2 0,5 2 1
0,5 1 0,6 2
2 0,6 1 1
1 2 1 1
26
1,7 0,8 0,9
0,8 0,7 0,3
0,9 0,3 1,7
3 1,5 4,5 5,5
1,5 3 2 1,6
4,5 2 3 1,7
5,5 1,6 1,7 3
27
2,3 1 1,3
1 2,8 1,3
1,3 1,3 3,3
1,6 1 1,4 1
1 1 0,5 2
1,4 0,5 2 1,2
1 2 1,2 0,5
85
№ вар
Перша матриця Друга матриця
28
1,5 0,6 0,7
0,6 1,5 0,3
0,7 0,3 1,5
2,4 0,5 2 1
0,5 1 0,8 2
2 0,8 1 0,5
1 2 0,5 1,2
29
2,7 1 1,7
1 3,2 1,7
1,7 1,7 3,7
0,5 1,2 2 1
1,2 2 0,5 1,2
2 0,5 1 0,5
1 1,2 0,5 1,6
30
1,4 1,2 1,3
1,2 0,9 0,4
1,3 0,4 0,8
− −
2,4 0,5 2 1
0,5 1 0,8 2
2 0,8 1 0,5
1 2 0,5 1,2
86
Розділ 4. Методи обробки числових даних
Досліднику звичайно доводиться мати справа з великими
масивами чисел, тому методи обробки числових даних мають для нього особливе значення. Часто ключем до правильного розуміння багатьох задач служить продумане представлення вхідних даних. Навпаки, невдале представлення вхідних даних буває причиною плутанини і помилок при розв’язанні задачі. Особливе значення в роботі дослідника мають наступні види обробки масивів чисел, які розглядаються в даному розділі: 1. Інтерполяція. 2. Апроксимація кривих. 3. Числове диференціювання. 4. Числове інтегрування. 4.1. Інтерполяція Дані, з якими доводиться мати справа досліднику,
найчастіше представляються у вигляді таблиць. Що може бути пов’язане або з тим, що дані були отримані експериментально й лише для деяких дискретних значень аргументу, або з тим, що об’єм таблиць обмежений і в них можна привести лише деякі дані. Сутність інтерполяції полягає у відшуканні значення функції в деякій проміжній точці. Найпростішою інтерполяцію є лінійна інтерполяція, в
основі якої лежить апроксимація кривої на ділянці між точками (xk, yk) та (xk+1, yk+1) прямою, що проходить через ті ж точки (рис. 2.13). Рівняння прямої можна представити у вигляді
1 1
1
( ) ( )k k k k
k k
y x x y x xy
x x+ +
+
− − −=
− (4.1)
або у вигляді
1
1
k k k
k k k
y y y y
x x x x+
+
− −=
− − . (4.2)
87
Рис. 2.13. Лінійна інтерполяція.
Таким чином, знаючи два табличні значення yk і yk+1, що
відповідають xk і xk+1, за допомогою зазначених формул можна знайти значення функції при будь-якім значенні х в інтервалі [xk, xk+1]. Звичайно вважається, якщо використати більше число сусідніх точок і апроксимувати реальну криву більш складною лінією, можна уточнити отриманий результат. У цьому розділі викладаються методи знаходження єдиного многочлена n-го ступеня Рn(х), що апроксимує функцію f(x) кривою, яка проходить через усі (n+1) задані в таблиці точки (xi, yi), де i = 0, 1,…,n. У цьому випадку говорять, що многочлен задовольняє умовам
Рn(хi) = yi при i = 0,1,…,n. (4.3) Методи відшукання такого многочлена діляться на три
групи: метод Лагранжа, різницеві методи та ітераційні методи.
Інтерполяція за Лагранжем. При цій інтерполяції задається (n+1) табличне значення (xi , yi), де i = 0, 1,…,n. Передбачається, що точки (xi , yi) належать кривій y = f(x) в інтервалі x0 ≤ x ≤ xn. Інтерполяційний многочлен для цього методу має вигляд
y
yk+1
yk
xk+1 xk
x
f(x) пряма
88
0 0 1 1( ) ( ) ( ) ( )n n nP x y b x y b x y b x= + + +… , (4.4) де всі bj(х) — многочлени ступеня n, коефіцієнти яких можна знайти з (n+1) рівнянь вигляду (4.3). У результаті маємо систему рівнянь
0 0 0 1 1 0 0 0
0 0 1 1
( ) ( ) ( ) ,
( ) ( ) ( ) .
n n
n n n n n n
y b x y b x y b x y
y b x y b x y b x y
+ + + =
+ + + =
…
… … …
…
(4.5)
Якщо значення bj(xi) обрано так, що 1, ,
( )0, ,j i
i jb x
i j
== ≠
(4.6)
то виписані вище рівняння будуть задоволені. Ця умова означає, що будь-який многочлен bj(x) дорівнює нулю в кожній точці хi, крім xj. Отже, у загальному випадку многочлен bj(x) має вигляд
0 1 1 1( ) ( )( ) ( )( ) ( )j j j j nb x C x x x x x x x x x x− += − − − − −… … . (4.7)
Оскільки bj(xj) = 1, то коефіцієнт Cj визначається виразом
0 1 1 11/ ( )( ) ( )( ) ( )j j j nC x x x x x x x x x x− += − − − − −… … . (4.8)
Нарешті, для шуканого многочлена отримуємо
0
( ) ( ) ( )n
n j j j jj
P x y L x L x=
= ∑ , (4.9)
де
0 1 1 1( ) ( )( ) ( )( ) ( )j j j nL x x x x x x x x x x x− += − − − − −… … . (4.10)
Метод розділених різниць. Існує багато різницевих
методів інтерполяції, однак найпоширенішим серед них є метод Ньютона для інтерполяції вперед, відомий також як метод Ньютона−Грегорі. Інтерполяційний многочлен для цього методу має вигляд
0 1 0 2 0 1
0 1 1
( ) ( ) ( )( )
( )( ) ( ).n
n n
P x c c x x c x x x x
c x x x x x x−
= + − + − − ++ − − −
…
… (4.11)
Коефіцієнти сj знаходяться із (n+1) рівняння, подібних (4.5), що дозволяє записати СЛАР у вигляді
89
0 0
0 1 1 0 1
0 1 2 0 2 2 0 2 1 2
0 0 1 1
,
( ) ,
( ) ( )( ) ,
( )( ) ( ) .n n n n n n
c y
c c x x y
c c x x c x x x x y
c c x x x x x x y−
=+ − =+ − + − − =
+ + − − − =… … …
… …
(4.12)
Це лінійна система рівнянь із трикутною матрицею, і визначення з її допомогою значень cj не викликає труднощів. Однак існує ще більш простий спосіб визначення cj , заснований на застосуванні правих скінченних різниць. Якщо значення х задані через рівні проміжки xi+1 − xi = h, то в загальному випадку xi = x0+i h, де i = 0,1,…,n. Останній вираз дозволяє привести розв’язання рівняння до вигляду
( )
( )
0 0
1 0 1
22 0 1 2
0 1 2
,
,
2 2 ,
[( 1) ] ( !) ,ii i
y c
y c c h
y c c h c h
y c c ih c ih i h c i h
== +
= + +
= + + − + +
… … …
…
(4.13)
звідки для коефіцієнтів маємо
1 0 1 0 00 0 1, .
y c y y yc y c
h h h
− − ∆= = = = (4.14)
Тут ∆ у0 називається першою правою різницею. Продовжуючи обчислення, знаходимо
2 2 0 1 2 1 1 02 2
20
02 2
1 1( 2 ) [( ) ( )]
2 2
1[ ( )] ,
2 2
c y c hc y y y yh h
yy
h h
= − − = − − − =
∆= ∆ ∆ =
(4.15)
де ∆2у0 — друга права різниця, яка представляє собою різницю
різниць. Загалом, коефіцієнт cj можна представити у вигляді
0 { !}j jjc y j h= ∆ . (4.16)
У загальному випадку різниці більш високих порядків для функції у = f(x) в інтервалі x0 ≤ x ≤ xn визначаються виразом
90
1 11
j j ji i iy y y− −
+∆ = ∆ − ∆ , де i = 0,1,…,n−j. (4.17)
Зауваження: • Часто вирази типу (4.17) зводять у таблиці, де різниці
порядку n виражені через різниці порядку (n−1). • Використовуючи інші різниці, одержимо інші
інтерполяційні схеми, наприклад метод Ньютона для інтерполяції назад, методи Гаусса для інтерполяції вперед і назад.
Ітераційні методи інтерполяції. Ці методи засновані на
повторному застосуванні простої інтерполяційної схеми. Найбільш відомим з них є метод Ейткена, який і буде розглянуто нижче. Сутність метода Ейткена в повторному застосуванні лінійної інтерполяції. Вище було показано, що лінійна інтерполяція між точками
(х0, у0) та (хi, уi) здійснюється за формулою
[ ]1 0 00
1( ) ( ) ( )i i i
i
y x y x x y x xx x
= − − −−
(4.18)
з використанням якої, задаючи значення хi, можна скласти таблицю функцій yi1(х), де i = 1,2,…,n. Користуючись цими функціями, за допомогою лінійної інтерполяції
[ ]2 11 1 01
1( ) ( )( ) ( )( )i i i
i
y x y x x x y x x xx x
= − − −−
(4.19)
одержимо нову сім’ю співвідношень. Простою підстановкою можна показати, що вирази для yi2(x) представляють собою многочлени другого ступеня, які описують криві, що проходять через точки (х0, у0), (х1, у1) й (хi, уi). Одержавши многочлени yi2 через лінійну інтерполяцію і використовуючи функції yi2(x), можна записати вираз для многочлена третього ступеня
[ ]3 22 2 02
1( ) ( )( ) ( )( )i i i
i
y x y x x x y x x xx x
= − − −−
(4.20)
91
який описує криві, що проходять через точки (х0, у0), (х1, у1), (х2, у2) та (хi, уi). Продовжуючи цей процес, будемо одержувати значення yij(x), які будуть прямувати до точного значення f(x).
Зауваження: • Хоча в принципі цей метод дозволяє вводити многочлени
ступеня більше ніж 3-й, цього не роблять, щоб уникнути катастрофічного зростання помилок.
• Метод Ейткена не вимагає, щоб значення функції, які використовують для інтерполяції, були розташовані через однакові інтервали.
Зворотна інтерполяція. Представляє собою алгоритм, за
допомогою якого знаходять значення аргументу х, яке відповідає заданому значенню функції у і лежить між двома його значеннями, що наведені в таблиці. Щоб застосувати викладені вище методи, потрібно видозмінити таблицю, помінявши в ній місцями х та у. Єдиний недолік цього прийому в тому, що тепер значення аргументу не будуть розташовані через рівні інтервали, що виключає використання методів Лагранжа та Ньютона, для яких крок аргументу повинен бути обов’язково постійним. 4.2. Апроксимація кривих Існує два основні підходи до апроксимації табличних даних
кривими. Згідно першого з них вимагається, щоб апроксимуюча крива (можливо, кусочно-гладка) проходила б через усі точки, які задані таблицею. Це вдається зробити з використанням методів інтерполяції, які були розглянуті вище. При другому підході дані апроксимують простою функцією, що застосовна у всім діапазоні табличних даних, але не обов’язково проходить через усі точки. Такий підхід називається припасуванням кривої, яке прагнуть провести так, щоб відхилення припасованої кривої від табличних даних були мінімальними. Звичайно при цьому мінімізують суму квадратів різниць між значеннями функції, що обумовлені обраною
92
кривою, і таблицею. Такий метод припасування називається методом найменших квадратів.
Метод найменших квадратів. Нехай у таблиці задана (n+1) точка (х0, y0), (х1, y1), …, (хn, уn) і потрібно знайти апроксимуючу криву g(x) у діапазоні x0 ≤ x ≤ xn. У цьому випадку похибка у кожній табличній точці буде εi = g(xi) − yi . Тоді сума квадратів похибок визначається виразом
[ ]2
1
( )n
i ii
E g x y=
= −∑ . (4.21)
Звичайно функцію g(x) вибирають у вигляді лінійної комбінації відповідних функцій
1 1 2 2( ) ( ) ( ) ( )k kg x c g x c g x c g x= + + +… . (4.22) Умова мінімуму Е визначається рівняннями
1 2
0k
E E E
c c c
∂ ∂ ∂= = = =∂ ∂ ∂
… . (4.23)
Оскільки
[ ]21 1 2 2
1
( ) ( ) ( )n
i i k k i ii
E c g x c g x c g x y=
= + + + −∑ … , (4.24)
то умова мінімуму Е еквівалентна системі рівнянь
[ ]
[ ]
1 1 2 2 1 11
1 1 2 2
2 ( ) ( ) ( ) ( ) 0,
2 ( ) ( ) ( ) ( ) 0.
i i k k i i
i i k k i i k ik
Ec g x c g x c g x y g x
c
Ec g x c g x c g x y g x
c
∂ = + + + − =∂
∂ = + + + − =∂
∑
∑
…
… … …
…
(4.25) Останні k рівнянь можна представити у вигляді СЛАР
Ac b=��
, (4.26) де
21 1
1
( ), ( ) ( ),
( ) , ( , 1, , ).
n njj j i jl j i l ii i
nj j i ii
a g x a g x g x
b g x y j l k
= =
=
= =
= =
∑ ∑
∑ … (4.27)
93
Оскільки елементи матриці в лівій частині (4.26) і вектора-стовпчика в правій визначаються табличними даними, то виписана система k лінійних рівнянь із k невідомими може бути розв’язана. Можна вибрати будь-яку функцію g(x), аби тільки вона була лінійної щодо своїх коефіцієнтів. Фактичний вибір функції повинен здійснюватися з урахуванням специфіки табличних даних, під якою розуміється їхня періодичність, експонентний або логарифмічний характер, властивості симетрії та наявність асимптотики.
Зауваження: • Іноді таблицю розбивають на декілька частин і
підбирають окрему апроксимуючу криву для кожної частини, однак це треба робити обачно. Такий підхід виправданий у тих випадках, коли є підстава вважати, що вихідні дані відповідають різним фізичним станам системи. Прикладами можуть слугувати переходи конструкції від стійкого стану до нестійкого, переходи від дозвукової течії до надзвукової або від ламінарної течії до турбулентної.
• Користуючись наближеною формулою, не слід виходити за межі інтервалу, де вона визначена.
Ортогональні поліноми. Якщо при побудові
апроксимуючої функції в якості gi (х) використати ортогональні поліноми, для яких
1 ( ) ( ) 0nj i l ii g x g x= =∑ при j ≠ l (4.28)
то матриця виписаної в попередньому розділі системи рівнянь (4.26) буде діагональною, а вирази для коефіцієнтів cj суттєво спрощуються:
{ } { }21 1( ) ( )n n
j j i i j ii ic g x y g x= == ∑ ∑ . (4.29)
Це дуже полегшує розв’язання задачі, і саме тому в багатьох стандартних програмах припасування кривих використовуються саме ортогональні поліноми. Приклад 5.
94
Знайти значення полінома 3-го ступеня 2 3
1 2 3 4( )F x C C x C x C x= + + + (4.30) в точці х0 = 0,186, якщо в точках xd = {0.68, 0.73, 0.80, 0.88, 0.93, 0.99} його значення наближено дорівнюють yd = {0.80866, 0.89492, 1.02964, 1.20966, 1.34087, 1.52368}. Невідомі коефіцієнти полінома знайти методом найменших квадратів. Код програми:
program lsq_test use DATA_PROCESSING 1 implicit none integer, parameter :: m=6, n=4, mm1=m-1 real (dp) :: q, err0, one = 1.d0, x0 = 0.715d0 ! x0 = 0.186d0 real (dp) :: x(m,n), yd(m), xd(m), xrow(m), yelem, & beta(mm1), c(n), res(m) integer :: nvar, i, j, ifault logical :: fit_const, lindep(m) data xd/0.68d0,0.73d0,0.80d0,0.88d0,0.93d0,0.99d0/ data yd/0.80866d0,0.89492d0,1.02964d0,1.20966d0, & 1.34087d0,1.52368d0/ ! Open output file open(2,file='least_sq_test.txt') ! Set values for A(*,*) do i = 1,m do j = 1,n x(i,j)=xd(i)**(j-1) end do end do ! Print A(*,*) write(2,*) ' A=' do i = 1,m write(2,'(4f8.4)') (x(i,j),j=1,n) end do ! Use include to form the orthogonal reduction. 1 Модуль DATA_PROCESSING знаходиться в Додатку.
95
nvar = n; fit_const = .true. call startup(nvar, fit_const) do i = 1, m xrow(1) = one do j = 1, n xrow(j+1) = x(i,j) end do yelem = yd(i) call includ(one, xrow, yelem) end do ! Call tolset to set tolerances, then sing to ! detect singularities. call tolset call sing(lindep, ifault) ! Calculate residual sums of squares (rss). call ss ! Calculate regression coefficients call regcf(beta, mm1, ifault) c(1) = beta(1) do i=2,n; c(i) = beta(i+1); end do write(2,'(a,4f12.4)') ' c=', c err0 = 0.0 do i=1,m q=c(1) do j=2,n; q=q+c(j)*(xd(i)**(j-1)); end do res(i)=abs(q-yd(i)); err0=err0+res(i)**2 end do err0=sqrt(err0)/m write(2,*) ' res= ' write(2,'(6x,3e12.4)') res write(*,*) ' res= ' write(*,'(6x,3e12.4)') res q=c(1) do j=2,n; q=q+c(j)*(x0**(j-1)); end do
96
write(2,'(a,f6.4,a,f8.4,a,1pe12.4)') ' q(',x0,')= ',q,' err= ',err0 write(*,'(a,f6.4,a,f8.4,a,1pe12.4)') ' q(',x0,')= ',q,' err= ',err0 end program lsq_test
Результат: A= 1.0000 0.6800 0.4624 0.3144 1.0000 0.7300 0.5329 0.3890 1.0000 0.8000 0.6400 0.5120 1.0000 0.8800 0.7744 0.6815 1.0000 0.9300 0.8649 0.8044 1.0000 0.9900 0.9801 0.9703 c= -1.0813 5.5686 -6.5920 3.6615 res= 0.1559E-03 0.3720E-03 0.2453E-03 0.2183E-03 0.3706E-03 0.1231E-03 q(0.7150)= 0.8686 err= 1.0841E-04 Аналогічний результат можна отримати, якщо
скористатися процедурою LSBRR із стандартної бібліотеки IMSL.
Сплайни. Сплайни лише недавно стали використовувати в обчислювальній математиці. Однак у машинобудівному кресленні вони фактично застосовуються вже давно, бо сплайн − це не що інше, як гнучка лінійка, яку деформують так, щоб по ній можна було провести криву через задані точки (хi, уi). Будучи деформована таким чином, лінійка отримує форму, при якій запасена в ній пружна енергія мінімальна. Використовуючи теорію вигину бруса при малих деформаціях, можна показати, що сплайн − це група пов’язаних кубічних многочленів, у місцях з’єднання яких перша і друга похідні безперервні. Такі функції називають кубічними сплайнами. Щоб побудувати кубічний сплайн, необхідно задати коефіцієнти, які єдиним чином визначають кубічний многочлен у проміжку між даними точками. Наприклад, у випадку, що представлений на рис. 2.14, необхідно задати всі
97
кубічні функції q1(x), q2(x), …, qm(x). У найбільш загальному випадку ці многочлени мають вигляд
2 31 2 3 4( )i i i i iq x k k x k x k x= + + + , i = 1,2,…,m, (4.31)
де kji − константи, що обумовлені зазначеними вище умовами. Перші 2m умов вимагають, щоб сплайни з’єднувалися в
заданих точках. Ці умови такі
1
( ) , 1, , ,
( ) , 0,1, , 1.i i i
i i i
q x y i m
q x y i m+
= == = −
…
… (4.32)
Наступні (2m−2) умов вимагають, щоб у місцях з’єднання сплайнів були рівні перші і другі похідні
1
1
( ) ( ), 0,1, , 1,
( ) ( ), 0,1, , 1.i i i i
i i i i
q x q x i m
q x q x i m+
+
′ ′= = −′′ ′′= = −
…
… (4.33)
Для того, щоб система лінійних алгебраїчних рівнянь мала розв’язок, необхідно, щоб число рівнянь точно дорівнювало числу невідомих. На даному етапі ми маємо 4m невідомих й (4m−2) рівнянь. Отже, ми повинні знайти ще два рівняння.
Рис. 2.14. Сплайни.
y
x
x0
y2 y1 y0
ym
xm-1 xm
ym-1
qm(x)
x1 x2
q2(x) q1(x)
98
Звичайно використовують рівняння
1 0 0( ) 0, ( ) 0.mq x q x′′ ′′= = (4.34) Отриманий таким способом сплайн називають “природним
кубічним сплайном”. Знайшовши коефіцієнти сплайна, можна використати цю кусочно-гладку поліноміальну функцію для представлення даних при інтерполяції, припасуванні кривої або поверхні. На перший погляд може здатися, що визначення
коефіцієнтів зводиться до розв’язання 4m рівнянь із 4m невідомими. Однак, спеціально вибравши вигляд кубічних многочленів, можна значно спростити задачу. Якщо окремі кубічні рівняння мають вигляд
2 21 1( ) ( ) ( ) ,
1, , ,
i i i i i i i iq x ty t y x k d tt k d t t
i m
− − = + + ∆ − − −
= … (4.35)
де
11 1, 1 , , ,i i
i i i i i i ii i
x x yt t t d y y y x x x
x x−
− −− ∆
= = − = ∆ = − ∆ = −∆ ∆
,
(4.36) то кожне з рівнянь qi(x) має тільки два постійні невідомі коефіцієнти. Після того, як перше рівняння qi(x) записане, з кожним наступним рівнянням додається тільки один новий невідомий коефіцієнт. При цьому при x = xi-1 0, 1t t= = , а при x = xi 1, 0t t= = . Отже, при такому виборі кубічних многочленів автоматично задовольняються всі умови, крім умов, що накладають на другі похідні. Останні виражаються для внутрішніх точок у вигляді співвідношень
1 1 1 1 1 12 ( ) 3( ),
1, , 1,i i i i i i i i i i ik x k x x k x d x d x
i m− + + + + +∆ + ∆ + ∆ + ∆ = ∆ + ∆= −…
(4.37)
а для двох зовнішніх − співвідношеннями
0 1 1 12 3 , 2 3m m mk k d k k d−+ = + = . (4.38) Таким чином, система рівнянь (4.35)-(4.38) лінійна щодо
коефіцієнтів сплайна ki, i = 0,…,m, а її матриця − тридіагональна. Тобто, система рівнянь (4.35)-(4.38) може бути успішно розв’язана методом прогонки (див. розділ 2.1).
99
У розглянутій системі рівнянь число обумовлених коефіцієнтів дорівнює числу заданих точок. Тому розв’язок виявляється не більш складним, ніж у випадку апроксимації (m+1) точок многочленом m-го ступеня. При цьому часто виявляється, що кубічний сплайн апроксимує функцію краще, ніж многочлен ступеня m. Слід зазначити, що існують і інші види сплайнів, які можна отримати при інших умовах на кінцях або при використанні многочленів більш високих ступенів. Приклад 6. Проінтерполювати функцію F(x) = Sin(x) на відрізку [0,1] із
використанням кубічного сплайну. Знайти значення функції в усіх проміжних точках. Код програми:
program main_spline use DATA_PROCESSING 1 implicit none integer, parameter :: n=11 ! Base points for interpolation integer, parameter :: nint=21 ! Сompute interpolation ! in nint points. real(8) :: xmin, xmax ! Given interval of x(). real(8) :: x, y, step, ys, error, errav real(8), dimension (n) :: xi, yi, b, c, d0 integer i real(8) :: f ! Open output file open (2, file='spline_rez.txt') ! xmin = 0.0; xmax = 1.0 ! Step 1: generate xi and yi from f(x), xmin, xmax, n step = (xmax-xmin)/(n-1) do i=1,n xi(i) = xmin + step*float(i-1) yi(i) = f(xi(i))
1 Модуль DATA_PROCESSING знаходиться у Додатку.
100
end do ! Step 2: call spline to calculate spline coeficients call spline (xi, yi, b, c, d0,n) ! Step 3: interpolation at nint points errav = 0.0; step = (xmax-xmin)/(nint-1) write(*,201) write(2,201) do i=1, nint x = xmin + step*float(i-1) ; y = f(x) ys = ispline(x, xi, yi, b, c, d0, n) error = ys-y write (*,200) x, ys, error write (2,200) x, ys, error ! Step 4: calculate quality of interpolation errav = errav + abs(y-ys)/nint end do write (*,202) errav write (2,202) errav 200 format (2f12.5,1pe12.4) 201 format (' x spline error') 202 format (' Average error= ',1pe12.4) end program main_spline ! Function f(x) ! function f(x) real(8) :: f, x f = sin(x) end function f
Результат: x spline error 0.00000 0.00000 0.0000E+00 0.05000 0.04998 4.0660E-07 0.10000 0.09983 0.0000E+00 0.15000 0.14944 -1.5139E-07 0.20000 0.19867 0.0000E+00
101
0.25000 0.24740 -3.4735E-08 0.30000 0.29552 0.0000E+00 0.35000 0.34290 -9.6562E-08 0.40000 0.38942 0.0000E+00 0.45000 0.43497 -1.1524E-07 0.50000 0.47943 0.0000E+00 0.55000 0.52269 -1.2267E-07 0.60000 0.56464 0.0000E+00 0.65000 0.60519 -2.1145E-07 0.70000 0.64422 0.0000E+00 0.75000 0.68164 2.2095E-08 0.80000 0.71736 0.0000E+00 0.85000 0.75128 -9.4287E-07 0.90000 0.78333 0.0000E+00 0.95000 0.81342 2.5745E-06 1.00000 0.84147 0.0000E+00 Average error= 2.2277E-07 Аналогічний результат можна отримати, якщо
скористатися процедурою CSIEZ із стандартної бібліотеки IMSL. 4.3. Числове диференціювання Іноді потрібно визначити наближену похідну функції, що
задана таблицею. Відповідні формули можна одержати, наприклад, із використанням ряду Тейлора або диференціюючи інтерполяційні вирази, що наведені в розд. 4.1. Числове диференціювання табличних функцій може дати
зовсім безглузді результати, тому його потрібно по можливості уникати. Щоб краще зрозуміти причини подібних утруднень, розглянемо два їх потенційних джерела. Перші труднощі виникають при використанні табличних даних, які отримані підчас експериментів. У будь-якому експерименті корисна інформація супроводжується більш-менш сильним шумом. Результат вимірів реального сигналу (рис. 2.15 а) містить
102
шумову компоненту (рис. 2.15 б). Якщо такий сигнал продиференціювати, то похибка різко зростає (рис. 2.15 в). Навпаки, при інтегруванні сигналу, що містить шум,
погрішність убуває (рис. 2.15 г). Цей приклад показує, що числове інтегрування − процес, набагато більш стійкий, ніж числове диференціювання.
а б
в г Рис. 2.15. Числове диференціювання та інтегрування сигналу із
шумом. Інші труднощі, які зустрічаються при числовому
диференціюванні, ілюструє рис. 2.16. Звернемо увагу, що навіть у випадку, коли інтерполяційний многочлен добре апроксимує табличну функцію, його похідні вищих порядків можуть не мати нічого спільного з похідними апроксимуючої
Похідна
від
поміряного сигналу
Час Час
Інтеграл
від
поміряного сигналу
Істинний
сигнал
Час
Поміряний
сигнал
Час
103
функції. Це добре видно на рис. 2.16 при порівнянні нахилу і кривизни двох кривих. Покажемо на простому прикладі, як можна одержати
формули числового диференціювання, виходячи з формул інтерполяції за Лагранжем. Нехай апроксимуючий многочлен другого ступеня
0 1 0 2 0 1( ) ( ) ( )( )P x C C x x C x x x x= + − + − − (2.141) обрано таким чином, що відповідна крива проходить через точки (x0, y0), (x1, y1) і (x2, y2). Користуючись викладеною вище методикою, можна визначити значення його констант:
1 0 2 1 00 0 1 2 2
, ,2
y y y y yC y C C
h h
− − += = = . (4.39)
Диференціюючи многочлен Р(х), одержимо
1 2 0 1( ) (2 )P x C C x x x′ = + − − . (4.40)
При х = х0, беручи до уваги, що х0 − х1= −h, маємо
0 0 1 2( ) ( 3 4 ) 2P x y y y h′ = − + − . (4.41) Отримана в (4.41) величина називається наближенням
другого порядку для похідної в точці х = х0. У всіх випадках, коли доводиться користуватися похідною,
яка отримана шляхом числового диференціювання, слід
Рис. 2.16. Похибки числового диференціювання при
використанні інтерполяційних многочленів.
y
x
f(x)
P(x)
104
оцінювати порядок величини помилки апроксимації. Для цього використовують розвинення функції в ряд Тейлора:
2 3ε ε( ε) ( ) ε ( ) ( ) ( )
2! 3!f x f x f x f x f x′ ′′ ′′′+ = + + + +… . (4.42)
Прийнявши х = х0 , ε = h (тобто рівним кроку таблиці), одержимо f(x0+h) = y1 . Отже,
2 32 3
1 0 0 0 0( ) ( ) ( )2 6
h hy y h D y D y D y= + + + +… . (4. 43)
Аналогічним чином, при ε = 2h маємо 3
2 2 32 0 0 0 0
42 ( ) 2 ( ) ( )
3
hy y h D y h D y D y= + + + +… . (4.44)
Якщо із цих двох рівнянь виключити другу похідну D2(y0), помноживши перше з них на 4, а друге на −1, й, потім, склавши обидва, маємо
30 1 2 0
03 4
( )2 3
y y y h yD y
h
′′′− + −= + . (4.45)
Це наближення другого порядку для першої похідної
відрізняється від виразу в (4.41) членом 3 3h y′′′ , який і визначає тут величину помилки апроксимації. Аналогічним чином можна одержати похідні більш
високих порядків для форм із правими, центральними або лівими різницями.
4.4. Числове інтегрування
Дослідникові часто доводиться обчислювати значення
визначеного інтеграла числовими методами. Це буває тоді, якщо або не вдається знайти інтеграл у явній формі, або явна форма настільки складна, що простіше скористатися числовим інтегруванням. Як було показано вище (рис. 2.15), числове інтегрування являє собою стійкий процес. На противагу числовому диференціюванню воно зменшує вплив похибок у вихідних даних на остаточний результат. В основі числового інтегрування лежить наближене обчислення площі під кривою,
105
що описує підінтегральна функція. У загальному вигляді задача формулюється як знаходження значення
( )b
a
In f x dx= ∫ . (4.46)
Методи числового інтегрування класифікуються в залежності від того, чи задані значення аргументу через рівні проміжки, чи ні. Так, метод Ньютона−Котеса вимагає, щоб значення х були задані з постійним кроком, а метод Гаусса не накладає такого обмеження. Перейдемо до розгляду обох цих методів.
Метод Ньютона−−−−Котеса. Найпростіша з формул
Ньютона−−−−Котеса утворюється при інтегруванні методом трапецій, в основі якого лежить лінійна апроксимація підінтегральної функції. З’єднаємо прямими сусідні точки (xi, yi) та (xi+ 1, yi+ 1), що
задані таблицею в інтервалі a ≤ x ≤ b. Якщо x0 = а, а xn = b, то інтеграл буде являти собою суму площ n трапецій висотою h кожна. Якщо виразити визначений інтеграл через задані в таблиці значення функції, маємо
0 1 2 11
( ) [ 2 2 2 ]2
b
n na
In f x dx h y y y y y−= = + + + + +∫ … . (4.47)
На рис. 2.17 метод трапецій представлено графічно. Очевидно, що чим менше інтервали, через які задаються значення функції, тем з більшою точністю буде обчислений визначений інтеграл. Очевидно, що можна підвищити точність результату,
замінивши лінійну апроксимацію апроксимацією кривими більш високого порядку, наприклад параболами. Правда, щоб провести параболу, необхідно мати три точки замість двох. Апроксимуючи підінтегральну функцію параболами,
одержимо іншу формулу, яка відома як правило Симпсона:
0 1 2 3 11
( ) [ 4 2 4 4 ]3
b
n na
In f x dx h y y y y y y−= = + + + + + +∫ … . (4.48)
106
Рис. 2.17. Інтегрування методом трапецій. У формулі Симпсона число інтервалів парне. Для числового інтегрування можна застосовувати також
апроксимуючі многочлени більш високих порядків. Загальна формула носить ім’я Ньютона−Котеса і має наступний вигляд:
1 ( ) *0 1
0
( ) ( )b n
k ki i
ia
In f x dx C h w f C h f x+
== = +∑∫ , (4.49)
де n − число смуг, які розбивають площу під підінтегральною кривою, k − ступінь відповідних многочленів, x* − деяка точка з інтервалу [а, b], f (k) (x*) − значення k−ї похідної функції f(x) у точці x*, a h − крок заданих значень функції. Значення коефіцієнтів С0, С1 та wi наведені в таблиці 2.1. Останній член у формулі Ньютона−Котеса С1 h
k+1 f (k) (x*) вказує на порядок величини похибки, що обумовлена апроксимацією. Очевидно, що при зменшенні h величина hk+1 убуває ще швидше. Однак слід мати на увазі, що похибка апроксимації також залежить від f (k) (x*). А, оскільки існують функції, для яких похідні високих порядків мають дуже великі значення, для них не вдається зменшити помилку шляхом збільшення k.
y
x
y=f(x)
a b xn xn+1
f(xn)
f(xn+1)
107
Таблиця 2.1. Коефіцієнти формул Ньютона−Котеса k C0 w0 w1 w2 w3 w4 w5 w6 C1 1 1/2 1 1 - - - - - -1/12 2 1/3 1 4 1 - - - - -1/90 3 3/8 1 3 3 1 - - - -3/80 4 2/45 7 32 12 32 7 - - -8/945
5
5/288
19
75
50
50
75
19
- 275
12096−
6
1/140
41
216
27
272
27
216
41 9
1400−
Метод Гаусса. При використанні методу Ньютона−Котеса
значення функції повинні задаватися з постійним кроком по осі Oх. Якщо зняти це обмеження, то крок, з яким задаються значення функції, можна вибрати так, щоб помилка апроксимації була якнайменшою. У цьому і полягає сутність методу Гаусса. Нехай у формулі
00
( ) ( )b n
i iia
In f x dx C h w f x E=
= = +∑∫ (4.50)
wi і xi розглядаються як невідомі, які потрібно визначити. Загальне число невідомих дорівнює 2(n+1). Щоб визначити всі коефіцієнти многочлена ступеня 2n+1, потрібно мати 2n+2 умов. Будемо апроксимувати інтеграл многочленом ступеня 2n+1 і зажадаємо, щоб помилка була нульовою для всіх многочленів того ж або меншого ступеня. У результаті маємо 2n+2 рівнянь із 2n+2 невідомими, які в загальному випадку будуть лінійними відносно wi і нелінійними відносно xi. Якщо інтегрування проводиться в інтервалі [−1, 1], то значення xi будуть являти собою n+1 корінь полінома Лежандра pn+1(x) = 0. Визначивши значення xi можна визначити значення wi з лінійної системи рівнянь. Проілюструємо сказане на прикладі для n = 1. Щоб умова
1 1
01
( ) ( )i ii
f x dx w f x=−
=∑∫ (4.51)
108
задовольнялося для всіх многочленів ступеня 2n+1 й менших при f(x) = 1, х, х2 або х3 зазначена рівність повинна бути точною. Цей висновок дозволяє записати наступні рівняння:
1
0 11
1
0 0 1 11
12 2 2
0 0 1 11
13 3 3
0 0 1 11
2,
0,
2,
3
0,
w w dx
w x w x xdx
w x w x x dx
w x w x x dx
−
−
−
−
+ = =
+ = =
+ = =
+ = =
∫
∫
∫
∫
(4.52)
що утворюють систему чотирьох рівнянь із чотирма невідомими, яку можна розв’язати, хоча вона і нелінійна. Щоб обійти труднощі, пов’язані з нелінійністю, можна скористатися поліномом Лежандра p2 = −1 + 3x2, корені якого x1 = −√3/3 і x2 = √3/3. Підставляючи ці значення х в будь-які два рівняння із записаних вище, одержимо w0 = w1 = l. Отже, інтеграл можна представити у вигляді
1
1
3 3( ) ( ) ( )
3 3f x dx f f
−= − +∫ . (4.53)
Зауваження:
• Обмеження на величину інтервалу [−1, 1] не таке суттєве, як це може здатися. Завдяки заміні змінної
[2 ( )] ( ), ( ) ( )x Z a b b a F Z f x= − + − = (4.54) інтеграл з довільними межами приводиться до вигляду
1
1
( ) ( )2
b
a
b aIn F Z dZ f x dx
−
−= =∫ ∫ . (4.55)
• Якщо загальний інтервал інтегрування розбити на рівні підінтервали, на кожному з яких можна скористатися формулою Гаусса, то значення інтеграла для всього
109
інтервалу визначається підсумовуванням відповідних значень інтегралів для підінтервалів.
Приклад числового інтегрування. Знайти адаптивними1 методами Симпсона та Гаусса
інтеграл 2
2
0
1.xIn xe dx e= = +∫ (4.56)
Код знаходження значення інтегралу методом Симпсона: program main_simps ! Integration of a function using Simpson rule ! with doubling number of intervals use DATA_PROCESSING implicit none integer nint real(8) :: a, b, f, integral, eps external f open(2,file='integral_rez.txt') a = 0.0; b=2.d0 eps = 1.0e-8 call simpson2(f,a,b,eps,integral,nint) write(*,101) nint, integral, exp(1.0)**2+1.0 write(2,101) nint, integral, exp(1.0)**2+1.0 101 format(‘ intervals = ‘,i8,/,’ integral = ‘,f15.9,/,’ e2+1 = ‘,f15.9) stop end program main_simps function f(x) ! Function for integration implicit none real(8) :: f, x f = x*exp(x) return end function f
1 Метод з автоматичним вибором кроку інтегрування.
110
Результат: intervals = 256 integral = 8.389056099 e^2+1 = 8.389055252 Код знаходження значення інтегралу методом Гаусса:
program main_gauss ! Integration of a function using Gauss 8 and 16 points ! with doubling number of intervals ! till error = |I_16 - I_8| < eps use DATA_PROCESSING implicit none integer nint real(8) :: a, b, f, integral, eps external f open(2,file='gauss_integral_rez.txt') a = 0.0; b = 2.0 eps = 1.0e-6 call gauss2(f,a,b,eps,integral,nint) write(*,101) nint, integral,exp(1.0)**2+1.0 write(2,101) nint, integral,exp(1.0)**2+1.0 101 format(' intervals = ',i8,/,' integral = ',f15.9,/,' e^2+1 = ',f15.9) stop end program main_gauss function f(x) ! Function for integration implicit none real(8) :: f, x f = x*exp(x) return end function f
Результат: intervals = 1 integral = 8.389056090 e^2+1 = 8.389055252
111
4.5. Запитання та вправи 1) Які Ви знаєте методи обробки числових даних? 2) Які Ви знаєте методи інтерполяції? 3) Які Ви знаєте апроксимуючі поліноми? 4) Що таке зворотна інтерполяція? 5) Наведіть алгоритм метода найменших квадратів. 6) Наведіть алгоритм метода сплайнів. 7) В чому полягають недоліки числового диференціювання? 8) Які Ви знаєте методи числового інтегрування функцій? 9) Наведіть алгоритм інтегрування функцій методом трапецій?
10) Наведіть алгоритм інтегрування функцій методом Симпсона?
11) Наведіть алгоритм інтегрування функцій методом Гаусса? 12) У чому полягають особливості реалізації числового інтегрування із заданою точністю?
13) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для числового інтегрування функції?
14*) Побудувати за методом найменших квадратів поліном третього ступеня, якщо відомо абсциси xd={0.41, 0.46, 0.52, 0.6, 0.65, 0.72} і ординати yd={2.57418, 2.32516, 2.09336, 1.86203, 1.74926, 1.62098} точок кривої. Знайти значення функції в точці х0 = 0.468. Скористатися стандартними процедурами із бібліотеки IMSL.
15*) За умови попередньої задачі обчислити коефіцієнти сплайна. Знайти значення сплайна в точці х0 = 0.468. Скористатися стандартними процедурами із бібліотеки IMSL.
16*) Знайти значення інтеграла (4.56). Скористатися стандартною процедурою інтегрування за методом Гаусса із бібліотеки IMSL.
17*) Знайти значення інтеграла
20
ln ln(10)
201 (10 )
xdx
x
π∞ −=+∫ .
Скористатися стандартною процедурою інтегрування за методом Гаусса із бібліотеки IMSL.
112
4.6. Практичні завдання Завдання 5. Апроксимація кривих.
Мета завдання:
1. Ознайомлення з методами апроксимації кривих: метод найменших квадратів, сплайни.
2. Ознайомлення з процедурами апроксимації кривих із бібліотеки IMSL: метод найменших квадратів, сплайни. Постановка завдання: Апроксимація кривих з використанням методу найменших
квадратів та сплайн-апроксимація. Апроксимація кривих з використанням методу найменших квадратів та сплайн-апроксимація із використанням стандартних методів із бібліотеки IMSL. Порівняти результати. Методичні вказівки: При підготовці до виконання роботи спочатку потрібно
познайомитися апроксимацією кривих з використанням методу найменших квадратів та сплайнів. Всі нижченаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Виконати апроксимацію функції заданої таблицею з використанням сплайнів на рівномірній сітці з першого завдання. Знайти значення функції в заданій точці х0.
2. Виконати апроксимацію функції заданої таблицею з використанням методу найменших квадратів на нерівномірній сітці з другого завдання. Знайти значення функції в заданій точці х0.
3. Повторити завдання з п.п. 1 та 2, скориставшись стандартними процедурами із бібліотеки IMSL.
4. Порівняти отримані результати. Варіанти завдання:
113
Перша таблиця
Друга таблиця
х у № вар.
х0 х у № вар.
х0
1,375 5,04192 1 1,3832 0,43 1,63597 1 0,702 1,380 5,17744 7 1,3926 0,48 1,73234 7 0,512 1,385 5,32016 13 1,3862 0,55 1,87686 13 0,645 1,390 5,47069 19 1,3934 0,62 2,03345 19 0,736 1,395 5,62968 25 1,3866 0,70 2,22846 25 0,608 1,400 5,79788 - - 0,75 2,35973 - - х у №
вар. х0 х у №
вар.
х0
0,115 8,65729 2 0,1264 0,02 1,02316 2 0,102 0,120 8,29329 8 0,1315 0,08 1,09590 8 0,114 0,125 7,95829 14 0,1232 0,12 1,14725 14 0,125 0,130 7,64893 20 0,1334 0,17 1,21483 20 0,203 0,135 7,36235 26 0,1285 0,23 1,30120 26 0,154 0,140 7,09613 - - 0,30 1,40976 - - х у №
вар. х0 х у №
вар.
х0
0,150 6,61659 3 0,1521 0,35 2,73951 3 0,526 0,155 6,39989 9 0,1611 0,41 2,30080 9 0,453 0,160 6,19658 15 0,1662 0,47 1,96864 15 0,482 0,165 6,00551 21 0,1542 0,51 1,78776 21 0,552 0,170 5,82558 27 0,1625 0,56 1,59502 27 0,436 0,175 5,65583 - - 0,64 1,34310 - - х у №
вар. х0 х у №
вар. х0
0,180 5,61543 4 0,1838 0,41 2,57418 4 0,616 0,185 5,46693 10 0,1875 0,46 2,32513 10 0,478 0,190 5,32634 16 0,1944 0,52 2,09336 16 0,665 0,195 5,19304 22 0,1976 0,60 1,86203 22 0,537 0,200 5,06649 28 0,2038 0,65
1,74926 28 0,673
0,205 4,94619 - - 0,72
1,62098 - -
114
Перша таблиця Друга таблиця
х у № вар.
х0 х у № вар.
х0
0,210 4,83170 5 0,2121 0,68 0,80866 5 0,896 0,215 4,72261 11 0,2165 0,73 0,89492 11 0,812 0,220 4,61855 17 0,2232 0,80 1,02964 17 0,774 0,225 4,51919 23 0,2263 0,88 1,20966 23 0,995 0,230 4,42422 29 0,2244 0,93 1,34087 29 0,715 0,235 4,33337 - - 0,99 1,52368 - - х у №
вар. х0 х у №
вар. х0
1,415 0,88855 6 1,4179 0,11 9,05421 6 0,314 1,420 0,88960 12 1,4258 0,15 6,61659 12 0,235 1,425 0,89064 18 1,4396 0,21 4,69170 18 0,332 1,430 0,89167 24 1,4236 0,29 3,35106 24 0,275 1,435 0,89269 30 1,4315 0,35 2,73951 30 0,186 1,440 0,89370 - - 0,40 2,36522 - -
Завдання 6. Числове інтегрування функцій одної змінної.
Мета завдання:
1. Ознайомлення з методами числового інтегрування функцій одної змінної: метод Симпсона, метод Гаусса.
2. Ознайомлення з процедурами числового інтегрування функцій одної змінної із бібліотеки IMSL: метод Симпсона, метод Гаусса.
Постановка завдання: Числове інтегрування двох функцій одної змінної за
методами Симпсона і Гаусса. Числове інтегрування функцій одної змінної за методами Симпсона і Гаусса із використанням стандартних методів із бібліотеки IMSL. Порівняти результати. Методичні вказівки: При підготовці до виконання роботи спочатку потрібно
познайомитися з методами Симпсона і Гаусса числового інтегрування функцій одної змінної. Всі нижченаведені кроки
115
лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Виконати числове інтегрування двох функцій одної змінної за методом Симсона.
2. Виконати числове інтегрування двох функцій одної змінної за методом Гаусса.
3. Повторити завдання з п.2, скориставшись стандартною процедурою із бібліотеки IMSL.
4. Порівняти отримані результати. Варіанти завдання:
№ Функції a b 1 1
2
1,
sin
x
x
f e
f e x
= −
=
0,2 0
2,1
π / 2
2
( )
3
1
2
1 ,
1 3 2cos
f x x
f x
= +
= +
1,0 0
8,0
π / 2
3
( )( )
2
1
2 2
2
1 ln ,
1 10 x
f x x
f x −
=
= − ⋅
2,0
1,1
2,7
1,5
4 1
3 2
2
arcsin,
(1 )
x
xf
x x
f x e
=+
=
0,2
0,0
0,3
0,8
5 ( )
1
2
arctg ,
1 1
f x x
f x
= ⋅
= +
0,0
0,0
1,7
2,0
116
№ Функції a b 6
( )1
3
2
1 5 3cos ,
tg2 8
f x
xf
π
= −
= +
0,0
0,0
π / 2
π / 8
7
( )( )
1
22
2 4 1 ,
1 1 1
f x
f x x
= −
= + +
1,0
0,0
2,0
0,2 8
1
32
1,
1
xf e
f x x
= +
= +
0,0
2,0
1,0
3,0
9 ( )1
2
arcsin,
1
2 1x
xf
x x
f
=−
= −
0,2
0,2
0,3
0,9
10
1
2
arctg ,
2
1 4
x
x
f x x
f
= ⋅
=−
0,0
-2,0
1,6
-1,3
11 ( )1
2
sin ,
1 3 2cos
xf e x
f x
== +
0,0
0,0
π / 4
π / 6
12 ( )3 2
1
2
,
1 1 2
xf x e
f x
=
= +
0,0
0,0
0,8
1,0
13
( )( )
1
2
2
1 1 ,
1 1 1
f x
f x x
= +
= + +
0,0
0,2
1,8
0,3
117
№ Функції a b
14
( )( )2 2
1
22
1 10 ,
1 ln
xf x
f x x
−= − ⋅
= ⋅
0,0
2,0
0,4
2,5
15
( )3
1
2
tg 0.5 16 ,
2 1x
f x
f
π= +
= −
0,0
0,3
π / 4
1,0
16 ƒ1 = sin4(x) + cos(x3),
ƒ2 = sin(x − π / 4)+ex + 6,25 π / 6 π / 4
π / 4 π / 2
17
ƒ1 = sin(2 x − π / 12), ƒ2 = 3 sin(x4) + 2,33
π / 6 π / 4
π / 2 3 π / 4
18
ƒ1 = cos(x5+1), ƒ2 = sin(2 log5(x))+1,1
π / 12 π / 5
π / 6 π / 4
19
ƒ1 = cos(x3+1) ƒ2 = arctg(sin(2,3 x) − 0,5)
π / 10 π / 5
π / 12 π / 6
20
ƒ1 = sin(x−π / 6) log5(x+1), ƒ2 = cos3(2x−π / 10)+arctg(x / π − 1 / 25)
π / 10 π / 15
π / 5 π / 5
21
ƒ1 = sin(12*x), ƒ2 = cos(2 x3) − 1+4,6
π / 6 π / 4
π / 2 3 π / 4
22
ƒ1 = cos2(x/2,1)*sin6(e3x ), ƒ2 = arctg(x / π − 1 / 25)
π / 20 π / 15
π / 10 π / 5
23
ƒ1 = 2*sin(x3)*cos(3*x-1), ƒ2 = arctg(e3x – 1)
π / 7 π / 15
π / 3 π / 5
24
ƒ1 = arctg(x3)+log8(3*x+1), ƒ2 = arcctg(e3x – 1)
π / 6 4,0
π / 4 5,2
25
ƒ1 = arctg(x / π), ƒ2 = 2*sin(1,2*x+1)+1
π / 6 π / 4
π / 2 3 π / 4
26
ƒ1 = x4 – ln(4+sin(x2)), ƒ2 = ln(x3) – 12,4*x
π / 12 1,5
π / 6 2,4
27
ƒ1 = ln(x+12)*sin(√x3), ƒ2 = 2,3*cos(x3)
π / 10 π / 5
π / 6 π / 3
28
ƒ1 = x 3*sin6 (e3x ), ƒ2 = arctg(x − 0,15)
π / 10 0,25
π / 5 1,25
118
№ Функції a b
29 ƒ1 = tg(ln x3 )*sin(√x),
ƒ2 = arctg(2*x−1,2) π / 6 1,4
π / 4 2,4
30
ƒ1 = arctg2(sin x), ƒ2 = arctg(0.5*ln x )+1
π / 20 0,15
π / 10 0,5
119
Розділ 5. Розв’язання звичайних диференціальних рівнянь
Диференціальними називаються рівняння, що містять одну
або кілька похідних. Дослідникові часто доводиться мати справу з диференціальними рівняннями або при виконанні числових експериментів, або при моделюванні реальних процесів, оскільки більша частина законів фізики формулюється саме у вигляді диференціальних рівнянь. По суті, будь-яка задача, пов’язана з розрахунками потоків енергії або рухом тіл, зводиться до розв’язання диференціальних рівнянь. На жаль, далеко не всі з них вдається розв’язати без допомоги комп’ютера. Тому числові методи розв’язання диференціальних рівнянь відіграють таку важливу роль в комп’ютерній механіці. В залежності від числа незалежних змінних і типу їх
похідних диференціальні рівняння діляться на дві суттєво різні категорії: звичайні диференціальні рівняння (ЗДР), що містять одну незалежну змінну та її похідні, і рівняння в частинних похідних, що містять дві (або більше) незалежні зміні та їх похідні. Ми будемо розглядати лише методи розв’язання звичайних диференціальних рівнянь. Передбачається, що читач в основному знайомий з теорією
диференціальних рівнянь. Тим, хто в цьому не певен, ми рекомендуємо попередньо з нею познайомитися. 5.1. Задача Коші і крайова задача Для того, щоб розв’язати звичайне диференціальне
рівняння, необхідно знати значення залежної змінної (і/або) її похідних при деяких граничних значеннях незалежної змінної. Якщо подібні додаткові умови задаються при одному значенні незалежної змінної, то така задача називається задачею з початковими умовами, або задачею Коші. Якщо ж умови задаються при двох (або більше) значеннях незалежної змінної, то така задача називається крайовою. В задачі Коші в якості незалежної змінної найчастіше виступає час. Прикладом може
120
бути задача про вільні коливання тіла, що підвішене на пружині. Рух такого тіла описується диференціальним рівнянням, незалежною змінною якого є час t . Якщо початкові умови задані у вигляді значень переміщення і швидкості при t=0, то маємо задачу Коші. У крайових задачах в якості незалежної змінної найчастіше виступає довжина. Відомим прикладом такої задачі є диференціальне рівняння, що описує деформацію пружного стержня. У цьому випадку крайові умови звичайно задаються на обох кінцях стержня. Хоча обидві зазначені задачі розглядаються в одній главі, при їхньому розв’язанні застосовуються суттєво різні методи і обчислювальні алгоритми. Почнемо із задачі Коші.
Задача Коші. Сформулюємо задачу Коші. Нехай дано диференціальне рівняння
( , )dy
f x ydx
= (5.1)
і початкова умова 0 0( )y x y= . Потрібно знайти функцію ( )y x , яка задовольняє і зазначене рівняння, і початкову умову. Звичайно числове розв’язання цієї задачі одержують, обчислюючи спочатку значення похідної, а потім задаючи малий приріст х і переходячи до нової точки 1 0x x h= + . Положення нової точки визначається за нахилом кривої, який обчислено із диференціального рівняння. Таким чином, графік числового розв’язання являє собою послідовність коротких прямолінійних відрізків, якими апроксимується реальна крива
( )y y x= . Сам алгоритм числового методу визначає порядок дій при переході від даної точки кривої до наступної. Оскільки числове розв’язання задачі Коші широко
застосовується в різних галузях науки і техніки, число розроблених для цього методів дуже велике. Зупинимося тут на наступних двох групах методів розв’язання задачі Коші: 1. Однокрокові методи, коли для знаходження наступної точки на кривій ( )y y x= потрібна інформація лише про один попередній крок. Однокроковими є метод Ейлера і методи Рунге−Кутта.
121
2. Методи прогнозу і корекції (багатокрокові), коли для відшукання наступної точки кривої ( )y y x= потрібна інформація більш ніж про одну з попередніх точок. Тут, щоб одержати достатньо точне числове значення, часто застосовують ітерації. До таких методів належать методи Мілна, Адамса−Башфорта та Хеммінга.
Похибки. Перш ніж перейти до обговорення конкретних
методів числового розв’язання диференціальних рівнянь, зупинимося на джерелах похибок, які пов’язані із числовою апроксимацією. Таких джерел три: 1. Похибка округлення обумовлена обмеженнями на представлення чисел у комп’ютері. Ці обмеження пов’язані, в першу чергу, з обмеженим числом значущих цифр, які запам’ятовуються і використовуються в комп’ютері при обчисленнях.
2. Похибка усічення пов’язана з тим, що при апроксимації функції замість нескінченних рядів часто використовується лише декілька їх перших членів. Цей звичайний для числових методів прийом являється джерелом похибок, які обумовлені лише методом обчислення і не залежать від можливостей самого комп’ютера.
3. Похибка поширення є результатом нагромадження похибок, які з’явилися на попередніх етапах розрахунку. Оскільки жоден наближений метод не може дати абсолютно точних результатів, то будь-яка похибка, що з’явилася підчас його виконання, зберігається і на наступних стадіях розрахунку.
Зазначені три джерела похибок являються причинами
обчислювальних помилок двох типів:
• Локальна помилка — сума похибок, що внесені до обчислювального процесу на кожному кроці обчислень.
• Глобальна помилка — різниця між обчисленим і точним значенням шуканої величини на кожному етапі
122
реалізації числового алгоритму, яка визначає сумарну похибку, що нагромадилася з моменту початку обчислень.
5.2. Однокрокові методи розв’язання задачі Коші Однокрокові методи призначені для розв’язання
диференціальних рівнянь першого порядку у вигляді ( , )y f x y′ = (5.2)
де y dy dx′ = , при початковій умові 0 0( )y x y= . Ці методи дозволяють обчислити послідовні значення y, що відповідають дискретним значенням незалежної змінної x.
Метод Ейлера. Є найпростішим методом розв’язання задачі Коші для диференціального рівняння першого порядку. Його точність невелика і тому на практиці ним користуються порівняно рідко. Однак на базі цього методу легше зрозуміти алгоритми інших, більш ефективних методів. Метод Ейлера засновано на розвиненні невідомої
функції y в ряд Тейлора в околі точки x0:
Рис. 2.18. Метод Ейлера.
y
x
h
y1
y0
x0 x1
Точний розв’язок
Нахил = f(x0,y0)
Похибка
123
20 0 0 0
1( ) ( ) ( ) ( )
2y x h y x h y x h y x′ ′′+ = + ⋅ + ⋅ +… . (5.3)
Якщо y мале, то члени, що містять h у другій або більш високих ступенях, є малими більш високих порядків і ними можна зневажити. Тоді
0 0 0( ) ( ) ( )y x h y x h y x′+ = + ⋅ , (5.4)
де 0( )y x′ знаходимо з правої частини диференціального рівняння при підстановці в нього початкової умови. Таким чином, можна одержати наближене значення залежної змінної при малому зсуві h від початкової точки. Цей процес можна продовжити, якщо скористатися співвідношенням
1 ( , ), 1,2,n n n ny y h f x y n+ = + ⋅ = … . (5.5) Графічно метод Ейлера показано на рис. 2.18. Похибка методу має порядок h2, бо в розвиненні (5.3) відкидаються члени, що містять h у другій і більш високих ступенях.
Модифікований метод Ейлера. Хоча тангенс кута нахилу
дотичної до точної кривої у вихідній точці відомий і рівний
0( )y x′ , він змінюється відповідно до зміни незалежної змінної. Тому в точці x0 + h нахил дотичної вже не такий, яким він
був у точці x0. Отже, при збереженні початкового нахилу дотичної на всім інтервалі h в результаті обчислень вноситься похибка. Точність методу Ейлера можна суттєво підвищити, якщо
поліпшити апроксимацію похідної. Наприклад, цього можна досягти, якщо використати середнє значення похідної на початку і на кінці інтервалу. Згідно алгоритму модифікованого метода Ейлера спочатку обчислюється значення функції в наступній точці за методом Ейлера
*1 ( , )n n n ny y h f x y+ = + ⋅ , (5.6)
яке використовується для обчислення наближеного значення
похідної наприкінці інтервалу *1 1( , )n nf x y+ + . Обчисливши
середнє між цим значенням похідної та її значенням на початку інтервалу, знайдемо більш точне значення 1ny + :
124
Рис. 2.19. Модифікований метод Ейлера.
*1 1 1
1( , ) ( , )
2n n n n n ny y h f x y f x y+ + + = + + (5.7)
Модифікований алгоритм Ейлера ілюструє рис. 2.19. Ідею, на якій засновано цю модифікацію метода Ейлера,
можна пояснити і інакше. Для цього повернемося до розвинення функції в ряд Тейлора (5.3). Очевидно, що, зберігаючи член з h2 та відкидаючи члени більш високих порядків, можна підвищити точність. Однак для того, щоб зберегти член з h2, треба знати другу похідну 0( )y x′′ . Її можна апроксимувати скінченною різницею [5]:
0 00
( ) ( )( )
y x h y xyy x
x h
′ ′′ + −∆′′ = =∆
(5.8)
Підставивши цей вираз в ряд Тейлора з відкинутими членами другого порядку, маємо формулу
[ ]0 0 0 01
( ) ( ) ( ) ( )2
y x h y x h y x h y x′ ′+ = + + + , (5.9)
яка збігається з раніше отриманим виразом (5.7) за умови, що точне значення похідної ( )ny x h′ + замінене
h/2 h/2
y
x
yn+1 y*
n+1 yn
xn xn+1
Точний розв’язок
Нахил = f(xn ,yn)
Похибка
Уточнення
Нахил = f(xn+1,y*n+1)
125
наближеним *1 1( , )n nf x y+ + . Оцінки показують, що помилка при
такій заміні має порядок h3.
Зауваження: • Модифікований алгоритм Ейлера має другий порядок
точності, бо містить член ряду Тейлора з h2. Похибка на кожному кроці, при використанні цього алгоритму, має порядок h3 .
• За підвищення точності доводиться розплачуватися додатковими витратами комп’ютерного часу, які
необхідні для обчислення *1ny + .
• Ще вища точність може бути досягнута, якщо виконати кращу апроксимацію похідної шляхом збереження більшого числа членів ряду Тейлора. Саме ця ідея лежить в основі методів Рунге−Кутта.
Методи Рунге−−−−Кутта. Щоб зберегти в ряді Тейлора член
n−го порядку, необхідно якимось чином обчислити n-у похідну від залежної змінної. При використанні модифікованого методу Ейлера для одержання другої похідної в скінченно-різницевій формі досить було знати нахили кривої на кінцях розглянутого інтервалу. Щоб обчислити третю похідну в скінченно-різницевому вигляді, необхідно мати значення другої похідної щонайменше у двох точках. Для цього необхідно додатково визначити нахил кривої в деякій проміжній точці інтервалу h, тобто між nx і 1nx + . Очевидно, що чим вище порядок похідної, яку необхідно знайти, тим більше додаткових обчислень буде потрібно виконати всередині інтервалу. Метод Рунге−Кутта дає набір формул для розрахунків координат внутрішніх точок, які необхідні для реалізації такого алгоритму. Оскільки існує декілька способів розташування внутрішніх точок і вибору відносних вагових коефіцієнтів для знайдених похідних, то метод Рунге−Кутта, по суті, поєднує цілу сім’ю методів розв’язання диференціальних рівнянь першого порядку. Найпоширенішим серед них є класичний метод Рунге−Кутта, коли утримуються
126
всі члени ряду Тейлора, включаючи h4. Це метод має четвертий порядок точності і для нього похибка на кожному кроці має порядок h5. Розрахунки при використанні цього методу проводяться за наступною формулою:
1 0 1 2 3( 2 2 ) 6n ny y K K K K+ = + + + + , (5.10) де
0
1 0
2 1
3 2
( , ),
( 2, 2),
( 2, 2),
( , ).
n n
n n
n n
n n
K h f x y
K h f x h y K
K h f x h y K
K h f x h y K
= ⋅= ⋅ + += ⋅ + += ⋅ + +
(5.11)
Зауваження. Метод Ейлера і його модифікація по суті
представляють собою методи Рунге−Кутта першого і другого порядку, відповідно. У порівнянні з ними метод Рунге−Кутта має важливу перевагу, бо забезпечує більш високу точність, яка з лишком виправдовує додаткове збільшення об’єму обчислень. Більш висока точність методу Рунге−Кутта часто
дозволяє збільшити крок інтегрування h, оскільки припустима похибка на кроці інтегрування і визначає його максимальну величину. Щоб забезпечити високу ефективність обчислювального процесу, величину h слід вибирати саме з міркувань максимальної припустимої похибки на кроці інтегрування. Такий вибір часто здійснюється автоматично і являється складовою частиною алгоритму методу Рунге−Кутта з автоматичним вибором кроку інтегрування. Відносну точність однокрокових методів
продемонструємо на прикладі. Нехай потрібно розв’язати рівняння
22 2dy
x ydx
= + (5.12)
при початковій умові (0) 1, 0 1y x= ≤ ≤ і 0,1h = . Це лінійне рівняння має точний розв’язок:
127
2 21,5 0,5xy e x x= − − − ; (5.13) який допоможе нам порівняти відносну точність різних методів. Результати розрахунків представлені в таблиці 2.2. Очевидні переваги методу Рунге−Кутта в порівнянні зі звичайним і модифікованим методами Ейлера. Таблиця 2.2. Порівняння точності методів розв’язання задачі
Коші для звичайних диференціальних рівнянь xn Метод
Ейлера Модифікований метод Ейлера
Метод Рунге−Кутта
Точний Розв’язок
0,0 1,0000 1,0000 1,0000 1,0000 0,1 1,2000 1,2210 1,2221 1,2221 0,2 1,4420 1,4923 1,4977 1,4977 0,3 1,7384 1,8284 1,8432 1,8432 0,4 2,1041 2,2466 2,2783 2,2783 0,5 2,5569 2,7680 2,8274 2,8274 0,6 3,1183 3,4176 3,5201 3,5202 0,7 3,8139 4,2257 4,3927 4,3928 0,8 4,6747 5,2288 5.4894 5,4895 0,9 5,7376 6,4704 6,8643 6,8645 1,0 7,0472 8,0032 8,5834 8,5836
Методи Рунге−−−−Кутта для системи диференціальних
рівнянь. Кожну з формул Рунге−Кутта можна використати для розв’язання системи диференціальних рівнянь першого порядку. А, отже, також для розв’язання диференціальних рівнянь більш високих порядків, оскільки відомо, що будь-яке диференціальне рівняння n-го порядку можна звести до системи із n диференціальних рівнянь першого порядку. Наприклад, диференціальне рівняння другого порядку
2
2, ,
d y dyg x y
dxdx
=
(5.14)
замінами 2 2,z dy dx dz dx d y dx= = можна звести до системи із двох рівнянь першого порядку:
128
( , , ), ( , , )dz dy
g x y z f x y zdx dx
= = , (5.15)
де ( , , )f x y z z≡ . Задача Коші в цьому випадку містить дві початкові умови
0 0 0 0( ) , ( )y x y z x z= = . (5.16)
Формули Рунге−Кутта для випадку системи із двох рівнянь мають вигляд
1 1,n n n ny y K z z L+ += + = + , (5.17) де
1 2 3 4 1 2 3 42 2 2 2,
6 6
K K K K L L L LK L
+ + + + + += = , (5.18)
Тут
1 1
2 1 1
2 1 1
3 2 2
3 2 2
4 3 3
4 3 3
( , , ), ( , , ),
( 2, 2, 2),
( 2, 2, 2),
( 2, 2, 2),
( 2, 2, 2),
( , , ),
( , , ).
n n n n n n
n n n
n n n
n n n
n n n
n n n
n n n
K h f x y z L h g x y z
K h f x h y K z L
L h g x h y K z L
K h f x h y K z L
L h g x h y K z L
K h f x h y K z L
L h g x h y K z L
= ⋅ = ⋅= ⋅ + + += ⋅ + + += ⋅ + + += ⋅ + + += ⋅ + + += ⋅ + + +
(5.19)
Загальна характеристика однокрокових методів. Усім
однокроковим методам властиві певні загальні риси: 1. Щоб одержати інформацію в новій точці, треба мати дані лише в одній попередній точці, що дозволяє легко змінювати величину кроку h.
2. В основі всіх однокрокових методів k-го порядку точності лежить розвинення функції в ряд Тейлора, у якому зберігаються члени, що містять h у ступені до k включно. Похибка на кроці інтегрування тут має порядок k+1.
3. Усі однокрокові методи не вимагають реального обчислення похідних — обчислюється лише сама функція, однак можуть знадобитися її значення в декількох проміжних точках. Останнє, звичайно, приводить до додаткових витрати часу і зусиль.
129
Розглянемо спочатку приклад використання класичного методу Рунге−Кутта для розв’язання задачі Коші
0.25 (1 / 20), (0) 1y y y y′ = − = . (5.20) Код програми:
program main_ODE_11 use ODE_sp_n_dp !------------------------------------------------------------------------------- ! Integrate a System of Ordinary Differential Equations By the ! Runge-Kutta-Fehlberg method (simple or double precision) ! ------------------------------------------------------------------------------ ! Solve a scalar equation: ! Y' = 0.25 * Y * ( 1 - Y / 20 ), Y(0)=1; ! ------------------------------------------------------------------------------ implicit none integer, parameter :: neqn = 1 integer :: iflag = 1, n_step = 5, i_step integer :: iwork(5) real :: abserr=0.00001, relerr=0.00001 real :: t_out=0.0, t_start=0.0, t_stop=20.0 real :: t, y_exact_01 real y(neqn), work(6*neqn+3) external f_01 !-----------------------------------begin-------------------------------------- open(2,file='ODE_rez.txt') write ( *, '(a)') ' ' write ( *, '(a)' ) ' Solve a scalar equation:' write ( *, '(a)' ) ' Y'' = 0.25 * Y * ( 1 - Y / 20 )' write ( *, '(a)') ' ' write ( 2, '(a)') ' ' write ( 2, '(a)' ) ' Solve a scalar equation:' write ( 2, '(a)' ) ' Y'' = 0.25 * Y * ( 1 - Y / 20 )' write ( 2, '(a)') ' ' y(1) = 1.0E+00 write ( *, '(a)' ) ' T Y Y_Exact Error' write ( *, '(a)' ) ' '
1 Модуль ODE_sp_n_dp знаходиться в Додатку.
130
write ( *, '(4g14.6)' ) t_out, y(1), y_exact_01(t_out), & y(1) - y_exact_01(t_out) write ( 2, '(a)' ) ' T Y Y_Exact Error' write ( 2, '(a)' ) ' ' write ( 2, '(4g14.6)' ) t_out, y(1), y_exact_01(t_out), & y(1) - y_exact_01(t_out) do i_step = 1, n_step t = ( ( n_step - i_step + 1 ) * t_start & + ( i_step - 1 ) * t_stop ) / real ( n_step ) t_out = ( ( n_step - i_step ) * t_start & + ( i_step ) * t_stop ) / real ( n_step ) call rkf45 ( f_01, neqn, y, t, t_out, relerr, abserr, & iflag, work, iwork ) write ( *, '(4g14.6)' ) t_out, y(1), y_exact_01(t_out), & y(1) - y_exact_01(t_out) write ( 2, '(4g14.6)' ) t_out, y(1), y_exact_01(t_out), & y(1) - y_exact_01(t_out) end do stop end program main_ODE_1 !-------------------------------------------------------------------- subroutine f_01 ( t, y, yp ) ! F_01 evaluates the derivative for the ODE. implicit none real :: t, y(1), yp(1) yp(1) = 0.25E+00 * y(1) * ( 1.0E+00 - y(1) / 20.0E+00 ) return end subroutine f_01 !-------------------------------------------------------------------- function y_exact_01 ( t ) ! Y_EXACT_01 evaluates the exact solution of the ODE. implicit none real :: t, y_exact_01 y_exact_01 = 20.0E+00 / ( 1.0E+00 + 19.0E+00 * & exp ( -0.25E+00 * t ) ) return end function y_exact_01
131
Результат: Solve a scalar equation: Y' = 0.25 * Y * ( 1 - Y / 20 ) T Y Y_Exact Error 0.00000 1.00000 1.00000 0.00000 4.00000 2.50322 2.50322 -0.452995E-05 8.00000 5.60008 5.60009 -0.104904E-04 12.0000 10.2777 10.2777 -0.114441E-04 16.0000 14.8368 14.8368 -0.858307E-05 20.0000 17.7302 17.7302 0.00000 Розглянемо тепер приклад використання класичного
методу Рунге−Кутта для розв’язання задачі Коші для рівняння п’ятого порядку:
V 2 IV 39 ( ) 45 40 ( )y y y y y y′′ ′′ ′′′ ′′′⋅ = ⋅ − ⋅ (5.21) при початкових умовах
IV(1) 1, (1) 1, (1) 1, (1) 1, (1) 1y y y y y′ ′′ ′′′= = = = = . (5.22) Рівняння (5.21) зводиться до системи рівнянь першого
порядку замінами IV
1 2 3 4 5, , , ,y y y y y y y y y y′ ′′ ′′′→ → → → → . (5.23) В результаті маємо задачу Коші для системи рівнянь
першого порядку
1 2
2 3
3 4
4 5
3 25 3 4 5 4 3
,
,
,
,
(45 40 ) (9 )
y y
y y
y y
y y
y y y y y y
′ =′ =′ =′ =
′ = −
(5.24)
при початкових умовах
1 2 3 4 5(0) (0) (0) (0) (0) 1y y y y y= = = = = . (5.25)
Тепер ми можемо використати метод Рунге−Кутта. Код програми:
132
program main_ODE_2 use ODE_sp_n_dp ! Integrate a System of Ordinary Differential Equations By the ! Runge-Kutta-Fehlberg method (simple or double precision) implicit none integer, parameter :: neqn = 5 integer :: iflag = 1, n_step = 12, i_step integer :: iwork(5) real :: abserr=0.000001, relerr=0.000001 real :: t_out=0.0, t_start=0.0, t_stop=1.5 real :: t !, y_exact_01 real :: y(neqn), work(6*neqn+3) external f_05 !------------------------------------------begin----------------------------------- open (2,file='ODE_2_rez.txt') ! write ( *, '(a)' ) ' Solve a vector equation in simple precision:' write ( *, '(a)') ' ' write ( *, '(a)' ) ' Y''(1) = Y(2)' write ( *, '(a)' ) ' Y''(2) = Y(3)' write ( *, '(a)' ) ' Y''(3) = Y(4)' write ( *, '(a)' ) ' Y''(4) = Y(5)' write ( *, '(a)' ) ' Y''(5) = 45 * y((3) * Y(4) * Y(5) - 40 * & Y(4)**3 / (9 * Y(3)**2)' write ( *, '(a)') ' ' write ( 2, '(a)' ) ' Solve a vector equation in simple precision:' write ( 2, '(a)') ' ' write ( 2, '(a)' ) ' Y''(1) = Y(2)' write ( 2, '(a)' ) ' Y''(2) = Y(3)' write ( 2, '(a)' ) ' Y''(3) = Y(4)' write ( 2, '(a)' ) ' Y''(4) = Y(5)' write ( 2, '(a)' ) ' Y''(5) = 45 * y((3) * Y(4) * Y(5) - 40 * & Y(4)**3 / (9 * Y(3)**2)' write ( 2, '(a)') ' ' y(1) = 1.0E+00; y(2) = 1.0E+00; y(3) = 1.0E+00 y(4) = 1.0E+00; y(5) = 1.0E+00 write ( *, '(a)' ) ' T Y1 Y2 Y3 Y4 Y5'
133
write ( *, '(6g13.6)' ) t_out, y(1), y(2), y(3), y(4), y(5) write ( 2, '(a)' ) ' T Y1 Y2 Y3 Y4 Y5' write ( 2, '(6g13.6)' ) t_out, y(1), y(2), y(3), y(4), y(5) do i_step = 1, n_step t = ( ( n_step - i_step + 1 ) * t_start & + ( i_step - 1 ) * t_stop ) / dble ( n_step ) t_out = ( ( n_step - i_step ) * t_start & + ( i_step ) * t_stop ) / dble ( n_step ) ! call rkf45 ( f_05, neqn, y, t, t_out, relerr, abserr, iflag, work, iwork ) ! write ( *, '(6g13.6)' ) t_out, y(1), y(2), y(3), y(4), y(5) write ( 2, '(6g13.6)' ) t_out, y(1), y(2), y(3), y(4), y(5) end do stop end program main_ODE_2 !------------------------------------------------------------------------------------- subroutine f_05 ( t, y, yp ) ! F_05 evaluates the derivative for the ODE. implicit none real :: t, y(5), yp(5) yp(1) = y(2) yp(2) = y(3) yp(3) = y(4) yp(4) = y(5) yp(5) = (45 * y(3) * y(4) * y(5) - 40 * y(4)**3) / (9 * Y(3)**2) return end subroutine f_05 Результат: Solve a vector equation in simple precision: Y'(1) = Y(2) Y'(2) = Y(3) Y'(3) = Y(4) Y'(4) = Y(5) Y'(5) = (45 * y(3) * Y(4) * Y(5) - 40 * Y(4)**3) / (9 * Y(3)**2)
134
T Y1 Y2 Y3 Y4 Y5 0.00000 1.00000 1.00000 1.00000 1.00000 1.00000 0.125000 1.13315 1.13314 1.13297 1.12870 1.05319 0.250000 1.28402 1.28393 1.28234 1.26132 1.05868 0.375000 1.45495 1.45442 1.44815 1.39023 0.988608 0.500000 1.64853 1.64661 1.62927 1.50394 0.809818 0.625000 1.86758 1.86226 1.82286 1.58674 0.488590 0.750000 2.11513 2.10263 2.02386 1.61909 0.247942E-05 0.875000 2.39429 2.36822 2.22464 1.57962 -0.658017 1.00000 2.70820 2.65836 2.41495 1.44897 -1.44897 1.12500 3.05982 2.97101 2.58257 1.21533 -2.28767 1.25000 3.45174 3.30252 2.71454 0.880394 -3.04568 1.37500 3.88602 3.64767 2.79922 0.463320 -3.57874 1.50000 4.36396 4.00000 2.82843 0.144173E-05 -3.77124 5.3. Методи прогнозу і корекції Методи прогнозу і корекції для обчислення положення
нової точки використовують інформацію про декілька раніше отриманих точок. Для цього застосовуються дві формули, що їх називають, відповідно, формулами прогнозу і корекції. Схеми алгоритмів для всіх методів прогнозу і корекції майже однакові, а самі методи відрізняються лише формулами. Будемо розглядати розв’язання методами прогнозу і корекції диференціальне рівняння
( , )y f x y′ = . (5.26) Оскільки в методах прогнозу і корекції використовується
інформація про декілька раніше отриманих точок, то на відміну від однокрокових методів вони не можуть “стартувати” самостійно. Тому, перш ніж застосовувати метод прогнозу і корекції, доводиться обчислювати перші декілька кроків за допомогою будь-якого однокрокового методу. Найчастіше для цього використовують метод Рунге−Кутта. Обчислення виконують за наступним алгоритмом. Спочатку по формулі прогнозу і вихідним значенням змінних визначають значення
(0)1ny + . Верхній індекс (0) означає, що прогнозоване значення є
135
одним з послідовності значень 1ny + , які розташовуються в
порядку зростання точності. За прогнозованим значенням (0)1ny + ,
з використанням (5.26) знаходять похідну (0) (0)11 1( ) ( , )nn ny f x y++ +′ =
яка потім підставляється у формулу корекції для обчислення
уточненого значення ( 1)1
jny +
+ . У свою чергу ( 1)
1j
ny ++
використовується для одержання більш точного значення похідної із диференціального рівняння
( 1) ( 1)11 1( ) ( , )j j
nn ny f x y+ +++ +′ = . (5.27)
Якщо це значення похідної недостатньо близьке до попереднього, то воно підставляється у формулу корекції і ітераційний процес триває. Якщо ж похідна змінюється в
припустимих межах, то значення ( 1)1( )j
ny ++ ′ використовується
для обчислення остаточного значення 1ny + , яке і видається на друк. Після цього процес повторюється на наступному кроці. Звичайно при виводі формул прогнозу і корекції
розв’язання рівняння розглядають як процес наближеного інтегрування, а самі формули одержують з використанням скінченно-різницевих методів. Так, якщо диференціальне рівняння (5.26) проінтегроване в інтервалі значень від nx до
n kx + , результат має вигляд
( ) ( ) ( , )n k
n
x
n k nx
y x y x f x y dx+
+ − = ∫ . (5.28)
Цей інтеграл не можна обчислити безпосередньо, бо залежність ( )y x заздалегідь невідома. Наближене значення інтеграла можна знайти з використанням одного з скінченно-різницевих методів. Вибір методу тут і буде визначати метод розв’язання диференціального рівняння (5.26). На етапі прогнозу можна скористатися будь-якою формулою числового інтегрування, якщо до неї не входить попереднє значення 1( )ny x +′ .
136
Метод Мілна. При програмуванні цього метода на етапі прогнозу використовується формула Мілна [23]
5 V1 3 1 2
4 28(2 2 )
3 90n n n n ny y h y y y h y+ − − −′ ′ ′= + − + + , (5.29)
а на етапі корекції — формула Симпсона
5 V1 1 1 1
1 1(2 4 )
3 90n n n n ny y h y y y h y+ − + −′ ′ ′= + + + − . (5.30)
Останні члени в обох формулах в дійсності в ітераційному процесі не використовуються і потрібні лише для оцінки похибки усікання. Метод Мілна відносять до методів четвертого порядку точності, бо в ньому відкидаються члени, що містять h у п’ятій та більш високих ступенях. Може виникнути питання, навіщо взагалі потрібна корекція, якщо прогноз має четвертий порядок точності. Відповідь на нього дає оцінка відносної величини членів похибки для кроків прогнозу і корекції. Очевидно, що похибка усікання при корекції в 28 раз менша і тому крок корекції набагато точніший кроку прогнозу. Взагалі ітераційні формули набагато точніші, ніж формули прогнозу, і тому їх використання виправдане, хоча і пов’язане з додатковими труднощами.
Зауваження. Незважаючи на те що формула Мілна містить найменший числовий коефіцієнт (1/90) перед залишковим членом, порівняно з іншими розглянутими далі методами, її використовують рідше, бо їй властива нестійкість. Це означає, що похибка поширення має тенденцію до експоненційного зростання, причому цей висновок слушний для всіх формул корекції, що засновані на формулах Симпсона.
Метод Адамса−−−−Башфорта. Цей метод також має четвертий порядок точності [23]. Формула прогнозу тут отримана інтегруванням зворотної інтерполяційної формули Ньютона і має вигляд
5 V1 1 2 3
1 251(55 59 37 9 )
24 720n n n n n ny y h y y y y h y+ − − −′ ′ ′ ′= + − + − +
(5.31)
137
На етапі корекції використовується наступна формула
5 V1 1 1 2
1 19(9 19 5 )
24 720n n n n n ny y h y y y y h y+ + − −′ ′ ′ ′= + − − + + (5.32)
Зауваження. Розрахунки за методом Адамса−Башфорта
виконуються за алгоритмом, подібним методу Мілна, однак на відміну від останнього, похибка, внесена на будь-якому кроці, не має тенденції до експоненційного зростання. Можна припустити, що оскільки величина залишкового
члена відома, то її можна використати для уточнення скорегованого значення залежної змінної. Однак, як правильно відзначається в монографії [23], це було б рівноцінно використанню системи більш високого порядку точності. Оскільки внесення виправлень у коригувальний член може негативно позначитися на стійкості розрахунку, то для підвищення точності розрахунку слід використовувати методи більш високих порядків точності.
Метод Хеммінга. Алгоритм цього метода включає наступні формули прогнозу:
(0)3 1 21
4(2 2 )
3n n n nny y h y y y− − −+ ′ ′ ′= + − + , (5.33)
уточнення прогнозу: (0) (0) (0)
1 1
(0) (0)11 1
112( ),
121
[ ] ( , )
n nn n
nn n
y y y y
y f x y
+ +
++ +
= + −
′ = (5.34)
та корекції:
( 1) (0)2 11 1
1 3(9 ) ([ ] 2 )
8 8j
n n n nn ny y y h y y y+− −+ + ′ ′ ′= − + + − (5.35)
Метод Хеммінга являється стійким методом четвертого порядку точності. Алгоритм його базується на наступних формулах прогнозу:
5 V1 3 1 2
4 28(2 2 )
3 90n n n n ny y h y y y h y+ − − −′ ′ ′= + − + + (5.36)
138
і корекції
5 V1 2 1 1
1 1[9 3 ( 2 )]
8 40n n n n n ny y y h y y y h y+ − + −′ ′ ′= − + + − − . (5.37)
Важлива особливість методу Хеммінга полягає в тому, що він дозволяє оцінити похибки, внесені на стадіях прогнозу і корекції та усувати їх. Завдяки простоті і стійкості цей метод є одним з найпоширеніших методів прогнозу і корекції.
Коротка характеристика методів прогнозу і корекції: У порівнянні з однокроковими методами методи
прогнозу і корекції мають низку особливостей:
• Для реалізації методів прогнозу і корекції необхідно мати інформацію про декілька попередніх кроків, причому для “старту” цих методів доводиться прибігати до будь-якого однокрокового методу. Тому, якщо в процесі розв’язання диференціальних рівнянь методом прогнозу і корекції необхідно змінити крок, то після цього знову доводиться тимчасово переходити на однокроковий метод.
• Оскільки для методів прогнозу і корекції потрібні дані про попередні кроки, то, відповідно, пред’являються і підвищені вимоги до об’єму пам’яті комп’ютера.
• І однокрокові методи, і методи прогнозу та корекції забезпечують приблизно однакову точність результатів. Однак другі, на відміну від перших дозволяють легко оцінити похибку на кроці інтегрування. Із цієї причини, користуючись однокроковими методами, величину кроку h звичайно вибирають трохи меншою, ніж це необхідно, і тому методи прогнозу і корекції виявляються більш ефективними.
• При програмуванні методу Рунге−Кутта четвертого порядку точності на кожному кроці доводиться обчислювати чотири значення функції, у той час як для забезпечення збіжності методу прогнозу і корекції однакового порядку точності, часто достатньо двох значень
139
функції. В результаті методи прогнозу і корекції вимагають майже вдвічі менше витрат комп’ютерного часу, ніж методи Рунге−Кутта порівнянної точності. Остання обставина може впливати на вибір алгоритму, бо вартість комп’ютерного часу може бути досить високою.
5.4. Вибір кроку інтегрування
Одним з важливих практичних питань, які встають перед
програмістом, який програмує розв’язання диференціальних рівнянь, є вибір підходящої величини кроку інтегрування. Якщо крок занадто малий, то розрахунок буде вимагати невиправдано багато комп’ютерного часу, а число похибок на окремих кроках, що складаються в сумарну похибку, буде досить велике. Якщо ж, навпаки, крок обраний занадто великим, то значною буде локальна похибка, що обумовлена усіканням рядів. А, отже, сумарна похибка розрахунку буде також неприпустимо великою. Вибираючи величину кроку інтегрування, звичайно
прагнуть, щоб локальна помилка на кроці була менше деякої заданої припустимої величини. Загалом кажучи, якщо порядок точності методу n, то локальна помилка визначається виразом
1nCh + , де C — деяка константа, а h — крок інтегрування. Якщо використовується один з методів прогнозу і корекції, то помилка на кроці інтегрування, як правило, визначається величиною останнього члена у формулі корекції. При використанні ж методу Рунге−Кутта локальну помилку не вдається представити в настільки явній формі. Один зі способів оцінки цієї помилки засновано на правилі Рунге і екстраполяції Річардсона [5]. Якщо для обчислення значення невідомої функції 1jy + в
точці 1jx + скористалися кроком h, то різниця між реальним і
обчисленим значеннями функції дорівнює: 1
1n
icm jy y Ch ++− = . (5.38)
Якщо зменшити крок удвічі і обчислити *1jy + в точці 1jx + , то
140
в результаті маємо 1
*1 2
n
icm jh
y y C+
+ − =
. (5.39)
Віднімаючи (5.39) від (5.38), знайдемо * 1 1
1 1 (1 0,5 )n nj jy y Ch + ++ +− = − (5.40)
Звідки можна знайти локальну похибку 1 *
1 111
2 ( )
2 1
nj jn
n
y yCh
++ +++
−=
− (5.41)
Остання формула і носить назву правила Рунге практичного оцінювання похибки апроксимації [5]. Недоліком використання правила Рунге для практичного
оцінювання похибки апроксимації є необхідність обчислювати двічі значення 1jy + . А, оскільки, для того щоб
обчислити *1jy + в точці 1jx + ще доводиться робити два
кроки, кожний з яких дорівнює половині вихідного, об’єм обчислень збільшується більш ніж удвічі. Проте, ця процедура часто включається в алгоритм методу Рунге−Кутта для автоматичної зміни кроку в процесі обчислень. Якщо ж помилка на кроці при даній його величині занадто велика, то її можна зменшити тільки, якщо скористатися при обчисленнях членом більш високого порядку. Що, звичайно, простіше зробити у випадку методів прогнозу і корекції. Головні переваги методів Рунге−Кутта — простота
початку розрахунку і можливість швидкої зміни величини кроку в процесі обчислень. З іншого боку, головною перевагою методів прогнозу і корекції є простота оцінки помилки на кроці інтегрування. Раніше вважалося, що ці переваги не можна об’єднати в одному алгоритмі. Однак зараз є високоефективні алгоритми, які дозволяють використати переваги обох груп обчислювальних методів. Такі гібридні методи можуть бути досить корисні при розв’язанні практичних задач. Як приклад можна згадати метод Гіра [3], який забезпечує автоматичне керування як
141
величиною кроку, так і числом членів у формулах прогнозу і корекції. 5.5. “Жорсткі” задачі Деякі звичайні диференціальні рівняння не
розв’язуються жодним з розглянутих вище методів. Щоб добре зрозуміти, чому це так, необхідно чітко представляти структуру розв’язку диференціального рівняння. Основний масштаб часу для диференціального рівняння першого порядку — це проміжок часу, після закінчення якого величина нестаціонарної частини розв’язку убуває в e-1 разів. У загальному випадку диференціальне рівняння n-порядку має n масштабів часу. Якщо будь-які два з них дуже відрізняються по величині або якщо один з масштабів часу досить малий у порівнянні з інтервалом часу, на якому шукається розв’язок, то задача називається “жорсткою” і її практично неможливо розв’язати звичайними методами. У таких випадках крок повинен бути дуже малим, щоб можна було враховувати зміну членів рівняння, які змінюються найшвидше, навіть після того, коли їх внесок стане практично непомітним. Якщо при цьому не вдається зберегти величину кроку достатньо малою, то розв’язок стає нестійким. Хоча труднощі, пов’язані із забезпеченням стійкості розв’язків “жорстких” задач звичайними методами, можна тимчасово обійти, зменшивши величину кроку, такий підхід має два суттєві недоліки. По-перше, якщо величина кроку дуже мала в порівнянні з інтервалом, для якого шукається розв’язок, то для одержання розв’язку буде потрібно дуже багато часу. По-друге, накопичені в процесі тривалих обчислень похибки округлення і усікання можуть привести до безглуздого результату. Оскільки з “жорсткими” задачами ми найчастіше
зустрічаємося при розв’язанні важливих задач керування, при розрахунках електричних мереж, хімічних реакцій та ін., останнім часом багато уваги приділяється розробці ефективних методів розв’язання саме таких задач.
142
Обговорення цих методів виходить за рамки даного посібника і зацікавленим читачам рекомендується самостійно ознайомитися з вже згадуваним методом Гіра [3]. 5.6. Методи розв’язання крайових задач
Як вже відзначалося вище, задача розв’язання звичайного
диференціального рівняння при додаткових умовах, поставлених при декількох значеннях незалежної змінної, називається крайовою. Для спрощення розглянемо звичайне диференціальне
рівняння другого порядку 2
2( , , )
d yf x y y
dx′= (5.42)
при крайових умовах ( ) , ( )y a A y b B= = . (5.43) Рівняння більш високих порядків можна розв’язувати
тими ж самими методами, які розіб’ємо на наступні дві групи:
• Методи, що засновані на заміні розв’язання крайової задачі розв’язання декількох задач Коші.
• Методи, які використовують скінченно-різницеву форму диференціального рівняння.
Методи “ стрільби”. Якщо звичайне диференціальне
рівняння другого порядку є лінійним, тобто має вигляд 1 2 3( ) ( ) ( )y f x y f x y f x′′ ′= + + (5.44)
при крайових умовах (5.43), то крайову задачу можна звести до задачі Коші з початковими умовами
1( ) , ( ) αy a A y a′= = . (5.45)
Знайшовши розв’язок 1( )y x , можна поставити інші крайові умови
2( ) , ( ) αy a A y a′= = (5.46)
і одержати другий розв’язок 2( )y x . Якщо 1 1( ) βy b = , а
143
2 2( ) βy b = , причому 1 2β β≠ то розв’язок
2 1 1 21 2
1( ) [( β ) ( ) (β ) ( )]
β βy x B y x B y x= − + −
− (5.47)
задовольняє обом крайовим умовам. Якщо розв’язується нелінійне ЗДР, то розв’язок крайової
задачі можна спробувати звести до розв’язання кількох задач Коші, послідовно вводячи в початкові умови значення α:
( ) , ( ) αy a A y a′= = (5.48) і намагаючись знайти розв’язок, який задовольняє умові
( )y b B= . Використання при цьому інтерполяції дозволяє побудувати впорядковану послідовність наближених розв’язків і звести до мінімуму об’єм обчислень. На жаль, цей метод малоефективний, і ми не можемо його рекомендувати для заміни більш досконалих методів “стрільби”, які описані у літературі [3].
Скінченно-різницеві методи. Перевага скінченно-різницевих методів у тому, що вони дозволяють звести розв’язання крайової задачі до розв’язання системи алгебраїчних рівнянь. При розв’язанні двухточкової крайової задачі (5.42)-(5.43) відрізок [ , ]a b можна розділити на n рівних частин:
0 , 1,2, ,ix x ih i n= + = … , (5.49)
де 0 , , ( )nx a x b h b a n= = = − . У точках ix , які називають
вузлами, необхідно отримати значення розв’язку iy . Знаючи координати вузлів і користуючись скінченно-різницевими представленнями для похідних
1 1( )2
i ii
y yy x
h+ −−′ = , 1 12
( )2
i i ii
y y yy x
h+ −− +′′ = (5.50)
можна представити диференціальне рівняння (5.42) у вигляді скінченно-різницевого рівняння.
Зауваження. Існують різні форми скінченно-різницевих представлень для похідних. Питання про представлення
144
похідних у вигляді скінченно-різницевих виразів докладніше можна ознайомитися в монографіях [13, 22]. Розв’язання отриманого скінченно-різницевого рівняння
при 1,2, ,i n= … , з врахуванням крайових умов (5.43), зводиться до розв’язання системи n-1 алгебраїчних рівнянь із n-1 невідомими iy . При цьому, якщо вихідне диференціальне рівняння лінійне, то отримана система рівнянь також буде лінійною. Тобто розв’язання вихідної задачі зводиться до розв’язання системи лінійних алгебраїчних рівнянь. Якщо ж вихідне диференціальне рівняння нелінійне, то отримана система рівнянь також буде нелінійною і вихідна задача зводиться до розв’язання системи нелінійних алгебраїчних або трансцендентних рівнянь. Розглянемо приклад розв’язання крайової задачі (5.42)-(5.43)
скінченно-різницевим методом. Нехай потрібно розв’язати диференціальне рівняння
2 3y x y′′ = + (5.51)
при крайових умовах (0) 0, (1) 1y y= = з кроком h = 0,2. У різницевій формі це рівняння має вигляд:
1 11
( 2 ) 2 3 , 0,50,04 i i i i iy y y x y i+ −− + = + = . (5.52)
Крайові умови при цьому мають вигляд:
0 50, 1y y= = . (5.53) Підставляючи (5.53) в (5.52), можна виписати наступну
систему чотирьох рівнянь із чотирма невідомими1:
1 2 3 4
1 2 3 4
2,12 0 0 0,016;
2,12 0 0,032;
y y y y
y y y y
− + + + =− + + =
1 2 3 4
1 2 3 4
0 2,12 0,064;
0 0 2,12 0,936.
y y y y
y y y y
+ − + = −+ + − = −
(5.54)
У наведеній нижче таблиці розв’язок системи (5.54)
1 У загальному випадку отримана тридіагональна система рівнянь розв’язується методом прогонки Томаса (див. розділ 2.1).
145
порівнюється з точним розв’язком:
5 sh 3 2( )
3 3sh 3
xy x = − . (5.55)
Таблиця 2.3. Порівняння точного розв’язку крайової задачі з її наближеним розв’язком скінченно-різницевим методом
y(x) x Наближений розв’язок Точний розв’язок
0,0 0,0 0,0 0,2 0,0827 0,0818 0,4 0,1912 0,1897 0,6 0,3548 0,3529 0,8 0,6088 0,6073 1,0 1,0000 1,0000
5.7. Вибір алгоритму розв’язання звичайних диференціальних
рівнянь
Сформулювати загальні правила вибору найкращого
методу розв’язання того або іншого ЗДР звичайно неможливо. Однак можна рекомендувати керуватися при цьому наступними міркуваннями:
• Розгляд типу задачі. Якщо це задача Коші, то для її розв’язання можна скористатися однією з наведених в посібнику підпрограм. Якщо ж це крайова задача, то, можливо, прийдеться складати власну програму.
• Оцінка ступеня складності диференціального рівняння. Якщо задача Коші достатньо складна і обчислення правої частини рівняння ( , )f x y пов’язане з великими труднощами, то звичайно перевагу віддають одному з методів прогнозу і корекції, бо вони вимагають обчислення лише двох значень ( , )f x y на кроці замість чотирьох, як у
методах Рунге−Кутта. Якщо ж обчислення ( , )f x y не викликає труднощів, то більш зручним часто виявляється саме один з методів Рунге−Кутта.
146
• Оцінка часу, необхідного для розв’язання задачі. Якщо в першу чергу доводиться враховувати вартість комп’ютерного часу, то кращим буде метод прогнозу і корекції. Якщо ж визначальним є час підготовки задачі до розрахунку, то слід скористатися методом Рунге−Кутта.
• Оцінка необхідної точності розв’язку. Взагалі, вважається, що чим вище порядок точності методу, тим більше точним буде отриманий результат. Але це твердження слушне лише певною мірою, бо скінченно-різницеві аналоги похідних у міру підвищення порядку апроксимації поводять себе усе гірше і гірше. Тому похибка методу при переході від п’ятого порядку до більш високих порядків точності (до того ж це пов’язано з додатковими громіздкими обчисленнями) практично не убуває. Оскільки звичайно досягається деякий компроміс між об’ємом і точністю обчислень, то слід приділяти увагу як вибору порядку точності методу, так і вибору величини кроку. Як наслідок сказаному вище, велике поширення одержали алгоритми або з автоматичною зміною кроку інтегрування, або з автоматичною зміною порядку точності застосовуваного методу.
• Облік наявного досвіду. Попередні успіхи або невдачі в застосуванні того або іншого алгоритму для розв’язання конкретної задачі можуть надати вагомий матеріал для судження про доцільність вибору тої або іншої програми. Це особливо важливо у випадку “жорстких” систем диференціальних рівнянь, бо, як правило, у цьому випадку невідомо зарані, чи є система “жорсткою”, доти, поки користувач не переконається на практиці в неефективній роботі алгоритму.
5.8. Запитання та вправи 1) Які Ви знаєте однокрокові методи розв’язання ЗДР та їх систем?
2) Наведіть алгоритми методу Ейлера та модифікованого
147
методу Ейлера. У чому полягає модифікація методу Ейлера?
3) Що Вам відомо про методи Рунге−Кутта розв’язання ЗДР та їх систем?
4) Наведіть алгоритми методу Рунге−Кутта четвертого порядку точності для розв’язання ЗДР та їх систем.
5) Які Ви знаєте методи прогнозу і корекції розв’язання ЗДР та їх систем?
6) Наведіть алгоритм методу Адамса розв’язання ЗДР? 7) Які Ви знаєте стандартні процедури бібліотеки IMSL, що призначені для розв’язання ЗДР та їх систем?
8) У чому особливості розв’язання “жорстких” ЗДР та їх систем?
9) На чому заснована процедура автоматичного вибору кроку інтегрування для методів Рунге−Кутта?
10*) Методом Адамса зі змінним кроком розв’язати задачу Коші на відрізку [0,-4] для системи рівнянь
2
3
2 4 1,
2 ( ) ,
x
x
y y y ze
z z y x e
− ′′ ′= + − −
′′ ′= + − (5.56)
при початкових значеннях (0) 1, (0) 1, (0) 0, (0) 0.5y y z z′ ′= = = = . (5.57) Результат порівняти із точним розв’язком
2, 0.5x xy x e z x e= + = ⋅ . (5.58) 11*) Розв’язати задачу Коші на відрізку [0,10] для системи
рівнянь
41 1 2 3
2 1 3
73 2
0.04 10 ,
,
3 10 ,
y y y y
y y y
y y
′ = − +
′ ′ ′= − − ′ ′= ×
(5.59)
при початкових значеннях 1 2 3(0) 1, (0) 0, (0) 0y y y= = = . (5.60)
12*) Розв’язати крайову задачу на відрізку [0, π] 2 2 cos ;
(0) (0) 1, ( ) 0.
y xy y x x
y y y π′′ ′+ + =
′+ = = (5.61)
148
13*) Розв’язати крайову задачу на відрізку [0, π] 3 2(1 sin )sin 0;
(0) ( ) 0.
y y t t
y y π′′ − + + =
= = (5.62)
5.9 Практичні завдання
Завдання 7. Числові методи розв’язання звичайних
диференційних рівнянь. Мета завдання:
1. Ознайомлення з числовими методами розв’язання задачі Коші. 2. Ознайомлення з числовими методами розв’язання крайової задачі.
3. Ознайомлення з процедурами числового розв’язання звичайних диференційних рівнянь із бібліотеки IMSL: метод Рунге−Кутта, скінченно-різницевий метод. Постановка завдання: Числове розв’язання задачі Коші методом Рунге−Кутта.
Числове розв’язання крайової задачі скінченно-різницевим методом. Числове розв’язання задачі Коші і крайової задачі із використанням стандартних методів із бібліотеки IMSL. Порівняти результати. Методичні вказівки: При підготовці до виконання роботи спочатку потрібно
познайомитися з методами розв’язання задачі Коші й крайової задачі. Всі нижченаведені кроки лабораторної роботи, а також опис алгоритму методів, потрібно відобразити у звіті. Програмування задач виконати за наступною схемою: 1. Виконати числове розв’язання задачі Коші методом Рунге−Кутта.
2. Виконати числове розв’язання крайової задачі скінченно-різницевим методом з точністю ε=10-3 і кроком h=0,05. Отриману тридіагональну СЛАР розв’язати методом прогонки Томаса (див. розділ 2.1).
149
3. Повторити завдання з п.п. 1 та 2, скориставшись стандартними процедурами IVMRK (Рунге−Кутта) та BVPFD (скінченно-різницевий метод) із бібліотеки IMSL.
4. Порівняти отримані результати. Варіанти завдання:
№ вар
Задача Коші Крайова задача
1
0
cos ,5
(1,8) 2,6; [1,8;2,8]
yy x
y x
′ = +
= ∈
2 ;
(0,7) 0,5;
2 (1) 3 (1) 1,2.
yy y x
xy
y y
′′′ + + =
=′+ =
2 0
cos ,3
(1,6) 4,6; [1,6;2,6]
yy x
y x
′ = +
= ∈
2 1,
(0,9) 0,5 (0,9) 2;
(1,2) 1.
y x y y x
y y
y
′′ ′− + = +′− =
=
3
0
cos ,10
(0,6) 0,8; [0,6;1,6]
yy x
y x
′ = +
= ∈
1;
(0,5) 2 (0,5) 1;
(0,8) 1,2.
y x y y x
y y
y
′′ ′+ + = +′− =
′ =
4
0
cos ,7
(0,5) 0,6; [0,5;1,5]
yy x
y x
′ = +
= ∈
2 3;
(0,2) 2;
0,5 (0,5) (0,5) 1.
yy y
xy
y y
′′ ′+ − =
=′⋅ − =
5
0
cos ,2,25
(1,4) 2,2; [1,4;2,4]
yy x
y x
′ = +
= ∈
22 ;
(0,6) 0,7;
(0,9) 0,5 (0,9) 1.
y y xy x
y
y y
′′ ′+ − =′ =
′− =
6 0
cos ,π
(1,7) 5,3; [1,7;2,7]
yy x
y x
′ = +
= ∈
20,4;
(1,1) 0,5 (1,1) 2;
(1,4) 4.
yy y x
xy y
y
′′ ′− + = +
′− =′ =
150
№ вар
Задача Коші Крайова задача
7 0
cos ,
(1,4) 2,5; [1,4;2,4]
yy x
ey x
′ = +
= ∈
3 1;
(0,4) 2;
(0,7) 2 (0,7) 0,7.
yy y
xy
y y
′′ ′− + =
=′+ =
8 0
sin ,3
(1,6) 4,6; [1,6;2,6]
yy x
y x
′ = +
= ∈
3 1;
(1,2) 1;
2 (1,5) (1,5) 0,5.
yy y x
xy
y y
′′ ′+ − = +
′ =′− =
9 0
sin ,π
(1,7) 5,3; [1,7;2,7]
yy x
y x
′ = +
= ∈
20,5 3 2 ;
(1) 2 (1) 0,6;
(1,3) 1.
y y y x
y y
y
′′ ′− + =′+ =
=
10
0
sin ,5
(1,8) 2,6; [1,8;2,8]
yy x
y x
′ = +
= ∈
1,5 0,5;
2 (1,3) (1,3) 1;
(1,6) 3.
y y xy
y y
y
′′ ′+ − =′− =
=
11
0
sin ,10
(0,6) 0,8; [0,6;1,6]
yy x
y x
′ = +
= ∈
2 0.4;
2 (0,3) (0,3) 1;
(0,6) 2.
y x y y
y y
y
′′ ′+ − =′+ =
′ =
12
0
sin ,2,8
(1,4) 2,2; [1,4;2,4]
yy x
y x
′ = +
= ∈
0.5 2;
(0,4) 1,2;
(0,7) 2 (0,7) 1,4.
y xy y
y
y y
′′ ′− + ==
′+ =
13 0
sin ,
(1,4) 2,5; [1,4;2,4]
yy x
ey x
′ = +
= ∈
23 2;
(0,8) 1,5;
2 (1,1) (1,1) 3.
yy y
xy
y y
′′′ + − =
′ =′+ =
151
№ вар
Задача Коші Крайова задача
14
0
sin ,2
(0,8) 1,3; [0,8;1,8]
yy x
y x
′ = +
= ∈
22 ;
2 (0,5) (0,5) 1;
(0,8) 3.
y x y y x
y y
y
′′ ′+ + =′− =
=
15
0
sin ,11
(0,6) 1,2; [0,6;1,6]
yy x
y x
′ = +
= ∈
3 2 1,5;
(0,7) 1,3;
0,5 (1) (1) 2.
y xy y
y
y y
′′ ′− + =′ =
′⋅ + =
16
0
cos ,5
(1,8) 2,6; [1,8;2,8]
yy x
y x
′ = +
= ∈
3 1;
(0,4) 2;
(0,7) 2 (0,7) 0,7.
yy y
xy
y y
′′ ′− + =
=′+ =
17 0
cos ,3
(1,6) 4,6; [1,6;2,6]
yy x
y x
′ = +
= ∈
3 1;
(1,2) 1;
2 (1,5) (1,5) 0,5.
yy y x
xy
y y
′′ ′+ − = +
′ =′− =
18
0
cos ,10
(0,6) 0,8; [0,6;1,6]
yy x
y x
′ = +
= ∈
20,5 3 2 ;
(1) 2 (1) 0,6;
(1,3) 1.
y y y x
y y
y
′′ ′− + =′+ =
=
19
0
cos ,7
(0,5) 0,6; [0,5;1,5]
yy x
y x
′ = +
= ∈
1,5 0,5;
2 (1,3) (1,3) 1;
(1,6) 3.
y y xy
y y
y
′′ ′+ − =′− =
=
20
0
cos ,2,25
(1,4) 2,2; [1,4;2,4]
yy x
y x
′ = +
= ∈
2 0.4;
2 (0,3) (0,3) 1;
(0,6) 2.
y x y y
y y
y
′′ ′+ − =′+ =
′ =
152
№ вар
Задача Коші Крайова задача
21 0
cos ,π
(1,7) 5,3; [1,7;2,7]
yy x
y x
′ = +
= ∈
2 ;
(0,7) 0,5;
2 (1) 3 (1) 1,2.
yy y x
xy
y y
′′′ + + =
=′+ =
22 0
cos ,
(1,4) 2,5; [1,4;2,4]
yy x
ey x
′ = +
= ∈
2 1,
(0,9) 0,5 (0,9) 2;
(1,2) 1.
y x y y x
y y
y
′′ ′− + = +′− =
=
23 0
sin ,3
(1,6) 4,6; [1,6;2,6]
yy x
y x
′ = +
= ∈
1;
(0,5) 2 (0,5) 1;
(0,8) 1,2.
y x y y x
y y
y
′′ ′+ + = +′− =
′ =
24 0
sin ,π
(1,7) 5,3; [1,7;2,7]
yy x
y x
′ = +
= ∈
2 3;
(0,2) 2;
0,5 (0,5) (0,5) 1.
yy y
xy
y y
′′ ′+ − =
=′⋅ − =
25
0
sin ,5
(1,8) 2,6; [1,8;2,8]
yy x
y x
′ = +
= ∈
22 ;
(0,6) 0,7;
(0,9) 0,5 (0,9) 1.
y y xy x
y
y y
′′ ′+ − =′ =
′− =
26
0
sin ,10
(0,6) 0,8; [0,6;1,6]
yy x
y x
′ = +
= ∈
20,4;
(1,1) 0,5 (1,1) 2;
(1,4) 4.
yy y x
xy y
y
′′ ′− + = +
′− =′ =
27
0
sin ,2,8
(1,4) 2,2; [1,4;2,4]
yy x
y x
′ = +
= ∈
3 1;
(1,2) 1;
2 (1,5) (1,5) 0,5.
yy y x
xy
y y
′′ ′+ − = +
′ =′− =
153
№ вар
Задача Коші Крайова задача
28 0
sin ,
(1,4) 2,5; [1,4;2,4]
yy x
ey x
′ = +
= ∈
3 2 1,5;
(0,7) 1,3;
0,5 (1) (1) 2.
y xy y
y
y y
′′ ′− + =′ =
′⋅ + =
29
0
sin ,2
(0,8) 1,3; [0,8;1,8]
yy x
y x
′ = +
= ∈
3 1;
(0,4) 2;
(0,7) 2 (0,7) 0,7.
yy y
xy
y y
′′ ′− + =
=′+ =
30
0
sin ,11
(0,6) 1,2; [0,6;1,6]
yy x
y x
′ = +
= ∈
3 1;
(1,2) 1;
2 (1,5) (1,5) 0,5.
yy y x
xy
y y
′′ ′+ − = +
′ =′− =
154
Відповіді до вправ Розділ 1. 9) program polov_del
Implicit none integer,parameter :: Nmax=1000 integer N real,parameter :: eps=1.0e-7 real f,c,a,b a=0.0; b=2.0 N=0; c=(a+b)/2.0 do while (N<Nmax) if (f(a)*f(c)>0) then a=c else b=c end if N=N+1; c=(a+b)/2.0 if (abs(f(c)) <= eps) exit if (abs(a-b) <= 2.0*eps) then c = 0.5*(a+b) exit end if end do write(*,*)' Root is ',c write(*,*)' Iteration are ',N end program polov_del !------------------------------------------------------------ real function f(x) real x f = 0.5**x-1.0+(x-2.0)**2 end function f
155
10) program hords implicit none integer :: n = 0 real,parameter :: eps = 1e-03 ! Точність обчислення real x(3), f(3), xout real funx x(1) = 0.0; x(2) = 2.0 f(1) = funx(x(1)); f(2) = funx(x(2)) do x(3) = x(1) - f(1)*(x(2) - x(1))/(f(2) - f(1)) f(3) = funx(x(3)) if (f(1)*f(3)>0) then x(1)=x(3); f(1)=f(3) else x(2)=x(3); f(2)=f(3) end if n = n+1 if (abs(f(3)) <= eps) then xout = x(3) exit end if if (abs(x(1)-x(2)) <= 2.0*eps) then xout = 0.5*(x(1)+x(2)) exit end if end do write(*,*) "Zero found is ", xout write(*,*) "Iterations are ", n end program hords !------------------------------------------------------------ real function funx(x)
156
real x funx = 0.5**x-1.0+(x-2.0)**2 end function funx
11) program sekusch
implicit none real x(3), f(3), eps, xout real,parameter :: eps = 1e-07 integer :: n = 0,shift real funx, fn x(1) = 0.0; x(2) = 0.0001 f(1) = funx(x(1)); f(2) = funx(x(2)) do n = n+1 fn = (f(2) - f(1))/(x(2) - x(1)) x(3) = x(2) - f(2)/fn f(3) = funx(x(3)) if (abs(f(3)) <= eps) then xout = x(3) exit end if if (abs(x(1)-x(2)) <= 2.0*eps) then xout = 0.5*(x(1)+x(2)) exit end if x(:) = cshift(x,shift=1) f(:) = cshift(f,shift=1) end do write(*,*) "Zero found is ", xout write(*,*) "Iterations are ", n end program sekusch !------------------------------------------------------------ real function funx(x) real x funx = 0.5**x-1.0+(x-2.0)**2 end function funx
157
Розділ 2. 14) program main_qr
use solve_LAEA1 integer, parameter :: n=3,np=3 real, dimension(n,n) :: a, b(n),c(n),d(n) logical sing data a/3.,1.,1.,1.,-3.,-1.,1.,-1.,3./,b/5.,-3.,3./
!--------------begin----------------------- open(2,file='qr_solve.txt')
! QR decomposition call qrdcmp(a,n,np,c,d,sing) if ( .not. sing) then
! Solve call qrsolv(a,n,np,c,d,b)
! Print result write(*,*) ' x= ',b write(2,*) ' x= ',b else write(*,*) 'Matrix with singularity. Program stop.' write(2,*) 'Matrix with singularity. Program stop.' end if stop end program main_qr
15) program inverse use imsl implicit none
! Declare variables integer,parameter :: ipath=1, n=3, lda=n, ldfac=n integer ipvt(n), j, i real a(lda,lda),b(n,n),fac0(ldfac,ldfac),x(n,n) ! set values for a and b data a/2.60,1.00,1.60,1.00,3.10,1.60,1.60,1.60,3.60/ data b/1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0/ !----------------begin-------------------------------------------------
1 Модуль solve_LAEA знаходиться в Додатку.
158
open(2,file='inverse_imsl_rez.txt') ! LU - decomposition
call lftrg (n, a, lda, fac0, ldfac, ipvt) ! Solve for the n right-hand sides
do j=1,n call lfsrg (n, fac0, ldfac, ipvt, b(:,j), ipath, x(:,j)) end do
! Print results write(*,*) 'Ainv' write(2,*) 'Ainv' do i=1,n write(*,*) i,(X(i,j),j=1,n) write(2,*) i,(X(i,j),j=1,n) end do
! Test result B(:,:)=matmul(A,X) write(*,*) 'Test' write(2,*) 'Test' do i=1,n write(*,*) i,(B(i,j),j=1,n) write(2,*) i,(B(i,j),j=1,n) end do stop end program inverse
16) program kvasi1 ! Declare variables
use imsl implicit none integer, parameter :: n=2 integer n, k,iparam(6) real fnorm real x(n),xguess(n),xscale(n) real fscale(n),fvec(n),rparam(5) external fcn, jac
! Set values of initial guess ! xguess = ( 4.0 4.0 )
159
data xguess/4.0,4.0/,xscale/1.0,1.0/,fscale/1.0,1.0/ !-----begin---------------------------------------------------
open(2,file='kvasi1.txt') ! Find the solution
iparam(1) = 0 call neqbj (fcn,jac,n,xguess,xscale,fscale,iparam, & rparam, x, fvec)
! Print result write (*,99999) (x(k),k=1,n) write (2,99999) (x(k),k=1,n)
99999 format (' the roots found are', /, ' x = (',f5.2,',',f5.2, ')') end program kvasi1
! User-supplied subroutine subroutine fcn (n, x, f) integer n real x(n), f(n) f(1) = sin(x(1)+2)-x(2)-1.5 f(2) = x(1)+cos(x(2)-2)-0.5 return end subroutine fcn
! User-supplied subroutine to compute jacobian subroutine jac (n, x, fjac, ldfjac) integer n, ldfjac real x(n), fjac(ldfjac,*) fjac(1,1) = cos(x(1)+2) fjac(1,2) = -1 fjac(2,1) =1 fjac(2,2) = -sin(x(2)-2) return end subroutine jac
17) program kvasi2 ! Declare variables use imsl implicit none integer, parameter :: n=2 integer n,k,iparam(6)
160
real x(n),xguess(n),xscale(n), real fscale(n),fvec(n),rparam(5) external fcn ! Set values of initial guess ! xguess = ( 4.0 4.0 ) data xguess/4.0,4.0/,xscale/1.0,1.0/,fscale/1.0,1.0/ !-----begin--------------------------------------------------- open(2,file='kvasi2.txt') ! Find the solution iparam(1) = 0 call neqbf (fcn,n,xguess,xscale,fscale,iparam, & rparam,x,fvec) ! Print result write (*,99999) (x(k),k=1,n) write (2,99999) (x(k),k=1,n) 99999 format (' the roots found are', /, ' x = (',f5.2,',',f5.2, ')') end program kvasi2 ! User-supplied subroutine subroutine fcn (n, x, f) integer n real x(n), f(n) f(1) = sin(x(1)+2)-x(2)-1.5 f(2) = x(1)+cos(x(2)-2)-0.5 return end subroutine fcn Розділ 3. 10) program min_own implicit none integer,parameter :: n=3 integer iter real a(n,n), x(n), r(n), ainv(n,n) real xold, xmax, xmin data a/2.6,1.,1.6,1.,3.1,1.6,1.6,1.6,3.6/ data ainv/0.5393879,-6.5228291E-02,-0.2107376, & -6.5228306E-02,0.4264928, -0.1605620, &
161
-0.2107376,-0.1605620, 0.4427998/ data x/1.0,0.0,0.0/ !---------begin------------------------------------------ open(2,file='Min_own_number.txt') xold = 0.0; iter = 0 write (6,100) write (6,101) write (6,102) write (6,100) write (6,104) iter, x(1), x(2), x(3) !--------Main cycle------------------------------------- do iter = iter +1 r = matmul(ainv, x) x = r call norml(xmax,x) xmin = 1./xmax write(6,103) iter, xmin, x(1), x(2), x(3) if ( abs( (xold-xmax)/xmax) <= 0.001 ) exit xold = xmax end do write(6,100) stop 100 format(1x,54('-')) 101 format(2x,'Iteration',3x,'Eigenvalue',11x,'Eigenvector') 102 format(3x,'number',6x,'(n/m2)',7x,'X(1)', & 6x,'X(2)',6x,'X(3)') 103 format(1x,i5,7x,e12.5,3f10.5) 104 format(1x,i5,19x,3f10.5) end program min_own !------------------------------------------------------- subroutine norml(xbig,x) real x(3) xbig =x(1) If (x(2) > xbig) xbig = x(2) If (x(3) > xbig) xbig = x(3) x = x / xbig
162
return end subroutine norml 11) program own_full ! Declare variables use imsl implicit none integer,parameter :: n=3, lda=n, ldevec=n integer i, j real a(lda,n), eval(n), evec(ldevec,n), pin ! Set values of a(*,*) data a/2.6,1.,1.6,1.,3.1,1.6,1.6,1.6,3.6/ !-----------begin-------------------------------------------- open(2,file='own.txt') ! Find eigenvalues and vectors of a(*,*) call evcsf (n, a, lda, eval, evec, ldevec) ! Compute performance index pin = episf (n, n, a, lda, eval, evec, ldevec) ! Print results write(*,'(/,a,3f8.3),/') ' Eval=',eval write(2,'(/,a,3f8.3),/') ' Eval=',eval write(*,*) ' Evec' write(2,*) ' Evec' do i=1,ldevec write(*,'(6x,3f8.3)') (evec(i,j),j=1,n) write(2,'(6x,3f8.3)') (evec(i,j),j=1,n) end do write (*, '(/,a,f6.3)') ' Performance index = ', pin write (2, '(/,a,f6.3)') ' Performance index = ', pin end program own_full Розділ 4. 14) program lsq use imsl implicit none
integer, parameter :: nra=6, nca=4, lda=nra
163
integer i,j real a(lda, nca), b(nra), c(nca), res(nra), tol real :: xd(nra), yd(nra), q, x0=0.468 data xd/0.41d0,0.46d0,0.52d0,0.6d0,0.65d0,0.72d0/ data yd/2.57418d0,2.32516d0,2.09336d0,1.86203d0, & 1.74926d0,1.62098d0/
!-------------------------begin-------------------------------------- open(6,file='polinom.txt') do i=1,nra do j=1,nca a(i,j)=xd(i)**(j-1) end do; end do write(6,*) 'A=' do i=1,nra; write (6,*) (a(i,j), j=1,nca); end do tol=1.0e-4 call lsbrr(nra, nca, a, lda, yd, tol, c, res, kbasis)
! Print result write(6,*) write(6,*) 'kbasis=', kbasis,' x0=',x0 write(6,*) 'c=', c write(6,*) 'res=', res q=c(1) do j=2,nca; q=q+c(j)*(x0**(j-1)); end do write(6,*) 'q=',q stop end program lsq
15) program spline use imsl implicit none integer,parameter :: ndata=6 integer i, nout real fdata(ndata), xdata(ndata) real value(1), xvec(1) data xdata/0.41,0.46,0.52,0.6,0.65,0.72/ data fdata/2.57418,2.32516,2.09336,1.86203,1.74926, & 1.62098/
164
data xvec/0.468/ !-----------begin--------------------------------------------------- open(2,file='polinom1.txt') ! ! Compute cubic spline interpolant call csiez (ndata, xdata, fdata, 1, xvec, value) ! Write heading write (*,99998) write (2,99998) 99998 format (13x, 'x', 9x, 'interpolant') ! Print the interpolant and the error ! on a finer grid write (*,99999) xvec, value(1) write (2,99999) xvec, value(1) 99999 format(' ', 2f15.3) end program spline 16) program gauss1 use imsl integer irule, nout real a, abs, b, errabs, errest, error, errrel, exact real f, result0 external f !------------ begin -------------------------------------------- open(2,file='gauss1.txt') ! Set limits of integration a = 0.0; b = 2.0 ! Set error tolerances errabs = 0.0; errrel = 0.001 ! Parameter for non-oscillatory function irule = 1 call qdag (f, a, b, errabs, errrel, irule, result0, errest) ! Print results exact = 1.0 + exp(2.0) error = abs(result0-exact) write (*,99999) result0, exact, errest, error write (2,99999) result0, exact, errest, error
165
99999 format (' Computed =', f8.3, 13x, ' Exact =', f8.3, /, & ' Error estimate =', 1pe10.3, 6x, ' Error =', 1pe10.3) end program gauss1 !----------------------------------------------------------------- real function f (x) real x f = x*exp(x) return end function f 17) program gauss_inf use imsl integer interv, nout real abs, alog, atan, bound, errabs, errest, error real errrel, exact, f, pi, result0 external f !----------begin--------------------------------------------------- open(2,file='gauss_inf.txt') ! Set limits of integration bound = 0.0; interv = 1 ! Set error tolerances errabs = 0.0; errrel = 0.001 call qdagi (f, bound, interv, errabs, errrel, result0, errest) ! Print results pi = 4.0*atan(1.0) exact = -pi*alog(10.)/20.; error = abs(result0-exact) write (*,99999) result0, exact, errest, error write (2,99999) result0, exact, errest, error 99999 format (' Computed =', f8.3, 13x, ' Exact =', f8.3//' Error ', & 'Estimate =', 1pe10.3, 6x,' Error =', 1pe10.3) end program gauss_inf !------------------------------------------------------------------- real function f (x) real x f = alog(x)/(1.+(10.*x)**2) return end function f
166
Розділ 5. 10) Попередньо зведемо систему рівнянь (5.56) до системи
із 4-х рівнянь першого порядку
1 2
22 2 1 3
3 4
34 4 1
,
2 4 1,
,
2 ( ) ,
x
x
y y
y y y y e
y y
y y y x e
−
′ = ′ = + − − ′ = ′ = + −
при наступних початкових умовах 1 2 3 4(0) 1, (0) 1, (0) 0, (0) 0.5y y y y= = = = . Код програми: program TestDE21
use ode_sp_n_dp1 implicit none integer, parameter :: m=4 real :: a, b, h, eps, y(m), e(m) integer :: i, error, cnt=0 !------------------------begin------------------------------------------ a=0.0; b=-4.0 ! Відрізок інтегрування ! Початковий крок інтегрування h=0.001953125 ! h=1/2**9 ! Точність інтегрування eps=0.5e-7 ! Початкові значення задаємо із точного розв’язку y(1)=exp(-a)+a y(2)=-exp(-a)+1.0 y(3)=0.5*a*exp(2.0*a) y(4)=0.5*exp(2.0*a)+a*exp(2.0*a) ! Основна процедура call de21(ds, a, b, h, eps, y, error) ! Точний розв’язок на кінці інтервалу e(1)=exp(-b)+b e(2)=-exp(-b)+1.0
1 Модуль ode_sp_n_dp знаходиться в Додатку.
167
e(3)=0.5*b*exp(2.0*b) e(4)=0.5*exp(2.0*b)+b*exp(2.0*b) ! Друк результату write(*,20) (i, e(i), i, y(i), i=1,m) write(*,30) error, h, a, cnt 20 format(/(' e',i1,' =',f14.6,' y',i1,' =',f14.6)) 30 format(/' error =',i2,' h =',e14.6,' x =',e14.6,' cnt ='i5) contains subroutine ds(x, y, dy) ! Процедура містить праві частини рівнянь real, intent(in) :: x, y(:) real :: dy(:) !----------------------begin--------------------------------------------- dy(1)=y(2) dy(2)=y(2)+2.0*y(1)-4.0*y(3)*exp(-2.0*x)-1.0 dy(3)=y(4) dy(4)=2.0*y(4)+(y(1)-x)*exp(3.0*x) cnt=cnt+1 return end subroutine ds end program testde21
11) Очевидно, що тут ми маємо справу з “жорсткою”
системою ЗДР, яка не може бути розв’язана за стандартною процедурою: Рунге−Кутта або прогноз-корекція. Скористаємося у цьому випадку стандартною процедурою із бібліотеки IMSL, що використовує метод Гіра
1. Код програми: Program Gear_stiff_BDF Use IMSL
1 Тут також можна скористатися подібною процедурою SLSODE з сайту http://www.netlib.org/odepack/ .
168
! Gear’s stiff BDF method integer,parameter :: mxparm=50, n=3 ! Specifications for parameters integer,parameter :: mabse=1, mbdf=2, msolve=1 ! specifications for local variables integer ido, istep, nout real a(1,1), param(mxparm), t, tend, tol, y(n) ! specifications for functions external fcn, fcnj !---------------------------------begin----------------------------------- open(2, file='gear stiff problem.txt') ! Set initial conditions t = 0.0 y(1) = 1.0; y(2) = 0.0; y(3) = 0.0 ! Set error tolerance tol = 1.0e-5 ! Set param to defaults param(:) = 0.0 ! Select absolute error control param(10) = mabse ! Select BDF method param(12) = mbdf ! Select chord method and a user-provided jacobian. param(13) = msolve ! Print header write (*,99998) write (2,99998) ido = 1; istep = 0 10 continue istep = istep + 1 tend = istep ! The array a(*,*) is not used. call ivpag (ido, n, fcn, fcnj, a, t, tend, tol, param, y) ! if (istep <= 10) then write (*,'(i6,f12.2,3f13.5)') istep, t, y write (2,'(i6,f12.2,3f13.5)') istep, t, y
169
! Final call to release workspace if (istep == 10) ido = 3 go to 10 end if 99998 format (4x,'istep',5x,'time',9x,'y1',11x,'y2',11x,'y3') end program gear_stiff_bdf !--------------------------------------------------------------------- subroutine fcn (n, t, y, yprime) ! Specifications for arguments integer n real t, y(n), yprime(n) ! Specifications for save variables real,save :: c1, c2, c3 ! data c1, c2, c3/0.04e0, 1.0e4, 3.0e7/ ! yprime(1) = -c1*y(1) + c2*y(2)*y(3) yprime(3) = c3*y(2)**2 yprime(2) = -yprime(1) - yprime(3) return end subroutine fcn !---------------------------------------------------------------------- subroutine fcnj (n, t, y, dypdy) ! Specifications for arguments integer n real t, y(n), dypdy(n,n) ! Specifications for save variables real,save :: c1, c2, c3 ! Specifications for subroutines data c1, c2, c3/0.04e0, 1.0e4, 3.0e7/ ! Clear array to zero dypdy(:,:) = 0.0 ! Compute partials dypdy(1,1) = -c1 dypdy(1,2) = c2*y(3) dypdy(1,3) = c2*y(2) dypdy(3,2) = 2.0*c3*y(2)
170
dypdy(2,1) = -dypdy(1,1) dypdy(2,2) = -dypdy(1,2) - dypdy(3,2) dypdy(2,3) = -dypdy(1,3) return end subroutine fcnj 12) program ode_bvp ! Solve boundary value problem for ODE on [a,b] ! y"+p(x)y'+q(x)y=f(x), ! c1*y(a)+c2*y'(a)=c, d1*y(b)+d2*y'(b)=d
use solve_LAEA implicit none integer, parameter :: n=101 integer :: er, i, nm1 real, parameter :: a=0.0, b=3.14, c=1.0, d=0.0, f=0.8 real, parameter :: c1=1.0, c2=1.0, d1=1.0, d2=0.0 real :: aa(n), bb(n), cc(n), dd(n), rez(n), x(n) real h, pi, qi, xx, fi, b0 !------------------------begin--------------------------------------- open(2,file='ODE_BVP1.txt') nm1=n-1 b0 = 4.0*atan(1.0) h=(b0-a)/nm1 aa = 0.0; bb = 0.0; cc = 0.0; dd = 0.0 x(1) = a; x(n) = b0 write(*,*) ' h= ',h,' x= ',x(1) do i=2,nm1 x(i) = a+(i-1)*h pi = 2.0*x(i) qi = 1.0 !*x(i) fi = 2.0*x(i)*cos(x(i)) aa(i) =-2./h**2+qi bb(i) = 1./h**2+pi/(2.*h) cc(i) = 1./h**2-pi/(2.*h) dd(i) = fi end do ! i=2,nm1 aa(1) = (c1-c2/h); cc(1) = c2/h; dd(1) = c
171
aa(n) = (d1+d2/h); bb(n) =-d2/h; dd(n) = d !-------------Main procedure------------------------------------------
call solve_band3(aa, bb, cc, dd, rez, Er) if (Er>=65) then print *, 'Matrix with singularity. Program stop.' stop ' Error 65' end if
!--------------Print result----------------------------------------------- write(*,12) do i=1,n,5; write(*,13) x(i), rez(i), sin(x(i)); end do write(2,12) do i=1,n,5; write(2,13) x(i), rez(i), sin(x(i)); end do 12 format(/' Solution:'//,' X Y(x) Sin x') 13 format(1x,F15.4,2F15.7) stop end program ode_bvp
13) Ця задача є нелінійною, а, отже, після скінченно-
різницевого представлення похідних у вихідному рівнянні відносно внутрішніх точок сітки маємо систему нелінійних рівнянь, яка повинна бути розв’язана одним із методів розв’язання систем нелінійних рівнянь. В даному випадку – це метод Ньютона, який потребує приведення рівняння другого порядку до системи рівнянь першого порядку
1 2
3 22 1
1 1
,
(1 sin )sin 0,
(0) ( ) 0,
y y
y y t t
y y π
′ =
′ − + + =
= =
а також додаткового визначення якобіана:
21
0 1
3 0J
y
=
.
Скористаємося стандартною процедурою бібліотеки IMSL. Код програми:
172
program ODE_BVP_IMSL use imsl ! Specifications for parameters integer,parameter :: mxgrid=45, neqns=2, ninit=12, &
ldyfin=neqns, ldyini=neqns) ! Specifications for local variables integer i, j, ncupbc, nfinal, nleft, nout real errest(neqns), pistep, tfinal(mxgrid), tinit(ninit), & tleft, tol, tright, yfinal(ldyfin,mxgrid), & yinit(ldyini,ninit) logical linear, print0 ! Specifications for intrinsics external fcnbc, fcneqn, fcnjac !----------------------begin---------------------------------------- open(2,file='ode_bvp_imsl.txt') ! Set parameters nleft = 1 ncupbc = 0 tol = .001 tleft = 0.0 tright = 4.0*atan(1.0) pistep = 0.0 print0 = .false. linear = .false. ! Define tinit and yinit do i=1, ninit tinit(i) = tleft + (i-1)*(tright-tleft)/float(ninit-1) yinit(1,i) = 0.4*(tinit(i)-tleft)*(tright-tinit(i)) yinit(2,i) = 0.4*(tleft-tinit(i)+tright-tinit(i)) end do ! Solve problem call bvpfd(fcneqn,fcnjac,fcnbc,fcneqn,fcnbc,neqns, & nleft,ncupbc,tleft,tright,pistep,tol, ninit, & tinit,yinit,ldyini,linear,print0,mxgrid, & nfinal,tfinal,yfinal,ldyfin,errest) ! Print results write (*,99997)
173
write (2,99997) write (*,99998) (i,tfinal(i),(yfinal(j,i),j=1,neqns) & ,i=1,nfinal) write (2,99998) (i,tfinal(i),(yfinal(j,i),j=1,neqns) & ,i=1,nfinal) write (*,99999) (errest(j),j=1,neqns) write (2,99999) (errest(j),j=1,neqns) 99997 format (4x, 'i', 7x, 't', 14x, 'y1', 13x, 'y2') 99998 format (i5, 1p3e15.6) 99999 format (/,' error estimates', 4x, 1p2e15.6) end program ODE_BVP_IMSL !---------------------------------------------------------------------- subroutine fcneqn (neqns, t, y, p, dydt) ! Specifications for arguments integer neqns real t, p, y(neqns), dydt(neqns) ! Define ODE dydt(1) = y(2) dydt(2) = y(1)**3 - sin(t)*(1.0+sin(t)**2) return end subroutine fcneqn !----------------------------------------------------------------------- subroutine fcnjac (neqns, t, y, p, dypdy) ! Specifications for arguments integer neqns real t, p, y(neqns), dypdy(neqns,neqns) ! Define jacobian d(dydt)/dy dypdy(1,1) = 0.0 dypdy(1,2) = 1.0 dypdy(2,1) = 3.0*y(1)**2 dypdy(2,2) = 0.0 return end subroutine fcnjac !----------------------------------------------------------------------- subroutine fcnbc (neqns, yleft, yright, p, f) ! Specifications for arguments integer neqns
174
real p, yleft(neqns), yright(neqns), f(neqns) ! Define boundary conditions f(1) = yleft(1) f(2) = yright(1) return end subroutine fcnbc
175
Додаток module solve_LAEA implicit none contains subroutine fact(n,a,jpvt) ! Factorises A into L.U ! jpvt(k) gives index of k-th pivot row. ! Sets jpvt(n) =-1 if zero pivot occurs integer,intent(in) :: n integer,intent(inout) :: jpvt(n) real,intent(inout) :: a(n,n) integer nm1,k,kp,i,j,l real s nm1 = n-1 ! Gauss elimination with partial pivoting do k = 1,nm1 kp = k + 1 ! Select pivot l = k do i = kp,n if (abs(a(i,k)) > abs(a(l,k))) l = i end do ! i jpvt(k) = l s = a(l,k) a(l,k) = a(k,k) a(k,k) = s ! Check for zero pivot if (abs(s) < 1.0e-15) exit ! Calculate multipliers do i=kp,n a(i,k) =-a(i,k)/s end do ! i ! Interchange and eliminate by columns do j = kp,n s = a(l,j) a(l,j) = a(k,j)
176
a(k,j) = s if (abs(s) < 1.0e-15) exit do i = kp,n a(i,j) = a(i,j) + a(i,k)*s end do ! i end do ! j end do ! k return 6 continue jpvt(n) =-1 return end subroutine fact !---------------------------------------------------- subroutine solve(n,a,jpvt,b) ! Solves linear system, A*x = b assumes A ! is factorised into L.U form (by fact) ! returns solution, x, in b integer,intent(in) :: n integer,intent(inout) :: jpvt(n) real,intent(inout) :: a(n,n),b(n) integer i,nm1,k,kp,l,ka,km real s ! Forward elimination nm1 = n - 1 do k=1,nm1 kp = k + 1 l= jpvt(k) s = b(l) b(l) = b(k) b(k) = s do i=kp,n b(i) = b(i)+a(i,k)*s end do ! i end do ! k ! Back substitution do ka = 1,nm1 km = n - ka
177
k= km + 1 b(k) = b(k)/a(k,k) s =-b(k) do i = 1,km b(i) = b(i)+a(i,k)*s end do ! i end do ! ka b(1)=b(1)/a(1,1) return end subroutine solve !---------------------------------------------------- subroutine solve_band3(A, B, C, D, X, Error) real, intent(in) :: A(:), B(:), C(:), D(:) real :: X(:) integer :: Error real, allocatable :: P(:), Q(:), R(:), S(:), T(:) real W integer i, ip1, n !--------------begin-------------------------------- n=size(A) if (n<3) then Error=1; return end if allocate(P(n), Q(n), R(n), S(n), T(n)) P(1)=0.0; Q(1)=0.0; R(1)=1.0 do i=1,n-1 ip1=i+1 W=A(i)+Q(i)*C(i) if (1.0+W == 1.0) then deallocate(P, Q, R, S, T) Error=65; return end if P(ip1)=(D(i)-P(i)*C(i))/W Q(ip1)=-B(i)/W R(ip1)=-R(i)*C(i)/W end do ! i S(n)=1.0; T(n)=0.0
178
do i=n-1,1,-1 ip1=i+1 S(i)=Q(ip1)*S(ip1)+R(ip1) T(i)=Q(ip1)*T(ip1)+P(ip1) end do ! i W=A(n)+B(n)*S(1)+c(n)*S(n-1) if (1.0+W == 1.0) then deallocate(P, Q, R, S, T) Error=65; return end if X(n)=(D(n)-B(n)*T(1)-C(n)*T(n-1))/W do i=1,n-1 X(i)=S(i)*X(n)+T(i) end do ! i deallocate(P, Q, R, S, T) Error=0; return end subroutine solve_band3 !---------------------------------------------------- subroutine solve_band5(A, B, C, D, E, G, X, Error) real, intent(in) :: A(:), B(:), C(:), D(:), E(:), G(:) real :: X(:) integer :: Error real, allocatable :: P(:), Q(:), R(:), S(:), T(:) real, allocatable :: U(:), V(:), W(:) real AA, DD, A11, A12, A21, A22, B1, B2, zz integer i, ip1, ip2, n !--------------------begin--------------------------- n=size(A) if (n<5) then Error=1; return end if allocate(P(n+2), Q(n+2), R(n+2), S(n+2), T(n+2)) allocate(U(n), V(n), W(n)) P(1)=0.0; Q(1)=0.0; R(1)=0.0; S(1)=1.0; T(1)=0.0 P(2)=0.0; Q(2)=0.0; R(2)=0.0; S(2)=0.0; T(2)=1.0 do i=1,n ip1=i+1; ip2=i+2
179
DD=D(i)+E(i)*Q(i) AA=A(i)+DD*Q(ip1)+E(i)*R(i) if (1.0+AA == 1.0) then deallocate(P,Q,R,S,T,U,V,W) Error=65; return end if P(ip2)=(G(i)-DD*P(ip1)-E(i)*P(i))/AA Q(ip2)=-(B(i)+DD*R(ip1))/AA R(ip2)=-C(i)/AA S(ip2)=-(DD*S(ip1)+E(i)*S(i))/AA T(ip2)=-(DD*T(ip1)+E(i)*T(i))/AA end do ! i U(n)=0.0; V(n)=0.0; W(n)=1.0 U(n-1)=0.0; V(n-1)=1.0; W(n-1)=0.0 do i=n-2,1,-1 ip1=i+1; ip2=i+2 U(i)=P(ip2)+Q(ip2)*U(ip1)+R(ip2)*U(ip2) V(i)=S(ip2)+Q(ip2)*V(ip1)+R(ip2)*V(ip2) W(i)=T(ip2)+Q(ip2)*W(ip1)+R(ip2)*W(ip2) end do ! i A11=1.0-S(n+1)-R(n+1)*V(1) A12=-(T(n+1)+Q(n+1)+R(n+1)*W(1)) A21=-(S(n+2)+Q(n+2)*V(1)+R(n+2)*V(2)) A22=1.0-T(n+2)-Q(n+2)*W(1)-R(n+2)*W(2) B1=P(n+1)+R(n+1)*U(1) B2=P(n+2)+Q(n+2)*U(1)+R(n+2)*U(2) DD=A11*A22-A12*A21 if (1.0+DD == 1.0) then deallocate(P,Q,R,S,T,U,V,W) Error=65; return end if X(n-1)=(B1*A22-B2*A12)/DD X(n) =(-B1*A21+B2*A11)/DD do i=1,n-2 X(i)=U(i)+V(i)*X(n-1)+W(i)*X(n) end do deallocate(P, Q, R, S, T, U, V, W)
180
Error=0; return end subroutine solve_band5 !---------------------------------------------------- subroutine qrdcmp(a,n,np,c,d,sing) ! Constructs the qr decomposition of a(1:n,1:n), ! with physical dimension np. integer,intent(in) :: n,np real,intent(inout) :: a(np,np),c(n),d(n) logical,intent(out) :: sing integer i,j,k real scale,sigma,sum,tau sing=.false. do k=1,n-1 scale=0. do i=k,n; scale=max(scale,abs(a(i,k))); end do if (scale == 0.) then ! singular case. sing=.true. c(k)=0.; d(k)=0. else ! form q k and qk x a. do i=k,n; a(i,k)=a(i,k)/scale; end do sum=0.0 do i=k,n; sum=sum+a(i,k)**2; end do sigma=sign(sqrt(sum),a(k,k)) a(k,k)=a(k,k)+sigma c(k)=sigma*a(k,k); d(k)=-scale*sigma do j=k+1,n sum=0. do i=k,n; sum=sum+a(i,k)*a(i,j); end do tau=sum/c(k) do i=k,n; a(i,j)=a(i,j)-tau*a(i,k); end do end do ! j end if end do ! k d(n)=a(n,n) if (d(n) == 0.0) sing = .true.
181
return end subroutine qrdcmp !---------------------------------------------------- subroutine qrsolv(a,n,np,c,d,b) ! Solves the set of n linear equations a ·x = b,wherea is a matrix ! with physical dimension np. integer,intent(in) :: n, np real,intent(inout) :: a(np,np), c(n), d(n), b(n) integer i, j real sum, tau do j=1,n-1 sum=0.0 do i=j,n; sum=sum+a(i,j)*b(i); end do tau=sum/c(j) do i=j,n; b(i)=b(i)-tau*a(i,j); end do end do ! j ! solve R·x = Q t call rsolv(a,n,np,d,b) return end subroutine qrsolv !---------------------------------------------------- subroutine rsolv(a,n,np,d,b) ! Solves the set of n linear equations r ·x = b,where r is an upper ! triangular matrix stored in a and d. integer,intent(in) :: n,np real,intent(inout) :: a(np,np),d(n),b(n) integer i,j real sum b(n)=b(n)/d(n) do i=n-1,1,-1 sum=0.0 do j=i+1,n; sum=sum+a(i,j)*b(j); end do b(i)=(b(i)-sum)/d(i) end do ! i return end subroutine rsolv !----------------------------------------------------
182
subroutine root_decomp(A, D, Trp, T, Error) real,intent(inout) :: A(:,:), D(:) logical,intent(in) :: Trp integer,intent(inout) :: T(:), Error real, allocatable :: W(:) real RN, AA, Sum integer i, j, k, m, p, N !-------------------------begin--------------------------- N=size(A,1); RN=float(N) Error=0 allocate(W(N)) do i=1,N; D(i)=A(i,i); end do do p=1, N if (Trp) then AA=abs(D(p)); m=p do k=p+1, N if (AA < abs(D(k))) then AA=abs(D(k)); m=k end if end do ! k if (m/=p) then AA=D(m); D(m)=D(p); D(p)=AA ! if p>1 then do i=1, p-1 AA=A(i,p); A(i,p)=A(i,m); A(i,m)=AA end do ! i ! end if ! if p+1<m then do i=p+1, m-1 AA=A(p,i); A(p,i)=A(i,m); A(i,m)=AA end do ! i ! end if ! if m<N then do i=m+1, N AA=A(p,i); A(p,i)=A(m,i); A(m,i)=AA end do ! i ! end if
183
end if T(p)=m end if if (RN+abs(D(p)) == RN) then deallocate(W) Error=65; return end if Sum=D(p) do k=1, p-1 W(k)=A(k,p)*D(k) Sum=Sum-A(k,p)*W(k) end do ! k D(p)=Sum do j=p+1, N Sum=A(p,j) do k=1, p-1; Sum=Sum-A(k,j)*W(k); end do A(p,j)=Sum/D(p) end do ! j end do ! p if (.not.Trp) then do i=1, N-1; T(i)=i; end do end if T(N)=N deallocate(W) return end subroutine root_decomp !---------------------------------------------------- subroutine root_solve(A, D, T, B, X) integer,intent(in) :: T(:) real,intent(in) :: A(:,:), D(:), B(:) real,intent(inout) :: X(:) real Sum, XX integer i, j, n, m !--------------------begin------------------------- N=size(A,1) if (loc(B) /= loc(X)) X=B do i=1, N
184
m=T(i); Sum=X(m); X(m)=X(i) do j=1, i-1; Sum=Sum-A(j,i)*X(j); end do X(i)=Sum ! X(i)=Sum/D(i) end do ! i do i=1,N; X(i)=X(i)/D(i); end do do i=N, 1, -1 Sum=X(i) do j=i+1, N; Sum=Sum-A(i,j)*X(j); end do X(i)=Sum end do ! i do i=1, N-1 m=T(i) if (m/=i) then XX=X(m); X(m)=X(i); X(i)=XX end if end do ! i return end subroutine root_solve !---------------------------------------------------- subroutine banfac(b,n,int) ! Factorises band matrix arising from linear or ! quadratic elements into L.U integer,intent(in) :: n real,intent(inout) :: b(5,n) integer int,i,j,jp,nm1,nh,js,ja,jb if (int == 2) goto 2 ! int = 1, linear elements - tridiagonal system nm1=n-1 do j=1,nm1 jp=j+1 b(2,jp) = b(2,jp)/b(3,j) b(3,jp) = b(3,jp) - b(2,jp)*b(4,j) end do ! j return 2 continue ! int=2, quadratics elements = pentadiagonal system ! assumes first equation formed at midside node
185
nh=n/2 do i=1,2 js=3-i do j=js,nh ja=2*(j-1) if (i == 2) goto 3 ! i=1, first pass, reduce to tridiagonal jb=ja+2 b(1,jb)=b(1,jb)/b(2,jb-1) b(2,jb)=b(2,jb)-b(1,jb)*b(3,jb-1) b(3,jb)=b(3,jb)-b(1,jb)*b(4,jb-1) exit ! i=2, second pass, reduce to upper triangular 3 jb=ja+3 b(2,jb-1)=b(2,jb-1)/b(3,jb-2) b(3,jb-1)=b(3,jb-1)-b(2,jb-1)*b(4,jb-2) if (jb > n) exit b(2,jb)=b(2,jb)/b(3,jb-1) b(3,jb)=b(3,jb)-b(2,jb)*b(4,jb-1) b(4,jb)=b(4,jb)-b(2,jb)*b(5,jb-1) end do ! j end do ! i return end subroutine banfac !---------------------------------------------------- subroutine bansol(r,x,b,n,int) ! Uses L.U factorisation to solve for x(:), given r(:) integer,intent(in) :: n,int real,intent(inout) :: b(5,n) real,intent(inout) :: r(n) real,intent(out) :: x(n) integer nm1,i,k,j,jp1,ibc,nh,ja,jb,nen if (int == 2) goto 2 ! int = 1, tridiagonal system nm1 = n - 1 do j = 1,nm1 jp1 = j + 1
186
r(jp1) = r(jp1) - b(2,jp1)*r(j) end do ! j x(n) = r(n)/b(3,n) do j = 1,nm1 ja = n - j x(ja) = (r(ja) - b(4,ja)*x(ja+1))/b(3,ja) end do ! j return 2 continue ! int=2, pentadiagonal system ! assumes first equation formed at midside node ! set ibc=0 if last equation formed at midside node ! set ibc=1 if last equation formed at corner node ibc=1; nh=n/2 if (2*nh == n) r(n+1)=0.0 if (2*nh == n) b(2,n+1)=0.0 do i=1,2 do j=1,nh ja=2*j do k=1,i jb=ja-1+k r(jb)=r(jb)-b(i,jb)*r(jb-1) end do ! k end do ! j end do ! i nen=nh-ibc x(n)=r(n)/b(3,n) if (ibc == 1) x(n-1)=(r(n-1)-b(4,n-1)*x(n))/b(3,n-1) do j=1,nen ja=n-2*j+1-ibc x(ja)=(r(ja)-b(4,ja)*x(ja+1)-b(5,ja)*x(ja+2))/b(5,ja) end do ! j return end subroutine bansol !---------------------------------------------------- end module solve_LAEA
187
module newton_raphson implicit none contains subroutine find_root( f, xinit, tol, maxiter, result0, success ) interface real function f(x) real, intent(in) :: x end function f end interface real, intent(in) :: xinit, tol integer, intent(in) :: maxiter real, intent(out) :: result0 logical, intent(out) :: success real :: eps = 1.0e-4 real :: fx1, fx2, fprime, x, xnew integer :: i !-------------------------begin------------------------------------ result0 = 0.0 success = .false. x = xinit do i = 1,max(1,maxiter) fx1 = f(x); fx2 = f(x+eps) fprime = (fx2 - fx1) / eps xnew = x - fx1 / fprime if ( abs(xnew-x) <= tol ) then success = .true. result0 = xnew exit end if x = xnew end do ! i end subroutine find_root !----------------------------------------------------- Subroutine Newton2(x,y,eps,flag) ! Solutions of two nonlinear equations ! f(x,y) = 0 ! g(x,y) = 0
188
! Input ... ! x,y - guess points ! eps - desired uncertainity of the root as f(Root)<eps ! Output ... ! x,y - roots of the equations ! flag - indicator of success ! >0 - roots are found, flag=number of iterations ! 0 - no solutions found ! Comments: f(x,y), g(x,y) and their derivatives are evaluated in ! subroutine fg(x,y,f,fx,fy,g,gx,gy) integer, parameter :: iter=200 integer i, flag real(8) :: x, y, eps real(8) :: f, fx, fy, g, gx, gy real(8) :: del, dx, dy !* Iterative refining the solution do i=1,iter call fg(x,y,f,fx,fy,g,gx,gy) del = fx*gy - fy*gx dx=(fy*g-f*gy)/del dy=(f*gx-fx*g)/del x = x + dx y = y + dy ! condition(s) to stop iterations) if (abs(dx)<= eps .and. abs(dy)<=eps) exit end do ! i !* check the convergence if (i /= iter) then flag=i else flag = 0 end if end subroutine Newton2 !----------------------------------------------------- end module newton_raphson
189
module QR_basic_mod implicit none contains !=============================================== subroutine QRbasic(a,e,eps,n,iter) !-------------------------------------------------------------- ! Compute all eigenvalues: real symmetric matrix a(n,n,) ! a*x = lambda*x ! method: the basic QR method ! Alex G. (January 2010) !-------------------------------------------------------------- ! Input ... ! a(n,n) - array of coefficients for matrix A ! n - dimension ! eps - convergence tolerance ! Output ... ! e(n) - eigenvalues ! iter - number of iterations to achieve the tolerance ! comments ... ! kmax - max number of allowed iterations !-------------------------------------------------------------- integer, parameter :: kmax=1000 integer n, iter integer k, i, j, m real(8) :: a(n,n), e(n), eps real(8) :: q(n,n), r(n,n), w(n), an, Ajnorm, sum, e0,e1 !-------------------begin--------------------------------------- ! Initialization q = 0.0 r = 0.0 e0 = 0.0 do k=1,kmax ! iterations ! Step 1: compute Q(n,n) and R(n,n) ! column 1 an = Ajnorm(a,n,1) r(1,1) = an do i=1,n; q(i,1) = a(i,1)/an; end do
190
! columns 2,...,n do j=2,n w = 0.0 do m=1,j-1 ! Product q^T*a result = scalar sum = 0.0 do i=1,n; sum = sum + q(i,m)*a(i,j); end do r(m,j) = sum ! Product (q^T*a)*q result = vector w(n) do i=1,n; w(i) = w(i) + sum*q(i,m); end do end do ! m ! New a'(j) do i =1,n; a(i,j) = a(i,j) - w(i); end do ! Evaluate the norm for a'(j) an = Ajnorm(a,n,j) r(j,j) = an ! Vector q(j) do i=1,n; q(i,j) = a(i,j)/an; end do end do ! j ! Step 2: compute A=R(n,n)*Q(n,n) a = matmul(r,q) ! egenvalues and the average eigenvale sum = 0.0 do i=1,n e(i) = a(i,i) sum = sum+e(i)*e(i) end do ! i e1 = dsqrt(sum) ! Print here eigenvalues ! write (*,201) (e(i),i=1,n) !201 format (6f12.6) ! Check for convergence if (dabs(e1-e0) < eps) exit ! Prepare for the next iteration e0 = e1 end do ! k iter = k
191
if (k == kmax) write (*,*)'The eigenvlue failed to converge' end subroutine QRbasic !=============================================== function Ajnorm(a,n,j) integer n, j, i real(8) :: a(n,n), Ajnorm real(8) :: sum sum = 0.d0 do i=1,n; sum = sum + a(i,j)*a(i,j); end do Ajnorm = dsqrt(sum) end function Ajnorm !=============================================== end module QR_basic_mod module data_processing !==============LSQ processing====================== !-------------------------------------------------------------------------- ! General declarations !-------------------------------------------------------------------------- implicit none integer, save :: nobs, ncol, r_dim integer, allocatable, save :: vorder(:), row_ptr(:) logical, save :: initialized = .false., & tol_set = .false., rss_set = .false. integer, parameter :: dp = selected_real_kind(12,60) real (dp), allocatable, save :: d(:), rhs(:), r(:), tol(:), rss(:) real (dp), save :: zero = 0.0_dp, one = 1.0_dp, vsmall real (dp), save :: sserr, toly !-------------------------------------------------------------------------- public :: dp, nobs, ncol, r_dim, vorder, row_ptr, & initialized, tol_set, rss_set, & d, rhs, r, tol, rss, sserr private :: zero, one, vsmall !-------------------------------------------------------------------------- contains !-------------------------------------------------------------------------- !============LSQ processing====================
192
!=============================================== subroutine startup(nvar, fit_const) ! Allocates dimensions for arrays and initializes to zero ! The calling program must set nvar = the number of variables, ! and fit_const = .true. if a constant is to be included in the ! model, otherwise fit_const = .false. !-------------------------------------------------------------------------- integer, intent(in) :: nvar logical, intent(in) :: fit_const ! Local variable integer :: i !------------------------begin------------------------------------------ vsmall = 10. * tiny(zero); nobs = 0 if (fit_const) then ncol = nvar + 1 else ncol = nvar end if if (initialized) deallocate(d, rhs, r, tol, rss, vorder, row_ptr) r_dim = ncol * (ncol - 1)/2 allocate( d(ncol), rhs(ncol), r(r_dim), tol(ncol), rss(ncol), & vorder(ncol), row_ptr(ncol) ) d = zero; rhs = zero; r = zero; sserr = zero if (fit_const) then do i = 1, ncol; vorder(i) = i-1; end do else do i = 1, ncol; vorder(i) = i; end do end if ! (fit_const) ! Row_ptr(i) is the position of element R(i,i+1) in array r(). row_ptr(1) = 1 do i = 2, ncol-1 row_ptr(i) = row_ptr(i-1) + ncol - i + 1 end do row_ptr(ncol) = 0 initialized = .true.; tol_set = .false.; rss_set = .false. return end subroutine startup
193
!=============================================== subroutine includ(weight, xrow, yelem) ! Calling this routine updates D, R, RHS and SSERR by the ! inclusion of xrow, yelem with the specified weight. !------------------------------------------------------------------------------- real (dp),intent(in) :: weight, yelem real (dp), dimension(:), intent(inout) :: xrow ! Local variables integer :: i, k, nextr real (dp) :: w, y, xi, di, wxi, dpi, cbar, sbar, xk !--------------------------------begin----------------------------------------- nobs = nobs + 1; w = weight; y = yelem rss_set = .false. nextr = 1 do i = 1, ncol ! Skip unnecessary transformations. Test on exact zeroes must be ! used or stability can be destroyed. if (abs(w) < vsmall) return xi = xrow(i) if (abs(xi) < vsmall) then nextr = nextr + ncol - i else di = d(i); wxi = w * xi dpi = di + wxi*xi cbar = di / dpi; sbar = wxi / dpi w = cbar * w; d(i) = dpi do k = i+1, ncol xk = xrow(k) xrow(k) = xk - xi * r(nextr) r(nextr) = cbar * r(nextr) + sbar * xk nextr = nextr + 1 end do ! k xk = y; y = xk - xi * rhs(i) rhs(i) = cbar * rhs(i) + sbar * xk end if ! abs(xi) < vsmall end do ! i = 1, ncol
194
! Y * SQRT(W) is now equal to the Brown, Durbin & Evans ! recursive residual. sserr = sserr + w * y * y return end subroutine includ !=============================================== subroutine regcf(beta, nreq, ifault) ! calculate regression coefficients for the first nreq ! variables !-------------------------------------------------------------------------- integer, intent(in) :: nreq integer, intent(out) :: ifault real (dp), dimension(:), intent(out) :: beta !-------------------------------------------------------------------------- ! Local variables integer :: i, j, nextr !---------------------Some checks------------------------------------- ifault = 0 if (nreq < 1 .or. nreq > ncol) ifault = ifault + 4 if (ifault /= 0) return if (.not. tol_set) call tolset() do i = nreq, 1, -1 if (sqrt(d(i)) < tol(i)) then beta(i) = zero; d(i) = zero; ifault = -i else beta(i) = rhs(i); nextr = row_ptr(i) do j = i+1, nreq beta(i) = beta(i) - r(nextr) * beta(j) nextr = nextr + 1 end do ! j = i+1, nreq end if ! sqrt(d(i)) < tol(i) end do ! i = nreq, 1, -1 return end subroutine regcf !=============================================== !
195
subroutine tolset(eps) ! Sets up array TOL for testing for zeroes in an orthogonal ! reduction formed using AS75.1. !-------------------------------------------------------------------------- real (dp), intent(in), optional :: eps !-------------------------------------------------------------------------- ! Unless the argument eps is set, it is assumed that the input data ! are recorded to full machine accuracy. This is often not the ! case. If, for instance, the data are recorded to `single precision' ! of about 6-7 significant decimal digits, then singularities will ! not be detected. ! It is suggested that in this case eps should be set equal to ! 10.0 * EPSILON(1.0) ! If the data are recorded to say 4 significant decimals, then eps ! should be set to 1.0E-03 ! The above comments apply to the predictor variables, not to the ! dependent variable. !-------------------------------------------------------------------------- ! Local variables. !-------------------------------------------------------------------------- integer :: col, row, pos real (dp) :: eps1, ten = 10.0, total, work(ncol) ! eps is a machine-dependent constant. if (present(eps)) then eps1 = max(abs(eps), ten * epsilon(ten)) else eps1 = ten * epsilon(ten) end if ! Set tol(i) = sum of absolute values in column I of R after ! scaling each element by the square root of its row multiplier, ! multiplied by EPS1. work = sqrt(abs(d)) do col = 1, ncol pos = col - 1 total = work(col) do row = 1, col-1 total = total + abs(r(pos)) * work(row)
196
pos = pos + ncol - row - 1 end do ! row tol(col) = eps1 * total end do ! col tol_set = .true. return end subroutine tolset !=============================================== subroutine sing(lindep, ifault) ! Checks for singularities, reports, and adjusts orthogonal ! reductions produced by AS75.1. ! Auxiliary routines called: INCLUD, TOLSET !-------------------------------------------------------------------------- integer, intent(out) :: ifault logical, dimension(:), intent(out) :: lindep !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- real (dp) :: temp, x(ncol), work(ncol), y, weight integer :: pos, row, pos2 !----------------------begin--------------------------------------------- ifault = 0 work = sqrt(abs(d)) if (.not. tol_set) call tolset() do row = 1, ncol temp = tol(row) pos = row_ptr(row) ! pos = location of first element in row ! If diagonal element is near zero, set it to zero, set appropriate ! element of LINDEP, and use INCLUD to augment the ! projections in the lower rows of the orthogonalization. lindep(row) = .false. if (work(row) <= temp) then lindep(row) = .true. ifault = ifault - 1 if (row < ncol) then pos2 = pos + ncol - row - 1 x = zero
197
x(row+1:ncol) = r(pos:pos2) y = rhs(row); weight = d(row) r(pos:pos2) = zero d(row) = zero; rhs(row) = zero call includ(weight, x, y) ! INCLUD automatically increases the number ! of cases each time it is called. nobs = nobs - 1 else sserr = sserr + d(row) * rhs(row)**2 end if ! (row < ncol) end if ! (work(row) <= temp) end do ! row = 1, ncol return end subroutine sing !=============================================== subroutine ss() ! Calculates partial residual sums of squares from an orthogonal ! reduction from AS75.1. !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- integer :: i real (dp) :: total !---------------------begin---------------------------------------------- total = sserr rss(ncol) = sserr do i = ncol, 2, -1 total = total + d(i) * rhs(i)**2 rss(i-1) = total end do ! i rss_set = .true. return end subroutine ss ! !=============================================== !
198
subroutine cov(nreq, var, covmat, dimcov, sterr, ifault) ! Calculate covariance matrix for regression coefficients for the ! first nreq variables, from an orthogonal reduction produced ! from AS75.1. ! Auxiliary routine called: INV !-------------------------------------------------------------------------- integer, intent(in) :: nreq, dimcov integer, intent(out) :: ifault real (dp), intent(out) :: var real (dp), dimension(:), intent(out) :: covmat, sterr !-------------------------------------------------------------------------- ! Local variables. !-------------------------------------------------------------------------- integer :: dim_rinv, pos, row, start, pos2, col, pos1, k real (dp) :: total real (dp), allocatable :: rinv(:) ! Check that dimension of array covmat is adequate. if (dimcov < nreq*(nreq+1)/2) then ifault = 1 return end if ! Check for small or zero multipliers on the diagonal. ifault = 0 do row = 1, nreq if (abs(d(row)) < vsmall) ifault = -row end do if (ifault /= 0) return ! Calculate estimate of the residual variance. if (nobs > nreq) then if (.not. rss_set) call ss() var = rss(nreq) / (nobs - nreq) else ifault = 2 return end if dim_rinv = nreq*(nreq-1)/2 allocate ( rinv(dim_rinv) )
199
call inv(nreq, rinv) pos = 1 start = 1 do row = 1, nreq pos2 = start do col = row, nreq pos1 = start + col - row if (row == col) then total = one / d(col) else total = rinv(pos1-1) / d(col) end if do k = col+1, nreq total = total + rinv(pos1) * rinv(pos2) / d(k) pos1 = pos1 + 1 pos2 = pos2 + 1 end do ! k = col+1, nreq covmat(pos) = total * var if (row == col) sterr(row) = sqrt(covmat(pos)) pos = pos + 1 end do ! col = row, nreq start = start + nreq - row end do ! row = 1, nreq deallocate(rinv) return end subroutine cov !=============================================== subroutine inv(nreq, rinv) ! Invert first nreq rows and columns of Cholesky factorization !-------------------------------------------------------------------------- integer, intent(in) :: nreq real (dp), dimension(:), intent(out) :: rinv !-------------------------------------------------------------------------- ! Local variables. !-------------------------------------------------------------------------- integer :: pos, row, col, start, k, pos1, pos2 real (dp) :: total
200
! Invert R ignoring row multipliers, from the bottom up. pos = nreq * (nreq-1)/2 do row = nreq-1, 1, -1 start = row_ptr(row) do col = nreq, row+1, -1 pos1 = start pos2 = pos total = zero do k = row+1, col-1 pos2 = pos2 + nreq - k total = total - r(pos1) * rinv(pos2) pos1 = pos1 + 1 end do ! k = row+1, col-1 rinv(pos) = total - r(pos1) pos = pos - 1 end do ! col = nreq, row+1, -1 end do ! row = nreq-1, 1, -1 return end subroutine inv !=============================================== subroutine partial_corr(in, cormat, dimc, ycorr, ifault) ! Calculate partial correlations after the variables in rows ! 1, 2, ..., IN have been forced into the regression. ! If IN = 1, and the first row of R represents a constant in the ! model, then the usual simple correlations are returned. ! If IN = 0, the value returned in array CORMAT for the ! correlation of variables Xi & Xj is: ! sum ( Xi.Xj ) / Sqrt ( sum (Xi^2) . sum (Xj^2) ) ! On return, array CORMAT contains the upper triangle of the ! matrix of partial correlations stored by rows, excluding the 1's ! on the diagonal.e.g. if IN = 2, the consecutive elements returned ! are: (3,4) (3,5) ... (3,ncol), (4,5) (4,6) ... (4,ncol), etc. ! Array YCORR stores the partial correlations with the ! Y-variable starting with YCORR(IN+1) = partial correlation ! with the variable in position (IN+1). !--------------------------------------------------------------------------
201
integer, intent(in) :: in, dimc integer, intent(out) :: ifault real (dp), dimension(:), intent(out) :: cormat, ycorr !-------------------------------------------------------------------------- ! Local variables. !-------------------------------------------------------------------------- integer :: base_pos, pos, row, col, col1, col2, pos1, pos2 real (dp) :: rms(in+1:ncol), sumxx, sumxy, sumyy real (dp) :: work(in+1:ncol) ! Some checks. ifault = 0 if (in < 0 .or. in > ncol-1) ifault = ifault + 4 if (dimc < (ncol-in)*(ncol-in-1)/2) ifault = ifault + 8 if (ifault /= 0) return ! Base position for calculating positions of elements ! in row (IN+1) of R. base_pos = in*ncol - (in+1)*(in+2)/2 ! Calculate 1/RMS of elements in columns from IN to (ncol-1). if (d(in+1) > zero) rms(in+1) = one / sqrt(d(in+1)) do col = in+2, ncol pos = base_pos + col; sumxx = d(col) do row = in+1, col-1 sumxx = sumxx + d(row) * r(pos)**2 pos = pos + ncol - row - 1 end do ! row = in+1, col-1 if (sumxx > zero) then rms(col) = one / sqrt(sumxx) else rms(col) = zero; ifault = -col end if ! (sumxx > zero) end do ! col = in+1, ncol-1 ! Calculate 1/RMS for the Y-variable sumyy = sserr do row = in+1, ncol sumyy = sumyy + d(row) * rhs(row)**2 end do ! row = in+1, ncol if (sumyy > zero) sumyy = one / sqrt(sumyy)
202
! Calculate sums of cross-products. ! These are obtained by taking dot products of pairs of columns ! of R, but with the product for each row multiplied by the row ! multiplier in array D. pos = 1 do col1 = in+1, ncol sumxy = zero; work(col1+1:ncol) = zero pos1 = base_pos + col1 do row = in+1, col1-1 pos2 = pos1 + 1 do col2 = col1+1, ncol work(col2) = work(col2) + d(row) * r(pos1) * r(pos2) pos2 = pos2 + 1 end do ! col2 = col1+1, ncol sumxy = sumxy + d(row) * r(pos1) * rhs(row) pos1 = pos1 + ncol - row - 1 end do ! row = in+1, col1-1 ! Row COL1 has an implicit 1 as its first element ! (in column COL1) pos2 = pos1 + 1 do col2 = col1+1, ncol work(col2) = work(col2) + d(col1) * r(pos2) pos2 = pos2 + 1 cormat(pos) = work(col2) * rms(col1) * rms(col2) pos = pos + 1 end do ! col2 = col1+1, ncol sumxy = sumxy + d(col1) * rhs(col1) ycorr(col1) = sumxy * rms(col1) * sumyy end do ! col1 = in+1, ncol-1 ycorr(1:in) = zero return end subroutine partial_corr !=============================================== SUBROUTINE vmove(from, to, ifault) ! Move variable from position FROM to position TO in an ! orthogonal reduction produced by AS75.1. !--------------------------------------------------------------------------
203
integer, intent(in) :: from, to integer, intent(out) :: ifault !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- real (dp) :: d1, d2, x, d1new, d2new, cbar, sbar, y integer :: m, first, last, inc, m1, m2, mp1, col, pos, row ! Check input parameters ifault = 0 if (from < 1 .or. from > ncol) ifault = ifault + 4 if (to < 1 .or. to > ncol) ifault = ifault + 8 if (ifault /= 0) return if (from == to) return if (.not. rss_set) call ss() if (from < to) then first = from; last = to - 1; inc = 1 else first = from - 1; last = to; inc = -1 end if do m = first, last, inc ! Find addresses of first elements of R in rows M and (M+1). m1 = row_ptr(m); m2 = row_ptr(m+1); mp1 = m + 1 d1 = d(m); d2 = d(mp1) ! Special cases. if (d1 < vsmall .and. d2 < vsmall) go to 40 x = r(m1) if (abs(x) * sqrt(d1) < tol(mp1)) then x = zero end if if (d1 < vsmall .or. abs(x) < vsmall) then d(m) = d2; d(mp1) = d1; r(m1) = zero do col = m+2, ncol m1 = m1 + 1 x = r(m1); r(m1) = r(m2); r(m2) = x m2 = m2 + 1 end do ! col = m+2, ncol x = rhs(m)
204
rhs(m) = rhs(mp1); rhs(mp1) = x go to 40 else if (d2 < vsmall) then d(m) = d1 * x**2; r(m1) = one / x r(m1+1:m1+ncol-m-1) = r(m1+1:m1+ncol-m-1) / x rhs(m) = rhs(m) / x go to 40 end if ! Planar rotation in regular case. d1new = d2 + d1*x**2; cbar = d2 / d1new sbar = x * d1 / d1new; d2new = d1 * cbar d(m) = d1new; d(mp1) = d2new r(m1) = sbar do col = m+2, ncol m1 = m1 + 1 y = r(m1); r(m1) = cbar*r(m2) + sbar*y r(m2) = y - x*r(m2) m2 = m2 + 1 end do ! col = m+2, ncol y = rhs(m) rhs(m) = cbar*rhs(mp1) + sbar*y rhs(mp1) = y - x*rhs(mp1) ! Swap columns M and (M+1) down to row (M-1). 40 pos = m do row = 1, m-1 x = r(pos); r(pos) = r(pos-1) r(pos-1) = x; pos = pos + ncol - row - 1 end do ! row = 1, m-1 ! Adjust variable order (VORDER), the tolerances (TOL) and ! the vector of residual sums of squares (RSS). m1 = vorder(m); vorder(m) = vorder(mp1); vorder(mp1) = m1 x = tol(m); tol(m) = tol(mp1); tol(mp1) = x rss(m) = rss(mp1) + d(mp1) * rhs(mp1)**2 end do ! m = first, last, inc return end subroutine vmove !===============================================
205
subroutine reordr(list, n, pos1, ifault) ! Re-order the variables in an orthogonal reduction produced by ! AS75.1 so that the N variables in LIST start at position POS1, ! though will not necessarily be in the same order as in LIST. ! Any variables in VORDER before position POS1 are not moved. ! Auxiliary routine called: VMOVE !-------------------------------------------------------------------------- integer, intent(in) :: n, pos1 integer, dimension(:), intent(in) :: list integer, intent(out) :: ifault !-------------------------------------------------------------------------- ! Local variables. !-------------------------------------------------------------------------- integer :: next, i, l, j ! Check N. ifault = 0 if (n < 1 .or. n > ncol+1-pos1) ifault = ifault + 4 if (ifault /= 0) return ! Work through VORDER finding variables which are in LIST. next = pos1; i = pos1 10 l = vorder(i) do j = 1, n; if (l == list(j)) go to 40; end do 30 i = i + 1 if (i <= ncol) go to 10 ! If this point is reached, one or more variables in LIST has not ! been found. ifault = 8 return ! Variable L is in LIST; move it up to position NEXT if it is not ! already there. 40 if (i > next) call vmove(i, next, ifault) next = next + 1 if (next < n+pos1) go to 30 return end subroutine reordr !===============================================
206
subroutine hdiag(xrow, nreq, hii, ifault) ! The hat matrix H = x(X'X) x' = x(R'DR) x' = z'Dz ! where z = x'R ! Here we only calculate the diagonal element hii corresponding to ! one row (xrow). The variance of the i-th least-squares residual is ! (1 - hii). !-------------------------------------------------------------------------- integer, intent(in) :: nreq integer, intent(out) :: ifault real (dp), dimension(:), intent(in) :: xrow real (dp), intent(out) :: hii !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- integer :: col, row, pos real (dp) :: total, wk(ncol) ! Some checks ifault = 0 if (nreq > ncol) ifault = ifault + 4 if (ifault /= 0) return ! The elements of xrow.inv(R).sqrt(D) are calculated ! and stored in WK. hii = zero do col = 1, nreq if (sqrt(d(col)) <= tol(col)) then wk(col) = zero else pos = col – 1; total = xrow(col) do row = 1, col-1 total = total - wk(row)*r(pos); pos = pos + ncol - row - 1 end do ! row = 1, col-1 wk(col) = total; hii = hii + total**2 / d(col) end if end do ! col = 1, nreq return end subroutine hdiag !===============================================
207
function varprd(x, nreq) result(fn_val) ! Calculate the variance of x'b where b consists of the first nreq ! least-squares regression coefficients. !-------------------------------------------------------------------------- integer, intent(in) :: nreq real (dp), dimension(:), intent(in) :: x real (dp) :: fn_val !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- integer :: ifault, row real (dp) :: var, wk(nreq) ! Check input parameter values fn_val = zero ifault = 0 if (nreq < 1 .or. nreq > ncol) ifault = ifault + 4 if (nobs <= nreq) ifault = ifault + 8 if (ifault /= 0) then write(*, '(1x, a, i4)') 'Error in function varprd: ifault =', ifault return end if ! Calculate the residual variance estimate. var = sserr / (nobs - nreq) ! Variance of x'b = var.x'(inv R)(inv D)(inv R')x ! First call BKSUB2 to calculate (inv R')x by back-substitution. call bksub2(x, wk, nreq) do row = 1, nreq if (d(row) > tol(row)) fn_val = fn_val + wk(row)**2 / d(row) end do fn_val = fn_val * var return end function varprd !=============================================== subroutine bksub2(x, b, nreq) ! Solve x = R'b for b given x, using only the first nreq rows and ! columns of R, and only the first nreq elements of R. !--------------------------------------------------------------------------
208
integer, intent(in) :: nreq real (dp), dimension(:), intent(in) :: x real (dp), dimension(:), intent(out) :: b !-------------------------------------------------------------------------- ! Local variables !-------------------------------------------------------------------------- integer :: pos, row, col real (dp) :: temp ! Solve by back-substitution, starting from the top. do row = 1, nreq pos = row - 1; temp = x(row) do col = 1, row-1 temp = temp - r(pos)*b(col); pos = pos + ncol - col - 1 end do ! col = 1, row-1 b(row) = temp end do ! row = 1, nreq return end subroutine bksub2 !===============End LSQ processing================= !=============================================== !===============Integration========================= subroutine simpson2(f,a,b,eps,integral,nint) !=============================================== ! Integration of f(x) on [a,b] ! Method: Simpson rule with doubling number of intervals ! till error = coeff*|I_n - I_2n| < eps !--------------------------------------------------------------------------------- ! IN: ! f - Function to integrate (supplied by a user) ! a - Lower limit of integration ! b - Upper limit of integration ! eps - tolerance ! OUT: ! integral - Result of integration ! nint - number of intervals to achieve accuracy !--------------------------------------------------------------------------------- integer, parameter :: nmax=1048576 ! max number of intervals
209
integer n, i, nint real(dp), parameter :: coeff = 1.0/15.0 ! error estimate coeff real(dp) :: f, a, b, eps, integral real(dp) :: sn, s2n, h, x ! Evaluate integral for 2 intervals (three points) h = (b-a)/2.0 sn = (1.0/3.0)*h*(f(a)+4.0*f(a+h)+f(b)) ! Loop over number of intervals (starting from 4 intervals) n=4 do while (n <= nmax) s2n = 0.0 h = (b-a)/dfloat(n) do i=2, n-2, 2 x = a+dfloat(i)*h s2n = s2n + 2.0*f(x) + 4.0*f(x+h) end do ! i=2, n-2, 2 s2n = (s2n + f(a) + f(b) + 4.0*f(a+h))*h/3.0 if (coeff*abs(s2n-sn) <= eps) then integral = s2n + coeff*(s2n-sn) nint = n exit end if sn = s2n n = n*2 end do ! while (n <= nmax) return end subroutine simpson2 !=============================================== subroutine gauss2(f,a,b,eps,integral,nint) !--------------------------------------------------------------------------------- ! Integration of f(x) on [a,b] ! Method: Gauss quadratures with doubling number of intervals ! till error = |I_16 - I_8| < eps !--------------------------------------------------------------------------------- ! IN: ! f - Function to integrate (supplied by a user) ! a - Lower limit of integration
210
! b - Upper limit of integration ! eps - tolerance ! OUT: ! integral - Result of integration ! nint - number of intervals to achieve accuracy !--------------------------------------------------------------------------------- integer, parameter :: nmax=16384 ! max number of intervals integer n, i, nint real(dp) :: f, a, b, eps, integral, gauss8, gauss16 real(dp) :: s1, s2, h, ax, bx external f ! Loop over number of intervals (starting from 1 interval) n=1 do while (n <= nmax) s1 = 0.0; s2 = 0.0 h = (b-a)/dfloat(n) do i=1, n ax = a+h*dfloat(i-1); bx = ax + h s1 = s1 + gauss8(f,ax,bx) s2 = s2 + gauss16(f,ax,bx) !write(*,101) i, ax, bx, s1, s2 !101 format(i5,4f15.5) end do ! i=1, n if (abs(s2-s1)<= eps .and. abs(s2-s1)/abs(s2+s1)<= eps) then integral = s2; nint = n exit end if integral = s2 nint = n; n = n*2 end do ! while (n <= nmax) return end subroutine gauss2 !=============================================== function gauss8(f,a,b) !--------------------------------------------------------------------------------- ! Integration of f(x) on [a,b]. Method: Gauss 8 points !---------------------------------------------------------------------------------
211
! IN: ! f - Function to integrate (supplied by a user) ! a - Lower limit of integration ! b - Upper limit of integration ! OUT: ! gauss8 - Result of integration !--------------------------------------------------------------------------------- integer, parameter :: n=4 integer i real(dp) :: gauss8, f, a, b real(dp) :: r, m, c real(dp) :: ti(n), ci(n) data ti/0.1834346424, 0.5255324099, 0.7966664774, & 0.9602898564/ data ci/0.3626837833, 0.3137066458, 0.2223810344, & 0.1012285362/ r = 0.0; m = (b-a)/2.0; c = (b+a)/2.0; do i = 1,n r = r + ci(i)*(f(m*(-1.0)*ti(i) + c) + f(m*ti(i) + c)) end do gauss8 = r*m return end function gauss8 !=============================================== function gauss16(f,a,b) !--------------------------------------------------------------------------------- ! Integration of f(x) on [a,b]. Method: Gauss 16 points !--------------------------------------------------------------------------------- ! IN: ! f - Function to integrate (supplied by a user) ! a - Lower limit of integration ! b - Upper limit of integration ! OUT: ! gauss16 - Result of integration !--------------------------------------------------------------------------------- integer, parameter :: n=8 integer i
212
real(dp) :: gauss16, f, a, b real(dp) :: ti(n), ci(n) real(dp) :: r, m, c data ti/0.0950125098, 0.2816035507, 0.4580167776, & 0.6178762444, 0.7554044083, 0.8656312023, & 0.9445750230, 0.9894009349/ data ci/0.1894506104, 0.1826034150, 0.1691565193, & 0.1495959888, 0.1246289712, 0.0951585116, & 0.0622535239, 0.0271524594/ r = 0.0; m = (b-a)/2.0; c = (b+a)/2.0; do i = 1,n r = r + ci(i)*(f(m*(-1.0)*ti(i) + c) + f(m*ti(i) + c)) end do gauss16 = r*m return end function gauss16 !==========End Integration========================= !==========Spline processing========================= subroutine spline (x, y, b, c, d, n) ! Calculate the coefficients b(i), c(i), and d(i), i=1,2,...,n ! for cubic spline interpolation ! s(x) = y(i) + b(i)*(x-x(i)) + c(i)*(x-x(i))**2 + d(i)*(x-x(i))**3 ! for x(i) <= x <= x(i+1) ! Input.. ! x = the arrays of data abscissas (in strictly increasing order) ! y = the arrays of data ordinates ! n = size of the arrays xi() and yi() (n>=2) ! Output.. ! b, c, d = arrays of spline coefficients !--------------------------------------------------------------------------------- integer n, i, j, gap real(dp) :: x(n), y(n), b(n), c(n), d(n) real(dp) :: h gap = n-1 ! Check input if ( n < 2 ) return if ( n < 3 ) then
213
b(1) = (y(2)-y(1))/(x(2)-x(1)) ! linear interpolation c(1) = 0.; d(1) = 0.; b(2) = b(1); c(2) = 0.; d(2) = 0. return end if ! Step 1: preparation d(1) = x(2) - x(1); c(2) = (y(2) - y(1))/d(1) do i = 2, gap d(i) = x(i+1) - x(i); b(i) = 2.0*(d(i-1) + d(i)) c(i+1) = (y(i+1) - y(i))/d(i); c(i) = c(i+1) - c(i) end do ! Step 2: end conditions b(1) = -d(1); b(n) = -d(n-1) c(1) = 0.0; c(n) = 0.0 if (n /= 3) then c(1) = c(3)/(x(4)-x(2)) - c(2)/(x(3)-x(1)) c(n) = c(n-1)/(x(n)-x(n-2)) - c(n-2)/(x(n-1)-x(n-3)) c(1) = c(1)*d(1)**2/(x(4)-x(1)); c(n) = -c(n)*d(n-1)**2/(x(n)-x(n-3)) end if ! Step 3: forward elimination do i = 2, n h = d(i-1)/b(i-1); b(i) = b(i) - h*d(i-1); c(i) = c(i) - h*c(i-1) end do ! Step 4: back substitution c(n) = c(n)/b(n) do j = 1, gap i = n-j; c(i) = (c(i) - d(i)*c(i+1))/b(i); end do ! Step 5: compute spline coefficients b(n) = (y(n) - y(gap))/d(gap) + d(gap)*(c(gap) + 2.0*c(n)) do i = 1, gap b(i) = (y(i+1) - y(i))/d(i) - d(i)*(c(i+1) + 2.0*c(i)) d(i) = (c(i+1) - c(i))/d(i); c(i) = 3.*c(i) end do c(n) = 3.0*c(n) d(n) = d(n-1) end subroutine spline !===============================================
214
function ispline(u, x, y, b, c, d, n) ! Function ispline evaluates the cubic spline interpolation at point z ! ispline = y(i)+b(i)*(u-x(i))+c(i)*(u-x(i))**2+d(i )*(u-x(i))**3 ! where x(i) <= u <= x(i+1) ! Input.. ! u = the abscissa at which the spline is to be evaluated ! x, y = the arrays of given data points ! b, c, d = arrays of spline coefficients computed by spline ! n = the number of data points ! Output: ! ispline = interpolated value at point u !--------------------------------------------------------------------------------- integer n, i, j, k real(dp) :: ispline real(dp) :: u, x(n), y(n), b(n), c(n), d(n) real(dp) :: dx ! If u is ouside the x() interval take a boundary value (left or right) if (u <= x(1)) then ispline = y(1) return end if if (u >= x(n)) then ispline = y(n) return end if ! Binary search for for i, such that x(i) <= u <= x(i+1) i = 1; j = n+1 do while (j > i+1) k = (i+j)/2 if (u < x(k)) then j=k else i=k end if end do ! while (j > i+1) ! Evaluate spline interpolation dx = u - x(i)
215
ispline = y(i) + dx*(b(i) + dx*(c(i) + dx*d(i))) end function ispline !=============END Spline processing============== !============================================ end module data_processing !============================================ !============================================ module ODE_sp_n_dp implicit none contains !============================================ subroutine rkf45 ( f, neqn, y, t, tout, relerr, abserr, iflag, & work, iwork ) ! RKF45 integrates a system of NEQN first order ordinary ! differential equations of the form: ! dY(i)/dT = F(T,Y(1),Y(2),...,Y(NEQN)) ! where the Y(1:NEQN) are given at T. !-------------------------------------------------------------------------- ! Input: ! external F, a subroutine of the form ! subroutine f ( t, y, yp ) ! real t ! real y(*) ! real yp(*) ! to evaluate the derivatives YP(I) = dY(I) / dT, ! NEQN - the number of equations to be integrated. ! Input/output, real Y(NEQN), the solution vector at T. ! Input/output, real T, the independent variable. ! Input, real TOUT, the output point at which solution is desired. ! Input, real RELERR, ABSERR, the relative and absolute error ! tolerances for the local error test. At each step the code ! requires: abs(local error) <= relerr*abs(y) + abserr ! for each component of the local error and solution vectors ! Output, integer IFLAG, indicator for status of integration. ! Workspace, real WORK(3+6*NEQN), an array to hold ! information internal to RKF45 which is necessary for ! subsequent calls.
216
! Workspace, integer IWORK(5), an array used to hold ! information internal to RKF45 which is necessary for ! subsequent calls. !-------------------------------------------------------------------------------- ! Output from rkf45 ! y(*) -- solution at t ! t -- last point reached in integration. ! iflag = 2 -- integration reached tout. indicates successful retur ! and is the normal mode for continuing integration. ! =-2 -- a single successful step in the direction of tout ! has been taken. normal mode for continuing ! integration one step at a time. ! = 3 -- integration was not completed because relative error ! tolerance was too small. relerr has been increased ! appropriately for continuing. ! = 4 -- integration was not completed because more than ! 3000 derivative evaluations were needed. this ! is approximately 500 steps. ! = 5 -- integration was not completed because solution ! vanished making a pure relative error test ! impossible. must use non-zero abserr to continue. ! using the one-step integration mode for one step ! is a good way to proceed. ! = 6 -- integration was not completed because requested ! accuracy could not be achieved using smallest ! allowable stepsize. user must increase the error ! tolerance before continued integration can be ! attempted. ! = 7 -- it is likely that rkf45 is inefficient for solving ! this problem. too much output is restricting the ! natural stepsize choice. use the one-step integrator ! mode. ! = 8 -- invalid input parameters ! this indicator occurs if any of the following is ! satisfied - neqn <= 0 ! t=tout and iflag /= +1 or -1 ! relerr or abserr < 0.
217
! iflag == 0 or < -2 or > 8 ! work(*),iwork(*) -- information which is usually of no interest ! to the user but necessary for subsequent calls. ! work(1),...,work(neqn) contain the first derivatives ! of the solution vector y at t. work(neqn+1) contains ! the stepsize h to be attempted on the next step. ! iwork(1) contains the derivative evaluation counter. integer neqn integer iflag, k1, k1m, k2, k3, k4, k5, k6 integer iwork(5) real abserr, relerr, t, tout real y(neqn), work(6*neqn+3) external f ! Compute indices for the splitting of the work array k1m = neqn + 1 k1 = k1m + 1 k2 = k1 + neqn k3 = k2 + neqn k4 = k3 + neqn k5 = k4 + neqn k6 = k5 + neqn ! This interfacing routine merely relieves the user of a long ! calling list via the splitting apart of two working storage arrays. !------------------------------------------------------------------------------ call rkfs ( f, neqn, y, t, tout, relerr, abserr, iflag, work(1), & work(k1m), work(k1), work(k2), work(k3), work(k4), & work(k5), work(k6), work(k6+1), & iwork(1), iwork(2), iwork(3), iwork(4), iwork(5) ) !------------------------------------------------------------------------------ return end subroutine rkf45 !============================================ subroutine rkf45_d ( f, neqn, y, t, tout, relerr, abserr, iflag, &
work, iwork ) ! RKF45_D carries out the Runge-Kutta-Fehlberg method ! (double precision). integer neqn, iflag, k1, k1m, k2, k3, k4, k5, k6
218
integer iwork(5) real(8) :: abserr, relerr, t, tout real(8) :: y(neqn), work(6*neqn+3) external f ! Compute indices for the splitting of the work array k1m = neqn + 1 k1 = k1m + 1 k2 = k1 + neqn k3 = k2 + neqn k4 = k3 + neqn k5 = k4 + neqn k6 = k5 + neqn ! This interfacing routine merely relieves the user of a long ! calling list via the splitting apart of two working storage arrays. !------------------------------------------------------------------------------ call rkfs_d ( f, neqn, y, t, tout, relerr, abserr, iflag, work(1), & work(k1m), work(k1), work(k2), work(k3), & work(k4), work(k5), work(k6), work(k6+1), & iwork(1), iwork(2), iwork(3), iwork(4), iwork(5) ) !------------------------------------------------------------------------------ return end subroutine rkf45_d !============================================ subroutine rkfs ( f, neqn, y, t, tout, relerr, abserr, iflag, yp, h, & f1, f2, f3, f4, f5, savre, savae, & nfe, kop, init, jflag, kflag ) ! RKFS implements the Runge-Kutta-Fehlberg method ! (single precision). ! RKFS integrates a system of first order ordinary differential ! equations as described in the comments for RKF45. integer neqn integer, parameter :: maxnfe = 3000 integer iflag, init, jflag, k, kflag, kop, mflag, nfe real, parameter :: remin = 1.0E-12 real a, abserr, relerr, ae, dt, ee, eeoet, eps, esttol, et, h, hmin real rer, s, savae, savre, scale, t, tol, toln, tout, ypk real, dimension(neqn) :: f1, f2, f3, f4, f5, y, yp
219
logical hfaild, output external f ! Check the input parameters. eps = epsilon ( eps ) if ( neqn < 1 ) then iflag = 8; return end if if ( relerr < 0.0E+00 ) then iflag = 8; return end if if ( abserr < 0.0E+00 ) then iflag = 8; return end if mflag = abs ( iflag ) if ( abs ( iflag ) < 1 .or. abs ( iflag ) > 8 ) then iflag = 8; return end if ! Is this the first call? if ( mflag == 1 ) go to 50 !--------------------------------------------------------------------- ! Check continuation possibilities if ( t == tout .and. kflag /= 3 ) then iflag = 8; return end if if ( mflag /= 2 ) go to 25 ! iflag = +2 or -2 if ( kflag == 3 ) go to 45 if ( init == 0 ) go to 45 if ( kflag == 4 ) go to 40 if ( kflag == 5 .and. abserr == 0.0E+00 ) stop if ( kflag == 6 .and. relerr <= savre .and. abserr <= savae ) stop go to 50 ! iflag = 3,4,5,6,7 or 8 25 continue if ( iflag == 3 ) go to 45 if ( iflag == 4 ) go to 40 if ( iflag == 5 .and. abserr > 0.0E+00 ) go to 45
220
! Integration cannot be continued since user did not respond to ! the instructions pertaining to iflag=5,6,7 or 8 stop ! Reset function evaluation counter 40 continue nfe = 0 if ( mflag == 2 ) go to 50 ! Reset flag value from previous call 45 continue iflag = jflag if ( kflag == 3 ) mflag = abs ( iflag ) ! Save input iflag and set continuation flag for subsequent ! input checking. 50 continue jflag = iflag; kflag = 0 ! Save relerr and abserr for checking input on subsequent calls savre = relerr savae = abserr ! Restrict relative error tolerance to be at least as large as ! 2*eps+remin to avoid limiting precision difficulties arising ! from impossible accuracy requests rer = 2.0E+00 * epsilon ( rer ) + remin ! The relative error tolerance is too small. if ( relerr < rer ) then relerr = rer; iflag = 3; kflag = 3 return end if dt = tout - t if ( mflag == 1 ) go to 60 if ( init == 0 ) go to 65 go to 80 ! Initialization: ! set initialization completion indicator, init ! set indicator for too many output points, kop ! evaluate initial derivatives ! set counter for function evaluations, nfe ! evaluate initial derivatives
221
! set counter for function evaluations, nfe ! estimate starting stepsize 60 continue init = 0; kop = 0; a = t call f ( a, y, yp ) nfe = 1 if ( t == tout ) then iflag = 2; return end if 65 continue init = 1 h = abs ( dt ); toln = 0.0E+00 do k = 1, neqn tol = relerr * abs ( y(k) ) + abserr if ( tol > 0.0E+00 ) then toln = tol; ypk = abs ( yp(k) ) if ( ypk * h**5 > tol) then h = ( tol / ypk )**0.2E+00 end if end if end do ! k = 1, neqn if ( toln <= 0.0E+00 ) h = 0.0E+00 h = max ( h, 26.0E+00 * eps * max ( abs ( t ), abs ( dt ) ) ) jflag = sign ( 2, iflag ) ! Set stepsize for integration in the direction from T to TOUT. 80 continue h = sign ( h, dt ) ! Test to see if RKF45 is being severely impacted by too ! many output points. if ( abs ( h ) >= 2.0E+00 * abs ( dt ) ) kop = kop + 1 ! Unnecessary frequency of output. if ( kop == 100 ) then kop = 0; iflag = 7; return end if ! If too close to output point, extrapolate and return. if ( abs ( dt ) <= 26.0E+00 * eps * abs ( t ) ) then y(1:neqn) = y(1:neqn) + dt * yp(1:neqn)
222
a = tout call f ( a, y, yp ) nfe = nfe + 1 ; t = tout; iflag = 2 return end if ! Initialize output point indicator. output = .false. ! To avoid premature underflow in the error tolerance function, ! scale the error tolerances scale = 2.0E+00 / relerr ae = scale * abserr ! Step by step integration. 100 continue hfaild = .false. ! Set smallest allowable stepsize. hmin = 26.0E+00 * eps * abs ( t ) ! Adjust stepsize if necessary to hit the output point. ! Look ahead two steps to avoid drastic changes in the stepsize and ! thus lessen the impact of output points on the code. dt = tout - t if ( abs ( dt ) >= 2.0E+00 * abs ( h ) ) go to 200 ! The next successful step will complete the integration ! to the output point. if ( abs ( dt ) <= abs ( h ) ) then output = .true.; h = dt go to 200 end if h = 0.5E+00 * dt ! Core integrator for taking a single step ! Test number of derivative function evaluations. ! If okay, try to advance the integration from T to T+H. 200 continue if ( nfe > maxnfe ) then iflag = 4; kflag = 4; return end if ! Advance an approximate solution over one step of length H. call fehl ( f, neqn, y, t, h, yp, f1, f2, f3, f4, f5, f1 )
223
nfe = nfe + 5 ! Compute and test allowable tolerances versus local error ! estimates and remove scaling of tolerances. Note that relative ! error is measured with respect to the average of the magnitudes of ! the solution at the beginning and end of the step. eeoet = 0.0E+00 do k = 1, neqn et = abs ( y(k) ) + abs ( f1(k) ) + ae if ( et <= 0.0E+00 ) then iflag = 5; return end if ee = abs ( ( -2090.0E+00 * yp(k) + ( 21970.0E+00 * f3(k) & - 15048.0E+00 * f4(k) ) ) + ( 22528.0E+00 * f2(k) & - 27360.0E+00 * f5(k) ) ) eeoet = max ( eeoet, ee / et ) end do ! k = 1, neqn esttol = abs ( h ) * eeoet * scale / 752400.0E+00 if ( esttol <= 1.0E+00 ) go to 260 ! Unsuccessful step. Reduce the stepsize, try again. ! The decrease is limited to a factor of 1/10. hfaild = .true.; output = .false. if ( esttol < 59049.0E+00 ) then s = 0.9E+00 / esttol**0.2E+00 else s = 0.1E+00 end if h = s * h if ( abs ( h ) < hmin ) then iflag = 6; kflag = 6; return else go to 200 end if ! Successful step. Store solution at T+H and evaluate ! derivatives there. 260 continue t = t + h; y(1:neqn) = f1(1:neqn); a = t call f ( a, y, yp )
224
nfe = nfe + 1 ! Choose next stepsize. The increase is limited to a factor of 5. ! If step failure has just occurred, next stepsize is not allowed ! to increase if ( esttol > 0.0001889568E+00 ) then s = 0.9E+00 / esttol**0.2E+00 else s = 5.0E+00 end if if ( hfaild ) s = min ( s, 1.0E+00 ) h = sign ( max ( s * abs ( h ), hmin ), h ) ! End of core integrator. Should we take another step? if ( output ) then t = tout; iflag = 2 end if if ( iflag > 0 ) go to 100 ! Integration successfully completed ! one-step mode iflag = - 2 return end subroutine rkfs !============================================ subroutine rkfs_d ( f, neqn, y, t, tout, relerr, abserr, iflag, yp, h, & f1, f2, f3, f4, f5, savre, savae, nfe, kop, init, jflag, kflag ) ! RKFS_D implements the Runge-Kutta-Fehlberg method ! (double precision). integer neqn integer, parameter :: maxnfe = 3000 integer iflag, init, jflag, k, kflag, kop, mflag, nfe double precision, parameter :: remin = 1.0D-12 real(8) :: a, abserr, relerr, ae, dt, ee, eeoet, eps, esttol, et, h, hmin real(8) :: rer, s, savae, savre, scale, t, tol, toln, tout, ypk real(8),dimension(neqn) :: f1, f2, f3, f4, f5, y, yp logical hfaild, output external f !---------------------------------------begin---------------------------------- ! Check the input parameters.
225
eps = epsilon ( eps ) if ( neqn < 1 ) then iflag = 8; return end if if ( relerr < 0.0D+00 ) then iflag = 8; return end if if ( abserr < 0.0D+00 ) then iflag = 8; return end if mflag = abs ( iflag ) if ( abs ( iflag ) < 1 .or. abs ( iflag ) > 8 ) then iflag = 8; return end if ! Is this the first call? if ( mflag == 1 ) go to 50 ! Check continuation possibilities if ( t == tout .and. kflag /= 3 ) then iflag = 8; return end if if ( mflag /= 2 ) go to 25 ! iflag = +2 or -2 if ( kflag == 3 ) go to 45 if ( init == 0 ) go to 45 if ( kflag == 4 ) go to 40 if ( kflag == 5 .and. abserr == 0.0D+00 ) stop if ( kflag == 6 .and. relerr <= savre .and. abserr <= savae ) stop go to 50 ! iflag = 3,4,5,6,7 or 8 25 continue if ( iflag == 3 ) go to 45 if ( iflag == 4 ) go to 40 if ( iflag == 5 .and. abserr > 0.0D+00 ) go to 45 ! Integration cannot be continued since user did not respond to ! the instructions pertaining to iflag=5,6,7 or 8 stop ! Reset function evaluation counter
226
40 continue nfe = 0 if ( mflag == 2 ) go to 50 ! Reset flag value from previous call 45 continue iflag = jflag if ( kflag == 3 ) mflag = abs ( iflag ) ! Save input iflag and set continuation flag for subsequent ! input checking. 50 continue jflag = iflag; kflag = 0 ! Save relerr and abserr for checking input on subsequent calls savre = relerr; savae = abserr ! Restrict relative error tolerance to be at least as large as ! 2*eps+remin to avoid limiting precision difficulties arising ! from impossible accuracy requests rer = 2.0D+00 * epsilon ( rer ) + remin ! The relative error tolerance is too small. if ( relerr < rer ) then relerr = rer iflag = 3; kflag = 3; return end if dt = tout - t if ( mflag == 1 ) go to 60 if ( init == 0 ) go to 65 go to 80 ! Initialization: ! set initialization completion indicator, init ! set indicator for too many output points, kop ! evaluate initial derivatives ! set counter for function evaluations, nfe ! evaluate initial derivatives ! set counter for function evaluations, nfe ! estimate starting stepsize 60 continue init = 0; kop = 0; a = t
227
call f ( a, y, yp ) nfe = 1 if ( t == tout ) then iflag = 2; return end if 65 continue init = 1 h = abs ( dt ); toln = 0.0D+00 do k = 1, neqn tol = relerr * abs ( y(k) ) + abserr if ( tol > 0.0D+00 ) then toln = tol ypk = abs ( yp(k) ) if ( ypk * h**5 > tol) h = ( tol / ypk )**0.2D+00 end if end do ! k = 1, neqn if ( toln <= 0.0D+00 ) h = 0.0D+00 h = max ( h, 26.0D+00 * eps * max ( abs ( t ), abs ( dt ) ) ) jflag = sign ( 2, iflag ) ! Set stepsize for integration in the direction from T to TOUT. 80 continue h = sign ( h, dt ) ! Test to see if RKF45 is being severely impacted by too ! many output points. if ( abs ( h ) >= 2.0D+00 * abs ( dt ) ) kop = kop + 1 ! Unnecessary frequency of output. if ( kop == 100 ) then kop = 0; iflag = 7; return end if ! If too close to output point, extrapolate and return. if ( abs ( dt ) <= 26.0D+00 * eps * abs ( t ) ) then y(1:neqn) = y(1:neqn) + dt * yp(1:neqn) a = tout call f ( a, y, yp ) nfe = nfe + 1; t = tout; iflag = 2 return end if
228
! Initialize output point indicator. output = .false. ! To avoid premature underflow in the error tolerance function, ! scale the error tolerances scale = 2.0D+00 / relerr ae = scale * abserr ! Step by step integration. 100 continue hfaild = .false. ! Set smallest allowable stepsize. hmin = 26.0D+00 * eps * abs ( t ) ! Adjust stepsize if necessary to hit the output point. ! Look ahead two steps to avoid drastic changes in the stepsize and ! thus lessen the impact of output points on the code. dt = tout - t if ( abs ( dt ) >= 2.0D+00 * abs ( h ) ) go to 200 ! The next successful step will complete the integration ! to the output point. if ( abs ( dt ) <= abs ( h ) ) then output = .true.; h = dt go to 200 end if h = 0.5D+00 * dt ! Test number of derivative function evaluations. ! If okay, try to advance the integration from T to T+H. 200 continue if ( nfe > maxnfe ) then iflag = 4; kflag = 4; return end if ! Advance an approximate solution over one step of length H. call fehl_d ( f, neqn, y, t, h, yp, f1, f2, f3, f4, f5, f1 ) nfe = nfe + 5 ! Compute and test allowable tolerances versus local error ! estimates and remove scaling of tolerances. Note that relative ! error is measured with respect to the average of the magnitudes of ! the solution at the beginning and end of the step. eeoet = 0.0D+00
229
do k = 1, neqn et = abs ( y(k) ) + abs ( f1(k) ) + ae if ( et <= 0.0D+00 ) then iflag = 5; return end if ee = abs ( ( -2090.0D+00 * yp(k) + ( 21970.0D+00 * f3(k) & - 15048.0D+00 * f4(k) ) ) & + ( 22528.0D+00 * f2(k) - 27360.0D+00 * f5(k) ) ) eeoet = max ( eeoet, ee / et ) end do ! k = 1, neqn esttol = abs ( h ) * eeoet * scale / 752400.0D+00 if ( esttol <= 1.0D+00 ) go to 260 ! Unsuccessful step. Reduce the stepsize, try again. ! The decrease is limited to a factor of 1/10. hfaild = .true.; output = .false. if ( esttol < 59049.0D+00 ) then s = 0.9D+00 / esttol**0.2D+00 else s = 0.1D+00 end if h = s * h if ( abs ( h ) < hmin ) then iflag = 6; kflag = 6; return else go to 200 end if ! Successful step. Store solution at T+H and evaluate ! derivatives there. 260 continue t = t + h; y(1:neqn) = f1(1:neqn); a = t call f ( a, y, yp ) nfe = nfe + 1 ! Choose next stepsize. The increase is limited to a factor of 5. if ( esttol > 0.0001889568D+00 ) then s = 0.9D+00 / esttol**0.2D+00 else s = 5.0D+00
230
end if if ( hfaild ) s = min ( s, 1.0D+00 ) h = sign ( max ( s * abs ( h ), hmin ), h ) ! End of core integrator ! Should we take another step? if ( output ) then t = tout; iflag = 2 end if if ( iflag > 0 ) go to 100 ! Integration successfully completed ! one-step mode iflag = - 2 return end subroutine rkfs_d !============================================ subroutine fehl ( f, neqn, y, t, h, yp, f1, f2, f3, f4, f5, s ) ! FEHL takes one Fehlberg fourth-fifth order step ! (single precision). ! Input, external F, a subroutine of the form ! subroutine f(t,y,yp) ! to evaluate the derivatives. ! YP(I) = dY(I) / dT ! Input, integer NEQN, the number of equations to be integrated. ! Input, real Y(NEQN), the current value of the dependent ! variable. ! Input, real T, the current value of the independent variable. ! Input, real H, the step size to take. ! Input, real YP(NEQN), the current value of the derivative of the ! dependent variable. ! Output, real F1(NEQN), real F2(NEQN), real F3(NEQN), ! real F4(NEQN), ! real F5(NEQN) are arrays of dimension NEQN which are ! needed for internal storage. ! Output, real S(NEQN), the computed estimate of the solution ! at T+H. integer neqn
231
real ch, h, t real,dimension(neqn) :: f1, f2, f3, f4, f5, s, y, yp external f !------------------------------begin----------------------------------------- ch = h / 4.0E+00 f5(1:neqn) = y(1:neqn) + ch * yp(1:neqn) call f ( t + ch, f5, f1 ) ch = 3.0E+00 * h / 32.0E+00 f5(1:neqn) = y(1:neqn) + ch * ( yp(1:neqn) + 3.0E+00 * & f1(1:neqn) ) call f ( t + 3.0E+00 * h / 8.0E+00, f5, f2 ) ch = h / 2197.0E+00 f5(1:neqn) = y(1:neqn) + ch * ( 1932.0E+00 * yp(1:neqn) & + ( 7296.0E+00 * f2(1:neqn) - 7200.0E+00 * f1(1:neqn) ) ) call f ( t + 12.0E+00 * h / 13.0E+00, f5, f3 ) ch = h / 4104.0E+00 f5(1:neqn) = y(1:neqn) + ch * ( ( 8341.0E+00 * yp(1:neqn) & - 845.0E+00 * f3(1:neqn) ) + ( 29440.0E+00 * f2(1:neqn) & - 32832.0E+00 * f1(1:neqn) ) ) call f ( t + h, f5, f4 ) ch = h / 20520.0E+00 f1(1:neqn) = y(1:neqn) + ch * ( ( -6080.0E+00 * yp(1:neqn) & + ( 9295.0E+00 * f3(1:neqn) - 5643.0E+00 * f4(1:neqn) ) ) & + ( 41040.0E+00 * f1(1:neqn) - 28352.0E+00 * f2(1:neqn) ) ) call f ( t + h / 2.0E+00, f1, f5 ) ! Ready to compute the approximate solution at T+H. ch = h / 7618050.0E+00 s(1:neqn) = y(1:neqn) + ch * ( ( 902880.0E+00 * yp(1:neqn) & +( 3855735.0E+00*f3(1:neqn) - 1371249.0E+00*f4(1:neqn))) & + ( 3953664.0E+00 * f2(1:neqn) + 277020.0E+00 * f5(1:neqn))) return end subroutine fehl !=============================================== subroutine fehl_d ( f, neqn, y, t, h, yp, f1, f2, f3, f4, f5, s ) ! FEHL_D takes one Fehlberg fourth-fifth order step ! (double precision). integer neqn
232
real(8) :: ch, h, t real(8),dimension(neqn) :: f1, f2, f3, f4, f5, y, yp, s external f !-----------------------------begin------------------------------------------ ch = h / 4.0D+00 f5(1:neqn) = y(1:neqn) + ch * yp(1:neqn) call f ( t + ch, f5, f1 ) ch = 3.0D+00 * h / 32.0D+00 f5(1:neqn) = y(1:neqn) + ch * ( yp(1:neqn) + 3.0D+00 * & f1(1:neqn) ) call f ( t + 3.0D+00 * h / 8.0D+00, f5, f2 ) ch = h / 2197.0D+00 f5(1:neqn) = y(1:neqn) + ch * ( 1932.0D+00 * yp(1:neqn) & + ( 7296.0D+00 * f2(1:neqn) - 7200.0D+00 * f1(1:neqn) ) ) call f ( t + 12.0D+00 * h / 13.0D+00, f5, f3 ) ch = h / 4104.0D+00 f5(1:neqn) = y(1:neqn) + ch * ( ( 8341.0D+00 * yp(1:neqn) & - 845.0D+00 * f3(1:neqn) ) + ( 29440.0D+00 * f2(1:neqn) & - 32832.0D+00 * f1(1:neqn) ) ) call f ( t + h, f5, f4 ) ch = h / 20520.0D+00 f1(1:neqn) = y(1:neqn) + ch * ( ( -6080.0D+00 * yp(1:neqn) & + ( 9295.0D+00 * f3(1:neqn) - 5643.0D+00 * f4(1:neqn) ) ) & + ( 41040.0D+00 * f1(1:neqn) - 28352.0D+00 * f2(1:neqn) ) ) call f ( t + h / 2.0D+00, f1, f5 ) ! Ready to compute the approximate solution at T+H. ch = h / 7618050.0D+00 s(1:neqn) = y(1:neqn) + ch * ( ( 902880.0D+00 * yp(1:neqn) & + (3855735.0D+00*f3(1:neqn) - 1371249.0D+00*f4(1:neqn))) & + ( 3953664.0D+00 * f2(1:neqn) + 277020.0D+00 * f5(1:neqn))) return end subroutine fehl_d !=====================end rkf45.f90================= !================Adams-Bashforth method============= subroutine DE21(DS, X, Xout, H, Eps, Y, Error) interface
233
subroutine DS(X, Y, DY) real, intent(in) :: X, Y(:) real :: DY(:) end subroutine DS end interface real, intent(in) :: Xout real, intent(inout) :: X, H, Eps, Y(:) integer :: i, j, k, M, N, Count, Error integer, parameter :: Order=4 real, parameter :: C1=0.5, C2=5.0/12.0, C3=0.375 real, parameter :: P=-19.0/720.0 real, parameter :: ARB=0.001, OneP=1.000001, EEE=0.0625 real, allocatable :: Y0(:), YH(:), DY(:), F(:), DF(:,:), W(:) real :: HM4, X0, XH, DX, Hmin, SaveH, R, E, E32, Err, D logical :: HChange !-----------------------------begin--------------------------------------- if (X==Xout) then H=0.0; Error=1; return end if M=size(Y); allocate(F(M)) HM4=4.0*epsilon(1.0) if (abs(X)>ARB) then; Hmin=HM4*abs(X) else; Hmin=HM4*ARB end if DX=Xout-X if (abs(DX)<float(Order)*Hmin) then H=DX call DS(X, Y, F) Y(:)=Y(:)+DX*F(:) deallocate(F) X=Xout; Error=1; return end if if (Eps<EEE*epsilon(1.0)) then Eps=EEE*epsilon(1.0) deallocate(F) Error=2; return end if
234
if (abs(H)<Hmin) H=Hmin if (float(Order)*abs(H)>abs(DX)) then H=DX/float(Order) else; H=sign(H, DX) end if allocate(DF(1:M,0:Order), DY(M), Y0(M), YH(M), W(M)) call DE19(DS, X, Y, H, M, Order, DF, XH, YH, Err) X0=X; Y0=Y !--------Main procedure----------------------------------------------- call AdamsOneStep(DS, X0, Y0, H, M, Order, DF, Y, Err) if (Err>Eps) then Y=Y0; deallocate(F, DF, DY, Y0, YH, W) Error=3; return end if X=X0+H; E=Eps/(-P); E32=E*0.03125 N=0; Count=0; Error=0 HChange=.false. 10 continue X0=X; Y0(:)=Y(:) 20 continue X=X0+H Y(:)=Y0(:)+DF(:,0)+C1*DF(:,1)+C2*DF(:,2)+C3*DF(:,3) call DS(X, Y, F) F(:)=H*F(:) DY(:)=DF(:,0)+DF(:,1)+DF(:,2)+DF(:,3)-F(:) Y(:)=Y(:)-C3*DY(:) DY(:)=P*DY(:) do i=1, M if (abs(Y(i))>ARB) then; D=abs(Y(i)) else; D=ARB end if D=abs(DY(i))/D if (D>E) goto 30 end do ! i=1, M goto 40 30 continue if (abs(X0)>ARB) then; Hmin=HM4*abs(X0)
235
else; Hmin=HM4*ARB end if if (abs(H)<Hmin*OneP) then X=X0; Y=Y0 deallocate(Y0, YH, DY, F, DF, W) Error=65; return end if N=0; Count=0 R=0.5; H=0.5*H if (abs(H)<Hmin) then H=sign(Hmin, H); R=H/(X-X0) end if call DE21P(M, Order, R, DF, DF) goto 20 40 continue do j=0, Order-1 W(:)=DF(:,j); DF(:,j)=F(:); F(:)=F(:)-W(:) end do DF(:,Order)=F(:) Y(:)=Y(:)+P*F(:) if (N>0) then N=N-1 if (N==0) then deallocate (Y0, YH, DY, F, DF, W) H=SaveH; return end if goto 10 end if do i=1, M if (abs(DY(i)/Y(i))>E32) then Count=0; goto 50 end if end do Count=Count+1 if (Count==Order) then Count=0 R=2.0; H=2.0*H
236
HChange=.true. end if 50 continue DX=Xout-X if (2.0*abs(H) > abs(DX)) then SaveH=H; HChange=.true. if (abs(H)>=abs(DX)) then R=DX/H; H=DX; N=1 else R=(0.5*DX)/H; H=0.5*DX; N=2 end if end if if (HChange) then HChange=.false. call DE21P(M, Order, R, DF, DF) end if goto 10 !----------------------------------------------------------------------------- contains !============================================== subroutine AdamsOneStep(DS, X0, Y0, H, M, Order, DF, Y, Err) interface subroutine DS(X, Y, DY) real, intent(in) :: X, Y(:) real :: DY(:) end subroutine DS end interface integer, intent(in) :: M, Order real, intent(in) :: X0, Y0(M), H real, intent(inout) :: DF(1:M,0:Order) integer, parameter :: ARB=0.001, MaxOrder=6 integer :: j real :: Y(M), Err, X real, allocatable :: DY(:), F(:), W(:) real, parameter :: C(0:MaxOrder-1)=(/1.0, 0.5, 5.0/12.0, & 0.375, 251.0/720.0, 95.0/288.0/) real, parameter :: P(MaxOrder)=(/-0.5, -1.0/12.0, -1.0/24.0, &
237
-19.0/720.0, -3.0/160.0, -863.0/60480.0/) !-------------------------------begin------------------------------- allocate (DY(M), F(M), W(M)) X=X0+H Y(:)=Y0(:)+DF(:,0); DY(:)=DF(:,0) do j=1, Order-1 Y(:)=Y(:)+C(j)*DF(:,j) DY(:)=DY(:)+DF(:,j) end do ! j=1, Order-1 call DS(X, Y, F) F(:)=H*F(:) Y(:)=Y(:)-C(Order-1)*DY(:)+C(Order-1)*F(:) do j=0, Order-1 W(:)=DF(:,j); DF(:,j)=F(:); F(:)=F(:)-W(:) end do ! j=0, Order-1 DF(:,Order)=F(:) Y(:)=Y(:)+P(Order)*F(:); Err=0.0 do i=1, M if (abs(Y(i))>ARB) then; R=abs(Y(i)) else; R=ARB end if R=abs(F(i))/R if (Err<R) Err=R end do ! i=1, M Err=-P(Order)*Err; deallocate (DY, F, W) return end subroutine AdamsOneStep !============================================== subroutine DE21P(M, Order, R, DFin, DFout) integer, intent(in) :: M, Order real, intent(in) :: R, DFin(1:M,0:Order) integer :: i, j, k, k1 real :: DFout(1:M,0:Order) real, allocatable :: S(:) real :: Rm1, C(21) !-------------------------------begin-------------------------------------------
238
if (R==1.0) return if (R==0.5) then C(1)=0.25 if (Order>=2) then C(2)=0.0625; C(3)=0.125 if (Order>=3) then C(4)=0.03125; C(5)=0.0625; C(6)=0.0625 if (Order>=4) then C(7)=5.0/256.0; C(8)=5.0/128.0 C(9)=3.0/64.0; C(10)=0.03125 if (Order>=5) then C(11)=7.0/512.0; C(12)=7.0/256.0; C(13)=9.0/256.0 C(14)=0.03125; C(15)=0.015625 else C(16)=21.0/2048.0; C(17)=21.0/1024.0 C(18)=7.0/256.0; C(19)=7.0/256.0 C(20)=5.0/256.0; C(21)=0.0078125 end if; end if; end if; end if else if (R==2.0) then C(1)=4.0 if (Order>=2) then C(2)=-2.0; C(3)=8.0 if (Order>=3) then C(4)=0.0; C(5)=-8.0; C(6)=16.0 if (Order>=4) then C(7)=0.0; C(8)=2.0; C(9)=-24.0; C(10)=32.0 if (Order>=5) then C(11)=0.0; C(12)=0.0; C(13)=12.0 C(14)=-64.0; C(15)=64.0 else C(16)=0.0; C(17)=0.0; C(18)=-2.0; C(19)=48.0 C(20)=-160.0; C(21)=128.0 end if; end if; end if; end if else C(1)=R*R if (Order>=2) then Rm1=R-1.0
239
C(2)=-0.5*C(1)*Rm1; C(3)=C(1)*R if (Order>=3) then C(4)=-(1.0/3.0)*C(2)*(R-2.0) C(5)=-C(3)*Rm1; C(6)=C(3)*R if (Order>=4) then C(7)=-0.25*C(4)*(R-3.0) C(8)=-(7.0/12.0)*C(5)*(R-(11.0/7.0)) C(9)=-1.5*C(6)*Rm1; C(10)=C(6)*R if (Order>=5) then C(11)=-0.2*C(7)*(R-4.0) C(12)=-1.5*C(4)*R*(R-(5.0/3.0)) C(13)=-(5.0/6.0)*C(9)*(R-1.4); C(14)=-2.0*C(10)*Rm1 C(15)=C(10)*R else C(16)=-(1.0/6.0)*C(11)*(R-5.0) C(17)=(31.0/60.0)*C(4)*R*((R-(132.0/31.0))*R+(137.0/31.0)) C(18)=0.5*C(9)*((R-(19.0/6.0))*R+2.5) C(19)=-(13.0/12.0)*C(14)*(R-(17.0/13.0)) C(20)=-2.5*C(15)*Rm1; C(21)=C(15)*R end if; end if; end if; end if end if allocate (S(M)) DFout(:,0)=DFin(:,0)*R do j=1, Order S(:)=0.0 do k=j, Order k1=k*(k-1)/2+j S(:)=S(:)+C(k1)*DFin(:,k) end do ! k=j, Order DFout(:,j)=S(:) end do ! j=1, Order deallocate (S) return end subroutine DE21P end subroutine DE21 !============================================== subroutine DE19(DS, X0, Y0, H, M, Order, DF, XH, YH, Err)
240
interface subroutine DS(X, Y, DY) real, intent(in) :: X, Y(:) real :: DY(:) end subroutine DS end interface integer, intent(in) :: M, Order real, intent(in) :: X0, Y0(M), H integer, parameter :: MaxOrder=6 integer :: i, j, k, n, p, Morder real, parameter :: ARB=0.001 real, parameter :: C(MaxOrder)=(/0.5, 5.0/12.0, 0.375, & 251.0/720.0, 95.0/288.0, 19087.0/60480.0/) real, parameter :: D((MaxOrder*(MaxOrder-1))/2)= & (/-2.,-3.,3.,-4.,5.,-4.,-5.,10.,-10.,5.,-6.,15.,-20.,15.,-6./) real, allocatable :: X(:), F0(:), F(:), S(:), W(:) real :: DF(1:M, 0:Order) real :: XH, YH(M), Err, R !--------------------------------begin----------------------------------------- Morder=Order if (Morder>MaxOrder) Morder=MaxOrder allocate(X(Morder), F0(M), F(M), S(M), W(M)) do n=1, Morder; X(n)=X0+H*float(n); end do XH=X(Morder) call DS(X0, Y0, F0) F0(:)=H*F0(:); DF(:,0)=F0(:) do n=1, Morder YH(:)=Y0(:) do k=1, n S(:)=YH(:)+DF(:,0) do j=1, n-1; S(:)=S(:)+C(j)*DF(:,j); end do YH(:)=S(:) call DS(X(k), YH, F) F(:)=H*F(:) do j=0, k-1; W(:)=DF(:,j); DF(:,j)=F(:); F(:)=F(:)-W(:); end do DF(:,k)=F(:) end do ! k=1, n
241
DF(:,0)=F0(:) do k=1, n-1 p=(n-1)*(n-2)/2-k; S(:)=DF(:,k) do j=k+1, n; S(:)=S(:)+D(p+j)*DF(:,j); end do DF(:,k)=S(:) end do ! k=1, n-1 end do ! n=1, Morder Err=0.0 do i=1, M if (abs(Y0(i))>ARB) then; R=abs(Y0(i)) else; R=ARB end if R=abs(F(i))/R if (Err<R) Err=R end do ! i=1, M Err=C(Morder)*Err deallocate (X, F0, F, S, W) return end subroutine DE19 !============================================== !===========end of Adams-Bashforth method============ end module ODE_sp_n_dp
242
Список літератури, що пропонується для вивчення :
а) основна:
1. Бартеньев, О.В., ФОРТРАН для профессионалов. Математическая библиотека IMSL. Части 1,2,3 / О.В. Бартеньев.− М.: "Диалог-МИФИ".− 2000-2001.
2. Бурківська, В.Л., Методи обчислень. Практикум на ЕОМ / В. Л. Бурківська, С. О. Войцехівський, І. П. Гаврилюк.– К. : Вища школа.− 1995.
3. Волков, Е.А., Численные методы / Е.А. Волков.– М. : Наука, 1987.
4. Воробьева, Г.Н., Практикум по численным методам / Г.Н. Воробьева, А.Н. Данилова.– М.: Высшая школа.– 1979.
5. Каліон, В.А., Обчислювальна гідромеханіка. Модельні задачі / В. А. Каліон. – К.: ВЦ “Київський університет”.− 2011.
6. Крылов, В.И., Вычислительные методы : в 2 ч. / В. И. Крылов, В. В. Бобков, П. И. Монастырный. – М. : Наука, 1977.
7. Мак-Кракен, Д., Численные методы и программирование на Фортране / Д. Мак-Кракен, У. Дорн.− М.: "Мир".− 1977.
8. Немнюгин, М.А., Современный Фортран. Самоучитель / М.А. Немнюгин, О.Л. Стесик.− СПб.: БХВ-Петербург, 2004.
9. Рыжиков, Ю.И., Программирование на Фортране PowerStation для инженеров / Ю.И. Рыжиков.− Санкт-Петербург : "Корона принт".− 1999.
10. Семенова, І.Ю., Завдання з програмування на Фортрані: Навчальний посібник / І.Ю. Семенова, М.В. Лавренюк.– Київ: КНУ ім. Тараса Шевченка, 2012.
11. Форсайт, Дж., Машинные методы математических вычислений / Дж. Форсайт, М. Малькольм, К. Моулер. – М. : Мир, 1980.
12. Шикин, Е.В., Кривые и поверхности на экране компьютера. Руководство по сплайнам для пользователя / Е.В. Шикин, А.И. Плис.− М.: Диалог-МИФИ.− 1996.
243
б) додаткова:
13. Андерсон, Д., Вычислительная гидромеханика и теплообмен : в 2 ч. / Д. Андерсон, Дж. Танненхилл, Р. Плетчер.– М. : Мир, 1990.
14. Бартеньев, О.В., Visual FORTRAN: новые возможности. / О.В. Бартеньев. − М.: "Диалог-МИФИ".− 1999.
15. Бахвалов, Н. С. Численные методы / Н. С. Бахвалов, Н. П. Жидков, Г. М. Кобельков. – М. : Наука, 1987. – 600 с.
16. Дэннис, Дж., Численные методы безусловной оптимизации и решения нелинейных уравнений / Дж. Дэннис, Р. Шнабель.− М.: Мир.− 1988.
17. Жермен-Лакур, П. Математика и САПР : в 2 кн. – Книга I и II / П. Жермен-Лакур, П. Жорж, Ф. Пистр, П. Безье. – М. : Мир, 1989.
18. Ляшко, И.И., Методы вычислений / И. И. Ляшко, В. Л. Макаров, А. А. Скоробогатько. – К. : Вища шк., 1977.
19. Молчанов, И. Н., Машинные методы решения прикладных задач. Алгебра, приближение функций / И. Н. Молчанов.– К. : Наук. думка, 1987.
20. Пейре, Р. Вычислительные методы в задачах механики жидкости / Р. Пейре, Т. Д. Тейлор. – Л. : Гидрометеоиздат, 1986. – 352 с.
21. Роуч,П.Дж. Вычислительная гидромеханика / П.Дж.Роуч. – М. : Мир, 1980.– 612 с.
22. Флетчер, К., Вычислительные методы в динамике жидкостей : в 2 ч. – Часть I и II / К. Флетчер.– М. : Мир, 1991.
23. Шуп, Т., Решение инженерных задач на ЭВМ / Т. Шуп. – М. : Мир, 1982.
24. Kazachkov, I.V., Numerical continuum mechanics / I. V. Kazachkov, V. A. Kalion. – Stockholm : Royal Institute of Technology. – 2002. – Vol. 1. – 273 p.
25. Chapman, S.J., Fortran 95, 2003 for scientists and engineers / S.J. Chapman.– NewYork : McGraw-Hili Primis.– 2007.
26. Markus, A., Modern Fortran in practice / A. Markus.– Cambridge: Cambridge University Press.– 2012.
244
Зміст
Передмова 3
Вступ 5
1. Числове розв’язання алгебраїчних та трансцендентних рівнянь 7 1.1. Корені нелінійного рівняння 8 1.2. Визначення корнів алгебраїчних рівнянь 18 1.3. Запитання та вправи 21 1.4. Практичні завдання 21 2. Методи розв’язання систем лінійних та нелінійних
алгебраїчних рівнянь 27 2.1. Прямі методи розв’язання систем лінійних
алгебраїчних рівнянь 27 2.2. Ітераційні методи розв’язання систем лінійних
алгебраїчних рівнянь 41 2.3. Особливості розв’язання систем нелінійних рівнянь
ітеративними методами 45 2.4. Метод Ньютона розв’язання систем нелінійних
алгебраїчних рівнянь 46 2.5. Квазіньютонівські методи 51 2.6. Запитання та вправи 52 2.7. Практичні завдання 54 3. Методи розв’язання задач на власні значення 63 3.1. Ітераційні методи знаходження власних чисел 64 3.2. Розв’язання повної проблеми власних чисел 71 3.3. Запитання та вправи 78 3.4. Практичні завдання 79 4. Методи обробки числових даних 86 4.1. Інтерполяція 86 4.2. Апроксимація кривих 91 4.3. Числове диференціювання 101 4.4. Числове інтегрування 104 4.5. Запитання та вправи 111
245
4.6. Практичні завдання 112 5. Розв’язання звичайних диференціальних рівнянь 119 5.1. Задача Коші і крайова задача 119 5.2. Однокрокові методи розв’язання задачі Коші 122 5.3. Методи прогнозу і корекції 134 5.4. Вибір кроку інтегрування 139 5.5. “Жорсткі” задачі 141 5.6. Методи розв’язання крайових задач 142 5.7. Вибір алгоритму розв’язання звичайних диференціальних рівнянь 145 5.8. Запитання та вправи 146 5.9 Практичні завдання 148 Відповіді до вправ 154
Додаток 172 Список використаної та рекомендованої літератури 239