Skip to content

Commit 2f8412f

Browse files
committed
Added DuffyQuadrature
1 parent b755b3c commit 2f8412f

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

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

src/Integration/files.jl

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

5+
include("DuffyQuadratures.jl")
6+
@reexport using Gridap.DuffyQuadratures
7+
58
include("CellQuadratures.jl")
69
@reexport using Gridap.CellQuadratures
710

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

test/IntegrationTests/runtests.jl

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

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

7+
@testset "DuffyQuadratures" begin include("DuffyQuadraturesTests.jl") end
8+
79
@testset "CellQuadratures" begin include("CellQuadraturesTests.jl") end
810

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

0 commit comments

Comments
 (0)