Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a1aca5f
Add a Jacobian function
mikeingold Mar 1, 2024
0a8e65f
Add an integral method for Torus using HCubature
mikeingold Mar 1, 2024
9d0455e
Add a torus test
mikeingold Mar 1, 2024
afe88ee
Bugfix
mikeingold Mar 1, 2024
0f6f6e3
Adjust arg type since hcubature passes SVector
mikeingold Mar 1, 2024
45b7494
Add placeholder methods for Torus
mikeingold Mar 1, 2024
61b5dd6
Bump version and update support matrix
mikeingold Mar 1, 2024
b253fda
Add generalized internal method for 2D integral using HCubature
mikeingold Mar 1, 2024
6cf6472
Extend usage of internal method
mikeingold Mar 1, 2024
e0911e0
Continue extending generalized method
mikeingold Mar 1, 2024
6111921
Add support for integral on CylinderSurface using hcubature
mikeingold Mar 1, 2024
f94c052
Disable failing CylinderSurface method, rename worker
mikeingold Mar 1, 2024
357e49e
Implement generalized 2D GaussLegendre
mikeingold Mar 1, 2024
3a83da6
Bugfixes
mikeingold Mar 1, 2024
09db1e7
Disable test for CylinderSurface with hcubature
mikeingold Mar 1, 2024
ae0bb5d
Extend application of generalized method
mikeingold Mar 1, 2024
3a78146
Add methods for ParaboloidSurface
mikeingold Mar 1, 2024
53e5a96
Add placeholder for ParaboloidSurface using GaussKronrod
mikeingold Mar 1, 2024
8a2bd3c
Implement generalized 2D GaussKronrod
mikeingold Mar 1, 2024
36ad18c
Update matrix
mikeingold Mar 1, 2024
fb7c734
Extend generalized GaussKronrod method
mikeingold Mar 1, 2024
cf598aa
Continue extending
mikeingold Mar 1, 2024
278859a
Add generalized 1D GaussLegendre
mikeingold Mar 1, 2024
0e41e4d
Bugfix
mikeingold Mar 1, 2024
e96d583
Extending generalized method
mikeingold Mar 1, 2024
468da30
Add generalized 1D GaussKronrod
mikeingold Mar 1, 2024
a3eec24
Bugfix
mikeingold Mar 1, 2024
17869c5
Add generalized 1D hcubature
mikeingold Mar 1, 2024
bb7ccb0
Add generalized 3D hcubature
mikeingold Mar 1, 2024
cf92619
Bugfix
mikeingold Mar 2, 2024
d078e89
Strip old code
mikeingold Mar 2, 2024
fe24734
Add generalized 3D GaussLegendre
mikeingold Mar 2, 2024
dbc7665
Update docs
mikeingold Mar 2, 2024
7d9fd82
Bugfix
mikeingold Mar 2, 2024
8bcda84
Update README plans
mikeingold Mar 2, 2024
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MeshIntegrals"
uuid = "dadec2fd-bbe0-4da4-9dbe-476c782c8e47"
authors = ["Mike Ingold <mike.ingold@gmail.com>"]
version = "0.10.0"
version = "0.11.0"

[deps]
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Methods are tested to ensure compatibility with
### Integral
| Geometry | Gauss-Legendre | Gauss-Kronrod | H-Adaptive Cubature |
|----------|----------------|---------------|---------------------|
| `Meshes.Box{Dim,T}` | :x: | :x: | :x: |
| `Meshes.Box{Dim>3,T}` | :x: | :x: | :x: |

### Line Integral
| Geometry | Gauss-Legendre | Gauss-Kronrod | H-Adaptive Cubature |
Expand All @@ -51,10 +51,10 @@ Methods are tested to ensure compatibility with
| `Meshes.Box{2,T}` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.CylinderSurface` | :x: | :white_check_mark: | :x: |
| `Meshes.Disk` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.ParaboloidSurface` | :x: | :x: | :x: |
| `Meshes.ParaboloidSurface` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.Sphere{3,T}` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.Triangle` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.Torus` | :x: | :x: | :x: |
| `Meshes.Torus` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `Meshes.SimpleMesh` | :x: | :x: | :x: |

### Volume Integral
Expand Down Expand Up @@ -95,13 +95,15 @@ fr(p) = fr(p.coords...)

# Plans and Work in Progress

- Short term:
- Implement all methods in the support matrix above
- TODO
- Update Example Usage and benchmarks
- Re-implement all tests for Unitful compatibility

- Longer term:
- Once all methods are implemented, determine which can be consolidated with a more abstract/unioned case
- Implement Aqua.jl tests
- Implement Documenter docs
- Improve README documentation in lieu of Documenter
- Implement Monte Carlo integration methods
- Implement BenchmarkTools test suite to quantify performance
- Continue working to generalize and consolidate methods

- Longer term plans
- Assess impact of upcoming Meshes.jl CRS refactor
- Once functionality is established and stable, evaluate transition to JuliaGeometry organization or direct absorption into Meshes.jl
115 changes: 53 additions & 62 deletions src/integral_line.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ end
# Gauss-Legendre
################################################################################

# Generalized method
function _integral_1d(f, geometry, settings::GaussLegendre)
# Compute Gauss-Legendre nodes/weights for x in interval [-1,1]
xs, ws = gausslegendre(settings.n)

# Change of variables: x [-1,1] ↦ t [0,1]
t(x) = 0.5x + 0.5
point(x) = geometry(t(x))

function paramfactor(x)
J = jacobian(geometry,[t(x)])
return norm(J[1])
end

# Integrate f along the geometry and apply a domain-correction factor for [-1,1] ↦ [0, 1]
integrand((w,x)) = w * f(point(x)) * paramfactor(x)
return 0.5 * sum(integrand, zip(ws, xs))
end

"""
integral(f, curve::Meshes.BezierCurve, ::GaussLegendre; alg=Meshes.Horner())

Expand Down Expand Up @@ -73,15 +92,7 @@ function integral(
# A Box{1,T} is definitionally embedded in 1D-space
_validate_integrand(f,1,T)

# Compute Gauss-Legendre nodes/weights for x in interval [-1,1]
xs, ws = gausslegendre(settings.n)

# Change of variables: x [-1,1] ↦ t [0,1]
t(x) = 0.5x + 0.5
point(x) = line(t(x))

# Integrate f along the line and apply a domain-correction factor for [-1,1] ↦ [0, length]
return 0.5 * length(line) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
return _integral_1d(f, line, settings)
end

function integral(
Expand All @@ -93,16 +104,7 @@ function integral(
# A Circle is definitionally embedded in 3D-space
_validate_integrand(f,3,T)

# Compute Gauss-Legendre nodes/weights for x in interval [-1,1]
xs, ws = gausslegendre(settings.n)

# Change of variables: x [-1,1] ↦ t [0,1]
t(x) = 0.5x + 0.5
point(x) = circle(t(x))

# Integrate f along the circle's rim and apply a domain-correction
# factor for [-1,1] ↦ [0, circumference]
return 0.5 * length(circle) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
return _integral_1d(f, circle, settings)
end

function integral(
Expand Down Expand Up @@ -135,15 +137,7 @@ function integral(
# Validate the provided integrand function
_validate_integrand(f,Dim,T)

# Compute Gauss-Legendre nodes/weights for x in interval [-1,1]
xs, ws = gausslegendre(settings.n)

# Change of variables: x [-1,1] ↦ t [0,1]
t(x) = 0.5x + 0.5
point(x) = segment(t(x))

# Integrate f along the line and apply a domain-correction factor for [-1,1] ↦ [0, length]
return 0.5 * length(segment) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
return _integral_1d(f, segment, settings)
end

function integral(
Expand All @@ -155,23 +149,25 @@ function integral(
# A Sphere{2,T} is simply a circle in 2D-space
_validate_integrand(f,2,T)

# Compute Gauss-Legendre nodes/weights for x in interval [-1,1]
xs, ws = gausslegendre(settings.n)

# Change of variables: x [-1,1] ↦ t [0,1]
t(x) = 0.5x + 0.5
point(x) = circle(t(x))

# Integrate f along the circle's rim and apply a domain-correction
# factor for [-1,1] ↦ [0, circumference]
return 0.5 * length(circle) * sum(w .* f(point(x)) for (w,x) in zip(ws, xs))
return _integral_1d(f, circle, settings)
end


################################################################################
# Gauss-Kronrod
################################################################################

# Generalized method
function _integral_1d(f, geometry, settings::GaussKronrod)
function paramfactor(t)
J = jacobian(geometry,[t])
return norm(J[1])
end

integrand(t) = f(geometry(t)) * paramfactor(t)
return QuadGK.quadgk(integrand, 0, 1; settings.kwargs...)[1]
end

"""
integral(f, curve::BezierCurve, ::GaussKronrod; alg=Horner(), kws...)

Expand Down Expand Up @@ -205,9 +201,7 @@ function integral(
# A Box is definitionally embedded in 1D-space
_validate_integrand(f,1,T)

len = length(line)
point(t) = line(t)
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
return _integral_1d(f, line, settings)
end

function integral(
Expand All @@ -219,9 +213,7 @@ function integral(
# A Circle is definitionally embedded in 3D-space
_validate_integrand(f,3,T)

len = length(circle)
point(t) = circle(t)
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
return _integral_1d(f, circle, settings)
end

function integral(
Expand All @@ -248,9 +240,7 @@ function integral(
# Validate the provided integrand function
_validate_integrand(f,Dim,T)

len = length(segment)
point(t) = segment(t)
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
return _integral_1d(f, segment, settings)
end

function integral(
Expand All @@ -262,16 +252,25 @@ function integral(
# A Sphere{2,T} is simply a circle in 2D-space
_validate_integrand(f,2,T)

len = length(circle)
point(t) = circle(t)
return QuadGK.quadgk(t -> len * f(point(t)), 0, 1; settings.kwargs...)[1]
return _integral_1d(f, circle, settings)
end


################################################################################
# HCubature
################################################################################

# Generalized method
function _integral_1d(f, geometry, settings::HAdaptiveCubature)
function paramfactor(t)
J = jacobian(geometry,t)
return norm(J[1])
end

integrand(t) = f(geometry(t[1])) * paramfactor(t)
return HCubature.hcubature(integrand, [0], [1]; settings.kwargs...)[1]
end

"""
integral(f, curve::BezierCurve, ::HAdaptiveCubature; alg=Horner(), kws...)

Expand Down Expand Up @@ -305,9 +304,7 @@ function integral(
# A Box is definitionally embedded in 1D-space
_validate_integrand(f,1,T)

len = length(line)
point(t) = line(t)
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
return _integral_1d(f, line, settings)
end

function integral(
Expand All @@ -319,9 +316,7 @@ function integral(
# A Circle is definitionally embedded in 3D-space
_validate_integrand(f,3,T)

len = length(circle)
point(t) = circle(t)
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
return _integral_1d(f, circle, settings)
end

function integral(
Expand Down Expand Up @@ -352,9 +347,7 @@ function integral(
# Validate the provided integrand function
_validate_integrand(f,Dim,T)

len = length(segment)
point(t) = segment(t)
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
return _integral_1d(f, segment, settings)
end

function integral(
Expand All @@ -366,7 +359,5 @@ function integral(
# A Sphere{2,T} is simply a circle in 2D-space
_validate_integrand(f,2,T)

len = length(circle)
point(t) = circle(t)
return hcubature(t -> len * f(point(t[1])), [0], [1]; settings.kwargs...)[1]
return _integral_1d(f, circle, settings)
end
Loading