Skip to content

Nonaxisymmetric surface interface in VACUUM#189

Merged
jhalpern30 merged 11 commits intodevelopfrom
jmh/nonaxisymmetric_surfs
Mar 13, 2026
Merged

Nonaxisymmetric surface interface in VACUUM#189
jhalpern30 merged 11 commits intodevelopfrom
jmh/nonaxisymmetric_surfs

Conversation

@jhalpern30
Copy link
Collaborator

Adding capability to run 3D vacuum with nonaxisymmetric surfaces

@jhalpern30
Copy link
Collaborator Author

@claude summarize and review this PR

@claude
Copy link

claude bot commented Mar 12, 2026

Claude finished @jhalpern30's task in 3m 0s —— View job


PR Review: Nonaxisymmetric surface interface in VACUUM

Tasks:

  • Post initial comment
  • Read changed files
  • Analyze changes
  • Post review

Summary

This PR extends the VACUUM module to accept nonaxisymmetric (fully 3D) plasma surfaces as input, enabling 3D vacuum calculations with non-circular toroidal geometry. Key changes:

  1. VacuumInput struct: Renamed rx, added y (Y-Cartesian coordinate), added mtheta_in/nzeta_in to distinguish axisymmetric from 3D input boundaries. Default values for mlow/mpert/nlow/npert changed from 0 to 1.

  2. PlasmaGeometry3D: Unified constructor now takes VacuumInput directly and branches on nzeta_in. Axisymmetric path now correctly uses the SFL angle ζ = ϕ - ν (fixing what appears to be a prior bug where ν was ignored in 3D extrusion). 3D path bicubic-interpolates (x,y,z) from input grid to vacuum grid.

  3. FourierTransforms.jl: Dispatch reworked — now branches on nzeta == 1 vs. > 1 (rather than n_2D === nothing). ν parameter changed to Union{Nothing, Vector{Float64}} with nothing as default for 3D.

  4. Vacuum.jl: Checks for ν field with hasproperty since PlasmaGeometry3D no longer carries ν.

  5. Tests: New nonaxisymmetric helper and tests for both PlasmaGeometry3D construction and full compute_vacuum_response with 3D input.

  6. gpec.toml example: Syncs deprecated tolerance parameters with current API (eulerlagrange_tolerance).


Issues

Bug: WallGeometry3D calls PlasmaGeometry(inputs) for non-axisymmetric inputs

DataTypes.jl:607-609:

surf_2D = PlasmaGeometry(inputs)
wall_2D = WallGeometry(inputs, surf_2D, wall_settings)

PlasmaGeometry(inputs) now asserts !isempty(inputs.ν). For a 3D non-axisymmetric VacuumInput (nzeta_in > 1), ν is typically empty/unset. Any non-nowall call to WallGeometry3D with a 3D non-axisymmetric input will crash with an AssertionError. The test for this case only exercises shape="nowall" (which returns early before reaching this code), so the bug is not caught. Either add a guard in WallGeometry3D to error early with a clear message for nzeta_in > 1 + non-nowall, or make the wall construction grid-agnostic.

Fix this →

Missing input validation for 3D non-axisymmetric case

When nzeta_in > 1, the y field must be non-empty and have length mtheta_in * nzeta_in. There is no validation anywhere for this contract. A user who sets nzeta_in > 1 but forgets to populate y will get a silent reshape/interpolation error far from the source.

Suggest adding to PlasmaGeometry3D in the else branch:

@assert !isempty(inputs.y) "y must be provided for 3D (nzeta_in > 1) inputs"
@assert length(inputs.x) == length(inputs.y) == length(inputs.z) == inputs.mtheta_in * inputs.nzeta_in "x, y, z must have length mtheta_in * nzeta_in"

Fix this →

Performance regression in compute_fourier_coefficients (3D path)

FourierTransforms.jl:119-127:

The previous code pre-computed nν_nϕ = n .* (ν .+ ϕ_grid') and used a broadcast+sincos pattern. The new code uses a plain scalar loop without ν (since the 3D basis is mθ - nζ, not mθ - n(ν+ζ)). The scalar loop is correct but slightly slower than the vectorized approach. This is likely acceptable since this runs once per vacuum solve, but worth noting.


Observations

Correctness fix in axisymmetric 3D extrusion: The old code mapped X = R cos(ϕ) / Y = R sin(ϕ) ignoring ν. The new code correctly computes X = R cos(ζ - ν) / Y = R sin(ζ - ν) where ζ is the SFL toroidal angle. This is a real correctness improvement.

ν removal from PlasmaGeometry3D: Removing ν::Vector{Float64} from the struct is clean — it was only needed during 2D→3D extrusion and doesn't belong in the final 3D description.

hasproperty pattern in Vacuum.jl:82 is a reasonable duck-typing approach, though an explicit dispatch on type or a helper function would be slightly more idiomatic.

Default values: The change of defaults for mlow/mpert/nlow/npert from 0 to 1 is a reasonable semantic improvement (the previous 0 was arguably a sentinel).

Test coverage: The new compute_vacuum_response 3D nonaxisymmetric boundary test is thorough for the happy path. It would benefit from a test verifying that the nonaxisymmetric boundary produces a different result from the equivalent axisymmetric input (i.e., that the 3D structure is actually used).


Overall this is a clean, well-documented extension. The main actionable items are the WallGeometry3D crash for non-nowall + 3D non-axisymmetric inputs and the missing input validation for y.

@jhalpern30 jhalpern30 marked this pull request as ready for review March 12, 2026 17:05
@jhalpern30 jhalpern30 requested a review from logan-nc March 12, 2026 17:05
@jhalpern30
Copy link
Collaborator Author

@logan-nc relatively small PR here - just adding the interface needed for nonaxisymmetric surfaces.
Results for Solovev ideal example 2D:

┌ Info: Least Stable Eigenmode Energies:
│   Plasma = -1.102e+01 +2.103e-06i
│   Vacuum = +1.058e+01 -1.735e-17i
└   Total  = -4.372e-01 +2.103e-06i
┌ Warning: Free-boundary mode unstable for n = 1

and 3D:

┌ Info: Least Stable Eigenmode Energies:
│   Plasma = -1.102e+01 +2.128e-06i
│   Vacuum = +1.058e+01 +3.595e-17i
└   Total  = -4.377e-01 +2.128e-06i
┌ Warning: Free-boundary mode unstable for n = 1

and the convergence scan I did for the precise QA stellarator
image

As we discussed, I've removed all the VTK writing stuff from this branch and am storing it in jmh/write_vtk for when we decide to add it to Analysis module

Copy link
Collaborator

@logan-nc logan-nc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@jhalpern30 jhalpern30 merged commit 90f453b into develop Mar 13, 2026
6 checks passed
@jhalpern30 jhalpern30 deleted the jmh/nonaxisymmetric_surfs branch March 13, 2026 13:04
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.

2 participants