00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_MUMPS_CXX
00021
00022 #include "Mumps.hxx"
00023
00024 namespace Seldon
00025 {
00026
00028 template<>
00029 inline void MatrixMumps<double>::CallMumps()
00030 {
00031 dmumps_c(&struct_mumps);
00032 }
00033
00034
00036 template<>
00037 inline void MatrixMumps<complex<double> >::CallMumps()
00038 {
00039 zmumps_c(&struct_mumps);
00040 }
00041
00042
00044 template<class T>
00045 inline MatrixMumps<T>::MatrixMumps()
00046 {
00047
00048 struct_mumps.comm_fortran = -987654;
00049
00050
00051 struct_mumps.job = -1;
00052 struct_mumps.par = 1;
00053 struct_mumps.sym = 0;
00054
00055
00056 CallMumps();
00057
00058
00059 struct_mumps.n = 0;
00060 type_ordering = 7;
00061 print_level = -1;
00062 out_of_core = false;
00063 new_communicator = false;
00064 }
00065
00066
00068 template<class T> template<class MatrixSparse>
00069 inline void MatrixMumps<T>
00070 ::InitMatrix(const MatrixSparse& A, bool distributed)
00071 {
00072
00073 Clear();
00074
00075 #ifdef SELDON_WITH_MPI
00076
00077 if (distributed)
00078 {
00079
00080 struct_mumps.comm_fortran = -987654;
00081 }
00082 else
00083 {
00084
00085 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
00086 MPI_Comm_group(MPI_COMM_WORLD, &single_group);
00087 MPI_Group_incl(single_group, 1, &rank, &single_group);
00088 MPI_Comm_create(MPI_COMM_WORLD, single_group, &single_comm);
00089 struct_mumps.comm_fortran = MPI_Comm_c2f(single_comm);
00090 new_communicator = true;
00091 }
00092 #endif
00093
00094
00095 struct_mumps.job = -1;
00096 if (IsSymmetricMatrix(A))
00097 struct_mumps.sym = 2;
00098 else
00099 struct_mumps.sym = 0;
00100
00101
00102 CallMumps();
00103
00104 struct_mumps.icntl[13] = 20;
00105 struct_mumps.icntl[6] = type_ordering;
00106
00107 if (out_of_core)
00108 struct_mumps.icntl[21] = 1;
00109 else
00110 struct_mumps.icntl[21] = 0;
00111
00112 struct_mumps.icntl[17] = 0;
00113
00114
00115 if (print_level >= 0)
00116 {
00117 struct_mumps.icntl[0] = 6;
00118 struct_mumps.icntl[1] = 0;
00119 struct_mumps.icntl[2] = 6;
00120 struct_mumps.icntl[3] = 2;
00121 }
00122 else
00123 {
00124 struct_mumps.icntl[0] = -1;
00125 struct_mumps.icntl[1] = -1;
00126 struct_mumps.icntl[2] = -1;
00127 struct_mumps.icntl[3] = 0;
00128 }
00129 }
00130
00131
00133 template<class T>
00134 inline void MatrixMumps<T>::SelectOrdering(int num_ordering)
00135 {
00136 type_ordering = num_ordering;
00137 }
00138
00139
00141 template<class T>
00142 MatrixMumps<T>::~MatrixMumps()
00143 {
00144 Clear();
00145 }
00146
00147
00149 template<class T>
00150 inline void MatrixMumps<T>::Clear()
00151 {
00152 if (struct_mumps.n > 0)
00153 {
00154 struct_mumps.job = -2;
00155 CallMumps();
00156
00157 num_row_glob.Clear(); num_col_glob.Clear();
00158 struct_mumps.n = 0;
00159
00160 }
00161
00162 #ifdef SELDON_WITH_MPI
00163 if (new_communicator)
00164 {
00165 MPI_Comm_free(&single_comm);
00166 new_communicator = false;
00167 }
00168 #endif
00169
00170 }
00171
00172
00174 template<class T>
00175 inline void MatrixMumps<T>::HideMessages()
00176 {
00177 print_level = -1;
00178
00179 struct_mumps.icntl[0] = -1;
00180 struct_mumps.icntl[1] = -1;
00181 struct_mumps.icntl[2] = -1;
00182 struct_mumps.icntl[3] = 0;
00183
00184 }
00185
00186
00188 template<class T>
00189 inline void MatrixMumps<T>::ShowMessages()
00190 {
00191 print_level = 0;
00192
00193 struct_mumps.icntl[0] = 6;
00194 struct_mumps.icntl[1] = 0;
00195 struct_mumps.icntl[2] = 6;
00196 struct_mumps.icntl[3] = 2;
00197
00198 }
00199
00200
00201 template<class T>
00202 inline void MatrixMumps<T>::EnableOutOfCore()
00203 {
00204 out_of_core = true;
00205 }
00206
00207
00208 template<class T>
00209 inline void MatrixMumps<T>::DisableOutOfCore()
00210 {
00211 out_of_core = false;
00212 }
00213
00214
00216
00221 template<class T> template<class Prop,class Storage,class Allocator>
00222 void MatrixMumps<T>::FindOrdering(Matrix<T, Prop, Storage, Allocator> & mat,
00223 IVect& numbers, bool keep_matrix)
00224 {
00225 InitMatrix(mat);
00226
00227 int n = mat.GetM(), nnz = mat.GetNonZeros();
00228
00229 IVect num_row, num_col; Vector<T, VectFull, Allocator> values;
00230 ConvertMatrix_to_Coordinates(mat, num_row, num_col, values, 1);
00231
00232 values.Clear();
00233 if (!keep_matrix)
00234 mat.Clear();
00235
00236 struct_mumps.n = n; struct_mumps.nz = nnz;
00237 struct_mumps.irn = num_row.GetData();
00238 struct_mumps.jcn = num_col.GetData();
00239
00240
00241 struct_mumps.job = 1;
00242 CallMumps();
00243
00244 numbers.Reallocate(n);
00245 for (int i = 0; i < n; i++)
00246 numbers(i) = struct_mumps.sym_perm[i]-1;
00247 }
00248
00249
00251
00255 template<class T> template<class Prop, class Storage, class Allocator>
00256 void MatrixMumps<T>::FactorizeMatrix(Matrix<T,Prop,Storage,Allocator> & mat,
00257 bool keep_matrix)
00258 {
00259 InitMatrix(mat);
00260
00261 int n = mat.GetM(), nnz = mat.GetNonZeros();
00262
00263 IVect num_row, num_col; Vector<T, VectFull, Allocator> values;
00264 ConvertMatrix_to_Coordinates(mat, num_row, num_col, values, 1);
00265 if (!keep_matrix)
00266 mat.Clear();
00267
00268 struct_mumps.n = n; struct_mumps.nz = nnz;
00269 struct_mumps.irn = num_row.GetData();
00270 struct_mumps.jcn = num_col.GetData();
00271 struct_mumps.a = reinterpret_cast<pointer>(values.GetData());
00272
00273
00274 struct_mumps.job = 4;
00275 CallMumps();
00276 }
00277
00278
00280 template<class T> template<class Prop, class Storage, class Allocator>
00281 void MatrixMumps<T>
00282 ::PerformAnalysis(Matrix<T, Prop, Storage, Allocator> & mat)
00283 {
00284 InitMatrix(mat);
00285
00286 int n = mat.GetM(), nnz = mat.GetNonZeros();
00287
00288 Vector<T, VectFull, Allocator> values;
00289 ConvertMatrix_to_Coordinates(mat, num_row_glob, num_col_glob, values, 1);
00290
00291 struct_mumps.n = n; struct_mumps.nz = nnz;
00292 struct_mumps.irn = num_row_glob.GetData();
00293 struct_mumps.jcn = num_col_glob.GetData();
00294 struct_mumps.a = reinterpret_cast<pointer>(values.GetData());
00295
00296
00297 struct_mumps.job = 1;
00298 CallMumps();
00299 }
00300
00301
00303
00309 template<class T> template<class Prop, class Storage, class Allocator>
00310 void MatrixMumps<T>
00311 ::PerformFactorization(Matrix<T, Prop, Storage, Allocator> & mat)
00312 {
00313
00314
00315 struct_mumps.a = reinterpret_cast<pointer>(mat.GetData());
00316
00317
00318 struct_mumps.job = 2;
00319 CallMumps();
00320 }
00321
00322
00324 template<class T>
00325 int MatrixMumps<T>::GetInfoFactorization() const
00326 {
00327 return struct_mumps.info[0];
00328 }
00329
00330
00332
00338 template<class T> template<class Prop1, class Storage1, class Allocator,
00339 class Prop2, class Storage2, class Allocator2>
00340 void MatrixMumps<T>::
00341 GetSchurMatrix(Matrix<T, Prop1, Storage1, Allocator>& mat, const IVect& num,
00342 Matrix<T, Prop2, Storage2, Allocator2> & mat_schur,
00343 bool keep_matrix)
00344 {
00345 InitMatrix(mat);
00346
00347 int n_schur = num.GetM(), n = mat.GetM();
00348
00349 IVect index_schur(n_schur);
00350 for (int i = 0; i < n_schur; i++)
00351 index_schur(i) = num(i)+1;
00352
00353
00354 Vector<T, VectFull, Allocator2> vec_schur(n_schur*n_schur);
00355
00356 struct_mumps.icntl[18] = n_schur;
00357 struct_mumps.size_schur = n_schur;
00358 struct_mumps.listvar_schur = index_schur.GetData();
00359 struct_mumps.schur = reinterpret_cast<pointer>(vec_schur.GetData());
00360
00361
00362 FactorizeMatrix(mat, keep_matrix);
00363
00364
00365 struct_mumps.icntl[18] = 0;
00366 struct_mumps.size_schur = 0;
00367 struct_mumps.listvar_schur = NULL;
00368 struct_mumps.schur = NULL;
00369
00370
00371 int nb = 0;
00372 mat_schur.Reallocate(n,n);
00373 for (int i = 0; i < n; i++)
00374 for (int j = 0; j < n ;j++)
00375 mat_schur(i,j) = vec_schur(nb++);
00376
00377 vec_schur.Clear(); index_schur.Clear();
00378 }
00379
00380
00382
00386 template<class T> template<class Allocator2, class Transpose_status>
00387 void MatrixMumps<T>::Solve(const Transpose_status& TransA,
00388 Vector<T, VectFull, Allocator2>& x)
00389 {
00390 #ifdef SELDON_CHECK_DIMENSIONS
00391 if (x.GetM() != struct_mumps.n)
00392 throw WrongDim("Mumps::Solve(TransA, c)",
00393 string("The length of x is equal to ")
00394 + to_str(x.GetM())
00395 + " while the size of the matrix is equal to "
00396 + to_str(struct_mumps.n) + ".");
00397 #endif
00398
00399 if (TransA.Trans())
00400 struct_mumps.icntl[8] = 0;
00401 else
00402 struct_mumps.icntl[8] = 1;
00403
00404 struct_mumps.rhs = reinterpret_cast<pointer>(x.GetData());
00405 struct_mumps.job = 3;
00406 CallMumps();
00407 }
00408
00409
00410
00411 template<class T> template<class Allocator2>
00412 void MatrixMumps<T>::Solve(Vector<T, VectFull, Allocator2>& x)
00413 {
00414 Solve(SeldonNoTrans, x);
00415 }
00416
00417
00419
00423 template<class T>
00424 template<class Allocator2, class Transpose_status, class Prop>
00425 void MatrixMumps<T>::Solve(const Transpose_status& TransA,
00426 Matrix<T, Prop, ColMajor, Allocator2>& x)
00427 {
00428
00429 #ifdef SELDON_CHECK_BOUNDS
00430 if (x.GetM() != struct_mumps.n)
00431 throw WrongDim("Mumps::Solve", string("Row size of x is equal to ")
00432 + to_str(x.GetM()) + " while size of matrix is equal to "
00433 + to_str(struct_mumps.n));
00434 #endif
00435
00436 if (TransA.Trans())
00437 struct_mumps.icntl[8] = 0;
00438 else
00439 struct_mumps.icntl[8] = 1;
00440
00441 struct_mumps.nrhs = x.GetN();
00442 struct_mumps.lrhs = x.GetM();
00443 struct_mumps.rhs = reinterpret_cast<pointer>(x.GetData());
00444 struct_mumps.job = 3;
00445 CallMumps();
00446 }
00447
00448
00449 #ifdef SELDON_WITH_MPI
00450
00451
00457 template<class T> template<class Prop, class Allocator>
00458 void MatrixMumps<T>::
00459 FactorizeDistributedMatrix(Matrix<T, General, ColSparse, Allocator> & mat,
00460 const Prop& sym, const IVect& glob_number,
00461 bool keep_matrix)
00462 {
00463
00464 Matrix<T, Prop, RowSparse, Allocator> Atest;
00465 InitMatrix(Atest, true);
00466
00467
00468 struct_mumps.icntl[17] = 3;
00469
00470
00471 int N = mat.GetM();
00472 int nnz = mat.GetNonZeros();
00473
00474 IVect num_row, num_col; Vector<T, VectFull, Allocator> values;
00475 ConvertMatrix_to_Coordinates(mat, num_row,
00476 num_col, values, 0);
00477
00478
00479 for (int i = 0; i < num_row.GetM(); i++)
00480 {
00481 num_row(i)++;
00482 num_col(i) = glob_number(num_col(i)) + 1;
00483 }
00484
00485 if (!keep_matrix)
00486 mat.Clear();
00487
00488
00489 struct_mumps.n = N; struct_mumps.nz_loc = nnz;
00490 struct_mumps.irn_loc = num_row.GetData();
00491 struct_mumps.jcn_loc = num_col.GetData();
00492 struct_mumps.a_loc = reinterpret_cast<pointer>(values.GetData());
00493
00494
00495 struct_mumps.job = 4;
00496 CallMumps();
00497 cout<<"Factorization completed"<<endl;
00498 }
00499
00500
00502 template<class Alloc1, class Alloc2, class Alloc3, class Tint>
00503 void FactorizeDistributedMatrix(Vector<int, VectFull, Alloc1>&,
00504 Vector<int, VectFull, Alloc2>&,
00505 Vector<T, VectFull, Alloc3>&,
00506 const Vector<Tint>& glob_number,
00507 bool sym, bool keep_matrix)
00508 {
00509 throw Undefined("FactorizeDistributedMatrix(Vector<int>&, Vector<int>&, "
00510 "Vector<T>&, Vector<Tint>, bool, bool)");
00511 }
00512
00513
00515
00520 template<class T> template<class Allocator2, class Transpose_status>
00521 void MatrixMumps<T>::SolveDistributed(const Transpose_status& TransA,
00522 Vector<T, VectFull, Allocator2>& x,
00523 const IVect& glob_num)
00524 {
00525 Vector<T, VectFull, Allocator2> rhs;
00526 int cplx = sizeof(T)/8;
00527
00528 rhs.Reallocate(struct_mumps.n); rhs.Zero();
00529
00530 if (rank == 0)
00531 {
00532
00533 int nb_procs; MPI_Status status;
00534 MPI_Comm_size(MPI_COMM_WORLD, &nb_procs);
00535 if (nb_procs > 1)
00536 {
00537
00538 Vector<T, VectFull, Allocator2> xp;
00539 IVect nump;
00540 for (int i = 0; i < nb_procs; i++)
00541 {
00542
00543 if (i != 0)
00544 {
00545 int nb_dof;
00546 MPI_Recv(&nb_dof, 1, MPI_INT, i, 34,
00547 MPI_COMM_WORLD, &status);
00548 xp.Reallocate(nb_dof);
00549 nump.Reallocate(nb_dof);
00550 MPI_Recv(xp.GetDataVoid(), cplx*nb_dof,
00551 MPI_DOUBLE, i, 35, MPI_COMM_WORLD, &status);
00552 MPI_Recv(nump.GetData(), nb_dof, MPI_INT, i, 36,
00553 MPI_COMM_WORLD, &status);
00554 }
00555 else
00556 {
00557 xp = x; nump = glob_num;
00558 }
00559
00560 for (int j = 0; j < nump.GetM(); j++)
00561 rhs(nump(j)) = xp(j);
00562 }
00563 }
00564 else
00565 Copy(x, rhs);
00566
00567 struct_mumps.rhs = reinterpret_cast<pointer>(rhs.GetData());
00568 }
00569 else
00570 {
00571
00572 int nb = x.GetM();
00573 MPI_Send(&nb, 1, MPI_INT, 0, 34, MPI_COMM_WORLD);
00574 MPI_Send(x.GetDataVoid(), cplx*nb, MPI_DOUBLE, 0, 35, MPI_COMM_WORLD);
00575 MPI_Send(glob_num.GetData(), nb, MPI_INT, 0, 36, MPI_COMM_WORLD);
00576 }
00577
00578
00579 if (TransA.Trans())
00580 struct_mumps.icntl[8] = 0;
00581 else
00582 struct_mumps.icntl[8] = 1;
00583
00584 struct_mumps.job = 3;
00585 CallMumps();
00586
00587
00588 MPI_Bcast(rhs.GetDataVoid(), cplx*rhs.GetM(),
00589 MPI_DOUBLE, 0, MPI_COMM_WORLD);
00590
00591
00592 for (int i = 0; i < x.GetM(); i++)
00593 x(i) = rhs(glob_num(i));
00594 }
00595
00596
00597 template<class T> template<class Allocator2>
00598 void MatrixMumps<T>::SolveDistributed(Vector<T, VectFull, Allocator2>& x,
00599 const IVect& glob_num)
00600 {
00601 SolveDistributed(SeldonNoTrans, x, glob_num);
00602 }
00603 #endif
00604
00605
00606 template<class T, class Storage, class Allocator>
00607 void GetLU(Matrix<T,Symmetric,Storage,Allocator>& A, MatrixMumps<T>& mat_lu,
00608 bool keep_matrix = false)
00609 {
00610 mat_lu.FactorizeMatrix(A, keep_matrix);
00611 }
00612
00613
00614 template<class T, class Storage, class Allocator>
00615 void GetLU(Matrix<T,General,Storage,Allocator>& A, MatrixMumps<T>& mat_lu,
00616 bool keep_matrix = false)
00617 {
00618 mat_lu.FactorizeMatrix(A, keep_matrix);
00619 }
00620
00621
00622 template<class T, class Storage, class Allocator, class MatrixFull>
00623 void GetSchurMatrix(Matrix<T, Symmetric, Storage, Allocator>& A,
00624 MatrixMumps<T>& mat_lu, const IVect& num,
00625 MatrixFull& schur_matrix, bool keep_matrix = false)
00626 {
00627 mat_lu.GetSchurMatrix(A, num, schur_matrix, keep_matrix);
00628 }
00629
00630
00631 template<class T, class Storage, class Allocator, class MatrixFull>
00632 void GetSchurMatrix(Matrix<T, General, Storage, Allocator>& A,
00633 MatrixMumps<T>& mat_lu, const IVect& num,
00634 MatrixFull& schur_matrix, bool keep_matrix = false)
00635 {
00636 mat_lu.GetSchurMatrix(A, num, schur_matrix, keep_matrix);
00637 }
00638
00639
00640 template<class T, class Allocator>
00641 void SolveLU(MatrixMumps<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00642 {
00643 mat_lu.Solve(x);
00644 }
00645
00646
00647 template<class T, class Allocator, class Transpose_status>
00648 void SolveLU(const Transpose_status& TransA,
00649 MatrixMumps<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
00650 {
00651 mat_lu.Solve(TransA, x);
00652 }
00653
00654
00655 template<class T, class Prop, class Allocator>
00656 void SolveLU(MatrixMumps<T>& mat_lu,
00657 Matrix<T, Prop, ColMajor, Allocator>& x)
00658 {
00659 mat_lu.Solve(SeldonNoTrans, x);
00660 }
00661
00662
00663 template<class T, class Allocator, class Transpose_status>
00664 void SolveLU(const Transpose_status& TransA,
00665 MatrixMumps<T>& mat_lu, Matrix<T, ColMajor, Allocator>& x)
00666 {
00667 mat_lu.Solve(TransA, x);
00668 }
00669
00670 }
00671
00672 #define SELDON_FILE_MUMPS_CXX
00673 #endif