00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_SUPERLU_CXX
00021
00022 #include "SuperLU.hxx"
00023
00024
00025
00026
00027
00028 void LUextract(SuperMatrix *L, SuperMatrix *U, double *Lval, int *Lrow,
00029 int *Lcol, double *Uval, int *Urow, int *Ucol, int *snnzL,
00030 int *snnzU)
00031 {
00032 int i, j, k;
00033 int upper;
00034 int fsupc, istart, nsupr;
00035 int lastl = 0, lastu = 0;
00036 SCformat *Lstore;
00037 NCformat *Ustore;
00038 double *SNptr;
00039
00040 Lstore = static_cast<SCformat*>(L->Store);
00041 Ustore = static_cast<NCformat*>(U->Store);
00042 Lcol[0] = 0;
00043 Ucol[0] = 0;
00044
00045
00046 for (k = 0; k <= Lstore->nsuper; ++k) {
00047
00048 fsupc = L_FST_SUPC(k);
00049 istart = L_SUB_START(fsupc);
00050 nsupr = L_SUB_START(fsupc+1) - istart;
00051 upper = 1;
00052
00053
00054 for (j = fsupc; j < L_FST_SUPC(k+1); ++j) {
00055 SNptr = &(static_cast<double*>(Lstore->nzval))[L_NZ_START(j)];
00056
00057
00058 for (i = U_NZ_START(j); i < U_NZ_START(j+1); ++i) {
00059 Uval[lastu] = (static_cast<double*>(Ustore->nzval))[i];
00060 Urow[lastu++] = U_SUB(i);
00061 }
00062 for (i = 0; i < upper; ++i) {
00063 Uval[lastu] = SNptr[i];
00064 Urow[lastu++] = L_SUB(istart+i);
00065 }
00066 Ucol[j+1] = lastu;
00067
00068
00069 Lval[lastl] = 1.0;
00070 Lrow[lastl++] = L_SUB(istart + upper - 1);
00071 for (i = upper; i < nsupr; ++i) {
00072 Lval[lastl] = SNptr[i];
00073 Lrow[lastl++] = L_SUB(istart+i);
00074 }
00075 Lcol[j+1] = lastl;
00076
00077 ++upper;
00078
00079 }
00080
00081 }
00082
00083 *snnzL = lastl;
00084 *snnzU = lastu;
00085 }
00086
00087
00088 namespace Seldon
00089 {
00091 template<class T>
00092 MatrixSuperLU_Base<T>::MatrixSuperLU_Base()
00093 {
00094 n = 0;
00095 permc_spec = COLAMD;
00096 Lstore = NULL;
00097 Ustore = NULL;
00098 StatInit(&stat);
00099 set_default_options(&options);
00100 ShowMessages();
00101 display_info = false;
00102 info_facto = 0;
00103 }
00104
00105
00107 template<class T>
00108 MatrixSuperLU_Base<T>::~MatrixSuperLU_Base()
00109 {
00110 Clear();
00111 }
00112
00113
00115
00124 template<class T>
00125 template<class Prop, class Allocator>
00126 void MatrixSuperLU_Base<T>
00127 ::GetLU(Matrix<double, Prop, ColSparse, Allocator>& Lmat,
00128 Matrix<double, Prop, ColSparse, Allocator>& Umat,
00129 bool permuted)
00130 {
00131 Lstore = static_cast<SCformat*>(L.Store);
00132 Ustore = static_cast<NCformat*>(U.Store);
00133
00134 int Lnnz = Lstore->nnz;
00135 int Unnz = Ustore->nnz;
00136
00137 int m = U.nrow;
00138 int n = U.ncol;
00139
00140 Vector<double, VectFull, Allocator> Lval(Lnnz);
00141 Vector<int, VectFull, CallocAlloc<int> > Lrow(Lnnz);
00142 Vector<int, VectFull, CallocAlloc<int> > Lcol(n + 1);
00143
00144 Vector<double, VectFull, Allocator> Uval(Unnz);
00145 Vector<int, VectFull, CallocAlloc<int> > Urow(Unnz);
00146 Vector<int, VectFull, CallocAlloc<int> > Ucol(n + 1);
00147
00148 int Lsnnz;
00149 int Usnnz;
00150 LUextract(&L, &U, Lval.GetData(), Lrow.GetData(), Lcol.GetData(),
00151 Uval.GetData(), Urow.GetData(), Ucol.GetData(), &Lsnnz, &Usnnz);
00152
00153 Lmat.SetData(m, n, Lval, Lcol, Lrow);
00154 Umat.SetData(m, n, Uval, Ucol, Urow);
00155
00156 if (!permuted)
00157 {
00158 Vector<int> row_perm_orig = perm_r;
00159 Vector<int> col_perm_orig = perm_c;
00160
00161 Vector<int> row_perm(n);
00162 Vector<int> col_perm(n);
00163 row_perm.Fill();
00164 col_perm.Fill();
00165
00166 Sort(row_perm_orig, row_perm);
00167 Sort(col_perm_orig, col_perm);
00168
00169 ApplyInversePermutation(Lmat, row_perm, col_perm);
00170 ApplyInversePermutation(Umat, row_perm, col_perm);
00171 }
00172 }
00173
00174
00176
00187 template<class T>
00188 template<class Prop, class Allocator>
00189 void MatrixSuperLU_Base<T>
00190 ::GetLU(Matrix<double, Prop, RowSparse, Allocator>& Lmat,
00191 Matrix<double, Prop, RowSparse, Allocator>& Umat,
00192 bool permuted)
00193 {
00194 Lmat.Clear();
00195 Umat.Clear();
00196
00197 Matrix<double, Prop, ColSparse, Allocator> Lmat_col;
00198 Matrix<double, Prop, ColSparse, Allocator> Umat_col;
00199 GetLU(Lmat_col, Umat_col, permuted);
00200
00201 Copy(Lmat_col, Lmat);
00202 Lmat_col.Clear();
00203 Copy(Umat_col, Umat);
00204 Umat_col.Clear();
00205 }
00206
00207
00209
00215 template<class T>
00216 const Vector<int>& MatrixSuperLU_Base<T>::GetRowPermutation() const
00217 {
00218 return perm_r;
00219 }
00220
00221
00223
00229 template<class T>
00230 const Vector<int>& MatrixSuperLU_Base<T>::GetColPermutation() const
00231 {
00232 return perm_c;
00233 }
00234
00235
00236 template<class T>
00237 void MatrixSuperLU_Base<T>::SelectOrdering(colperm_t type)
00238 {
00239 permc_spec = type;
00240 }
00241
00242
00243 template<class T>
00244 void MatrixSuperLU_Base<T>::SetPermutation(const IVect& permut)
00245 {
00246 permc_spec = MY_PERMC;
00247 perm_c = permut;
00248 perm_r = permut;
00249 }
00250
00251
00253 template<class T>
00254 void MatrixSuperLU_Base<T>::Clear()
00255 {
00256 if (n > 0)
00257 {
00258
00259 Destroy_SuperMatrix_Store(&B);
00260 Destroy_SuperNode_Matrix(&L);
00261 Destroy_CompCol_Matrix(&U);
00262 perm_r.Clear();
00263 perm_c.Clear();
00264 n = 0;
00265 }
00266 }
00267
00268
00270 template<class T>
00271 void MatrixSuperLU_Base<T>::HideMessages()
00272 {
00273 display_info = false;
00274 }
00275
00276
00278 template<class T>
00279 void MatrixSuperLU_Base<T>::ShowMessages()
00280 {
00281 display_info = true;
00282 }
00283
00284
00285 template<class T>
00286 int MatrixSuperLU_Base<T>::GetInfoFactorization() const
00287 {
00288 return info_facto;
00289 }
00290
00291
00293 template<class Prop, class Storage, class Allocator>
00294 void MatrixSuperLU<double>::
00295 FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat,
00296 bool keep_matrix)
00297 {
00298
00299 Clear();
00300
00301
00302 n = mat.GetN();
00303 Matrix<double, General, ColSparse> Acsr;
00304 Copy(mat, Acsr);
00305 if (!keep_matrix)
00306 mat.Clear();
00307
00308 SuperMatrix A, AA;
00309 int nnz = Acsr.GetDataSize();
00310 dCreate_CompCol_Matrix(&AA, n, n, nnz, Acsr.GetData(), Acsr.GetInd(),
00311 Acsr.GetPtr(), SLU_NC, SLU_D, SLU_GE);
00312
00313
00314 options.ColPerm = permc_spec;
00315 if (permc_spec != MY_PERMC)
00316 {
00317 perm_r.Reallocate(n);
00318 perm_c.Reallocate(n);
00319 perm_r.Fill();
00320 perm_c.Fill();
00321
00322 get_perm_c(permc_spec, &AA, perm_c.GetData());
00323 }
00324
00325
00326 Vector<int> etree(n);
00327 sp_preorder(&options, &AA, perm_c.GetData(), etree.GetData(), &A);
00328
00329 int panel_size = sp_ienv(1);
00330 int relax = sp_ienv(2);
00331 int lwork = 0;
00332
00333
00334 dgstrf(&options, &A, relax, panel_size, etree.GetData(),
00335 NULL, lwork, perm_c.GetData(), perm_r.GetData(), &L, &U, &stat,
00336 &info_facto);
00337
00338
00339 Destroy_CompCol_Permuted(&A);
00340 Destroy_CompCol_Matrix(&AA);
00341
00342 if (info_facto == 0 && display_info)
00343 {
00344 mem_usage_t mem_usage;
00345 Lstore = (SCformat *) L.Store;
00346 Ustore = (NCformat *) U.Store;
00347 cout << "Number of nonzeros in factor L = " << Lstore->nnz << endl;
00348 cout << "Number of nonzeros in factor U = " << Ustore->nnz << endl;
00349 cout << "Number of nonzeros in L+U = "
00350 << Lstore->nnz + Ustore->nnz << endl;
00351 dQuerySpace(&L, &U, &mem_usage);
00352 cout << "Memory used for factorization in MB: "
00353 << mem_usage.total_needed / (1024. * 1024.) << endl;
00354 }
00355
00356 Acsr.Nullify();
00357 }
00358
00359
00361 template<class Allocator2>
00362 void MatrixSuperLU<double>::Solve(Vector<double, VectFull, Allocator2>& x)
00363 {
00364 trans_t trans = NOTRANS;
00365 int nb_rhs = 1, info;
00366
00367 dCreate_Dense_Matrix(&B, x.GetM(), nb_rhs,
00368 x.GetData(), x.GetM(), SLU_DN, SLU_D, SLU_GE);
00369
00370 SuperLUStat_t stat;
00371 StatInit(&stat);
00372
00373 dgstrs(trans, &L, &U, perm_r.GetData(),
00374 perm_c.GetData(), &B, &stat, &info);
00375 }
00376
00377
00379 template<class TransStatus, class Allocator2>
00380 void MatrixSuperLU<double>::Solve(const TransStatus& TransA,
00381 Vector<double, VectFull, Allocator2>& x)
00382 {
00383 if (TransA.NoTrans())
00384 {
00385 Solve(x);
00386 return;
00387 }
00388
00389 trans_t trans = TRANS;
00390 int nb_rhs = 1, info;
00391
00392 dCreate_Dense_Matrix(&B, x.GetM(), nb_rhs,
00393 x.GetData(), x.GetM(), SLU_DN, SLU_D, SLU_GE);
00394
00395 SuperLUStat_t stat;
00396 StatInit(&stat);
00397
00398 dgstrs(trans, &L, &U, perm_r.GetData(),
00399 perm_c.GetData(), &B, &stat, &info);
00400 }
00401
00402
00404 template<class Prop, class Storage, class Allocator>
00405 void MatrixSuperLU<complex<double> >::
00406 FactorizeMatrix(Matrix<complex<double>, Prop, Storage, Allocator> & mat,
00407 bool keep_matrix)
00408 {
00409
00410 Clear();
00411
00412
00413 n = mat.GetN();
00414 Matrix<complex<double>, General, ColSparse> Acsr;
00415 Copy(mat, Acsr);
00416 if (!keep_matrix)
00417 mat.Clear();
00418
00419 SuperMatrix AA, A;
00420 int nnz = Acsr.GetDataSize();
00421 zCreate_CompCol_Matrix(&AA, n, n, nnz,
00422 reinterpret_cast<doublecomplex*>(Acsr.GetData()),
00423 Acsr.GetInd(), Acsr.GetPtr(),
00424 SLU_NC, SLU_Z, SLU_GE);
00425
00426
00427 options.ColPerm = permc_spec;
00428 if (permc_spec != MY_PERMC)
00429 {
00430 perm_r.Reallocate(n);
00431 perm_c.Reallocate(n);
00432 perm_r.Fill();
00433 perm_c.Fill();
00434
00435 get_perm_c(permc_spec, &AA, perm_c.GetData());
00436 }
00437
00438
00439 Vector<int> etree(n);
00440 sp_preorder(&options, &AA, perm_c.GetData(), etree.GetData(), &A);
00441
00442 int panel_size = sp_ienv(1);
00443 int relax = sp_ienv(2);
00444 int lwork = 0;
00445
00446
00447 zgstrf(&options, &A, relax, panel_size, etree.GetData(),
00448 NULL, lwork, perm_c.GetData(), perm_r.GetData(), &L, &U, &stat,
00449 &info_facto);
00450
00451
00452 Destroy_CompCol_Permuted(&A);
00453 Destroy_CompCol_Matrix(&AA);
00454
00455 if (info_facto == 0 && display_info)
00456 {
00457 mem_usage_t mem_usage;
00458 Lstore = (SCformat *) L.Store;
00459 Ustore = (NCformat *) U.Store;
00460 cout << "Number of nonzeros in factor L = " << Lstore->nnz<<endl;
00461 cout << "Number of nonzeros in factor U = " << Ustore->nnz<<endl;
00462 cout << "Number of nonzeros in L+U = "
00463 << Lstore->nnz + Ustore->nnz<<endl;
00464 zQuerySpace(&L, &U, &mem_usage);
00465 cout << "Memory used for factorization in MB: "
00466 << mem_usage.total_needed / (1024. * 1024.) << endl;
00467 }
00468
00469 Acsr.Nullify();
00470 }
00471
00472
00474 template<class Allocator2>
00475 void MatrixSuperLU<complex<double> >::
00476 Solve(Vector<complex<double>, VectFull, Allocator2>& x)
00477 {
00478 trans_t trans = NOTRANS;
00479 int nb_rhs = 1, info;
00480 zCreate_Dense_Matrix(&B, x.GetM(), nb_rhs,
00481 reinterpret_cast<doublecomplex*>(x.GetData()),
00482 x.GetM(), SLU_DN, SLU_Z, SLU_GE);
00483
00484 zgstrs(trans, &L, &U, perm_c.GetData(),
00485 perm_r.GetData(), &B, &stat, &info);
00486 }
00487
00488
00490 template<class TransStatus, class Allocator2>
00491 void MatrixSuperLU<complex<double> >::
00492 Solve(const TransStatus& TransA,
00493 Vector<complex<double>, VectFull, Allocator2>& x)
00494 {
00495 if (TransA.NoTrans())
00496 {
00497 Solve(x);
00498 return;
00499 }
00500
00501 trans_t trans = TRANS;
00502 int nb_rhs = 1, info;
00503 zCreate_Dense_Matrix(&B, x.GetM(), nb_rhs,
00504 reinterpret_cast<doublecomplex*>(x.GetData()),
00505 x.GetM(), SLU_DN, SLU_Z, SLU_GE);
00506
00507 zgstrs(trans, &L, &U, perm_c.GetData(),
00508 perm_r.GetData(), &B, &stat, &info);
00509 }
00510
00511
00512 template<class T, class Prop, class Storage, class Allocator>
00513 void GetLU(Matrix<T, Prop, Storage, Allocator>& A, MatrixSuperLU<T>& mat_lu,
00514 bool keep_matrix = false)
00515 {
00516 mat_lu.FactorizeMatrix(A, keep_matrix);
00517 }
00518
00519
00520 template<class T, class Allocator>
00521 void SolveLU(MatrixSuperLU<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00522 {
00523 mat_lu.Solve(x);
00524 }
00525
00526
00527 template<class T, class Allocator>
00528 void SolveLU(const SeldonTranspose& TransA,
00529 MatrixSuperLU<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00530 {
00531 mat_lu.Solve(TransA, x);
00532 }
00533
00534 }
00535
00536 #define SELDON_FILE_SUPERLU_CXX
00537 #endif