12 #include "../config/config.hpp"
20 #error "MUMPSSolver requires HYPRE_Int == int, for now."
24 #define MUMPS_ICNTL(I) icntl[(I) -1]
25 #define MUMPS_INFO(I) info[(I) -1]
34 MFEM_VERIFY(APtr,
"Not compatible matrix type");
39 comm = APtr->GetComm();
40 MPI_Comm_size(comm, &numProcs);
41 MPI_Comm_rank(comm, &myid);
43 auto parcsr_op = (hypre_ParCSRMatrix *) const_cast<HypreParMatrix &>(*APtr);
46 hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
48 #if MFEM_HYPRE_VERSION >= 21600
49 hypre_CSRMatrixBigJtoJ(csr_op);
52 int *Iptr = csr_op->i;
53 int *Jptr = csr_op->j;
54 int n_loc = csr_op->num_rows;
56 row_start = parcsr_op->first_row_index;
63 for (
int i = 0; i < n_loc; i++)
65 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
67 int ii = row_start + i + 1;
70 if (ii>=jj) { nnz++; }
76 nnz = csr_op->num_nonzeros;
79 int * I =
new int[nnz];
80 int * J =
new int[nnz];
89 data =
new double[nnz];
90 for (
int i = 0; i < n_loc; i++)
92 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
94 int ii = row_start + i + 1;
100 data[l++] = csr_op->data[k];
108 for (
int i = 0; i < n_loc; i++)
110 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
112 I[k] = row_start + i + 1;
127 id =
new DMUMPS_STRUC_C;
129 id->comm_fortran = (MUMPS_INT) MPI_Comm_c2f(comm);
143 id->n = parcsr_op->global_num_rows;
161 hypre_CSRMatrixDestroy(csr_op);
164 if (mat_type) {
delete [] data; }
166 #if MFEM_MUMPS_VERSION >= 530
168 irhs_loc =
new int[n_loc];
169 for (
int i = 0; i < n_loc; i++)
171 irhs_loc[i] = row_start + i + 1;
174 MPI_Allgather(&row_start, 1, MPI_INT, row_starts, 1, MPI_INT, comm);
179 delete [] recv_counts;
180 rhs_glob =
new double[parcsr_op->global_num_rows];
181 recv_counts =
new int[numProcs];
183 MPI_Gather(&n_loc, 1, MPI_INT, recv_counts, 1, MPI_INT, 0, comm);
187 displs =
new int[numProcs];
190 for (
int k = 0; k < numProcs-1; k++)
203 #if MFEM_MUMPS_VERSION >= 530
205 id->nloc_rhs = x.
Size();
206 id->lrhs_loc = x.
Size();
208 id->irhs_loc = irhs_loc;
210 id->lsol_loc =
id->MUMPS_INFO(23);
211 id->isol_loc =
new int[
id->MUMPS_INFO(23)];
212 id->sol_loc =
new double[
id->MUMPS_INFO(23)];
218 RedistributeSol(id->isol_loc, id->sol_loc, y.
GetData());
220 delete []
id->sol_loc;
221 delete []
id->isol_loc;
224 rhs_glob, recv_counts,
225 displs, MPI_DOUBLE, 0, comm);
227 if (myid == 0) {
id->rhs = rhs_glob; }
233 MPI_Scatterv(rhs_glob, recv_counts, displs,
235 MPI_DOUBLE, 0, comm);
242 id->MUMPS_ICNTL(9) = 0;
245 id->MUMPS_ICNTL(9) = 1;
251 print_level = print_lvl;
263 #if MFEM_MUMPS_VERSION >= 530
266 delete [] recv_counts;
276 void MUMPSSolver::SetParameters()
279 id->MUMPS_ICNTL(1) = 6;
281 id->MUMPS_ICNTL(2) = 6;
283 id->MUMPS_ICNTL(3) = 6;
285 id->MUMPS_ICNTL(4) = print_level;
287 id->MUMPS_ICNTL(5) = 0;
289 id->MUMPS_ICNTL(9) = 1;
291 id->MUMPS_ICNTL(10) = 0;
293 id->MUMPS_ICNTL(11) = 0;
295 id->MUMPS_ICNTL(13) = 0;
297 id->MUMPS_ICNTL(14) = 20;
299 id->MUMPS_ICNTL(16) = 0;
301 id->MUMPS_ICNTL(18) = 3;
303 id->MUMPS_ICNTL(19) = 0;
305 #if MFEM_MUMPS_VERSION >= 530
307 id->MUMPS_ICNTL(20) = 10;
309 id->MUMPS_ICNTL(21) = 1;
312 id->MUMPS_ICNTL(20) = 0;
314 id->MUMPS_ICNTL(21) = 0;
317 id->MUMPS_ICNTL(22) = 0;
319 id->MUMPS_ICNTL(23) = 0;
322 #if MFEM_MUMPS_VERSION >= 530
323 int MUMPSSolver::GetRowRank(
int i,
const Array<int> &row_starts_)
const
325 if (row_starts_.Size() == 1)
329 auto up = std::upper_bound(row_starts_.begin(), row_starts_.end(), i);
330 return std::distance(row_starts_.begin(), up) - 1;
333 void MUMPSSolver::RedistributeSol(
const int * row_map,
334 const double * x,
double * y)
const
336 int size =
id->MUMPS_INFO(23);
337 int * send_count =
new int[numProcs]();
338 for (
int i = 0; i < size; i++)
340 int j = row_map[i] - 1;
341 int row_rank = GetRowRank(j, row_starts);
342 if (myid == row_rank) {
continue; }
343 send_count[row_rank]++;
346 int * recv_count =
new int[numProcs];
347 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
349 int * send_displ =
new int [numProcs]; send_displ[0] = 0;
350 int * recv_displ =
new int [numProcs]; recv_displ[0] = 0;
351 int sbuff_size = send_count[numProcs-1];
352 int rbuff_size = recv_count[numProcs-1];
353 for (
int k = 0; k < numProcs - 1; k++)
355 send_displ[k + 1] = send_displ[k] + send_count[k];
356 recv_displ[k + 1] = recv_displ[k] + recv_count[k];
357 sbuff_size += send_count[k];
358 rbuff_size += recv_count[k];
361 int * sendbuf_index =
new int[sbuff_size];
362 double * sendbuf_values =
new double[sbuff_size];
363 int * soffs =
new int[numProcs]();
365 for (
int i = 0; i < size; i++)
367 int j = row_map[i] - 1;
368 int row_rank = GetRowRank(j, row_starts);
369 if (myid == row_rank)
371 int local_index = j - row_start;
372 y[local_index] = x[i];
376 int k = send_displ[row_rank] + soffs[row_rank];
377 sendbuf_index[k] = j;
378 sendbuf_values[k] = x[i];
383 int * recvbuf_index =
new int[rbuff_size];
384 double * recvbuf_values =
new double[rbuff_size];
385 MPI_Alltoallv(sendbuf_index,
394 MPI_Alltoallv(sendbuf_values,
405 for (
int i = 0; i < rbuff_size; i++)
407 int local_index = recvbuf_index[i] - row_start;
408 y[local_index] = recvbuf_values[i];
411 delete [] recvbuf_values;
412 delete [] recvbuf_index;
414 delete [] sendbuf_values;
415 delete [] sendbuf_index;
416 delete [] recv_displ;
417 delete [] send_displ;
418 delete [] recv_count;
419 delete [] send_count;
425 #endif // MFEM_USE_MPI
426 #endif // MFEM_USE_MUMPS
void SetOperator(const Operator &op)
Set the Operator and perform factorization.
void SetPrintLevel(int print_lvl)
Set the error print level for MUMPS.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int Size() const
Returns the size of the vector.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void MultTranspose(const Vector &x, Vector &y) const
Transpose Solve y = Op^{-T} x.
void Mult(const Vector &x, Vector &y) const
Solve y = Op^{-1} x.
void SetMatrixSymType(MatType mtype)
Set the matrix type.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
virtual const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int height
Dimension of the output / number of rows in the matrix.
Wrapper for hypre's ParCSR matrix class.
virtual double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
int width
Dimension of the input / number of columns in the matrix.