Repository navigation
High-order polar splines via homotopy operators (PolarFEEC.jl port) - #779
Open
max-models wants to merge 8 commits into
Open
max-models wants to merge 8 commits into
max-models wants to merge 8 commits into
Conversation
Port of the high-order polar FEEC construction of R. Remmerswaal (PolarFEEC.jl, NMPP seminar 2026) to struphy: - struphy.polar.homotopy: serial core with 1D B-spline/trigonometric spaces, 2D form spaces and mappings, Zernike bases, the 2D polar complex (free and Dirichlet, all enrichments, boundary-compatible homotopies), the 3D total complex and the homotopy solvers (2D curl-curl "free lunch", Poisson). - Derham integration: DerhamOptions(polar_method="homotopy", polar_regularity=r, ...) via PolarExtractionBlocksHomotopy; commuting projectors F~^T pi with an identity polar inter-/histopolation matrix. - New analytic domains PerturbedDiskCylinder and RoundedSquareCylinder. - Tutorials tutorial_polar_splines and dev_tutorial_polar_homotopy (talk figures and PolarFEEC.jl examples 04-06), example Poisson/polar_rounded_square with a convergence driver, docs section. - Tests of the core (cross-checked against PolarFEEC.jl), the 3D complex, the demos and the Derham layer. - Fixes: grad_1d_matrix for a single periodic basis function (was [[1]]), ImplicitDiffusion ignored PolarVector sources. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e for the high-order polar splines ScalarWave model and leapfrog propagator, Maxwell leapfrog, HelicalTube domain, HelicalVacuumField equilibrium (Cartesian equilibria finite on the polar axis), demos for PolarFEEC.jl examples 01-03/07/08 and the wave studies of the talk, examples, tests, tutorials and docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
|
It seems the code was ported entirely, without making use of struphy's existing B-spline functionality. Similarly, it seems the existing polar construction still exists, which should (this should be verified) coincide exactly with setting regularity == 1 in the general framework. It seems only the mappings that come with the PolarFEEC package are suppoted; instead the mappings from struphy's existing geometry should be supported. |
The general polar construction is the only one: polar_splines=True gives polar splines of regularity polar_regularity (default 1), which spans the former C1 spaces. Removes PolarExtractionBlocksC1, the hard-coded C1 layout, the C1 projector Kronecker solvers and the C1 shift of the projection grids; polar_method and polar_poloidal_solver are deprecated. The central polar basis is scaled to the polar rings (conditioning under refinement). Fixes the local branch of the 5D current coupling, guards stored eigenfunctions against the old layout, and adds the tutorial 'Polar splines in the Struphy de Rham complex'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DerhamSpace1D wraps the feectools spline spaces of the Derham complex (basis values, grad_1d_matrix, the projection grids of get_pts_and_wts); the polar algebra and the 2D form layer take a coefficient layout (Struphy's i*ny+j or PolarFEEC.jl's), so the Derham blocks need no value matching or permutation. The cross-section evaluates the domain once per tensor grid, must be planar, and warns for regularity >= 2 when it changes shape along eta3. Tests compare the Struphy-ordered complex with the reference construction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and move the old core to the tests
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

High-order polar splines of arbitrary regularity 𝔯 at the pole, built with Poincaré homotopy operators: a port of R. Remmerswaal's PolarFEEC.jl and of the methods in the NMPP seminar talk (2026). They are available as
C¹ (
polar_method="c1") remains the default and is unchanged.Solves the following issue(s):
None
Serial core:
struphy.polar.homotopyA pure numpy/scipy port of the algorithms of PolarFEEC.jl, with its conventions.
spaces1d: clamped and periodic B-splines and trigonometric spaces, each with a derivative-scaled companion and exact derivative matrices.forms2d: tensor-product and physical 2D form spaces, with commuting and L² projections.mappings: disk-like mappings.polynomials: the Zernike basis and the centre-shifted polynomial basis.complex2d:PolarComplex2D, which builds:cochain_chain,cochainandnone;complex3d:PolarComplex3D, the total complex with the 1D complex in η₃. It has the cohomology of the solid torus: [1,1,0,0] free and [0,0,1,1] Dirichlet.solvers: Poisson and curl–curl in the homotopy gauge. The 2D curl–curl "free lunch" is one M̄₂ solve followed by h₂.Core changes
DerhamOptions: new fieldspolar_method,polar_regularity,polar_enrichment,polar_polynomial_projectionandpolar_cross_section.PolarExtractionBlocksHomotopy(polar/homotopy/derham_blocks.py) provides the blocks ofstruphy.polar.linear_operatorsfor the 3D total complex. InPolarDerhamSpace:Nel2 % 3 == 0, p ≥ 2) apply only to C¹;mpi_dims_mask=(False, True, True).CommutingProjector: the homotopy path is the tensor-product projection followed by F̃ᵀ. The polar inter-/histopolation matrix is the identity, and nopolar_shiftis needed. The C¹ path is unchanged.HollowCylinder(a1=0),HollowTorus(a1=0),IGAPolarTorus, and the new domains:PerturbedDiskCylinder(kind_map 23) andRoundedSquareCylinder(24), with pyccel and CUDA kernels;HelicalTube, a spline mapping with the presets"stellarator"and"islands".HelicalVacuumField: a single helical harmonic, B = B₀∇(z + δ I_m(kr) sin(mθ − kz)/k). It evaluates the Bessel functions with SciPy, so on GPU it is evaluated on the host, like GVEC and DESC.CartesianFluidEquilibriumWithB,CartesianMHDequilibrium) returned NaN on a polar axis. They now evaluate b, j and ∇|B| directly in Cartesian coordinates; away from the axis the values are unchanged (≤ 5e-15).grad_1d_matrixnow works for n = 1.ImplicitDiffusionis fixed.Model-specific changes
ScalarWave: the 0-form wave equation, with the propagatorScalarWaveLeapfrog.MaxwellWeakAmpere(algo="leapfrog"): velocity Verlet, the symplectic scheme of the talk.Examples
Each example has a physics description,
--test-runand a pproc script with the standard snapshots.examples/ScalarWave/gaussian_perturbed_disk: the 0-form wave across the axis. It matches the core leapfrog to 1e-11.examples/Maxwell/gaussian_perturbed_disk: the 1-form wave. It matches the core to about 1e-5.examples/Maxwell/gaussian_helical_tube: the 3D 1-form wave inHelicalTube("stellarator").examples/Poisson/polar_rounded_squareandexamples/CurlCurl/polar_rounded_square: PolarFEEC.jl example 05. They match the core.examples/GuidingCenter/vacuum_near_axis: orbits near the axis ofHelicalVacuumFieldand the energy error max_t |E(t) − E(0)| / (μ|B|).convergence_vacuum_near_axis.pyruns the scan over 𝔯 = 0…4 and Δt = 0.04…0.0025.Demos, tutorials and figures
struphy.polar.homotopy.demosreproduces the figures of the talk and of PolarFEEC.jl:spacesbasis,regularityprojectionspdemaxwellfieldlinesperformancewavesThe tutorials
tutorial_polar_splines.ipynbanddev_tutorial_polar_homotopy.ipynbuse these demos. By default they run at a coarse resolution for CI;STRUPHY_TUTORIAL_FULL=1switches to the resolution of the talk.Tests
In
src/struphy/polar/tests/:test_homotopy_core: a port of the PolarFEEC.jl tests (paper theorems, polar complex, boundary homotopies, the 2D curl–curl case).test_homotopy_convergence(markerconvergence): rates 4, 3, 3 on the perturbed disk.test_homotopy_3d: the total complex, the torus volume and the 3D Poisson problem.test_homotopy_derham: the Derham blocks equal the core matrices; commuting projectors, cohomology, masses, the preconditioner and Dirichlet, for 𝔯 = 1…4. Runs serially and on 4 MPI ranks.test_homotopy_demos.test_homotopy_applications:ScalarWaveequals the core leapfrog;HelicalTube;HelicalVacuumFieldis curl- and divergence-free and finite on the axis;Every new example passes
test_examples. The existing C¹ polar tests,fields_backgroundtests (including a newHelicalVacuumFieldCuPy case), Maxwell and CurlCurl verification tests and toy-model tests all pass. Locally, the 2DESCunitdomain tests fail only becausedesc-optis not installed.The core was cross-checked against PolarFEEC.jl (Julia) on small cases: E, F, the homotopies, the dimensions and the Maxwell eigenvalues.
Documentation changes
numerics-geomFE.rst): a new section on the homotopy construction, a paper ↔ code table and a study ↔ code table.ScalarWaveandScalarWaveLeapfrogare added.Reconstructed parts
The seminar's wave and guiding-centre scripts were not available. Those studies follow the methods stated in the talk and in the wave script from the PolarFEEC.jl history:
The following are choices made here and are listed in the docs:
Known gaps (follow-ups)
solver="homotopy"option in theCurlCurlpropagator (the free lunch in 2D; PCG on D̄ᵀM̄₂D̄ followed by h₂ in 3D), plus a homotopy case intest_verif_CurlCurl.py;examples/CurlCurl/gaussian_on_axis_torus;tutorial_domains.ipynb;demos/plotting.pywould fit there better.🤖 Generated with Claude Code