From b37166fbd7b4c9f2e14cf81cff0db81091f7ffba Mon Sep 17 00:00:00 2001 From: Wenqing Wang <wenqing.wang@ufz.de> Date: Wed, 26 Mar 2014 17:41:59 +0100 Subject: [PATCH] Rectangular PETSc matrix --- MathLib/LinAlg/PETSc/PETScMatrix.cpp | 80 ++++++++++------- MathLib/LinAlg/PETSc/PETScMatrix.h | 97 ++++++++++++--------- Tests/MathLib/TestGlobalMatrixInterface.cpp | 89 +++++++++++++++++-- 3 files changed, 183 insertions(+), 83 deletions(-) diff --git a/MathLib/LinAlg/PETSc/PETScMatrix.cpp b/MathLib/LinAlg/PETSc/PETScMatrix.cpp index aa5d482f8da..14ce090f443 100644 --- a/MathLib/LinAlg/PETSc/PETScMatrix.cpp +++ b/MathLib/LinAlg/PETSc/PETScMatrix.cpp @@ -18,55 +18,55 @@ namespace MathLib { -PETScMatrix::PETScMatrix (const PetscInt size) - :_size(size), _n_loc_rows(PETSC_DECIDE), _n_loc_cols(PETSC_DECIDE) +PETScMatrix::PETScMatrix(const PetscInt dim) + :_nrows(dim), _ncols(dim), _n_loc_rows(PETSC_DECIDE), _n_loc_cols(PETSC_DECIDE) { create(); + config(PETSC_DECIDE, PETSC_DECIDE); } -PETScMatrix::PETScMatrix (const PetscInt size, const PetscInt n_loc_cols, - const bool is_global_size) - :_size(size), _n_loc_rows(PETSC_DECIDE), _n_loc_cols(n_loc_cols) -{ - if(!is_global_size) - { - _size = PETSC_DECIDE; - _n_loc_rows = size; - } - - create(); -} - -PETScMatrix::PETScMatrix (const PetscInt size, const PETScMatrixOption &mat_opt) - :_size(size), _n_loc_rows(PETSC_DECIDE), _n_loc_cols(mat_opt._n_local_cols) +PETScMatrix::PETScMatrix (const PetscInt nrows, const PETScMatrixOption &mat_opt) + :_nrows(nrows), _ncols(nrows), _n_loc_rows(PETSC_DECIDE), + _n_loc_cols(mat_opt._n_local_cols) { if(!mat_opt._is_global_size) { - _size = PETSC_DECIDE; - _n_loc_rows = size; + _nrows = PETSC_DECIDE; + _ncols = PETSC_DECIDE; + _n_loc_rows = nrows; + + // Make the matrix be square. + MPI_Allreduce(&_n_loc_rows, &_nrows, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD); + _ncols = _nrows; } create(); - config(mat_opt); + config(mat_opt._d_nz, mat_opt._o_nz); } -void PETScMatrix::create() +PETScMatrix::PETScMatrix(const PetscInt nrows_global, const PetscInt ncols_global) + :_nrows(nrows_global), _ncols(ncols_global), _n_loc_rows(PETSC_DECIDE), _n_loc_cols(PETSC_DECIDE) { - MatCreate(PETSC_COMM_WORLD, &_A); - MatSetSizes(_A, _n_loc_rows, _n_loc_cols, _size, _size); - - MatSetFromOptions(_A); + create(); + config(PETSC_DECIDE, PETSC_DECIDE); } -void PETScMatrix::config(const PETScMatrixOption &mat_opt) +PETScMatrix::PETScMatrix (const PetscInt nrows, const PetscInt ncols, const PETScMatrixOption &mat_opt) + :_nrows(nrows), _ncols(ncols), _n_loc_rows(PETSC_DECIDE), + _n_loc_cols(mat_opt._n_local_cols) { - // for a dense matrix: MatSeqAIJSetPreallocation(_A, d_nz, PETSC_NULL); - MatMPIAIJSetPreallocation(_A, mat_opt._d_nz, PETSC_NULL, mat_opt._o_nz, PETSC_NULL); + if(!mat_opt._is_global_size) + { + _nrows = PETSC_DECIDE; + _ncols = PETSC_DECIDE; + _n_loc_rows = nrows; + _n_loc_cols = ncols; + } - MatGetOwnershipRange(_A, &_start_rank, &_end_rank); - MatGetSize(_A, &_size, PETSC_NULL); - MatGetLocalSize(_A, &_n_loc_rows, &_n_loc_cols); + create(); + + config(mat_opt._d_nz, mat_opt._o_nz); } void PETScMatrix::setRowsColumnsZero(std::vector<PetscInt> const& row_pos) @@ -101,6 +101,24 @@ void PETScMatrix::viewer(const std::string &file_name, const PetscViewerFormat v } +void PETScMatrix::create() +{ + MatCreate(PETSC_COMM_WORLD, &_A); + MatSetSizes(_A, _n_loc_rows, _n_loc_cols, _nrows, _ncols); + + MatSetFromOptions(_A); +} + +void PETScMatrix::config(const PetscInt d_nz, const PetscInt o_nz) +{ + // for a dense matrix: MatSeqAIJSetPreallocation(_A, d_nz, PETSC_NULL); + MatMPIAIJSetPreallocation(_A, d_nz, PETSC_NULL, o_nz, PETSC_NULL); + + MatGetOwnershipRange(_A, &_start_rank, &_end_rank); + MatGetSize(_A, &_nrows, &_ncols); + MatGetLocalSize(_A, &_n_loc_rows, &_n_loc_cols); +} + bool finalizeMatrixAssembly(PETScMatrix &mat, const MatAssemblyType asm_type) { mat.finalizeAssembly(asm_type); diff --git a/MathLib/LinAlg/PETSc/PETScMatrix.h b/MathLib/LinAlg/PETSc/PETScMatrix.h index 40eb50c94e5..83bf3a91336 100644 --- a/MathLib/LinAlg/PETSc/PETScMatrix.h +++ b/MathLib/LinAlg/PETSc/PETScMatrix.h @@ -27,53 +27,48 @@ namespace MathLib { /*! - \brief Wrapper class for PETSc matrix routines for a square matrix for - the system of linear equations. + \brief Wrapper class for PETSc matrix routines for matrix. */ class PETScMatrix { public: /*! - \brief Constructor for the matrix partitioning with default options: - The size of the glabal size, the numbers of local rows - and columns have the value of PETSC_DECIDE. - \param size The dimension of the matrix. + \brief Constructor for a square matrix partitioning with default options: + The numbers of local rows and columns have the value of PETSC_DECIDE. + \param dim The dimension of the matrix. */ - explicit PETScMatrix(const PetscInt size); + explicit PETScMatrix(const PetscInt dim); /*! - \brief Constructor for the user determined matrix partitioning - with two options. - \param size The number of rows of the matrix or the local matrix. - \param n_loc_cols Number of the columns of the rank. - If it is -1, it is PETSC_DECIDE. - \param is_global_size The flag of the type of vec_size, - i.e. whether it is a global size or local size. - The default is true. + \brief Constructor for a square matrix partitioning with more options + \param nrows The number of rows of the matrix or the local matrix. + \param mat_op The configuration information for creating a matrix. */ - PETScMatrix(const PetscInt size, const PetscInt n_loc_cols, - const bool is_global_size); + PETScMatrix(const PetscInt nrows, const PETScMatrixOption &mat_op = PETScMatrixOption() ); /*! - \brief Constructor for the user determined partitioning with more options - \param size The number of rows of the matrix or the local matrix. + \brief Constructor for a rectangular matrix partitioning with default options: + The numbers of local rows and columns have the value of PETSC_DECIDE. + \param nrows_global The number of global rows. + \param ncols_global The number of global columns. + */ + PETScMatrix(const PetscInt nrows_global, const PetscInt ncols_global); + + /*! + \brief Constructor for a rectangular matrix partitioning with more options + \param nrows The number of global or local rows. + \param ncols The number of global or local columns. \param mat_op The configuration information for creating a matrix. */ - PETScMatrix(const PetscInt size, const PETScMatrixOption &mat_op = PETScMatrixOption() ); + PETScMatrix(const PetscInt nrows, const PetscInt ncols, + const PETScMatrixOption &mat_op = PETScMatrixOption() ); + ~PETScMatrix() { MatDestroy(&_A); } - /*! - \brief Config memory allocation and set the related member data. - Only called after an intance is created with the constructor - wthout PETScMatrixOption argument. - \param mat_op The configuration information for creating a matrix. - */ - void config(const PETScMatrixOption &mat_op); - /*! \brief Perform MPI collection of assembled entries in buffer \param asm_type Assmebly type, either MAT_FLUSH_ASSEMBLY @@ -88,26 +83,15 @@ class PETScMatrix /// Get the number of rows. PetscInt getNRows() const { - return _size; + return _nrows; } /// Get the number of columns. PetscInt getNCols() const { - return _size; - } - - /// Get the start global index of the rows of the same rank. - PetscInt getRangeBegin() const - { - return _start_rank; + return _ncols; } - /// Get the end global index of the rows in the same rank. - PetscInt getRangeEnd() const - { - return _end_rank; - } /// Get the number of local rows. PetscInt getNLocalRows() const @@ -121,6 +105,18 @@ class PETScMatrix return _n_loc_cols; } + /// Get the start global index of the rows of the same rank. + PetscInt getRangeBegin() const + { + return _start_rank; + } + + /// Get the end global index of the rows in the same rank. + PetscInt getRangeEnd() const + { + return _end_rank; + } + /// Get matrix reference. PETSc_Mat &getRawMatrix() { @@ -215,21 +211,36 @@ class PETScMatrix /// PETSc matrix PETSc_Mat _A; - /// Dimension of matrix - PetscInt _size; + /// Number of the global rows + PetscInt _nrows; + + /// Number of the global columns + PetscInt _ncols; + /// Number of the local rows PetscInt _n_loc_rows; + /// Number of the local columns PetscInt _n_loc_cols; /// Starting index in a rank PetscInt _start_rank; + /// Ending index in a rank PetscInt _end_rank; /// Create the matrix void create(); + /*! + \brief Config memory allocation and set the related member data. + \param Number of nonzeros per row in the diagonal portion of local submatrix + (same value is used for all local rows), + \param Number of nonzeros per row in the off-diagonal portion of local submatrix + (same value is used for all local rows) + */ + void config(const PetscInt d_nz, const PetscInt o_nz); + friend bool finalizeMatrixAssembly(PETScMatrix &mat, const MatAssemblyType asm_type); }; diff --git a/Tests/MathLib/TestGlobalMatrixInterface.cpp b/Tests/MathLib/TestGlobalMatrixInterface.cpp index bae80573d6d..48d789731cf 100644 --- a/Tests/MathLib/TestGlobalMatrixInterface.cpp +++ b/Tests/MathLib/TestGlobalMatrixInterface.cpp @@ -61,13 +61,17 @@ void checkGlobalMatrixInterfaceMPI(T_MATRIX &m, T_VECTOR &v) MPI_Comm_rank(PETSC_COMM_WORLD, &mrank); ASSERT_EQ(3u, msize); - ASSERT_EQ(6u, m.getNRows()); ASSERT_EQ(m.getRangeEnd()-m.getRangeBegin(), m.getNLocalRows()); + int gathered_rows; + int local_rows = m.getNLocalRows(); + MPI_Allreduce(&local_rows, &gathered_rows, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD); + ASSERT_EQ(m.getNRows(), gathered_rows); + int gathered_cols; int local_cols = m.getNLocalColumns(); MPI_Allreduce(&local_cols, &gathered_cols, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD); - ASSERT_EQ(6u, gathered_cols); + ASSERT_EQ(m.getNCols(), gathered_cols); // Add entries MathLib::DenseMatrix<double> loc_m(2, 2); @@ -106,6 +110,61 @@ void checkGlobalMatrixInterfaceMPI(T_MATRIX &m, T_VECTOR &v) ASSERT_EQ(sqrt((2*3*3 + 8*8 + 3*7*7)), y.getNorm()); } + +// Rectanglular matrix +template <class T_MATRIX, class T_VECTOR> +void checkGlobalRectangularMatrixInterfaceMPI(T_MATRIX &m, T_VECTOR &v) +{ + int mrank; + MPI_Comm_rank(PETSC_COMM_WORLD, &mrank); + + ASSERT_EQ(m.getRangeEnd()-m.getRangeBegin(), m.getNLocalRows()); + + int gathered_rows; + int local_rows = m.getNLocalRows(); + MPI_Allreduce(&local_rows, &gathered_rows, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD); + ASSERT_EQ(m.getNRows(), gathered_rows); + + int gathered_cols; + int local_cols = m.getNLocalColumns(); + MPI_Allreduce(&local_cols, &gathered_cols, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD); + ASSERT_EQ(m.getNCols(), gathered_cols); + + printf("m.getNRows()%d m.getNRows() %d %d", m.getNRows(), m.getNCols(), v.size() ); + + // Add entries + MathLib::DenseMatrix<double> loc_m(2, 3); + loc_m(0, 0) = 1.; + loc_m(0, 1) = 2.; + loc_m(0, 1) = 3.; + loc_m(1, 0) = 1.; + loc_m(1, 1) = 2.; + loc_m(1, 1) = 3.; + + std::vector<int> row_pos(2); + std::vector<int> col_pos(3); + row_pos[0] = 2 * mrank; + row_pos[1] = 2 * mrank + 1; + col_pos[0] = 3 * mrank; + col_pos[1] = 3 * mrank + 1; + col_pos[2] = 3 * mrank + 2; + + m.add(row_pos, col_pos, loc_m); + + MathLib::finalizeMatrixAssembly(m); + + /* + Cannot perform the following multiplication due to PETSc bug. + // Multiply by a vector + v = 1.; + const bool deep_copy = false; + T_VECTOR y(v, deep_copy); + m.multi(v, y); + + ASSERT_EQ(sqrt(24.), y.getNorm()); + */ +} + #endif // end of: ifdef USE_PETSC // or MPI } // end namespace @@ -152,20 +211,32 @@ TEST(Math, CheckInterface_PETScMatrix_Global_Size) checkGlobalMatrixInterfaceMPI(A, x); } -TEST(Math, CheckInterface_PETScMatrix_Global_local_late_config) +// Test rectangular matrix +TEST(Math, CheckInterface_PETSc_Rectangular_Matrix_Local_Size) { MathLib::PETScMatrixOption opt; - opt._d_nz = 2; + opt._d_nz = 3; opt._o_nz = 0; opt._is_global_size = false; - opt._n_local_cols = 2; - MathLib::PETScMatrix A(2, 2, false); + opt._n_local_cols = -1; + MathLib::PETScMatrix A(2, 3, opt); const bool is_gloabal_size = false; - MathLib::PETScVector x(2, is_gloabal_size); + MathLib::PETScVector x(3, is_gloabal_size); - A.config(opt); - checkGlobalMatrixInterfaceMPI(A, x); + checkGlobalRectangularMatrixInterfaceMPI(A, x); +} + +TEST(Math, CheckInterface_PETSc_Rectangular_Matrix_Global_Size) +{ + MathLib::PETScMatrixOption opt; + opt._d_nz = 3; + opt._o_nz = 0; + MathLib::PETScMatrix A(6, 9, opt); + + MathLib::PETScVector x(9); + + checkGlobalRectangularMatrixInterfaceMPI(A, x); } #endif // end of: ifdef USE_PETSC // or MPI -- GitLab