Warning: this documentation for the development version is under construction.
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