More work on parallel stuff
This commit is contained in:
91
src/cg.py
Normal file
91
src/cg.py
Normal file
@ -0,0 +1,91 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
# Funktion zur Berechnung der 2-Norm
|
||||
def norm(vec):
|
||||
sum_of_squares = 0
|
||||
for i in range(0, len(vec)):
|
||||
sum_of_squares = sum_of_squares + vec[i] ** 2
|
||||
|
||||
return np.sqrt(sum_of_squares)
|
||||
|
||||
|
||||
# Test, ob die Matrix M positiv definit ist, mittels Cholesky-Zerlegung
|
||||
def ist_positiv_definit(m):
|
||||
try:
|
||||
np.linalg.cholesky(m)
|
||||
return True
|
||||
except np.linalg.LinAlgError:
|
||||
return False
|
||||
|
||||
|
||||
n = 1000
|
||||
h = 1 / (n - 1)
|
||||
|
||||
# Initialisierung der Matrix A und des Vektor f für LGS Au = f
|
||||
A = np.diag(-1 * np.ones(n - 1), k=1) + np.diag(2 * np.ones(n), k=0) + np.diag(-1 * np.ones(n - 1), k=-1)
|
||||
f = h ** 2 * 2 * np.ones(n)
|
||||
|
||||
# Teste, ob A positiv definitv ist mittels Eigenwerten
|
||||
if np.all(np.linalg.eigvals(A) <= 0): # Prüfen, ob alle Eigenwerte positiv sind
|
||||
raise ValueError("A ist nicht positiv definit.")
|
||||
|
||||
# Teste, ob A positiv definit ist mittels Cholesky-Zerlegung
|
||||
if not (ist_positiv_definit(A)):
|
||||
raise ValueError("A ist nicht positiv definit.")
|
||||
|
||||
# Teste, ob A symmetrisch ist
|
||||
if (A != A.T).all():
|
||||
raise ValueError("A ist nicht symmetrisch.")
|
||||
|
||||
# Intialisierung des Startvektors x
|
||||
x = np.ones(n)
|
||||
|
||||
# Toleranz epsilon
|
||||
eps = 0.001
|
||||
|
||||
count = 1
|
||||
|
||||
# Anfangswerte berechnen
|
||||
r = f - A @ x # Anfangsresiduum
|
||||
p = r # Anfangsabstiegsrichtung
|
||||
|
||||
print("0. Iterationsschritt: \n")
|
||||
print("Startvektor:", x)
|
||||
print("Norm des Anfangsresiduums: ", norm(r))
|
||||
|
||||
while eps < norm(r) < 1000:
|
||||
z = A @ p # Matrix-Vektorprodukt berechnen und speichern
|
||||
|
||||
alpha = (np.dot(r, p)) / (np.dot(p, z))
|
||||
print(alpha)
|
||||
|
||||
x = x + alpha * p # neue Itterierte x
|
||||
r = r - alpha * z # neues Residuum
|
||||
|
||||
# Bestimmung der neuen Suchrichtung
|
||||
beta = - (np.dot(r, z)) / (np.dot(p, z))
|
||||
p = r + beta * p # neue konjugierte Abstiegsrichtung
|
||||
|
||||
print(count, ". Iterationsschritt: \n")
|
||||
print("Aktuelle Iterierte:", x)
|
||||
print("Norm des Residuums: ", norm(r))
|
||||
|
||||
count = count + 1
|
||||
|
||||
# Vergleich mit numpy-interner Lsg
|
||||
u = np.linalg.solve(A, f)
|
||||
|
||||
print("Lösung mit CG-Verfahren:", x)
|
||||
print("Numpy interne Lösung:", u)
|
||||
|
||||
if norm(u - x) > eps:
|
||||
print("Der CG-Algorithmus hat nicht richtig funktioniert!")
|
||||
else:
|
||||
print("Der CG-Algorithmus war erfolgreich.")
|
||||
|
||||
plt.plot(x, linewidth=2)
|
||||
plt.plot(u, linewidth=2)
|
||||
|
||||
plt.show()
|
@ -0,0 +1,6 @@
|
||||
# m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000))
|
||||
from matrix_mpi import MatrixMPI
|
||||
|
||||
m1 = MatrixMPI([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6], (5, 3))
|
||||
|
||||
print(m1 + m1)
|
||||
|
@ -5,14 +5,18 @@ from matrix import Matrix
|
||||
|
||||
|
||||
class MatrixMPI:
|
||||
__mpi_comm__ = MPI.COMM_WORLD
|
||||
__mpi_size__ = __mpi_comm__.Get_size()
|
||||
__mpi_rank__ = __mpi_comm__.Get_rank()
|
||||
__mpi_comm__ = None
|
||||
__mpi_size__ = None
|
||||
__mpi_rank__ = None
|
||||
|
||||
__matrix__: Matrix = None
|
||||
__chunk__: list = None
|
||||
|
||||
def __init__(self, data=None, shape=None, structure=None, model=None, offset=None, n=None):
|
||||
def __init__(self, mpi_comm, data=None, shape=None, structure=None, model=None, offset=None, n=None):
|
||||
self.__mpi_comm__ = mpi_comm
|
||||
self.__mpi_size__ = self.__mpi_comm__.Get_size()
|
||||
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
|
||||
|
||||
self.__matrix__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n)
|
||||
|
||||
total_amount_of_rows = self.__matrix__.shape()[0]
|
||||
@ -111,8 +115,3 @@ class MatrixMPI:
|
||||
def __setitem__(self, key, value):
|
||||
self.__matrix__[key] = value
|
||||
|
||||
|
||||
# m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000))
|
||||
m1 = MatrixMPI([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6], (5, 3))
|
||||
|
||||
print(m1 - m1)
|
||||
|
@ -1,8 +1,21 @@
|
||||
import numpy
|
||||
from mpi4py import MPI
|
||||
from vector import Vector
|
||||
|
||||
|
||||
class VectorMPI:
|
||||
...
|
||||
__mpi_comm__ = None
|
||||
__mpi_size__ = None
|
||||
__mpi_rank__ = None
|
||||
|
||||
__vector__: Vector = None
|
||||
|
||||
def __init__(self, mpi_comm, data=None, shape=None):
|
||||
self.__mpi_comm__ = mpi_comm
|
||||
self.__mpi_size__ = self.__mpi_comm__.Get_size()
|
||||
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
|
||||
|
||||
self.__vector__ = Vector(data=data, shape=shape)
|
||||
|
||||
# class Vector:
|
||||
# start_idx = 0 # Nullter Eintrag des Vektors auf dem aktuellen Rang
|
||||
|
Reference in New Issue
Block a user