38 #if defined(GMM_USES_MUMPS) || defined(HAVE_DMUMPS_C_H)
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");
150 GMM_WARNING1(
"Solve with MUMPS failed: matrix is singular");
153 GMM_ASSERT1(
false,
"Solve with MUMPS failed: error "
154 <<
id.INFO(1) <<
", increase ICNTL(14)");
156 GMM_ASSERT1(
false,
"Solve with MUMPS failed: not enough memory");
158 GMM_ASSERT1(
false,
"Solve with MUMPS failed with error "
169 template <
typename MAT,
typename VECTX,
typename VECTB>
170 bool MUMPS_solve(
const MAT &A,
const VECTX &X_,
const VECTB &B,
171 bool sym =
false,
bool distributed =
false) {
172 VECTX &X =
const_cast<VECTX &
>(X_);
174 typedef typename linalg_traits<MAT>::value_type T;
175 typedef typename mumps_interf<T>::value_type MUMPS_T;
176 GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A),
"Non-square matrix");
178 std::vector<T> rhs(gmm::vect_size(B)); gmm::copy(B, rhs);
180 ij_sparse_matrix<T> AA(A, sym);
182 const int JOB_INIT = -1;
183 const int JOB_END = -2;
184 const int USE_COMM_WORLD = -987654;
186 typename mumps_interf<T>::MUMPS_STRUC_C id;
190 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
195 id.sym = sym ? 2 : 0;
196 id.comm_fortran = USE_COMM_WORLD;
197 mumps_interf<T>::mumps_c(
id);
199 if (rank == 0 || distributed) {
200 id.n = int(gmm::mat_nrows(A));
202 id.nz_loc = int(AA.irn.size());
203 id.irn_loc = &(AA.irn[0]);
204 id.jcn_loc = &(AA.jcn[0]);
205 id.a_loc = (MUMPS_T*)(&(AA.a[0]));
207 id.nz = int(AA.irn.size());
208 id.irn = &(AA.irn[0]);
209 id.jcn = &(AA.jcn[0]);
210 id.a = (MUMPS_T*)(&(AA.a[0]));
213 id.rhs = (MUMPS_T*)(&(rhs[0]));
236 mumps_interf<T>::mumps_c(
id);
237 bool ok = mumps_error_check(
id);
240 mumps_interf<T>::mumps_c(
id);
243 MPI_Bcast(&(rhs[0]),
id.n,gmm::mpi_type(T()),0,MPI_COMM_WORLD);
257 template <
typename MAT,
typename VECTX,
typename VECTB>
258 bool MUMPS_distributed_matrix_solve(
const MAT &A,
const VECTX &X_,
259 const VECTB &B,
bool sym =
false) {
260 return MUMPS_solve(A, X_, B, sym,
true);
266 inline T real_or_complex(std::complex<T> a) {
return a.real(); }
268 inline T real_or_complex(T &a) {
return a; }
274 template <typename MAT, typename T = typename linalg_traits<MAT>::value_type>
275 T MUMPS_determinant(
const MAT &A,
int &exponent,
276 bool sym =
false,
bool distributed =
false) {
278 typedef typename mumps_interf<T>::value_type MUMPS_T;
279 typedef typename number_traits<T>::magnitude_type R;
280 GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A),
"Non-square matrix");
282 ij_sparse_matrix<T> AA(A, sym);
284 const int JOB_INIT = -1;
285 const int JOB_END = -2;
286 const int USE_COMM_WORLD = -987654;
288 typename mumps_interf<T>::MUMPS_STRUC_C id;
292 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
297 id.sym = sym ? 2 : 0;
298 id.comm_fortran = USE_COMM_WORLD;
299 mumps_interf<T>::mumps_c(
id);
301 if (rank == 0 || distributed) {
302 id.n = int(gmm::mat_nrows(A));
304 id.nz_loc = int(AA.irn.size());
305 id.irn_loc = &(AA.irn[0]);
306 id.jcn_loc = &(AA.jcn[0]);
307 id.a_loc = (MUMPS_T*)(&(AA.a[0]));
309 id.nz = int(AA.irn.size());
310 id.irn = &(AA.irn[0]);
311 id.jcn = &(AA.jcn[0]);
312 id.a = (MUMPS_T*)(&(AA.a[0]));
333 mumps_interf<T>::mumps_c(
id);
334 mumps_error_check(
id);
336 T det = real_or_complex(std::complex<R>(
id.RINFOG(12),
id.RINFOG(13)));
337 exponent =
id.INFOG(34);
340 mumps_interf<T>::mumps_c(
id);
353 #endif // GMM_MUMPS_INTERFACE_H
355 #endif // GMM_USES_MUMPS