Comparison: This Implementation vs. Steger & Sorenson (1979)
A detailed comparison of the ellipticSS solver in GridGeneration.jl against the original Steger & Sorenson method and its production implementation in the GRAPE code (Sorenson, NASA TM-81198, 1980).
Overview
The ellipticSS implementation is a faithful simplified version of the Steger & Sorenson approach. It captures the core mathematical ideas – elliptic PDE smoothing with automatic wall-forcing for orthogonality – but omits several algorithmic accelerations that GRAPE uses for production efficiency.
| Aspect | Steger & Sorenson / GRAPE | This Implementation |
|---|---|---|
| PDE formulation | Poisson system in computational coords | Same |
| Orthogonality enforcement | Automatic P,Q from boundary residuals | Same |
| Forcing decay | Exponential decay into domain | Same |
| Linear solver | Line Gauss-Seidel (Thomas algorithm) | Point Gauss-Seidel (SOR) |
| Acceleration | Coarse-fine sequencing (multigrid-like) | None |
| Relaxation | Over-relaxation (omega > 1) | Under-relaxation (omega = 0.2) |
| Control functions | Full P,Q with J^2 coupling | Simplified direct RHS forcing |
| Spacing control | Prescribed s(xi) distribution | Linear interpolation of corner spacings |
1. PDE Formulation: Essentially Identical
Both solve the same transformed Poisson system:
alpha * x_{xi,xi} - 2*beta * x_{xi,eta} + gamma * x_{eta,eta} = RHS_x
alpha * y_{xi,xi} - 2*beta * y_{xi,eta} + gamma * y_{eta,eta} = RHS_ywith identical metric coefficient definitions. The discretization uses the same 9-point stencil with central differences. No difference here.
2. Orthogonality Enforcement: Same Core Idea, Simplified Execution
What Steger & Sorenson Do
The original method computes control functions P(xi,eta) and Q(xi,eta) by evaluating the full Poisson equations at the boundary with desired derivatives imposed:
alpha * x_{xi,xi} - 2*beta * x_{xi,eta} + gamma * x_{eta,eta} + J^2*(P*x_xi + Q*x_eta) = 0At the wall, with beta_b = 0 (orthogonality enforced) and known desired derivatives, this yields explicit values of P and Q at every boundary point. These P, Q values are then decayed into the interior and appear as source terms throughout the domain, coupled through the J^2 factor.
What This Implementation Does
The code computes the boundary residual directly:
RHS_x = -(alpha_b * x_{xi,xi} + gamma_b * x_{eta,eta})This is equivalent to computing J^2*(P*x_xi + Q*x_eta) at the boundary, but skips the explicit decomposition into P and Q. The forcing is applied as a single combined RHS term rather than separate P, Q control functions multiplied by first derivatives.
Practical Consequence
The difference is subtle but meaningful:
Steger & Sorenson: P and Q are scalar functions. When propagated into the interior, they multiply the local first derivatives (xxi, xeta, etc.) at each interior point. This means the forcing adapts to the local grid geometry as it moves away from the wall.
This implementation: The RHS values computed at the wall are propagated as fixed vectors that don't interact with interior metrics. The forcing at an interior point (i,j) is simply the wall value times exp(-decay * distance), regardless of what the local grid looks like at (i,j).
For grids where the interior geometry doesn't differ dramatically from the boundary geometry, this is a reasonable simplification. For highly curved or stretched grids, the Steger & Sorenson approach provides more physically consistent forcing in the interior.
3. Wall Spacing Control: Simplified
Steger & Sorenson / GRAPE
GRAPE allows the user to prescribe a full spacing distribution s(xi) along each boundary. This can be:
- Constant spacing (uniform boundary layer)
- Geometric stretching (exponential growth away from corners)
- Arbitrary user-specified distribution
- Matched to a flow solution (adaptive refinement)
This Implementation
The spacing is determined by linear interpolation between the actual spacings at the two corner points of each boundary:
s1 = ||point[1, wall] - point[1, wall+1]||
s2 = ||point[Ni, wall] - point[Ni, wall+1]||
s_vec = LinRange(s1, s2, Ni)This means:
- The user doesn't directly control wall spacing – it's inherited from the initial grid
- The spacing varies linearly along the wall, which may not match the desired distribution
- There's no option for geometric stretching or custom distributions
Impact: For grids where the initial TFI/edge-solver already provides good boundary spacing, this works fine. For boundary layer grids requiring precise wall-normal spacing control, the GRAPE approach is more capable.
4. Linear Solver: The Biggest Algorithmic Difference
Steger & Sorenson / GRAPE: Line Gauss-Seidel
GRAPE reorganizes the discretized equations at each j-level into a tridiagonal system in the i-direction:
a_i * x_{i-1,j}^{n+1} + b_i * x_{i,j}^{n+1} + c_i * x_{i+1,j}^{n+1} = d_iwhere:
- a_i = alpha[i,j]
- b_i = -2*(alpha[i,j] + gamma[i,j])
- c_i = alpha[i,j]
- d_i = -gamma[i,j](x[i,j+1] + x[i,j-1]) + beta[i,j]/2(cross terms using old values) - RHS[i,j]
This tridiagonal system is solved exactly in O(Ni) operations using the Thomas algorithm. The key advantage: all points along a j-line are updated simultaneously and implicitly coupled, leading to much faster information propagation across the grid.
After sweeping all j-levels, the same process is applied along i-levels for the eta-direction (alternating direction).
This Implementation: Point SOR
Each interior point is updated individually using only its current neighbors:
x_new = (alpha*(x[i+1,j]+x[i-1,j]) + gamma*(x[i,j+1]+x[i,j-1])
- beta/2*cross_terms + RHS) / (2*(alpha + gamma))
x[i,j] = (1 - omega)*x[i,j] + omega*x_newPerformance Comparison
| Property | Line Gauss-Seidel | Point SOR (omega=0.2) |
|---|---|---|
| Work per iteration | O(Ni*Nj) | O(Ni*Nj) |
| Convergence rate | Fast (implicit coupling) | Slow (local updates) |
| Iterations for N x N grid | O(N) | O(N^2) to O(N^3) |
| Total work | O(N^3) | O(N^4) to O(N^5) |
| Stability | Can use omega > 1 | Requires omega < 1 |
| Implementation complexity | Moderate (Thomas solver) | Simple |
The line solver is dramatically faster because information propagates across an entire grid line in a single step, whereas point SOR can only move information one grid point per iteration.
Example: For a 100 x 100 grid:
- Line Gauss-Seidel: ~100-500 iterations
- Point SOR (omega=0.2): ~5000-50000 iterations
This is the single biggest performance gap between the implementation and GRAPE.
5. Acceleration Techniques: Not Implemented
GRAPE's Coarse-Fine Sequencing
GRAPE uses a two-level coarse-fine strategy (a simplified multigrid):
- Extract every 2nd (or 4th) point to create a coarse grid
- Solve the elliptic system on the coarse grid to convergence
- Interpolate the coarse solution onto the fine grid
- Use this as the initial guess for the fine-grid solve
- The fine-grid solve converges much faster with a good initial guess
This can reduce total iteration count by a factor of 4-10x.
This Implementation
No multigrid or coarse-fine acceleration. The solver starts from the TFI grid directly and iterates at full resolution. This is simpler but slower for large grids.
6. Relaxation Strategy: Opposite Approaches
GRAPE: Over-Relaxation (omega > 1)
Because GRAPE uses line Gauss-Seidel (which is inherently more stable due to implicit coupling), it can afford over-relaxation with omega in the range 1.0-1.8. The optimal omega for the line method is typically around 1.4-1.6, providing significant acceleration.
GRAPE also uses variable relaxation: different omega values for different iteration phases, and sometimes different omega for x vs. y updates.
This Implementation: Under-Relaxation (omega = 0.2)
The point SOR method with recomputed nonlinear metrics requires under-relaxation for stability. The default omega = 0.2 means each update step is only 20% of the full Gauss-Seidel correction.
Why the difference?
- Line methods implicitly solve for all points on a line simultaneously, averaging out local errors. This makes them tolerant of aggressive relaxation.
- Point methods update each point in isolation using neighbors that may be a mix of old and new values. The nonlinear metric feedback can amplify errors if steps are too large.
7. Convergence Monitoring
GRAPE
GRAPE monitors multiple convergence metrics:
- Maximum absolute change in x and y coordinates (L-infinity norm)
- RMS change across the grid
- Maximum Jacobian ratio (measure of cell quality)
- Orthogonality angle at boundaries
It also uses adaptive iteration control: if convergence stalls, it can adjust omega or switch between solver phases.
This Implementation
Monitors the larger of the L2 norms of the x- and y-displacements, warns when max_iter is reached, and errors on a non-finite update:
err = max(norm(x - x_old), norm(y - y_old))This is adequate for detecting convergence but doesn't distinguish between:
- Grid still moving significantly (not converged)
- Grid quality improving but positions are stable
- Grid quality degrading (rare, but possible with bad parameters)
y-displacement is not independently monitored.
8. Boundary Derivative Computation
Steger & Sorenson
The original paper uses second-order one-sided differences for normal derivatives at the wall, with careful treatment of the ghost-point approach to impose desired first derivatives.
This Implementation
Uses a specific modified stencil (line 86 of EllipticSolver.jl):
x_etaeta = 0.5*(-7*x[i,wall] + 8*x[i,wall+1] - x[i,wall+2]) - dir*3*x_eta_desiredThis formula is consistent with the Steger & Sorenson approach. It can be derived by:
Writing the Taylor expansion at the wall with the desired first derivative:
x[wall+1] = x[wall] + x_eta_desired + (1/2)*x_etaeta + ... x[wall+2] = x[wall] + 2*x_eta_desired + 2*x_etaeta + ...Solving these two equations for x_etaeta in terms of known values.
The coefficients (-7, 8, -1, -3) arise from this derivation. This matches the original method's approach of using the desired derivative to compute a consistent second derivative.
However, let us verify the stencil. From a second-order one-sided formula for f''(0) using points at 0, h, 2h with a known f'(0):
f(h) = f(0) + h*f'(0) + (h^2/2)*f''(0) + (h^3/6)*f'''(0) + ...
f(2h) = f(0) + 2h*f'(0) + 2h^2*f''(0) + (4h^3/3)*f'''(0) + ...With h = 1 (unit computational spacing):
f(1) = f(0) + f'_desired + (1/2)*f''
f(2) = f(0) + 2*f'_desired + 2*f''From the second equation: f'' = (f(2) - f(0) - 2*f'_desired) / 2
But the code uses a different linear combination, suggesting a higher-order or modified stencil. The exact derivation likely involves ensuring consistency with the specific discretization used in the elliptic equation at the boundary.
9. Multi-Block Support
GRAPE
The original GRAPE is a single-block solver. Multi-block extensions were developed later (e.g., GRAPE3D by Sorenson & Steger, 1984), where interface conditions between blocks must be carefully handled to ensure continuity of the grid and its derivatives.
This Implementation
Has native multi-block support through SmoothBlocks(), which iterates over each block independently:
for i in eachindex(blocks)
xr, yr, finalError, finalIter = EllipticSolver(blocks[i][1,:,:], blocks[i][2,:,:], ...)
endHowever, the blocks are smoothed independently – there is no inter-block coupling during the elliptic solve. This means:
- Block interfaces maintain their positions (treated as fixed boundaries)
- No guarantee of derivative continuity across block interfaces
- Each block converges independently
A fully coupled multi-block elliptic solver would iterate across all blocks simultaneously, updating interface positions to ensure C1 continuity (matching first derivatives) across block boundaries.
10. Summary: What's Preserved and What's Simplified
Faithfully Preserved from Steger & Sorenson
- The elliptic PDE formulation in computational coordinates
- The 9-point stencil discretization with alpha, beta, gamma metrics
- Automatic orthogonality enforcement via boundary residual computation
- Exponential decay of forcing into the domain interior
- The overall iterate-until-convergence framework
- Independent wall control (enable/disable per boundary)
- The modified one-sided derivative stencil at boundaries
Simplified or Omitted
- Point SOR instead of line Gauss-Seidel – the largest performance difference
- No coarse-fine sequencing – no multigrid acceleration
- Under-relaxation instead of over-relaxation – necessary due to point SOR
- Direct RHS forcing instead of separate P,Q control functions – minor accuracy impact
- Linear spacing interpolation instead of prescribed s(xi) – less control over wall spacing
- Single displacement-based convergence metric (max of x and y L2 norms) – no grid-quality diagnostics
- Independent block smoothing – no inter-block coupling for derivative continuity
Suggested Improvements (in priority order)
Line Gauss-Seidel: Replace point SOR with a Thomas-algorithm-based line solver. This would allow over-relaxation and reduce iteration counts by 10-100x. Partly done:
EllipticParams(sweep = :line)adds alternating line Gauss-Seidel for the current equations (100x fewer iterations without forcing, ~6x with wall forcing, where omega must stay <= 0.3). Proper P,Q control functions (item 5) are likely needed before over-relaxation works with forcing.Prescribed wall spacing: Allow user to specify s(xi) along each boundary rather than interpolating from corner spacings.
~~Monitor both x and y convergence: Track max(norm(x-xold), norm(y-yold)).~~ Done.
Coarse-fine sequencing: Add a simple two-level multigrid for large grids.
P,Q control functions: Decompose the boundary forcing into proper P,Q functions that multiply local first derivatives when propagated into the interior.
References
Steger & Sorenson (1979). "Automatic mesh-point clustering near a boundary in grid generation with elliptic partial differential equations." J. Comp. Phys. 33, 405-410.
Sorenson (1980). "A computer program to generate two-dimensional grids about airfoils and other shapes by the use of Poisson's equation." NASA TM-81198 (the GRAPE code).
Sorenson & Steger (1984). "Grid generation in three dimensions by Poisson equations with control of cell size and skewness at boundary surfaces." NASA TM-86301.
White (1990). "Two-dimensional grid generation with derivatives of the physical coordinates on boundary orthogonal grids." NASA CR-4348. (Improved forcing propagation using transfinite interpolation.)
Hilgenstock (1988). "A fast method for the elliptic generation of three- dimensional grids with full boundary control." In Numerical Grid Generation in Computational Fluid Mechanics. (Efficient computation of control functions.)
Thompson, Warsi & Mastin (1985). Numerical Grid Generation: Foundations and Applications. (Comprehensive textbook covering the full theory.)