Skip to content

Commit 3027b0e

Browse files
authored
Merge pull request #61 from gridap/duffy_based_integration_for_simplices
Duffy based integration for simplices
2 parents 45363a0 + b76f627 commit 3027b0e

9 files changed

+258
-14
lines changed

Manifest.toml

+41
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
[[Base64]]
44
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
55

6+
[[BinDeps]]
7+
deps = ["Compat", "Libdl", "SHA", "URIParser"]
8+
git-tree-sha1 = "12093ca6cdd0ee547c39b1870e0c9c3f154d9ca9"
9+
uuid = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
10+
version = "0.8.10"
11+
612
[[BinaryProvider]]
713
deps = ["Libdl", "Logging", "SHA"]
814
git-tree-sha1 = "c7361ce8a2129f20b0e05a89f7070820cfed6648"
@@ -21,6 +27,12 @@ git-tree-sha1 = "50b3ae4d643dc27eaff69fb6be06ee094d5500c9"
2127
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
2228
version = "0.7.0"
2329

30+
[[Compat]]
31+
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
32+
git-tree-sha1 = "84aa74986c5b9b898b0d1acaf3258741ee64754f"
33+
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
34+
version = "2.1.0"
35+
2436
[[DataStructures]]
2537
deps = ["InteractiveUtils", "OrderedCollections", "Random", "Serialization", "Test"]
2638
git-tree-sha1 = "ca971f03e146cf144a9e2f2ce59674f5bf0e8038"
@@ -31,10 +43,20 @@ version = "0.15.0"
3143
deps = ["Printf"]
3244
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
3345

46+
[[DelimitedFiles]]
47+
deps = ["Mmap"]
48+
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
49+
3450
[[Distributed]]
3551
deps = ["Random", "Serialization", "Sockets"]
3652
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
3753

54+
[[FastGaussQuadrature]]
55+
deps = ["Compat", "LinearAlgebra", "SpecialFunctions"]
56+
git-tree-sha1 = "769ac4057ed875f433372e9a571a2cb86347d1be"
57+
uuid = "442a2c76-b920-505d-bb47-c5924d526838"
58+
version = "0.3.3"
59+
3860
[[InteractiveUtils]]
3961
deps = ["Markdown"]
4062
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
@@ -62,6 +84,9 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
6284
deps = ["Base64"]
6385
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
6486

87+
[[Mmap]]
88+
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
89+
6590
[[OrderedCollections]]
6691
deps = ["Random", "Serialization", "Test"]
6792
git-tree-sha1 = "c4c13474d23c60d20a67b217f1d7f22a40edf8f1"
@@ -108,13 +133,23 @@ uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
108133
[[Serialization]]
109134
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
110135

136+
[[SharedArrays]]
137+
deps = ["Distributed", "Mmap", "Random", "Serialization"]
138+
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
139+
111140
[[Sockets]]
112141
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
113142

114143
[[SparseArrays]]
115144
deps = ["LinearAlgebra", "Random"]
116145
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
117146

147+
[[SpecialFunctions]]
148+
deps = ["BinDeps", "BinaryProvider", "Libdl", "Test"]
149+
git-tree-sha1 = "0b45dc2e45ed77f445617b99ff2adf0f5b0f23ea"
150+
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
151+
version = "0.7.2"
152+
118153
[[StaticArrays]]
119154
deps = ["InteractiveUtils", "LinearAlgebra", "Random", "Statistics", "Test"]
120155
git-tree-sha1 = "3841b39ed5f047db1162627bf5f80a9cd3e39ae2"
@@ -147,6 +182,12 @@ git-tree-sha1 = "a25d8e5a28c3b1b06d3859f30757d43106791919"
147182
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
148183
version = "0.9.4"
149184

185+
[[URIParser]]
186+
deps = ["Test", "Unicode"]
187+
git-tree-sha1 = "6ddf8244220dfda2f17539fa8c9de20d6c575b69"
188+
uuid = "30578b45-9adc-5946-b283-645ec420af67"
189+
version = "0.4.0"
190+
150191
[[UUIDs]]
151192
deps = ["Random", "SHA"]
152193
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

Project.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.2.0"
55

66
[deps]
77
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
8+
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
89
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
910
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
1011
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"

src/Integration/DuffyQuadratures.jl

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
module DuffyQuadratures
2+
3+
using Gridap
4+
using FastGaussQuadrature: gaussjacobi
5+
using FastGaussQuadrature: gausslegendre
6+
using StaticArrays
7+
8+
export DuffyQuadrature
9+
import Gridap: coordinates
10+
import Gridap: weights
11+
12+
struct DuffyQuadrature{D} <: Quadrature{D}
13+
x::Vector{Point{D,Float64}}
14+
w::Vector{Float64}
15+
end
16+
17+
function DuffyQuadrature{D}(order::Integer) where D
18+
x,w = _duffy_quad_data(order,D)
19+
DuffyQuadrature{D}(x,w)
20+
end
21+
22+
coordinates(q::DuffyQuadrature) = q.x
23+
24+
weights(q::DuffyQuadrature) = q.w
25+
26+
# Helpers
27+
28+
function _duffy_quad_data(order::Integer,D::Int)
29+
30+
beta = 0
31+
dim_to_quad_1d = [
32+
_gauss_jacobi_in_0_to_1(order,(D-1)-(d-1),beta) for d in 1:(D-1) ]
33+
34+
quad_1d = _gauss_legendre_in_0_to_1(order)
35+
push!(dim_to_quad_1d,quad_1d)
36+
37+
x_pos = 1
38+
w_pos = 2
39+
dim_to_xs_1d = [quad_1d[x_pos] for quad_1d in dim_to_quad_1d]
40+
dim_to_ws_1d = [quad_1d[w_pos] for quad_1d in dim_to_quad_1d]
41+
42+
a = 0.5
43+
for d in (D-1):-1:1
44+
ws_1d = dim_to_ws_1d[d]
45+
ws_1d[:] *= a
46+
a *= 0.5
47+
end
48+
49+
x,w = _tensor_product(dim_to_xs_1d,dim_to_ws_1d)
50+
51+
(_duffy_map.(x),w)
52+
53+
end
54+
55+
"""
56+
Duffy map from the n-cube in [0,1]^d to the n-simplex in [0,1]^d
57+
"""
58+
function _duffy_map(q::Point{D,T}) where {D,T}
59+
m = zero(MVector{D,T})
60+
m[1] = q[1]
61+
a = one(T)
62+
for i in 2:D
63+
a *= (1-q[i-1])
64+
m[i] = a*q[i]
65+
end
66+
Point{D,T}(m)
67+
end
68+
69+
_duffy_map(q::Point{1,T}) where T = q
70+
71+
function _gauss_jacobi_in_0_to_1(order,alpha,beta)
72+
n = _npoints_from_order(order)
73+
x,w = gaussjacobi(n,alpha,beta)
74+
_map_to(0,1,x,w)
75+
end
76+
77+
function _gauss_legendre_in_0_to_1(order)
78+
n = _npoints_from_order(order)
79+
x,w = gausslegendre(n)
80+
_map_to(0,1,x,w)
81+
end
82+
83+
"""
84+
Transforms a 1-D quadrature from `[-1,1]` to `[a,b]`, with `a<b`.
85+
"""
86+
function _map_to(a,b,points,weights)
87+
points_ab = 0.5*(b-a)*points .+ 0.5*(a+b)
88+
weights_ab = 0.5*(b-a)*weights
89+
(points_ab, weights_ab)
90+
end
91+
92+
function _npoints_from_order(order)
93+
ceil(Int, (order + 1.0) / 2.0 )
94+
end
95+
96+
function _tensor_product(
97+
dim_to_xs_1d::Vector{Vector{T}},
98+
dim_to_ws_1d::Vector{Vector{W}}) where {T,W}
99+
100+
D = length(dim_to_ws_1d)
101+
@assert D == length(dim_to_xs_1d)
102+
dim_to_n = [length(ws_1d) for ws_1d in dim_to_ws_1d]
103+
n = prod(dim_to_n)
104+
xs = zeros(Point{D,T},n)
105+
ws = zeros(W,n)
106+
cis = CartesianIndices(tuple(dim_to_n...))
107+
m = zero(MVector{D,T})
108+
_tensor_product!(xs,ws,dim_to_xs_1d,dim_to_ws_1d,cis,m)
109+
(xs,ws)
110+
end
111+
112+
function _tensor_product!(
113+
xs,ws,dim_to_xs_1d,dim_to_ws_1d,cis::CartesianIndices{D},m) where D
114+
k = 1
115+
for ci in cis
116+
w = 1.0
117+
for d in 1:D
118+
xs_1d = dim_to_xs_1d[d]
119+
ws_1d = dim_to_ws_1d[d]
120+
i = ci[d]
121+
xi = xs_1d[i]
122+
wi = ws_1d[i]
123+
w *= wi
124+
m[d] = xi
125+
end
126+
xs[k] = m
127+
ws[k] = w
128+
k += 1
129+
end
130+
end
131+
132+
end # module
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module QuadratureFactories
2+
3+
using Gridap
4+
using Gridap.Helpers
5+
6+
import Gridap: Quadrature
7+
8+
"""
9+
Factory function to create Quadrature objects in a convenient way
10+
"""
11+
function Quadrature(p::Polytope,order::Int)
12+
Quadrature(p.extrusion.array.data,order=order)
13+
end
14+
15+
function Quadrature(extrusion::NTuple{D,Int};order::Int) where D
16+
17+
if all(extrusion .== HEX_AXIS)
18+
return TensorProductQuadrature(orders=tuple(fill(order,D)...))
19+
20+
elseif all(extrusion .== TET_AXIS)
21+
return DuffyQuadrature{D}(order)
22+
23+
else
24+
@notimplemented
25+
end
26+
27+
end
28+
29+
end # module

src/Integration/Quadratures.jl

-14
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ coordinates(::Quadrature{D} where D)::Array{Point{D,Float64},1} = @abstractmetho
2525

2626
weights(::Quadrature)::Array{Float64,1} = @abstractmethod
2727

28-
# Factories
29-
30-
"""
31-
Factory function to create Quadrature objects in a convenient way
32-
"""
33-
function Quadrature(extrusion::NTuple{D,Int};order::Int) where D
34-
_quadrature(extrusion,order)
35-
end
36-
3728
# Concrete structs
3829

3930
"""
@@ -62,11 +53,6 @@ weights(self::TensorProductQuadrature) = self.weights
6253

6354
# Helpers
6455

65-
function _quadrature(extrusion::NTuple{D,Int},order) where D
66-
@notimplementedif any(extrusion == TET_AXIS)
67-
TensorProductQuadrature(orders=tuple(fill(order,D)...))
68-
end
69-
7056
function _tensor_product(quads,npoints,::Val{D}) where D
7157
@assert length(quads) == D
7258
@assert length(npoints) == D

src/Integration/files.jl

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
include("Quadratures.jl")
33
@reexport using Gridap.Quadratures
44

5+
include("DuffyQuadratures.jl")
6+
@reexport using Gridap.DuffyQuadratures
7+
8+
include("QuadratureFactories.jl")
9+
@reexport using Gridap.QuadratureFactories
10+
511
include("CellQuadratures.jl")
612
@reexport using Gridap.CellQuadratures
713

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module DuffyQuadraturesTests
2+
3+
using Test
4+
using Gridap
5+
6+
D = 3
7+
order=2
8+
quad = DuffyQuadrature{D}(order)
9+
@test isa(coordinates(quad),Vector{Point{D,Float64}})
10+
@test isa(weights(quad),Vector{Float64})
11+
@test sum(weights(quad)) 1/6
12+
13+
D = 2
14+
order=2
15+
quad = DuffyQuadrature{D}(order)
16+
x = coordinates(quad)
17+
r = Point{D,Float64}[
18+
(0.155051, 0.178559), (0.644949, 0.0750311),
19+
(0.155051, 0.66639), (0.644949, 0.28002)]
20+
@test isapprox(reinterpret(Float64,x),reinterpret(Float64,r),rtol=1e-3)
21+
@test sum(weights(quad)) 1/2
22+
23+
D = 1
24+
order=2
25+
quad = DuffyQuadrature{D}(order)
26+
@test sum(weights(quad)) 1
27+
28+
end # module
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module QuadratureFactoriesTests
2+
3+
using Test
4+
using Gridap
5+
6+
order = 5
7+
8+
p = Polytope(HEX_AXIS,HEX_AXIS)
9+
quad = Quadrature(p,order)
10+
@test isa(quad,TensorProductQuadrature)
11+
12+
13+
p = Polytope(TET_AXIS,TET_AXIS,TET_AXIS)
14+
quad = Quadrature(p,order)
15+
@test isa(quad,DuffyQuadrature)
16+
17+
end # module

test/IntegrationTests/runtests.jl

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ using Test
44

55
@testset "Quadratures" begin include("QuadraturesTests.jl") end
66

7+
@testset "DuffyQuadratures" begin include("DuffyQuadraturesTests.jl") end
8+
9+
@testset "QuadraturesFactories" begin include("QuadratureFactoriesTests.jl") end
10+
711
@testset "CellQuadratures" begin include("CellQuadraturesTests.jl") end
812

913
@testset "Triangulations" begin include("TriangulationsTests.jl") end

0 commit comments

Comments
 (0)