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!");
379 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
380 set_default_options_dist(options);
381#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
382 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
385 options->Algo3d = YES;
392 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
393 yes_no_t opt = print_stat ? YES : NO;
394 options->PrintStat = opt;
399 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
400 yes_no_t opt = equil ? YES : NO;
401 options->Equil = opt;
406 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
407 colperm_t opt = (colperm_t)col_perm;
410 MFEM_ABORT(
"SuperLUSolver::SetColumnPermutation does not yet support "
413 else if (opt == PARMETIS)
415 options->ParSymbFact = YES;
417 options->ColPerm = opt;
422 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
423 rowperm_t opt = (rowperm_t)row_perm;
426 MFEM_ABORT(
"SuperLUSolver::SetRowPermutation does not yet support "
429 options->RowPerm = opt;
434 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
435 IterRefine_t opt = (IterRefine_t)iter_ref;
436 options->IterRefine = opt;
441 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
442 yes_no_t opt = rtp ? YES : NO;
443 options->ReplaceTinyPivot = opt;
448 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
449 options->num_lookaheads = num_lookaheads;
454 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
455 yes_no_t opt = etree ? YES : NO;
456 options->lookahead_etree = opt;
461 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
462 yes_no_t opt = sym ? YES : NO;
463 options->SymPattern = opt;
468 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
469 yes_no_t opt = par ? YES : NO;
470 options->ParSymbFact = opt;
475 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
476 fact_t opt = (fact_t)fact;
482 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
483 options->superlu_acc_offload = offload;
489 bool LUStructInitialized = (
APtr_ != NULL);
491 MFEM_VERIFY(
APtr_,
"SuperLUSolver::SetOperator: Not a SuperLURowLocMatrix!");
493 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
499#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
500 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
501 gridinfo3d_t *grid3d = NULL;
514 MFEM_VERIFY(!LUStructInitialized ||
516 "SuperLUSolver::SetOperator: Inconsistent new matrix size!");
520 if (!LUStructInitialized)
527 options->Fact = DOFACT;
532 switch (options->Fact)
535 MFEM_ABORT(
"SuperLUSolver::SetOperator: Previous matrix was never used!");
537 case SamePattern_SameRowPerm:
540#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
541(SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
544 if (grid3d->zscp.Iam == 0)
547 &(grid3d->grid2d), LUstruct);
549 &(grid3d->grid2d), LUstruct);
566#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
567(SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
570 if (grid3d->zscp.Iam == 0)
579 DeAllocGlu_3d(LUstruct);
590 MFEM_ABORT(
"SuperLUSolver::SetOperator: Unexpected value for "
594 if (options->Fact == FACTORED) { options->Fact = DOFACT; }
610 MFEM_ASSERT(
APtr_ != NULL,
611 "SuperLU Error: The operator must be set before"
612 " the system can be solved.");
614 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
621#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
622 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
623 gridinfo3d_t *grid3d = NULL;
639 "Number of columns mismatch in SuperLUSolver::Mult!");
641 "SuperLUSolver does not support multiple solves with different "
642 "numbers of RHS vectors!");
646 MFEM_ASSERT(X[0] && Y[0],
"Missing Vector in SuperLUSolver::Mult!");
655 MFEM_ASSERT(X[0],
"Missing Vector in SuperLUSolver::Mult!");
659 for (
int i = 0; i <
nrhs_; i++)
661 MFEM_ASSERT(X[i],
"Missing Vector in SuperLUSolver::Mult!");
670 if (!(berr = doubleMalloc_dist(
nrhs_)))
672 MFEM_ABORT(
"SuperLUSolver::Mult: Malloc failed for berr!");
677#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
678 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
681 pdgssvx3d(options, A, ScalePermstruct, B, ldx,
nrhs_,
682 grid3d, LUstruct, SOLVEstruct, berr, &stat, &info);
687 pdgssvx(options, A, ScalePermstruct, B, ldx,
nrhs_,
688 grid, LUstruct, SOLVEstruct, berr, &stat, &info);
693 options->Fact = FACTORED;
703 for (
int i = 0; i <
nrhs_; i++)
705 MFEM_ASSERT(Y[i],
"Missing Vector in SuperLUSolver::Mult!");
715 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
716 options->Trans = TRANS;
720 options->Trans = NOTRANS;
727 superlu_dist_options_t *options = (superlu_dist_options_t *)
optionsPtr_;
728 options->Trans = TRANS;
732 options->Trans = NOTRANS;
735void SuperLUSolver::HandleError(
int info)
const
745 MFEM_ABORT(
"SuperLUSolver: SuperLU options are invalid!");
748 MFEM_ABORT(
"SuperLUSolver: Matrix A (in Ax=b) is invalid!");
751 MFEM_ABORT(
"SuperLUSolver: Vector b dimension (in Ax=b) is "
755 MFEM_ABORT(
"SuperLUSolver: Number of right-hand sides is "
759 MFEM_ABORT(
"SuperLUSolver: Parameter with index "
760 << -info <<
"invalid (1-indexed)!");
764 else if (info <= A->ncol)
766 MFEM_ABORT(
"SuperLUSolver: Found a singular matrix, U("
767 << info <<
"," << info <<
") is exactly zero!");
769 else if (info > A->ncol)
771 MFEM_ABORT(
"SuperLUSolver: Memory allocation error with "
772 << info - A->ncol <<
" bytes already allocated!");
776 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 SetDeviceOffload(bool offload)
Specify whether to offload numerical factorization onto the device (default true if SuperLU_DIST has ...
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 (default false)
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 equilibrate 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)