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);
45 hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
46 #if MFEM_HYPRE_VERSION >= 21600
47 hypre_CSRMatrixBigJtoJ(csr_op);
50 int *Iptr = csr_op->i;
51 int *Jptr = csr_op->j;
52 int n_loc = csr_op->num_rows;
54 row_start = parcsr_op->first_row_index;
61 for (
int i = 0; i < n_loc; i++)
63 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
65 int ii = row_start + i + 1;
68 if (ii>=jj) { nnz++; }
74 nnz = csr_op->num_nonzeros;
77 int * I =
new int[nnz];
78 int * J =
new int[nnz];
87 data =
new double[nnz];
88 for (
int i = 0; i < n_loc; i++)
90 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
92 int ii = row_start + i + 1;
98 data[l++] = csr_op->data[k];
106 for (
int i = 0; i < n_loc; i++)
108 for (
int j = Iptr[i]; j < Iptr[i + 1]; j++)
110 I[k] = row_start + i + 1;
125 id =
new DMUMPS_STRUC_C;
127 id->comm_fortran = (MUMPS_INT) MPI_Comm_c2f(comm);
141 id->n = parcsr_op->global_num_rows;
159 hypre_CSRMatrixDestroy(csr_op);
162 if (mat_type) {
delete [] data; }
164 #if MFEM_MUMPS_VERSION >= 530
166 irhs_loc =
new int[n_loc];
167 for (
int i = 0; i < n_loc; i++)
169 irhs_loc[i] = row_start + i + 1;
172 MPI_Allgather(&row_start, 1, MPI_INT, row_starts, 1, MPI_INT, comm);
177 delete [] recv_counts;
178 rhs_glob =
new double[parcsr_op->global_num_rows];
179 recv_counts =
new int[numProcs];
181 MPI_Gather(&n_loc, 1, MPI_INT, recv_counts, 1, MPI_INT, 0, comm);
185 displs =
new int[numProcs];
188 for (
int k = 0; k < numProcs-1; k++)
201 #if MFEM_MUMPS_VERSION >= 530
203 id->nloc_rhs = x.
Size();
204 id->lrhs_loc = x.
Size();
206 id->irhs_loc = irhs_loc;
208 id->lsol_loc =
id->MUMPS_INFO(23);
209 id->isol_loc =
new int[
id->MUMPS_INFO(23)];
210 id->sol_loc =
new double[
id->MUMPS_INFO(23)];
216 RedistributeSol(id->isol_loc, id->sol_loc, y.
GetData());
218 delete []
id->sol_loc;
219 delete []
id->isol_loc;
222 rhs_glob, recv_counts,
223 displs, MPI_DOUBLE, 0, comm);
225 if (myid == 0) {
id->rhs = rhs_glob; }
231 MPI_Scatterv(rhs_glob, recv_counts, displs,
233 MPI_DOUBLE, 0, comm);
240 id->MUMPS_ICNTL(9) = 0;
243 id->MUMPS_ICNTL(9) = 1;
249 print_level = print_lvl;
261 #if MFEM_MUMPS_VERSION >= 530
264 delete [] recv_counts;
274 void MUMPSSolver::SetParameters()
277 id->MUMPS_ICNTL(1) = 6;
279 id->MUMPS_ICNTL(2) = 6;
281 id->MUMPS_ICNTL(3) = 6;
283 id->MUMPS_ICNTL(4) = print_level;
285 id->MUMPS_ICNTL(5) = 0;
287 id->MUMPS_ICNTL(9) = 1;
289 id->MUMPS_ICNTL(10) = 0;
291 id->MUMPS_ICNTL(11) = 0;
293 id->MUMPS_ICNTL(13) = 0;
295 id->MUMPS_ICNTL(14) = 20;
297 id->MUMPS_ICNTL(16) = 0;
299 id->MUMPS_ICNTL(18) = 3;
301 id->MUMPS_ICNTL(19) = 0;
303 #if MFEM_MUMPS_VERSION >= 530
305 id->MUMPS_ICNTL(20) = 10;
307 id->MUMPS_ICNTL(21) = 1;
310 id->MUMPS_ICNTL(20) = 0;
312 id->MUMPS_ICNTL(21) = 0;
315 id->MUMPS_ICNTL(22) = 0;
317 id->MUMPS_ICNTL(23) = 0;
320 #if MFEM_MUMPS_VERSION >= 530
321 int MUMPSSolver::GetRowRank(
int i,
const Array<int> &row_starts_)
const
323 if (row_starts_.Size() == 1)
327 auto up = std::upper_bound(row_starts_.begin(), row_starts_.end(), i);
328 return std::distance(row_starts_.begin(), up) - 1;
331 void MUMPSSolver::RedistributeSol(
const int * row_map,
332 const double * x,
double * y)
const
334 int size =
id->MUMPS_INFO(23);
335 int * send_count =
new int[numProcs]();
336 for (
int i = 0; i < size; i++)
338 int j = row_map[i] - 1;
339 int row_rank = GetRowRank(j, row_starts);
340 if (myid == row_rank) {
continue; }
341 send_count[row_rank]++;
344 int * recv_count =
new int[numProcs];
345 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
347 int * send_displ =
new int [numProcs]; send_displ[0] = 0;
348 int * recv_displ =
new int [numProcs]; recv_displ[0] = 0;
349 int sbuff_size = send_count[numProcs-1];
350 int rbuff_size = recv_count[numProcs-1];
351 for (
int k = 0; k < numProcs - 1; k++)
353 send_displ[k + 1] = send_displ[k] + send_count[k];
354 recv_displ[k + 1] = recv_displ[k] + recv_count[k];
355 sbuff_size += send_count[k];
356 rbuff_size += recv_count[k];
359 int * sendbuf_index =
new int[sbuff_size];
360 double * sendbuf_values =
new double[sbuff_size];
361 int * soffs =
new int[numProcs]();
363 for (
int i = 0; i < size; i++)
365 int j = row_map[i] - 1;
366 int row_rank = GetRowRank(j, row_starts);
367 if (myid == row_rank)
369 int local_index = j - row_start;
370 y[local_index] = x[i];
374 int k = send_displ[row_rank] + soffs[row_rank];
375 sendbuf_index[k] = j;
376 sendbuf_values[k] = x[i];
381 int * recvbuf_index =
new int[rbuff_size];
382 double * recvbuf_values =
new double[rbuff_size];
383 MPI_Alltoallv(sendbuf_index,
392 MPI_Alltoallv(sendbuf_values,
403 for (
int i = 0; i < rbuff_size; i++)
405 int local_index = recvbuf_index[i] - row_start;
406 y[local_index] = recvbuf_values[i];
409 delete [] recvbuf_values;
410 delete [] recvbuf_index;
412 delete [] sendbuf_values;
413 delete [] sendbuf_index;
414 delete [] recv_displ;
415 delete [] send_displ;
416 delete [] recv_count;
417 delete [] send_count;
423 #endif // MFEM_USE_MPI
424 #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.