@@ -30,138 +30,30 @@ isdefined(FEType::Type{<:HDIVBDM2}, ::Type{<:Triangle2D}) = true
3030interior_dofs_offset (:: Type{<:ON_CELLS} , :: Type{<:HDIVBDM2{2}} , :: Type{<:Triangle2D} ) = 9
3131
3232
33- function ExtendableGrids . interpolate! (Target :: AbstractArray{T, 1} , FE :: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_FACES} , data; items = [], kwargs ... ) where {T, Tv, Ti, FEType <: HDIVBDM2 , APT}
34- ncomponents = get_ncomponents (FEType)
35- xFaceNormals = FE . dofgrid[FaceNormals]
36- nfaces = num_sources (xFaceNormals )
37- if items == []
38- items = 1 : nfaces
33+ function BDM2_normalflux_eval! (dim)
34+ @assert dim == 2 " BDM3 for dim=3 not available yet "
35+ function closure (result, f, qpinfo)
36+ result[ 1 ] = dot (f, qpinfo . normal )
37+ result[ 2 ] = result[ 1 ] * (qpinfo . xref[ 1 ] - 1 // dim)
38+ result[ 3 ] = result[ 1 ] * (qpinfo . xref[ 1 ] ^ 2 - qpinfo . xref[ 1 ] + 1 // 6 )
3939 end
40+ end
41+ init_interpolator! (FES:: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_FACES} ) where {Tv, Ti, FEType <: HDIVBDM2 , APT} = FaceFluxEvaluator (BDM2_normalflux_eval! (FEType. parameters[1 ]), FES, ON_FACES)
42+ init_interpolator! (FES:: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_CELLS} ) where {Tv, Ti, FEType <: HDIVBDM2{2} , APT} = MomentInterpolator (FES, ON_CELLS; FEType_moments = H1MINI{1 ,2 }, moments_dofs = [1 ,2 ,4 ], moments_operator = CurlScalar)
4043
41- # integrate normal flux of exact_function over edges
42- data_eval = zeros (T, ncomponents)
43- function normalflux_eval (result, qpinfo)
44- data (data_eval, qpinfo)
45- result[1 ] = dot (data_eval, view (xFaceNormals, :, qpinfo. item))
46- result[2 ] = result[1 ] * (qpinfo. xref[1 ] - 1 // ncomponents)
47- return result[3 ] = result[1 ] * (qpinfo. xref[1 ]^ 2 - qpinfo. xref[1 ] + 1 // 6 )
48- end
49- return integrate! (Target, FE. dofgrid, ON_FACES, normalflux_eval; quadorder = 4 , items = items, offset = [0 , nfaces, 2 * nfaces], kwargs... )
44+
45+ function ExtendableGrids. interpolate! (Target:: AbstractArray{T, 1} , FE:: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_FACES} , exact_function!; items = [], kwargs... ) where {T, Tv, Ti, FEType <: HDIVBDM2 , APT}
46+ get_interpolator (FE, ON_FACES). evaluate! (Target, exact_function!, items; kwargs... )
5047end
5148
52- function ExtendableGrids. interpolate! (Target:: AbstractArray{T, 1} , FE:: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_CELLS} , data ; items = [], time = 0 , bonus_quadorder = 0 , kwargs... ) where {T, Tv, Ti, FEType <: HDIVBDM2 , APT}
49+ function ExtendableGrids. interpolate! (Target:: AbstractArray{T, 1} , FE:: FESpace{Tv, Ti, FEType, APT} , :: Type{ON_CELLS} , exact_function! ; items = [], time = 0 , bonus_quadorder = 0 , kwargs... ) where {T, Tv, Ti, FEType <: HDIVBDM2 , APT}
5350 # delegate cell faces to face interpolation
5451 subitems = slice (FE. dofgrid[CellFaces], items)
55- interpolate! (Target, FE, ON_FACES, data; items = subitems, kwargs... )
56-
57- # set values of interior BDM2 functions as piecewise best-approximation
58- ncomponents = get_ncomponents (FEType)
59- EG = (ncomponents == 2 ) ? Triangle2D : Tetrahedron3D
60- ndofs = get_ndofs (ON_CELLS, FEType, EG)
61- interior_offset:: Int = 9
62- nidofs:: Int = ndofs - interior_offset
63- ncells = num_sources (FE. dofgrid[CellNodes])
64- xCellVolumes:: Array{Tv, 1} = FE. dofgrid[CellVolumes]
65- xCellRegions = FE. dofgrid[CellRegions]
66- xCellDofs:: DofMapTypes{Ti} = FE[CellDofs]
67- qf = QuadratureRule {T, EG} (max (4 , 2 + bonus_quadorder))
68- FEB = FEEvaluator (FE, Identity, qf; T = T)
69- QP = QPInfos (FE. dofgrid; kwargs... )
70-
71- # evaluation of gradient of P1 functions
72- FE3 = H1P1{1 }
73- FES3 = FESpace {FE3, ON_CELLS} (FE. dofgrid)
74- FEBP1 = FEEvaluator (FES3, Gradient, qf; T = T)
75- # evaluation of curl of bubble functions
76- FE4 = H1BUBBLE{1 }
77- FES4 = FESpace {FE4, ON_CELLS} (FE. dofgrid)
78- FEBB = FEEvaluator (FES4, CurlScalar, qf; T = T)
79-
80- if items == []
81- items = 1 : ncells
82- end
83-
84- interiordofs = zeros (Int, nidofs)
85- basisvals:: Array{T, 3} = FEB. cvals
86- basisvalsP1:: Array{T, 3} = FEBP1. cvals
87- basisvalsB:: Array{T, 3} = FEBB. cvals
88- IMM_face = zeros (T, nidofs, interior_offset)
89- IMM = zeros (T, nidofs, nidofs)
90- lb = zeros (T, nidofs)
91- temp:: T = 0
92- data_eval = zeros (T, ncomponents)
93- for cell in items
94- # update basis
95- update_basis! (FEB, cell)
96- update_basis! (FEBP1, cell)
97- update_basis! (FEBB, cell)
98- fill! (IMM, 0 )
99- fill! (IMM_face, 0 )
100- fill! (lb, 0 )
101-
102- QP. item = cell
103- QP. cell = cell
104- QP. region = xCellRegions[cell]
105-
106- # quadrature loop
107- for i in 1 : length (qf. w)
108- # right-hand side : f times grad(P1),curl(bubble)
109- eval_trafo! (QP. x, FEB. L2G, FEB. xref[i])
110- QP. xref = FEB. xref[i]
111- data (data_eval, QP)
112- data_eval .*= xCellVolumes[cell] * qf. w[i]
113- for dof in 1 : nidofs
114- for k in 1 : ncomponents
115- if dof < 3
116- lb[dof] += data_eval[k] * basisvalsP1[k, dof, i]
117- elseif dof == 3
118- lb[dof] += data_eval[k] * basisvalsB[k, 1 , i]
119- end
120- end
121-
122- # mass matrix of interior basis functions
123- for dof2 in 1 : (nidofs - 1 )
124- temp = 0
125- for k in 1 : ncomponents
126- temp += basisvals[k, interior_offset + dof, i] * basisvalsP1[k, dof2, i]
127- end
128- IMM[dof2, dof] += temp * xCellVolumes[cell] * qf. w[i]
129- end
130- temp = 0
131- for k in 1 : ncomponents
132- temp += basisvals[k, interior_offset + dof, i] * basisvalsB[k, 1 , i]
133- end
134- IMM[3 , dof] += temp * xCellVolumes[cell] * qf. w[i]
135-
136- # mass matrix of face basis functions
137- for dof2 in 1 : interior_offset
138- temp = 0
139- if dof < 3
140- for k in 1 : ncomponents
141- temp += basisvalsP1[k, dof, i] * basisvals[k, dof2, i]
142- end
143- elseif dof == 3
144- for k in 1 : ncomponents
145- temp += basisvalsB[k, 1 , i] * basisvals[k, dof2, i]
146- end
147- end
148- IMM_face[dof, dof2] += temp * xCellVolumes[cell] * qf. w[i]
149- end
150- end
151- end
152-
153- # subtract face interpolation from right-hand side
154- for dof in 1 : nidofs, dof2 in 1 : interior_offset
155- lb[dof] -= Target[xCellDofs[dof2, cell]] * IMM_face[dof, dof2]
156- end
52+ interpolate! (Target, FE, ON_FACES, exact_function!; items = subitems, kwargs... )
15753
158- # solve local system
159- for dof in 1 : nidofs
160- interiordofs[dof] = xCellDofs[interior_offset + dof, cell]
161- end
162- Target[interiordofs] = IMM \ lb
163- end
164- return
54+ # set interior dofs such that moments with ∇P1 and curl(b) are preserved
55+ # (b is the cell bubble)
56+ get_interpolator (FE, ON_CELLS). evaluate! (Target, exact_function!, items; kwargs... )
16557end
16658
16759# # only normalfluxes on faces
0 commit comments