#include // notwendig zur Ausgabe #include #include "hdnum.hh" // hdnum header namespace hdnum { template class SparseMatrix { struct MatrixEntry { int i; int j; REAL value; }; public: void AddEntry (int i, int j, REAL value) { if (i < 0 || j < 0) HDNUM_ERROR("Zeilen und Spalten dürfen nicht negativ sein!"); // create new matrix entry MatrixEntry entry; entry.i = i; entry.j = j; entry.value = value; // add entry to entries vector entries.insert(entries.begin(), entry); } template void mv (Vector& y, const Vector& x) { // iterate through all entries for(typename std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { if ((*it).i > y.size() || (*it).j > x.size()) HDNUM_ERROR("Vektor(en) hat/haben falsche Dimension!"); // modify corresponding vector entry y[(*it).i] += x[(*it).j] * (*it).value; } } private: // vector storing non-zero elements std::vector entries; }; } // zum Test, fluss matrizen aus rohrleitungsnetzwerk hdnum::SparseMatrix flussMatrixSparse(int N) { hdnum::SparseMatrix A; // berechnung der kantenlaenge int n = floor(sqrt(N+1)); for(int i = 0; i < N; i++) { int edges = 0; if ((i+1)%n != 0) { // nicht linker rand edges++; if (i-1 >= 0) A.AddEntry(i, i-1, -1); } if ((i+2)%n != 0) { // nicht rechter rand edges++; A.AddEntry(i, i+1, -1); } if (i+n < N) { // nicht unterer rand edges++; A.AddEntry(i, i+n, -1); } if (i-n >= -1) { // nicht oberer rand edges++; if (i-n >= 0) A.AddEntry(i, i-n, -1); } A.AddEntry(i, i, edges); } return A; } // Funktion zum Aufstellen der Matrix (aus rohrleitungsnetzwerk) hdnum::DenseMatrix flussMatrix(int N) { hdnum::DenseMatrix A(N,N); // berechnung der kantenlaenge int n = floor(sqrt(N+1)); for(int i = 0; i < N; i++) { int edges = 0; if ((i+1)%n != 0) { // nicht linker rand edges++; if (i-1 >= 0) A(i, i-1) = -1; // falls nicht der referenzknoten } if ((i+2)%n != 0) { // nicht rechter rand edges++; A(i, i+1) = -1; } if (i+n < N) { // nicht unterer rand edges++; A(i, i+n) = -1; } if (i-n >= -1) { // nicht oberer rand edges++; if (i-n >= 0) A(i, i-n) = -1; // falls nicht der referenzknoten } A(i, i) = edges; } return A; } // funktion zum testen void testMatrixVectorProduct(int N) { hdnum::SparseMatrix A = flussMatrixSparse(N); hdnum::DenseMatrix B = flussMatrix(N); // test vektor hdnum::Vector x(N); for(int i=0; i y1(N); hdnum::Vector y2(N); // Pretty-printing fuer Vektoren x.scientific(false); x.width(15); // test ob Ax = Bx A.mv(y1, x); B.mv(y2, x); std::cout << "Mit Sparse Matrix: " << y1 << std::endl; std::cout << "Mit Dense Matrix: " << y2; } int main () { // testMatrixVectorProduct(15); // messe zeiten fuer n=4,...,14 und N = 2^n for(int n=4; n<=14; n++) { int N = pow(2, n); // test vektor hdnum::Vector x(N); for(int i=0; i y(N); hdnum::SparseMatrix A = flussMatrixSparse(N); hdnum::DenseMatrix B = flussMatrix(N); // timer hier fuer die SparseMatrix implementierung hdnum::Timer myTimer; A.mv(y, x); std::cout << N << " " << myTimer.elapsed() << std::endl; } }