00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #ifndef QVSPARSEBLOCKMATRIX_H
00026 #define QVSPARSEBLOCKMATRIX_H
00027
00028 #include <QMap>
00029 #include <qvmath/qvmatrix.h>
00030
00031 #ifdef MKL_AVAILABLE
00032 #include "mkl_dss.h"
00033 #endif
00034
00172 class QVSparseBlockMatrix: public QMap<int, QMap<int, QVMatrix> >
00173 {
00174 protected:
00175 int majorRows, majorCols, minorRows, minorCols;
00176
00177 public:
00178 int blockCount;
00180 QVSparseBlockMatrix(): QMap<int, QMap<int, QVMatrix> >(),
00181 majorRows(0), majorCols(0), minorRows(0), minorCols(0), blockCount(0)
00182 {
00183
00184 }
00185
00186 QVSparseBlockMatrix (const QVSparseBlockMatrix &other): QMap<int, QMap<int, QVMatrix> >(other),
00187 majorRows(other.majorRows), majorCols(other.majorCols), minorRows(other.minorRows), minorCols(other.minorCols), blockCount(other.blockCount)
00188 {
00189
00190 }
00191
00201 QVSparseBlockMatrix(const int majorRows, const int majorCols, const int minorRows, const int minorCols): QMap<int, QMap<int, QVMatrix> >(),
00202 majorRows(majorRows), majorCols(majorCols), minorRows(minorRows), minorCols(minorCols), blockCount(0)
00203 { }
00204
00221 QVSparseBlockMatrix(const int majorRows, const int majorCols, const QVMatrix &other): QMap<int, QMap<int, QVMatrix> >(),
00222 majorRows(majorRows), majorCols(majorCols), minorRows(other.getRows() / majorRows), minorCols(other.getCols() / majorCols)
00223 {
00224
00225 if( (minorRows*majorRows != other.getRows()) || (minorCols*majorCols != other.getCols()) )
00226 {
00227 std::cout << "[QVSparseBlockMatrix] Error: tried to construct a sparse block matrix of incompatible sizes with original dense matrix." << std::endl
00228 << "\tSparse matrix number of blocks:\t" << majorRows << "x" << majorCols << std::endl
00229 << "\tDense matrix number of blocks:\t" << other.getRows() << "x" << other.getCols() << std::endl;
00230 exit(1);
00231 }
00232
00233 for(int i = 0; i < majorRows; i++)
00234 for(int j = 0; j < majorCols; j++)
00235 {
00236 QVMatrix M = other.getSubmatrix(i*minorRows, (i+1)*minorRows-1, j*minorCols, (j+1)*minorCols-1);
00237 if (M != QVMatrix(minorRows, minorCols, 0.0))
00238 operator[](i)[j] = M;
00239 }
00240 }
00241
00243 inline int getMajorRows() const {return majorRows;};
00244
00246 inline int getMajorCols() const {return majorCols;};
00247
00249 inline int getMinorRows() const {return minorRows;};
00250
00252 inline int getMinorCols() const {return minorCols;};
00253
00255 operator QVMatrix () const
00256 {
00257 QVMatrix result(majorRows * minorRows, majorCols * minorCols, 0.0);
00258
00259
00260
00261
00262 foreach(int i, keys())
00263 foreach(int j, operator[](i).keys())
00264 result.setSubmatrix(i*minorRows, j*minorCols, operator[](i)[j]);
00265 return result;
00266 }
00267
00268 QVSparseBlockMatrix transpose() const;
00269
00288 void setBlock(const int majorRow, const int majorCol, const QVMatrix &M)
00289 {
00290 if (majorRow < 0 || majorRow >= majorRows || majorCol < 0 || majorCol >= majorCols)
00291 {
00292 std::cout << "[QVSparseBlockMatrix::setBlock]: accessing a block outside the sparse matrix." << std::endl
00293 << "\tProvided block index:\t" << majorRow << "," << majorCol << std::endl
00294 << "\tValid block ranges for the matrix:\t" << majorRows << "x" << majorCols << std::endl;
00295 exit(1);
00296 }
00297
00298 if (minorRows != M.getRows() || minorCols != M.getCols())
00299 {
00300 std::cout << "[QVSparseBlockMatrix::setBlock] Error: tried to assing a matrix of incorrect dimensions to a block." << std::endl
00301 << "\tMatrix size:\t" << M.getRows() << "x" << M.getCols() << std::endl
00302 << "\tSparse matrix block size:\t" << minorRows << "x" << minorCols << std::endl;
00303 exit(1);
00304 }
00305
00306 QMap<int, QVMatrix> & row = operator[](majorRow);
00307 if (!row.contains(majorCol))
00308 blockCount ++;
00309
00310 operator[](majorRow)[majorCol] = M;
00311 }
00312
00314 QVMatrix & getBlock(const int majorRow, const int majorCol)
00315 {
00316 if (majorRow < 0 || majorRow >= majorRows || majorCol < 0 || majorCol >= majorCols)
00317 {
00318 std::cout << "[QVSparseBlockMatrix::getBlock] Error: accessing a block outside the sparse matrix." << std::endl
00319 << "\tProvided block index:\t" << majorRow << "," << majorCol << std::endl
00320 << "\tValid block ranges for the matrix:\t" << majorRows << "x" << majorCols << std::endl;
00321 exit(1);
00322 }
00323
00324 QMap<int, QVMatrix> & row = operator[](majorRow);
00325
00326
00327 if (!row.contains(majorCol))
00328 row[majorCol] = QVMatrix(minorRows, minorCols, 0.0);
00329
00330 return row[majorCol];
00331 }
00332
00339 bool isNullBlock(const int majorRow, const int majorCol) const
00340 {
00341 if (majorRow < 0 || majorRow >= majorRows || majorCol < 0 || majorCol >= majorCols)
00342 {
00343 std::cout << "[QVSparseBlockMatrix::isNullBlock] Error: accessing a block outside the sparse matrix." << std::endl
00344 << "\tProvided block index:\t" << majorRow << "," << majorCol << std::endl
00345 << "\tValid block ranges for the matrix:\t" << majorRows << "x" << majorCols << std::endl;
00346 exit(1);
00347 }
00348
00349 return !operator[](majorRow).contains(majorCol);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 void printBlocks() const
00374 {
00375 std::cout << "Blocks for sparse matrix:" << std::endl;
00376 for(int i = 0; i < majorRows; i++)
00377 {
00378 std::cout << "\t";
00379 for(int j = 0; j < majorCols; j++)
00380 if (operator[](i).contains(j))
00381 std::cout << "[]";
00382 else
00383 std::cout << "<>";
00384 std::cout << std::endl;
00385 }
00386 }
00387
00393 QList<int> getBlockRowIndexes(const int majorRow) const
00394 {
00395 return operator[](majorRow).keys();
00396 }
00397
00403 QVSparseBlockMatrix operator*(const QVSparseBlockMatrix &other) const { return dotProduct(other, false, false); };
00404
00408 QVVector operator*(const QVVector &vector) const { return dotProduct(vector, false); }
00409
00415 QVSparseBlockMatrix dotProduct(const QVSparseBlockMatrix &other,
00416 const bool transposeFirstOperand = false,
00417 const bool transposeSecondOperand = false) const;
00418
00424 QVVector dotProduct(const QVVector &vector, const bool transposeMatrix = false) const;
00425
00427 QVSparseBlockMatrix & operator=(const QVSparseBlockMatrix &other);
00428
00430 void clear() { QMap<int, QMap<int, QVMatrix> >::clear(); }
00431
00432
00433
00434 #ifndef DOXYGEN_IGNORE_THIS
00435 double trace()
00436 {
00437
00438 double trace = 0.0;
00439 int count = 0;
00440 for(int k = 0; k < MIN(getMajorRows(),getMajorCols()); k++)
00441 {
00442 if (isNullBlock(k,k))
00443 continue;
00444
00445 const QVMatrix M = getBlock(k,k);
00446 if (M.getCols() < getMinorCols() || M.getRows() < getMinorRows())
00447 {
00448 std::cout << "ERROR: block in the diagonal is NULL." << std::endl;
00449 exit(1);
00450 }
00451
00452 for (int j = 0; j < MIN(getMinorRows(), getMinorCols()); j++)
00453 {
00454 trace += M(j,j);
00455 count++;
00456 }
00457 }
00458
00459 return trace;
00460 }
00461 #endif
00462
00472 static QVSparseBlockMatrix randomSquare(const int NB,const int N, const double NZProb,const bool symmetric=true,const bool positive=true);
00473 };
00474
00475 #ifndef DOXYGEN_IGNORE_THIS
00476
00477 class MKLPardisoSparseFormat
00478 {
00479 public:
00480 MKLPardisoSparseFormat(const QVSparseBlockMatrix qvspmatrix, bool isSymmetric);
00481 MKLPardisoSparseFormat(): majorRows(0), majorCols(0), minorRows(0), minorCols(0), nRows(0), nCols(0), nNonZeros(0), rowIndex(NULL), columns(NULL), values(NULL)
00482 {};
00483
00484 ~MKLPardisoSparseFormat();
00485 int majorRows, majorCols, minorRows, minorCols;
00486 int nRows;
00487 int nCols;
00488 int nNonZeros;
00489 #ifdef MKL_AVAILABLE
00490 _INTEGER_t *rowIndex;
00491 _INTEGER_t *columns;
00492 _DOUBLE_PRECISION_t *values;
00493 #else
00494 int *rowIndex;
00495 int *columns;
00496 double *values;
00497 #endif
00498
00500 inline int getMajorRows() const {return majorRows;};
00501
00503 inline int getMajorCols() const {return majorCols;};
00504
00506 inline int getMinorRows() const {return minorRows;};
00507
00509 inline int getMinorCols() const {return minorCols;};
00510 };
00511
00512 #ifdef MKL_AVAILABLE
00513 void squareSymmetricSparseMatrixToPardisoFormat(const QVSparseBlockMatrix &qvspmatrix, MKLPardisoSparseFormat &pardiso);
00514 #endif
00515
00516 #endif
00517
00518
00519 #endif