Методы решения обыкновенных дифференциальных уравнений

Автор работы: Пользователь скрыл имя, 01 Апреля 2012 в 19:49, лабораторная работа

Краткое описание

Постановка задачи 3
Ручной счёт и алгоритмы 3
Метод Эйлера 3
Метод Рунге-Кутты 4-го порядка 4
Метод Рунге-Кутты 5-го порядка 5
Метод Адамса 6
Правило Рунге для оценки погрешности 6
Метод прогонки 7
Реализация на языках программирования 9
Реализация на С++ 9
Метод Эйлера 9
Метод Рунге-Кутты 4-го порядка 10
Метод Рунге-Кутты 5-го порядка 11
Метод Адамса 12
Метод прогонки 14
Реализация на Fortran 15
Метод Эйлера 15
Метод Рунге-Кутты 4-го порядка 16
Метод Рунге-Кутты 5-го порядка 17
Метод Адамса 18
Метод прогонки 20
Реализация на SciLab 21
Метод Эйлера 21
Метод Рунге-Кутты 4-го порядка 22
Метод Рунге-Кутты 5-го порядка 23
Метод Адамса 23
Метод прогонки 25
Реализация на Pascal 26
Метод Эйлера 26
Метод Рунге-Кутты 4-го порядка 27
Метод Рунге-Кутты 5-го порядка 28
Метод Адамса 29
Метод прогонки 30
Реализация на Basic 32
Метод Эйлера 32
Метод Рунге-Кутты 4-го порядка 33
Метод Рунге-Кутты 5-го порядка 34
Метод Адамса 35
Метод прогонки 36
Сводная таблица результатов 38

Содержание работы

Постановка задачи
Ручной счёт и алгоритмы
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Правило Рунге для оценки погрешности
Метод прогонки
Реализация на языках программирования
Реализация на С++
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Метод прогонки
Реализация на Fortran
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Метод прогонки
Реализация на SciLab
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Метод прогонки
Реализация на Pascal
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Метод прогонки
Реализация на Basic
Метод Эйлера
Метод Рунге-Кутты 4-го порядка
Метод Рунге-Кутты 5-го порядка
Метод Адамса
Метод прогонки
Сводная таблица результатов
Вывод
Список используемой литературы

Содержимое работы - 1 файл

отчёт.doc

— 979.50 Кб (Скачать файл)

Таблица 4. Правило Рунге для оценки погрешности.

 

,

.

За оценку погрешности решения, вычисленного с шагом , принимаем величину 0.113.

Метод прогонки

Дано:

,

,

,

,

,

.

Найти численное решение дифференциального уравнения.

Решение:

Необходимые формулы:

, ,

,

,

,

,

,

,

,

,

,

.

Находим :

,

,

,

.

Исходя из полученных данных, можно найти и все остальное.

Результаты соответствующих итераций приведены в таблице 5:

№ итерации

x

y

m

n

c

d

0

1

1.3

-1.97844

0.978448

-0.50544

-1.26683

1

1.0625

1.25463

-1.97889

0.977537

-0.67349

-0.62261

2

1.125

1.21529

-1.97933

0.977895

-0.75716

-0.40669

3

1.1875

1.18186

-1.97974

0.978241

-0.80706

-0.29787

4

1.25

1.15422

-1.98015

0.978577

-0.84007

-0.23187

5

1.3125

1.13227

-1.98055

0.978901

-0.86341

-0.18729

6

1.375

1.11595

-1.98093

0.979214

-0.88069

-0.15491

7

1.4375

1.1052

-1.9813

0.979517

-0.98394

-0.13015

8

1.5

1.1

-1.98165

0.979809

-0.90435

-0.11045

Таблица 5. Метод прогонки.

 

Реализация на языках программирования

Таблица идентификаторов

Идентификаторы

Тип

Значение

function()

double

Функция для вычисления значения правой части ОДУ

x0, xN

double

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

h

double

Шаг сетки

y

double[]

Искомая функция

dy

double

Приращение функции

k1, k2, k3, k4,k5

double

Коэффициенты

y0

double

Значение функции в точке x0

n

int

Количество разбиений промежутка, на котором требуется решить задачу Коши

yh, yh2

double[]

Соответственно, значения искомой функции, вычисленные с сеткой с шагом h и 2h

funA

double

Коэффициент перед y’’ в краевой задаче

funB

double

Коэффициент перед y’ в краевой задаче

funC

double

Коэффициент перед y в краевой задаче

funF

double

Коэффициент в правой части в краевой задаче

a, b

double

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

c, d, m, n

double[]

Вспомогательные массивы в методе прогонки


 

Реализация на С++

Метод Эйлера

Файл eiler.cpp

#include<iostream>

#include<cmath>

#include<iomanip>

using namespace std;

double function(double x, double y){

              return (1+y)/(1+pow(x,3)*y);

}

double x0, xN, h, y;

double dy = 0.0;

int main(){

  cout << "Method eilera" << endl;

  cout << "y'= exp(x*y)" << endl;

  cout << "Vvedite x0: " ;

  cin >> x0;

  cout << "Vvedite xN: " ;

  cin >> xN;

  cout << "Vvedite shag: " ;

  cin >> h;

  cout << "Vvedite y(0): " ;

  cin >> y;

  cout << "Result:" << endl;

  cout << setw(3) << "x" << setw(10) << "y"<< setw(10) << "dy" << endl;

  while(x0 < xN+h){

    dy=h*function(x0,y);

    cout << setw(3) <<  x0 << setw(10) << y << setw(10) << dy << endl; 

    y+=dy;

    x0+=h;

  }

  return 0;

}

 

Результат работы программы:

Метод Рунге-Кутты 4-го порядка

Файл RK4.cpp

#include<iostream>

#include<cmath>

using namespace std;

double function(double x, double y){

  return exp(x*y);

}

int main()

{

  double x0,xN,h,y,k1,k2,k3,k4;

  cout << "Vvedite a: ";

  cin >> x0;

  cout << "Vvedite b: ";

  cin >> xN;

  cout << "Vvedite shag: ";

  cin >> h;

  cout << "Vvedite y(0): ";

  cin >> y;

  double x=x0;

  cout << "x\ty" << endl;

  while(x < xN+h)

  {

    cout << x << "\t" << y << endl;

    k1 = h*function(x,y);

    k2 = h*function(x + h/2, y + k1/2);

    k3 = h*function(x + h/2, y + k2/2);

    k4 = h*function(x + h, y + k3);

    y+=(k1+2*k2+2*k3+k4)/6;

    x+=h;

  }

  return 0;

}

 

Результат работы программы:

 

Метод Рунге-Кутты 5-го порядка

Файл RK5.cpp

#include<iostream>

#include<cmath>

using namespace std;

double function(double x,double y)

{return exp(x*y);}

int main()

{

  double x0,xN,h,y,k1,k2,k3,k4,k5;

  cout << "Vvedite x0: ";

  cin >> x0;

  cout << "Vvedite xN: ";

  cin >> xN;

  cout << "Vvedite shag: ";

  cin >> h;

  cout << "Vvedite y(0): ";

  cin >> y;

  double x=x0;

  cout << "x\ty"<< endl;

  while(x < xN+h)

  {

    cout << x << "\t" << y << endl;

    k1 = h*function(x,y)/3;

    k2 = h*function(x + h/3, y + k1)/3;

    k3 = h*function(x + h/3, y + k1/2 + k2/2)/3;

    k4 = h*function(x + h/2, y + 3*k1/8 + 9*k3/8)/3;

    k5 = h*function(x + h, y + 3*k1/2 - 9*k3/2 + 6*k4)/3;

    y+=(k1 + 4*k4 + k5)/2;

    x+=h;

  }

  return 0;

}

 

Результат работы программы:

Метод Адамса

Файл adams.cpp

#include<iostream>

#include<cmath>

using namespace std;

double function(double x,double y)

{return exp(x*y);}

int main()

{

  double x0, xN, h, k1, k2, k3, k4, k5, y, y0, x;

  cout << "Vvedite x0: "; cin >> x0;

  cout << "Vvedite xN: "; cin >> xN;

  cout << "Vvedite shag: "; cin >> h;

  cout << "Vvedite y(" << x0 << "): "; cin >> y0;

  int n = ceil(fabs(xN-x0)/h);

  double *yh = new double[n];

  double *yh2 = new double[2*n];

  y = y0; x = x0;

  for(int i = 0; x <= xN; i++){

    yh[i] = y;

    k1 = h*function(x,y);

    k2 = h*function(x + h/2, y + k1/2);

    k3 = h*function(x + h/2, y + k2/2);

    k4 = h*function(x + h, y + k3);

    y += (k1+2*k2+2*k3+k4)/6;

    x += h;

  }

  int i = 4;

  x = x0 + i*h;

  while(x <= xN){

yh[i] = yh[i-1] + h*(55*function(x,yh[i-1]) - 59*function(x-h,yh[i-2]) + 37*function(x-2*h,yh[i-3])-9*function(x-3*h,yh[i-4]))/24;

    x = x+h;

    i++;

  }

  cout << "Result: " << endl;

  cout << "y(" << xN << ") = " << yh[n] << endl;

  y = y0; x = x0; h = h/2;

  for(int i = 0; x <= xN; i++){

    yh2[i] = y;

    k1 = h*function(x,y);

    k2 = h*function(x + h/2, y + k1/2);

    k3 = h*function(x + h/2, y + k2/2);

    k4 = h*function(x + h, y + k3);

    y += (k1+2*k2+2*k3+k4)/6;

    x += h;

  }

  i = 8;

  x = x0 + i*h;

  while(x <= xN){

    yh2[i] = yh2[i-1] + h*(55*function(x,yh2[i-1])-59*function(x-h,yh2[i-2]) + 37*function(x-2*h,yh2[i-3])-9*function(x-3*h,yh2[i-4]))/24;

    x = x+h;

    i++;

  }

  cout << "eps = " << (yh[n] - yh2[2*n])/(pow(2, 4)-1) << endl;

  return 0;

}

 

Результат работы программы:

где eps – погрешность вычисленного решения.

 

Метод прогонки

Файл progon.cpp

#include <iostream>

#include <cmath>

using namespace std;

const double pi = 3.1416;

double funA(double x)

{

              return 0.4+2*x+x*x/2;

}

 

double funB(double x)

{

              return pow(x,0.7);

double funC(double x)

{

              return -0.95*x*x;

}

 

double funF(double x)

{

              return (pow(x,0.5) + cos(2*x/pi))/funA(x);

}

int main()

{

              double a, b, x, h;

              int N;

              cout << "Vvedite a = "; cin >> a;

              cout << "Vvedite b = "; cin >> b;

              if (a>=b){ cout << "bad interval" << endl; return -1; }

              cout << "Vvedite N = "; cin >> N;

              double y[N+1] ,c[N+1], d[N+1], m[N+1], n[N+1];

              cout << "Vvedite y(" << a << ") = "; cin >> y[0];

              cout << "Vvedite y(" << b << ") = "; cin >> y[N];

              h = (b-a)/N;

              m[0]=-2+funB(a)*h/funA(a);

              n[0]=1-funB(a)*h/funA(a)+funC(a)*h*h/funA(a);

              c[0]=1/m[0];

              d[0]=-n[0]*y[0]+funF(a)*h*h;

              for (int i=1;i<N+1;i++)

              {

                            x=a+i*h;

                            m[i]=-2+funB(x)*h/funA(x);

                            n[i]=1-funB(x)*h/funA(x)+funC(x)*h*h/funA(x);

                            c[i]=1/(m[i]-n[i]*c[i-1]);

                            d[i]=funF(x)*h*h-n[i]*c[i-1]*d[i-1];

              }

              for (int i=N;i>1; i--)

              {

                            y[i-1]=c[i-2]*(d[i-2]-y[i]);

              }

              cout << "x\ty" << endl;

              for (int i=0;i<N+1;i++)

              {

                cout << a+i*h << '\t' <<y[i] << endl;

              }

    return 0;

}

 

Результат работы программы:

Реализация на Fortran

Метод Эйлера

Файл eiler.f

1

2-5

6

9   72

 

 

 

program eiler

f(x,z)=exp(x*z)

real::xk,xN,h,y1,yk,yk12

print *,'Method eilera'

print *,'y''=exp(x*y)'

print *,'Vvedite x0: '

read *,x0

print *,'Vvedite xN: '

read *,xN

print *,'Vvedite shag: '

read *,h

print *,'Vvedite y(0): '

read *,y

print *,'x     ydy'

do while(x0<=xN)

dy=h*f(x0,y)

print *,x0,y,dy

y=y+dy

x0=x0+h

end do 

end program eiler

 

Результат работы программы:

 

Метод Рунге-Кутты 4-го порядка

 

Файл RK4.f

1

2-5

6

9   72

 

 

 

program RK4

f(x,y)= exp(x*y)

real:: x0, xN, h, k1, k2, k3, k4, y

print *,'Vvedite x0: '

read *, x0

print *,'Vvedite xN'

read *, xN

print *,'Vvedite shag: '

read *, h

print *,'Vvedite y(0): '

read *, y

x = x0

write(*,*) 'x              y'

do while(x<=xN)

write(*,'(f3.1,4x,f8.6)') x ,y

k1 = h*f(x,y)

k2 = h*f(x + h/2.0, y + k1/2.0)

k3 = h*f(x + h/2.0, y + k2/2.0)

k4 = h*f(x + h, y + k3)

y = y+(k1+2.0*k2+2.0*k3+k4)/6.0

x = x+h

end do

end program RK4

 

Результат работы программы:

Метод Рунге-Кутты 5-го порядка

Файл RK5.f

1

2-5

6

9                                                                                                        72

 

 

 

program RK5

f(x,y) = exp(x*y)

real::x0, xN, h, y, x, k1, k2, k3, k4, k5

print *,'Vvedite x0: '

read *, x0

print *,'Vvedite xN: '

read *, xN

print *,'Vvedite shag: '

read *, h

print *,'Vvedite y(x0): '

read *, y

x=x0

write(*,*) 'x              y'

do while(x<=xN)

write(*,'(f3.1,4x,f8.6)') x, y

k1 = h*f(x,y)/3.0

k2 = h*f(x + h/3.0, y + k1)/3.0

k3 = h*f(x + h/3.0, y + k1/2.0 + k2/2.0)/3.0

k4 = h*f(x + h/2.0, y + 3.0*k1/8.0 + 9.0*k3/8)/3.0

k5 = h*f(x + h, y + 3.0*k1/2 - 9.0*k3/2.0 + 6.0*k4)/3.0

y = y+(k1 + 4.0*k4 + k5)/2.0

x = x+h

end do

end program RK5

Информация о работе Методы решения обыкновенных дифференциальных уравнений