computation/interfaces/direct/UmfPack.cxx

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