00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QVSparseBlockMatrix>
00026
00027 #ifdef MKL_AVAILABLE
00028 #include "mkl_dss.h"
00029 #endif
00030
00031 QVSparseBlockMatrix QVSparseBlockMatrix::transpose() const
00032 {
00033 QVSparseBlockMatrix result(majorCols, majorRows, minorCols, minorRows);
00034
00035 for(int i = 0; i < majorRows; i++)
00036 for(int j = 0; j < majorCols; j++)
00037 if (operator[](i)[j] != QVMatrix())
00038 result[j][i] = operator[](i)[j].transpose();
00039
00040 return result;
00041 }
00042
00043 QVSparseBlockMatrix QVSparseBlockMatrix::dotProduct(const QVSparseBlockMatrix &other,
00044 const bool transposeFirstOperand,
00045 const bool transposeSecondOperand) const
00046 {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 if (transposeSecondOperand)
00064 std::cout << "Warning: dotProduct method can't perform the multiplication transposing the second term matrix yet. " << std::endl;
00065
00066 QVSparseBlockMatrix result( transposeFirstOperand? majorCols : majorRows,
00067 other.majorCols,
00068 transposeFirstOperand? minorCols: minorRows,
00069 other.minorCols);
00070
00071 foreach(int index1r, keys())
00072 {
00073 const QMap<int, QVMatrix> & majorRowFirstOperand = operator[](index1r);
00074
00075 foreach(int index1c, majorRowFirstOperand.keys())
00076 {
00077 const QVMatrix & actual = majorRowFirstOperand[index1c];
00078
00079 const int i_ = transposeFirstOperand? index1c : index1r,
00080 k_ =transposeFirstOperand? index1r : index1c;
00081
00082 const QMap<int, QVMatrix> & majorRowSecondOperand = other[k_];
00083 QMap<int, QVMatrix> & majorRowResult = result[i_];
00084
00085 foreach(int j, majorRowSecondOperand.keys())
00086 {
00087 QVMatrix &res = majorRowResult[j];
00088
00089 if (res == QVMatrix())
00090 res = actual.dotProduct(majorRowSecondOperand[j], transposeFirstOperand, false);
00091 else
00093 res += actual.dotProduct(majorRowSecondOperand[j], transposeFirstOperand, false);
00094 }
00095 }
00096 }
00097 return result;
00098 }
00099
00100 QVVector QVSparseBlockMatrix::dotProduct(const QVVector &vector, const bool transposeMatrix) const
00101 {
00102 const int majorSourceIndex = transposeMatrix? majorRows: majorCols,
00103 minorSourceIndex = transposeMatrix? minorRows: minorCols;
00104
00105 const int majorDestinationIndex = transposeMatrix? majorCols: majorRows,
00106 minorDestinationIndex = transposeMatrix? minorCols: minorRows;
00107
00108
00109 QVector< QVVector > sparseBlockVector(majorSourceIndex);
00110 for(int i = 0; i < majorSourceIndex; i++)
00111 sparseBlockVector[i] = vector.mid(i*minorSourceIndex, minorSourceIndex);
00112
00113
00114 QVector< QVVector > sparseBlockResult(majorDestinationIndex, QVVector(minorDestinationIndex, 0.0));
00115 foreach(int i, keys())
00116 {
00117 const QMap<int, QVMatrix> & majorRow = operator[](i);
00118 foreach(int j, majorRow.keys())
00119 if (not transposeMatrix)
00121 sparseBlockResult[i] += majorRow[j].dotProduct(sparseBlockVector[j], transposeMatrix);
00122 else
00123 sparseBlockResult[j] += majorRow[j].dotProduct(sparseBlockVector[i], transposeMatrix);
00124 }
00125
00126
00127 QVVector result(majorDestinationIndex*minorDestinationIndex);
00128 double *resultPtr = result.data();
00129
00130 int i = 0;
00131 foreach(QVVector v, sparseBlockResult)
00132 {
00133 const double *vPtr = v.constData();
00134 double *blockVectorPtr = resultPtr + minorDestinationIndex*i;
00135
00136 for(int j = 0; j < minorDestinationIndex; j++)
00137 blockVectorPtr[j] = vPtr[j];
00138 i++;
00139 }
00140
00141 return result;
00142 }
00143
00144 QVSparseBlockMatrix & QVSparseBlockMatrix::operator=(const QVSparseBlockMatrix &other)
00145 {
00146 majorRows = other.majorRows;
00147 majorCols = other.majorCols;
00148 minorRows = other.minorRows;
00149 minorCols = other.minorCols;
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 QMap<int, QMap<int, QVMatrix> >::operator=(other);
00160 return *this;
00161 }
00162
00163
00164
00165 QVSparseBlockMatrix QVSparseBlockMatrix::randomSquare(const int NB,const int N, const double NZProb, const bool symmetric, const bool positive)
00166 {
00167 QVSparseBlockMatrix result(NB,NB,N,N);
00168
00169 if(symmetric and positive) {
00170 QVSparseBlockMatrix inter(NB*(NB+1)/2,NB,N,N);
00171
00172 int row = 0;
00173 for(int i=0;i<NB;i++) {
00174 for(int j=i;j<NB;j++) {
00175 double roulette=random(0.0,1.0);
00176 if( (i==j) or (roulette <= NZProb)) {
00177 inter.setBlock(row,i,QVMatrix::random(N,N));
00178 inter.setBlock(row,j,QVMatrix::random(N,N));
00179 }
00180 row++;
00181 }
00182 }
00183
00184 result = inter.dotProduct(inter,true,false);
00185 } else if (symmetric and not positive) {
00186 for(int i=0;i<NB;i++) {
00187 for(int j=i;j<NB;j++) {
00188 double roulette=random(0.0,1.0);
00189 if( (i==j) or (roulette <= NZProb)) {
00190 QVMatrix inter = QVMatrix::random(N,N);
00191 if(i==j)
00192 result.setBlock(i,j,(inter+inter.transpose())/2);
00193 else {
00194 result.setBlock(j,i,inter);
00195 result.setBlock(i,j,inter.transpose());
00196 }
00197 }
00198 }
00199 }
00200 } else if (not symmetric and not positive) {
00201 for(int i=0;i<NB;i++) {
00202 for(int j=0;j<NB;j++) {
00203 double roulette=random(0.0,1.0);
00204 if( (i==j) or (roulette <= NZProb)) {
00205 QVMatrix inter = QVMatrix::random(N,N);
00206 result.setBlock(i,j,inter);
00207 }
00208 }
00209 }
00210 } else {
00211 qFatal("QVSparseBlockMatrix::randomSquare(): not symmetric and positive definite matrix requested");
00212 }
00213
00214 return result;
00215 }
00216
00217
00218
00219
00220 #ifdef MKL_AVAILABLE
00221 MKLPardisoSparseFormat::MKLPardisoSparseFormat(const QVSparseBlockMatrix qvspmatrix, bool isSymmetric):
00222 majorRows(qvspmatrix.getMajorRows()), majorCols(qvspmatrix.getMajorCols()),
00223 minorRows(qvspmatrix.getMinorRows()), minorCols(qvspmatrix.getMinorCols())
00224 {
00225
00226 int sbr = qvspmatrix.getMinorRows();
00227 int sbc = qvspmatrix.getMinorCols();
00228
00229 int br = qvspmatrix.getMajorRows();
00230 int bc = qvspmatrix.getMajorCols();
00231
00232
00233 nRows = sbr*br;
00234 nCols = sbc*bc;
00235
00236
00237 int tb = 0, nmd = 0;
00238 foreach(int ib, qvspmatrix.keys())
00239 foreach(int jb, qvspmatrix[ib].keys())
00240 {
00241 if(isSymmetric)
00242 {
00243 if(ib <= jb)
00244 tb++;
00245 if(ib == jb)
00246 nmd++;
00247 }
00248 else
00249 tb++;
00250 }
00251
00252
00253 nNonZeros = tb*sbr*sbc;
00254 if(isSymmetric)
00255 nNonZeros -= nmd*(sbr>sbc ? sbr*sbc-sbc*(sbc+1)/2 : sbr*(sbr-1)/2);
00256
00257
00258 rowIndex = new _INTEGER_t [nRows+1];
00259 columns = (nNonZeros==0) ? NULL : new _INTEGER_t [nNonZeros];
00260 values = (nNonZeros==0) ? NULL : new _DOUBLE_PRECISION_t [nNonZeros];
00261 int indexvalues = 0, indexrows = 0;
00262 foreach(int ib, qvspmatrix.keys())
00263 {
00264 const QMap<int, QVMatrix> &majorRow = qvspmatrix[ib];
00265
00266 for(int i=0;i<sbr;i++)
00267 {
00268 rowIndex[indexrows] = indexvalues + 1;
00269 foreach(int jb, majorRow.keys())
00270 {
00271 int increment = 0;
00272 for(int j=0;j<sbc;j++)
00273 {
00274 if(isSymmetric and ( (ib > jb) or ( (ib == jb) and (i > j) ) ) )
00275 continue;
00276 values[indexvalues] = majorRow[jb](i,j);
00277 columns[indexvalues] = jb*sbc + j + 1;
00278 indexvalues++;
00279 increment++;
00280 }
00281
00282
00283
00284 }
00285 indexrows++;
00286 }
00287 }
00288 rowIndex[indexrows] = indexvalues + 1;
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 }
00301
00302 MKLPardisoSparseFormat::~MKLPardisoSparseFormat()
00303 {
00304 if(rowIndex != NULL) delete [] rowIndex;
00305 if(columns != NULL) delete [] columns;
00306 if(values != NULL) delete [] values;
00307 }
00308
00309 void squareSymmetricSparseMatrixToPardisoFormat(const QVSparseBlockMatrix &qvspmatrix, MKLPardisoSparseFormat &pardiso)
00310 {
00311
00312 pardiso.majorRows = qvspmatrix.getMajorRows();
00313 pardiso.majorCols = qvspmatrix.getMajorCols();
00314 pardiso.minorRows = qvspmatrix.getMinorRows();
00315 pardiso.minorCols = qvspmatrix.getMinorCols();
00316
00317
00318
00319 int sbr = qvspmatrix.getMinorRows();
00320 int sbc = qvspmatrix.getMinorCols();
00321
00322
00323 int br = qvspmatrix.getMajorRows();
00324 int bc = qvspmatrix.getMajorCols();
00325
00326 if (br != bc)
00327 {
00328 std::cout << "ERROR 01" << std::endl;
00329 exit(0);
00330 }
00331
00332 if (sbr != sbc)
00333 {
00334 std::cout << "ERROR 02" << std::endl;
00335 exit(0);
00336 }
00337
00338
00339 pardiso.nRows = sbr*br;
00340 pardiso.nCols = sbc*bc;
00341
00342
00343
00344
00345 pardiso.nNonZeros = qvspmatrix.blockCount * sbc * sbr - bc * sbr*(sbr-1)/2;
00346 pardiso.rowIndex = new int [pardiso.nRows+2];
00347 pardiso.columns = new int [pardiso.nNonZeros];
00348 pardiso.values = new double [pardiso.nNonZeros];
00349
00350
00351 int tempIndex = 0, tempCount = 1;
00352 foreach(int ib, qvspmatrix.keys())
00353 {
00354 const QMap<int, QVMatrix> &majorRow = qvspmatrix[ib];
00355
00356 for(int i = 0; i < sbr; tempCount += sbc*majorRow.count() - i, i++)
00357 pardiso.rowIndex[tempIndex++] = tempCount;
00358 pardiso.rowIndex[tempIndex] = tempCount;
00359
00360 int rowBlockCount = 0;
00361 foreach(int jb, majorRow.keys())
00362 {
00363 const double *matrixData = majorRow[jb].getReadData();
00364 for(int i=0;i<sbr;i++)
00365 {
00366 if (ib > jb)
00367 {
00368 std::cout << "------------------ ***** &&& Error 989577546435634 *********** -----------------" << std::endl;
00369 continue;
00370 }
00371
00372 const double *rowData = matrixData + sbc*i;
00373 int indexvalues = pardiso.rowIndex[ib * sbr + i]-1 + rowBlockCount * sbc - ((ib != jb)?i:0);
00374
00375 for(int j=0;j<sbc;j++)
00376 {
00377 if( (ib == jb) and (i > j) )
00378 continue;
00379
00380 pardiso.values[indexvalues] = rowData[j];
00381 pardiso.columns[indexvalues] = jb*sbc + j + 1;
00382 indexvalues++;
00383 }
00384 }
00385 rowBlockCount++;
00386 }
00387 }
00388 }
00389 #endif