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     // No refinement by default.
00042     refine_solution = false;
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     // iparm[IPARM_VERBOSE] = API_VERBOSE_NO;
00050   }
00051 
00052 
00054   template<class T>
00055   MatrixPastix<T>::~MatrixPastix()
00056   {
00057     Clear();
00058   }
00059 
00060 
00062   template<>
00063   void MatrixPastix<double>::
00064   CallPastix(const MPI_Comm& comm, pastix_int_t* colptr, pastix_int_t* row,
00065              double* val, double* b, pastix_int_t nrhs)
00066   {
00067     if (distributed)
00068       d_dpastix(&pastix_data, comm, n, colptr, row, val,
00069                 col_num.GetData(), perm.GetData(), invp.GetData(),
00070                 b, nrhs, iparm, dparm);
00071     else
00072       d_pastix(&pastix_data, comm, n, colptr, row, val,
00073                perm.GetData(), invp.GetData(), b, nrhs, iparm, dparm);
00074   }
00075 
00076 
00078   template<>
00079   void MatrixPastix<complex<double> >::
00080   CallPastix(const MPI_Comm& comm, pastix_int_t* colptr, pastix_int_t* row,
00081              complex<double>* val, complex<double>* b, pastix_int_t nrhs)
00082   {
00083     if (distributed)
00084       z_dpastix(&pastix_data, comm, n, colptr, row,
00085                 reinterpret_cast<DCOMPLEX*>(val),
00086                 col_num.GetData(), perm.GetData(), invp.GetData(),
00087                 reinterpret_cast<DCOMPLEX*>(b), nrhs, iparm, dparm);
00088     else
00089       /* z_dpastix(&pastix_data, comm, n, colptr, row,
00090          reinterpret_cast<DCOMPLEX*>(val),
00091          col_num.GetData(), perm.GetData(), invp.GetData(),
00092          reinterpret_cast<DCOMPLEX*>(b), nrhs, iparm, dparm); */
00093       z_pastix(&pastix_data, comm, n, colptr, row,
00094                reinterpret_cast<DCOMPLEX*>(val),
00095                perm.GetData(), invp.GetData(),
00096                reinterpret_cast<DCOMPLEX*>(b), nrhs, iparm, dparm);
00097   }
00098 
00099 
00101   template<class T>
00102   void MatrixPastix<T>::Clear()
00103   {
00104     if (n > 0)
00105       {
00106         pastix_int_t nrhs = 1;
00107         iparm[IPARM_START_TASK] = API_TASK_CLEAN;
00108         iparm[IPARM_END_TASK] = API_TASK_CLEAN;
00109 
00110         CallPastix(MPI_COMM_WORLD, NULL, NULL, NULL, NULL, nrhs);
00111 
00112         perm.Clear();
00113         invp.Clear();
00114         col_num.Clear();
00115         n = 0;
00116         pastix_data = NULL;
00117         distributed = false;
00118 
00119         MPI_Comm_free(&comm_facto);
00120       }
00121   }
00122 
00123 
00125   template<class T>
00126   void MatrixPastix<T>::HideMessages()
00127   {
00128     iparm[IPARM_VERBOSE] = API_VERBOSE_NOT;
00129   }
00130 
00131 
00133   template<class T>
00134   void MatrixPastix<T>::ShowMessages()
00135   {
00136     iparm[IPARM_VERBOSE] = API_VERBOSE_NO;
00137   }
00138 
00140   template<class T>
00141   void MatrixPastix<T>::RefineSolution()
00142   {
00143     refine_solution = true;
00144   }
00145 
00146 
00148   template<class T>
00149   void MatrixPastix<T>::DoNotRefineSolution()
00150   {
00151     refine_solution = false;
00152   }
00153 
00154 
00155   template<class T>
00156   void MatrixPastix<T>::CreateCommunicator()
00157   {
00158     MPI_Group single_group;
00159     int rank, nb_cpu;
00160     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
00161     MPI_Comm_size(MPI_COMM_WORLD, &nb_cpu);
00162 
00163     if (distributed)
00164       {
00165         IVect rank_(nb_cpu); rank_.Fill();
00166         MPI_Comm_group(MPI_COMM_WORLD, &single_group);
00167         MPI_Group_incl(single_group, nb_cpu, rank_.GetData(), &single_group);
00168         MPI_Comm_create(MPI_COMM_WORLD, single_group, &comm_facto);
00169       }
00170     else
00171       {
00172         MPI_Comm_group(MPI_COMM_WORLD, &single_group);
00173         MPI_Group_incl(single_group, 1, &rank, &single_group);
00174         MPI_Comm_create(MPI_COMM_WORLD, single_group, &comm_facto);
00175       }
00176   }
00177 
00178 
00180   template<class T>
00181   template<class T0, class Prop, class Storage, class Allocator, class Tint>
00182   void MatrixPastix<T>::
00183   FindOrdering(Matrix<T0, Prop, Storage, Allocator> & mat,
00184                Vector<Tint>& numbers, bool keep_matrix)
00185   {
00186     // We clear the previous factorization, if any.
00187     Clear();
00188 
00189     distributed = false;
00190     CreateCommunicator();
00191 
00192     n = mat.GetN();
00193     if (n <= 0)
00194       return;
00195 
00196     pastix_int_t nrhs = 1, nnz = 0;
00197     pastix_int_t* ptr_ = NULL;
00198     pastix_int_t* ind_ = NULL;
00199     Vector<pastix_int_t> Ptr, Ind;
00200 
00201     iparm[IPARM_SYM] = API_SYM_YES;
00202     iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00203     GetSymmetricPattern(mat, Ptr, Ind);
00204     if (!keep_matrix)
00205       mat.Clear();
00206 
00207     ptr_ = Ptr.GetData();
00208     // Changing to 1-index notation.
00209     for (int i = 0; i <= n; i++)
00210       ptr_[i]++;
00211 
00212     nnz = Ind.GetM();
00213     ind_ = Ind.GetData();
00214     for (int i = 0; i < nnz; i++)
00215       ind_[i]++;
00216 
00217     perm.Reallocate(n); invp.Reallocate(n);
00218     perm.Fill(); invp.Fill();
00219 
00220     // We get ordering only.
00221     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00222     iparm[IPARM_END_TASK] = API_TASK_ORDERING;
00223 
00224     CallPastix(comm_facto, ptr_, ind_, NULL, NULL, nrhs);
00225 
00226     numbers = perm;
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     CreateCommunicator();
00241     n = mat.GetN();
00242     if (n <= 0)
00243       return;
00244 
00245     pastix_int_t nrhs = 1, nnz = 0;
00246     pastix_int_t* ptr_ = NULL;
00247     pastix_int_t* ind_ = NULL;
00248     T* values_ = NULL;
00249     Vector<pastix_int_t, VectFull, MallocAlloc<pastix_int_t> > Ptr, IndRow;
00250     Vector<T, VectFull, MallocAlloc<T> > Val;
00251 
00252     iparm[IPARM_SYM] = API_SYM_NO;
00253     iparm[IPARM_FACTORIZATION] = API_FACT_LU;
00254 
00255     General prop;
00256     ConvertToCSC(mat, prop, Ptr, IndRow, Val, true);
00257     if (!keep_matrix)
00258       mat.Clear();
00259 
00260     ptr_ = Ptr.GetData();
00261     // changing to 1-index notation
00262     for (int i = 0; i <= n; i++)
00263       ptr_[i]++;
00264 
00265     nnz = IndRow.GetM();
00266     ind_ = IndRow.GetData();
00267     for (int i = 0; i < nnz; i++)
00268       ind_[i]++;
00269 
00270     values_ = Val.GetData();
00271 
00272     perm.Reallocate(n); invp.Reallocate(n);
00273     perm.Fill(); invp.Fill();
00274 
00275     // factorization only
00276     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00277     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00278 
00279     CallPastix(comm_facto, ptr_, ind_, values_, NULL, nrhs);
00280 
00281     if (iparm[IPARM_VERBOSE] != API_VERBOSE_NOT)
00282       cout << "Factorization successful" << endl;
00283   }
00284 
00285 
00287   template<class T> template<class Storage, class Allocator>
00288   void MatrixPastix<T>::
00289   FactorizeMatrix(Matrix<T, Symmetric, Storage, Allocator> & mat,
00290                   bool keep_matrix)
00291   {
00292     // we clear previous factorization if present
00293     Clear();
00294 
00295     distributed = false;
00296     CreateCommunicator();
00297     n = mat.GetN();
00298     if (n <= 0)
00299       return;
00300 
00301     pastix_int_t nrhs = 1, nnz = 0;
00302     pastix_int_t* ptr_ = NULL;
00303     pastix_int_t* ind_ = NULL;
00304 
00305     T* values_ = NULL;
00306     Vector<pastix_int_t, VectFull, MallocAlloc<pastix_int_t> > Ptr, IndRow;
00307     Vector<T, VectFull, MallocAlloc<T> > Val;
00308 
00309     Symmetric prop;
00310     ConvertToCSR(mat, prop, Ptr, IndRow, Val);
00311 
00312     iparm[IPARM_SYM]           = API_SYM_YES;
00313     iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00314     if (!keep_matrix)
00315       mat.Clear();
00316 
00317     ptr_ = Ptr.GetData();
00318     // changing to 1-index notation
00319     for (int i = 0; i <= n; i++)
00320       ptr_[i]++;
00321 
00322     nnz = IndRow.GetM();
00323     ind_ = IndRow.GetData();
00324     for (int i = 0; i < nnz; i++)
00325       ind_[i]++;
00326 
00327     values_ = Val.GetData();
00328 
00329     perm.Reallocate(n); invp.Reallocate(n);
00330     perm.Fill(); invp.Fill();
00331 
00332     // factorization only
00333     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00334     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00335     // iparm[IPARM_VERBOSE]          = 4;
00336 
00337     CallPastix(comm_facto, ptr_, ind_, values_, NULL, nrhs);
00338   }
00339 
00340 
00342   template<class T> template<class Allocator2>
00343   void MatrixPastix<T>::Solve(Vector<T, VectFull, Allocator2>& x)
00344   {
00345     Solve(SeldonNoTrans, x);
00346   }
00347 
00348 
00350   template<class T> template<class Allocator2, class Transpose_status>
00351   void MatrixPastix<T>::Solve(const Transpose_status& TransA,
00352                               Vector<T, VectFull, Allocator2>& x)
00353   {
00354     pastix_int_t nrhs = 1;
00355     T* rhs_ = x.GetData();
00356 
00357     iparm[IPARM_START_TASK] = API_TASK_SOLVE;
00358     if (refine_solution)
00359       iparm[IPARM_END_TASK] = API_TASK_REFINE;
00360     else
00361       iparm[IPARM_END_TASK] = API_TASK_SOLVE;
00362 
00363     CallPastix(comm_facto, NULL, NULL, NULL, rhs_, nrhs);
00364   }
00365 
00366 
00367 #ifdef SELDON_WITH_MPI
00368 
00370   template<class T>
00371   void MatrixPastix<T>::SetNbThreadPerNode(int nb_thread)
00372   {
00373     iparm[IPARM_THREAD_NBR] = nb_thread;
00374   }
00375 
00376 
00378   template<class T>
00379   template<class Alloc1, class Alloc2, class Alloc3, class Tint>
00380   void MatrixPastix<T>::
00381   FactorizeDistributedMatrix(Vector<pastix_int_t, VectFull, Alloc1>& Ptr,
00382                              Vector<pastix_int_t, VectFull, Alloc2>& IndRow,
00383                              Vector<T, VectFull, Alloc3>& Val,
00384                              const Vector<Tint>& glob_number,
00385                              bool sym, bool keep_matrix)
00386   {
00387     // we clear previous factorization if present
00388     Clear();
00389 
00390     n = Ptr.GetM() - 1;
00391     if (n <= 0)
00392       return;
00393 
00394     distributed = true;
00395 
00396     CreateCommunicator();
00397 
00398     iparm[IPARM_SYM] = API_SYM_YES;
00399 
00400     iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
00401     iparm[IPARM_GRAPHDIST] = API_YES;
00402 
00403     int rank;
00404     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
00405 
00406     pastix_int_t* ptr_ = Ptr.GetData();
00407     pastix_int_t nrhs = 1;
00408     // changing to 1-index notation
00409     for (int i = 0; i <= n; i++)
00410       ptr_[i]++;
00411 
00412     pastix_int_t nnz = IndRow.GetM();
00413     pastix_int_t* ind_ = IndRow.GetData();
00414     for (int i = 0; i < nnz; i++)
00415       ind_[i]++;
00416 
00417     T* values_ = Val.GetData();
00418 
00419     col_num.Reallocate(n);
00420     perm.Reallocate(n); invp.Reallocate(n);
00421     perm.Fill(); invp.Fill();
00422     for (int i = 0; i < n; i++)
00423       col_num(i) = glob_number(i)+1;
00424 
00425     // factorization only
00426     // iparm[IPARM_VERBOSE] = API_VERBOSE_YES;
00427     iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00428     iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00429 
00430     CallPastix(comm_facto, ptr_, ind_, values_, NULL, nrhs);
00431   }
00432 
00433 
00434   template<class T> template<class Allocator2, class Tint>
00435   void MatrixPastix<T>::SolveDistributed(Vector<T, Vect_Full, Allocator2>& x,
00436                                          const Vector<Tint>& glob_num)
00437   {
00438     SolveDistributed(SeldonNoTrans, x, glob_num);
00439   }
00440 
00441 
00442   template<class T>
00443   template<class Allocator2, class Transpose_status, class Tint>
00444   void MatrixPastix<T>::SolveDistributed(const Transpose_status& TransA,
00445                                          Vector<T, Vect_Full, Allocator2>& x,
00446                                          const Vector<Tint>& glob_num)
00447   {
00448     pastix_int_t nrhs = 1;
00449     T* rhs_ = x.GetData();
00450 
00451     iparm[IPARM_START_TASK] = API_TASK_SOLVE;
00452     if (refine_solution)
00453       iparm[IPARM_END_TASK] = API_TASK_REFINE;
00454     else
00455       iparm[IPARM_END_TASK] = API_TASK_SOLVE;
00456 
00457     CallPastix(comm_facto, NULL, NULL, NULL, rhs_, nrhs);
00458   }
00459 #endif
00460 
00461 
00462   template<class T, class Prop, class Storage, class Allocator>
00463   void GetLU(Matrix<T, Prop, Storage, Allocator>& A, MatrixPastix<T>& mat_lu,
00464              bool keep_matrix = false)
00465   {
00466     mat_lu.FactorizeMatrix(A, keep_matrix);
00467   }
00468 
00469 
00470   template<class T, class Allocator>
00471   void SolveLU(MatrixPastix<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00472   {
00473     mat_lu.Solve(x);
00474   }
00475 
00476 
00477   template<class T, class Allocator, class Transpose_status>
00478   void SolveLU(const Transpose_status& TransA,
00479                MatrixPastix<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00480   {
00481     mat_lu.Solve(TransA, x);
00482   }
00483 
00484 } // end namespace
00485 
00486 #define SELDON_FILE_PASTIX_CXX
00487 #endif