Skip to content

check_isoparametric_boundaries, mass_qr, and cellcenter for Pyramids and Wedges + L2Projector tests for Hexahedron, Tetrahedron, Pyramid, and Wedge.#1215

Open
AbdAlazezAhmed wants to merge 10 commits intoFerrite-FEM:masterfrom
AbdAlazezAhmed:L2-pyr-wed
Open

check_isoparametric_boundaries, mass_qr, and cellcenter for Pyramids and Wedges + L2Projector tests for Hexahedron, Tetrahedron, Pyramid, and Wedge.#1215
AbdAlazezAhmed wants to merge 10 commits intoFerrite-FEM:masterfrom
AbdAlazezAhmed:L2-pyr-wed

Conversation

@AbdAlazezAhmed
Copy link
Copy Markdown
Collaborator

PointEvalHandler needed these functions to work. Also, L2 Projector is only tested with triangles and quads. I added a bit more general test using Interpolations.jl instead of manually calculating the test values for first order interpolations.

@codecov
Copy link
Copy Markdown

codecov bot commented Jul 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.07%. Comparing base (eb76ddc) to head (9d7aa10).
⚠️ Report is 13 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1215      +/-   ##
==========================================
- Coverage   94.25%   93.07%   -1.18%     
==========================================
  Files          40       40              
  Lines        6750     6859     +109     
==========================================
+ Hits         6362     6384      +22     
- Misses        388      475      +87     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread Project.toml Outdated
[deps]
EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

extras?

Copy link
Copy Markdown
Collaborator

@lijas lijas left a comment

Choose a reason for hiding this comment

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

Is it easy to implement the linear interpolation ourself and avoid importing the Interpolations package?

Comment thread test/test_l2_projection.jl Outdated
function test_projection(order, elementtype)
refshape = getrefshape(elementtype)
dim = Ferrite.getrefdim(refshape)
grid = single_element_grid(elementtype)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why did you change this to a single element grid? Previously we had triangles/tetrahedrons filled a square/cube.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My bad, I didn't notice it.

test_projection(2, RefQuadrilateral)
test_projection(2, RefTriangle)
for ref_shape in (
Quadrilateral,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These are not refshapes

Comment thread test/test_l2_projection.jl Outdated
# A linear approximation can not recover a quadratic solution,
# so projected values will be different from the analytical ones
ae = [f_approx(i) for i in 1:4]
qp_1D_coord = Float64[]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add a small comment what you are trying to do here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I was trying to calculate the first order approximation values using linear extrapolation from the quadrature points instead of using precomputed hardcoded values. But since we use more than one element this won't work so I'll compute the values for other cell types and add them instead.

@AbdAlazezAhmed AbdAlazezAhmed changed the title check_isoparametric_boundaries and cellcenter for Pyramids and Wedges + better tests for L2Projector. check_isoparametric_boundaries, mass_qr, and cellcenter for Pyramids and Wedges + L2Projector tests for Hexahedron, Tetrahedron, Pyramid, and Wedge. Mar 6, 2026
@AbdAlazezAhmed AbdAlazezAhmed marked this pull request as ready for review March 6, 2026 21:30
@termi-official
Copy link
Copy Markdown
Member

PointEvalHandler needed these functions to work.

https://app.codecov.io/gh/Ferrite-FEM/Ferrite.jl/pull/1215?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=checks&utm_campaign=pr+comments&utm_term=Ferrite-FEM

The new functions are never called in the tests.

@AbdAlazezAhmed
Copy link
Copy Markdown
Collaborator Author

AbdAlazezAhmed commented Mar 9, 2026

So it seems like there's something off with the quadrature rules for prisms and pyramids. Here's a copied test to check what quadrature orders work:

Some Copied Code
using Ferrite

function test_pe_scalar_field(celltype::Type{<:Ferrite.AbstractCell}, ip_order, qr_order)
    ref_shape = getrefshape(celltype)
    dim = Ferrite.getrefdim(ref_shape)
    mesh = generate_grid(celltype, ntuple(_ -> 3, dim))

    f(x) = sum(x)
    ip_f = Lagrange{ref_shape, ip_order}() # function interpolation
    ip_g = geometric_interpolation(celltype) # geometry interpolation

    # points where we want to retrieve field values
    points = Vec{dim, Float64}[]

    # compute values in quadrature points
    qr = Ferrite.QuadratureRule{ref_shape}(qr_order) # exactly integrate field
    cv = CellValues(qr, ip_f, ip_g)
    qp_vals = [Vector{Float64}(undef, getnquadpoints(cv)) for _ in 1:getncells(mesh)]
    for cellid in eachindex(mesh.cells)
        xe = getcoordinates(mesh, cellid)
        reinit!(cv, xe)
        for qp in 1:getnquadpoints(cv)
            x = spatial_coordinate(cv, qp, xe)
            qp_vals[cellid][qp] = f(x)
            push!(points, x)
        end
    end

    # do a L2Projection for getting values in dofs
    projector = L2Projector(ip_f, mesh)
    projector_vals = project(projector, qp_vals, qr)
    return maximum(projector_vals)  dim
end

for ip_order in 1:3
    for qr_order in 1:7
        function Ferrite._mass_qr(::Lagrange{RefPyramid, order}) where {order}
            return QuadratureRule{RefPyramid}(qr_order)
        end

        function Ferrite._mass_qr(::Lagrange{RefPrism, order}) where {order}
            return QuadratureRule{RefPrism}(qr_order)
        end
        for cell_type in (Wedge, Pyramid)
            try
                worked = test_pe_scalar_field(cell_type, ip_order, qr_order)
                println("cell: $cell_type, ip order: $ip_order, qr order: $qr_order ::: correct values? $worked")
            catch
                println("cell: $cell_type, ip order: $ip_order, qr order: $qr_order ::: Crashed")
            end
            println("--------------")
        end
    end
end

Results:
for order 1 ip: order 3 pyramid qr, order 4 prism qr
for order 2 ip: order 5 pyramid qr, order 6 prism qr
for order 3 ip:

All results
cell: Wedge, ip order: 1, qr order: 1 ::: Crashed
--------------
cell: Pyramid, ip order: 1, qr order: 1 ::: Crashed
--------------
cell: Wedge, ip order: 1, qr order: 2 ::: Crashed
--------------
cell: Pyramid, ip order: 1, qr order: 2 ::: correct values? false
--------------
cell: Wedge, ip order: 1, qr order: 3 ::: Crashed
--------------
cell: Pyramid, ip order: 1, qr order: 3 ::: correct values? true
--------------
cell: Wedge, ip order: 1, qr order: 4 ::: correct values? true
--------------
cell: Pyramid, ip order: 1, qr order: 4 ::: correct values? true
--------------
cell: Wedge, ip order: 1, qr order: 5 ::: correct values? true
--------------
cell: Pyramid, ip order: 1, qr order: 5 ::: correct values? true
--------------
cell: Wedge, ip order: 1, qr order: 6 ::: correct values? true
--------------
cell: Pyramid, ip order: 1, qr order: 6 ::: correct values? true
--------------
cell: Wedge, ip order: 1, qr order: 7 ::: correct values? true
--------------
cell: Pyramid, ip order: 1, qr order: 7 ::: Crashed
--------------
cell: Wedge, ip order: 2, qr order: 1 ::: Crashed
--------------
cell: Pyramid, ip order: 2, qr order: 1 ::: Crashed
--------------
cell: Wedge, ip order: 2, qr order: 2 ::: Crashed
--------------
cell: Pyramid, ip order: 2, qr order: 2 ::: Crashed
--------------
cell: Wedge, ip order: 2, qr order: 3 ::: Crashed
--------------
cell: Pyramid, ip order: 2, qr order: 3 ::: Crashed
--------------
cell: Wedge, ip order: 2, qr order: 4 ::: Crashed
--------------
cell: Pyramid, ip order: 2, qr order: 4 ::: Crashed
--------------
cell: Wedge, ip order: 2, qr order: 5 ::: Crashed
--------------
cell: Pyramid, ip order: 2, qr order: 5 ::: correct values? true
--------------
cell: Wedge, ip order: 2, qr order: 6 ::: correct values? true
--------------
cell: Pyramid, ip order: 2, qr order: 6 ::: correct values? true
--------------
cell: Wedge, ip order: 2, qr order: 7 ::: correct values? true
--------------
cell: Pyramid, ip order: 2, qr order: 7 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 1 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 1 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 2 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 2 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 3 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 3 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 4 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 4 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 5 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 5 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 6 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 6 ::: Crashed
--------------
cell: Wedge, ip order: 3, qr order: 7 ::: Crashed
--------------
cell: Pyramid, ip order: 3, qr order: 7 ::: Crashed
--------------
Edit: Ah, we don't have order 3 in the first place. I thought we do it using tensor products.

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.

3 participants