МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ІКТА, кафедра “Захист інформації”
ЗВІТ
З ЛАБОРАТОРНОЇ РОБОТИ № 6
З КУРСУ “ КОМП’ЮТЕРНІ МЕТОДИ ДОСЛІДЖЕННЯ ІНФОРМАЦІЙНИХ ПРОЦЕСІВ ТА СИСТЕМ ”
НА ТЕМУ: “ МЕТОДИ ЧИСЕЛЬНОГО РОЗВЯЗУВАННЯ
ДИФЕРЕНЦІАЛЬНИХ РІВНЯНЬ“
Варіант 19
Львів – 2007
Мета роботи – ознайомлення з методами чисельного інтегрування диференційних рівнянь
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
Диференціальним називається рівняння, в яке входять похідні невідомої функції.
Приклад:
(1)
(2)
Диференціальне рівняння (ДР), що містить лише одну незалежну змінну і похідні за нею, називають звичайними (ДР). Це, наприклад, рівняння (1). ДР, що містить декілька незалежних змінних і похідні за ними, називають рівняння в частинних похідних
Порядком ДР називається найвищий порядок похідної (або диференціалу), який входить в рівняння. Звичайне ДР (ЗДР) -го порядку в загальному випадку має незалежну змінну, невідому функцію та її похідні (або диференціал) до -го порядку включно:
(3)
- незалежна змінна;
- невідома функція (залежна змінна);
- похідні цієї функції.
Диференціальне рівняння -го порядку, розв’язане відносно старшої похідної, може бути записано у вигляді:
(4)
Щоб розв’язати ЗДР, необхідно мати значення залежної змінної та (або) її похідних при деяких значення незалежної змінної.
Якщо ці значення задані при одному значенні незалежної змінної - така задача називається задачею з початковими умовами або задачею Коші.
Якщо ці значення задаються при або більше значеннях незалежної змінної - задача називається крайовою.
Значення залежної змінної та її похідних називаються ще додатковими умовами, котрі в задачі Коші називаються початковими, а в крайовій задачі - граничними.
Задача Коші
Задача Коші формулюється так:
Нехай задане ДР
(5)
з початковими умовами . Потрібно знайти функцію , що задовольняє дане рівняння, та початкову умову. Для одержання чисельний розв’язку цієї задачі спочатку обчислюють значення похідної, а потім задаючи малий приріст , переходять до нової точки
Положення нової точки визначають за нахилом кривої, обчисленому з допомогою ДР. Таким чином, графік чисельного розв’язку являє собою послідовність коротких прямолінійних відрізків, якими апроксимується істинна крива . Сам чисельний метод визначає порядок дій при переході від даної точки кривої до наступної.
Існують дві групи методів розв’язування задачі Коші.
Однокрокові методи. В них для знаходження наступної точки на кривій потрібна інформація лише про попередній крок. (Однокроковими є метод Ейлера та методи Руте-Кутта.)
Багатокрокові (або методи прогнозування та коригування). Для знаходження наступної точки кривої вимагається інформація більш ніж про одну з попередніх точок. До них належать методи Адамса, Мілна, Хеммінга.
Це чисельні методи розв’язування ДР. Вони дають розв’язок у вигляді таблиці значень.
2.ЗАВДАННЯ ДО ЛАБОРАТОРНОЇ РОБОТИ
Розв’язати чисельним методом звичайне диференційне рівняння.
БЛОК-СХЕМА ПРОГРАМИ
ТАБЛИЦЯ ІДЕНТИФІКАТОРІВ КОНСТАНТ, ЗМІННИХ, ФУНКЦІЙ, ВИКОРИСТАНИХ У ПРОГРАМІ, ТА ЇХ ПОЯСНЕННЯ:
func()
Функція вичислення правих частин рівняння
ys[]
Перша похідна
t
Незалежний аргумент
Adams()
Функція, яка реалізує метод Адамса
f()
Функція вичислення правих частин системи
*y
Масив розмірності n значень залежних змінних
*ys
Масив розмірності n значень похідних
tn
Початок інтервалу інтегрування
tk
Кінець інтервалу інтегрування
m
Початкове число розбивань відрізка інтегрування
eps
Відносна похибка інтегрування
*k1,*k2,*k3,*k4
Змінні для методу Рунге-Кутто
*q0,*q1,*q2,*q3
Значеннязмінних для методу Адамса
*ya
Тимчасовий масив
*y0,*y1,*y2,*y3
Значення функцій для метода Адамса
h
Крок інтегрування
xi
Значення незалежної змінної
eps2
Для оцінки похибки
dq2,dq1,dq0,d2q1,d2q0,d3q0
Похідні
flag
Приймає значення 0, коли йдеперший підрахунок
i,j
Індекси
y[0]
Початкові умови
xs,xe
Початок інтегрування
Текст програми мовою С
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define z 1
void func (double *y, double *ys, double t)
{
ys[0]=y[0]+y[0]*t*t*t;
}
void Adams (
void f (double *y, double *ys, double x),
double *y, int n, double tn,
double tk, int m, double eps)
{
double *k1, *k2, *k3, *k4, *q0, *q1, *q2, *q3,
*ya, *y0, *y1, *y2, *y3, h, xi, eps2,
dq2, dq1, dq0, d2q1, d2q0, d3q0;
int i, j, flag = 0;
if (m < 4) m = 4;
if (tn >= tk)
{ printf ("\nNe pravilny argumenty\n");
abort ();
}
if ((k1 =(double*)malloc ((4 + 4 + 4 + 1) * n * sizeof (double))) == 0)
{ printf ("\nPomilka rozpodilennia pamiaty\n");
abort ();
}
k2 = k1 + n; k3 = k2 + n; k4 = k3 + n;
y0 = k4 + n; y1 = y0 + n; y2 = y1 + n; y3 = y2 + n;
ya = y3 + n;
q0 = ya + n; q1 = q0 + n; q2 = q1 + n; q3 = q2 + n;
h = (tk - tn) / m;
eps = fabs (eps);
start:
xi = tn;
for (j = 0; j < n; j++) y0[j] = y[j];
f (y0, q0, xi);
for (j = 0; j < n; j++) q0[j] *= h;
xi += h;
for (i = 0; i < 3; i++)
{
f (&y0[i * n], k1, xi);
for (j = 0; j < n; j++)
{
k1[j] *= h;
ya[j] = y0[i*n+j] + k1[j] / 2.;
}
f (ya, k2, xi + (h / 2.));
for (j = 0; j < n; j++)
{
k2[j] *= h;
ya[j] = y0[i*n+j] + k2[j] / 2.;
}
f (ya, k3, xi + h / 2.);
for (j = 0; j < n; j++)
{
k3[j] *= h;
ya[j] = y0[i*n+j] + k3[j];
}
f (ya, k4, xi + h);
for (j = 0; j < n; j++) k4[j] *= h;
for (j = 0; j < n; j++)
y0[(i+1)*n+j] = y0[i*n+j] + (k1[j] + 2. * k2[j] + 2 * k3[j] + k4[j]) / 6.;
f (&y0[(i+1)*n], &q0[(i+1)*n], xi);
for (j = 0; j < n; j++) q0[((i+1)*n)+j] *= h;
xi += h;
}
again:
for (j = 0; j < n; j++)
{
dq2 = q3[j] - q2[j]; dq1 = q2[j] - q1[j]; dq0 = q1[j] - q0[j];
d2q1 = dq2 - dq1; d2q0 = dq1 - dq0;
d3q0 = d2q1 - d2q0;
ya[j] = y3[j] + (q3[j] + (dq2 / 2.) + (5. * d2q1 / 12.) + (3. * d3q0 / 8.));
y0[j] = y1[j]; y1[j] = y2[j]; y2[j] = y3[j]; y3[j] = ya[j];
q0[j] = q1[j]; q1[j] = q2[j]; q2[j] = q3[j];
}
f (y3, q3, xi);
for (j = 0; j < n; j++) q3[j] *= h;
xi += h;
if (xi < tk) goto again;
if (flag == 0)
flag = 1;
else
{
for (j = 0; j < n; j++)
{ eps2 = fabs (((y3[j] - y2[j]) / y2[j]));
if (eps2 > eps) break;
}
if (j == n)
{
for (j = 0; j < n; j++) y[j] = y3[j];
free (k1);
return;
}
}
h /= 2.;
goto start;
}
int main (void)
{
double y[z], xs, xe;
int i;
y[0] = 1;
xs = .0; xe = .1;
printf ("x = %5.3lg, y(%4.2lg) = %10.3lg\n", xs, xs, y[0]);
for (i = 0; i < 20; i++)
{
Adams (func, y, 1, xs, xe, 10, 1.e-3);
xs += 0.1; xe += 0.1;
printf ("x=%4.2lg, y(%4.2lf)=%4.4lf \n", xs, xs, y[0]);
}
return 0;
}
Результат роботи програми:
x= 0.1, y(0.10)=1.1045
x= 0.2, y(0.20)=1.2211
x= 0.3, y(0.30)=1.3517
x= 0.4, y(0.40)=1.5005
x= 0.5, y(0.50)=1.6736
x= 0.6, y(0.60)=1.8809
x= 0.7, y(0.70)=2.1370
x= 0.8, y(0.80)=2.4670
x= 0.9, y(0.90)=2.8947
x= 1, y(1.00)=3.4841
x= 1.1, y(1.10)=4.3243
x= 1.2, y(1.20)=5.5657
x= 1.3, y(1.30)=7.4801
x= 1.4, y(1.40)=10.5702
x= 1.5, y(1.50)=15.8406
x= 1.6, y(1.60)=25.3951
x= 1.7, y(1.70)=43.9590
x= 1.8, y(1.80)=83.0657
x= 1.9, y(1.90)=172.9941
x= 2, y(2.00)=401.5101
Висновок: на цій лабораторній роботі я ознайомився з методами чисельного інтегрування диференційних рівнянь