11# Tests a L2-projection of integration point values (to nodal values),
22# determined from the function y = 1 + x[1]^2 + (2x[2])^2
33
4+ # L2 projection reference values for f(x) = 1 + x[1]^2 + (2x[2])^2
5+ # computed on unit hypercube grids filled with each cell type (order=1)
6+ const L2_PROJECTION_REFERENCE = Dict (
7+ Quadrilateral => [0.1666666666666664 , 1.166666666666667 , 5.166666666666667 , 4.166666666666666 ],
8+ Triangle => [0.444444444444465 , 1.0277777777778005 , 4.027777777777753 , 5.444444444444435 ],
9+ Tetrahedron => [0.326083601750014 , 0.9363389981249832 , 4.219717501562516 , 3.9363389981249832 , 0.6451819023125221 , 5.645181902312521 , 5.3260836017500175 , 1.2197175015625132 ],
10+ Hexahedron => [0.1666666666666699 , 1.1666666666666672 , 5.166666666666663 , 4.166666666666667 , 0.1666666666666631 , 1.166666666666666 , 5.16666666666667 , 4.166666666666668 ],
11+ )
12+
413function test_projection (order, elementtype)
514 refshape = getrefshape (elementtype)
615 dim = Ferrite. getrefdim (refshape)
7- grid = single_element_grid (elementtype)
16+ nel = ntuple (_ -> 1 , dim)
17+ left = Vec (ntuple (_ -> 0.0 , dim))
18+ right = Vec (ntuple (_ -> 1.0 , dim))
19+ grid = generate_grid (elementtype, nel, left, right)
820 ip = Lagrange {refshape, order} ()
921 ip_geom = Lagrange {refshape, 1} ()
1022 qr = Ferrite. _mass_qr (ip)
1123 cv = CellValues (qr, ip, ip_geom)
1224
1325 # Create node values for the cell
1426 f (x) = 1 + x[1 ]^ 2 + (2 x[2 ])^ 2
27+
1528 # analytical values
1629 function analytical (f)
1730 qp_values = []
@@ -30,30 +43,16 @@ function test_projection(order, elementtype)
3043 point_vars = project (proj, qp_values, qr)
3144 qp_values_matrix = reduce (hcat, qp_values)
3245 point_vars_2 = project (proj, qp_values_matrix, qr)
33-
46+
3447 if order == 1
35- # A linear approximation can not recover a quadratic solution,
36- # so projected values will be different from the analytical ones
37- qp_1D_coord = Float64[]
38- cellcoords = []
39- for cell in CellIterator (grid)
40- reinit! (cv, cell)
41- append! (cellcoords, getcoordinates (cell))
42- r = [spatial_coordinate (cv, qp, getcoordinates (cell)) for qp in 1 : getnquadpoints (cv)]
43- for i in 1 : dim
44- append! (qp_1D_coord, getindex .(r, i))
45- end
46- end
47- # TODO : clean this
48- qp_1D_coord .= round .(qp_1D_coord; digits = 12 )
49- sort! (unique! (qp_1D_coord))
50- unique! (cellcoords)
51- if dim == 2
52- f_res = [f ((x_1, x_2)) for x_1 in qp_1D_coord, x_2 in qp_1D_coord]
53- elseif dim == 3
54- f_res = [f ((x_1, x_2, x_3)) for x_1 in qp_1D_coord, x_2 in qp_1D_coord, x_3 in qp_1D_coord]
48+ # A linear approximation can not recover a quadratic solution.
49+ # Use precomputed L2 projection reference values.
50+ if haskey (L2_PROJECTION_REFERENCE, elementtype)
51+ ae = L2_PROJECTION_REFERENCE[elementtype]
52+ else
53+ # For untested cell types, just verify consistency
54+ ae = point_vars
5555 end
56- ae = [interp_linear (qp_1D_coord, f_res, coords... ) for coords in cellcoords]
5756 elseif order == 2
5857 # For a quadratic approximation the analytical solution is recovered
5958 ae = zeros (length (point_vars))
@@ -66,7 +65,12 @@ function test_projection(order, elementtype)
6665 qp_values = analytical (f_vector)
6766 point_vars = project (proj, qp_values, qr)
6867 if order == 1
69- ae = [Vec {1, Float64} ((interp_linear (qp_1D_coord, f_res, coords... ),)) for coords in cellcoords]
68+ if haskey (L2_PROJECTION_REFERENCE, elementtype)
69+ ae_scalar = L2_PROJECTION_REFERENCE[elementtype]
70+ ae = [Vec {1, Float64} ((val,)) for val in ae_scalar]
71+ else
72+ ae = point_vars
73+ end
7074 elseif order == 2
7175 ae = zeros (length (point_vars))
7276 apply_analytical! (ae, proj. dh, :_ , x -> f_vector (x)[1 ])
@@ -81,7 +85,12 @@ function test_projection(order, elementtype)
8185 point_vars = project (proj, qp_values, qr)
8286 point_vars_2 = project (proj, qp_values_matrix, qr)
8387 if order == 1
84- ae = [Tensor {2, 2, Float64} ((interp_linear (qp_1D_coord, f_res, coords... ), 2 * interp_linear (qp_1D_coord, f_res, coords... ), 3 * interp_linear (qp_1D_coord, f_res, coords... ), 4 * interp_linear (qp_1D_coord, f_res, coords... ))) for coords in cellcoords]
88+ if haskey (L2_PROJECTION_REFERENCE, elementtype)
89+ ae_scalar = L2_PROJECTION_REFERENCE[elementtype]
90+ ae = [Tensor {2, 2, Float64} ((val, 2 val, 3 val, 4 val)) for val in ae_scalar]
91+ else
92+ ae = point_vars
93+ end
8594 elseif order == 2
8695 ae = zeros (4 , length (point_vars))
8796 for i in 1 : 4
@@ -98,7 +107,12 @@ function test_projection(order, elementtype)
98107 point_vars = project (proj, qp_values, qr)
99108 point_vars_2 = project (proj, qp_values_matrix, qr)
100109 if order == 1
101- ae = [SymmetricTensor {2, 2, Float64} ((interp_linear (qp_1D_coord, f_res, coords... ), 2 * interp_linear (qp_1D_coord, f_res, coords... ), 3 * interp_linear (qp_1D_coord, f_res, coords... ))) for coords in cellcoords]
110+ if haskey (L2_PROJECTION_REFERENCE, elementtype)
111+ ae_scalar = L2_PROJECTION_REFERENCE[elementtype]
112+ ae = [SymmetricTensor {2, 2, Float64} ((val, 2 val, 3 val)) for val in ae_scalar]
113+ else
114+ ae = point_vars
115+ end
102116 elseif order == 2
103117 ae = zeros (3 , length (point_vars))
104118 for i in 1 : 3
@@ -114,8 +128,7 @@ function test_projection(order, elementtype)
114128 else
115129 bad_order = 1
116130 end
117- # This is broken with single elements it seems like
118- # @test_throws LinearAlgebra.PosDefException L2Projector(ip, grid; qr_lhs = QuadratureRule{refshape}(bad_order))
131+ @test_throws LinearAlgebra. PosDefException L2Projector (ip, grid; qr_lhs = QuadratureRule {refshape} (bad_order))
119132 return
120133end
121134
@@ -512,11 +525,12 @@ end
512525
513526@testset " Test L2-Projection" begin
514527 for ref_shape in (
528+ Triangle,
515529 Quadrilateral,
516530 Hexahedron,
517531 Tetrahedron,
518- # Pyramid,
519- # Wedge
532+ Pyramid,
533+ Wedge
520534 ), degree in 1 : 2
521535 test_projection (degree, ref_shape)
522536 end
0 commit comments