Skip to content

docs(internals): a contributor walkthrough of the main operations - #101

Merged
kylebeggs merged 2 commits into
mainfrom
docs/internals-walkthrough
Sep 11, 2026
Merged

kylebeggs merged 2 commits into
mainfrom
docs/internals-walkthrough

Conversation

@kylebeggs

Copy link
Copy Markdown
Collaborator

Closes #98.

Adds docs/pages/internals.qmd, the page a new contributor needs and the repo did not have. Every existing page is written for a user of the API — amr.qmd explains what regrid! means semantically but never mentions LeafKey, forest.index, or the generation counter. DESIGN.md is the record of decisions and rationale, and shouldn't become a walkthrough of control flow. There is no CONTRIBUTING.md, so this is now the contributor entry point.

Ten sections, one per main operation. Each gives the entry point, an ASCII call diagram, a type trace naming the concrete type at every step with allocations and mutations marked, step-by-step commentary, and a table of what it throws and what it invalidates:

apply! on one grid · adjoints and the five traits · the solver boundary · linearize · forest topology · block field layouts · the forest exchange · regrid! · multigrid · distributed.

Two departures from the issue's outline, both to cut forward references. The issue's forest section splits into topology (§5) and regrid (§8) so neither carries two unrelated stories, and so the flagship regrid! walkthrough has zero forward references. And linearize moves up to §4, next to adjoints: LinearizedOp takes a Field and multigrid and distributed are CartesianGrid-only, so none of them depend on the forest cluster at all. Four forward references remain, each one sentence, each pointing into the forest cluster.

The page closes with ## Rules for changing this code — eight obligations the type system cannot enforce, each paired with the test that catches you if you skip it.

Conventions

  • Static fences only. quarto render docs runs the full test suite via pages/coverage.qmd, so nothing on this page executes. Verified the page renders standalone outside the project.
  • Exported symbols link to api.qmd once, on first mention; everything else is bare. api.qmd iterates names(MatrixFreeOperators), so non-exported names — LeafKey, Forest, ExchangeSchedule, MGLevel, PreparedComposed, BlocksLayout — have no anchor to point at. All 31 links check out against the export block.
  • No line numbers, anywhere. They rot faster than anything else; the per-section Source line plus a symbol name is enough to grep.
  • toc: true, toc-depth: 2 — the second reference-shaped page on the site after the generated api.qmd, and the only one you jump into rather than read through.

It is ~1400 lines against 134–312 for the narrative pages. That is deliberate for a reference page, and the TOC plus the uniform section template is what keeps it navigable.

Checks run

  • All 230 distinct backticked identifiers resolve in src/ or ext/ (the two misses were the prose words "Pkg" and "grep").
  • All 31 api.qmd links point at exported symbols; no duplicates.
  • All 6 ASCII boxes align on both borders and every interior row, accounting for combining diacritics in /ȳ.
  • Fences balanced, zero executing cells, every .qmd link target exists, pages/api.qmd still alone under part: "API".
  • Spot-verified the load-bearing claims against source rather than trusting the trace — the regrid! sequence, the single generation bump site, halo_update! being a literal identity off a forest, "Martin–Cartwright" as the real name in schedule.jl, and that _build_coarsest is the only matrix assembly in src/.

Also adds one sentence linking the page from docs/index.qmd's Overview, and the sidebar entry last in part: "Docs".


🤖 Beep boop — Claude wrote this one after reading the same call graphs one time too many.

Agent-Harness: claude-code 2.1.268
Agent-Model: claude-opus-5[1m]
Agent-Review: unreviewed

Nothing in docs/ explained how the package works internally — every page is
written for a user of the API, and a new contributor asking what happens to
field data across a regrid had nowhere to go but the source.

Ten sections, one per main operation: apply!, adjoints and the five traits,
the solver boundary, linearize, forest topology, block field layouts, the
forest exchange, regrid!, multigrid, distributed. Each gives the entry point,
a call diagram, a type trace naming the concrete type at every step, step
commentary, and a table of what it throws and what it invalidates. Closes with
the obligations the type system cannot enforce, each paired with the test that
catches you.

Split the issue's forest section into topology and regrid so neither carries
two stories, and placed linearize next to adjoints since it is a single-grid
operator wrapper, not part of the forest cluster.

Every block is a static fence: rendering the book runs the full test suite via
pages/coverage.qmd.

Closes #98

Agent-Harness: claude-code 2.1.268
Agent-Model: claude-opus-5[1m]
Agent-Review: unreviewed
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown

Benchmark Results

Time

427b573... a47cf6e... 427b573... / a47cf6e...
forest/2D 64×32²/halo_update! 19.9 ± 0.081 μs 22.6 ± 0.16 μs 0.881 ± 0.0072
forest/2D 64×32²/laplacian mul! 0.113 ± 0.0012 ms 0.111 ± 0.00096 ms 1.01 ± 0.014
forest/2D 64×32²/laplacian mul! (packed) 0.0994 ± 0.00077 ms 0.104 ± 0.00083 ms 0.957 ± 0.011
forest/2D 64×32²/prepare 0.0964 ± 0.042 ms 0.102 ± 0.042 ms 0.949 ± 0.57
forest/2D refined/halo_update! 0.0884 ± 0.00092 ms 0.205 ± 0.0051 ms 0.432 ± 0.012
forest/2D refined/halo_update_adjoint! 0.221 ± 0.0098 ms 0.234 ± 0.0091 ms 0.943 ± 0.056
forest/2D refined/laplacian apply_adjoint! 1.52 ± 0.015 ms 1.51 ± 0.012 ms 1 ± 0.013
grid/2D 256²/(∂x + ∂y)ᵀ adjoint 0.772 ± 0.0026 ms 0.771 ± 0.0029 ms 1 ± 0.0051
grid/2D 256²/2λ + κ·I mul! 0.112 ± 0.001 ms 0.114 ± 0.0016 ms 0.976 ± 0.016
grid/2D 256²/adjoint(∂x + ∂y) mul! 0.799 ± 0.0046 ms 0.8 ± 0.0044 ms 0.998 ± 0.008
grid/2D 256²/advection mul! 0.071 ± 0.0011 ms 0.0684 ± 0.0022 ms 1.04 ± 0.037
grid/2D 256²/diffusion mul! 0.0942 ± 0.00047 ms 0.0933 ± 0.0006 ms 1.01 ± 0.0082
grid/2D 256²/diffusion prepare 3.92 ± 2.4 μs 4.43 ± 6.6 μs 0.886 ± 1.4
grid/2D 256²/diffusion slab adjoint (β = 0) 0.0382 ± 0.00019 ms 0.0381 ± 0.00021 ms 1 ± 0.0074
grid/2D 256²/diffusion slab adjoint (β ≠ 0) 0.0978 ± 0.00059 ms 0.0977 ± 0.0011 ms 1 ± 0.012
grid/2D 256²/diffusion slab apply! 25.9 ± 0.19 μs 25.9 ± 0.16 μs 1 ± 0.0096
grid/2D 256²/divergence mul! 0.105 ± 0.00048 ms 0.106 ± 0.00057 ms 0.996 ± 0.007
grid/2D 256²/divergenceᵀ adjoint (β ≠ 0) 0.226 ± 0.0033 ms 0.226 ± 0.0048 ms 0.997 ± 0.026
grid/2D 256²/gradient mul! 0.177 ± 0.0031 ms 0.177 ± 0.0037 ms 1 ± 0.027
grid/2D 256²/gradientᵀ adjoint (β ≠ 0) 0.383 ± 0.01 ms 0.383 ± 0.01 ms 1 ± 0.038
grid/2D 256²/laplacian mul! 0.0589 ± 0.00045 ms 0.0575 ± 0.00054 ms 1.02 ± 0.012
grid/2D 256²/laplacian prepare 4.04 ± 2.3 μs 4.49 ± 6.6 μs 0.899 ± 1.4
grid/2D 256²/∂x adjoint (β = 0) 0.379 ± 0.01 ms 0.379 ± 0.0096 ms 1 ± 0.037
grid/2D 256²/∂x adjoint (β ≠ 0) 0.405 ± 0.01 ms 0.405 ± 0.0095 ms 1 ± 0.034
grid/2D 256²/∇·(κ∇u) mul! 0.263 ± 0.01 ms 0.26 ± 0.01 ms 1.01 ± 0.055
grid/2D 256²/∇·(κ∇u) prepare 13.7 ± 9.7 μs 16.4 ± 15 μs 0.831 ± 0.97
grid/3D 64³/diffusion mul! 0.526 ± 0.012 ms 0.539 ± 0.013 ms 0.976 ± 0.032
grid/3D 64³/diffusion slab adjoint (β = 0) 0.54 ± 0.011 ms 0.54 ± 0.012 ms 1 ± 0.03
grid/3D 64³/diffusion slab adjoint (β ≠ 0) 0.879 ± 0.0055 ms 0.882 ± 0.0049 ms 0.997 ± 0.0084
grid/3D 64³/diffusion slab apply! 0.191 ± 0.0044 ms 0.192 ± 0.0068 ms 0.997 ± 0.042
grid/3D 64³/laplacian mul! 0.324 ± 0.011 ms 0.322 ± 0.011 ms 1.01 ± 0.047
grid/3D 64³/laplacian prepare 0.129 ± 0.069 ms 0.124 ± 0.076 ms 1.03 ± 0.84
time_to_load 0.296 ± 0.0037 s 0.297 ± 0.0011 s 0.999 ± 0.013

Memory and allocations

427b573... a47cf6e... 427b573... / a47cf6e...
forest/2D 64×32²/halo_update! 0 allocs: 0 B 0 allocs: 0 B
forest/2D 64×32²/laplacian mul! 0 allocs: 0 B 0 allocs: 0 B
forest/2D 64×32²/laplacian mul! (packed) 0 allocs: 0 B 0 allocs: 0 B
forest/2D 64×32²/prepare 0.582 k allocs: 1.72 MB 0.582 k allocs: 1.72 MB 1
forest/2D refined/halo_update! 0 allocs: 0 B 0 allocs: 0 B
forest/2D refined/halo_update_adjoint! 0 allocs: 0 B 0 allocs: 0 B
forest/2D refined/laplacian apply_adjoint! 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/(∂x + ∂y)ᵀ adjoint 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/2λ + κ·I mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/adjoint(∂x + ∂y) mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/advection mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/diffusion mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/diffusion prepare 6 allocs: 1.02 MB 6 allocs: 1.02 MB 1
grid/2D 256²/diffusion slab adjoint (β = 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/diffusion slab adjoint (β ≠ 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/diffusion slab apply! 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/divergence mul! 1 allocs: 0.0469 kB 1 allocs: 0.0469 kB 1
grid/2D 256²/divergenceᵀ adjoint (β ≠ 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/gradient mul! 1 allocs: 0.0469 kB 1 allocs: 0.0469 kB 1
grid/2D 256²/gradientᵀ adjoint (β ≠ 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/laplacian mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/laplacian prepare 6 allocs: 1.02 MB 6 allocs: 1.02 MB 1
grid/2D 256²/∂x adjoint (β = 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/∂x adjoint (β ≠ 0) 0 allocs: 0 B 0 allocs: 0 B
grid/2D 256²/∇·(κ∇u) mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/2D 256²/∇·(κ∇u) prepare 18 allocs: 5.08 MB 18 allocs: 5.08 MB 1
grid/3D 64³/diffusion mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/3D 64³/diffusion slab adjoint (β = 0) 0 allocs: 0 B 0 allocs: 0 B
grid/3D 64³/diffusion slab adjoint (β ≠ 0) 0 allocs: 0 B 0 allocs: 0 B
grid/3D 64³/diffusion slab apply! 0 allocs: 0 B 0 allocs: 0 B
grid/3D 64³/laplacian mul! 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
grid/3D 64³/laplacian prepare 6 allocs: 4.39 MB 6 allocs: 4.39 MB 1
time_to_load 0.149 k allocs: 11.2 kB 0.149 k allocs: 11.2 kB 1

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

Agent-Harness: codex-cli unknown
Agent-Model: gpt-6-astra
Agent-Review: unreviewed
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://RallypointOne.github.io/MatrixFreeOperators.jl/pr-preview/pr-101/

Built to branch gh-pages at 2026-09-11 18:52 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@kylebeggs
kylebeggs merged commit dffd111 into main Sep 11, 2026
10 checks passed
@kylebeggs
kylebeggs deleted the docs/internals-walkthrough branch September 11, 2026 22:40
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.

docs(internals): a contributor-facing walkthrough of the main operations — pseudocode with the types called out

1 participant