Files
mfem/linalg/superlu.hpp
T

304 lines
11 KiB
C++

// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_SUPERLU
#define MFEM_SUPERLU
#include "../config/config.hpp"
#ifdef MFEM_USE_SUPERLU
#ifdef MFEM_USE_MPI
#include "operator.hpp"
#include "hypre.hpp"
#include <mpi.h>
namespace mfem
{
namespace superlu
{
// Copy selected enumerations from SuperLU (from superlu_enum_consts.h)
#ifdef MFEM_USE_SUPERLU5
typedef enum
{
NOROWPERM,
LargeDiag,
MY_PERMR
} RowPerm;
#else
/// Define the type of row permutation
typedef enum
{
/// No row permutation
NOROWPERM,
/** @brief Duff/Koster algorithm to make the diagonals large compared to the
off-diagonals. Use LargeDiag for SuperLU version 5 and below. */
LargeDiag_MC64,
/** @brief Parallel approximate weight perfect matching to make the diagonals
large compared to the off-diagonals. Option doesn't exist in SuperLU
version 5 and below. */
LargeDiag_HWPM,
/// User defined row permutation
MY_PERMR
} RowPerm;
#endif
/// Define the type of column permutation
typedef enum
{
/// Natural ordering
NATURAL,
/// Minimum degree ordering on structure of $ A^T*A $
MMD_ATA,
/// Minimum degree ordering on structure of $ A^T+A $
MMD_AT_PLUS_A,
/// Approximate minimum degree column ordering
COLAMD,
/// Sequential ordering on structure of $ A^T+A $ using the METIS package
METIS_AT_PLUS_A,
/** @brief Sequential ordering on structure of $ A^T+A $ using the
PARMETIS package */
PARMETIS,
/// Use the Zoltan library from Sandia to define the column ordering
ZOLTAN,
/// User defined column permutation
MY_PERMC
} ColPerm;
/// Define how to do iterative refinement
typedef enum
{
/// No interative refinement
NOREFINE,
/// Iterative refinement accumulating residuals in a float.
SLU_SINGLE=1,
/// Iterative refinement accumulating residuals in a double.
SLU_DOUBLE,
/// Iterative refinement accumulating residuals in a higher precision variable.
SLU_EXTRA
} IterRefine;
/** @brief Define the information that is provided about the matrix
factorization ahead of time. */
typedef enum
{
/// No information is provided, do the full factorization.
DOFACT,
/** @brief Matrix A will be factored assuming the sparsity is the same as a
previous factorization. Column permutations will be reused. */
SamePattern,
/** @brief Matrix A will be factored assuming the sparsity is the same and
the matrix as a previous are similar as a previous factorization. Column
permutations and row permutations will be reused. */
SamePattern_SameRowPerm,
/** @brief The matrix A was provided in fully factored form and no
factorization is needed. */
FACTORED
} Fact;
} // namespace superlu
class SuperLURowLocMatrix : public Operator
{
public:
/** @brief Creates a general parallel matrix from a local CSR matrix on each
processor described by the I, J and data arrays. The local matrix should
be of size (local) nrows by (global) glob_ncols. The new parallel matrix
contains copies of all input arrays (so they can be deleted). */
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);
/** @brief Creates a copy of the parallel matrix hypParMat in SuperLU's
RowLoc format. All data is copied so the original matrix may be
deleted. */
SuperLURowLocMatrix(const Operator &op);
~SuperLURowLocMatrix();
/// Matrix Vector products are not supported for this type of matrix
void Mult(const Vector &x, Vector &y) const
{
MFEM_ABORT("SuperLURowLocMatrix::Mult: Matrix vector products are not "
"supported!");
}
void *InternalData() const { return rowLocPtr_; }
/// Get the MPI communicator for this matrix
MPI_Comm GetComm() const { return comm_; }
/// Get the number of global rows in this matrix
HYPRE_BigInt GetGlobalNumRows() const { return num_global_rows_; }
/// Get the number of global columns in this matrix
HYPRE_BigInt GetGlobalNumColumns() const { return num_global_cols_; }
private:
MPI_Comm comm_;
void *rowLocPtr_;
HYPRE_BigInt num_global_rows_, num_global_cols_;
};
/** The MFEM wrapper around the SuperLU Direct Solver class.
The mfem::SuperLUSolver class uses the SuperLU_DIST library to perform LU
factorization of a parallel sparse matrix. The solver is capable of handling
double precision types. It is currently maintained by Xiaoye Sherry Li at
NERSC, see http://crd-legacy.lbl.gov/~xiaoye/SuperLU/.
*/
class SuperLUSolver : public Solver
{
public:
/** @brief Constructor with MPI_Comm parameter.
@a npdep is the replication factor for the matrix
data and must be a power of 2 and divide evenly
into the number of processors. */
SuperLUSolver(MPI_Comm comm, int npdep = 1);
/** @brief Constructor with SuperLU matrix object.
@a npdep is the replication factor for the matrix
data and must be a power of 2 and divide evenly
into the number of processors. */
SuperLUSolver(SuperLURowLocMatrix &A, int npdep = 1);
/// Default destructor.
~SuperLUSolver();
/** @brief Set the operator/matrix.
@note @a A must be a SuperLURowLocMatrix. */
void SetOperator(const Operator &op);
/** @brief Factor and solve the linear system $ y = Op^{-1} x $
@note Factorization modifies the operator matrix. */
void Mult(const Vector &x, Vector &y) const;
/** @brief Factor and solve the linear systems $ y_i = Op^{-1} x_i $
for all i in the @a X and @a Y arrays.
@note Factorization modifies the operator matrix. */
void ArrayMult(const Array<const Vector *> &X, Array<Vector *> &Y) const;
/** @brief Factor and solve the transposed linear system
$ y = Op^{-T} x $
@note Factorization modifies the operator matrix. */
void MultTranspose(const Vector &x, Vector &y) const;
/** @brief Factor and solve the transposed linear systems
$ y_i = Op^{-T} x_i $ for all i in the @a X and @a Y arrays.
@note Factorization modifies the operator matrix. */
void ArrayMultTranspose(const Array<const Vector *> &X,
Array<Vector *> &Y) const;
/// Specify whether to print the solver statistics (default true)
void SetPrintStatistics(bool print_stat);
/** @brief Specify whether to equibrate the system scaling to make
the rows and columns have unit norms. (default true) */
void SetEquilibriate(bool equil);
/** @brief Specify how to permute the columns of the matrix.
Supported options are:
superlu::NATURAL, superlu::MMD_ATA, superlu::MMD_AT_PLUS_A,
superlu::COLAMD, superlu::METIS_AT_PLUS_A (default),
superlu::PARMETIS, superlu::ZOLTAN, superlu::MY_PERMC */
void SetColumnPermutation(superlu::ColPerm col_perm);
/** @brief Specify how to permute the rows of the matrix.
Supported options are:
superlu::NOROWPERM, superlu::LargeDiag (default), superlu::MY_PERMR for
SuperLU version 5. For later versions the supported options are:
superlu::NOROWPERM, superlu::LargeDiag_MC64 (default),
superlu::LargeDiag_HWPM, superlu::MY_PERMR */
void SetRowPermutation(superlu::RowPerm row_perm);
/** @brief Specify how to handle iterative refinement
Supported options are:
superlu::NOREFINE, superlu::SLU_SINGLE,
superlu::SLU_DOUBLE (default), superlu::SLU_EXTRA */
void SetIterativeRefine(superlu::IterRefine iter_ref);
/** @brief Specify whether to replace tiny diagonals encountered
during pivot with $ \sqrt{\epsilon} \lVert A \rVert $
(default false) */
void SetReplaceTinyPivot(bool rtp);
/// Specify the number of levels in the look-ahead factorization (default 10)
void SetNumLookAheads(int num_lookaheads);
/** @brief Specifies whether to use the elimination tree computed from the
serial symbolic factorization to perform static scheduling
(default false) */
void SetLookAheadElimTree(bool etree);
/** @brief Specify whether the matrix has a symmetric pattern to avoid extra
work (default false) */
void SetSymmetricPattern(bool sym);
/** @brief Specify whether to perform parallel symbolic factorization
(default false)
@note If true SuperLU will use superlu::PARMETIS for the Column
Permutation regardless of the setting */
void SetParSymbFact(bool par);
/** @brief Specify what information has been provided ahead of time about the
factorization of A.
Supported options are:
superlu::DOFACT, superlu::SamePattern, superlu::SamePattern_SameRowPerm,
superlu::FACTORED*/
void SetFact(superlu::Fact fact);
/** @brief Specify whether to offload numerical factorization onto the device
(default true if SuperLU_DIST has been compiled with GPU support) */
void SetDeviceOffload(bool offload);
// Processor grid for SuperLU_DIST.
const int nprow_, npcol_, npdep_;
private:
// Initialize the solver.
void Init(MPI_Comm comm);
// Handle error message from call to SuperLU solver.
void HandleError(int info) const;
protected:
const SuperLURowLocMatrix *APtr_;
mutable Vector sol_;
mutable int nrhs_;
/** The actual types of the following pointers are hidden to avoid exposing
the SuperLU header files to the entire library. Their types are given in
the trailing comments. The reason that this is necessary is that SuperLU
defines these structs differently for use with its real and complex
solvers. If we want to add support for SuperLU's complex solvers one day
we will need to hide these types to avoid name conflicts. */
void *optionsPtr_; // superlu_options_t *
void *ScalePermstructPtr_; // ScalePermsruct_t *
void *LUstructPtr_; // LUstruct_t *
void *SOLVEstructPtr_; // SOLVEstruct_t *
void *gridPtr_; // gridinfo_t * or gridinfo3d_t *
};
} // namespace mfem
#endif // MFEM_USE_MPI
#endif // MFEM_USE_SUPERLU
#endif // MFEM_SUPERLU