Skip to content

Fix MappedH1OrL2SurfaceInterpolants Jacobian for surface quadrature#98

Merged
lxmota merged 3 commits into
mainfrom
feature/tetra4-surface-quadrature-fix
Mar 16, 2026
Merged

Fix MappedH1OrL2SurfaceInterpolants Jacobian for surface quadrature#98
lxmota merged 3 commits into
mainfrom
feature/tetra4-surface-quadrature-fix

Conversation

@lxmota

@lxmota lxmota commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fix Jacobian normalization for unshifted reference elements: The previous code used det_J = norm(X_diff) (physical edge length) for all 1D boundaries, which is only correct for shifted elements parameterized on [0,1]. For unshifted edges on [−1,1], the reference length is 2, so det_J = physical_length / 2. This caused a 2× force error for QUAD4 Neumann BCs.
  • Fix for 2D faces: Analogous fix for surface faces — shifted Tri on [0,1]² has reference area 1/2; unshifted Quad on [−1,1]² has reference area 4. Divide det_J by the appropriate reference area.
  • Fix SVector{2} hardcoded dimension: The physical quadrature point coordinate X_q was constructed as SVector{2, ...}, failing for 3D elements. Replace with X_face * N_reduced which infers the correct dimension.
  • Fix face 4 surface quadrature coordinates for Tet elements.

lxmota added 3 commits March 15, 2026 22:36
    The last block in surface_quadrature_points_and_weights was writing
    face 4's (z=0) quadrature coordinates to ξ_return[:,:,1] instead of
    ξ_return[:,:,4], corrupting face 1 and leaving face 4 as all-zeros.
    This caused incorrect Neumann BC assembly on Tet faces 1 and 4.
The old implementation computed det_J as the length of the edge between
nodes 1 and 2 of the volume element (a 1D Jacobian), and hardcoded X_q
as SVector{2}, both wrong for 3D volume elements whose faces are 2D
(Tri for Tet, Quad for Hex).

For 2D boundary elements (Tri/Quad), compute the area Jacobian via the
cross product of the two face tangent vectors:
  t1 = X_face[:,2] - X_face[:,1]
  t2 = X_face[:,3] - X_face[:,1]
  det_J = |t1 × t2|,  n = (t1 × t2) / det_J

For 1D boundary elements (Edge), retain the existing edge-length
Jacobian with the hard-coded reference normal.

Also fixes: X_q now inferred from X_face * N_reduced (correct spatial
dimension) instead of SVector{2,...} (hardcoded 2D); X_face is built
from the face's local node indices via boundary_dofs, not from the
first two columns of the volume element coordinate matrix.
…rmalization

The physical Jacobian must account for the reference element's measure:
- 1D boundary (unshifted Edge on [-1,1]): det_J = physical_length / 2
- 1D boundary (shifted Edge on [0,1]):    det_J = physical_length     (unchanged)
- 2D boundary (shifted Tri on [0,1]²):    det_J = |t1×t2|             (unchanged)
- 2D boundary (unshifted Quad on [-1,1]²): det_J = |t1×t2| / 4

Without this fix, QUAD4 NBC forces were 2x too large (reference interval
length 2 vs. physical length h), while TRI3 was already correct because
the shifted edge uses weights that sum to 1 (not 2).
@lxmota lxmota requested a review from cmhamel March 16, 2026 19:29
@lxmota lxmota merged commit d03dfc6 into main Mar 16, 2026
4 checks passed
@lxmota lxmota deleted the feature/tetra4-surface-quadrature-fix branch March 16, 2026 19:42
@lxmota

lxmota commented Mar 16, 2026

Copy link
Copy Markdown
Contributor Author

@JuliaRegistrator register

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