diff --git a/src/solver/sparse_matrix.cc b/src/solver/sparse_matrix.cc index 0e2302a84..50cb10848 100644 --- a/src/solver/sparse_matrix.cc +++ b/src/solver/sparse_matrix.cc @@ -1,69 +1,69 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "communicator.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(DOFManager & dof_manager, const MatrixType & matrix_type, const ID & id) - : id(id), _dof_manager(dof_manager), matrix_type(matrix_type), + : id(id), dof_manager(dof_manager), matrix_type(matrix_type), size_(dof_manager.getSystemSize()), nb_non_zero(0) { AKANTU_DEBUG_IN(); - const auto & comm = _dof_manager.getCommunicator(); + const auto & comm = dof_manager.getCommunicator(); this->nb_proc = comm.getNbProc(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(const SparseMatrix & matrix, const ID & id) - : SparseMatrix(matrix._dof_manager, matrix.matrix_type, id) { + : SparseMatrix(matrix.dof_manager, matrix.matrix_type, id) { nb_non_zero = matrix.nb_non_zero; } /* -------------------------------------------------------------------------- */ SparseMatrix::~SparseMatrix() = default; // /* -------------------------------------------------------------------------- // */ Array<Real> & operator*=(SolverVector & vect, const SparseMatrix & mat) { // Array<Real> tmp(vect.size(), vect.getNbComponent(), 0.); // mat.matVecMul(vect, tmp); // vect.copy(tmp); // return vect; // } /* -------------------------------------------------------------------------- */ void SparseMatrix::add(const SparseMatrix & B, Real alpha) { B.addMeTo(*this, alpha); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/solver/sparse_matrix.hh b/src/solver/sparse_matrix.hh index 4881cf857..d46e6b7ed 100644 --- a/src/solver/sparse_matrix.hh +++ b/src/solver/sparse_matrix.hh @@ -1,158 +1,158 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_SPARSE_MATRIX_HH_ #define AKANTU_SPARSE_MATRIX_HH_ /* -------------------------------------------------------------------------- */ namespace akantu { class DOFManager; class TermsToAssemble; class SparseSolverVector; } // namespace akantu namespace akantu { class SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrix(DOFManager & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix"); SparseMatrix(const SparseMatrix & matrix, const ID & id = "sparse_matrix"); virtual ~SparseMatrix(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// remove the existing profile virtual void clearProfile(); /// set the matrix to 0 virtual void set(Real val) = 0; virtual void zero() { this->set(0); } /// add a non-zero element to the profile virtual Idx add(Idx i, Idx j) = 0; /// assemble a local matrix in the sparse one virtual void add(Idx i, Idx j, Real value) = 0; /// save the profil in a file using the MatrixMarket file format virtual void saveProfile(const std::string & /* filename */) const { AKANTU_TO_IMPLEMENT(); } /// save the matrix in a file using the MatrixMarket file format virtual void saveMatrix(const std::string & /* filename */) const { AKANTU_TO_IMPLEMENT(); }; /// multiply the matrix by a coefficient virtual void mul(Real alpha) = 0; /// add matrices virtual void add(const SparseMatrix & B, Real alpha = 1.); /// Equivalent of *gemv in blas virtual void matVecMul(const SparseSolverVector & x, SparseSolverVector & y, Real alpha = 1., Real beta = 0.) const = 0; /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(Real block_val = 1.) = 0; /// copy the profile of another matrix virtual void copyProfile(const SparseMatrix & other) = 0; /// operator *= SparseMatrix & operator*=(Real alpha) { this->mul(alpha); return *this; } /// Check if all entries are finite. The default implementation throws. virtual bool isFinite() const { AKANTU_TO_IMPLEMENT(); } protected: /// This is the revert of add \f[B += \alpha * *this\f]; virtual void addMeTo(SparseMatrix & B, Real alpha) const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the values at potition i, j virtual inline Real operator()(Idx /*i*/, Idx /*j*/) const { AKANTU_TO_IMPLEMENT(); } /// return the values at potition i, j virtual inline Real & operator()(Idx /*i*/, Idx /*j*/) { AKANTU_TO_IMPLEMENT(); } AKANTU_GET_MACRO_AUTO(NbNonZero, nb_non_zero); Int size() const { return size_; } AKANTU_GET_MACRO_AUTO(MatrixType, matrix_type); virtual Int getRelease() const = 0; virtual Real min() = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: ID id; /// Underlying dof manager - DOFManager & _dof_manager; + DOFManager & dof_manager; /// sparce matrix type MatrixType matrix_type; /// Size of the matrix Int size_; /// number of processors Int nb_proc; /// number of non zero element Int nb_non_zero; }; // Array<Real> & operator*=(Array<Real> & vect, const SparseMatrix & mat); } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_inline_impl.hh" #endif /* AKANTU_SPARSE_MATRIX_HH_ */ diff --git a/src/solver/sparse_matrix_petsc.cc b/src/solver/sparse_matrix_petsc.cc index 60a1ce70b..1fd4b344a 100644 --- a/src/solver/sparse_matrix_petsc.cc +++ b/src/solver/sparse_matrix_petsc.cc @@ -1,284 +1,285 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_petsc.hh" #include "dof_manager_petsc.hh" #include "mpi_communicator_data.hh" #include "solver_vector_petsc.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & matrix_type, const ID & id) - : SparseMatrix(dof_manager, matrix_type, id), dof_manager(dof_manager) { + : SparseMatrix(dof_manager, matrix_type, id) { AKANTU_DEBUG_IN(); auto && mpi_comm = dof_manager.getMPIComm(); MatCreate(mpi_comm, &mat); detail::PETScSetName(mat, id); resize(); MatSetFromOptions(mat); MatSetUp(mat); MatSetOption(mat, MAT_ROW_ORIENTED, PETSC_TRUE); MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE); if (matrix_type == _symmetric) { MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::SparseMatrixPETSc(const SparseMatrixPETSc & matrix, const ID & id) - : SparseMatrix(matrix, id), dof_manager(matrix.dof_manager) { + : SparseMatrix(matrix, id) { MatDuplicate(matrix.mat, MAT_COPY_VALUES, &mat); detail::PETScSetName(mat, id); } /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::~SparseMatrixPETSc() { AKANTU_DEBUG_IN(); if (mat != nullptr) { MatDestroy(&mat); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::resize() { auto local_size = dof_manager.getPureLocalSystemSize(); MatSetSizes(mat, local_size, local_size, size_, size_); - auto & is_ltog_mapping = dof_manager.getISLocalToGlobalMapping(); + auto & is_ltog_mapping = + aka::as_type<DOFManagerPETSc>(dof_manager).getISLocalToGlobalMapping(); MatSetLocalToGlobalMapping(mat, is_ltog_mapping, is_ltog_mapping); } /* -------------------------------------------------------------------------- */ /** * Method to save the nonzero pattern and the values stored at each position * @param filename name of the file in which the information will be stored */ void SparseMatrixPETSc::saveMatrix(const std::string & filename) const { AKANTU_DEBUG_IN(); - auto && mpi_comm = dof_manager.getMPIComm(); + auto && mpi_comm = aka::as_type<DOFManagerPETSc>(dof_manager).getMPIComm(); /// create Petsc viewer PetscViewer viewer; PetscViewerASCIIOpen(mpi_comm, filename.c_str(), &viewer); PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATRIXMARKET); MatView(mat, viewer); PetscViewerPopFormat(viewer); PetscViewerDestroy(&viewer); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /// Equivalent of *gemv in blas void SparseMatrixPETSc::matVecMul(const SparseSolverVector & _x, SparseSolverVector & _y, Real alpha, Real beta) const { const auto & x = aka::as_type<SparseSolverVectorPETSc>(_x); auto & y = aka::as_type<SparseSolverVectorPETSc>(_y); // y = alpha A x + beta y SparseSolverVectorPETSc w(x, this->id + ":tmp"); // w = A x if (release == 0) { VecZeroEntries(w); } else { MatMult(mat, x, w); } if (alpha != 1.) { // w = alpha w VecScale(w, alpha); } // y = w + beta y VecAYPX(y, beta, w); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addMeToImpl(SparseMatrixPETSc & B, Real alpha) const { // std::cout << "addMeTo" << std::endl; // PETSc_call(MatView, B.mat, PETSC_VIEWER_STDOUT_WORLD); MatAXPY(B.mat, alpha, mat, SAME_NONZERO_PATTERN); // PETSc_call(MatView, B.mat, PETSC_VIEWER_STDOUT_WORLD); B.release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addMeTo(SparseMatrix & B, Real alpha) const { if (aka::is_of_type<SparseMatrixPETSc>(B)) { auto & B_petsc = aka::as_type<SparseMatrixPETSc>(B); this->addMeToImpl(B_petsc, alpha); } else { AKANTU_TO_IMPLEMENT(); // this->addMeToTemplated<SparseMatrix>(*this, alpha); } } /* -------------------------------------------------------------------------- */ /** * MatSetValues() generally caches the values. The matrix is ready to * use only after MatAssemblyBegin() and MatAssemblyEnd() have been * called. (http://www.mcs.anl.gov/petsc/) */ void SparseMatrixPETSc::applyModifications() { this->beginAssembly(); this->endAssembly(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::beginAssembly() { MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::endAssembly() { MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY); MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE); this->release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::copyProfile(const SparseMatrix & other) { const auto & A = aka::as_type<SparseMatrixPETSc>(other); MatDestroy(&mat); MatDuplicate(A.mat, MAT_DO_NOT_COPY_VALUES, &mat); detail::PETScSetName(mat, id); this->zero(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::applyBoundary(Real block_val) { AKANTU_DEBUG_IN(); const auto & blocked_dofs = this->dof_manager.getGlobalBlockedDOFsIndexes(); // std::vector<PetscInt> rows; // for (auto && data : enumerate(blocked)) { // if (std::get<1>(data)) { // rows.push_back(std::get<0>(data)); // } // } // applyModifications(); // static int c = 0; // saveMatrix("before_blocked_" + std::to_string(c) + ".mtx"); MatZeroRowsColumnsLocal(mat, blocked_dofs.size(), blocked_dofs.data(), block_val, nullptr, nullptr); // saveMatrix("after_blocked_" + std::to_string(c) + ".mtx"); // ++c; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::mul(Real alpha) { MatScale(mat, alpha); this->release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::zero() { MatZeroEntries(mat); this->release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::clearProfile() { SparseMatrix::clearProfile(); MatResetPreallocation(mat); MatSetOption(mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE); // MatSetOption( MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); // MatSetOption( MAT_NEW_NONZERO_ALLOCATIONS, PETSC_TRUE); // MatSetOption( MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); this->zero(); } /* -------------------------------------------------------------------------- */ Idx SparseMatrixPETSc::add(Idx i, Idx j) { MatSetValue(mat, i, j, 0, ADD_VALUES); return 0; } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::add(Idx i, Idx j, Real val) { MatSetValue(mat, i, j, val, ADD_VALUES); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addLocal(Idx i, Idx j) { MatSetValueLocal(mat, i, j, 0, ADD_VALUES); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addLocal(Idx i, Idx j, Real val) { MatSetValueLocal(mat, i, j, val, ADD_VALUES); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addLocal(const Vector<Int> & rows, const Vector<Int> & cols, const Matrix<Real> & values) { MatSetValuesLocal(mat, rows.size(), rows.data(), cols.size(), cols.data(), values.data(), ADD_VALUES); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::addValues(const Vector<Int> & rows, const Vector<Int> & cols, const Matrix<Real> & values, MatrixType values_type) { if (values_type == _unsymmetric and matrix_type == _symmetric) { MatSetOption(mat, MAT_SYMMETRIC, PETSC_FALSE); MatSetOption(mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_FALSE); } MatSetValues(mat, rows.size(), rows.data(), cols.size(), cols.data(), values.data(), ADD_VALUES); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/solver/sparse_matrix_petsc.hh b/src/solver/sparse_matrix_petsc.hh index 8be6a4901..9d3971baf 100644 --- a/src/solver/sparse_matrix_petsc.hh +++ b/src/solver/sparse_matrix_petsc.hh @@ -1,151 +1,148 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_PETSC_MATRIX_HH_ #define AKANTU_PETSC_MATRIX_HH_ /* -------------------------------------------------------------------------- */ #include "aka_types.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ #include <petscmat.h> /* -------------------------------------------------------------------------- */ namespace akantu { class DOFManagerPETSc; } namespace akantu { class SparseMatrixPETSc : public SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix_petsc"); SparseMatrixPETSc(const SparseMatrixPETSc & matrix, const ID & id = "sparse_matrix_petsc"); ~SparseMatrixPETSc() override; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the matrix to 0 void zero() override; void set(Real /*val*/) override { AKANTU_TO_IMPLEMENT(); } void clearProfile() override; /// add a non-zero element to the profile Idx add(Idx i, Idx j) override; /// assemble a local matrix in the sparse one void add(Idx i, Idx j, Real value) override; void addLocal(Idx i, Idx j); void addLocal(Idx i, Idx j, Real val); void addLocal(const Vector<Int> & rows, const Vector<Int> & cols, const Matrix<Real> & values); /// add a block of values void addValues(const Vector<Int> & rows, const Vector<Int> & cols, const Matrix<Real> & values, MatrixType values_type); /// save the profil in a file using the MatrixMarket file format // void saveProfile(__attribute__((unused)) const std::string &) const // override { // AKANTU_DEBUG_TO_IMPLEMENT(); // } /// save the matrix in a file using the MatrixMarket file format void saveMatrix(const std::string & filename) const override; /// multiply the matrix by a coefficient void mul(Real alpha) override; /// Equivalent of *gemv in blas void matVecMul(const SparseSolverVector & x, SparseSolverVector & y, Real alpha = 1., Real beta = 0.) const override; /// modify the matrix to "remove" the blocked dof void applyBoundary(Real block_val = 1.) override; /// copy the profile of a matrix void copyProfile(const SparseMatrix & other) override; void applyModifications(); void resize(); Real min() override { AKANTU_TO_IMPLEMENT(); } protected: void addMeTo(SparseMatrix & B, Real alpha) const override; /// This is the specific implementation void addMeToImpl(SparseMatrixPETSc & B, Real alpha) const; void beginAssembly(); void endAssembly(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the values at potition i, j inline Real operator()(Idx /*i*/, Idx /*j*/) const override { AKANTU_TO_IMPLEMENT(); } /// return the values at potition i, j inline Real & operator()(Idx /*i*/, Idx /*j*/) override { AKANTU_TO_IMPLEMENT(); } Int getRelease() const override { return release; }; operator Mat &() { return mat; } operator const Mat &() const { return mat; } AKANTU_GET_MACRO(Mat, mat, const Mat &); AKANTU_GET_MACRO_NOT_CONST(Mat, mat, Mat &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - // DOFManagerPETSc that contains the numbering for petsc - DOFManagerPETSc & dof_manager; - /// store the PETSc matrix Mat mat; /// matrix release Int release{0}; }; } // namespace akantu #endif /* AKANTU_PETSC_MATRIX_HH_ */