Skip to content

Add a uniform coarsening algorithm - #2016

Open
pratikvn wants to merge 14 commits into
developfrom
unif-coarsening
Open

Add a uniform coarsening algorithm#2016
pratikvn wants to merge 14 commits into
developfrom
unif-coarsening

Conversation

@pratikvn

@pratikvn pratikvn commented May 7, 2026

Copy link
Copy Markdown
Member

This PR adds a uniform coarsening algorithm, an improved version of #1526. The idea is the same as in there, but now there is an option to enforce connectedness that ensures that the graphs in the coarser levels remain connected and there are no disjoint vertices.

While still algebraic, this coarsening strategy is cheaper to generate than PGM, and might be beneficial for matrices with a uniform sparsity pattern.

@pratikvn
pratikvn requested review from MarcelKoch and yhmtsai May 7, 2026 07:20
@pratikvn pratikvn self-assigned this May 7, 2026
@pratikvn pratikvn added is:new-feature A request or implementation of a feature that does not exist yet. 1:ST:ready-for-review This PR is ready for review labels May 7, 2026
@ginkgo-bot ginkgo-bot added reg:build This is related to the build system. reg:testing This is related to testing. mod:core This is related to the core module. mod:cuda This is related to the CUDA module. mod:reference This is related to the reference module. mod:hip This is related to the HIP module. type:multigrid This is related to multigrid labels May 7, 2026
Comment thread core/config/registry.cpp
Comment thread core/multigrid/uniform_coarsening_kernels.hpp
Comment thread core/test/multigrid/uniform_coarsening.cpp Outdated
Comment thread core/test/multigrid/uniform_coarsening.cpp
Comment thread core/test/multigrid/uniform_coarsening.cpp Outdated
Comment thread reference/multigrid/uniform_coarsening_kernels.cpp
Comment thread core/multigrid/uniform_coarsening.cpp
Comment thread core/multigrid/uniform_coarsening.cpp
Comment thread core/multigrid/uniform_coarsening.cpp Outdated
Comment thread core/multigrid/uniform_coarsening.cpp
@pratikvn
pratikvn requested a review from yhmtsai May 18, 2026 09:04

@yhmtsai yhmtsai left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason to keep prolong/restrict as CSR not using SparsityCSR and RowGatherer?

Comment on lines +165 to +168
if (c > 0) A_data.nonzeros.emplace_back(i, i - 1, -1);
if (c < N - 1) A_data.nonzeros.emplace_back(i, i + 1, -1);
if (r > 0) A_data.nonzeros.emplace_back(i, i - N, -1);
if (r < N - 1) A_data.nonzeros.emplace_back(i, i + N, -1);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (c > 0) A_data.nonzeros.emplace_back(i, i - 1, -1);
if (c < N - 1) A_data.nonzeros.emplace_back(i, i + 1, -1);
if (r > 0) A_data.nonzeros.emplace_back(i, i - N, -1);
if (r < N - 1) A_data.nonzeros.emplace_back(i, i + N, -1);
if (c > 0) {A_data.nonzeros.emplace_back(i, i - 1, -1);}
if (c < N - 1) {A_data.nonzeros.emplace_back(i, i + 1, -1);}
if (r > 0) {A_data.nonzeros.emplace_back(i, i - N, -1);}
if (r < N - 1) {A_data.nonzeros.emplace_back(i, i + N, -1);}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can reorder it a bit such that it is already sorted

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still miss {}

Comment on lines +42 to +44
* UniformCoarsening is a simple coarse grid generation algorithm. It
* selects the coarse matrix from the fine matrix by constant jumps that can be
* specified by the user.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds a geometric like?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the wording now. Its not really geometric, but its not algebraic either. So, I just say index-based ordering now.

Comment on lines +102 to +103
* When set to `true` (the default), every fine row is mapped to
* its nearest coarse row (aggregation-style), so that the Galerkin

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add more detail about the nearest coarse row? It is assigned to the floor(id/skip_coarse), right?

Comment on lines +44 to +45
using real_type = gko::remove_complex<value_type>;
UniformCoarsening()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using real_type = gko::remove_complex<value_type>;
UniformCoarsening()
using real_type = gko::remove_complex<value_type>;
UniformCoarsening()

Comment on lines +102 to +107
SCOPED_TRACE("Using coarse skip:" + std::to_string(coarse_skip));
gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
ref, coarse_skip, &c_rows);
gko::kernels::GKO_DEVICE_NAMESPACE::uniform_coarsening::
fill_incremental_indices(exec, coarse_skip, &d_c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, d_c_rows);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SCOPED_TRACE("Using coarse skip:" + std::to_string(coarse_skip));
gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
ref, coarse_skip, &c_rows);
gko::kernels::GKO_DEVICE_NAMESPACE::uniform_coarsening::
fill_incremental_indices(exec, coarse_skip, &d_c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, d_c_rows);
SCOPED_TRACE("Using coarse skip:" + std::to_string(coarse_skip));
c_rows.fill(-gko::one<index_type>());
d_c_rows.fill(-gko::one<index_type>());
gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
ref, coarse_skip, &c_rows);
gko::kernels::GKO_DEVICE_NAMESPACE::uniform_coarsening::
fill_incremental_indices(exec, coarse_skip, &d_c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, d_c_rows);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it updates the value in each loop

Comment on lines +435 to +436
using VT = value_type;
UniformCoarseningAgg()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using VT = value_type;
UniformCoarseningAgg()
using VT = value_type;
UniformCoarseningAgg()

Comment on lines +40 to +42
using SparsityCsr = gko::matrix::SparsityCsr<value_type, index_type>;
using MgLevel = gko::multigrid::UniformCoarsening<value_type, index_type>;
using RowGatherer = gko::matrix::RowGatherer<index_type>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using SparsityCsr = gko::matrix::SparsityCsr<value_type, index_type>;
using MgLevel = gko::multigrid::UniformCoarsening<value_type, index_type>;
using RowGatherer = gko::matrix::RowGatherer<index_type>;
using MgLevel = gko::multigrid::UniformCoarsening<value_type, index_type>;

Comment on lines +257 to +262
auto c_rows = gko::array<index_type>(this->exec, 10);
c_rows.fill(-gko::one<index_type>());

gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
this->exec, 2, &c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, c2_rows);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto c_rows = gko::array<index_type>(this->exec, 10);
c_rows.fill(-gko::one<index_type>());
gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
this->exec, 2, &c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, c2_rows);
auto c_rows = gko::array<index_type>(this->exec, 10);
c_rows.fill(-gko::one<index_type>());
gko::kernels::reference::uniform_coarsening::fill_incremental_indices(
this->exec, 2, &c_rows);
GKO_ASSERT_ARRAY_EQ(c_rows, c2_rows);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is more to keep the consistent as the following.

}


} // namespace

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Suggested change
} // namespace

Comment on lines +118 to +119
auto uc_factory =
uc::build().with_coarse_skip(2).with_aggregation(false).on(this->exec);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need another test for the diag matrix size is not divisible by coarse_skip like coarse_skip = 3

yhmtsai
yhmtsai previously requested changes Jun 8, 2026
Comment on lines +165 to +168
if (c > 0) A_data.nonzeros.emplace_back(i, i - 1, -1);
if (c < N - 1) A_data.nonzeros.emplace_back(i, i + 1, -1);
if (r > 0) A_data.nonzeros.emplace_back(i, i - N, -1);
if (r < N - 1) A_data.nonzeros.emplace_back(i, i + N, -1);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still miss {}

array<IndexType>* coarse_rows)
{
const size_type num_elems = coarse_rows->get_size();
const size_type num_iters = (num_elems + coarse_skip - 1) / coarse_skip;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use ceildiv



/**
* UniformCoarsening is a simple algebraic coarse grid generation algorithm.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* UniformCoarsening is a simple algebraic coarse grid generation algorithm.
* UniformCoarsening is a simple geometric coarse grid generation algorithm.

To me it is more like geometric?

@yhmtsai

yhmtsai commented Jul 20, 2026

Copy link
Copy Markdown
Member

@pratikvn after rebase, you do not need EnableLinOp anymore, but you will need to change it to LinOp and corresponding constructor

@ginkgo-bot

Copy link
Copy Markdown
Member

Error: The following files need to be formatted:

include/ginkgo/core/multigrid/uniform_coarsening.hpp

You can find a formatting patch under Artifacts here or run format! if you have write access to Ginkgo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1:ST:ready-for-review This PR is ready for review is:new-feature A request or implementation of a feature that does not exist yet. mod:core This is related to the core module. mod:cuda This is related to the CUDA module. mod:hip This is related to the HIP module. mod:reference This is related to the reference module. reg:build This is related to the build system. reg:testing This is related to testing. type:multigrid This is related to multigrid

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants