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_coloringgroups 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()/Getrestrict the seeds to a label's stratum, intersected with the stratum-pc_patch_construct_dim/-codimselects, so a closure-completed label spanning every stratum may be passed unchanged. This is what a smoother on an adaptively refined level wants.PCPatchSetPatchLabel()/Getsupply 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_coloringbranches key offpatch->patchLabel != NULL, andPCPatchGetPatchPointIS_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_localfrom !9480 — pads with empty strata, keeping the label's values identical everywhere soDMPlexLabelCompleteStar()stays collective. DMPlexLabelCompleteStar()does itsDMLabelGather()/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).