-
Notifications
You must be signed in to change notification settings - Fork 18
initial lumped mass matrix implementation #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,20 @@ GalerkinProjectionSolver::GalerkinProjectionSolver( | |
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| ierr = KSPSetOperators(ksp_, A, A); | ||
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| if (mass_integrator.IsDiagonal()) { | ||
| // Jacobi preconditioning applies inv(diag(A)), which for a diagonal | ||
| // matrix is exactly inv(A). Pairing it with KSPPREONLY therefore gives | ||
| // the exact solution in a single application — no Krylov iterations, no | ||
| // factorization, no convergence tolerance in play. Command line options | ||
| // can still override via KSPSetFromOptions below. | ||
| ierr = KSPSetType(ksp_, KSPPREONLY); | ||
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| PC pc = nullptr; | ||
| ierr = KSPGetPC(ksp_, &pc); | ||
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| ierr = PCSetType(pc, PCJACOBI); | ||
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| } | ||
|
Comment on lines
+63
to
+70
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please replace the |
||
| ierr = KSPSetFromOptions(ksp_); | ||
| CHKERRABORT(PETSC_COMM_WORLD, ierr); | ||
| ierr = KSPSetUp(ksp_); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add a new header file just for this enum class? I am not sure which existing header will be the best to move it to though.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably not needed. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #ifndef PCMS_TRANSFER_MASS_MATRIX_TYPE_HPP | ||
| #define PCMS_TRANSFER_MASS_MATRIX_TYPE_HPP | ||
|
|
||
| namespace pcms | ||
| { | ||
|
|
||
| // Mass-matrix formulation used by Galerkin projections. | ||
| enum class MassMatrixType | ||
| { | ||
| Consistent, // full Galerkin mass matrix | ||
| Lumped, // row-sum lumped diagonal mass matrix | ||
| }; | ||
|
|
||
| } // namespace pcms | ||
|
|
||
| #endif // PCMS_TRANSFER_MASS_MATRIX_TYPE_HPP |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,11 +44,14 @@ void FillP0MassCoo( | |
| } | ||
|
|
||
| // Fills the 3x3-block COO sparsity pattern of a P1 (linear) mass matrix: each | ||
| // element contributes a dense block coupling its three vertex DOFs. | ||
| // element contributes a dense block coupling its three vertex DOFs. When | ||
| // lumped, every block entry is mapped onto the row's diagonal instead; PETSc's | ||
| // COO assembly sums repeated indices, so the unmodified element values | ||
| // accumulate into the row-sum lumped diagonal. | ||
| void FillP1MassCooPattern( | ||
| int nelems, const Omega_h::LOs& faces2nodes, | ||
| const Kokkos::View<const LO*, DeviceMemorySpace>& global_to_local, | ||
| const Kokkos::View<PetscInt*, DeviceMemorySpace>& coo_rows, | ||
| bool lumped, const Kokkos::View<PetscInt*, DeviceMemorySpace>& coo_rows, | ||
| const Kokkos::View<PetscInt*, DeviceMemorySpace>& coo_cols) | ||
| { | ||
| Kokkos::parallel_for( | ||
|
|
@@ -57,25 +60,28 @@ void FillP1MassCooPattern( | |
| for (int i = 0; i < 3; ++i) { | ||
| for (int j = 0; j < 3; ++j) { | ||
| const int idx = e * 9 + i * 3 + j; | ||
| coo_rows(idx) = static_cast<PetscInt>(global_to_local(verts[i])); | ||
| coo_cols(idx) = static_cast<PetscInt>(global_to_local(verts[j])); | ||
| const auto row = static_cast<PetscInt>(global_to_local(verts[i])); | ||
| coo_rows(idx) = row; | ||
| coo_cols(idx) = | ||
| lumped ? row : static_cast<PetscInt>(global_to_local(verts[j])); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| OmegaHMassIntegrator::OmegaHMassIntegrator(const FunctionSpace& target_space) | ||
| OmegaHMassIntegrator::OmegaHMassIntegrator(const FunctionSpace& target_space, | ||
| MassMatrixType mass_type) | ||
| : OmegaHMassIntegrator(std::dynamic_pointer_cast<const OmegaHLagrangeLayout>( | ||
| target_space.GetLayout()), | ||
| target_space.GetCoordinateSystem()) | ||
| target_space.GetCoordinateSystem(), mass_type) | ||
| { | ||
| } | ||
|
|
||
| OmegaHMassIntegrator::OmegaHMassIntegrator( | ||
| std::shared_ptr<const OmegaHLagrangeLayout> target_layout, | ||
| CoordinateSystem coordinate_system) | ||
| CoordinateSystem coordinate_system, MassMatrixType mass_type) | ||
| { | ||
| detail::CheckOmegaHScalarLagrangeLayout(coordinate_system, target_layout, | ||
| "OmegaHMassIntegrator", "target"); | ||
|
|
@@ -85,6 +91,8 @@ OmegaHMassIntegrator::OmegaHMassIntegrator( | |
| const PetscInt num_dofs = | ||
| static_cast<PetscInt>(target_layout->GetNumOwnedDofHolder()); | ||
| const int nelems = mesh.nelems(); | ||
| diagonal_ = | ||
| target_layout->GetOrder() == 0 || mass_type == MassMatrixType::Lumped; | ||
|
|
||
| if (target_layout->GetOrder() == 0) { | ||
| // P0 target: piecewise-constant basis functions have disjoint support, so | ||
|
|
@@ -132,8 +140,8 @@ OmegaHMassIntegrator::OmegaHMassIntegrator( | |
| const PetscInt nnz = static_cast<PetscInt>(nelems) * 9; | ||
| Kokkos::View<PetscInt*, DeviceMemorySpace> coo_rows("mass_coo_rows", nnz); | ||
| Kokkos::View<PetscInt*, DeviceMemorySpace> coo_cols("mass_coo_cols", nnz); | ||
| FillP1MassCooPattern(nelems, faces2nodes, global_to_local, coo_rows, | ||
| coo_cols); | ||
| FillP1MassCooPattern(nelems, faces2nodes, global_to_local, | ||
| mass_type == MassMatrixType::Lumped, coo_rows, coo_cols); | ||
|
Comment on lines
140
to
+144
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be fine for now. |
||
|
|
||
| // Create sparse matrix, preallocate with COO pattern, then bulk-set values. | ||
| // elm_mass_dev is in the same element-major order as coo_rows/coo_cols, so | ||
|
|
@@ -164,10 +172,15 @@ Mat OmegaHMassIntegrator::GetMatrix() const noexcept | |
| return mat_; | ||
| } | ||
|
|
||
| bool OmegaHMassIntegrator::IsDiagonal() const noexcept | ||
| { | ||
| return diagonal_; | ||
| } | ||
|
|
||
| std::unique_ptr<BilinearFormIntegrator> BuildOmegaHMassIntegrator( | ||
| const FunctionSpace& target_space) | ||
| const FunctionSpace& target_space, MassMatrixType mass_type) | ||
| { | ||
| return std::make_unique<OmegaHMassIntegrator>(target_space); | ||
| return std::make_unique<OmegaHMassIntegrator>(target_space, mass_type); | ||
| } | ||
|
|
||
| } // namespace pcms | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this related to this PR or just an older bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an old bug that the header was missing.