Draft: PCPatch: take the patches, or the points they are built around, as a DMLabel

Stacked on !9480 — review against pbrubeck/plex-coloring-order, not main.

PCPATCH hardwired its seed set to a whole stratum, so there was no way to relax only part of a mesh, and PCPatchCreateColorLabel_Private() named DMPlexCreateColoring() directly. @BarrySmith asked about the latter in pcpatchimpl.h:22 and pcpatch.c:1134: the coloring need not be a DMPLEX one, since a DMDA could construct patches and supply a coloring just as well.

The goal is for PCPATCH to take its patch definition as DMLabel data: which entities get a patch, or the finished patches themselves. Both are DM-neutral at the interface, so supplying the second bypasses every DMConvert() to DMPLEX in patch construction.

  • -pc_patch_use_coloring groups star patches whose seeds have pairwise disjoint stars into one block-diagonal solve per color, turning thousands of tiny solves into a few large ones.
  • PCPatchSetConstructLabel()/Get restrict the seeds to a label's stratum, intersected with the stratum -pc_patch_construct_dim/-codim selects, so a closure-completed label spanning every stratum may be passed unchanged. This is what a smoother on an adaptively refined level wants.
  • PCPatchSetPatchLabel()/Get supply the patches directly, one stratum per patch, bypassing construction entirely. This is the DM-neutral injection point.
  • The internal representation is one label whose strata are the colors, replacing the per-color array of labels, so DMPlexLabelCompleteStar() completes all colors in one call and the per-color allocation and cleanup loops go away.
  • The four use_coloring branches key off patch->patchLabel != NULL, and PCPatchGetPatchPointIS_Private() holds the stratum-value convention that three call sites repeated.
  • The stratum count is the largest any process needed, so a coloring whose color count varies between processes — -dm_plex_coloring_local from !9480 — pads with empty strata, keeping the label's values identical everywhere so DMPlexLabelCompleteStar() stays collective.
  • DMPlexLabelCompleteStar() does its DMLabelGather()/Distribute() once outside the per-value loop.

Options

Option Effect
-pc_patch_use_coloring One patch per color instead of one per point. A process only builds patches around the points it owns, so the coloring need only separate those; adding -dm_plex_coloring_local colors them without communicating and usually with fewer colors.
-pc_patch_construct_label name Builds patches only around the points the named DMLabel on the PC's DM marks. Resolved in PCPatchCreateCellPatches(), where the DM is known to be set, rather than in PCSetFromOptions_PATCH(), where it may not be yet.
-pc_patch_construct_label_value value The stratum of that label holding the points.

The two compose: colors are computed over the selected points only, so restricting the seeds can merge colors but never split one.

Review comments

Applied @BarrySmith's three inline suggestions: pcpatch.c "Did not manage to find" → "Did not find" at both sites, and the redundant #include <petscpc.h> dropped from ex12.c.

The coloring is now injectable, which answers the DM-dependence comment without a topology refactor: PCPatchSetPatchLabel() takes the finished grouping and needs no DMPLEX at all, and the one remaining site that names DMPlexCreateColoringLabel() is confined to PCPatchCreateColorLabel_Private(), which errors with a pointer to that setter if the DM will not convert.

Deferred by choice, worth a follow-up: the PetscSegBufferCreate() suggestions at pcpatch.c:1224 and plexsubmesh.c:319, and the PetscInt *points[] signature change at pcpatch.c:1214.

src/ksp/pc/tests/ex12.c compares standard against colored, labeled, fully-restricted, genuinely-restricted, named-label and locally-colored solves, each asserting an equal iteration count.

petsc4py gains PC.setPatchConstructLabel()/get and PC.setPatchLabel()/get.

AI was used to draft this change (Claude Code, Opus 5).

Edited by Pablo Brubeck

Merge request reports

Loading