Главная Учебники - Разные Лекции (разные) - часть 62
|
СОДЕРЖАНИЕ
1. Задание. 2. Расчетно-пояснительная записка. 3. Аннотация. 4. Ведение. 5. Теория. 6. Алгоритмы. 7. Программы. 8. Инструкция пользователя. 9. Результаты экспериментов. 10.Заключение. ЗАДАНИЕ
A.Выписать систему конечно-разностных уравнений.
B.Оценить вычислительные затраты, требуемые для выполнения аналитических решений с шестью десятичными цифрами в 100 и 1000 точках интервала. Определить и использовать разложение в ряд Тейлора для этих вычислений.
C.Оценить до проведения любых вычислений те вычислительные затраты, которые потребуются для решения конечно-разностных уравнений в 100 и 1000 точках при помощи:
1.
Исключения Гаусса,
2.Итерационного метода Якоби,
3.Итерационного метода Гаусса-Зейделя.
D.
Вычислить решения конечно-разностных уравнений при помощи каждого из трех методов из задания
C.
E.
Оценить применимость различных методов приближен-ного решения краевых задач для дифференциальных уравнений.
АННОТАЦИЯ
В данной работе по исследованию прямых и итерационных методов решения линейных систем
,
возникающих в краевых задачах для дифференциальных уравнений было составлено шесть программ непосредственно по алгоритмам Гаусса
,
Якоби
,
Гаусса-Зейделя
.
Каждый из методов был представлен в виде самостоятельной программы
,
которая имеет инструкцию для пользователя
.
Каждая программа работает по определенному управлению
,
причем программа Гаусса формирует матрицу сама
,
а в программах Якоби и Гаусса-Зейделя вводится только количество точек на интервал
,
исходя из чего формируется столбец неизвестных членов
.
Начальные значения неизвестных задаются автоматически
на основе результатов
,
полученных в ходе исследования были сделаны соответствующие выводы
.
ВВЕДЕНИЕ
Персональные компьютеры являются одним из самых мощных факторов развития человечества
.
Благодаря универсальности
,
высокому быстродействию
,
неутомимостью в работе
,
простоте в управлении
PC
нашли широкое применение в различных сферах деятельности человека
.
С развитием научно-технического прогресса все большая часть задач требует решения на ЭВМ
,
поэтому наш курсовой проект направили на развитие не только определенных навыков логического мышления
,
но и способность развивать и закреплять эти навыки
.
ТЕОРИЯ
Дискретизация обыкновенных дифференциальных уравнений конечными разностями приводит к линейным уравнениям
;
если рассматривается краевая задача
,
то уравнения образуют совместную линейную систему
.
Прямым методом решения линейной системы
решение
или в общем виде
:
Стоимость такого решения составляет
Сведение матриц А к одному из двух указанных выше видов осуществляется с помощью ее умножения на специально подобранную матрицу М
,
так что система
Во многих случаях матрицу М подбирают таким образом
,
чтобы матрица МА стала верхней треугольной
.
Прямые методы решения СЛУ нельзя применять при очень больших, из-за нарастающих ошибок, округлениях, связанных с выполнением большого числа арифметических операций. Устранить эти трудности помогают итерационные методы. С их помощью можно получить, начиная с вектора
Метод является сходящимся, если это состояние справедливо для произвольного начального вектора
Во всех методах, которые рассмотрены ниже, матрица А представляется в виде А=М-
N
( ниже показано, как это наполняется ) и последовательно решаются системы
Формально решением системы является
:
где -
Критерием окончания итерационного процесса является соблюдение соотношения
:
где
РАЗНОСТНЫЕ УРАВНЕНИЯ
Многие физические системы моделируются дифферинци-альными уравнениями, например :
простой разностью, например
:
где, 0,2=1
/
5=
X4
-X3
.
Тогда аппроксимирующее разностное уравнение имеет вид:
В каждой точке дискретизации справедливо одно такое уравнение, которое приводит к линейной системе для приближенных значений решения дифференциального уравнения.
Уравнения такого вида можно решить с помощью разложения в ряд Тейлора. В нашем случае уравнения решенные разложением в ряд Тейлора имеют вид;
Найти
y’(0); y’’(0)=1; y’’’(0)=1;
обозначим у
’
(0) как С.
Решение:
Решение:
Система конечно-разностных уравнений
интервал
[0,2]
разделим на 10 точек
-2 1 0 0 0 0 0 0 0 0
1 -2 1 0 0 0 0 0 0 0
0 1 -2 1 0 0 0 0 0 0
0 0 1 -2 1 0 0 0 0 0
0 0 0 1 -2 1 0 0 0 0
0 0 0 0 1 -2 1 0 0 0
0 0 0 0 0 1 -2 1 0 0
0 0 0 0 0 0 1 -2 1 0
0 0 0 0 0 0 0 1 -2 1
0 0 0 0 0 0 0 0 1 -2
5 точек.
АЛГОРИТМ ГАУССА
Назначение: Решить
Входные параметры:
masheps
Вектор правых частей
Входно - выходные параметры
после разложения в А сохраняются ее верхние треугольные сомножители
Код возврата
retcode=0
при успешном решении и
retcode=1
при вырождении матрицы.
Выходные параметры:
Алгоритм
1.
retcode=0
2.
if n=1 then
2.1
if A[1,1]=0 then retcode=1
2.2
return
(*Гауссово исключение с частичным выбором ведущего элемента*)
3.
for k=1 to n do
(*найти ведущий элемент*)
3.1
Amax <= |A[k,k]|
3.2
Imax <= k
3.3
for i=k+1 to n do
3.3.1
if |[i,k]| > Amax then
3.3.1.1.
Amax <= |A[i,k]|
3.3.1.2.
Imax <= 1
(*
проверка на вырожденность*)
3.4.
if Amax < masheps
*n then
3.4.1.
retcode<=1
3.4.2.
return
3.5.
if Imax<> k then
3.5.1.
Amax <= A[Imax,k]
3.5.2.
A[Imax,k] <= A[k,k]
3.5.3.
A[Imax,k] <= Amax
3.7.
for i=k+1 to n do A[i,k] <= A[i,k]/Amax
(*перестановка и исключение по столбцам*) 3.8.
for j=k+1 to n do
3.8.1. Amax<=A[Imax,j]
3.8.2.
A[Imax,j]<=A[k,j]
3.8.3.
A[k,j]<=Amax
3.8.4.
if Amax<>0 then
for i=k+1 to n do
A[i,j]<=A[i,j]-A[i,k]*Amax
4.
if retcode=0 then (*
разложение успешно*)
(*решить СЛУ
Ly=b
и
Vx=y *)
5.
for i=2 to n do
6.
for k=n downto 1 do
return
end.
АЛГОРИТМ ЯКОБИ
Входные параметры:
Код возврата:
retcode=0
при успешном решении
u=1,
при не успешном решении превышение допустимого числа итераций.
Память: Требуется дополнительный массив
Алгоритм
retcode=1
for Iter=1 to maxiter do (*
расчет вектора невязок*)
rmax=0
for i=1 to n do
(*
проверка на окончание итерационного процесса*)
if rmax<eps then do retcode=0
return
(*
найти улучшенное решение*)
for i=1 to n do
x[i]=x[i]+r[i]/A[i,j]
АЛГОРИТМ ГАУССА-ЗЕЙДЕЛЯ
Входные параметры:
( релаксационный коэффициент )
maxiter-
максимальное число итераций.
Входно- выходные параметры:
Алгоритм
retcode=1
for iter=1 to maxiter do
rmax=0
(*
улучшить решение
*)
for i=1 to n do
(*
проверка на окончание итерационного процесса*)
if rmax<eps then
retcode=0
return
program GAUS1(input,output); type matrix=array[1..100,1..100] of real; vektor=array[1..100] of real; var a:matrix; x,b,y:vektor; n:integer; ret_code:integer; procedure geradlini(var a:matrix;var b,y:vektor;var n:integer); var s:real;j,i:integer; begin for i:=1 to n do begin s:=0; for j:=1 to (i-1) do s:=s+a[i,j]*y[j]; y[i]:=b[i]-s; end; end; procedure ruckgang(var a:matrix;var y,x:vektor;var n:integer); var s:real;i,j:integer; begin s:=0; for i:=n downto 1 do begin s:=0; for j:=(i+1) to n do s:=s+a[i,j]*x[j]; x[i]:=(y[i]-s)/a[i,i]; end; end; procedure vvod(var a:matrix;var b:vektor;var n:integer); var i,j:integer; q:real; begin writeln('Введите количество точек на интервал: '); readln(n); for i:=1 to n do begin for j:=1 to n do a[i,j]:=0; a[i,i]:=(-2); end; for i:=1 to (n-1) do a[i,i+1]:=1; for i:=2 to n do a[i,i-1]:=1; q:=sqr(2/n); for i:=1 to n do if i<>n then b[i]:=q else b[i]:=(q-2); end; procedure triangul(var a:matrix;var b:vektor; var ret_code:integer;n:integer); label 1; var eps,buf,max,c:real; k,imax,i,j:integer; begin ret_code:=1; eps:=1; buf:=1+eps; while buf>1.0 do begin eps:=eps/2; buf:=1+eps; end; buf:=n*eps; for k:=1 to (n-1) do begin max:=a[k,k]; imax:=k; for i:=k to n do if a[i,k]>max then begin max:=a[i,k]; imax:=i; end; if a[imax,k]>buf then begin for j:=1 to n do begin c:=a[imax,j]; a[imax,j]:=a[k,j]; a[k,j]:=c; end; c:=b[imax]; b[imax]:=b[k]; b[k]:=c; for i:=(k+1) to n do begin a[i,k]:=a[i,k]/a[k,k]; for j:=(k+1) to n do a[i,j]:=a[i,j]-a[i,k]*a[k,j]; end; end else begin ret_code:=0; goto 1 end; 1: end; end; procedure vivod(var x:vektor;var n:integer); var i:integer; begin for i:=1 to n do writeln('x',i:1,'=',x[i],' '); end; begin vvod(a,b,n); triangul(a,b,ret_code,n); if ret_code=1 then begin geradlini(a,b,y,n); ruckgang(a,y,x,n); vivod(x,n); end else writeln('Матрица вырожденна'); end. program GAUS2(input,output); type matrix=array[1..100,1..100] of real; vektor=array[1..100] of real; var a:matrix; x,b,y:vektor; n:integer; ret_code:integer; procedure geradlini(var a:matrix;var b,y:vektor; var n:integer); var s:real;j,i:integer; begin for i:=1 to n do begin s:=0; for j:=1 to (i-1) do s:=s+a[i,j]*y[j]; y[i]:=b[i]-s; end; end; procedure ruckgang(var a:matrix;var y,x:vektor; var n:integer); var s:real;i,j:integer; begin s:=0; for i:=n downto 1 do begin s:=0; for j:=(i+1) to n do s:=s+a[i,j]*x[j]; x[i]:=(y[i]-s)/a[i,i]; end; end; procedure vvod(var a:matrix;var b:vektor; var n:integer); var i,j:integer; q:real; begin writeln('Введите количество точек на интервал: '); readln(n); q:=(-2+sqr(0.5/n)*(sqr(4*arctan(1))/4)); for i:=1 to n do begin for j:=1 to n do a[i,j]:=0; a[i,i]:=(q); end; for i:=1 to (n-1) do a[i,i+1]:=1; for i:=2 to n do a[i,i-1]:=1; for i:=1 to n do if i<>n then b[i]:=0 else b[i]:=(-sqr(2)/2); end; procedure triangul(var a:matrix;var b:vektor;var ret_code:integer; n:integer); label 1; var eps,buf,max,c:real; k,imax,i,j:integer; begin ret_code:=1; eps:=1; buf:=1+eps; while buf>1.0 do begin eps:=eps/2; buf:=1+eps; end; buf:=n*eps; for k:=1 to (n-1) do begin max:=a[k,k]; imax:=k; for i:=k to n do if a[i,k]>max then begin max:=a[i,k]; imax:=i; end; if a[imax,k]>buf then begin for j:=1 to n do begin c:=a[imax,j]; a[imax,j]:=a[k,j]; a[k,j]:=c; end; c:=b[imax]; b[imax]:=b[k]; b[k]:=c; for i:=(k+1) to n do begin a[i,k]:=a[i,k]/a[k,k]; for j:=(k+1) to n do a[i,j]:=a[i,j]-a[i,k]*a[k,j]; end; end else begin ret_code:=0; goto 1 end; 1: end; end; procedure vivod(var x:vektor;var n:integer); var i:integer; begin for i:=1 to n do writeln('x',i:1,'=',x[i]); end; begin vod(a,b,n); triangul(a,b,ret_code,n); if ret_code=1 then begin geradlini(a,b,y,n); ruckgang(a,y,x,n); vivod(x,n); end else writeln('Матрица вырождена '); end. program jakobi1(input,output); type vektor=array[1..100] of real; var r,y:vektor; z,ret_code,maxiter:integer; eps:real; procedure vvod(var z,maxiter:integer;var eps:real); begin writeln('Введите кол-во точек на интервал'); readln(z); writeln('Введите точность'); readln(eps); writeln('Введите кол-во итераций'); readln(maxiter); end; procedure ren(var r,y:vektor;var z,ret_kode,maxiter:integer;var eps:real); label 1; var iter,i:integer; rmax,q:real; begin q:=sqr(2/z); for i:=1 to z do y[i]:=1; ret_code:=0; for iter:=1 to maxiter do {c.1} begin rmax:=0; for i:=1 to z do {c.2} begin if i=1 then begin r[i]:=q-(-2*y[1]+y[2]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; if i=z then begin r[z]:=(-2+q)-(y[z-1]-2*y[z]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; if(i<>1)and(i<>z) then begin r[i]:=q-(y[i-1]-2*y[i]+y[i+1]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; end;{c.2} if rmax<=eps then goto 1 else for i:=1 to z do y[i]:=y[i]+r[i]/(-2); end; {c.1} ret_code:=1; 1: end; procedure vivod(var y:vektor;var z:integer); var i:integer; ch:char; begin for i:=1 to z do writeln('y',i:1,y[i]); end; begin vvod(z,maxiter,eps); ren(r,y,z,ret_code,maxiter,eps); if ret_code=0 then vivod(y,z) else writeln('Превышено допустимое число итераций'); end. program jakobi2(input,output); type vektor=array[1..100] of real; var r,y:vektor; z,ret_code,maxiter:integer; eps:real; procedure vvod(var z,maxiter:integer;var eps:real); begin writeln('Введите кол-во точек на интервал'); readln(z); writeln('Введите точность'); readln(eps); writeln('Введите кол-во итераций'); readln(maxiter); end; procedure ren(var r,y:vektor;var z,ret_kode,maxiter:integer;var eps:real); label 1; var iter,i:integer; rmax,q:real; begin q:=sqr(2/z); for i:=1 to z do y[i]:=1; ret_code:=0; for iter:=1 to maxiter do begin rmax:=0; for i:=1 to z do begin if i=1 then begin r[i]:=q-(-2*y[1]+y[2]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; if i=z then begin r[z]:=(-2+q)-(y[z-1]-2*y[z]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; if(i<>1)and(i<>z) then begin r[i]:=q-(y[i-1]-2*y[i]+y[i+1]); if rmax<abs(r[i]) then rmax:=abs(r[i]); end; end; if rmax<=eps then goto 1 else for i:=1 to z do y[i]:=y[i]+r[i]/q; end; ret_code:=1; 1:end; procedure vivod(var y:vektor;var z:integer); var i:integer; begin for i:=1 to z do writeln('y',i:1,y[i]); end; begin vvod(z,maxiter,eps); ren(r,y,z,ret_code,maxiter,eps); if ret_code=0 then vivod(y,z) else write('Превышено допустимое число итераций'); end. program zeidel1(input,output); type vector=array[1..1000] of real; var y:vector; z,retcode,maxiter:integer; eps:real; procedure wod(var z,maxiter:integer;var eps:real); begin writeln; writeln('введите количество точек на интервал '); readln(z); writeln('введите точность ');readln(eps); writeln('введите количество итераций ');readln(maxiter); writeln('коофицент релаксации W,принят равный 1'); end; procedure reshen(var y:vector;var z,retcode,maxiter:integer;var eps:real); label 1; var Iter,I:integer;R,Rmax,Q:real; begin Q:=sqr(2/z); for i:=1 to z do y[i]:=1; retcode:=1; for Iter:=1 to maxiter do begin Rmax:=0; for i:=1 to z do begin if i=1 then begin R:=Q-(-2*y[1]+y[2]); if Rmax<Abs(R) then Rmax:=abs(R); y[i]:=y[i]+R/(-2); end; if i=z then begin R:=(-2+Q)-(y[z-1]-2*y[z]); if Rmax<ABS(R) then Rmax:=ABS(R); y[i]:=y[i]+r/(-2); end; if (I<>1) and (i<>z) then begin r:=Q-(y[i-1]-2*y[i]+y[i+1]); if Rmax<abs(r) then Rmax:=abs(r); y[i]:=y[i]+R/-2; end; end; if Rmax<=eps then begin retcode:=0; goto 1; end; end; 1: end; procedure vivod(var y:vector;var z:integer); var i:integer; begin for i:=1 to z do write('y',i:2,'=',y[i]); end; begin wod(z,maxiter,eps); reshen(y,z,retcode,maxiter,eps); if retcode=0 then vivod(y,z) else write('число итераций'); end. program zeidel2(input,output); type vector=array[1..1000] of real; var y:vector; z,retcode,maxiter:integer; eps:real; procedure wod(var z,maxiter:integer;var eps:real); begin writeln; writeln('введите количество точек на интервал '); readln(z); writeln('введите точность ');readln(eps); writeln('введите количество итераций ');readln(maxiter); writeln('коофицент релаксации W,принят равный 1'); end; procedure reshen(var y:vector;var z,retcode,maxiter:integer;var eps:real); label 1; var Iter,I:integer;R,Rmax,Q:real; begin Q:=(-2+sqr(0.5/z)*sqr(4*arctan(1))/4); for i:=1 to z do y[i]:=1; retcode:=1; for Iter:=1 to maxiter do begin Rmax:=0; for i:=1 to z do begin if i=1 then begin r:=-(q*y[1]+y[z]); if Rmax<Abs(R) then Rmax:=abs(R); y[i]:=y[i]+R/q; end; if i=z then begin r:=-sqrt(z)/2-(y[z-1]+q*y[z]); if Rmax<ABS(R) then Rmax:=R; y[i]:=y[i]+r/q; end; if (I<>1) and (i<>z) then begin r:=-(y[i-1]+q*y[i]+y[i+1]); if Rmax<abs(r) then Rmax:=r; y[i]:=y[i]+R/q; end; end; if Rmax<=eps then begin retcode:=0; goto 1; end; end; 1: end; procedure vivod(var y:vector;var z:integer); var i:integer; begin for i:=1 to z do writeln (i:1,'=',y[i],); end; begin wod(z,maxiter,eps); reshen(y,z,retcode,maxiter,eps); if retcode=0 then vivod(y,z) else write('число итераций'); end. ИНСТРУКЦИЯ ДЛЯ ПОЛЬЗОВАТЕЛЯ
Программа
Jacobi1
предназначена для решения уравнений
Программы
Zeidel1
и
Zeidel2
, также решают уравнения
Вычисление уравнений с помощью итерационного метода Якоби требует времени
t=0(maxiter Z)
, где
Z
- количество точек на интервал, а
maxiter
- количество итераций.
Вычисление уравнений с помощью метода Гаусса требует времени
t=0(
Решение с помощью метода Гаусса требует больше времени чем решения другими двумя приведенными способами.
| ||||||||||||||||||||||||||||||||||||||||