Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InterfaceValues for DG interface integration #743

Merged
Merged
Show file tree
Hide file tree
Changes from 129 commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
000eab4
InterfaceValues initial implementation + reinit!
AbdAlazezAhmed Apr 23, 2023
e9d1c0e
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed Apr 24, 2023
5568746
Common functionality grouped
AbdAlazezAhmed Apr 25, 2023
aa236b3
Merge branch 'face-integration-experiments' of https://github.com/Abd…
AbdAlazezAhmed Apr 25, 2023
a4754f2
fixed copying and assignment errors
AbdAlazezAhmed Apr 25, 2023
d69b2cd
back to short circuiting
AbdAlazezAhmed Apr 25, 2023
edfa09c
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed May 10, 2023
b06dc9e
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed May 15, 2023
c4889e2
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed May 23, 2023
eb3afb9
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed Jun 17, 2023
60573db
Starting point
AbdAlazezAhmed Jun 18, 2023
5e81b66
CodeGen
AbdAlazezAhmed Jun 18, 2023
0065423
reinit!
AbdAlazezAhmed Jun 18, 2023
c5a530f
Initial docs
AbdAlazezAhmed Jun 18, 2023
60a842a
just a comment
AbdAlazezAhmed Jun 18, 2023
57e03b2
Merge branch 'face-integration-experiments' of https://github.com/Abd…
AbdAlazezAhmed Jun 18, 2023
f3b1f49
remove scalar
AbdAlazezAhmed Jun 18, 2023
09fa6bd
more methods + docs
AbdAlazezAhmed Jun 19, 2023
79bb40f
docs edit
AbdAlazezAhmed Jun 19, 2023
698874a
2*nbf -> nbf
AbdAlazezAhmed Jun 19, 2023
e1e7532
discontinuous ip assertion
AbdAlazezAhmed Jun 19, 2023
49e3429
Missed issue with iv
AbdAlazezAhmed Jun 19, 2023
cfb5ddf
initial `InterfaceIterator`
AbdAlazezAhmed Jun 19, 2023
c6bf804
nqp ->nqp
AbdAlazezAhmed Jun 19, 2023
42d59a7
undouble nqp
AbdAlazezAhmed Jun 19, 2023
9c60a0b
InterfaceOrientationInfo
AbdAlazezAhmed Jun 19, 2023
de83a50
`get_neighbor_quadp` by searching for coordinates
AbdAlazezAhmed Jun 19, 2023
9cfce1b
docs
AbdAlazezAhmed Jun 19, 2023
10cf989
Interface* -> Face*
AbdAlazezAhmed Jun 20, 2023
b86e289
some exports
AbdAlazezAhmed Jun 20, 2023
34d72de
docs
AbdAlazezAhmed Jun 20, 2023
c03c787
Revert "Interface* -> Face*"
AbdAlazezAhmed Jun 20, 2023
5f6324a
iterate over intrfaces only
AbdAlazezAhmed Jun 20, 2023
c1f6a39
reuse cellcache in interfacecache
AbdAlazezAhmed Jun 20, 2023
ef53949
fixed typo
AbdAlazezAhmed Jun 20, 2023
d221888
docs & exports
AbdAlazezAhmed Jun 20, 2023
8b18c3d
error fixes
AbdAlazezAhmed Jun 20, 2023
c302fca
Make this PR for `InterfaceValues` only.
AbdAlazezAhmed Jun 20, 2023
76f6cb0
No mirroring for 1D elements
AbdAlazezAhmed Jun 21, 2023
1193c42
spatial_coordinate
AbdAlazezAhmed Jun 21, 2023
08c4af0
Initial tests + implementation change.
AbdAlazezAhmed Jun 21, 2023
851fe05
reorder includes
AbdAlazezAhmed Jun 21, 2023
b10ece4
initial tests copied from `FaveValues` tests
AbdAlazezAhmed Jun 22, 2023
1dadcda
`function*` initial implementation + copy
AbdAlazezAhmed Jun 22, 2023
b432c91
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed Jun 23, 2023
c28f0b2
Make this PR of scalar interpolations
AbdAlazezAhmed Jun 23, 2023
db877bf
Initial transformation. works for 1D, 2D and 3D.
AbdAlazezAhmed Jun 25, 2023
aff0602
Just for testing with julia 1.6, will revert
AbdAlazezAhmed Jun 26, 2023
5df1627
Revert "Just for testing with julia 1.6, will revert"
AbdAlazezAhmed Jun 26, 2023
232b2a8
1.6
AbdAlazezAhmed Jun 26, 2023
abd32ca
some code cleanup
AbdAlazezAhmed Jun 26, 2023
7732a11
Remove get_neighbor_quadp
AbdAlazezAhmed Jun 26, 2023
874b492
remove repeated facevalues copy test
AbdAlazezAhmed Jun 26, 2023
d34b035
With normal & without normal jump.
AbdAlazezAhmed Jun 26, 2023
1de61c9
Better norals + error test
AbdAlazezAhmed Jun 27, 2023
15d24cc
Change docs for `InterfaceOrientationInfo`
AbdAlazezAhmed Jun 27, 2023
687a3e2
consistent naming (neighbor -> other)
AbdAlazezAhmed Jun 27, 2023
acbfd5b
Typo in facevalues?
AbdAlazezAhmed Jun 28, 2023
5c78c61
Requested edits
AbdAlazezAhmed Jun 28, 2023
c5c222c
Jump integration test
AbdAlazezAhmed Jun 29, 2023
cb394d8
Benchmarks
AbdAlazezAhmed Jul 1, 2023
56763b7
Better performance by calculating transformation matrix without inverse
AbdAlazezAhmed Jul 1, 2023
d82f177
How did I push this thing??
AbdAlazezAhmed Jul 4, 2023
e7940cf
function* stuff
AbdAlazezAhmed Jul 5, 2023
050ac5e
FaceValues
AbdAlazezAhmed Jul 6, 2023
60bf549
use simple definition
AbdAlazezAhmed Jul 6, 2023
6a7a194
Merge branch 'master' of https://github.com/Ferrite-FEM/Ferrite.jl in…
AbdAlazezAhmed Jul 6, 2023
600fae6
better coverage?
AbdAlazezAhmed Jul 6, 2023
38d1581
UwU
AbdAlazezAhmed Jul 6, 2023
fe47865
Merge branch 'master' of https://github.com/AbdAlazezAhmed/Ferrite.jl…
AbdAlazezAhmed Jul 6, 2023
b1ce481
Vroom
AbdAlazezAhmed Jul 6, 2023
02cc036
Requested edits
AbdAlazezAhmed Jul 6, 2023
ee7163e
Updates:
AbdAlazezAhmed Jul 23, 2023
bf2cc74
Use FerriteViz transformations
AbdAlazezAhmed Jul 23, 2023
2a6baad
benchmarks
AbdAlazezAhmed Jul 24, 2023
0453aed
Only update values and gradients when needed
AbdAlazezAhmed Jul 24, 2023
823847f
Merge branch 'master' of https://github.com/AbdAlazezAhmed/Ferrite.jl…
AbdAlazezAhmed Jul 24, 2023
6558515
Use `InterfaceIterator`
AbdAlazezAhmed Jul 24, 2023
aae8c7d
Update docs
AbdAlazezAhmed Jul 24, 2023
eb369a8
iv.update_quadrature_points[] defaults to true for 2D elements *alway…
AbdAlazezAhmed Jul 24, 2023
750c2bf
docs typo
AbdAlazezAhmed Jul 24, 2023
ed92be2
Changed the way orientation is calculated
AbdAlazezAhmed Jul 28, 2023
fae501b
Merge branch 'master' of https://github.com/AbdAlazezAhmed/Ferrite.jl…
AbdAlazezAhmed Jul 28, 2023
bcb041e
Reversed face test
AbdAlazezAhmed Jul 28, 2023
f3c4411
oopsie
AbdAlazezAhmed Jul 28, 2023
e60c1cb
Make it work for general unstructured mesh
AbdAlazezAhmed Jul 28, 2023
b3e35e6
Don't use |>
AbdAlazezAhmed Jul 29, 2023
4d02580
Edits to make it work with pyramids/wedges?
AbdAlazezAhmed Jul 29, 2023
96af088
Docs
AbdAlazezAhmed Jul 29, 2023
ca53d09
Some vectoriztion?
AbdAlazezAhmed Jul 29, 2023
a2d16d3
UwU
AbdAlazezAhmed Jul 29, 2023
7f1a24d
Merge branch 'master' of https://github.com/AbdAlazezAhmed/Ferrite.jl…
AbdAlazezAhmed Aug 29, 2023
5153fde
update stuff
AbdAlazezAhmed Aug 29, 2023
c6b583b
Now everything works except for edges and pyramids
AbdAlazezAhmed Aug 29, 2023
d678133
Now everything works UwU
AbdAlazezAhmed Aug 29, 2023
c63bba4
there - here
AbdAlazezAhmed Sep 2, 2023
ae75309
minor doc change
AbdAlazezAhmed Sep 2, 2023
93f191c
suggested edits
AbdAlazezAhmed Sep 3, 2023
bad45f4
update -> update_interface_transformation!
AbdAlazezAhmed Sep 3, 2023
e4ccf6a
Merge remote-tracking branch 'origin/master' into face-integration-ex…
fredrikekre Sep 4, 2023
42573e7
getcoordinates
AbdAlazezAhmed Sep 8, 2023
9b74203
use_element_a -> here
AbdAlazezAhmed Sep 8, 2023
852fcaa
remove geometric_value(iv)
AbdAlazezAhmed Sep 8, 2023
5603afd
docs
AbdAlazezAhmed Sep 8, 2023
c8258ea
Multiple dispatch + don't pass grid
AbdAlazezAhmed Sep 8, 2023
bd05745
Revert "Some vectoriztion?"
AbdAlazezAhmed Sep 8, 2023
c785e12
nice
AbdAlazezAhmed Sep 8, 2023
b42fbde
Update src/FEValues/face_integrals.jl
AbdAlazezAhmed Sep 9, 2023
1981c81
move from common file
fredrikekre Sep 15, 2023
ed7f14d
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed Sep 15, 2023
9f117dd
add case for <:Vec
AbdAlazezAhmed Sep 15, 2023
675f0ab
Revert "add case for <:Vec"
fredrikekre Sep 15, 2023
2a6bed3
add back vec dofs
fredrikekre Sep 16, 2023
7b081c3
s/face_values_(a|b)/(t)here/g
fredrikekre Sep 16, 2023
85b2286
more here/there changes
fredrikekre Sep 18, 2023
e87fb5a
constructor fixes
fredrikekre Sep 18, 2023
4264702
get_face_refshape
AbdAlazezAhmed Sep 18, 2023
76d36bd
Better type stability
AbdAlazezAhmed Sep 19, 2023
6dc6117
branching
AbdAlazezAhmed Sep 19, 2023
de79e40
Fix printing
AbdAlazezAhmed Sep 20, 2023
933fe78
1D error path
AbdAlazezAhmed Sep 20, 2023
9d5437b
use linear indices
fredrikekre Sep 20, 2023
59cccd0
ws
fredrikekre Sep 20, 2023
b93937c
small fixes
fredrikekre Sep 20, 2023
9010f86
TMP
fredrikekre Sep 21, 2023
cec25a4
function_* tests + some changes to pass tests
AbdAlazezAhmed Sep 21, 2023
159b4a1
Oopsie
AbdAlazezAhmed Sep 21, 2023
11d0a9a
shape_value here
AbdAlazezAhmed Sep 21, 2023
c4f6ed9
Better test coverage?
AbdAlazezAhmed Sep 22, 2023
bed6b53
More codegen
AbdAlazezAhmed Oct 1, 2023
ec55515
Single `u` dispatch
AbdAlazezAhmed Oct 1, 2023
1048d49
Merge branch 'Ferrite-FEM:master' into face-integration-experiments
AbdAlazezAhmed Oct 1, 2023
1f966e8
Merge branch 'face-integration-experiments' of https://github.com/Abd…
AbdAlazezAhmed Oct 1, 2023
347e796
another constructor
AbdAlazezAhmed Oct 7, 2023
fafc549
test
AbdAlazezAhmed Oct 7, 2023
e7d31f9
remove function_(curl|divergence|symmetricgradient)
AbdAlazezAhmed Oct 7, 2023
07ac92f
default for facevalues_there
AbdAlazezAhmed Oct 7, 2023
e21c0fb
docs for now
AbdAlazezAhmed Oct 8, 2023
754eb75
minor simplifications
fredrikekre Oct 8, 2023
32799be
move back files
fredrikekre Oct 8, 2023
84a24ab
move interfacetransofrmation
fredrikekre Oct 8, 2023
87ce37c
ws
fredrikekre Oct 8, 2023
e765843
Remove dispatch with u_here and u_there
AbdAlazezAhmed Oct 12, 2023
3c7f366
here - there
AbdAlazezAhmed Oct 12, 2023
6eb4680
4:32 AM push
AbdAlazezAhmed Oct 12, 2023
6cee960
Revert "4:32 AM push"
AbdAlazezAhmed Oct 12, 2023
0d631c0
test dof_range
AbdAlazezAhmed Oct 12, 2023
1cc5e30
Some fix for mixed grids with two cell types
AbdAlazezAhmed Oct 12, 2023
2532e58
Minor changes
fredrikekre Oct 16, 2023
a7cd849
enable test
AbdAlazezAhmed Oct 17, 2023
40e4499
getcoordinates
AbdAlazezAhmed Oct 17, 2023
1e1f7c5
getcoordinates v2 ?
AbdAlazezAhmed Oct 17, 2023
6ccb524
VectorizedInterpolation tests + constructor
AbdAlazezAhmed Oct 17, 2023
ce1886d
5AM push
AbdAlazezAhmed Oct 21, 2023
b7a32cf
DummyRefShapes module for testing
AbdAlazezAhmed Oct 26, 2023
1d61ac4
Merge branch 'master' of https://github.com/AbdAlazezAhmed/Ferrite.jl…
AbdAlazezAhmed Nov 10, 2023
d7de299
Bump Tensors to 1.14
AbdAlazezAhmed Nov 10, 2023
8e665d6
Minor changes while reviewing
fredrikekre Dec 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion benchmark/benchmarks-assembly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ for spatial_dim ∈ 1:3
for geo_type ∈ FerriteBenchmarkHelper.geo_types_for_spatial_dim(spatial_dim)
COMMON_LOCAL_ASSEMBLY["spatial-dim",spatial_dim][string(geo_type)] = BenchmarkGroup()

grid = generate_grid(geo_type, tuple(repeat([1], spatial_dim)...));
grid = generate_grid(geo_type, tuple(repeat([2], spatial_dim)...));
topology = ExclusiveTopology(grid)
ip_geo = Ferrite.default_interpolation(geo_type)
ref_type = FerriteBenchmarkHelper.getrefshape(geo_type)

Expand Down Expand Up @@ -66,6 +67,20 @@ for spatial_dim ∈ 1:3

LAGRANGE_SUITE["ritz-galerkin"]["face-flux"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $fsv, shape_gradient, shape_value, *)
LAGRANGE_SUITE["petrov-galerkin"]["face-flux"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $fsv, shape_gradient, $fsv2, shape_value, *)

ip = DiscontinuousLagrange{ref_type, order}()
isv = InterfaceValues(qr_face, ip, ip_geo; geom_interpol_b = ip_geo);
isv2 = InterfaceValues(qr_face, ip, ip_geo; geom_interpol_b = ip_geo);
dh = DofHandler(grid)
add!(dh, :u, ip)
close!(dh)

LAGRANGE_SUITE["ritz-galerkin"]["interface-{grad}⋅[[val]]"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_interfaces($dh, $isv, shape_gradient_average, shape_value_jump, ⋅)
LAGRANGE_SUITE["petrov-galerkin"]["interface-{grad}⋅[[val]]"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_interfaces($dh, $isv, shape_gradient_average, $isv2, shape_value_jump, ⋅)

LAGRANGE_SUITE["ritz-galerkin"]["interface-interior-penalty"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_interfaces($dh, $isv, shape_value_jump, shape_value_jump, ⋅)
LAGRANGE_SUITE["petrov-galerkin"]["interface-interior-penalty"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_interfaces($dh, $isv, shape_value_jump, $isv2, shape_value_jump, ⋅)

end
end
end
Expand Down
50 changes: 50 additions & 0 deletions benchmark/helper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@ function _generalized_ritz_galerkin_assemble_local_matrix(grid::Ferrite.Abstract
f
end

function _generalized_ritz_galerkin_assemble_interfaces(dh::Ferrite.AbstractDofHandler, interfacevalues::InterfaceValues{<: FaceValues{<: Ferrite.InterpolationByDim{dim}}}, f_shape, f_test, op) where {dim}
n_basefuncs = getnbasefunctions(interfacevalues)

K = zeros(ndofs(dh), ndofs(dh))

for ic in InterfaceIterator(dh)
reinit!(interfacevalues, ic)
for q_point in 1:getnquadpoints(interfacevalues)
dΓ = getdetJdV(interfacevalues, q_point)
for i in 1:n_basefuncs
test = f_test(interfacevalues, q_point, i)
f_test == shape_value_jump && (test *= getnormal(interfacevalues, q_point))
for j in 1:n_basefuncs
shape = f_shape(interfacevalues, q_point, j)
f_shape == shape_value_jump && (shape *= getnormal(interfacevalues, q_point))
K[interfacedofs(ic)[i], interfacedofs(ic)[j]] += op(test, shape) * dΓ
end
end
end
end

K
end

# Minimal Petrov-Galerkin type local assembly loop. We assume that both function spaces share the same integration rule. Test is applied from the left.
function _generalized_petrov_galerkin_assemble_local_matrix(grid::Ferrite.AbstractGrid, cellvalues_shape::CellValues{<: Ferrite.InterpolationByDim{dim}}, f_shape, cellvalues_test::CellValues{<: Ferrite.InterpolationByDim{dim}}, f_test, op) where {dim}
n_basefuncs_shape = getnbasefunctions(cellvalues_shape)
Expand Down Expand Up @@ -122,6 +146,32 @@ function _generalized_petrov_galerkin_assemble_local_matrix(grid::Ferrite.Abstra
f
end

function _generalized_petrov_galerkin_assemble_interfaces(dh::Ferrite.AbstractDofHandler, interfacevalues_shape::InterfaceValues{<: FaceValues{<: Ferrite.InterpolationByDim{dim}}}, f_shape, interfacevalues_test::InterfaceValues{<: FaceValues{<: Ferrite.InterpolationByDim{dim}}}, f_test, op) where {dim}
n_basefuncs_shape = getnbasefunctions(interfacevalues_shape)
n_basefuncs_test = getnbasefunctions(interfacevalues_test)

K = zeros(ndofs(dh), ndofs(dh))

for ic in InterfaceIterator(dh)
reinit!(interfacevalues_shape, ic)
reinit!(interfacevalues_test, ic)
for q_point in 1:getnquadpoints(interfacevalues_shape)
dΓ = getdetJdV(interfacevalues_test, q_point)
for i in 1:n_basefuncs_test
test = f_test(interfacevalues_test, q_point, i)
f_test == shape_value_jump && (test *= getnormal(interfacevalues_test, q_point))
for j in 1:n_basefuncs_shape
shape = f_shape(interfacevalues_shape, q_point, j)
f_shape == shape_value_jump && (shape *= getnormal(interfacevalues_shape, q_point))
K[interfacedofs(ic)[i], interfacedofs(ic)[j]] += op(test, shape) * dΓ
end
end
end
end

K
end

function _assemble_mass(dh, cellvalues, sym)
n_basefuncs = getnbasefunctions(cellvalues)
Me = zeros(n_basefuncs, n_basefuncs)
Expand Down
4 changes: 3 additions & 1 deletion docs/src/devdocs/elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ Ferrite.getvertexinstances
Ferrite.filterfaces
Ferrite.filteredges
Ferrite.filtervertices
Ferrite.element_to_face_transformation
Ferrite.face_to_element_transformation
Ferrite.InterfaceTransformation
```

18 changes: 18 additions & 0 deletions docs/src/reference/fevalues.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,21 @@ FaceValues
getcurrentface
getnquadpoints(::FaceValues)
```

## [InterfaceValues](@id reference-interfacevalues)

All of the methods for [`FaceValues`](@ref) apply for `InterfaceValues` as well.
In addition, there are some methods that are unique for `InterfaceValues`:

```@docs
InterfaceValues
shape_value_average
shape_value_jump
shape_gradient_average
shape_gradient_jump
function_value_average
function_value_jump
function_gradient_average
function_gradient_jump
transform_interface_points!
```
40 changes: 25 additions & 15 deletions src/FEValues/common_values.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ getnquadpoints(fe::FaceValues) = getnquadpoints(fe.qr, fe.current_face[])
getdetJdV(fe_v::AbstractValues, q_point::Int)

Return the product between the determinant of the Jacobian and the quadrature
point weight for the given quadrature point: ``\\det(J(\\mathbf{x})) w_q``
point weight for the given quadrature point: ``\\det(J(\\mathbf{x})) w_q``.

This value is typically used when one integrates a function on a
finite element cell or face as
Expand All @@ -78,6 +78,12 @@ quadrature point `q_point`.
@propagate_inbounds shape_value(cv::CellValues, q_point::Int, base_func::Int) = cv.N[base_func, q_point]
@propagate_inbounds shape_value(bv::FaceValues, q_point::Int, base_func::Int) = bv.N[base_func, q_point, bv.current_face[]]

"""
geometric_value(fe_v::AbstractValues, q_point::Int, base_function::Int)

Return the value of shape function `base_function` used for geometric interpolation evaluated in
quadrature point `q_point`.
"""
@propagate_inbounds geometric_value(cv::CellValues, q_point::Int, base_func::Int) = cv.M[base_func, q_point]
@propagate_inbounds geometric_value(bv::FaceValues, q_point::Int, base_func::Int) = bv.M[base_func, q_point, bv.current_face[]]

AbdAlazezAhmed marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -174,13 +180,14 @@ function function_gradient(fe_v::AbstractValues, q_point::Int, u::AbstractVector
end

# TODO: Deprecate this, nobody is using this in practice...
function function_gradient(fe_v::AbstractValues, q_point::Int, u::AbstractVector{<:Vec})
function function_gradient(fe_v::AbstractValues, q_point::Int, u::AbstractVector{<:Vec}, dof_range = eachindex(u))
n_base_funcs = getnbasefunctions(fe_v)
length(u) == n_base_funcs || throw_incompatible_dof_length(length(u), n_base_funcs)
length(dof_range) == n_base_funcs || throw_incompatible_dof_length(length(dof_range), n_base_funcs)
@boundscheck checkbounds(u, dof_range)
@boundscheck checkquadpoint(fe_v, q_point)
grad = function_gradient_init(fe_v, u)
@inbounds for i in 1:n_base_funcs
grad += u[i] ⊗ shape_gradient(fe_v, q_point, i)
@inbounds for (i, j) in pairs(dof_range)
grad += u[j] ⊗ shape_gradient(fe_v, q_point, i)
end
return grad
end
Expand All @@ -206,13 +213,7 @@ The symmetric gradient of a scalar function is computed as
where ``\\mathbf{u}_i`` are the nodal values of the function.
"""
function function_symmetric_gradient(fe_v::AbstractValues, q_point::Int, u::AbstractVector, dof_range = eachindex(u))
grad = function_gradient(fe_v, q_point, u, dof_range)
return symmetric(grad)
end

# TODO: Deprecate this, nobody is using this in practice...
function function_symmetric_gradient(fe_v::AbstractValues, q_point::Int, u::AbstractVector{<:Vec})
grad = function_gradient(fe_v, q_point, u)
grad = dof_range == eachindex(u) ? function_gradient(fe_v, q_point, u) : function_gradient(fe_v, q_point, u, dof_range) # Workaround for calling deprecated method
return symmetric(grad)
end

Expand Down Expand Up @@ -241,6 +242,15 @@ function function_divergence(fe_v::AbstractValues, q_point::Int, u::AbstractVect
return diverg
end

"""
function_curl(fe_v::AbstractValues, q_point::Int, u::AbstractVector)

Compute the curl of the vector valued function in a quadrature point.

The curl of a vector valued functions in the quadrature point ``\\mathbf{x}_q)`` is computed as
``\\mathbf{\\nabla} \\times \\mathbf{u}(\\mathbf{x_q}) = \\sum\\limits_{i = 1}^n \\mathbf{\\nabla} N_i \\times (\\mathbf{x_q}) \\cdot \\mathbf{u}_i``
where ``\\mathbf{u}_i`` are the nodal values of the function.
"""
function_curl(fe_v::AbstractValues, q_point::Int, u::AbstractVector, dof_range = eachindex(u)) =
curl_from_gradient(function_gradient(fe_v, q_point, u, dof_range))

Expand All @@ -257,11 +267,11 @@ coordinates of the cell.
The coordinate is computed, using the geometric interpolation, as
``\\mathbf{x} = \\sum\\limits_{i = 1}^n M_i (\\mathbf{x}) \\mathbf{\\hat{x}}_i``
"""
function spatial_coordinate(fe_v::AbstractValues, q_point::Int, x::AbstractVector{Vec{dim,T}}) where {dim,T}
function spatial_coordinate(fe_v::AbstractValues, q_point::Int, x::AbstractVector{<:Vec})
n_base_funcs = getngeobasefunctions(fe_v)
length(x) == n_base_funcs || throw_incompatible_coord_length(length(x), n_base_funcs)
@boundscheck checkquadpoint(fe_v, q_point)
vec = zero(Vec{dim,T})
vec = zero(eltype(x))
@inbounds for i in 1:n_base_funcs
vec += geometric_value(fe_v, q_point, i) * x[i]
end
Expand All @@ -273,7 +283,7 @@ function Base.show(io::IO, ::MIME"text/plain", fe_v::AbstractValues)
end

# copy
for ValueType in (CellValues, FaceValues)
for ValueType in (CellValues, FaceValues, InterfaceValues)
args = [:(copy(cv.$fname)) for fname in fieldnames(ValueType)]
@eval begin
function Base.copy(cv::$ValueType)
Expand Down
86 changes: 83 additions & 3 deletions src/FEValues/face_integrals.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
"""
face_to_element_transformation(point::Vec, ::Type{<:AbstractRefShape}, face::Int)

Transform quadrature point from face's reference (N-1)D coordinates to ND coordinates on the
cell's face.
Transform quadrature point from face's reference coordinates to coordinates on the
cell's face, increasing the number of dimensions by one.
"""
face_to_element_transformation

"""
element_to_face_transformation(point::AbstractVector, cell::AbstractCell{AbstractRefShape}, face::Int)

Transform quadrature point from cell's coordinates to the face's reference coordinates, decreasing the number of dimensions by one.
AbdAlazezAhmed marked this conversation as resolved.
Show resolved Hide resolved
This is the inverse of `face_to_element_transformation`.
This is the inverse of `face_to_element_transformation`.
"""
element_to_face_transformation
termi-official marked this conversation as resolved.
Show resolved Hide resolved

"""
weighted_normal(J::AbstractTensor, fv::FaceValues, face::Int)
weighted_normal(J::AbstractTensor, ::Type{<:AbstractRefShape}, face::Int)
Expand Down Expand Up @@ -62,12 +71,20 @@ end
##################

# Mapping from to 0D node to 1D line vertex.
function face_to_element_transformation(::Vec{0, T}, ::Type{RefLine}, face::Int) where {T}
function face_to_element_transformation(::Union{Vec{0, T},Vec{1, T}}, ::Type{RefLine}, face::Int) where {T}
face == 1 && return Vec{1, T}(( -one(T),))
face == 2 && return Vec{1, T}(( one(T),))
throw(ArgumentError("unknown face number"))
end

# Mapping from 1D line to point.
function element_to_face_transformation(point::Vec{1, T}, ::Type{RefLine}, face::Int) where T
x = point[]
face == 1 && return Vec(-x)
face == 2 && return Vec( x)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(::Tensor{2,1,T}, ::Type{RefLine}, face::Int) where {T}
face == 1 && return Vec{1,T}((-one(T),))
face == 2 && return Vec{1,T}(( one(T),))
Expand All @@ -88,6 +105,16 @@ function face_to_element_transformation(point::Vec{1, T}, ::Type{RefQuadrilatera
throw(ArgumentError("unknown face number"))
end

# Mapping from 2D face of a quadrilateral to 1D line.
function element_to_face_transformation(point::Vec{2, T}, ::Type{RefQuadrilateral}, face::Int) where T
x, y = point
face == 1 && return Vec( x)
face == 2 && return Vec( y)
face == 3 && return Vec( -x)
face == 4 && return Vec( -y)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,2}, ::Type{RefQuadrilateral}, face::Int)
@inbounds begin
face == 1 && return Vec{2}(( J[2,1], -J[1,1]))
Expand All @@ -111,6 +138,15 @@ function face_to_element_transformation(point::Vec{1, T}, ::Type{RefTriangle},
throw(ArgumentError("unknown face number"))
end

# Mapping from 2D face of a triangle to 1D line.
function element_to_face_transformation(point::Vec{2, T}, ::Type{RefTriangle}, face::Int) where T
x, y = point
face == 1 && return Vec( one(T) - x * 2)
face == 2 && return Vec( one(T) - y * 2 )
face == 3 && return Vec( x * 2 - one(T))
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,2}, ::Type{RefTriangle}, face::Int)
@inbounds begin
face == 1 && return Vec{2}((-(J[2,1] - J[2,2]), J[1,1] - J[1,2]))
Expand All @@ -136,6 +172,18 @@ function face_to_element_transformation(point::Vec{2, T}, ::Type{RefHexahedron},
throw(ArgumentError("unknown face number"))
end

# Mapping from 3D face of a hexahedron to 2D quadrilateral.
function element_to_face_transformation(point::Vec{3, T}, ::Type{RefHexahedron}, face::Int) where T
x, y, z = point
face == 1 && return Vec( y, x)
face == 2 && return Vec( x, z)
face == 3 && return Vec( y, z)
face == 4 && return Vec( -x, z)
face == 5 && return Vec( z, y)
face == 6 && return Vec( x, y)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,3}, ::Type{RefHexahedron}, face::Int)
@inbounds begin
face == 1 && return J[:,2] × J[:,1]
Expand All @@ -162,6 +210,16 @@ function face_to_element_transformation(point::Vec{2, T}, ::Type{RefTetrahedron}
throw(ArgumentError("unknown face number"))
end

# Mapping from 3D face of a tetrahedon to 2D triangle.
function element_to_face_transformation(point::Vec{3, T}, ::Type{RefTetrahedron}, face::Int) where T
x, y, z = point
face == 1 && return Vec( one(T)-x-y, y)
face == 2 && return Vec( one(T)-z-x, x)
face == 3 && return Vec( x, y)
face == 4 && return Vec( one(T)-y-z, z)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,3}, ::Type{RefTetrahedron}, face::Int)
@inbounds begin
face == 1 && return J[:,2] × J[:,1]
Expand All @@ -188,6 +246,17 @@ function face_to_element_transformation(point::Vec{2, T}, ::Type{RefPrism}, face
throw(ArgumentError("unknown face number"))
end

# Mapping from 3D face of a wedge to 2D triangle or 2D quadrilateral.
function element_to_face_transformation(point::Vec{3, T}, ::Type{RefPrism}, face::Int) where T
x, y, z = point
face == 1 && return Vec( one(T)-x-y, y)
face == 2 && return Vec( 2*x - one(T), 2*z - one(T) )
face == 3 && return Vec( 2*(one(T) - y) - one(T), 2*z - one(T) )
face == 4 && return Vec( 2*y - one(T), 2*z - one(T) )
face == 5 && return Vec( one(T) - x - y, x)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,3}, ::Type{RefPrism}, face::Int)
@inbounds begin
face == 1 && return J[:,2] × J[:,1]
Expand All @@ -214,6 +283,17 @@ function face_to_element_transformation(point::Vec{2, T}, ::Type{RefPyramid}, fa
throw(ArgumentError("unknown face number"))
end

# Mapping from 3D face of a pyramid to 2D triangle or 2D quadrilateral.
function element_to_face_transformation(point::Vec{3, T}, ::Type{RefPyramid}, face::Int) where T
x, y, z = point
face == 1 && return Vec( 2*y - one(T), 2*x - one(T))
face == 2 && return Vec( one(T) - z - x, x)
face == 3 && return Vec( one(T) - y - z, z)
face == 4 && return Vec( x - y, y)
face == 5 && return Vec( one(T) - x - z, z)
throw(ArgumentError("unknown face number"))
end

function weighted_normal(J::Tensor{2,3}, ::Type{RefPyramid}, face::Int)
@inbounds begin
face == 1 && return J[:,2] × J[:,1]
Expand Down
Loading