Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2003-2009 Marc Duruflé 00002 // 00003 // This file is part of the linear-algebra library Seldon, 00004 // http://seldon.sourceforge.net/. 00005 // 00006 // Seldon is free software; you can redistribute it and/or modify it under the 00007 // terms of the GNU Lesser General Public License as published by the Free 00008 // Software Foundation; either version 2.1 of the License, or (at your option) 00009 // any later version. 00010 // 00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00014 // more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00018 00019 00020 #ifndef SELDON_FILE_SUPERLU_CXX 00021 00022 #include "SuperLU.hxx" 00023 00024 // The function comes from the Matlab interface to SuperLU. It is part of 00025 // SuperLU package. Its copyright is held by University of California 00026 // Berkeley, Xerox Palo Alto Research Center and Lawrence Berkeley National 00027 // Lab. It is released under a license compatible with the GNU LGPL. 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 /* for each supernode */ 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 /* for each column in the supernode */ 00054 for (j = fsupc; j < L_FST_SUPC(k+1); ++j) { 00055 SNptr = &(static_cast<double*>(Lstore->nzval))[L_NZ_START(j)]; 00056 00057 /* Extract U */ 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) { /* upper triangle in the supernode */ 00063 Uval[lastu] = SNptr[i]; 00064 Urow[lastu++] = L_SUB(istart+i); 00065 } 00066 Ucol[j+1] = lastu; 00067 00068 /* Extract L */ 00069 Lval[lastl] = 1.0; /* unit diagonal */ 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 } /* for j ... */ 00080 00081 } /* for k ... */ 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 // SuperLU objects are cleared 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 // clearing previous factorization 00299 Clear(); 00300 00301 // conversion in CSC format 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 // we get renumbering vectors perm_r and perm_c 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 // Original matrix AA is permuted to obtain matrix A. 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 // Then calling factorization on permuted matrix. 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 // Clearing matrices. 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 // Putting right hand side on SuperLU structure. 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 // Solving A x = b. 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 // Putting right hand side on SuperLU structure. 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 // Solving A^T x = b. 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 // clearing previous factorization 00410 Clear(); 00411 00412 // conversion in CSR format 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 // We get renumbering vectors perm_r and perm_c. 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 // Permuting matrix. 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 // Factorization. 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 // Clearing matrices. 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