Skip to content

Comments

Direct Solver: Recursive Skeletonization#164

Open
alexfikl wants to merge 1 commit intoinducer:mainfrom
alexfikl:direct-solver-recursion
Open

Direct Solver: Recursive Skeletonization#164
alexfikl wants to merge 1 commit intoinducer:mainfrom
alexfikl:direct-solver-recursion

Conversation

@alexfikl
Copy link
Collaborator

@alexfikl alexfikl commented Jun 30, 2022

Attempting to break up the direct solver MR into smaller, more reviewable pieces. As a rundown

The code for this is mostly in the deprecated https://gitlab.tiker.net/inducer/pytential/-/merge_requests/137.

@alexfikl alexfikl changed the title Direct Solver: Direct Solver: Recursive Skeletonization Jun 30, 2022
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 5 times, most recently from 39e8347 to 80bb8e1 Compare July 1, 2022 15:00
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 3 times, most recently from 8e3731d to 78699ec Compare July 14, 2022 12:30
@alexfikl alexfikl marked this pull request as ready for review July 14, 2022 12:31
@alexfikl
Copy link
Collaborator Author

@inducer This should be ready for a look. It doesn't do much:

  • adds a data structure to hold the hierarchical cluster info from boxtree.Tree and merge cluster indices.
  • adds some helper functions to do the recursive skeletonization + simple tests.

@alexfikl alexfikl requested a review from inducer July 14, 2022 15:12
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 3 times, most recently from 7ed33f4 to ea42c82 Compare August 2, 2022 06:24
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 5 times, most recently from 80fe1fb to b44f4a8 Compare August 4, 2022 18:09
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from cc4be24 to 0176d32 Compare August 12, 2022 12:57
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 0176d32 to f71a21b Compare August 22, 2022 06:19
Copy link
Owner

@inducer inducer left a comment

Choose a reason for hiding this comment

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

Noticed a pending review. Figured it'd be better to submit it. :) Don't quite know how old this is.


Current level that is represented.

.. attribute:: nlevels
Copy link
Owner

Choose a reason for hiding this comment

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

Is this avoidable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Reworked this a while back, so not quite sure if your comment still applies?

# {{{ cluster tree

@dataclass(frozen=True)
class ClusterTreeLevel:
Copy link
Owner

Choose a reason for hiding this comment

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

Is this two things rather than one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, separated into a ClusterTree and ClusterLevel with a ClusterTree.levels() iterator to go through them for the recursive skeletonization.

Naming could still be better probably?

logger.info("\n%s", case)

run_skeletonize_by_proxy(actx, case, case.resolutions[0], visualize=visualize)
dd = sym.DOFDescriptor(case.name, discr_stage=case.skel_discr_stage)
Copy link
Owner

Choose a reason for hiding this comment

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

Update the test docstring to describe precisely what's being tested here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from 9a8db7f to ce00d4e Compare August 23, 2022 16:09
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 3 times, most recently from c1e986c to 814b8ac Compare September 14, 2022 07:10
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from c479984 to 8aa200f Compare September 1, 2024 08:19
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 3 times, most recently from 9c5bb68 to a7c5d19 Compare September 20, 2024 11:51
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from 8bef46c to ae443aa Compare November 16, 2024 09:00
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from ae443aa to 85033db Compare December 17, 2024 08:13
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 85033db to 15eee49 Compare January 8, 2025 08:41
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 15eee49 to 78c496d Compare February 8, 2025 09:19
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from ba99713 to 963f568 Compare February 27, 2025 08:16
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 963f568 to 537447a Compare August 12, 2025 11:28
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 537447a to cf88a78 Compare August 19, 2025 07:40
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from cf88a78 to 978a582 Compare August 30, 2025 11:17
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 978a582 to 702d44a Compare September 16, 2025 17:02
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 702d44a to 3d8faf1 Compare October 10, 2025 06:19
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from 7f705e1 to 2df2cc8 Compare October 17, 2025 13:18
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from f153ed6 to 8994a24 Compare November 5, 2025 08:52
@alexfikl alexfikl force-pushed the direct-solver-recursion branch from 8994a24 to 48a5862 Compare December 16, 2025 08:36
@alexfikl alexfikl force-pushed the direct-solver-recursion branch 2 times, most recently from fe8b4f8 to 0490e47 Compare January 7, 2026 12:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR advances the direct solver work by introducing hierarchical clustering infrastructure and wiring it into proxy-based skeletonization to enable recursive (multi-level) skeletonization, along with the associated test and documentation updates.

Changes:

  • Add a new pytential.linalg.cluster module providing cluster trees/levels, clustering helpers, and partition_by_nodes.
  • Extend skeletonization to produce richer results (including diagonal blocks) and add rec_skeletonize_by_proxy for multi-level skeletonization.
  • Update proxy and skeletonization tests (and docs) to match the new clustering/tree and neighbor-gathering APIs.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pytential/linalg/cluster.py New clustering module (cluster tree/levels, partitioning, visualization utilities).
pytential/linalg/skeletonization.py Adds recursive skeletonization and augments skeletonization results/weighting/logging.
pytential/linalg/proxy.py Removes partition_by_nodes (moved to cluster module) and updates neighbor gathering API.
pytential/linalg/utils.py Documents/exports helper utilities used by skeletonization (make_flat_cluster_diag, interp_decomp).
test/extra_matrix_data.py Updates test fixtures to return (index, tree) and import partitioning from linalg.cluster.
test/test_linalg_cluster.py New tests for cluster tree construction and (un)clustering behavior.
test/test_linalg_proxy.py Adapts tests to updated cluster index return type and neighbor gathering signature.
test/test_linalg_skeletonization.py Updates tests to exercise multilevel skeletonization flow.
test/test_matrix.py Adapts callers to updated get_cluster_index / get_tgt_src_cluster_index return type.
doc/linalg.rst Includes pytential.linalg.cluster in the linalg documentation.
doc/conf.py Adds/adjusts intersphinx mappings for new referenced types.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if discr.ambient_dim == 2:
_visualize_clusters_2d(actx, generator, discr, srcindex, tree, filename,
dofdesc=dofdesc, overwrite=overwrite)
elif discr.ambient_dim == 2:
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

The 3D branch in visualize_clusters is unreachable because both the if and elif check discr.ambient_dim == 2. This prevents 3D visualization and will raise NotImplementedError for ambient_dim == 3. The elif condition should check for ambient_dim == 3.

Suggested change
elif discr.ambient_dim == 2:
elif discr.ambient_dim == 3:

Copilot uses AI. Check for mistakes.
Comment on lines +476 to +480
ax = fig.gca()

plotter = TreePlotter(tree._tree)
plotter.set_bounding_box()
plotter.draw_tree(fill=False, edgecolor="black", zorder=10)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

_visualize_clusters_2d unconditionally constructs TreePlotter(tree._tree). When partition_by_nodes(..., tree_kind=None) is used, ClusterTree._tree is None, so visualization will crash. Consider either raising a clearer error if tree._tree is None or skipping tree plotting in that case.

Copilot uses AI. Check for mistakes.
Comment on lines +956 to +964
for i, clevel in enumerate(ctree.levels[:-1]):
for ibrow, ibcol in product(range(wrangler.nrows), range(wrangler.ncols)):
skeleton = _skeletonize_block_by_proxy_with_mats(
actx, ibrow, ibcol, proxy.places, proxy, wrangler, tgt_src_index,
id_eps=id_eps,
# NOTE: we probably never want to set the rank here?
id_rank=None,
rng=rng,
max_particles_in_box=max_particles_in_box)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

rec_skeletonize_by_proxy takes places as an argument, but passes proxy.places into _skeletonize_block_by_proxy_with_mats. If a caller supplies _proxy built from a different GeometryCollection than places, the evaluation will use inconsistent geometries. Consider passing places through (and/or asserting proxy.places is places) to avoid subtle mismatches.

Copilot uses AI. Check for mistakes.
Comment on lines 603 to 605
"""Evaluate the proxy to cluster and neighbor to cluster interactions for
each cluster in *cluster_index*.
"""
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

Docstring for _evaluate_proxy_skeletonization_interaction still refers to *cluster_index*, but the function now takes source_index/target_index. Updating the wording to match the new parameter names would avoid confusion for future readers.

Copilot uses AI. Check for mistakes.
assert isinstance(discr, Discretization)

if tree_kind is not None:
setup_actx = lpot_source._setup_actx
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

In partition_by_nodes, setup_actx is taken from lpot_source._setup_actx, but places.get_geometry(...) can be a plain meshmode.discretization.Discretization (e.g. when GeometryCollection is built from a discretization), which does not provide _setup_actx. gather_cluster_neighbor_points handles this by using discr._setup_actx instead. Consider using discr._setup_actx here (or branching on the type) to avoid an AttributeError when tree_kind is not None.

Suggested change
setup_actx = lpot_source._setup_actx
if hasattr(lpot_source, "_setup_actx"):
setup_actx = lpot_source._setup_actx
else:
setup_actx = discr._setup_actx

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants