12 #include "../config/config.hpp" 14 #ifdef MFEM_USE_SUPERLU 20 #include "superlu_ddefs.h" 22 #if XSDK_INDEX_SIZE == 64 && !(defined(HYPRE_BIGINT) || defined(HYPRE_MIXEDINT)) 23 #error "Mismatch between HYPRE (32bit) and SuperLU (64bit) integer types" 25 #if XSDK_INDEX_SIZE == 32 && (defined(HYPRE_BIGINT) || defined(HYPRE_MIXEDINT)) 26 #error "Mismatch between HYPRE (64bit) and SuperLU (32bit) integer types" 29 #if SUPERLU_DIST_MAJOR_VERSION > 6 || \ 30 (SUPERLU_DIST_MAJOR_VERSION == 6 && SUPERLU_DIST_MINOR_VERSION >= 3) 31 #define ScalePermstruct_t dScalePermstruct_t 32 #define LUstruct_t dLUstruct_t 33 #define SOLVEstruct_t dSOLVEstruct_t 34 #define ZeroLblocks dZeroLblocks 35 #define ZeroUblocks dZeroUblocks 36 #define Destroy_LU dDestroy_LU 37 #define SolveFinalize dSolveFinalize 38 #define ScalePermstructInit dScalePermstructInit 39 #define ScalePermstructFree dScalePermstructFree 40 #define LUstructFree dLUstructFree 41 #define LUstructInit dLUstructInit 44 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 45 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 46 #define DeAllocLlu_3d dDeAllocLlu_3d 47 #define DeAllocGlu_3d dDeAllocGlu_3d 48 #define Destroy_A3d_gathered_on_2d dDestroy_A3d_gathered_on_2d 54 unsigned int root = 0;
55 unsigned short len =
sizeof(int); len <<= 2;
56 unsigned short shift = (
unsigned short)((len << 1) - 2);
58 for (
int i = 0; i < len; i++)
61 rem = ((rem << 2) + (a >> shift));
80 MPI_Comm_size(comm, &np);
81 MFEM_VERIFY(npdep > 0 && np % npdep == 0 && !(npdep & (npdep - 1)),
82 "SuperLUSolver: 3D partition depth must be a power of two " 83 "and evenly divide the number of processors!");
84 int nr = (int)
sqrti((
unsigned int)(np / npdep));
85 while (np % nr != 0 && nr > 0)
90 "SuperLUSolver: Unable to determine processor grid for np = " << np);
97 MPI_Comm_size(comm, &np);
98 int nc = np / (nr * npdep);
99 MFEM_VERIFY(nr * nc * npdep == np,
100 "SuperLUSolver: Impossible processor partition!");
118 width = num_loc_rows;
121 rowLocPtr_ =
new SuperMatrix;
122 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
125 int_t m = glob_nrows;
126 int_t n = glob_ncols;
127 int_t nnz_loc = I[num_loc_rows];
128 int_t m_loc = num_loc_rows;
129 int_t fst_row = first_loc_row;
131 double *nzval = NULL;
132 int_t *colind = NULL;
133 int_t *rowptr = NULL;
135 if (!(nzval = doubleMalloc_dist(nnz_loc)))
137 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for nzval!");
139 for (int_t i = 0; i < nnz_loc; i++)
144 if (!(colind = intMalloc_dist(nnz_loc)))
146 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for colind!")
148 for (int_t i = 0; i < nnz_loc; i++)
153 if (!(rowptr = intMalloc_dist(m_loc+1)))
155 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for rowptr!")
157 for (int_t i = 0; i <= m_loc; i++)
163 dCreate_CompRowLoc_Matrix_dist(A, m, n, nnz_loc, m_loc, fst_row,
164 nzval, colind, rowptr,
165 SLU_NR_loc, SLU_D, SLU_GE);
168 num_global_rows_ = m;
169 num_global_cols_ = n;
175 MFEM_VERIFY(APtr,
"Not a compatible matrix type");
183 rowLocPtr_ =
new SuperMatrix;
184 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
188 hypre_ParCSRMatrix *parcsr_op =
189 (hypre_ParCSRMatrix *)const_cast<HypreParMatrix &>(*APtr);
194 hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
196 HYPRE_Int *Iptr = csr_op->i;
197 #if MFEM_HYPRE_VERSION >= 21600 200 HYPRE_Int *Jptr = csr_op->j;
202 int_t m = parcsr_op->global_num_rows;
203 int_t n = parcsr_op->global_num_cols;
204 int_t fst_row = parcsr_op->first_row_index;
205 int_t nnz_loc = csr_op->num_nonzeros;
206 int_t m_loc = csr_op->num_rows;
211 double *nzval = NULL;
212 int_t *colind = NULL;
213 int_t *rowptr = NULL;
215 if (!(nzval = doubleMalloc_dist(nnz_loc)))
217 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for nzval!");
219 for (int_t i = 0; i < nnz_loc; i++)
221 nzval[i] = csr_op->data[i];
224 if (!(colind = intMalloc_dist(nnz_loc)))
226 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for colind!")
228 for (int_t i = 0; i < nnz_loc; i++)
233 if (!(rowptr = intMalloc_dist(m_loc+1)))
235 MFEM_ABORT(
"SuperLURowLocMatrix: Malloc failed for rowptr!")
237 for (int_t i = 0; i <= m_loc; i++)
243 dCreate_CompRowLoc_Matrix_dist(A, m, n, nnz_loc, m_loc, fst_row,
244 nzval, colind, rowptr,
245 SLU_NR_loc, SLU_D, SLU_GE);
248 hypre_CSRMatrixDestroy(csr_op);
251 num_global_rows_ = m;
252 num_global_cols_ = n;
257 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
258 Destroy_CompRowLoc_Matrix_dist(A);
280 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
286 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 287 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 290 gridinfo3d_t *grid3d = (gridinfo3d_t *)
gridPtr_;
294 if (grid3d->zscp.Iam == 0)
299 SolveFinalize(options, SOLVEstruct);
305 DeAllocGlu_3d(LUstruct);
307 Destroy_A3d_gathered_on_2d(SOLVEstruct, grid3d);
308 ScalePermstructFree(ScalePermstruct);
309 LUstructFree(LUstruct);
312 superlu_gridexit3d(grid3d);
318 gridinfo_t *grid = (gridinfo_t *)
gridPtr_;
323 SolveFinalize(options, SOLVEstruct);
324 ScalePermstructFree(ScalePermstruct);
325 LUstructFree(LUstruct);
328 superlu_gridexit(grid);
333 delete ScalePermstruct;
338 void SuperLUSolver::Init(MPI_Comm comm)
346 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 347 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 358 "SuperLUSolver: 3D partitioning is only available for " 359 "SuperLU_DIST version >= 7.2.0!");
374 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
375 set_default_options_dist(options);
376 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 377 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 380 options->Algo3d = YES;
387 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
388 yes_no_t opt = print_stat ? YES : NO;
389 options->PrintStat = opt;
394 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
395 yes_no_t opt = equil ? YES : NO;
396 options->Equil = opt;
401 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
402 colperm_t opt = (colperm_t)col_perm;
405 MFEM_ABORT(
"SuperLUSolver::SetColumnPermutation does not yet support " 410 options->ParSymbFact = YES;
412 options->ColPerm = opt;
417 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
418 rowperm_t opt = (rowperm_t)row_perm;
421 MFEM_ABORT(
"SuperLUSolver::SetRowPermutation does not yet support " 424 options->RowPerm = opt;
429 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
430 IterRefine_t opt = (IterRefine_t)iter_ref;
431 options->IterRefine = opt;
436 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
437 yes_no_t opt = rtp ? YES : NO;
438 options->ReplaceTinyPivot = opt;
443 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
444 options->num_lookaheads = num_lookaheads;
449 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
450 yes_no_t opt = etree ? YES : NO;
451 options->lookahead_etree = opt;
456 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
457 yes_no_t opt = sym ? YES : NO;
458 options->SymPattern = opt;
463 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
464 yes_no_t opt = par ? YES : NO;
465 options->ParSymbFact = opt;
470 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
471 fact_t opt = (fact_t)fact;
478 bool LUStructInitialized = (
APtr_ != NULL);
480 MFEM_VERIFY(
APtr_,
"SuperLUSolver::SetOperator: Not a SuperLURowLocMatrix!");
482 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
488 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 489 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 490 gridinfo3d_t *grid3d = NULL;
503 MFEM_VERIFY(!LUStructInitialized ||
505 "SuperLUSolver::SetOperator: Inconsistent new matrix size!");
509 if (!LUStructInitialized)
521 switch (options->Fact)
524 MFEM_ABORT(
"SuperLUSolver::SetOperator: Previous matrix was never used!");
529 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 530 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 533 if (grid3d->zscp.Iam == 0)
536 &(grid3d->grid2d), LUstruct);
538 &(grid3d->grid2d), LUstruct);
555 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 556 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 559 if (grid3d->zscp.Iam == 0)
568 DeAllocGlu_3d(LUstruct);
579 MFEM_ABORT(
"SuperLUSolver::SetOperator: Unexpected value for " 599 MFEM_ASSERT(
APtr_ != NULL,
600 "SuperLU Error: The operator must be set before" 601 " the system can be solved.");
603 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
610 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 611 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 612 gridinfo3d_t *grid3d = NULL;
628 "Number of columns mismatch in SuperLUSolver::Mult!");
630 "SuperLUSolver does not support multiple solves with different " 631 "numbers of RHS vectors!");
635 MFEM_ASSERT(X[0] && Y[0],
"Missing Vector in SuperLUSolver::Mult!");
644 MFEM_ASSERT(X[0],
"Missing Vector in SuperLUSolver::Mult!");
648 for (
int i = 0; i <
nrhs_; i++)
650 MFEM_ASSERT(X[i],
"Missing Vector in SuperLUSolver::Mult!");
658 if (!(berr = doubleMalloc_dist(
nrhs_)))
660 MFEM_ABORT(
"SuperLUSolver::Mult: Malloc failed for berr!");
665 #if SUPERLU_DIST_MAJOR_VERSION > 7 || \ 666 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2) 669 pdgssvx3d(options, A, ScalePermstruct, B, ldx,
nrhs_,
670 grid3d, LUstruct, SOLVEstruct, berr, &stat, &info);
675 pdgssvx(options, A, ScalePermstruct, B, ldx,
nrhs_,
676 grid, LUstruct, SOLVEstruct, berr, &stat, &info);
691 for (
int i = 0; i <
nrhs_; i++)
693 MFEM_ASSERT(Y[i],
"Missing Vector in SuperLUSolver::Mult!");
703 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
704 options->Trans = TRANS;
708 options->Trans = NOTRANS;
715 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
716 options->Trans = TRANS;
720 options->Trans = NOTRANS;
723 void SuperLUSolver::HandleError(
int info)
const 733 MFEM_ABORT(
"SuperLUSolver: SuperLU options are invalid!");
736 MFEM_ABORT(
"SuperLUSolver: Matrix A (in Ax=b) is invalid!");
739 MFEM_ABORT(
"SuperLUSolver: Vector b dimension (in Ax=b) is " 743 MFEM_ABORT(
"SuperLUSolver: Number of right-hand sides is " 747 MFEM_ABORT(
"SuperLUSolver: Parameter with index " 748 << -info <<
"invalid (1-indexed)!");
752 else if (info <= A->ncol)
754 MFEM_ABORT(
"SuperLUSolver: Found a singular matrix, U(" 755 << info <<
"," << info <<
") is exactly zero!");
757 else if (info > A->ncol)
759 MFEM_ABORT(
"SuperLUSolver: Memory allocation error with " 760 << info - A->ncol <<
" bytes already allocated!");
764 MFEM_ABORT(
"Unknown SuperLU error: info = " << info <<
"!");
771 #endif // MFEM_USE_MPI 772 #endif // MFEM_USE_SUPERLU void SetRowPermutation(superlu::RowPerm row_perm)
void SetFact(superlu::Fact fact)
int GetGridRows(MPI_Comm comm, int npdep)
void ArrayMultTranspose(const Array< const Vector *> &X, Array< Vector *> &Y) const
Action of the transpose operator on a matrix: Y=A^t(X).
void * ScalePermstructPtr_
void SetSize(int s)
Resize the vector to size s.
HYPRE_BigInt GetGlobalNumRows() const
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void HostRead() const
Update the internal hypre_ParCSRMatrix object, A, to be on host.
void SetSymmetricPattern(bool sym)
HYPRE_BigInt GetGlobalNumColumns() const
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void SetOperator(const Operator &op)
Set/update the solver for the given operator.
void * InternalData() const
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
unsigned int sqrti(unsigned int a)
void SetIterativeRefine(superlu::IterRefine iter_ref)
void SetColumnPermutation(superlu::ColPerm col_perm)
void SetNumLookAheads(int num_lookaheads)
void SetPrintStatistics(bool print_stat)
MPI_Comm GetComm() const
MPI communicator.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
A class to initialize the size of a Tensor.
int height
Dimension of the output / number of rows in the matrix.
void SetLookAheadElimTree(bool etree)
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
void ArrayMult(const Array< const Vector *> &X, Array< Vector *> &Y) const
Operator application on a matrix: Y=A(X).
void HypreRead() const
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
void SetReplaceTinyPivot(bool rtp)
int Size() const
Return the logical size of the array.
SuperLURowLocMatrix(MPI_Comm comm, int num_loc_rows, HYPRE_BigInt first_loc_row, HYPRE_BigInt glob_nrows, HYPRE_BigInt glob_ncols, int *I, HYPRE_BigInt *J, double *data)
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
const SuperLURowLocMatrix * APtr_
void SetParSymbFact(bool par)
int GetGridCols(MPI_Comm comm, int npdep, int nr)
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.
SuperLUSolver(MPI_Comm comm, int npdep=1)
void SetEquilibriate(bool equil)