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_UMFPACK_CXX 00021 00022 #include "UmfPack.hxx" 00023 00024 namespace Seldon 00025 { 00026 00028 template<class T> 00029 MatrixUmfPack_Base<T>::MatrixUmfPack_Base() 00030 { 00031 Symbolic = NULL; 00032 Numeric = NULL; 00033 n = 0; 00034 00035 // allocation of arrays Control and Info 00036 Control.Reallocate(UMFPACK_CONTROL); 00037 Info.Reallocate(UMFPACK_INFO); 00038 00039 print_level = -1; 00040 transpose = false; 00041 status_facto = 0; 00042 } 00043 00044 00046 template<class T> 00047 void MatrixUmfPack_Base<T>::HideMessages() 00048 { 00049 print_level = -1; 00050 Control(UMFPACK_PRL) = 0; 00051 } 00052 00053 00055 template<class T> 00056 void MatrixUmfPack_Base<T>::ShowMessages() 00057 { 00058 print_level = 1; 00059 Control(UMFPACK_PRL) = 2; 00060 } 00061 00062 00063 template<class T> 00064 void MatrixUmfPack_Base<T>::ShowFullHistory() 00065 { 00066 print_level = 2; 00067 } 00068 00069 00070 template<class T> 00071 int MatrixUmfPack_Base<T>::GetInfoFactorization() const 00072 { 00073 return status_facto; 00074 } 00075 00076 00077 template<class T> 00078 void MatrixUmfPack_Base<T>::SelectOrdering(int type) 00079 { 00080 Control(UMFPACK_ORDERING) = type; 00081 } 00082 00083 00084 template<class T> 00085 void MatrixUmfPack_Base<T>::SetPermutation(const IVect& permut) 00086 { 00087 throw Undefined("MatrixUmfPack_Base::SetPermutation(const Vector&)"); 00088 } 00089 00090 00092 MatrixUmfPack<double>::MatrixUmfPack() : MatrixUmfPack_Base<double>() 00093 { 00094 ptr_ = NULL; 00095 ind_ = NULL; 00096 data_ = NULL; 00097 umfpack_di_defaults(this->Control.GetData()); 00098 this->HideMessages(); 00099 } 00100 00101 00103 MatrixUmfPack<complex<double> >::MatrixUmfPack() 00104 : MatrixUmfPack_Base<complex<double> >() 00105 { 00106 ptr_ = NULL; 00107 ind_ = NULL; 00108 data_real_ = NULL; 00109 data_imag_ = NULL; 00110 umfpack_zi_defaults(this->Control.GetData()); 00111 this->HideMessages(); 00112 } 00113 00114 00116 MatrixUmfPack<double>::~MatrixUmfPack() 00117 { 00118 Clear(); 00119 } 00120 00121 00123 void MatrixUmfPack<double>::Clear() 00124 { 00125 if (this->n > 0) 00126 { 00127 // memory used for matrix is released 00128 free(ptr_); 00129 free(ind_); 00130 free(data_); 00131 00132 // memory for numbering scheme is released 00133 umfpack_di_free_symbolic(&this->Symbolic) ; 00134 00135 // memory used by LU factorization is released 00136 umfpack_di_free_numeric(&this->Numeric) ; 00137 00138 this->n = 0; 00139 this->Symbolic = NULL; 00140 this->Numeric = NULL; 00141 ptr_ = NULL; 00142 ind_ = NULL; 00143 data_ = NULL; 00144 } 00145 } 00146 00147 00149 MatrixUmfPack<complex<double> >::~MatrixUmfPack() 00150 { 00151 Clear(); 00152 } 00153 00154 00156 void MatrixUmfPack<complex<double> >::Clear() 00157 { 00158 if (this->n > 0) 00159 { 00160 // memory used for matrix is released 00161 free(ptr_); 00162 free(ind_); 00163 free(data_real_); 00164 free(data_imag_); 00165 00166 // memory for numbering scheme is released 00167 umfpack_zi_free_symbolic(&this->Symbolic) ; 00168 00169 // memory used by LU factorization is released 00170 umfpack_zi_free_numeric(&this->Numeric) ; 00171 00172 this->n = 0; 00173 this->Symbolic = NULL; 00174 this->Numeric = NULL; 00175 00176 ptr_ = NULL; 00177 ind_ = NULL; 00178 data_real_ = NULL; 00179 data_imag_ = NULL; 00180 } 00181 } 00182 00183 00185 template<class Prop, class Storage, class Allocator> 00186 void MatrixUmfPack<double>:: 00187 FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat, 00188 bool keep_matrix) 00189 { 00190 // we clear previous factorization 00191 Clear(); 00192 00193 // conversion to unsymmetric matrix in Column Sparse Column Format 00194 Matrix<double, General, ColSparse, MallocAlloc<double> > Acsc; 00195 transpose = false; 00196 00197 this->n = mat.GetM(); 00198 Copy(mat, Acsc); 00199 if (!keep_matrix) 00200 mat.Clear(); 00201 00202 // we retrieve pointers of Acsc and nullify this object 00203 ptr_ = Acsc.GetPtr(); 00204 ind_ = Acsc.GetInd(); 00205 data_ = Acsc.GetData(); 00206 Acsc.Nullify(); 00207 00208 // factorization with UmfPack 00209 umfpack_di_symbolic(this->n, this->n, ptr_, ind_, data_, &this->Symbolic, 00210 this->Control.GetData(), this->Info.GetData()); 00211 00212 // we display informations about the performed operation 00213 status_facto = 00214 umfpack_di_numeric(ptr_, ind_, data_, 00215 this->Symbolic, &this->Numeric, 00216 this->Control.GetData(), this->Info.GetData()); 00217 00218 // we display informations about the performed operation 00219 if (print_level > 1) 00220 { 00221 umfpack_di_report_status(this->Control.GetData(), status_facto); 00222 umfpack_di_report_info(this->Control.GetData(),this->Info.GetData()); 00223 } 00224 00225 if (print_level > 0) 00226 { 00227 int size_mem = (this->Info(UMFPACK_SYMBOLIC_SIZE) 00228 + this->Info(UMFPACK_NUMERIC_SIZE_ESTIMATE)) 00229 *this->Info(UMFPACK_SIZE_OF_UNIT); 00230 00231 cout << "Memory used to store LU factors: " 00232 << double(size_mem)/(1024*1024) << " MB" << endl; 00233 } 00234 } 00235 00236 00238 template<class Prop, class Allocator> 00239 void MatrixUmfPack<double> 00240 ::PerformAnalysis(Matrix<double, Prop, RowSparse, Allocator> & mat) 00241 { 00242 // we clear previous factorization 00243 Clear(); 00244 00245 // conversion to unsymmetric matrix in Column Sparse Row Format 00246 Matrix<double, General, RowSparse, MallocAlloc<double> > Acsr; 00247 transpose = true; 00248 00249 Copy(mat, Acsr); 00250 00251 // we retrieve pointers of Acsc and nullify this object 00252 this->n = mat.GetM(); 00253 ptr_ = Acsr.GetPtr(); 00254 ind_ = Acsr.GetInd(); 00255 data_ = Acsr.GetData(); 00256 Acsr.Nullify(); 00257 00258 // factorization with UmfPack 00259 umfpack_di_symbolic(this->n, this->n, ptr_, ind_, data_, &this->Symbolic, 00260 this->Control.GetData(), this->Info.GetData()); 00261 00262 } 00263 00264 00266 template<class Prop, class Allocator> 00267 void MatrixUmfPack<double> 00268 ::PerformFactorization(Matrix<double, Prop, RowSparse, Allocator> & mat) 00269 { 00270 // we copy values 00271 double* data = mat.GetData(); 00272 for (int i = 0; i < mat.GetDataSize(); i++) 00273 data_[i] = data[i]; 00274 00275 status_facto = 00276 umfpack_di_numeric(ptr_, ind_, data_, 00277 this->Symbolic, &this->Numeric, 00278 this->Control.GetData(), this->Info.GetData()); 00279 00280 // we display informations about the performed operation 00281 if (print_level > 1) 00282 { 00283 umfpack_di_report_status(this->Control.GetData(), status_facto); 00284 umfpack_di_report_info(this->Control.GetData(),this->Info.GetData()); 00285 } 00286 } 00287 00288 00290 template<class Allocator2> 00291 void MatrixUmfPack<double>::Solve(Vector<double, VectFull, Allocator2>& x) 00292 { 00293 // local copy of x 00294 Vector<double, VectFull, Allocator2> b(x); 00295 00296 int sys = UMFPACK_A; 00297 if (transpose) 00298 sys = UMFPACK_Aat; 00299 00300 int status 00301 = umfpack_di_solve(sys, ptr_, ind_, data_, x.GetData(), 00302 b.GetData(), this->Numeric, this->Control.GetData(), 00303 this->Info.GetData()); 00304 00305 // we display informations about the performed operation 00306 if (print_level > 1) 00307 umfpack_di_report_status(this->Control.GetData(), status); 00308 } 00309 00310 00311 template<class StatusTrans, class Allocator2> 00312 void MatrixUmfPack<double>::Solve(const StatusTrans& TransA, 00313 Vector<double, VectFull, Allocator2>& x) 00314 { 00315 if (TransA.NoTrans()) 00316 { 00317 Solve(x); 00318 return; 00319 } 00320 00321 // local copy of x 00322 Vector<double, VectFull, Allocator2> b(x); 00323 00324 int sys = UMFPACK_Aat; 00325 if (transpose) 00326 sys = UMFPACK_A; 00327 00328 int status 00329 = umfpack_di_solve(sys, ptr_, ind_, data_, x.GetData(), 00330 b.GetData(), this->Numeric, this->Control.GetData(), 00331 this->Info.GetData()); 00332 00333 // We display information about the performed operation. 00334 if (print_level > 1) 00335 umfpack_di_report_status(this->Control.GetData(), status); 00336 } 00337 00338 00340 template<class Prop, class Storage,class Allocator> 00341 void MatrixUmfPack<complex<double> >:: 00342 FactorizeMatrix(Matrix<complex<double>, Prop, Storage, Allocator> & mat, 00343 bool keep_matrix) 00344 { 00345 Clear(); 00346 00347 this->n = mat.GetM(); 00348 // conversion to CSC format 00349 Matrix<complex<double>, General, ColSparse, 00350 MallocAlloc<complex<double> > > Acsc; 00351 transpose = false; 00352 00353 Copy(mat, Acsc); 00354 if (!keep_matrix) 00355 mat.Clear(); 00356 00357 int nnz = Acsc.GetDataSize(); 00358 complex<double>* data = Acsc.GetData(); 00359 int* ptr = Acsc.GetPtr(); 00360 int* ind = Acsc.GetInd(); 00361 Vector<double, VectFull, MallocAlloc<double> > 00362 ValuesReal(nnz), ValuesImag(nnz); 00363 00364 Vector<int, VectFull, MallocAlloc<int> > Ptr(this->n+1), Ind(nnz); 00365 00366 for (int i = 0; i < nnz; i++) 00367 { 00368 ValuesReal(i) = real(data[i]); 00369 ValuesImag(i) = imag(data[i]); 00370 Ind(i) = ind[i]; 00371 } 00372 00373 for (int i = 0; i <= this->n; i++) 00374 Ptr(i) = ptr[i]; 00375 00376 // we clear intermediary matrix Acsc 00377 Acsc.Clear(); 00378 00379 // retrieve pointers and nullify Seldon vectors 00380 data_real_ = ValuesReal.GetData(); 00381 data_imag_ = ValuesImag.GetData(); 00382 ptr_ = Ptr.GetData(); 00383 ind_ = Ind.GetData(); 00384 ValuesReal.Nullify(); ValuesImag.Nullify(); 00385 Ptr.Nullify(); Ind.Nullify(); 00386 00387 // we call UmfPack 00388 umfpack_zi_symbolic(this->n, this->n, ptr_, ind_, 00389 data_real_, data_imag_, 00390 &this->Symbolic, this->Control.GetData(), 00391 this->Info.GetData()); 00392 00393 status_facto 00394 = umfpack_zi_numeric(ptr_, ind_, data_real_, data_imag_, 00395 this->Symbolic, &this->Numeric, 00396 this->Control.GetData(), this->Info.GetData()); 00397 00398 if (print_level > 1) 00399 { 00400 umfpack_zi_report_status(this->Control.GetData(), status_facto); 00401 umfpack_zi_report_info(this->Control.GetData(), this->Info.GetData()); 00402 } 00403 00404 if (print_level > 0) 00405 { 00406 int size_mem = (this->Info(UMFPACK_SYMBOLIC_SIZE) 00407 + this->Info(UMFPACK_NUMERIC_SIZE_ESTIMATE)) 00408 *this->Info(UMFPACK_SIZE_OF_UNIT); 00409 00410 cout << "Estimated memory used to store LU factors: " 00411 << double(size_mem)/(1024*1024) << " MB" << endl; 00412 } 00413 } 00414 00415 00417 template<class Allocator2> 00418 void MatrixUmfPack<complex<double> >:: 00419 Solve(Vector<complex<double>, VectFull, Allocator2>& x) 00420 { 00421 Solve(SeldonNoTrans, x); 00422 } 00423 00424 00426 template<class StatusTrans, class Allocator2> 00427 void MatrixUmfPack<complex<double> >:: 00428 Solve(const StatusTrans& TransA, 00429 Vector<complex<double>, VectFull, Allocator2>& x) 00430 { 00431 int m = x.GetM(); 00432 // creation of vectors 00433 Vector<double> b_real(m), b_imag(m); 00434 for (int i = 0; i < m; i++) 00435 { 00436 b_real(i) = real(x(i)); 00437 b_imag(i) = imag(x(i)); 00438 } 00439 00440 Vector<double> x_real(m), x_imag(m); 00441 x_real.Zero(); 00442 x_imag.Zero(); 00443 00444 int sys = UMFPACK_A; 00445 if (TransA.Trans()) 00446 sys = UMFPACK_Aat; 00447 00448 int status 00449 = umfpack_zi_solve(sys, ptr_, ind_, data_real_, data_imag_, 00450 x_real.GetData(), x_imag.GetData(), 00451 b_real.GetData(), b_imag.GetData(), 00452 this->Numeric, 00453 this->Control.GetData(), this->Info.GetData()); 00454 b_real.Clear(); 00455 b_imag.Clear(); 00456 00457 for (int i = 0; i < m; i++) 00458 x(i) = complex<double>(x_real(i), x_imag(i)); 00459 00460 if (print_level > 1) 00461 umfpack_zi_report_status(this->Control.GetData(), status); 00462 } 00463 00464 00466 template<class T, class Prop, class Storage, class Allocator> 00467 void GetLU(Matrix<T, Prop, Storage, Allocator>& A, MatrixUmfPack<T>& mat_lu, 00468 bool keep_matrix = false) 00469 { 00470 mat_lu.FactorizeMatrix(A, keep_matrix); 00471 } 00472 00473 00475 template<class T, class Allocator> 00476 void SolveLU(MatrixUmfPack<T>& mat_lu, Vector<T, VectFull, Allocator>& x) 00477 { 00478 mat_lu.Solve(x); 00479 } 00480 00481 00482 template<class T, class Allocator> 00483 void SolveLU(const SeldonTranspose& TransA, 00484 MatrixUmfPack<T>& mat_lu, Vector<T, VectFull, Allocator>& x) 00485 { 00486 mat_lu.Solve(TransA, x); 00487 } 00488 00489 } 00490 00491 #define SELDON_FILE_UMFPACK_CXX 00492 #endif