computation/interfaces/direct/Pastix.cxx

00001 // Copyright (C) 2001-2010 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 #ifndef SELDON_FILE_PASTIX_CXX
00020 
00021 #include "Pastix.hxx"
00022 
00023 namespace Seldon
00024 {
00025 
00027   template<class T>
00028   MatrixPastix<T>::MatrixPastix()
00029   {
00030     pastix_data = NULL;
00031     n = 0;
00032     for (int i = 0; i < 64; i++)
00033       {
00034         iparm[i] = 0;
00035         dparm[i] = 0;
00036       }
00037 
00038     // Factorization of a matrix on a single processor.
00039     distributed = false;
00040 
00041     // Refinement by default.
00042     refine_solution = true;
00043 
00044     // initializing parameters
00045     pastix_initParam(iparm, dparm);
00046 
00047     iparm[IPARM_RHS_MAKING] = API_RHS_B;
00048     iparm[IPARM_VERBOSE] = API_VERBOSE_NOT;
00049   }
00050 
00051 
00053   template<class T>
00054   MatrixPastix<T>::~MatrixPastix()
00055   {
00056     Clear();
00057   }
00058 
00059 
00061   template<>
00062   void MatrixPastix<double>::
00063   CallPastix(const MPI_Comm& comm, pastix_int_t* colptr, pastix_int_t* row,
00064              double* val, double* b, pastix_int_t nrhs)
00065   {
00066     if (distributed)
00067       d_dpastix(&pastix_data, comm, n, colptr, row, val,
00068                 col_num.GetData(), perm.GetData(), invp.GetData(),
00069                 b, nrhs, iparm, dparm);
00070     else
00071       d_pastix(&pastix_data, comm, n, colptr, row, val,
00072                perm.GetData(), invp.GetData(), b, nrhs, iparm, dparm);
00073   }
00074 
00075 
00077   template<>
00078   void MatrixPastix<complex<double> >::
00079   CallPastix(const MPI_Comm& comm, pastix_int_t* colptr, pastix_int_t* row,
00080              complex<double>* val, complex<double>* b, pastix_int_t nrhs)
00081   {
00082     if (distributed)
00083       z_dpastix(&pastix_data, comm, n, colptr, row,
00084                 reinterpret_cast<DCOMPLEX*>(val),
00085                 col_num.GetData(), perm.GetData(), invp.GetData(),
00086                 reinterpret_cast<DCOMPLEX*>(b), nrhs, iparm, dparm);
00087     else
00088       z_pastix(&pastix_data, comm, n, colptr, row,
00089                reinterpret_cast<DCOMPLEX*>(val),
00090                perm.GetData(), invp.GetData(),
00091                reinterpret_cast<DCOMPLEX*>(b), nrhs, iparm, dparm);
00092   }
00093 
00094 
00096   template<class T>
00097   void MatrixPastix<T>::Clear()
00098   {
00099     if (n > 0)
00100       {
00101         pastix_int_t nrhs = 1;
00102         iparm[IPARM_START_TASK] = API_TASK_CLEAN;
00103         iparm[IPARM_END_TASK] = API_TASK_CLEAN;
00104 
00105         CallPastix(MPI_COMM_WORLD, NULL, NULL, NULL, NULL, nrhs);
00106 
00107         perm.Clear();
00108         invp.Clear();
00109         col_num.Clear();
00110         n = 0;
00111         pastix_data = NULL;
00112         distributed = false;
00113       }
00114   }
00115 
00116 
00118   template<class T>
00119   void MatrixPastix<T>::HideMessages()
00120   {
00121     iparm[IPARM_VERBOSE] = API_VERBOSE_NOT;
00122   }
00123 
00124 
00126   template<class T>
00127   void MatrixPastix<T>::ShowMessages()
00128   {
00129     iparm[IPARM_VERBOSE] = API_VERBOSE_NO;
00130   }
00131 
00132 
00134   template<class T>
00135   void MatrixPastix<T>::ShowFullHistory()
00136   {
00137     iparm[IPARM_VERBOSE] = API_VERBOSE_YES;
00138   }
00139 
00140 
00141   template<class T>
00142   void MatrixPastix<T>::SelectOrdering(int type)
00143   {
00144     iparm[IPARM_ORDERING] = type;
00145   }
00146 
00147 
00148   template<class T>
00149   void MatrixPastix<T>::SetPermutation(const IVect& permut)
00150   {
00151     iparm[IPARM_ORDERING] = API_ORDER_PERSONAL;
00152     perm.Reallocate(permut.GetM());
00153     invp.Reallocate(permut.GetM());
00154     for (int i = 0; i < perm.GetM(); i++)
00155       {
00156         perm(i) = permut(i) + 1;
00157         invp(permut(i)) = i+1;
00158       }
00159   }
00160 
00161 
00163   template<class T>
00164   void MatrixPastix<T>::RefineSolution()
00165   {
00166     refine_solution = true;
00167   }
00168 
00169 
00171   template<class T>
00172   void MatrixPastix<T>::DoNotRefineSolution()
00173   {
00174     refine_solution = false;
00175   }
00176 
00177 
00179   template<class T>
00180   template<class T0, class Prop, class Storage, class Allocator, class Tint>
00181   void MatrixPastix<T>::
00182   FindOrdering(Matrix<T0, Prop, Storage, Allocator> & mat,
00183                Vector<Tint>& numbers, bool keep_matrix)
00184   {
00185     // We clear the previous factorization, if any.
00186     Clear();
00187 
00188     distributed = false;
00189 
00190     n = mat.GetN();
00191     if (n <= 0)
00192       return;
00193 
00194     pastix_int_t nrhs = 1, nnz = 0;
00195     pastix_int_t* ptr_ = NULL;
00196     pastix_int_t* ind_ = NULL;
00197     Vector<pastix_int_t> Ptr, Ind;
00198 
00199     iparm[IPARM_SYM] = API_SYM_YES;
00200     iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00201     GetSymmetricPattern(mat, Ptr, Ind);
00202     if (!keep_matrix)
00203       mat.Clear();
00204 
00205     ptr_ = Ptr.GetData();
00206     // Changing to 1-index notation.
00207     for (int i = 0; i <= n; i++)
00208       ptr_[i]++;
00209 
00210     nnz = Ind.GetM();
00211     ind_ = Ind.GetData();
00212     for (int i = 0; i < nnz; i++)
00213       ind_[i]++;
00214 
00215     perm.Reallocate(n); invp.Reallocate(n);
00216     perm.Fill(); invp.Fill();
00217 
00218     // We get ordering only.
00219     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00220     iparm[IPARM_END_TASK] = API_TASK_ORDERING;
00221 
00222     CallPastix(MPI_COMM_SELF, ptr_, ind_, NULL, NULL, nrhs);
00223 
00224     numbers.Reallocate(perm.GetM());
00225     for (int i = 0; i < perm.GetM(); i ++)
00226       numbers(i) = perm(i);
00227   }
00228 
00229 
00231   template<class T> template<class Storage, class Allocator>
00232   void MatrixPastix<T>
00233   ::FactorizeMatrix(Matrix<T, General, Storage, Allocator> & mat,
00234                     bool keep_matrix)
00235   {
00236     // we clear previous factorization if present
00237     Clear();
00238 
00239     distributed = false;
00240     n = mat.GetN();
00241     if (n <= 0)
00242       return;
00243 
00244     pastix_int_t nrhs = 1, nnz = 0;
00245     pastix_int_t* ptr_ = NULL;
00246     pastix_int_t* ind_ = NULL;
00247     T* values_ = NULL;
00248     Vector<pastix_int_t, VectFull, CallocAlloc<pastix_int_t> > Ptr, IndRow;
00249     Vector<T, VectFull, CallocAlloc<T> > Val;
00250 
00251     General prop;
00252     ConvertToCSC(mat, prop, Ptr, IndRow, Val, true);
00253     if (!keep_matrix)
00254       mat.Clear();
00255 
00256     ptr_ = Ptr.GetData();
00257     // changing to 1-index notation
00258     for (int i = 0; i <= n; i++)
00259       ptr_[i]++;
00260 
00261     nnz = IndRow.GetM();
00262     ind_ = IndRow.GetData();
00263     for (int i = 0; i < nnz; i++)
00264       ind_[i]++;
00265 
00266     values_ = Val.GetData();
00267 
00268     if (iparm[IPARM_ORDERING] != API_ORDER_PERSONAL)
00269       {
00270         perm.Reallocate(n); invp.Reallocate(n);
00271         perm.Fill(); invp.Fill();
00272       }
00273 
00274     iparm[IPARM_SYM] = API_SYM_NO;
00275     iparm[IPARM_FACTORIZATION] = API_FACT_LU;
00276 
00277     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00278     iparm[IPARM_END_TASK] = API_TASK_ANALYSE;
00279 
00280     CallPastix(MPI_COMM_SELF, ptr_, ind_, values_, NULL, nrhs);
00281 
00282     // factorization only
00283     IVect proc_num(iparm[IPARM_THREAD_NBR]);
00284     proc_num.Fill(MPI::COMM_WORLD.Get_rank());
00285     pastix_setBind(pastix_data, iparm[IPARM_THREAD_NBR], proc_num.GetData());
00286 
00287     iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
00288     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00289 
00290     CallPastix(MPI_COMM_SELF, ptr_, ind_, values_, NULL, nrhs);
00291 
00292     if (iparm[IPARM_VERBOSE] != API_VERBOSE_NOT)
00293       cout << "Factorization successful" << endl;
00294   }
00295 
00296 
00298   template<class T> template<class Storage, class Allocator>
00299   void MatrixPastix<T>::
00300   FactorizeMatrix(Matrix<T, Symmetric, Storage, Allocator> & mat,
00301                   bool keep_matrix)
00302   {
00303     // we clear previous factorization if present
00304     Clear();
00305 
00306     distributed = false;
00307     n = mat.GetN();
00308     if (n <= 0)
00309       return;
00310 
00311     pastix_int_t nrhs = 1, nnz = 0;
00312     pastix_int_t* ptr_ = NULL;
00313     pastix_int_t* ind_ = NULL;
00314 
00315     T* values_ = NULL;
00316     Vector<pastix_int_t, VectFull, MallocAlloc<pastix_int_t> > Ptr, IndRow;
00317     Vector<T, VectFull, MallocAlloc<T> > Val;
00318 
00319     Symmetric prop;
00320     ConvertToCSR(mat, prop, Ptr, IndRow, Val);
00321 
00322     iparm[IPARM_SYM]           = API_SYM_YES;
00323     iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00324     if (!keep_matrix)
00325       mat.Clear();
00326 
00327     ptr_ = Ptr.GetData();
00328     // changing to 1-index notation
00329     for (int i = 0; i <= n; i++)
00330       ptr_[i]++;
00331 
00332     nnz = IndRow.GetM();
00333     ind_ = IndRow.GetData();
00334     for (int i = 0; i < nnz; i++)
00335       ind_[i]++;
00336 
00337     values_ = Val.GetData();
00338 
00339     perm.Reallocate(n); invp.Reallocate(n);
00340     perm.Fill(); invp.Fill();
00341 
00342     // ordering and analysis
00343     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00344     iparm[IPARM_END_TASK] = API_TASK_ANALYSE;
00345 
00346     CallPastix(MPI_COMM_SELF, ptr_, ind_, values_, NULL, nrhs);
00347 
00348     IVect proc_num(iparm[IPARM_THREAD_NBR]);
00349     proc_num.Fill(MPI::COMM_WORLD.Get_rank());
00350     pastix_setBind(pastix_data, iparm[IPARM_THREAD_NBR], proc_num.GetData());
00351 
00352     // factorization only
00353     iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
00354     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00355 
00356     CallPastix(MPI_COMM_SELF, ptr_, ind_, values_, NULL, nrhs);
00357   }
00358 
00359 
00361   template<class T> template<class Allocator2>
00362   void MatrixPastix<T>::Solve(Vector<T, VectFull, Allocator2>& x)
00363   {
00364     Solve(SeldonNoTrans, x);
00365   }
00366 
00367 
00369   template<class T> template<class Allocator2, class Transpose_status>
00370   void MatrixPastix<T>::Solve(const Transpose_status& TransA,
00371                               Vector<T, VectFull, Allocator2>& x)
00372   {
00373     pastix_int_t nrhs = 1;
00374     T* rhs_ = x.GetData();
00375 
00376     iparm[IPARM_START_TASK] = API_TASK_SOLVE;
00377     if (refine_solution)
00378       iparm[IPARM_END_TASK] = API_TASK_REFINE;
00379     else
00380       iparm[IPARM_END_TASK] = API_TASK_SOLVE;
00381 
00382     CallPastix(MPI_COMM_SELF, NULL, NULL, NULL, rhs_, nrhs);
00383   }
00384 
00385 
00387   template<class T>
00388   void MatrixPastix<T>::SetNumberThreadPerNode(int num_thread)
00389   {
00390     iparm[IPARM_THREAD_NBR] = num_thread;
00391   }
00392 
00393 
00395   template<class T>
00396   template<class Alloc1, class Alloc2, class Alloc3, class Tint>
00397   void MatrixPastix<T>::
00398   FactorizeDistributedMatrix(MPI::Comm& comm_facto,
00399                              Vector<pastix_int_t, VectFull, Alloc1>& Ptr,
00400                              Vector<pastix_int_t, VectFull, Alloc2>& IndRow,
00401                              Vector<T, VectFull, Alloc3>& Val,
00402                              const Vector<Tint>& glob_number,
00403                              bool sym, bool keep_matrix)
00404   {
00405     // we clear previous factorization if present
00406     Clear();
00407 
00408     n = Ptr.GetM() - 1;
00409     if (n <= 0)
00410       return;
00411 
00412     distributed = true;
00413 
00414     if (sym)
00415       {
00416         iparm[IPARM_SYM] = API_SYM_YES;
00417         iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00418       }
00419     else
00420       {
00421         iparm[IPARM_SYM] = API_SYM_NO;
00422         iparm[IPARM_FACTORIZATION] = API_FACT_LU;
00423       }
00424 
00425     iparm[IPARM_GRAPHDIST] = API_YES;
00426 
00427     pastix_int_t* ptr_ = Ptr.GetData();
00428     pastix_int_t nrhs = 1;
00429     // changing to 1-index notation
00430     for (int i = 0; i <= n; i++)
00431       ptr_[i]++;
00432 
00433     pastix_int_t nnz = IndRow.GetM();
00434     pastix_int_t* ind_ = IndRow.GetData();
00435     for (int i = 0; i < nnz; i++)
00436       ind_[i]++;
00437 
00438     T* values_ = Val.GetData();
00439 
00440     col_num.Reallocate(n);
00441     perm.Reallocate(n); invp.Reallocate(n);
00442     perm.Fill(); invp.Fill();
00443     for (int i = 0; i < n; i++)
00444       col_num(i) = glob_number(i)+1;
00445 
00446     // factorization only
00447     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00448     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00449 
00450     CallPastix(comm_facto, ptr_, ind_, values_, NULL, nrhs);
00451   }
00452 
00453 
00454   template<class T> template<class Allocator2, class Tint>
00455   void MatrixPastix<T>::SolveDistributed(MPI::Comm& comm_facto,
00456                                          Vector<T, Vect_Full, Allocator2>& x,
00457                                          const Vector<Tint>& glob_num)
00458   {
00459     SolveDistributed(comm_facto, SeldonNoTrans, x, glob_num);
00460   }
00461 
00462 
00463   template<class T>
00464   template<class Allocator2, class Transpose_status, class Tint>
00465   void MatrixPastix<T>::SolveDistributed(MPI::Comm& comm_facto,
00466                                          const Transpose_status& TransA,
00467                                          Vector<T, Vect_Full, Allocator2>& x,
00468                                          const Vector<Tint>& glob_num)
00469   {
00470     pastix_int_t nrhs = 1;
00471     T* rhs_ = x.GetData();
00472 
00473     iparm[IPARM_START_TASK] = API_TASK_SOLVE;
00474     if (refine_solution)
00475       iparm[IPARM_END_TASK] = API_TASK_REFINE;
00476     else
00477       iparm[IPARM_END_TASK] = API_TASK_SOLVE;
00478 
00479     CallPastix(comm_facto, NULL, NULL, NULL, rhs_, nrhs);
00480   }
00481 
00482 
00483   template<class T, class Prop, class Storage, class Allocator>
00484   void GetLU(Matrix<T, Prop, Storage, Allocator>& A, MatrixPastix<T>& mat_lu,
00485              bool keep_matrix = false)
00486   {
00487     mat_lu.FactorizeMatrix(A, keep_matrix);
00488   }
00489 
00490 
00491   template<class T, class Allocator>
00492   void SolveLU(MatrixPastix<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00493   {
00494     mat_lu.Solve(x);
00495   }
00496 
00497 
00498   template<class T, class Allocator, class Transpose_status>
00499   void SolveLU(const Transpose_status& TransA,
00500                MatrixPastix<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00501   {
00502     mat_lu.Solve(TransA, x);
00503   }
00504 
00505 } // end namespace
00506 
00507 #define SELDON_FILE_PASTIX_CXX
00508 #endif