00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00039 distributed = false;
00040
00041
00042 refine_solution = false;
00043
00044
00045 pastix_initParam(iparm, dparm);
00046
00047 iparm[IPARM_RHS_MAKING] = API_RHS_B;
00048 iparm[IPARM_VERBOSE] = API_VERBOSE_NOT;
00049
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
00090
00091
00092
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
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
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
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
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
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
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
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
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
00333 iparm[IPARM_START_TASK] = API_TASK_ORDERING;
00334 iparm[IPARM_END_TASK] = API_TASK_NUMFACT;
00335
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
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
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
00426
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 }
00485
00486 #define SELDON_FILE_PASTIX_CXX
00487 #endif