diff --git a/.github/workflows/joss.yml b/.github/workflows/joss.yml new file mode 100644 index 0000000..a4416cc --- /dev/null +++ b/.github/workflows/joss.yml @@ -0,0 +1,34 @@ +name: JOSS Paper +on: + push: + paths: + - doc/paper/** + - .github/workflows/joss.yml + schedule: + - cron: '17 3 * * 0' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + paper: + runs-on: ubuntu-latest + name: Paper Draft + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Build draft PDF + uses: openjournals/openjournals-draft-action@master + with: + journal: joss + paper-path: doc/paper/paper.md + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: paper + path: doc/paper/paper.pdf + +# vim: sw=4 diff --git a/doc/paper/.gitignore b/doc/paper/.gitignore new file mode 100644 index 0000000..ec6a328 --- /dev/null +++ b/doc/paper/.gitignore @@ -0,0 +1,5 @@ +.inara +joss +*.pdf +*.tex +latex.out diff --git a/doc/paper/Makefile b/doc/paper/Makefile new file mode 100644 index 0000000..c5b3ecf --- /dev/null +++ b/doc/paper/Makefile @@ -0,0 +1,77 @@ +OUTDIR?=latex.out +TEXMK?=latexmk -verbose -pdflua -output-directory=$(OUTDIR) + +INARA_PATH := .inara +TARGET_FOLDER := $$(pwd)/publishing-artifacts + +JOURNAL := joss +INARA_DATA_PATH := $(INARA_PATH)/data +OPENJOURNALS_PATH := $(INARA_PATH)/resources +ARTICLE_INFO_FILE = $(OPENJOURNALS_PATH)/default-article-info.yaml + +all: paper +.PHONY: all + +help: ## Show this help + @echo -e "\nSpecify a command. The choices are:\n" + @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-12s\033[m %s\n", $$1, $$2}' + @echo "" +.PHONY: help + +%.pdf: %.tex + PYTHONWARNINGS=ignore $(TEXMK) $< + @cp $(OUTDIR)/$@ . + +paper: paper.md paper.bib ## Compile paper to PDF using JOSS tools + mkdir -p $(TARGET_FOLDER) + make -C $(INARA_PATH) -B resources/footer.csl + INARA_ARTIFACTS_PATH=$(TARGET_FOLDER)/ pandoc \ + --data-dir=$(INARA_DATA_PATH) \ + --defaults=$(INARA_DATA_PATH)/defaults/shared.yaml \ + --defaults=$(INARA_DATA_PATH)/defaults/pdf.yaml \ + --defaults=$(OPENJOURNALS_PATH)/$(JOURNAL)/defaults.yaml \ + --resource-path=$$(pwd):$(OPENJOURNALS_PATH) \ + --metadata=article-info-file=$(ARTICLE_INFO_FILE) \ + --variable=$(JOURNAL) \ + --output=$@.tex \ + $< + make paper.pdf +.PHONY: paper + +inara: ## Download JOSS tools (inara) for compilation + @if [ ! -d "$(INARA_PATH)" ]; then \ + git clone git@github.com:openjournals/inara.git $(INARA_PATH); \ + else \ + cd $(INARA_PATH) && git pull origin main; \ + fi + mkdir -p joss + cp $(INARA_PATH)/resources/joss/logo.png joss/logo.png +.PHONY: inara + +tidy: paper.bib ## Clean up bibliography (with bibtex-tidy) + @bibtex-tidy \ + --modify \ + --sort \ + --sort-fields \ + --drop-all-caps \ + --merge last \ + --numeric \ + --strip-enclosing-braces \ + --trailing-commas \ + --blank-lines \ + --remove-empty-fields \ + --remove-dupe-fields \ + --wrap \ + $< +.PHONY: tidy + +clean: ## Remove temporary files generated by JOSS tools + rm -rf $(TARGET_FOLDER) + rm -rf $(OUTDIR) +.PHONY: clean + +purge: clean + rm -rf paper.pdf + rm -rf .inara +.PHONY: purge + diff --git a/doc/paper/images/Makefile b/doc/paper/images/Makefile new file mode 100644 index 0000000..93a31eb --- /dev/null +++ b/doc/paper/images/Makefile @@ -0,0 +1,41 @@ +OUTDIR?=latex.out +TEXMK?=latexmk -verbose -pdf -output-directory=$(OUTDIR) +PYTHON?=python -X dev + +all: figures + +help: ## Show this help + @echo -e "\nSpecify a command. The choices are:\n" + @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-12s\033[m %s\n", $$1, $$2}' + @echo "" +.PHONY: help + +%.pdf: %.tex + PYTHONWARNINGS=ignore $(TEXMK) $< + @cp $(OUTDIR)/$@ . + +%.png: %.pdf + magick \ + -density 600 \ + $< \ + -quality 100 \ + -background white \ + -alpha remove \ + $@ + +quadrature_rules.png: + magick \ + quadrature_rule_vr_order_11_2d.png \ + \( -size 900x`identify -format "%h" quadrature_rule_vr_order_11_2d.png` xc:white \) \ + quadrature_rule_wv_order_11_2d.png \ + +append \ + -background white \ + quadrature_rules.png + +figures: simplices quadratures ## Compile all figures + for img in simplices.png pkdo-2d.png quadrature_rules.png; do \ + magick "$${img}" -trim +repage "$${img}"; \ + done + +simplices: simplices.png +quadratures: quadrature_rules.png diff --git a/doc/paper/images/pkdo-2d.png b/doc/paper/images/pkdo-2d.png new file mode 100644 index 0000000..2df581f Binary files /dev/null and b/doc/paper/images/pkdo-2d.png differ diff --git a/doc/paper/images/quadrature_rule_vr_order_11_2d.png b/doc/paper/images/quadrature_rule_vr_order_11_2d.png new file mode 100644 index 0000000..1ce388b Binary files /dev/null and b/doc/paper/images/quadrature_rule_vr_order_11_2d.png differ diff --git a/doc/paper/images/quadrature_rule_wv_order_11_2d.png b/doc/paper/images/quadrature_rule_wv_order_11_2d.png new file mode 100644 index 0000000..a5a3d69 Binary files /dev/null and b/doc/paper/images/quadrature_rule_wv_order_11_2d.png differ diff --git a/doc/paper/images/quadrature_rules.png b/doc/paper/images/quadrature_rules.png new file mode 100644 index 0000000..3076fea Binary files /dev/null and b/doc/paper/images/quadrature_rules.png differ diff --git a/doc/paper/images/simplices.png b/doc/paper/images/simplices.png new file mode 100644 index 0000000..91324dc Binary files /dev/null and b/doc/paper/images/simplices.png differ diff --git a/doc/paper/images/simplices.tex b/doc/paper/images/simplices.tex new file mode 100644 index 0000000..de25285 --- /dev/null +++ b/doc/paper/images/simplices.tex @@ -0,0 +1,66 @@ +\documentclass[tikz]{standalone} +\usepackage{tikz} +\usepackage{amsmath} + +\renewcommand\familydefault{\sfdefault} + +\begin{document} +\large + +\begin{tikzpicture}[scale=2] +\definecolor{VertexBlue}{HTML}{4C72B0}; +\definecolor{LineBlue}{HTML}{4C72B0}; +\definecolor{FaceBlue}{HTML}{D2DBEB}; +\definecolor{FaceDarkBlue}{HTML}{C0CDE3}; + +% 1-simplex +\begin{scope}[shift={(0, 0)}] +\draw[LineBlue, ultra thick] (0, 1) -- (1.5, 1); +\fill[VertexBlue] (0, 1) circle (2pt); +\fill[VertexBlue] (1.5, 1) circle (2pt); +\node at (0.75, -0.5) {1-simplex}; +\end{scope} + +% 2-simplex +\begin{scope}[shift={(3, 0)}] +\coordinate (A) at (0, 0); +\coordinate (B) at (2, 0); +\coordinate (C) at (0, 2); + +\fill[FaceBlue] (A) -- (B) -- (C) -- cycle; +\draw[LineBlue, ultra thick] (A) -- (B) -- (C) -- cycle; +\foreach \p in {A,B,C} + \fill[VertexBlue] (\p) circle (2pt); + +\node at (1, -0.5) {2-simplex}; +\end{scope} + +% 3-simplex +\begin{scope}[shift={(6.5, 0)}] +\coordinate (O) at (0, 0.5, 0); +\coordinate (X) at (2, 0.5, 0); +\coordinate (Y) at (0.75, 2, 0); +\coordinate (Z) at (0.75, 0.0, 0.0); + +% faces +\fill[FaceBlue] (O) -- (X) -- (Y) -- cycle; +\fill[FaceBlue] (O) -- (X) -- (Z) -- cycle; +\fill[FaceDarkBlue] (X) -- (Y) -- (Z) -- cycle; +\fill[FaceBlue] (Y) -- (O) -- (Z) -- cycle; + +% edges +\draw[LineBlue, ultra thick] (X) -- (Y) -- (O); +\draw[LineBlue!60, ultra thick] (O) -- (X); +\draw[LineBlue, ultra thick] (O) -- (Z); +\draw[LineBlue, ultra thick] (X) -- (Z); +\draw[LineBlue, ultra thick] (Y) -- (Z); + +% vertices +\foreach \p in {O,X,Y,Z} + \fill[VertexBlue] (\p) circle (2pt); + +\node at (1, -0.5, 0) {3-simplex}; +\end{scope} +\end{tikzpicture} + +\end{document} diff --git a/doc/paper/paper.bib b/doc/paper/paper.bib new file mode 100644 index 0000000..c17d460 --- /dev/null +++ b/doc/paper/paper.bib @@ -0,0 +1,347 @@ +@article{Bezanson2017, + title = {Julia: {A} Fresh Approach to Numerical Computing}, + author = {Jeff Bezanson and Alan Edelman and Stefan Karpinski and Viral B. Shah}, + year = 2017, + journal = {{SIAM} Review}, + publisher = {Society for Industrial \& Applied Mathematics {(SIAM)}}, + volume = 59, + pages = {65--98}, + doi = {10.1137/141000671}, + issue = 1, +} + +@book{Brenner2007, + title = {The Mathematical Theory of Finite Element Methods}, + author = {Susanne Brenner and Ridgway Scott}, + year = 2007, + publisher = {Springer Science \& Business Media}, + isbn = 9780387759333, +} + +@article{Dubiner1991, + title = {Spectral Methods on Triangles and Other Domains}, + author = {M. Dubiner}, + year = 1991, + journal = {Journal of Scientific Computing}, + publisher = {Springer Science and Business Media {LLC}}, + volume = 6, + pages = {345--390}, + doi = {10.1007/bf01060030}, + issue = 4, +} + +@software{FIAT, + title = {{FIAT}: 2025.4.0}, + author = { + Mikl\'{o}s Homolya and Pablo Brubeck and David A. Ham and Robert Kirby and + Lawrence Mitchell and Jan Blechta and Marie E Rognes and Garth N. Wells and + Anders Logg and cyruscycheng21 and Thomas H. Gibson and Johannes Ring and + Ivan Yashchuk and Justincrum and k-b-oelgaard and ksagiyam and Chris + Richardson and Nico Schl\"{o} mer and Reuben W. Nixon-Hill and Lizao Li and + Aslak Bergersen and Connor Ward and Nicholas Barton and Colin J Cotter and + Patrick E. Farrell and Jack S. Hale and FAznaran and Matthew Knepley and + Florian Rathgeber and Matthew Scroggs + }, + year = 2025, + month = apr, + publisher = {Zenodo}, + doi = {10.5281/zenodo.15302339}, + url = {https://doi.org/10.5281/zenodo.15302339}, + version = {2025.4.0}, +} + +@software{FInAT, + title = {{FInAT}: {A} smarter library of finite elements}, + author = { + David A. Ham and Mikl\'{o}s Homolya and Robert Kirby and Lawrence Mitchell + and Pablo Brubeck and cyruscycheng21 and FAznaran and ksagiyam and Matthew + Scroggs and Patrick E. Farrell and Justincrum and Connor Ward and celdred + and Thomas Bendall and Jack Betteridge and FabianL1908 + }, + year = 2025, + month = mar, + publisher = {Zenodo}, + doi = {10.5281/zenodo.15114385}, + url = {https://doi.org/10.5281/zenodo.15114385}, + version = {Firedrake\_20250331.0}, +} + +@article{Geuzaine2009, + title = { + {Gmsh}: {A} 3-D finite element mesh generator with built-in pre-and + post-processing facilities + }, + author = {Geuzaine, Christophe and Remacle, Jean-Fran{\c{c}}ois}, + year = 2009, + journal = {International Journal for Numerical Methods in Engineering}, + publisher = {Wiley Online Library}, + volume = 79, + number = 11, + doi = {10.1002/nme.2579}, + pages = {1309--1331}, +} + +@software{Grudge, + title = {{Grudge}: {A}n environment for Discontinuous {Galerkin} discretizations}, + author = {Andreas Kl\"{o}ckner and others}, + year = 2025, + url = {https://github.com/inducer/grudge}, + version = {hash:193100a}, +} + +@article{Grundmann1978, + title = {Invariant Integration Formulas for the N-Simplex by Combinatorial Methods}, + author = {A. Grundmann and H. M. M\"{o}ller}, + year = 1978, + journal = {{SIAM} Journal on Numerical Analysis}, + publisher = {Society for Industrial \& Applied Mathematics {(SIAM)}}, + volume = 15, + pages = {282--290}, + doi = {10.1137/0715019}, + issue = 2, +} + +@book{Hesthaven2007, + title = {Nodal Discontinuous {Galerkin} Methods}, + author = {J. S. Hesthaven and T. Warburton}, + year = 2007, + publisher = {Springer Science \& Business Media}, + isbn = 9780387720678, +} + +@article{Isaac2020, + title = { + Recursive, Parameter-Free, Explicitly Defined Interpolation Nodes for + Simplices + }, + author = {Tobin Isaac}, + year = 2020, + journal = {{SIAM} Journal on Scientific Computing}, + publisher = {Society for Industrial \& Applied Mathematics {(SIAM)}}, + volume = 42, + pages = {A4046--a4062}, + doi = {10.1137/20m1321802}, + issue = 6, +} + +@article{Jaskowiec2021, + title = {High-order Symmetric Cubature Rules for Tetrahedra and Pyramids}, + author = {J. Ja\'{s}kowiec and N. Sukumar}, + year = 2021, + journal = {International Journal for Numerical Methods in Engineering}, + publisher = {Wiley}, + volume = 122, + pages = {148--171}, + doi = {10.1002/nme.6528}, + issue = 1, +} + +@article{Julia2018, + title = {Julia Subtyping: {A} Rational Reconstruction}, + author = { + Francesco Zappa Nardelli and Julia Belyakova and Artem Pelenitsyn and + Benjamin Chung and Jeff Bezanson and Jan Vitek + }, + year = 2018, + journal = {Proceedings of the {ACM} on Programming Languages}, + publisher = {Association for Computing {Machinery} {(ACM)}}, + volume = 2, + pages = {1--27}, + doi = {10.1145/3276483}, + url = {https://dl.acm.org/doi/10.1145/3276483}, + issue = {Oopsla}, +} + +@article{Orszag1980, + title = {Spectral Methods for Problems in Complex Geometries}, + author = {Steven A. Orszag}, + year = {1980}, + journal = {Journal of Computational Physics}, + publisher = {Elsevier {BV}}, + volume = {37}, + pages = {70--92}, + doi = {10.1016/0021-9991(80)90005-4}, + issue = {1}, +} + +@software{Pymbolic, + title = {{Pymbolic}: {A} package to do symbolic operations for code generation}, + author = { + Kl\"{o}ckner, Andreas and Wala, Matt and Fernando, Isuru and Kulkarni, Kaushik + and Fikl, Alex and Weiner, Zach and Kempf, Dominic and Ham, David A. and + Mitchell, Lawrence and Wilcox, Lucas C and Diener, Matthias and Kapyshin, + Pavlo and Raksi, Reno and Gibson, Thomas H. + }, + year = 2024, + month = dec, + publisher = {Zenodo}, + doi = {10.5281/zenodo.14526145}, + url = {https://doi.org/10.5281/zenodo.14526145}, + version = {v2024.2.2}, +} + +@software{PyNucleus, + title = { + {PyNucleus}: {A} finite element code that specifically targets nonlocal + operators + }, + author = {Glusa, Christian}, + year = 2021, + url = {https://github.com/sandialabs/PyNucleus}, + institution = {Sandia National Lab (SNL-NM), Albuquerque, NM (United States)}, +} + +@software{Pytential, + title = {{Pytential}: {E}valuate layer and volume potentials accurately}, + author = {Andreas Kl\"{o}ckner and others}, + year = 2025, + month = may, + url = {https://github.com/inducer/pytential}, + version = {hash:7395b97f}, +} + +@software{Python_AST, + title = {{ast} --- Abstract Syntax Trees}, + author = {{Python Software Foundation}}, + year = 2024, + url = {https://docs.python.org/3/library/ast.html}, +} + +@software{QuadPy, + title = {{QuadPy}: {N}umerical integration (quadrature, cubature) in {Python}}, + author = { + Nico Schl\"{o}mer and Nick Papior and Darius Arnold and Jan Blechta and + Rasmus Zetter + }, + year = 2021, + publisher = {Zenodo}, + doi = {10.5281/zenodo.5541216}, + version = {v0.16.10}, +} + +@software{StartUpDG, + title = {{StartUpDG.jl}: {R}eference elements and physical meshes for {DG}}, + author = { + Jesse Chan and David Knapp and Mason McCallum and Hendrik Ranocha and + Vincent X. Wang and Johannes Markert + }, + year = 2024, + url = {https://github.com/jlchan/StartUpDG.jl}, + version = {v1.1.5}, +} + +@software{SymEngine, + title = {{SymEngine}: {A} fast symbolic manipulation library written in {C++}}, + author = { + O. \v{C}ert\'{\i}k and I. Fernando and S. Garg and T. Rathnayake and others + }, + year = 2013, + url = {https://github.com/symengine/symengine}, +} + +@article{SymPy, + title = {{SymPy}: {S}ymbolic computing in {Python}}, + author = { + Meurer, Aaron and Smith, Christopher P and Paprocki, Mateusz and + \v{C}ert\'{\i}k, Ond\v{r}ej and Kirpichev, Sergey B and Rocklin, Matthew + and Kumar, AMiT and Ivanov, Sergiu and Moore, Jason K and Singh, Sartaj and + others + }, + year = 2017, + journal = {PeerJ Computer Science}, + publisher = {PeerJ Inc.}, + volume = 3, + pages = {e103}, +} + +@book{Trefethen2020, + title = {Approximation Theory and Approximation Practice}, + author = {Lloyd N. Trefethen}, + year = 2020, + publisher = {Society for Industrial and Applied Mathematics}, + isbn = 9781611975932, +} + +@article{Vioreanu2014, + title = {Spectra of Multiplication Operators as a Numerical Tool}, + author = {B. Vioreanu and V. Rokhlin}, + year = 2014, + journal = {{SIAM} Journal on Scientific Computing}, + publisher = {Society for Industrial \& Applied Mathematics {(SIAM)}}, + volume = 36, + pages = {A267--a288}, + doi = {10.1137/110860082}, + issue = 1, +} + +@article{Waldvogel2006, + title = { + Fast Construction of the {Fej\'{e}r} and {Clenshaw–Curtis} Quadrature Rules + }, + author = {J. Waldvogel}, + year = 2006, + journal = {BIT Numerical Mathematics}, + publisher = {Springer Science and Business Media {LLC}}, + volume = 46, + pages = {195--202}, + doi = {10.1007/s10543-006-0045-4}, + issue = 1, +} + +@article{Warburton2007, + title = {An Explicit Construction of Interpolation Nodes on the Simplex}, + author = {T. Warburton}, + year = 2007, + journal = {Journal of Engineering Mathematics}, + publisher = {Springer Nature}, + volume = 56, + pages = {247--262}, + doi = {10.1007/s10665-006-9086-6}, + issue = 3, +} + +@article{Wicaksono2025, + title = {{Minterpy}: {M}ultivariate polynomial interpolation in {Python}}, + author = { + Damar Wicaksono and Uwe Hernandez Acosta and Sachin Krishnan Thekke Veettil + and Jannik Kissinger and Michael Hecht + }, + year = 2025, + journal = {Journal of Open Source Software}, + publisher = {The Open Journal}, + volume = 10, + number = 109, + pages = 7702, + doi = {10.21105/joss.07702}, + url = {https://doi.org/10.21105/joss.07702}, +} + +@article{Witherden2015, + title = { + On the Identification of Symmetric Quadrature Rules for Finite Element + Methods + }, + author = {F. D. Witherden and P. E. Vincent}, + year = 2015, + journal = {Computers \& Mathematics With Applications}, + publisher = {Elsevier {BV}}, + volume = 69, + pages = {1232--1241}, + doi = {10.1016/j.camwa.2015.03.017}, + issue = 10, +} + +@article{Xiao2010, + title = { + A Numerical Algorithm for the Construction of Efficient Quadrature Rules in + Two and Higher Dimensions + }, + author = {H. Xiao and Z. Gimbutas}, + year = 2010, + journal = {Computers \& Mathematics With Applications}, + publisher = {Elsevier {BV}}, + volume = 59, + pages = {663--676}, + doi = {10.1016/j.camwa.2009.10.027}, + issue = 2, +} diff --git a/doc/paper/paper.md b/doc/paper/paper.md new file mode 100644 index 0000000..0ada3d9 --- /dev/null +++ b/doc/paper/paper.md @@ -0,0 +1,171 @@ +--- +breaks: false +title: 'modepy: Basis Functions, Interpolation, and Quadrature (not just) for Finite Elements' +tags: + - Python + - approximation theory +authors: + - given-names: Andreas + surname: Klöckner + corresponding: true + orcid: 0000-0003-1228-519X + affiliation: 1 + - given-names: Alexandru + surname: Fikl + orcid: 0000-0002-0552-5936 + affiliation: 2 + - given-names: Jacob Xiaoyu + surname: Wei + orcid: 0000-0001-7063-7865 + affiliation: 3 + - given-names: Thomas H. + surname: Gibson + orcid: 0000-0002-7978-6848 + affiliation: 4 + - given-names: Addison J. + surname: Alvey-Blanco + affiliation: 1 +affiliations: + - index: 1 + name: Siebel School of Computing and Data Science, University of Illinois at Urbana-Champaign, US + - index: 2 + name: Institute for Advanced Environmental Research (ICAM), West University of Timişoara, Romania + - index: 3 + name: Pathlit, US + - index: 4 + name: Advanced Micro Devices Inc., US +date: 1 May 2025 +bibliography: paper.bib + +--- + +# Summary + +`modepy` is a Python library for defining reference elements, equipping them with +appropriate approximation spaces, and numerically performing calculus operations +(derivatives, integrals) on those spaces. It is written in pure, type-annotated Python +3, offering comprehensive documentation and minimal runtime dependencies (mainly NumPy). + +`modepy` focuses on high-order accuracy --- given an element size $h$, this refers +to the asymptotic decay of the approximation error as $O(h^n)$, for $n \ge 3$, +assuming sufficient smoothness of the solution being approximated. For a problem +in $d$ dimensions, the number of unknowns scales as $O(h^{-d})$. Therefore, if +accuracy is desired at manageable cost, high-order methods are crucial. + +A popular approach for accurate approximation of functions on geometrically complex +domains is the use of *unstructured discretizations*, e.g. in the Finite Element +Method (FEM). The geometry is typically represented as a disjoint union (a "mesh") of +primitive geometric shapes, most often simplices and quadrilaterals. Given the means +to perform calculus operations on these *reference elements* and mapping functions +from them to the *global* elements, calculus operations become available on the entire +domain. These primitives are chiefly useful in the numerical solution of integral and +(partial) differential equations. Additional applications include computer graphics, +Computer Aided Design (CAD), and robotics. Those, in turn, can be used to model many +physical phenomena, including fluid flow, electromagnetism, and solid mechanics. +`modepy` has been used to construct FEM solvers [@Grudge; @PyNucleus] and integral +equation solvers [@Pytential] that run on both CPUs and GPUs. + +# Statement of need + +The functionality outlined above is often embedded in an ad-hoc manner in +larger codes, restricting scope and reusability. `modepy` addresses this +need by providing a reusable, generalizable, and composable implementation. + +There are several other libraries in the literature with similar goals, but +important differences and limitations. FInAT [@FInAT] (and the earlier FIAT +[@FIAT]) offers reference elements and basis functions, but is tightly coupled +to the FEniCS/Firedrake ecosystem. Similarly, `StartUpDG.jl` [@StartUpDG] has a +focus on the needs of discontinuous Galerkin FEM in the Trixi framework. `QuadPy` +[@QuadPy] provides access to quadrature rules, but it is no longer open source +and lacks `modepy`'s composability. `minterpy` [@Wicaksono2025], meanwhile, deals +exclusively with polynomial interpolation, with a focus on sparse grids. + +The solvers served by `modepy` typically have tight cost constraints, often adopting +HPC techniques (GPU, MPI, etc.). To facilitate separation of implementation and +high-performance concerns from the core numerical method, `modepy` adopts a two-pronged +approach. First, if it suffices to represent operations as data in matrix or tabular +form, execution of `modepy` code is not needed in a cost-constrained setting. For +example, nodes and bilinear forms on reference elements can generally be pre-computed +and tabulated. Second, if this tabulation approach falls short, `modepy` provides +data structures to reveal additional internal structure. + +Tensor product elements provide an example of this. In this instance, many operator +matrices permit a Kronecker product factorization that significantly reduces the +asymptotic complexity of a matrix-vector product in higher dimensions [@Orszag1980]. +`modepy` exposes functionality that allows reshaping degrees of freedom arrays to take +advantage of such factorizations. Another prominent example is the evaluation of basis +functions at points known only at runtime. To facilitate efficient evaluation, `modepy` +allows its functions to be "traced", in the sense of lazy or deferred evaluation. +The resulting expression graph is represented by the `pymbolic` [@Pymbolic] software +library, that can interoperate with Python ASTs [@Python_AST], SymPy [@SymPy], SymEngine +[@SymEngine], etc., for straightforward generation of high-performance code. + +# Overview + +The high-level concepts available in `modepy` are shapes (i.e. reference domains), +modes (i.e. the basis functions), and nodes (i.e. the degrees of freedom). These are +implemented in a user-extensible fashion using the `singledispatch` mechanism, with +inspiration taken from common idiomatic usage in Julia [@Bezanson2017]. + +## Shapes + +The geometry of a reference element is described in `modepy` by the `Shape` class. +Built-in support exists for `Simplex` and `Hypercube` geometries, encompassing +the commonly used interval, triangle, tetrahedron, quadrilateral, and hexahedral +shapes (see \autoref{FigureSimplices}). `TensorProductShape` can be used to compose +additional shapes (e.g. prims, as generated by, e.g. `gmsh` [@Geuzaine2009]). + +![Domains corresponding to the one-, two-, and three-dimensional simplices.](images/simplices.png){#FigureSimplices width="80%"} + +## Modes and Spaces + +To perform calculus operations, each reference element can be equipped with a function +space described by the `FunctionSpace` class. These represent a finite-dimensional +space of functions $\phi_i: D \to \mathbb{R}$, where $D$ is the reference element +domain, and no specific choice of basis. Predefined choices include the `PN` space, +containing polynomials of total degree at most $N$, and the `QN` space, containing +polynomials of maximum degree at most $N$. As with shapes, these spaces can be +combined using `TensorProductSpace`. A `Basis` objects is available separately, +giving access to basis functions and their derivatives, for, e.g., the monomials, +general Jacobi polynomials, and the Proriol-Koornwinder-Dubiner-Owens (PKDO) basis +from [@Dubiner1991] (see \autoref{FigurePKDO}). + +![PKDO basis functions for the triangle.](images/pkdo-2d.png){#FigurePKDO width="80%"} + +## Nodes + +A final component in an FEM discretization [@Brenner2007, Section 3.1] is a set of +'degrees of freedom' ('DOFs') that uniquely identify a certain function in the span of +a basis. `modepy` supports modal DOFs (i.e. basis coefficients) and nodal DOFs (i.e. +function or derivative values at a point). On simplices, the "warp-and-blend" nodes +[@Warburton2007] are available, and on the hypercube, standard tensor product nodes +are constructed from one-dimensional Legendre-Gauss(-Lobatto) nodes. `modepy` can also +directly interoperate with the `recursivenodes` library described in [@Isaac2020], +which offers additional well-conditioned nodes on the simplex. + +## Quadrature + +`modepy` also offers a wide array of quadrature rules that can be used on each reference +element. For the interval, Clenshaw--Curtis, Fejér, and Jacobi-Gauss(-Lobatto) are +provided. Many more state-of-the-art rules are available, typically up to high order +$n > 20$ from [@Grundmann1978;@Vioreanu2014;@Xiao2010;@Jaskowiec2021;@Witherden2015] +(see \autoref{FigureQuadrature}). There is also functionality [@Vioreanu2014] to allow +constructing novel quadratures on a given domain. + +![(left) Vioreanu--Rokhlin quadrature points of order 11 and (right) Witherden--Vincent quadrature points of order 11.](images/quadrature_rules.png){#FigureQuadrature width="50%"} + +## Matrices + +`modepy`'s functionality is rounded out by various tabulation and matrix +generation functions. This includes the ability to tabulate operator matrices +for fairly general bilinear forms used in FEM. + +# Acknowledgements + +A. Fikl was supported by the Office of Naval Research (ONR) as part of the +Multidisciplinary University Research Initiatives (MURI) Program, under Grant +Number *N00014-16-1-2617*. A. Klöckner was supported by the US National Science +Foundation under award number DMS-2410943, and by the US Department of Energy +under award number DE-NA0003963. + +# References diff --git a/doc/paper/typos.toml b/doc/paper/typos.toml new file mode 100644 index 0000000..13254b7 --- /dev/null +++ b/doc/paper/typos.toml @@ -0,0 +1,7 @@ +[files] +extend-exclude = ["*.bib"] + + +[default.extend-words] +# the space +PN = "PN" diff --git a/pyproject.toml b/pyproject.toml index adccae8..a90c4a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -130,7 +130,7 @@ nd = "nd" zerod = "zerod" [tool.typos.files] -extend-exclude = [] +extend-exclude = ["doc/paper/paper.bib"] [tool.basedpyright] pythonVersion = "3.10"