Skip to content

Improve sympde - #189

Closed
FrederikSchnack wants to merge 22 commits into
masterfrom
improve_sympde
Closed

FrederikSchnack wants to merge 22 commits into
masterfrom
improve_sympde

Conversation

@FrederikSchnack

@FrederikSchnack FrederikSchnack commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Modernize SymPDE and clean up its public API

Summary

This PR modernizes SymPDE’s repository setup, documentation, testing workflows, and import interface.

The main objective is to reduce import overhead and provide a clear public API, as requested by issue #182. Additionally, we bump the sympy dependency to its latest version.

It also repairs the documentation infrastructure, migrates documentation publishing to GitHub Pages, and removes obsolete repository content.

Import performance and public API

  • 9c336d8 — Defer plotting imports until they are needed.
    Matplotlib and mpl_toolkits were imported whenever sympde.utilities.utils was loaded, even when no plotting was requested. The commit moves Matplotlib imports into the plotting functions and removes the wildcard import. It also fixes the identity-mapping dimension used for unmapped 2D domains. This addresses the expensive and unnecessary imports reported in Avoid useless imports #180.

  • 700bf5e — Add an explicit public API.
    Adds sympde.api, whose objects are imported explicitly from their defining modules. It provides one supported convenience namespace without relying on package-level wildcard exports. This implements the first step proposed in Remove unnecessary imports from __init__.py files #181 .

  • 1c37b9b — Remove package-level wildcard exports.
    Empties every package initializer except sympde.api, migrates internal imports to defining modules, updates tests and documentation, and removes a hidden import cycle between topology mappings and derivatives. This implements the second step of Remove unnecessary imports from __init__.py files #181.

  • fbf29f3 — Avoid dynamic execution in API tests.
    Replaces the exec-based wildcard-import test with direct inspection of sympde.api.all. This preserves API coverage while satisfying static-analysis requirements. It validates the API introduced for Remove unnecessary imports from __init__.py files #181.

  • 05b744f — Remove unused production imports.
    Removes 116 unused import bindings from 15 production files, including 84 third-party imports. Imports required by dynamic operator and serialization lookup are retained. This completes the unused-import audit requested by Avoid useless imports #180 .

  • 7d5f6ca — Defer domain serialization dependencies.
    Moves NumPy, HDF5, and PyYAML imports into Domain.export() and Domain.from_file(). Ordinary topology imports no longer load these serialization-only dependencies. This resolves another source of unnecessary import cost from Avoid useless imports #180 .

Sympy version

  • 457509d — Fix symbolic atom construction for modern SymPy
    ScalarFunction, VectorFunction, and DifferentialForm previously bypassed Symbol.__new__, leaving internal Symbol state such as _assumptions0 uninitialized. Current SymPy accesses that state during normal expression processing and consequently raised errors.
    The classes now use SymPy’s Symbol construction path. Regression tests cover assumptions, commutativity, free symbols, hashing, and differential-form identity.

  • 9fcbb54 — Fix integral sum multiplication postprocessing
    mul_add() accidentally wrapped the transformed IntAdd expression in a Python list. Modern SymPy strictly sympifies constructor-postprocessor results and rejected this list while checking form linearity.

    The postprocessor now returns a valid SymPy expression directly.

  • bb34a28 — Normalize structural arguments for modern SymPy

    Several custom symbolic objects stored ordinary strings, integers, dictionaries, tuples, or None directly in Basic.args. Modern SymPy expects every element of an expression tree to be a SymPy object, causing failures during traversal and LaTeX printing.

    This commit introduces centralized normalization for structural arguments and applies it to domains, boundaries, interfaces, equations, traces, one-dimensional forms, multipatch mappings, and matrix indices. Public properties still return the established Python-facing values, preserving the existing API.

    It also preserves integer-valued DifferentialForm.dim results and SymPDE’s historical name-based function-symbol identity.

  • 2178131 — Support the maintained SymPy release range

    The project dependency was changed from sympy >= 1.5, < 1.10 to sympy >= 1.12, < 1.15.

    The upper bound prevents an untested future SymPy release from being selected automatically. The normal CI matrix tests the newest allowed version, while an additional Python 3.11 job explicitly installs SymPy 1.12 to protect the lower bound.

  • 553d8ae — Remove obsolete SymPy compatibility utilities

    Replaced the copied is_sequence implementation with SymPy’s maintained sympy.utilities.iterables.is_sequence and converted singleton classes to native Python metaclass
    syntax.

    The special handling that prevents VectorFunction objects from being interpreted as sequences is now expressed directly at the relevant call sites. Missing is_sequence
    imports were also added to previously untested indexing paths.

    Since SymPDE now requires Python 3.9 and SymPy 1.12, the compatibility helpers are no longer needed and old_sympy_utilities.py was deleted.

Breaking import change

Objects are no longer re-exported from:

  • sympde;
  • sympde.topology;
  • sympde.calculus;
  • sympde.expr;
  • sympde.exterior;
  • sympde.printing; or
  • sympde.utilities.

User-facing code should now use:

  from sympde.api import Cube, Mapping, Constant
  from sympde.api import ScalarFunctionSpace, VectorFunctionSpace, elements_of
  from sympde.api import BilinearForm, LinearForm, Norm

Implementation code may instead import objects directly from their defining modules.

sympde.api.__all__ defines the supported wildcard-import surface. Tests verify that it contains no duplicates, exposes no accidental names, and references the objects from their defining modules.

Documentation infrastructure

  • 869494a — Repair strict documentation builds.
    Adds reproducible documentation builds, replaces shell-generated API documentation, configures bibliography and MathJax support, and fixes malformed API docstrings. This addresses the broken documentation setup in Failing readthedocs build #166
    and fixes the Domain.join documentation problem from Add docstring to Domain.join() #140 .

  • c70890a — Align testing and documentation workflows with Psydac.
    Renames the unit-test workflow to testing.yml, adopts Psydac’s workflow structure, updates the README badge, and formats the documentation workflow consistently. This improves the repository setup associated with Failing readthedocs build #166 .

  • 219cbd7 — Migrate documentation to GitHub Pages.
    Publishes strict Sphinx builds from master using GitHub Pages, updates project links, and removes the obsolete Read the Docs configuration. This addresses Failing readthedocs build #166 .

  • 3dda950 — Replace obsolete notebooks with tested examples.
    Converts useful notebook content into executable documentation scripts covering variational forms, differential calculus, analytical mappings, exterior calculus, and nonlinear Poisson linearization. The scripts are executed in documentation CI. This
    prevents the examples from becoming stale while updating them to the API introduced for Remove unnecessary imports from __init__.py files #181 .

  • a68f1e9— Remove the obsolete TODO file.
    Deletes an unreferenced roadmap from 2019 that describes removed APIs and already-completed work. Current work is tracked through GitHub issues.

Testing and repository maintenance

  • 26d16d7— Remove obsolete legacy test artifacts.
    Deletes unmaintained snapshots from old/ and removes bin/run_tests.sh, which references test modules that no longer exist. The maintained pytest suite is now the single documented test entry point.

  • 84667d7 — Modernize project metadata and test CI.
    Moves pytest configuration and development dependencies into pyproject.toml, tests the installed package across supported Python versions, and stores coverage as a CI artifact.

Closes #180
Closes #181
Closes #182
Closes #166
Closes #140
Closes #106

Delete the unmaintained old/ snapshots and bin/run_tests.sh. The script references test modules that no longer exist, so it advertises a broken workflow while the deleted snapshots duplicate history already preserved by Git.
Move pytest configuration and development dependencies into pyproject.toml, test installed packages across supported Python versions, and collect coverage as a CI artifact.

Keep the tested SymPy upper bound in place while #106 tracks the compatibility work needed for current releases.
Add reproducible GitHub Actions and Read the Docs builds, replace shell-based API generation, configure bibliography and MathJax support, and correct malformed API docstrings.

Addresses the failing documentation setup reported in #166.

Fixes the Domain.join documentation problem reported in #140.
Avoid importing Matplotlib and mpl_toolkits when SymPDE utilities are loaded. Add coverage for unmapped 2D domains and correct their identity mapping dimension from three to two.

Partially addresses the unnecessary-import problem in #180.
Rename the unit-test workflow to testing.yml, mirror Psydac's matrix and step layout, and update the README badge. Format the documentation workflow consistently while retaining Read the Docs rather than Psydac's GitHub Pages deployment.
Publish strict Sphinx builds from master through GitHub Pages, matching the Psydac documentation workflow. Update project links and remove the obsolete Read the Docs configuration.

Addresses #166.
Provide a curated sympde.api namespace whose objects are imported directly from their defining modules. Document representative imports and test that wildcard imports expose only the declared API.

This is the compatibility-preserving first phase of #181; existing package initializers remain until internal and Psydac imports are migrated.

Refs #181.
Empty every non-API package initializer and import internal dependencies from their defining modules. Migrate tests and documentation to sympde.api, and break the hidden mapping/derivatives import cycle.

BREAKING CHANGE: public objects are no longer re-exported from sympde or its subpackage namespaces. Import user-facing objects from sympde.api or import implementation objects from their defining modules.

Closes #181.
Verify the declared public namespace directly instead of executing a wildcard import string, satisfying static-analysis requirements without weakening API coverage.

Refs #181.
Move the useful variational-form, differential-calculus, mapping, exterior-calculus, and nonlinear-linearization material into executable documentation scripts. Run these examples in documentation CI and remove the stale notebooks, custom notebook styling, and Binder badge.

Refs #181.
Delete the unreferenced 2019 roadmap, which describes removed APIs and work that has since been implemented. Active work is tracked through GitHub issues.

Refs #181.
@FrederikSchnack
FrederikSchnack marked this pull request as draft September 28, 2026 13:11
@FrederikSchnack
FrederikSchnack marked this pull request as ready for review September 28, 2026 13:11
Delete dead standard-library, NumPy, SymPy, and internal imports while retaining dependencies used by dynamic operator and serialization lookup.

Refs #180.

Refs #182.
Import NumPy, HDF5, and PyYAML only when exporting or loading domain files, avoiding their cold-start cost for ordinary topology imports.

Refs #180.

Refs #182.
@FrederikSchnack
FrederikSchnack marked this pull request as draft September 28, 2026 13:46
@FrederikSchnack
FrederikSchnack marked this pull request as ready for review September 28, 2026 13:46
Construct function symbols and differential forms through Symbol so that SymPy initializes their assumptions and free-symbol state. Keep their SymPDE metadata in structural identity without exposing non-Basic values through args.

Refs #106
Keep the transformed IntAdd as a SymPy expression instead of wrapping it in a Python list. Modern SymPy strictly sympifies constructor postprocessor results and rejected the list while checking form linearity.

Refs #106
Convert string, numeric, container, and optional metadata stored in custom Basic.args to SymPy objects. Restore the public Python values through properties so callers keep the existing API while traversal, printing, hashing, and substitution can safely inspect expression trees.

Also preserve integer DifferentialForm dimensions and the historical name-based identity of function symbols.

Refs #106
Raise the minimum dependency to SymPy 1.12 for supported Python versions and cap it below 1.15 until the next compatibility review. Keep the regular CI matrix on the newest allowed release and add a Python 3.11 job pinned to the minimum.

Refs #106
Use SymPy's maintained is_sequence helper and native Python metaclass syntax now that the project requires Python 3.9 and SymPy 1.12. Preserve VectorFunction argument handling explicitly and add missing is_sequence imports to indexing code paths.

Delete the unused copied iterable helpers and compatibility module.

Refs #106
Accept normalized SymPy arguments in topology, equation, tensor-form, and multipatch-mapping constructors. Preserve structural metadata during rebuilding and cover func/xreplace round trips with regression tests.
Document the current domain, function-space, form, lowering, tensorization, mapping, and linearization APIs. Run the literal-included examples in the existing documentation workflow and remove obsolete helper scripts that imported deleted interfaces.
Trigger test and documentation workflows when pull requests are opened, reopened, synchronized, or marked ready so later commits cannot bypass validation.
Give function spaces structural equality and include them in scalar and vector function hashes. Equal names in different spaces now remain distinct symbols instead of collapsing during SymPy simplification.
@FrederikSchnack

Copy link
Copy Markdown
Contributor Author

This PR was split up into #190 #191 #193 #194

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant