38 #if defined(GMM_USES_MUMPS)
40 #ifndef GMM_MUMPS_INTERFACE_H
41 #define GMM_MUMPS_INTERFACE_H
69 #define ICNTL(I) icntl[(I)-1]
70 #define INFO(I) info[(I)-1]
71 #define INFOG(I) infog[(I)-1]
72 #define RINFOG(I) rinfog[(I)-1]
74 template <
typename T>
struct ij_sparse_matrix {
80 template <
typename L>
void store(
const L& l,
size_type i) {
81 typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
82 ite = vect_const_end(l);
83 for (; it != ite; ++it) {
84 int ir = (int)i + 1, jc = (
int)it.index() + 1;
85 if (*it != T(0) && (!sym || ir >= jc))
86 { irn.push_back(ir); jcn.push_back(jc); a.push_back(*it); }
90 template <
typename L>
void build_from(
const L& l, row_major) {
91 for (
size_type i = 0; i < mat_nrows(l); ++i)
92 store(mat_const_row(l, i), i);
95 template <
typename L>
void build_from(
const L& l, col_major) {
96 for (
size_type i = 0; i < mat_ncols(l); ++i)
97 store(mat_const_col(l, i), i);
101 template <
typename L> ij_sparse_matrix(
const L& A,
bool sym_) {
104 irn.reserve(nz); jcn.reserve(nz); a.reserve(nz);
105 build_from(A,
typename principal_orientation_type<
typename
106 linalg_traits<L>::sub_orientation>::potype());
114 template <
typename T>
struct mumps_interf {};
116 template <>
struct mumps_interf<float> {
117 typedef SMUMPS_STRUC_C MUMPS_STRUC_C;
118 typedef float value_type;
120 static void mumps_c(MUMPS_STRUC_C &
id) { smumps_c(&
id); }
123 template <>
struct mumps_interf<double> {
124 typedef DMUMPS_STRUC_C MUMPS_STRUC_C;
125 typedef double value_type;
126 static void mumps_c(MUMPS_STRUC_C &
id) { dmumps_c(&
id); }
129 template <>
struct mumps_interf<std::complex<float> > {
130 typedef CMUMPS_STRUC_C MUMPS_STRUC_C;
131 typedef mumps_complex value_type;
132 static void mumps_c(MUMPS_STRUC_C &
id) { cmumps_c(&
id); }
135 template <>
struct mumps_interf<std::complex<double> > {
136 typedef ZMUMPS_STRUC_C MUMPS_STRUC_C;
137 typedef mumps_double_complex value_type;
138 static void mumps_c(MUMPS_STRUC_C &
id) { zmumps_c(&
id); }
142 template <
typename MUMPS_STRUCT>
143 static inline bool mumps_error_check(MUMPS_STRUCT &
id) {
144 if (
id.INFO(1) < 0) {
145 switch (
id.INFO(1)) {
147 GMM_ASSERT1(
false,
"Solve with MUMPS failed: NZ = " <<
id.INFO(2)
148 <<
" is out of range");
151 GMM_WARNING1(
"Solve with MUMPS failed: matrix is singular");
154 GMM_ASSERT1(
false,
"Solve with MUMPS failed: error "
155 <<
id.INFO(1) <<
", increase ICNTL(14)");
158 GMM_ASSERT1(
false,
"Solve with MUMPS failed: not enough memory");
161 GMM_ASSERT1(
false,
"Solve with MUMPS failed with error "
173 template <
typename MAT,
typename VECTX,
typename VECTB>
174 bool MUMPS_solve(
const MAT &A,
const VECTX &X_,
const VECTB &B,
175 bool sym =
false,
bool distributed =
false) {
176 VECTX &X =
const_cast<VECTX &
>(X_);
178 typedef typename linalg_traits<MAT>::value_type T;
179 typedef typename mumps_interf<T>::value_type MUMPS_T;
180 GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A),
"Non-square matrix");
182 std::vector<T> rhs(gmm::vect_size(B));
gmm::copy(B, rhs);
184 ij_sparse_matrix<T> AA(A, sym);
186 const int JOB_INIT = -1;
187 const int JOB_END = -2;
188 const int USE_COMM_WORLD = -987654;
190 typename mumps_interf<T>::MUMPS_STRUC_C id;
194 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
199 id.sym = sym ? 2 : 0;
200 id.comm_fortran = USE_COMM_WORLD;
201 mumps_interf<T>::mumps_c(
id);
203 if (rank == 0 || distributed) {
204 id.n = int(gmm::mat_nrows(A));
206 id.nz_loc = int(AA.irn.size());
207 id.irn_loc = &(AA.irn[0]);
208 id.jcn_loc = &(AA.jcn[0]);
209 id.a_loc = (MUMPS_T*)(&(AA.a[0]));
211 id.nz = int(AA.irn.size());
212 id.irn = &(AA.irn[0]);
213 id.jcn = &(AA.jcn[0]);
214 id.a = (MUMPS_T*)(&(AA.a[0]));
217 id.rhs = (MUMPS_T*)(&(rhs[0]));
240 mumps_interf<T>::mumps_c(
id);
241 bool ok = mumps_error_check(
id);
244 mumps_interf<T>::mumps_c(
id);
247 MPI_Bcast(&(rhs[0]),
id.n,gmm::mpi_type(T()),0,MPI_COMM_WORLD);
261 template <
typename MAT,
typename VECTX,
typename VECTB>
262 bool MUMPS_distributed_matrix_solve(
const MAT &A,
const VECTX &X_,
263 const VECTB &B,
bool sym =
false) {
264 return MUMPS_solve(A, X_, B, sym,
true);
270 inline T real_or_complex(std::complex<T> a) {
return a.real(); }
272 inline T real_or_complex(T &a) {
return a; }
278 template <typename MAT, typename T = typename linalg_traits<MAT>::value_type>
279 T MUMPS_determinant(
const MAT &A,
int &exponent,
280 bool sym =
false,
bool distributed =
false) {
282 typedef typename mumps_interf<T>::value_type MUMPS_T;
283 typedef typename number_traits<T>::magnitude_type R;
284 GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A),
"Non-square matrix");
286 ij_sparse_matrix<T> AA(A, sym);
288 const int JOB_INIT = -1;
289 const int JOB_END = -2;
290 const int USE_COMM_WORLD = -987654;
292 typename mumps_interf<T>::MUMPS_STRUC_C id;
296 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
301 id.sym = sym ? 2 : 0;
302 id.comm_fortran = USE_COMM_WORLD;
303 mumps_interf<T>::mumps_c(
id);
305 if (rank == 0 || distributed) {
306 id.n = int(gmm::mat_nrows(A));
308 id.nz_loc = int(AA.irn.size());
309 id.irn_loc = &(AA.irn[0]);
310 id.jcn_loc = &(AA.jcn[0]);
311 id.a_loc = (MUMPS_T*)(&(AA.a[0]));
313 id.nz = int(AA.irn.size());
314 id.irn = &(AA.irn[0]);
315 id.jcn = &(AA.jcn[0]);
316 id.a = (MUMPS_T*)(&(AA.a[0]));
337 mumps_interf<T>::mumps_c(
id);
338 mumps_error_check(
id);
340 T det = real_or_complex(std::complex<R>(
id.RINFOG(12),
id.RINFOG(13)));
341 exponent =
id.INFOG(34);
344 mumps_interf<T>::mumps_c(
id);
size_type nnz(const L &l)
count the number of non-zero entries of a vector or matrix.
void copy(const L1 &l1, L2 &l2)
*/
Include the base gmm files.
size_t size_type
used as the common size type in the library