MFEM  v4.2.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
cpardiso.cpp
Go to the documentation of this file.
1 #include "cpardiso.hpp"
2 #include "hypre.hpp"
3 #include <algorithm>
4 #include <vector>
5 #include <numeric>
6 
7 #ifdef MFEM_USE_MPI
8 #ifdef MFEM_USE_MKL_CPARDISO
9 
10 namespace mfem
11 {
12 CPardisoSolver::CPardisoSolver(MPI_Comm comm) : comm_(comm)
13 {
14  // Indicate that default parameters are changed
15  iparm[0] = 1;
16  // Use METIS for fill-in reordering
17  iparm[1] = 2;
18  // Do not write the solution into the x vector data
19  iparm[5] = 0;
20  // Maximum number of iterative refinement steps
21  iparm[7] = 2;
22  // Perturb the pivot elements with 1E-13
23  iparm[9] = 13;
24  // Use nonsymmetric permutation
25  iparm[10] = 1;
26  // Perform a check on the input data
27  iparm[26] = 1;
28  // 0-based indexing in CSR data structure
29  iparm[34] = 1;
30  // All inputs are distributed between MPI processes
31  iparm[39] = 2;
32  // Maximum number of numerical factorizations
33  maxfct = 1;
34  // Which factorization to use. This parameter is ignored and always assumed
35  // to be equal to 1. See MKL documentation.
36  mnum = 1;
37  // Print statistical information in file
38  msglvl = 0;
39  // Initialize error flag
40  error = 0;
41  // Real nonsymmetric matrix
42  mtype = MatType::REAL_NONSYMMETRIC;
43  // Number of right hand sides
44  nrhs = 1;
45 };
46 
48 {
49  auto hypreParMat = dynamic_cast<const HypreParMatrix &>(op);
50 
51  MFEM_ASSERT(hypreParMat, "Must pass HypreParMatrix as Operator");
52 
53  auto parcsr_op = static_cast<hypre_ParCSRMatrix *>(
54  const_cast<HypreParMatrix &>(hypreParMat));
55 
56  hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
57 #if MFEM_HYPRE_VERSION >= 21600
58  hypre_CSRMatrixBigJtoJ(csr_op);
59 #endif
60 
61  m = parcsr_op->global_num_rows;
62  first_row = parcsr_op->first_row_index;
63  nnz_loc = csr_op->num_nonzeros;
64  m_loc = csr_op->num_rows;
65 
66  height = m_loc;
67  width = m_loc;
68 
69  double *csr_nzval = csr_op->data;
70  int *csr_colind = csr_op->j;
71 
72  delete[] csr_rowptr;
73  delete[] reordered_csr_colind;
74  delete[] reordered_csr_nzval;
75  csr_rowptr = new int[m_loc + 1];
76  reordered_csr_colind = new int[nnz_loc];
77  reordered_csr_nzval = new double[nnz_loc];
78 
79  for (int i = 0; i <= m_loc; i++)
80  {
81  csr_rowptr[i] = (csr_op->i)[i];
82  }
83 
84  // CPardiso expects the column indices to be sorted for each row
85  std::vector<int> permutation_idx(nnz_loc);
86  std::iota(permutation_idx.begin(), permutation_idx.end(), 0);
87  for (int i = 0; i < m_loc; i++)
88  {
89  std::sort(permutation_idx.begin() + csr_rowptr[i],
90  permutation_idx.begin() + csr_rowptr[i + 1],
91  [csr_colind](int i1, int i2)
92  {
93  return csr_colind[i1] < csr_colind[i2];
94  });
95  }
96 
97  for (int i = 0; i < nnz_loc; i++)
98  {
99  reordered_csr_colind[i] = csr_colind[permutation_idx[i]];
100  reordered_csr_nzval[i] = csr_nzval[permutation_idx[i]];
101  }
102 
103  hypre_CSRMatrixDestroy(csr_op);
104 
105  // The number of row in global matrix, rhs element and solution vector that
106  // begins the input domain belonging to this MPI process
107  iparm[40] = first_row;
108 
109  // The number of row in global matrix, rhs element and solution vector that
110  // ends the input domain belonging to this MPI process
111  iparm[41] = first_row + m_loc - 1;
112 
113  // Analyze inputs
114  phase = 11;
115  cluster_sparse_solver(pt,
116  &maxfct,
117  &mnum,
118  &mtype,
119  &phase,
120  &m,
121  reordered_csr_nzval,
122  csr_rowptr,
123  reordered_csr_colind,
124  &idum,
125  &nrhs,
126  iparm,
127  &msglvl,
128  &ddum,
129  &ddum,
130  &comm_,
131  &error);
132 
133  MFEM_ASSERT(error == 0, "CPardiso analyze input error");
134 
135  // Numerical factorization
136  phase = 22;
137  cluster_sparse_solver(pt,
138  &maxfct,
139  &mnum,
140  &mtype,
141  &phase,
142  &m,
143  reordered_csr_nzval,
144  csr_rowptr,
145  reordered_csr_colind,
146  &idum,
147  &nrhs,
148  iparm,
149  &msglvl,
150  &ddum,
151  &ddum,
152  &comm_,
153  &error);
154 
155  MFEM_ASSERT(error == 0, "CPardiso factorization input error");
156 }
157 
158 void CPardisoSolver::Mult(const Vector &b, Vector &x) const
159 {
160  // Solve
161  phase = 33;
162  cluster_sparse_solver(pt,
163  &maxfct,
164  &mnum,
165  &mtype,
166  &phase,
167  &m,
168  reordered_csr_nzval,
169  csr_rowptr,
170  reordered_csr_colind,
171  &idum,
172  &nrhs,
173  iparm,
174  &msglvl,
175  b.GetData(),
176  x.GetData(),
177  &comm_,
178  &error);
179 
180  MFEM_ASSERT(error == 0, "Pardiso solve error");
181 }
182 
183 void CPardisoSolver::SetPrintLevel(int print_level)
184 {
185  msglvl = print_level;
186 }
187 
189 {
190  mtype = mat_type;
191 }
192 
194 {
195  // Release all internal memory
196  phase = -1;
197  cluster_sparse_solver(pt,
198  &maxfct,
199  &mnum,
200  &mtype,
201  &phase,
202  &m,
203  reordered_csr_nzval,
204  csr_rowptr,
205  reordered_csr_colind,
206  &idum,
207  &nrhs,
208  iparm,
209  &msglvl,
210  &ddum,
211  &ddum,
212  &comm_,
213  &error);
214 
215  MFEM_ASSERT(error == 0, "CPardiso free error");
216 
217  delete[] csr_rowptr;
218  delete[] reordered_csr_colind;
219  delete[] reordered_csr_nzval;
220 }
221 
222 } // namespace mfem
223 
224 #endif // MFEM_USE_MKL_CPARDISO
225 #endif // MFEM_USE_MPI
void Mult(const Vector &b, Vector &x) const override
Solve.
Definition: cpardiso.cpp:158
CPardisoSolver(MPI_Comm comm)
Construct a new CPardisoSolver object.
Definition: cpardiso.cpp:12
double * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:169
double b
Definition: lissajous.cpp:42
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:27
void SetOperator(const Operator &op) override
Set the Operator object and perform factorization.
Definition: cpardiso.cpp:47
Vector data type.
Definition: vector.hpp:51
void SetPrintLevel(int print_lvl)
Set the print level for MKL CPardiso.
Definition: cpardiso.cpp:183
void SetMatrixType(MatType mat_type)
Set the matrix type.
Definition: cpardiso.cpp:188
Abstract operator.
Definition: operator.hpp:24
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:181
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:28