Skip to content

ymf cleanup: docs re-shelved, dead schema keys refused, model/approximation naming (cekees/ymf#1–#5) - #24

Merged
cekees merged 16 commits into
proteustoolkit:mainfrom
cekees:main
Nov 2, 2026
Merged

cekees merged 16 commits into
proteustoolkit:mainfrom
cekees:main

Conversation

@cekees

@cekees cekees commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Step 0 of the ymf cleanup (C42): five reviewed PRs from cekees/ymf, merged there in order.

Proteus impact: none needed. No refused key appears in proteus main, and proteus calls the renamed functions through the kept aliases. A follow-up proteus PR can switch to the new names.

CI on this PR, Linux (py3.10 to 3.14, x64 and aarch64): every extra 617 passed, 1 skipped, no xfail (cekees#3 fixed the composed-domain test). One extra per leg: spec 442 passed, symbolic 543 passed, units 334 passed. The same commit passed macOS Intel on cekees/ymf. Before the cleanup it was 604 passed, 2 skipped, 1 xfailed.

🤖 Generated with Claude Code

cekees and others added 16 commits November 1, 2026 20:09
The docs directory mixed the two guides with superseded drafts, a session
log and unverified research, and the index called the v0.1 draft "the best
statement of the design principles" after two of them were dropped. This
sorts them by what they are, with no change to any guide's content beyond
moving closed gaps out.

- design/time-outside-space.md: status says implemented (ymf#22/proteustoolkit#23,
  proteus#109/#110) and that both § 8 questions were answered by
  cekees/proteus#121.
- history/: schema-v0.1, schema-v0.2-delta, session-2026-07-29, each with
  a header saying what replaced it.
- research/: units, data-sources, csdms-bmi; the csdms errors move from
  the index into the file's own header.
- changes.md (new): the closed Known-gaps entries, dated, with the commit
  that closed each, plus the two C27 decisions recorded only outside the
  repo until now (composition may remove; numbers and expressions
  treated uniformly).
- problem-specification.md: Known gaps keeps only open gaps (5, two of
  them the remnants left inside closed entries). The boundary-condition
  behaviour that lived there (Neumann sign, Robin, series) moves into the
  body. "Only on a box" was stale: only periodic needs a box.
- archive-format.md, README: Proteus writes this on its 2.0 line, not "the
  ymf_io branch"; say that the solver's tree is called domain in a solver
  document and approximation in an output.
- Doc paths in source comments updated. No code changed.

Checked: every relative link and anchor in README.md and docs/ resolves
(0 broken). Tests: 596 passed, 2 skipped, before and after (petsc-dev env,
macOS arm64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The extras were tested only all-or-nothing: the core smoke test, then every
extra at once. Installing one extra alone shows what that hid:

| install          | before                              | after                  |
|------------------|-------------------------------------|------------------------|
| ymf[spec]        | 427 passed, 20 skipped              | 428 passed, 19 skipped |
| ymf[units]       | 7 collection errors (run aborted)   | 331 passed, 48 skipped |
|                  | then 18 failed under them           |                        |
| ymf[symbolic]    | 1 failed (run from tests/)          | 525 passed, 14 skipped |
| every extra      | 596 passed, 2 skipped               | 596 passed, 2 skipped  |

- Seven files imported ymf.schema (strictyaml) above their importorskip,
  or had none: test_compose, test_domain, test_examples, test_references,
  test_removal, test_schema, test_values. The guard now comes first.
- Fifteen tests needed strictyaml or sympy and did not say so: the closure
  tests (one guard in their spec helper), the old-private-name alias test,
  the notebook round trip, three units tests. The Fourier number is in the
  spec notation, so without ymf[symbolic] it is asserted absent, not
  skipped.
- Two tests opened examples/ relative to the working directory, so they
  passed only from the repo root; they use their own path like the rest.
- A one-extra job, linux-64 / py3.12, for spec, units and symbolic: install
  the sdist with that extra alone, import its modules, run the suite.

No module changed. Measured on macOS arm64 with python 3.13 venvs holding
one extra each, and the petsc-dev env for every extra.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sify

The cleanup inventory listed four gaps to guard before any code moves; the
previous commit is the first (one-extra CI legs). These are the other three.

- units without ymf[symbolic] (test_units, 2 tests). problem-specification
  promises that a bare ymf[units] install still sees the coefficients that
  are already numbers. Nothing tested it. The tests hide sympy and
  ymf.symbolic, so the fallback is checked in every environment, and the
  units-only leg runs them for real: numbers and quoted numbers resolve,
  expression and notation formulas are left out, and a neumann condition
  is reported "not checked ... ymf[symbolic]" under missing_units="error"
  rather than failed.
- a domain composed across files (test_domain, 3 tests). Changing the kind
  in a child is refused, naming the parent's keys; replacing the region
  through remove: works and is logged. Adding boundary_tags in a child to
  the parent's region is refused today ("required key(s) 'kind' not
  found"): _partial does not relax a Str() | Map() validator. That test is
  xfail(strict=True) until the fix, a separate PR.
- classify on a coupled system (test_symbolic, 4 tests): cross-diffusion is
  keyed by the other unknown, a flux that depends on another unknown is
  advection, |grad phi|^2 is Hamiltonian, hamiltonian_gradients moves grad p
  out of the flux, and an undeclared name is refused. The two-phase model
  family builds on this step.

| install       | before (previous commit) | after                              |
|---------------|--------------------------|------------------------------------|
| every extra   | 596 passed, 2 skipped    | 604 passed, 2 skipped, 1 xfailed   |
| ymf[spec]     | 428 passed, 19 skipped   | 430 passed, 19 skipped, 1 xfailed  |
| ymf[units]    | 331 passed, 48 skipped   | 333 passed, 48 skipped             |
| ymf[symbolic] | 525 passed, 14 skipped   | 531 passed, 14 skipped, 1 xfailed  |

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A child that only adds boundary_tags to the region its model states was
refused: "required key(s) 'kind' not found". _partial, which relaxes the
schema for the files of a chain, descended into mappings and lists of
mappings but not into an alternative, and the domain is Str() | Map(...),
so its mapping kept `kind` required in every file. Both sides of an
alternative are now relaxed; the composed domain is still checked against
its kind by ymf.domain.validate_domain_block, as before.

Blast radius, walked over YMF_SCHEMA: three alternatives hold a mapping
(unknowns[], strong_form.domain, coefficients.*), and _partial reaches only
the domain (it does not descend a Seq of alternatives or a MapPattern). So
this changes one site.

| suite                         | before                            | after                  |
|-------------------------------|-----------------------------------|------------------------|
| every extra (petsc-dev)       | 604 passed, 2 skipped, 1 xfailed  | 605 passed, 2 skipped  |
| ymf[spec] alone               | 430 passed, 19 skipped, 1 xfailed | 431 passed, 19 skipped |
| ymf[symbolic] alone           | 531 passed, 14 skipped, 1 xfailed | 532 passed, 14 skipped |

The xfail(strict=True) on test_a_child_may_tag_the_region_its_parent_states
comes off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The schema accepted them from the v0.1/v0.2 drafts; no code in ymf or in
Proteus (cekees/main, checked by grep) reads or writes any of them, so a
document carrying one said something nobody heard. Now it is told which key.

- strong_form: strong_form_expression (superseded by equations; units.py
  only mentioned it in two docstrings, which now say what it does read),
  known_analytical_solution, dimensional_check (+ DimensionalCheckDef,
  DimCheckMethodEnum)
- model: unit_systems (+ UnitSystemDef)
- discretizations[]: bmi_interface
- top level: archive, xdmf, and the Xdmf -> xdmf fold in compose

Kept: mesh_generation and roughness_source, which ymf.data_sources reads;
they go with the decision on that module. Not on the list but also read by
nothing: model.units (convention, default); left for that decision too.

Examples heat_equation.ymf and poisson_v02_enriched.ymf drop
dimensional_check and bmi_interface; three test fixtures drop
strong_form_expression (one moves to equations). New
test_a_removed_key_is_refused_by_name loads from a file, so the Xdmf case
covers the fold: 8 of 8 cases fail on the schema before this commit.
Recorded in docs/changes.md (from #1, merged into this branch).

| suite               | before (#2)                       | after                             |
|---------------------|-----------------------------------|-----------------------------------|
| every extra         | 604 passed, 2 skipped, 1 xfailed  | 612 passed, 2 skipped, 1 xfailed  |
| ymf[spec] alone     | 430 passed, 19 skipped, 1 xfailed | 438 passed, 19 skipped, 1 xfailed |
| ymf[units] alone    | 333 passed, 48 skipped            | 333 passed, 48 skipped            |
| ymf[symbolic] alone | 531 passed, 14 skipped, 1 xfailed | 539 passed, 14 skipped, 1 xfailed |

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec's top-level key has been `model` since a66ea1c, and the archive
of a spec stores the realized spec under the key the spec uses. The README,
the archive guide and several docstrings still showed `Problem:`; they now
say `model:`. `Problem:` and `problem:` still fold to `model:` on read.

The functions that build and check the tree a solver writes were named for
a domain, which is also the region a problem is posed on. They are now
named for an approximation, which is what the archive of a spec already
calls the tree (outputs[key].approximation):

  new_domain           -> new_approximation
  validate_domain      -> validate_approximation
  canonicalize_domain  -> canonicalize_approximation
  select_domain        -> select_approximation
  rebase_domain        -> rebase_approximation
  inline_domain        -> inline_approximation
  domain_arrays        -> approximation_arrays

The old names are the same function objects, exported as before, so
Proteus (which calls all seven positionally) needs no change in lockstep.
The solver file's `domain:` key and the parameter names are unchanged: the
key is part of ymf_archive_version 2.

Tests, before (dead-keys, 7f68da3) -> after:
  every extra        612 passed, 2 skipped, 1 xfailed -> 615, 2, 1
  ymf[spec] alone    438 passed, 19 skipped, 1 xfailed -> 441, 19, 1
  ymf[units] alone   333 passed, 48 skipped            -> 334, 48
  ymf[symbolic] alone 539 passed, 14 skipped, 1 xfailed -> 542, 14, 1
New: the old key still reads as model (two cases), and the old function
names are the new functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Docs: re-shelve into design/, history/, research/, and a changes.md
Tests skip without an extra; one-extra CI legs; tests for three gaps
A file in an extends chain may tag its parent's region without restating its kind
Refuse eight schema keys that nothing reads
One name per thing: model for the spec, approximation for the tree
@cekees
cekees merged commit d466645 into proteustoolkit:main Nov 2, 2026
10 checks passed
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.

1 participant