- •Обзор методов решения систем линейных алгебраических уравнений
- •1.1 Прямые методы решения
- •1.2 Вариационные методы
- •Метод Якоби
- •Решение на однопроцессорных компьютерах
- •Решение на многопроцессорных компьютерах
- •Основные функции mpi
- •Численный эксперимент
- •Расчет на однопроцессорных компьютерах
- •4.2 Расчет на многопроцессорных компьютерах
- •Литература
Метод Якоби
Постановка задачи
Возьмём систему линейных уравнений:
, где
Или
Описание метода
Для того, чтобы построить итеративную процедуру метода Якоби, необходимо провести предварительное преобразование системы уравнений к итерационному виду. Оно может быть осуществлено по одному из следующих правил:
где в принятых обозначениях D означает матрицу, у которой на главной диагонали стоят соответствующие элементы матрицы A, а все остальные нули; тогда как матрицы U и L содержат верхнюю и нижнюю треугольные части A, на главной диагонали которых нули, E — единичная матрица.
Тогда процедура нахождения решения имеет вид:
где k счётчик итерации.
В отличие от метода Гаусса-Зейделямы не можем заменятьнав процессе итерационной процедуры, т.к. эти значения понадобятся для остальных вычислений. Это наиболее значимое различие между методом Якоби и методом Гаусса-Зейделя решенияСЛАУ. Таким образом на каждой итерации придётся хранить оба вектора приближений: старый и новый.
Условие сходимости
Приведем достаточное условие сходимости метода.
Теорема. Пусть. Тогда при любом выборе начального приближения:
метод сходится;
скорость сходимости метода равна скорости сходимости геометрической прогрессиисо знаменателем;
верна оценка погрешности: .
Условие остановки
Условие окончания итерационного процесса при достижении точности ε в упрощённой форме имеет вид:
(Существует более точное условие окончания итерационного процесса, которое более сложно и требует дополнительных вычислений)
Алгоритм
Ниже приведён алгоритм реализации на C++
#include <math.h>
const double eps = 0.001; ///< желаемая точность
/// N - размерность матрицы; A[N][N] - матрица коэффициентов, F[N] - столбец свободных членов,
/// X[N] - начальное приближение, ответ записывается также в X[N];
void Jacobi (int N, double **A, double *F, double *X)
{
double * TempX = new double[N];
double norm; // норма, определяемая как наибольшая разность компонент столбца иксов соседних итераций.
do {
for (int i = 0; i < N; i++) {
TempX[i] =- F[i];
for (int g = 0; g < N; g++) {
if (i != g)
TempX[i] += A[i][g] * X[g];
}
TempX[i] /= -A[i][i];
}
norm = fabs(X[0] - TempX[0]);
for (int h = 0; h < N; h++) {
if (fabs(X[h] - TempX[h]) > norm)
norm = fabs(X[h] - TempX[h]);
X[h] = TempX[h];
}
} while (norm > eps);
delete[] TempX;
}
Решение на однопроцессорных компьютерах
#include <fstream>
#include <math.h>
#include <iostream>
using namespace std;
void main()
{ double x[100], x0[100], b[100], a[100][100],
s, d, eps=1e-8, max, k;
int n, i, j ;
freopen("input.txt","r",stdin);
cin>>n;
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++) cin>>a[i][j];
cin>>b[i];
}
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++) cout<<a[i][j]<<" ";
cout<<b[i]<<endl;
}
k=0;
for (i=1;i<=n;i++) x[i]=0; // Начальное приближение
do
{ k++;
for (i=1;i<=n;i++) x0[i]=x[i];
max=0;
for (i=1;i<=n;i++)
{ s=0;
for (j=1;j<=n;j++) if (i!=j) s=s+a[i][j]*x0[j];
x[i]=(b[i]-s)/a[i][i];
d=fabs(x[i]-x0[i]); if (max<d) max=d;
}
} while (max>eps);
for (i=1;i<=n;i++) cout<<"x"<<i<<"="<<x[i]<<endl;
cout<<endl<<"k="<<k<<endl;
cout<<"d="<<d<<endl;
}
???
#include <fstream>
#include <math.h>
#include <iomanip>
#include <iostream>
#include <stdio.h>
using namespace std;
void main()
{ double x[100], x0[100], b[100], a[100][100],
s, d, eps=1e-8, max, k, h, pi=3.1415926;
int n, i, j ;
// freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=50;
h=1.0/n;
memset(a,0,sizeof(a));
for (i=1;i<=n-1;i++)
{
if (i>1) a[i][i-1]=1;
a[i][i]=-2;
if(i<n-1) a[i][i+1]=1;
b[i]=-4*pi*pi*h*h*sin(2*pi*i*h);
}
k=0;
for (i=1;i<=n-1;i++) x[i]=0; // Начальное приближение
do
{ k++;
for (i=1;i<=n-1;i++) x0[i]=x[i];
max=0;
for (i=1;i<=n-1;i++)
{ s=0;
for (j=1;j<=n;j++) if (i!=j) s=s+a[i][j]*x0[j];
x[i]=(b[i]-s)/a[i][i];
d=fabs(x[i]-x0[i]); if (max<d) max=d;
}
} while (max>eps);
for (i=1;i<=n-1;i++) printf("%6.2lf",x[i]);
cout<<endl;
for (i=1;i<=n-1;i++) printf("%6.2lf",sin(2*pi*i*h));
cout<<endl<<"k="<<k<<endl;
cout<<"d="<<d<<endl;
}