Skip to content

Commit 5d92c86

Browse files
authored
Consolidate differential element calculations (#36)
* Consolidate paramfactor functions into a common differential function * Fix typo * Fix bug by vectorizing scalar arg * Tweak differential and add docstring * Bump version
1 parent 66ed919 commit 5d92c86

File tree

5 files changed

+39
-61
lines changed

5 files changed

+39
-61
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "MeshIntegrals"
22
uuid = "dadec2fd-bbe0-4da4-9dbe-476c782c8e47"
33
authors = ["Mike Ingold <[email protected]>"]
4-
version = "0.11.3"
4+
version = "0.11.4"
55

66
[deps]
77
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"

src/integral_line.jl

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,8 @@ function _integral_1d(
1616
t(x) = T(1/2) * x + T(1/2)
1717
point(x) = geometry(t(x))
1818

19-
function paramfactor(x)
20-
J = jacobian(geometry, T[t(x)])
21-
return norm(J[1])
22-
end
23-
2419
# Integrate f along the geometry and apply a domain-correction factor for [-1,1] ↦ [0, 1]
25-
integrand((w,x)) = w * f(point(x)) * paramfactor(x)
20+
integrand((w,x)) = w * f(point(x)) * differential(geometry, [t(x)])
2621
return T(1/2) * sum(integrand, zip(ws, xs))
2722
end
2823

@@ -32,13 +27,7 @@ function _integral_1d(
3227
settings::GaussKronrod
3328
)
3429
T = coordtype(geometry)
35-
36-
function paramfactor(t)
37-
J = jacobian(geometry, T[t])
38-
return norm(J[1])
39-
end
40-
41-
integrand(t) = f(geometry(t)) * paramfactor(t)
30+
integrand(t) = f(geometry(t)) * differential(geometry, [t])
4231
return QuadGK.quadgk(integrand, T(0), T(1); settings.kwargs...)[1]
4332
end
4433

@@ -48,13 +37,7 @@ function _integral_1d(
4837
settings::HAdaptiveCubature
4938
)
5039
T = coordtype(geometry)
51-
52-
function paramfactor(t)
53-
J = jacobian(geometry, t)
54-
return norm(J[1])
55-
end
56-
57-
integrand(t) = f(geometry(t[1])) * paramfactor(t)
40+
integrand(t) = f(geometry(t[1])) * differential(geometry, t)
5841
return HCubature.hcubature(integrand, T[0], T[1]; settings.kwargs...)[1]
5942
end
6043

src/integral_surface.jl

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@ function _integral_2d(
1717
v(x) = T(1/2)*x + T(1/2)
1818
point(xi,xj) = geometry2d(u(xi), v(xj))
1919

20-
function paramfactor(xi, xj)
21-
uv = [u(xi), v(xj)]
22-
J = jacobian(geometry2d, uv)
23-
return norm(J[1] × J[2])
24-
end
25-
26-
integrand(((wi,wj), (xi,xj))) = wi * wj * f(point(xi,xj)) * paramfactor(xi,xj)
20+
integrand(((wi,wj), (xi,xj))) = wi * wj * f(point(xi,xj)) * differential(geometry2d, [u(xi), v(xj)])
2721

2822
return T(1/4) .* sum(integrand, zip(wws,xxs))
2923
end
@@ -33,12 +27,7 @@ function _integral_2d(
3327
geometry2d::G,
3428
settings::GaussKronrod
3529
) where {Dim, T, G<:Meshes.Geometry{Dim,T}}
36-
function paramfactor(uv)
37-
J = jacobian(geometry2d, uv)
38-
return norm(J[1] × J[2])
39-
end
40-
41-
integrand(u,v) = f(geometry2d(u,v)) * paramfactor([u,v])
30+
integrand(u,v) = f(geometry2d(u,v)) * differential(geometry2d, [u,v])
4231
innerintegral(v) = QuadGK.quadgk(u -> integrand(u,v), T(0), T(1); settings.kwargs...)[1]
4332
return QuadGK.quadgk(v -> innerintegral(v), T(0), T(1); settings.kwargs...)[1]
4433
end
@@ -48,12 +37,7 @@ function _integral_2d(
4837
geometry2d::G,
4938
settings::HAdaptiveCubature
5039
) where {Dim, T, G<:Meshes.Geometry{Dim,T}}
51-
function paramfactor(uv)
52-
J = jacobian(geometry2d, uv)
53-
return norm(J[1] × J[2])
54-
end
55-
56-
integrand(uv) = paramfactor(uv) * f(geometry2d(uv...))
40+
integrand(uv) = differential(geometry2d, uv) * f(geometry2d(uv...))
5741
return hcubature(integrand, T[0,0], T[1,1]; settings.kwargs...)[1]
5842
end
5943

src/integral_volume.jl

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@ function _integral_3d(
1919

2020
point(stu) = geometry3d(stu[1], stu[2], stu[3])
2121

22-
function paramfactor(stu)
23-
J = jacobian(geometry3d, stu)
24-
return abs((J[1] × J[2]) J[3])
25-
end
26-
2722
function integrand(((wi,wj,wk), (xi,xj,xk)))
2823
stu = [s(xi),t(xj),u(xk)]
29-
wi * wj * wk * f(point(stu)) * paramfactor(stu)
24+
wi * wj * wk * f(point(stu)) * differential(geometry3d, stu)
3025
end
3126

3227
return T(1/8) .* sum(integrand, zip(wws,xxs))
@@ -37,12 +32,7 @@ function _integral_3d(
3732
geometry3d::G,
3833
settings::HAdaptiveCubature
3934
) where {Dim, T, G<:Meshes.Geometry{Dim,T}}
40-
function paramfactor(ts)
41-
J = jacobian(geometry3d, ts)
42-
return abs((J[1] × J[2]) J[3])
43-
end
44-
45-
integrand(ts) = paramfactor(ts) * f(geometry3d(ts...))
35+
integrand(ts) = differential(geometry3d, ts) * f(geometry3d(ts...))
4636
return hcubature(integrand, zeros(T,3), ones(T,3); settings.kwargs...)[1]
4737
end
4838

src/utils.jl

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ function jacobian(
1515
) where {T<:AbstractFloat}
1616
# Get the partial derivative along the n'th axis via finite difference approximation
1717
# where ts is the current parametric position (εv is a reusable buffer)
18-
function r_∂tn!(εv, ts, n)
18+
function ₙr!(εv, ts, n)
1919
if ts[n] < T(0.01)
20-
return r_∂tn_right!(εv, ts, n)
20+
return ₙr_right!(εv, ts, n)
2121
elseif T(0.99) < ts[n]
22-
return r_∂tn_left!(εv, ts, n)
22+
return ₙr_left!(εv, ts, n)
2323
else
24-
return r_∂tn_central!(εv, ts, n)
24+
return ₙr_central!(εv, ts, n)
2525
end
2626
end
2727

2828
# Central finite difference
29-
function r_∂tn_central!(εv, ts, n)
29+
function ₙr_central!(εv, ts, n)
3030
εv .= T(0)
3131
εv[n] = ε
3232
a = ts - εv
@@ -35,7 +35,7 @@ function jacobian(
3535
end
3636

3737
# Left finite difference
38-
function r_∂tn_left!(εv, ts, n)
38+
function ₙr_left!(εv, ts, n)
3939
εv .= T(0)
4040
εv[n] = ε
4141
a = ts - εv
@@ -44,7 +44,7 @@ function jacobian(
4444
end
4545

4646
# Right finite difference
47-
function r_∂tn_right!(εv, ts, n)
47+
function ₙr_right!(εv, ts, n)
4848
εv .= T(0)
4949
εv[n] = ε
5050
a = ts
@@ -55,8 +55,29 @@ function jacobian(
5555
# Allocate a re-usable ε vector
5656
εv = similar(ts)
5757

58-
∂r_∂tn(n) = ∂r_∂tn!(εv,ts,n)
59-
return map(∂r_∂tn, 1:length(ts))
58+
∂ₙr(n) = ∂ₙr!(εv,ts,n)
59+
return map(∂ₙr, 1:length(ts))
60+
end
61+
62+
"""
63+
differential(geometry, ts)
64+
65+
Calculate the differential element (length, area, volume, etc) of the parametric
66+
function for `geometry` at arguments `ts`.
67+
"""
68+
function differential(geometry, ts::AbstractVector)
69+
J = jacobian(geometry, ts)
70+
71+
# TODO generalize this with geometric algebra, e.g.: norm(foldl(∧, J))
72+
if length(J) == 1
73+
return norm(J[1])
74+
elseif length(J) == 2
75+
return norm(J[1] × J[2])
76+
elseif length(J) == 3
77+
return abs((J[1] × J[2]) J[3])
78+
else
79+
error("Not implemented yet. Please report this as an Issue on GitHub.")
80+
end
6081
end
6182

6283
"""

0 commit comments

Comments
 (0)