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     display_info = false;
00040     transpose = false;
00041   }
00042 
00043 
00045   template<class T>
00046   void MatrixUmfPack_Base<T>::HideMessages()
00047   {
00048     display_info = false;
00049     Control(UMFPACK_PRL) = 0;
00050   }
00051 
00052 
00054   template<class T>
00055   void MatrixUmfPack_Base<T>::ShowMessages()
00056   {
00057     display_info = true;
00058     Control(UMFPACK_PRL) = 2;
00059   }
00060 
00061 
00063   MatrixUmfPack<double>::MatrixUmfPack() : MatrixUmfPack_Base<double>()
00064   {
00065     ptr_ = NULL;
00066     ind_ = NULL;
00067     data_ = NULL;
00068     umfpack_di_defaults(this->Control.GetData());
00069     this->HideMessages();
00070   }
00071 
00072 
00074   MatrixUmfPack<complex<double> >::MatrixUmfPack()
00075     : MatrixUmfPack_Base<complex<double> >()
00076   {
00077     ptr_ = NULL;
00078     ind_ = NULL;
00079     data_real_ = NULL;
00080     data_imag_ = NULL;
00081     umfpack_zi_defaults(this->Control.GetData());
00082     this->HideMessages();
00083   }
00084 
00085 
00087   MatrixUmfPack<double>::~MatrixUmfPack()
00088   {
00089     Clear();
00090   }
00091 
00092 
00094   void MatrixUmfPack<double>::Clear()
00095   {
00096     if (this->n > 0)
00097       {
00098         // memory used for matrix is released
00099         free(ptr_);
00100         free(ind_);
00101         free(data_);
00102 
00103         // memory for numbering scheme is released
00104         umfpack_di_free_symbolic(&this->Symbolic) ;
00105 
00106         // memory used by LU factorization is released
00107         umfpack_di_free_numeric(&this->Numeric) ;
00108 
00109         this->n = 0;
00110         this->Symbolic = NULL;
00111         this->Numeric = NULL;
00112         ptr_ = NULL;
00113         ind_ = NULL;
00114         data_ = NULL;
00115       }
00116   }
00117 
00118 
00120   MatrixUmfPack<complex<double> >::~MatrixUmfPack()
00121   {
00122     Clear();
00123   }
00124 
00125 
00127   void MatrixUmfPack<complex<double> >::Clear()
00128   {
00129     if (this->n > 0)
00130       {
00131         // memory used for matrix is released
00132         free(ptr_);
00133         free(ind_);
00134         free(data_real_);
00135         free(data_imag_);
00136 
00137         // memory for numbering scheme is released
00138         umfpack_zi_free_symbolic(&this->Symbolic) ;
00139 
00140         // memory used by LU factorization is released
00141         umfpack_zi_free_numeric(&this->Numeric) ;
00142 
00143         this->n = 0;
00144         this->Symbolic = NULL;
00145         this->Numeric = NULL;
00146 
00147         ptr_ = NULL;
00148         ind_ = NULL;
00149         data_real_ = NULL;
00150         data_imag_ = NULL;
00151       }
00152   }
00153 
00154 
00156   template<class Prop, class Storage, class Allocator>
00157   void MatrixUmfPack<double>::
00158   FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat,
00159                   bool keep_matrix)
00160   {
00161     // we clear previous factorization
00162     Clear();
00163 
00164     // conversion to unsymmetric matrix in Column Sparse Column Format
00165     Matrix<double, General, ColSparse, MallocAlloc<double> > Acsc;
00166     transpose = false;
00167 
00168     this->n = mat.GetM();
00169     Copy(mat, Acsc);
00170     if (!keep_matrix)
00171       mat.Clear();
00172 
00173     // we retrieve pointers of Acsc and nullify this object
00174     ptr_ = Acsc.GetPtr();
00175     ind_ = Acsc.GetInd();
00176     data_ = Acsc.GetData();
00177     Acsc.Nullify();
00178 
00179     // factorization with UmfPack
00180     umfpack_di_symbolic(this->n, this->n, ptr_, ind_, data_, &this->Symbolic,
00181                         this->Control.GetData(), this->Info.GetData());
00182 
00183     // we display informations about the performed operation
00184     int status =
00185       umfpack_di_numeric(ptr_, ind_, data_,
00186                          this->Symbolic, &this->Numeric,
00187                          this->Control.GetData(), this->Info.GetData());
00188 
00189     // we display informations about the performed operation
00190     if (this->display_info)
00191       {
00192         umfpack_di_report_status(this->Control.GetData(), status);
00193         umfpack_di_report_info(this->Control.GetData(),this->Info.GetData());
00194       }
00195   }
00196 
00197 
00199   template<class Prop, class Allocator>
00200   void MatrixUmfPack<double>
00201   ::PerformAnalysis(Matrix<double, Prop, RowSparse, Allocator> & mat)
00202   {
00203     // we clear previous factorization
00204     Clear();
00205 
00206     // conversion to unsymmetric matrix in Column Sparse Row Format
00207     Matrix<double, General, RowSparse, MallocAlloc<double> > Acsr;
00208     transpose = true;
00209 
00210     Copy(mat, Acsr);
00211 
00212     // we retrieve pointers of Acsc and nullify this object
00213     this->n = mat.GetM();
00214     ptr_ = Acsr.GetPtr();
00215     ind_ = Acsr.GetInd();
00216     data_ = Acsr.GetData();
00217     Acsr.Nullify();
00218 
00219     // factorization with UmfPack
00220     umfpack_di_symbolic(this->n, this->n, ptr_, ind_, data_, &this->Symbolic,
00221                         this->Control.GetData(), this->Info.GetData());
00222 
00223   }
00224 
00225 
00227   template<class Prop, class Allocator>
00228   void MatrixUmfPack<double>
00229   ::PerformFactorization(Matrix<double, Prop, RowSparse, Allocator> & mat)
00230   {
00231     // we copy values
00232     double* data = mat.GetData();
00233     for (int i = 0; i < mat.GetDataSize(); i++)
00234       data_[i] = data[i];
00235 
00236     int status =
00237       umfpack_di_numeric(ptr_, ind_, data_,
00238                          this->Symbolic, &this->Numeric,
00239                          this->Control.GetData(), this->Info.GetData());
00240 
00241     // we display informations about the performed operation
00242     if (this->display_info)
00243       {
00244         umfpack_di_report_status(this->Control.GetData(), status);
00245         umfpack_di_report_info(this->Control.GetData(),this->Info.GetData());
00246       }
00247   }
00248 
00249 
00251   template<class Allocator2>
00252   void MatrixUmfPack<double>::Solve(Vector<double, VectFull, Allocator2>& x)
00253   {
00254     // local copy of x
00255     Vector<double, VectFull, Allocator2> b(x);
00256 
00257     int sys = UMFPACK_A;
00258     if (transpose)
00259       sys = UMFPACK_Aat;
00260 
00261     int status
00262       = umfpack_di_solve(sys, ptr_, ind_, data_, x.GetData(),
00263                          b.GetData(), this->Numeric, this->Control.GetData(),
00264                          this->Info.GetData());
00265 
00266     // we display informations about the performed operation
00267     if (this->display_info)
00268       umfpack_di_report_status(this->Control.GetData(), status);
00269   }
00270 
00271 
00273   template<class Prop, class Storage,class Allocator>
00274   void MatrixUmfPack<complex<double> >::
00275   FactorizeMatrix(Matrix<complex<double>, Prop, Storage, Allocator> & mat,
00276                   bool keep_matrix)
00277   {
00278     Clear();
00279 
00280     this->n = mat.GetM();
00281     // conversion to CSC format
00282     Matrix<complex<double>, General, ColSparse,
00283       MallocAlloc<complex<double> > > Acsc;
00284     transpose = false;
00285 
00286     Copy(mat, Acsc);
00287     if (!keep_matrix)
00288       mat.Clear();
00289 
00290     int nnz = Acsc.GetDataSize();
00291     complex<double>* data = Acsc.GetData();
00292     int* ptr = Acsc.GetPtr();
00293     int* ind = Acsc.GetInd();
00294     Vector<double, VectFull, MallocAlloc<double> >
00295       ValuesReal(nnz), ValuesImag(nnz);
00296 
00297     Vector<int, VectFull, MallocAlloc<int> > Ptr(this->n+1), Ind(nnz);
00298 
00299     for (int i = 0; i < nnz; i++)
00300       {
00301         ValuesReal(i) = real(data[i]);
00302         ValuesImag(i) = imag(data[i]);
00303         Ind(i) = ind[i];
00304       }
00305 
00306     for (int i = 0; i <= this->n; i++)
00307       Ptr(i) = ptr[i];
00308 
00309     // we clear intermediary matrix Acsc
00310     Acsc.Clear();
00311 
00312     // retrieve pointers and nullify Seldon vectors
00313     data_real_ = ValuesReal.GetData();
00314     data_imag_ = ValuesImag.GetData();
00315     ptr_ = Ptr.GetData();
00316     ind_ = Ind.GetData();
00317     ValuesReal.Nullify(); ValuesImag.Nullify();
00318     Ptr.Nullify(); Ind.Nullify();
00319 
00320     // we call UmfPack
00321     umfpack_zi_symbolic(this->n, this->n, ptr_, ind_,
00322                         data_real_, data_imag_,
00323                         &this->Symbolic, this->Control.GetData(),
00324                         this->Info.GetData());
00325 
00326     int status
00327       = umfpack_zi_numeric(ptr_, ind_, data_real_, data_imag_,
00328                            this->Symbolic, &this->Numeric,
00329                            this->Control.GetData(), this->Info.GetData());
00330 
00331     if (this->display_info)
00332       {
00333         umfpack_zi_report_status(this->Control.GetData(), status);
00334         umfpack_zi_report_info(this->Control.GetData(), this->Info.GetData());
00335       }
00336   }
00337 
00338 
00340   template<class Allocator2>
00341   void MatrixUmfPack<complex<double> >::
00342   Solve(Vector<complex<double>, VectFull, Allocator2>& x)
00343   {
00344     int m = x.GetM();
00345     // creation of vectors
00346     Vector<double> b_real(m), b_imag(m);
00347     for (int i = 0; i < m; i++)
00348       {
00349         b_real(i) = real(x(i));
00350         b_imag(i) = imag(x(i));
00351       }
00352 
00353     Vector<double> x_real(m), x_imag(m);
00354     x_real.Zero();
00355     x_imag.Zero();
00356     int status
00357       = umfpack_zi_solve(UMFPACK_A, ptr_, ind_, data_real_, data_imag_,
00358                          x_real.GetData(), x_imag.GetData(),
00359                          b_real.GetData(), b_imag.GetData(),
00360                          this->Numeric,
00361                          this->Control.GetData(), this->Info.GetData());
00362     b_real.Clear();
00363     b_imag.Clear();
00364 
00365     for (int i = 0; i < m; i++)
00366       x(i) = complex<double>(x_real(i), x_imag(i));
00367 
00368     if (this->display_info)
00369       umfpack_zi_report_status(this->Control.GetData(), status);
00370   }
00371 
00372 
00374   template<class T, class Prop, class Storage, class Allocator>
00375   void GetLU(Matrix<T, Prop, Storage, Allocator>& A, MatrixUmfPack<T>& mat_lu,
00376              bool keep_matrix = false)
00377   {
00378     mat_lu.FactorizeMatrix(A, keep_matrix);
00379   }
00380 
00381 
00383   template<class T, class Allocator>
00384   void SolveLU(MatrixUmfPack<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00385   {
00386     mat_lu.Solve(x);
00387   }
00388 
00389 
00390   template<class T, class Allocator>
00391   void SolveLU(const SeldonTranspose& TransA,
00392                MatrixUmfPack<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00393   {
00394     if (!TransA.NoTrans())
00395       throw
00396         WrongArgument("SolveLU(SeldonTranspose&, MatrixUmfPack&, Vector&)",
00397                       "Only non-transposed matrices are supported.");
00398     mat_lu.Solve(x);
00399   }
00400 
00401 }
00402 
00403 #define SELDON_FILE_UMFPACK_CXX
00404 #endif