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 =
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;
338void 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 "
408 else if (opt == PARMETIS)
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)
516 options->Fact = DOFACT;
521 switch (options->Fact)
524 MFEM_ABORT(
"SuperLUSolver::SetOperator: Previous matrix was never used!");
526 case SamePattern_SameRowPerm:
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 "
583 if (options->Fact == FACTORED) { options->Fact = DOFACT; }
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!");
659 if (!(berr = doubleMalloc_dist(
nrhs_)))
661 MFEM_ABORT(
"SuperLUSolver::Mult: Malloc failed for berr!");
666#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
667 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
670 pdgssvx3d(options, A, ScalePermstruct, B, ldx,
nrhs_,
671 grid3d, LUstruct, SOLVEstruct, berr, &stat, &info);
676 pdgssvx(options, A, ScalePermstruct, B, ldx,
nrhs_,
677 grid, LUstruct, SOLVEstruct, berr, &stat, &info);
682 options->Fact = FACTORED;
692 for (
int i = 0; i <
nrhs_; i++)
694 MFEM_ASSERT(Y[i],
"Missing Vector in SuperLUSolver::Mult!");
704 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
705 options->Trans = TRANS;
709 options->Trans = NOTRANS;
716 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
717 options->Trans = TRANS;
721 options->Trans = NOTRANS;
724void SuperLUSolver::HandleError(
int info)
const
734 MFEM_ABORT(
"SuperLUSolver: SuperLU options are invalid!");
737 MFEM_ABORT(
"SuperLUSolver: Matrix A (in Ax=b) is invalid!");
740 MFEM_ABORT(
"SuperLUSolver: Vector b dimension (in Ax=b) is "
744 MFEM_ABORT(
"SuperLUSolver: Number of right-hand sides is "
748 MFEM_ABORT(
"SuperLUSolver: Parameter with index "
749 << -info <<
"invalid (1-indexed)!");
753 else if (info <= A->ncol)
755 MFEM_ABORT(
"SuperLUSolver: Found a singular matrix, U("
756 << info <<
"," << info <<
") is exactly zero!");
758 else if (info > A->ncol)
760 MFEM_ABORT(
"SuperLUSolver: Memory allocation error with "
761 << info - A->ncol <<
" bytes already allocated!");
765 MFEM_ABORT(
"Unknown SuperLU error: info = " << info <<
"!");
int Size() const
Return the logical size of the array.
Wrapper for hypre's ParCSR matrix class.
void HypreRead() const
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
void HostRead() const
Update the internal hypre_ParCSRMatrix object, A, to be on host.
MPI_Comm GetComm() const
MPI communicator.
A class to initialize the size of a Tensor.
int width
Dimension of the input / number of columns in the matrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
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)
Creates a general parallel matrix from a local CSR matrix on each processor described by the I,...
void * InternalData() const
HYPRE_BigInt GetGlobalNumColumns() const
Get the number of global columns in this matrix.
HYPRE_BigInt GetGlobalNumRows() const
Get the number of global rows in this matrix.
SuperLUSolver(MPI_Comm comm, int npdep=1)
Constructor with MPI_Comm parameter.
void ArrayMultTranspose(const Array< const Vector * > &X, Array< Vector * > &Y) const
Factor and solve the transposed linear systems for all i in the X and Y arrays.
void SetColumnPermutation(superlu::ColPerm col_perm)
Specify how to permute the columns of the matrix.
void SetRowPermutation(superlu::RowPerm row_perm)
Specify how to permute the rows of the matrix.
void SetParSymbFact(bool par)
Specify whether to perform parallel symbolic factorization.
void * ScalePermstructPtr_
~SuperLUSolver()
Default destructor.
const SuperLURowLocMatrix * APtr_
void SetReplaceTinyPivot(bool rtp)
Specify whether to replace tiny diagonals encountered during pivot with (default false)
void SetNumLookAheads(int num_lookaheads)
Specify the number of levels in the look-ahead factorization (default 10)
void MultTranspose(const Vector &x, Vector &y) const
Factor and solve the transposed linear system .
void SetFact(superlu::Fact fact)
Specify what information has been provided ahead of time about the factorization of A.
void ArrayMult(const Array< const Vector * > &X, Array< Vector * > &Y) const
Factor and solve the linear systems for all i in the X and Y arrays.
void SetEquilibriate(bool equil)
Specify whether to equibrate the system scaling to make the rows and columns have unit norms....
void Mult(const Vector &x, Vector &y) const
Factor and solve the linear system .
void SetLookAheadElimTree(bool etree)
Specifies whether to use the elimination tree computed from the serial symbolic factorization to perf...
void SetSymmetricPattern(bool sym)
Specify whether the matrix has a symmetric pattern to avoid extra work (default false)
void SetOperator(const Operator &op)
Set the operator/matrix.
void SetIterativeRefine(superlu::IterRefine iter_ref)
Specify how to handle iterative refinement.
void SetPrintStatistics(bool print_stat)
Specify whether to print the solver statistics (default true)
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
void SyncMemory(const Vector &v) const
Update the memory location of the vector to match v.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
ColPerm
Define the type of column permutation.
IterRefine
Define how to do iterative refinement.
Fact
Define the information that is provided about the matrix factorization ahead of time.
unsigned int sqrti(unsigned int a)
int GetGridCols(MPI_Comm comm, int npdep, int nr)
int GetGridRows(MPI_Comm comm, int npdep)