Skip to content

Commit 47af3f0

Browse files
authored
Consolidation onto integral function (#16)
* Transform line surface and volume functions into dim-checked aliases for integral * Tweak arg types * Implement renamed functions * Bump version and update test matrix * Update naming * Remove debugging and update messaging for not-supported methods * Update README
1 parent d02bec5 commit 47af3f0

File tree

7 files changed

+166
-90
lines changed

7 files changed

+166
-90
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.9.6"
4+
version = "0.10.0"
55

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

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# MeshIntegrals.jl
22

3-
This package implements methods for computing integrals over geometric polytopes
3+
This package implements methods for numerically-computing integrals over geometric polytopes
44
from [**Meshes.jl**](https://github.com/JuliaGeometry/Meshes.jl) using:
5-
- Gauss-Legendre quadrature rules from [**FastGaussQuadrature.jl**](https://github.com/JuliaApproximation/FastGaussQuadrature.jl)
6-
- H-adaptive Gauss-Kronrod quadrature rules from [**QuadGK.jl**](https://github.com/JuliaMath/QuadGK.jl)
7-
- H-adaptive cubature rules from [**HCubature.jl**](https://github.com/JuliaMath/HCubature.jl)
5+
- Gauss-Legendre quadrature rules from [**FastGaussQuadrature.jl**](https://github.com/JuliaApproximation/FastGaussQuadrature.jl): `GaussLegendre(n)`
6+
- H-adaptive Gauss-Kronrod quadrature rules from [**QuadGK.jl**](https://github.com/JuliaMath/QuadGK.jl): `GaussKronrod(kwargs...)`
7+
- H-adaptive cubature rules from [**HCubature.jl**](https://github.com/JuliaMath/HCubature.jl): `HAdaptiveCubature(kwargs...)`
8+
9+
Functions available:
10+
- `integral(f, geometry, ::IntegrationAlgorithm)`: integrates a function `f` over a domain defined by `geometry` using a particular
11+
- `lineintegral`, `surfaceintegral`, and `volumeintegral` are available as aliases for `integral` that first verify that `geometry` has the appropriate number of parametric dimensions
812

913
Methods are tested to ensure compatibility with
1014
- Meshes.jl geometries with **Unitful.jl** coordinate types, e.g. `Point(1.0u"m", 2.0u"m")`

src/integral.jl

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ end
5656
# Integral Function API
5757
################################################################################
5858

59+
"""
60+
integral(f, geometry, algorithm::IntegrationAlgorithm)
61+
62+
Numerically integrate a given function `f(::Point)` over the domain defined by
63+
a `geometry` using a particular `integration algorithm`.
64+
"""
5965
function integral end
6066

6167
"""
@@ -67,12 +73,19 @@ using a particular `integration algorithm`.
6773
Algorithm types available:
6874
- GaussKronrod
6975
- GaussLegendre
76+
- HAdaptiveCubature
7077
"""
7178
function lineintegral(
7279
f::F,
73-
geometry::G
74-
) where {F<:Function, G<:Meshes.Geometry}
75-
return lineintegral(f, geometry, GaussKronrod())
80+
geometry::G,
81+
settings::I=GaussKronrod()
82+
) where {F<:Function, G<:Meshes.Geometry, I<:IntegrationAlgorithm}
83+
dim = paramdim(geometry)
84+
if dim == 1
85+
return integral(f, geometry, settings)
86+
else
87+
error("Performing a line integral on a geometry with $dim parametric dimensions not supported.")
88+
end
7689
end
7790

7891
"""
@@ -83,9 +96,15 @@ using a particular `integration algorithm`.
8396
"""
8497
function surfaceintegral(
8598
f::F,
86-
geometry::G
87-
) where {F<:Function, G<:Meshes.Geometry}
88-
return surfaceintegral(f, geometry, HAdaptiveCubature())
99+
geometry::G,
100+
settings::I=HAdaptiveCubature()
101+
) where {F<:Function, G<:Meshes.Geometry, I<:IntegrationAlgorithm}
102+
dim = paramdim(geometry)
103+
if dim == 2
104+
return integral(f, geometry, settings)
105+
else
106+
error("Performing a surface integral on a geometry with $dim parametric dimensions not supported.")
107+
end
89108
end
90109

91110
"""
@@ -97,7 +116,13 @@ Numerically integrate a given function `f(::Point)` throughout a volumetric
97116
"""
98117
function volumeintegral(
99118
f::F,
100-
geometry::G
101-
) where {F<:Function, G<:Meshes.Geometry}
102-
return volumeintegral(f, geometry, HAdaptiveCubature())
119+
geometry::G,
120+
settings::I=HAdaptiveCubature()
121+
) where {F<:Function, G<:Meshes.Geometry, I<:IntegrationAlgorithm}
122+
dim = paramdim(geometry)
123+
if dim == 3
124+
return integral(f, geometry, settings)
125+
else
126+
error("Performing a volume integral on a geometry with $dim parametric dimensions not supported.")
127+
end
103128
end

src/integral_line.jl

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Common Methods
33
################################################################################
44

5-
function lineintegral(
5+
function integral(
66
f::F,
77
ring::Meshes.Ring,
88
settings::I
@@ -11,7 +11,7 @@ function lineintegral(
1111
return sum(segment -> lineintegral(f, segment, settings), segments(ring))
1212
end
1313

14-
function lineintegral(
14+
function integral(
1515
f::F,
1616
rope::Meshes.Rope,
1717
settings::I
@@ -20,22 +20,31 @@ function lineintegral(
2020
return sum(segment -> lineintegral(f, segment, settings), segments(rope))
2121
end
2222

23+
function lineintegral(
24+
f::F,
25+
curve::Meshes.BezierCurve{Dim,T,V},
26+
settings::I;
27+
alg::Meshes.BezierEvalMethod=Meshes.Horner()
28+
) where {F<:Function, Dim, T, V, I<:IntegrationAlgorithm}
29+
return integral(f, curve, settings; alg=alg)
30+
end
31+
2332

2433
################################################################################
2534
# Gauss-Legendre
2635
################################################################################
2736

2837
"""
29-
lineintegral(f, curve::Meshes.BezierCurve, ::GaussLegendre; alg=Meshes.Horner())
38+
integral(f, curve::Meshes.BezierCurve, ::GaussLegendre; alg=Meshes.Horner())
3039
31-
Like [`lineintegral`](@ref) but integrates along the domain defined a `curve`.
32-
By default this uses Horner's method to improve performance when parameterizing
40+
Like [`integral`](@ref) but integrates along the domain defined a `curve`. By
41+
default this uses Horner's method to improve performance when parameterizing
3342
the `curve` at the expense of a small loss of precision. Additional accuracy
3443
can be obtained by specifying the use of DeCasteljau's algorithm instead with
3544
`alg=Meshes.DeCasteljau()` but can come at a steep cost in memory allocations,
3645
especially for curves with a large number of control points.
3746
"""
38-
function lineintegral(
47+
function integral(
3948
f::F,
4049
curve::Meshes.BezierCurve{Dim,T,V},
4150
settings::GaussLegendre;
@@ -55,7 +64,7 @@ function lineintegral(
5564
return 0.5 * length(curve) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
5665
end
5766

58-
function lineintegral(
67+
function integral(
5968
f::F,
6069
line::Meshes.Box{1,T},
6170
settings::GaussLegendre
@@ -75,7 +84,7 @@ function lineintegral(
7584
return 0.5 * length(line) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
7685
end
7786

78-
function lineintegral(
87+
function integral(
7988
f::F,
8089
circle::Meshes.Circle{T},
8190
settings::GaussLegendre
@@ -96,7 +105,7 @@ function lineintegral(
96105
return 0.5 * length(circle) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
97106
end
98107

99-
function lineintegral(
108+
function integral(
100109
f::F,
101110
line::Meshes.Line{Dim,T},
102111
settings::GaussLegendre
@@ -118,7 +127,7 @@ function lineintegral(
118127
return sum(w .* integrand(x) for (w,x) in zip(ws, xs))
119128
end
120129

121-
function lineintegral(
130+
function integral(
122131
f::F,
123132
segment::Meshes.Segment{Dim,T},
124133
settings::GaussLegendre
@@ -137,7 +146,7 @@ function lineintegral(
137146
return 0.5 * length(segment) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
138147
end
139148

140-
function lineintegral(
149+
function integral(
141150
f::F,
142151
circle::Meshes.Sphere{2,T},
143152
settings::GaussLegendre
@@ -164,16 +173,16 @@ end
164173
################################################################################
165174

166175
"""
167-
lineintegral(f, curve::BezierCurve, ::GaussKronrod; alg=Horner(), kws...)
176+
integral(f, curve::BezierCurve, ::GaussKronrod; alg=Horner(), kws...)
168177
169-
Like [`lineintegral`](@ref) but integrates along the domain defined a `curve`.
170-
By default this uses Horner's method to improve performance when parameterizing
178+
Like [`integral`](@ref) but integrates along the domain defined a `curve`. By
179+
default this uses Horner's method to improve performance when parameterizing
171180
the `curve` at the expense of a small loss of precision. Additional accuracy
172181
can be obtained by specifying the use of DeCasteljau's algorithm instead with
173182
`alg=Meshes.DeCasteljau()` but can come at a steep cost in memory allocations,
174183
especially for curves with a large number of control points.
175184
"""
176-
function lineintegral(
185+
function integral(
177186
f::F,
178187
curve::Meshes.BezierCurve{Dim,T,V},
179188
settings::GaussKronrod;
@@ -187,7 +196,7 @@ function lineintegral(
187196
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
188197
end
189198

190-
function lineintegral(
199+
function integral(
191200
f::F,
192201
line::Meshes.Box{1,T},
193202
settings::GaussKronrod
@@ -201,7 +210,7 @@ function lineintegral(
201210
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
202211
end
203212

204-
function lineintegral(
213+
function integral(
205214
f::F,
206215
circle::Meshes.Circle{T},
207216
settings::GaussKronrod
@@ -215,7 +224,7 @@ function lineintegral(
215224
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
216225
end
217226

218-
function lineintegral(
227+
function integral(
219228
f::F,
220229
line::Meshes.Line{Dim,T},
221230
settings::GaussKronrod
@@ -231,7 +240,7 @@ function lineintegral(
231240
return QuadGK.quadgk(t -> f(point(t)), -Inf, Inf; settings.kwargs...)[1]
232241
end
233242

234-
function lineintegral(
243+
function integral(
235244
f::F,
236245
segment::Meshes.Segment{Dim,T},
237246
settings::GaussKronrod
@@ -244,7 +253,7 @@ function lineintegral(
244253
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
245254
end
246255

247-
function lineintegral(
256+
function integral(
248257
f::F,
249258
circle::Meshes.Sphere{2,T},
250259
settings::GaussKronrod
@@ -264,16 +273,16 @@ end
264273
################################################################################
265274

266275
"""
267-
lineintegral(f, curve::BezierCurve, ::HAdaptiveCubature; alg=Horner(), kws...)
276+
integral(f, curve::BezierCurve, ::HAdaptiveCubature; alg=Horner(), kws...)
268277
269-
Like [`lineintegral`](@ref) but integrates along the domain defined a `curve`.
270-
By default this uses Horner's method to improve performance when parameterizing
278+
Like [`integral`](@ref) but integrates along the domain defined a `curve`. By
279+
default this uses Horner's method to improve performance when parameterizing
271280
the `curve` at the expense of a small loss of precision. Additional accuracy
272281
can be obtained by specifying the use of DeCasteljau's algorithm instead with
273282
`alg=Meshes.DeCasteljau()` but can come at a steep cost in memory allocations,
274283
especially for curves with a large number of control points.
275284
"""
276-
function lineintegral(
285+
function integral(
277286
f::F,
278287
curve::Meshes.BezierCurve{Dim,T,V},
279288
settings::HAdaptiveCubature;
@@ -287,7 +296,7 @@ function lineintegral(
287296
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
288297
end
289298

290-
function lineintegral(
299+
function integral(
291300
f::F,
292301
line::Meshes.Box{1,T},
293302
settings::HAdaptiveCubature
@@ -301,7 +310,7 @@ function lineintegral(
301310
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
302311
end
303312

304-
function lineintegral(
313+
function integral(
305314
f::F,
306315
circle::Meshes.Circle{T},
307316
settings::HAdaptiveCubature
@@ -315,7 +324,7 @@ function lineintegral(
315324
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
316325
end
317326

318-
function lineintegral(
327+
function integral(
319328
f::F,
320329
line::Meshes.Line{Dim,T},
321330
settings::HAdaptiveCubature
@@ -335,7 +344,7 @@ function lineintegral(
335344
return hcubature(integrand, [-1], [1]; settings.kwargs...)[1]
336345
end
337346

338-
function lineintegral(
347+
function integral(
339348
f::F,
340349
segment::Meshes.Segment{Dim,T},
341350
settings::HAdaptiveCubature
@@ -348,7 +357,7 @@ function lineintegral(
348357
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
349358
end
350359

351-
function lineintegral(
360+
function integral(
352361
f::F,
353362
circle::Meshes.Sphere{2,T},
354363
settings::HAdaptiveCubature

0 commit comments

Comments
 (0)