From db70516b7c32debff05f99ba10d53a9da8df1cc2 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Mon, 28 Sep 2026 13:51:08 +0200 Subject: [PATCH 01/17] Repair strict documentation builds 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 https://github.com/pyccel/sympde/issues/166. Fixes the Domain.join documentation problem reported in https://github.com/pyccel/sympde/issues/140. --- .github/workflows/documentation.yml | 57 +++++++++++++++++++ .readthedocs.yaml | 17 ++++++ doc/conf.py | 67 +++++++++++----------- sympde/expr/evaluation.py | 3 +- sympde/topology/domain.py | 88 ++++++++--------------------- sympde/topology/mapping.py | 12 ++-- 6 files changed, 136 insertions(+), 108 deletions(-) create mode 100644 .github/workflows/documentation.yml create mode 100644 .readthedocs.yaml diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 00000000..7f47c57c --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,57 @@ +name: Documentation + +on: + push: + branches: [master] + paths: + - 'doc/**' + - 'sympde/**' + - 'pyproject.toml' + - '.readthedocs.yaml' + - '.github/workflows/documentation.yml' + pull_request: + branches: [master] + paths: + - 'doc/**' + - 'sympde/**' + - 'pyproject.toml' + - '.readthedocs.yaml' + - '.github/workflows/documentation.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: documentation-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + cache: pip + cache-dependency-path: pyproject.toml + + - name: Install project and documentation dependencies + run: | + python -m pip install --upgrade pip + python -m pip install ".[docs]" + + - name: Build documentation + run: >- + python -m sphinx -W --keep-going + -b html doc doc/_build/html + + - name: Upload rendered documentation + uses: actions/upload-artifact@v4 + with: + name: sympde-documentation + path: doc/_build/html diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..6a6333f0 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +sphinx: + configuration: doc/conf.py + fail_on_warning: true + +python: + install: + - method: pip + path: . + extra_requirements: + - docs diff --git a/doc/conf.py b/doc/conf.py index e8531e46..f3a8bc45 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,10 +1,10 @@ -# -*- coding: utf-8 -*- -# -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/master/config +"""Sphinx configuration for the SymPDE documentation.""" + +from pathlib import Path + +from sphinx.ext.apidoc import main as sphinx_apidoc + +from sympde import __version__ # -- Path setup -------------------------------------------------------------- @@ -19,21 +19,21 @@ # -- Project information ----------------------------------------------------- -project = 'sympde' -copyright = '2018, A. Ratnani, S. Hadjout' -author = 'A. Ratnani, S. Hadjout' +project = 'SymPDE' +copyright = '2018-2026, SymPDE developers' +author = 'SymPDE developers' # The short X.Y version -version = '' +version = __version__.split('-dev', maxsplit=1)[0] # The full version, including alpha/beta/rc tags -release = '' +release = version # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # -# needs_sphinx = '1.0' +needs_sphinx = '7.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -42,7 +42,7 @@ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', - 'sphinx.ext.imgmath', + 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', 'sphinxcontrib.bibtex', ] @@ -54,7 +54,7 @@ # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = {'.rst': 'restructuredtext'} # The master toctree document. master_doc = 'index' @@ -64,7 +64,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -143,26 +143,13 @@ latex_additional_files = ['latex_macros.sty'] latex_elements = { - 'printmodindex': '', 'printindex': '', 'preamble' : r'\usepackage{amsmath} \usepackage{amssymb} \usepackage{latex_macros}', - 'docclass':'report', } ##################################################### # add LaTeX macros -f = open('latex_macros.sty', 'r') - -try: - imgmath_latex_preamble # check whether this is already defined -except NameError: - imgmath_latex_preamble = "" - -for macro in f: - # used when building html version - imgmath_latex_preamble += macro + '\n' - # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples @@ -192,11 +179,21 @@ # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True +bibtex_bibfiles = ['math/refs_feec.bib'] -# -- APIDOC ---------------------------------------------- -import subprocess -cmd = 'rm -rf source; sphinx-apidoc --force --maxdepth=3 -o source/ ../sympde' -subprocess.call(cmd, shell=True) -# create _static directory -subprocess.call('mkdir -p _static', shell=True) +# -- APIDOC ---------------------------------------------- +doc_dir = Path(__file__).resolve().parent +source_dir = doc_dir / 'source' +static_dir = doc_dir / '_static' +source_dir.mkdir(exist_ok=True) +static_dir.mkdir(exist_ok=True) +apidoc_args = [ + '--force', + '--remove-old', + '--maxdepth', '3', + '--output-dir', str(source_dir), + str(doc_dir.parent / 'sympde'), +] +apidoc_args.extend(str(path) for path in (doc_dir.parent / 'sympde').glob('*/tests')) +sphinx_apidoc(apidoc_args) diff --git a/sympde/expr/evaluation.py b/sympde/expr/evaluation.py index d3f0ace4..aa148b04 100644 --- a/sympde/expr/evaluation.py +++ b/sympde/expr/evaluation.py @@ -502,8 +502,7 @@ class TerminalExpr(CalculusFunction): Parameters ---------- - expr : Expr | Matrix | ImmutableDenseMatrix (from sympy) - | LogicalExpr (from sympde.topology.mapping) + expr : Expr or Matrix or ImmutableDenseMatrix or LogicalExpr The mathematical expression. domain : BasicDomain (from sympde.topology.basic) diff --git a/sympde/topology/domain.py b/sympde/topology/domain.py index f7cefdea..d3fecfcd 100644 --- a/sympde/topology/domain.py +++ b/sympde/topology/domain.py @@ -434,23 +434,19 @@ def from_file(cls, filename): @classmethod def join(cls, patches, connectivity, name): - """ - Create a multipatch domain by joining two or more patches in 2D or 3D. + """Create a multipatch domain by joining patches in 2D or 3D. Parameters ---------- - patches : list[Domain] - List of patches. - - connectivity : list - List of interfaces, identified by a tuple of 2 boundaries and an orientation - (bound_minus, bound_plus, ornt) where - - Each boundary is identified by a tuple of 3 integers: (patch, axis, ext) - with patches given as objects (or by their indices in the patches list) - and - - In 2D, ornt is an integer that can take the value of 1 or -1 - - In 3D, ornt is a tuple of 3 integers that can take the value of 1 or -1 - (see below for more details) + patches : sequence of Domain + Atomic patches in the joined domain. + + connectivity : sequence of tuple + Interface descriptions of the form ``(minus, plus, orientation)``. + Each side is ``(patch, axis, ext)``, where ``patch`` is a patch + object or its index in ``patches`` and ``ext`` is ``-1`` or ``1``. + A 2D orientation is ``-1`` or ``1``. A 3D orientation is a tuple + of three values, each equal to ``-1`` or ``1``. name : str Name of the domain. @@ -462,56 +458,19 @@ def join(cls, patches, connectivity, name): Notes ----- - The orientations are specified in the same manner as in GeoPDES, see e.g. - - and - T. Dokken, E. Quak, V. Skytt. Requirements from Isogeometric Analysis for changes in product design ontologies, 2010. - - Example - ------- - # list of patches (mapped domains) - Omega_0 = F0(A) - Omega_1 = F1(A) - Omega_2 = F2(A) - Omega_3 = F3(A) - - patches = [Omega_0, Omega_1, Omega_2, Omega_3] - - # integers representing the axes - axis_0 = 0 - axis_1 = 1 - axis_2 = 2 - - # integers representing the extremities: left (-1) or right (+1) - ext_0 = -1 - ext_1 = +1 - - # A connectivity list in 2D - connectivity = [((Omega_0, axis_0, ext_0), (Omega_1, axis_0, ext_1), 1), - ((Omega_1, axis_1, ext_0), (Omega_3, axis_1, ext_1), -1), - ((Omega_0, axis_1, ext_0), (Omega_2, axis_1, ext_1), 1), - ((Omega_2, axis_0, ext_0), (Omega_3, axis_0, ext_1), -1)] - - # alternative option (passing interface patches by their indices in the patches list): - connectivity = [((0, axis_0, ext_0), (1, axis_0, ext_1), 1), - ((1, axis_1, ext_0), (3, axis_1, ext_1), -1), - ((0, axis_1, ext_0), (2, axis_1, ext_1), 1), - ((2, axis_0, ext_0), (3, axis_0, ext_1), -1)] - - # A connectivity list in 3D - connectivity = [((Omega_0, axis_0, ext_1), (Omega_1, axis_0, ext_0), ( 1, 1, 1)), - ((Omega_0, axis_1, ext_1), (Omega_2, axis_1, ext_0), ( 1, -1, 1)), - ((Omega_1, axis_1, ext_1), (Omega_3, axis_1, ext_0), (-1, 1, -1)), - ((Omega_2, axis_0, ext_1), (Omega_3, axis_0, ext_0), (-1, 1, 1))] - - # alternative option (passing interface patches by their indices in the patches list): - connectivity = [((0, axis_0, ext_1), (1, axis_0, ext_0), ( 1, 1, 1)), - ((0, axis_1, ext_1), (2, axis_1, ext_0), ( 1, -1, 1)), - ((1, axis_1, ext_1), (3, axis_1, ext_0), (-1, 1, -1)), - ((2, axis_0, ext_1), (3, axis_0, ext_0), (-1, 1, 1))] - - # the multi-patch domain - Omega = Domain.join(patches=patches, connectivity=connectivity, name='Omega') + The orientation convention follows the `GeoPDEs multipatch geometry + specification `_. + + Examples + -------- + Join the right side of one square to the left side of another: + + >>> patch_a = Square('A') + >>> patch_b = Square('B') + >>> interfaces = [((0, 0, 1), (1, 0, -1), 1)] + >>> domain = Domain.join([patch_a, patch_b], interfaces, 'Omega') + >>> len(domain) + 2 """ assert isinstance(patches, (tuple, list)) assert isinstance(connectivity, (tuple, list)) @@ -1142,4 +1101,3 @@ def split(domain, value): else: raise NotImplementedError('TODO') - diff --git a/sympde/topology/mapping.py b/sympde/topology/mapping.py index c4844316..f0947038 100644 --- a/sympde/topology/mapping.py +++ b/sympde/topology/mapping.py @@ -751,12 +751,12 @@ def eval(cls, F): """ this class methods computes the jacobian of a mapping - Parameters: + Parameters ---------- F: Mapping mapping object - Returns: + Returns ---------- expr : ImmutableDenseMatrix the jacobian matrix @@ -799,7 +799,7 @@ def eval(cls, F, v): """ This class methods computes the covariant transformation - Parameters: + Parameters ---------- F: Mapping mapping object @@ -807,7 +807,7 @@ def eval(cls, F, v): v: the basis function - Returns: + Returns ---------- expr : Tuple the covariant transformation @@ -848,7 +848,7 @@ def eval(cls, F, v): """ This class methods computes the contravariant transformation - Parameters: + Parameters ---------- F: Mapping mapping object @@ -856,7 +856,7 @@ def eval(cls, F, v): v: the basis function - Returns: + Returns ---------- expr : Tuple the contravariant transformation From fb4a5c70258c385e1b21f6f68717fe7b3b72c642 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Tue, 29 Sep 2026 16:59:57 +0200 Subject: [PATCH 02/17] Align documentation workflow with Psydac Use the maintained Sphinx build layout while keeping documentation CI separate from the test matrix. --- .github/workflows/documentation.yml | 80 ++++++++++++++--------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 7f47c57c..636eed95 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -2,56 +2,56 @@ name: Documentation on: push: - branches: [master] + branches: [ master ] paths: + - 'README.rst' - 'doc/**' - - 'sympde/**' + - 'sympde/**.py' - 'pyproject.toml' - '.readthedocs.yaml' - '.github/workflows/documentation.yml' + pull_request: - branches: [master] - paths: - - 'doc/**' - - 'sympde/**' - - 'pyproject.toml' - - '.readthedocs.yaml' - - '.github/workflows/documentation.yml' + branches: [ master ] + types: + - ready_for_review + workflow_dispatch: permissions: contents: read -concurrency: - group: documentation-${{ github.ref }} - cancel-in-progress: true - jobs: - build: - runs-on: ubuntu-24.04 + build_docs: + runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: '3.12' - cache: pip - cache-dependency-path: pyproject.toml - - - name: Install project and documentation dependencies - run: | - python -m pip install --upgrade pip - python -m pip install ".[docs]" - - - name: Build documentation - run: >- - python -m sphinx -W --keep-going - -b html doc doc/_build/html - - - name: Upload rendered documentation - uses: actions/upload-artifact@v4 - with: - name: sympde-documentation - path: doc/_build/html + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.10' + cache: 'pip' + cache-dependency-path: | + pyproject.toml + + - name: Upgrade pip, setuptools, and wheel + run: | + pip install --upgrade pip setuptools wheel + + - name: Install project and documentation dependencies + run: | + pip install .[docs] + pip freeze + + - name: Make the Sphinx documentation + run: >- + python -m sphinx -W --keep-going + -b html doc doc/_build/html + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: sympde-documentation + path: 'doc/_build/html' From ad1f5d1c4f2b50d8c42236b9e0fe64d86fb540ac Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Mon, 28 Sep 2026 14:10:59 +0200 Subject: [PATCH 03/17] Migrate documentation to GitHub Pages 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. --- .github/workflows/documentation.yml | 23 +++++++++++++++++++---- .readthedocs.yaml | 17 ----------------- README.md | 10 +++++++++- pyproject.toml | 5 +++++ 4 files changed, 33 insertions(+), 22 deletions(-) delete mode 100644 .readthedocs.yaml diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 636eed95..f1bfa418 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -4,11 +4,10 @@ on: push: branches: [ master ] paths: - - 'README.rst' + - 'README.md' - 'doc/**' - 'sympde/**.py' - 'pyproject.toml' - - '.readthedocs.yaml' - '.github/workflows/documentation.yml' pull_request: @@ -20,6 +19,8 @@ on: permissions: contents: read + pages: write + id-token: write jobs: build_docs: @@ -50,8 +51,22 @@ jobs: python -m sphinx -W --keep-going -b html doc doc/_build/html + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-pages-artifact@v3 with: - name: sympde-documentation path: 'doc/_build/html' + + deploy_docs: + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + needs: build_docs + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index 6a6333f0..00000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,17 +0,0 @@ -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.12" - -sphinx: - configuration: doc/conf.py - fail_on_warning: true - -python: - install: - - method: pip - path: . - extra_requirements: - - docs diff --git a/README.md b/README.md index 764fae61..cb47ff2c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![CI status](https://github.com/pyccel/sympde/actions/workflows/testing.yml/badge.svg?branch=master&event=push)](https://github.com/pyccel/sympde/actions/workflows/testing.yml) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/pyccel/sympde/master) -[![Documentation Status](https://readthedocs.org/projects/sympde/badge/?version=latest)](http://sympde.readthedocs.io/en/latest/?badge=latest) +[![Documentation Status](https://github.com/pyccel/sympde/actions/workflows/documentation.yml/badge.svg)](https://github.com/pyccel/sympde/actions/workflows/documentation.yml) **SymPDE** is a symbolic calculus library for partial differential equations and variational forms. It can be used to provide capabilities similar to the [FEniCS](https://fenicsproject.org/) project by extending and writing your own *printing* functions. @@ -76,6 +76,14 @@ The complete test suite can be run from any directory with: pytest -n auto --dist loadgroup --pyargs sympde -ra ``` +The documentation dependencies are installed separately, and the HTML pages +are built with warnings treated as errors: + +```bash +python3 -m pip install --editable ".[docs]" +python3 -m sphinx -W --keep-going -b html doc doc/_build/html +``` + ## For developers Because many important SymPDE features are only tested in Psydac, new pull requests should also be tested against the Psydac test suite. diff --git a/pyproject.toml b/pyproject.toml index ecd04efc..d58959e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,8 +37,13 @@ test = [ "pytest-cov >= 5", "pytest-xdist >= 3", ] +docs = [ + "sphinx >= 7", + "sphinxcontrib-bibtex >= 2.6", +] [project.urls] +Documentation = "https://pyccel.github.io/sympde/" Issues = "https://github.com/pyccel/sympde/issues" Repository = "https://github.com/pyccel/sympde" From b80f0b43ebb2530317f5ec133ac9c014293c0a9b Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Tue, 29 Sep 2026 17:00:10 +0200 Subject: [PATCH 04/17] Run documentation checks on pull request updates Build the documentation when pull requests are opened, reopened, or synchronized, in addition to ready-for-review transitions. --- .github/workflows/documentation.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index f1bfa418..cd9a787e 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -13,6 +13,9 @@ on: pull_request: branches: [ master ] types: + - opened + - reopened + - synchronize - ready_for_review workflow_dispatch: From d2948454586528542614c3c593e62d0594c9709c Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Tue, 29 Sep 2026 17:21:50 +0200 Subject: [PATCH 05/17] Preserve Domain.join orientation notes Restore the detailed multipatch orientation reference and connectivity examples that were removed while repairing the documentation build. --- sympde/topology/domain.py | 64 ++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/sympde/topology/domain.py b/sympde/topology/domain.py index d3fecfcd..c5055d7f 100644 --- a/sympde/topology/domain.py +++ b/sympde/topology/domain.py @@ -458,19 +458,56 @@ def join(cls, patches, connectivity, name): Notes ----- - The orientation convention follows the `GeoPDEs multipatch geometry - specification `_. - - Examples - -------- - Join the right side of one square to the left side of another: - - >>> patch_a = Square('A') - >>> patch_b = Square('B') - >>> interfaces = [((0, 0, 1), (1, 0, -1), 1)] - >>> domain = Domain.join([patch_a, patch_b], interfaces, 'Omega') - >>> len(domain) - 2 + The orientations are specified in the same manner as in GeoPDES, see e.g. + + and + T. Dokken, E. Quak, V. Skytt. Requirements from Isogeometric Analysis for changes in product design ontologies, 2010. + + Example + ------- + # list of patches (mapped domains) + Omega_0 = F0(A) + Omega_1 = F1(A) + Omega_2 = F2(A) + Omega_3 = F3(A) + + patches = [Omega_0, Omega_1, Omega_2, Omega_3] + + # integers representing the axes + axis_0 = 0 + axis_1 = 1 + axis_2 = 2 + + # integers representing the extremities: left (-1) or right (+1) + ext_0 = -1 + ext_1 = +1 + + # A connectivity list in 2D + connectivity = [((Omega_0, axis_0, ext_0), (Omega_1, axis_0, ext_1), 1), + ((Omega_1, axis_1, ext_0), (Omega_3, axis_1, ext_1), -1), + ((Omega_0, axis_1, ext_0), (Omega_2, axis_1, ext_1), 1), + ((Omega_2, axis_0, ext_0), (Omega_3, axis_0, ext_1), -1)] + + # alternative option (passing interface patches by their indices in the patches list): + connectivity = [((0, axis_0, ext_0), (1, axis_0, ext_1), 1), + ((1, axis_1, ext_0), (3, axis_1, ext_1), -1), + ((0, axis_1, ext_0), (2, axis_1, ext_1), 1), + ((2, axis_0, ext_0), (3, axis_0, ext_1), -1)] + + # A connectivity list in 3D + connectivity = [((Omega_0, axis_0, ext_1), (Omega_1, axis_0, ext_0), ( 1, 1, 1)), + ((Omega_0, axis_1, ext_1), (Omega_2, axis_1, ext_0), ( 1, -1, 1)), + ((Omega_1, axis_1, ext_1), (Omega_3, axis_1, ext_0), (-1, 1, -1)), + ((Omega_2, axis_0, ext_1), (Omega_3, axis_0, ext_0), (-1, 1, 1))] + + # alternative option (passing interface patches by their indices in the patches list): + connectivity = [((0, axis_0, ext_1), (1, axis_0, ext_0), ( 1, 1, 1)), + ((0, axis_1, ext_1), (2, axis_1, ext_0), ( 1, -1, 1)), + ((1, axis_1, ext_1), (3, axis_1, ext_0), (-1, 1, -1)), + ((2, axis_0, ext_1), (3, axis_0, ext_0), (-1, 1, 1))] + + # the multi-patch domain + Omega = Domain.join(patches=patches, connectivity=connectivity, name='Omega') """ assert isinstance(patches, (tuple, list)) assert isinstance(connectivity, (tuple, list)) @@ -1100,4 +1137,3 @@ def split(domain, value): else: raise NotImplementedError('TODO') - From 69a41d72df4533343e20a55ec937d3a4945d6443 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Tue, 29 Sep 2026 17:23:24 +0200 Subject: [PATCH 06/17] Format restored Domain.join example for Sphinx Keep the full multipatch connectivity notes while marking their example as a Python code block so strict documentation builds remain warning-free. --- sympde/topology/domain.py | 88 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/sympde/topology/domain.py b/sympde/topology/domain.py index c5055d7f..2451b547 100644 --- a/sympde/topology/domain.py +++ b/sympde/topology/domain.py @@ -465,49 +465,51 @@ def join(cls, patches, connectivity, name): Example ------- - # list of patches (mapped domains) - Omega_0 = F0(A) - Omega_1 = F1(A) - Omega_2 = F2(A) - Omega_3 = F3(A) - - patches = [Omega_0, Omega_1, Omega_2, Omega_3] - - # integers representing the axes - axis_0 = 0 - axis_1 = 1 - axis_2 = 2 - - # integers representing the extremities: left (-1) or right (+1) - ext_0 = -1 - ext_1 = +1 - - # A connectivity list in 2D - connectivity = [((Omega_0, axis_0, ext_0), (Omega_1, axis_0, ext_1), 1), - ((Omega_1, axis_1, ext_0), (Omega_3, axis_1, ext_1), -1), - ((Omega_0, axis_1, ext_0), (Omega_2, axis_1, ext_1), 1), - ((Omega_2, axis_0, ext_0), (Omega_3, axis_0, ext_1), -1)] - - # alternative option (passing interface patches by their indices in the patches list): - connectivity = [((0, axis_0, ext_0), (1, axis_0, ext_1), 1), - ((1, axis_1, ext_0), (3, axis_1, ext_1), -1), - ((0, axis_1, ext_0), (2, axis_1, ext_1), 1), - ((2, axis_0, ext_0), (3, axis_0, ext_1), -1)] - - # A connectivity list in 3D - connectivity = [((Omega_0, axis_0, ext_1), (Omega_1, axis_0, ext_0), ( 1, 1, 1)), - ((Omega_0, axis_1, ext_1), (Omega_2, axis_1, ext_0), ( 1, -1, 1)), - ((Omega_1, axis_1, ext_1), (Omega_3, axis_1, ext_0), (-1, 1, -1)), - ((Omega_2, axis_0, ext_1), (Omega_3, axis_0, ext_0), (-1, 1, 1))] - - # alternative option (passing interface patches by their indices in the patches list): - connectivity = [((0, axis_0, ext_1), (1, axis_0, ext_0), ( 1, 1, 1)), - ((0, axis_1, ext_1), (2, axis_1, ext_0), ( 1, -1, 1)), - ((1, axis_1, ext_1), (3, axis_1, ext_0), (-1, 1, -1)), - ((2, axis_0, ext_1), (3, axis_0, ext_0), (-1, 1, 1))] - - # the multi-patch domain - Omega = Domain.join(patches=patches, connectivity=connectivity, name='Omega') + .. code-block:: python + + # list of patches (mapped domains) + Omega_0 = F0(A) + Omega_1 = F1(A) + Omega_2 = F2(A) + Omega_3 = F3(A) + + patches = [Omega_0, Omega_1, Omega_2, Omega_3] + + # integers representing the axes + axis_0 = 0 + axis_1 = 1 + axis_2 = 2 + + # integers representing the extremities: left (-1) or right (+1) + ext_0 = -1 + ext_1 = +1 + + # A connectivity list in 2D + connectivity = [((Omega_0, axis_0, ext_0), (Omega_1, axis_0, ext_1), 1), + ((Omega_1, axis_1, ext_0), (Omega_3, axis_1, ext_1), -1), + ((Omega_0, axis_1, ext_0), (Omega_2, axis_1, ext_1), 1), + ((Omega_2, axis_0, ext_0), (Omega_3, axis_0, ext_1), -1)] + + # alternative option (passing interface patches by their indices in the patches list): + connectivity = [((0, axis_0, ext_0), (1, axis_0, ext_1), 1), + ((1, axis_1, ext_0), (3, axis_1, ext_1), -1), + ((0, axis_1, ext_0), (2, axis_1, ext_1), 1), + ((2, axis_0, ext_0), (3, axis_0, ext_1), -1)] + + # A connectivity list in 3D + connectivity = [((Omega_0, axis_0, ext_1), (Omega_1, axis_0, ext_0), ( 1, 1, 1)), + ((Omega_0, axis_1, ext_1), (Omega_2, axis_1, ext_0), ( 1, -1, 1)), + ((Omega_1, axis_1, ext_1), (Omega_3, axis_1, ext_0), (-1, 1, -1)), + ((Omega_2, axis_0, ext_1), (Omega_3, axis_0, ext_0), (-1, 1, 1))] + + # alternative option (passing interface patches by their indices in the patches list): + connectivity = [((0, axis_0, ext_1), (1, axis_0, ext_0), ( 1, 1, 1)), + ((0, axis_1, ext_1), (2, axis_1, ext_0), ( 1, -1, 1)), + ((1, axis_1, ext_1), (3, axis_1, ext_0), (-1, 1, -1)), + ((2, axis_0, ext_1), (3, axis_0, ext_0), (-1, 1, 1))] + + # the multi-patch domain + Omega = Domain.join(patches=patches, connectivity=connectivity, name='Omega') """ assert isinstance(patches, (tuple, list)) assert isinstance(connectivity, (tuple, list)) From c8300426e6be15b16e0b52afb5a46bd4507dc51b Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 10:20:33 +0200 Subject: [PATCH 07/17] readme venv instructions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb47ff2c..49d96438 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ The documentation dependencies are installed separately, and the HTML pages are built with warnings treated as errors: ```bash -python3 -m pip install --editable ".[docs]" -python3 -m sphinx -W --keep-going -b html doc doc/_build/html +pip install --editable ".[docs]" +sphinx-build -W --keep-going -b html doc doc/_build/html ``` ## For developers From a374c0c81f8317fe94400f24bea7b3c6431c2110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaman=20G=C3=BC=C3=A7l=C3=BC?= Date: Thu, 1 Oct 2026 11:28:00 +0200 Subject: [PATCH 08/17] Remove duplication from AUTHORS file --- AUTHORS | 1 - 1 file changed, 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index d61f2333..9fbe15ef 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,7 +8,6 @@ Contributors * Ahmed Ratnani (original author) * Said Hadjout (original author) * Antoine Lavandier -* Martin Campos Pinto * Tom Caruso * Alisa Kirkinskaia * Elena Moral Sánchez From 9c191e76c7c6e7b06af1f03ae9a62590337ea650 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:33:14 +0200 Subject: [PATCH 09/17] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaman Güçlü --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 49d96438..52f973c8 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,9 @@ sphinx-build -W --keep-going -b html doc doc/_build/html Because many important SymPDE features are only tested in Psydac, new pull requests should also be tested against the Psydac test suite. This can be done by opening a pull request in Psydac whose only change is to install the corresponding SymPDE branch. -To achieve this, modify the line corresponding to `sympde` in Psydac's `pyproject.toml` file. +Because many important SymPDE features are only tested in PSYDAC, new pull requests should also be tested against the PSYDAC test suite. +This can be done by opening a pull request in PSYDAC whose only change is to install the corresponding SymPDE branch. +To achieve this, modify the line corresponding to `sympde` in PSYDAC's `pyproject.toml` file. For instance, to test a new SymPDE branch called `my_feature`, use: From 527ea1832b49b3e1817b1a47e10c8e717192c345 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:33:33 +0200 Subject: [PATCH 10/17] Update sympde/topology/mapping.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaman Güçlü --- sympde/topology/mapping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sympde/topology/mapping.py b/sympde/topology/mapping.py index f0947038..f53bb715 100644 --- a/sympde/topology/mapping.py +++ b/sympde/topology/mapping.py @@ -757,7 +757,7 @@ def eval(cls, F): mapping object Returns - ---------- + ------- expr : ImmutableDenseMatrix the jacobian matrix """ From 75171d404a8dedb0d8b1990e34d28a306d305de7 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:33:53 +0200 Subject: [PATCH 11/17] Update sympde/topology/mapping.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaman Güçlü --- sympde/topology/mapping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sympde/topology/mapping.py b/sympde/topology/mapping.py index f53bb715..6d8af2e9 100644 --- a/sympde/topology/mapping.py +++ b/sympde/topology/mapping.py @@ -808,7 +808,7 @@ def eval(cls, F, v): the basis function Returns - ---------- + ------- expr : Tuple the covariant transformation """ From 4680f6278263a021945e1e1deb7605c34c008a02 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:34:03 +0200 Subject: [PATCH 12/17] Update sympde/topology/mapping.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaman Güçlü --- sympde/topology/mapping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sympde/topology/mapping.py b/sympde/topology/mapping.py index 6d8af2e9..585dd85e 100644 --- a/sympde/topology/mapping.py +++ b/sympde/topology/mapping.py @@ -857,7 +857,7 @@ def eval(cls, F, v): the basis function Returns - ---------- + ------- expr : Tuple the contravariant transformation """ From f63ef533e1cda948017787c15c8af0f389f6cd77 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:35:21 +0200 Subject: [PATCH 13/17] Update .github/workflows/documentation.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaman Güçlü --- .github/workflows/documentation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index cd9a787e..8df2dc3d 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -55,10 +55,10 @@ jobs: -b html doc doc/_build/html - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@v6 - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: path: 'doc/_build/html' @@ -72,4 +72,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 From 3f5eea8a2a15f5c23e75fa99535ec7268ec8a58a Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 11:42:10 +0200 Subject: [PATCH 14/17] use raw docstring --- doc/conf.py | 1 + sympde/topology/domain.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index f3a8bc45..24786ce0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -55,6 +55,7 @@ # # source_suffix = ['.rst', '.md'] source_suffix = {'.rst': 'restructuredtext'} +default_role = 'py:obj' # The master toctree document. master_doc = 'index' diff --git a/sympde/topology/domain.py b/sympde/topology/domain.py index 2451b547..4fe4ebce 100644 --- a/sympde/topology/domain.py +++ b/sympde/topology/domain.py @@ -442,11 +442,11 @@ def join(cls, patches, connectivity, name): Atomic patches in the joined domain. connectivity : sequence of tuple - Interface descriptions of the form ``(minus, plus, orientation)``. - Each side is ``(patch, axis, ext)``, where ``patch`` is a patch - object or its index in ``patches`` and ``ext`` is ``-1`` or ``1``. - A 2D orientation is ``-1`` or ``1``. A 3D orientation is a tuple - of three values, each equal to ``-1`` or ``1``. + Interface descriptions of the form `(minus, plus, orientation)`. + Each side is `(patch, axis, ext)`, where `patch` is a patch + object or its index in `patches` and `ext` is `-1` or `1`. + A 2D orientation is `-1` or `1`. A 3D orientation is a tuple + of three values, each equal to `-1` or `1`. name : str Name of the domain. From 90226e5ec30689a36aaa6db3e60f33068ad4ed1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaman=20G=C3=BC=C3=A7l=C3=BC?= Date: Thu, 1 Oct 2026 14:14:54 +0200 Subject: [PATCH 15/17] Add "Unreleased" section to CHANGELOG.md --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c481f87e..cabb0b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. +## Unreleased + +### Added + +### Changed + +### Deprecated + +### Deprecated + +### Removed + ## [0.20.0] - 2026-09-07 ### Added From 4421d790a0da29bceb5ddeeb4772b7de5aa7429b Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 16:37:46 +0200 Subject: [PATCH 16/17] add unreleased changes --- CHANGELOG.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cabb0b2d..b05f4bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,25 @@ All notable changes to this project will be documented in this file. ### Added +- [DEVELOPER] Test supported Python versions 3.9 through 3.14 on the latest Ubuntu and macOS runners. +- [DEVELOPER] Add separate documentation dependencies and a strict Sphinx workflow that checks pull requests and publishes the documentation to GitHub Pages. +- [DEVELOPER] Add an `AUTHORS` file listing the project maintainers and contributors. + ### Changed -### Deprecated +- Convert the README to Markdown and expand the installation, testing, and documentation-build instructions. +- [DEVELOPER] Modernize the package metadata and consolidate the pytest and coverage configuration in `pyproject.toml`. +- [DEVELOPER] Modernize the Sphinx configuration, API-documentation generation, and API docstring markup. + +### Fixed -### Deprecated +- #140: Fix the rendering of the `Domain.join()` API documentation. +- #166: Restore warning-free documentation builds, including bibliography and mathematical notation support. ### Removed +- [DEVELOPER] Remove obsolete CI configuration, the standalone pytest configuration, and the legacy test runner script. + ## [0.20.0] - 2026-09-07 ### Added From bf32bd09b523116948451402e8f788da4e125197 Mon Sep 17 00:00:00 2001 From: Frederik Schnack Date: Thu, 1 Oct 2026 17:17:02 +0200 Subject: [PATCH 17/17] Changelog v2 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b05f4bc6..89430b40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ All notable changes to this project will be documented in this file. ### Added -- [DEVELOPER] Test supported Python versions 3.9 through 3.14 on the latest Ubuntu and macOS runners. +- [DEVELOPER] Add a `CHANGELOG.md` file listing changes between different versions. +- [DEVELOPER] Add Python version 3.14 to the testing workflow. - [DEVELOPER] Add separate documentation dependencies and a strict Sphinx workflow that checks pull requests and publishes the documentation to GitHub Pages. - [DEVELOPER] Add an `AUTHORS` file listing the project maintainers and contributors. @@ -25,6 +26,8 @@ All notable changes to this project will be documented in this file. - [DEVELOPER] Remove obsolete CI configuration, the standalone pytest configuration, and the legacy test runner script. +### Deprecated + ## [0.20.0] - 2026-09-07 ### Added