Skip to content
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6a6b5c1
Add tests for SimpleMesh
mikeingold Jun 23, 2025
e087324
Add integral method for Domains, generalize aliases to GeometryOrDomain
mikeingold Jun 24, 2025
6e6ea2c
Define specialization methods for PolyArea
mikeingold Jun 24, 2025
83c1461
Use explicit namespace for Meshes.Domain
mikeingold Jun 24, 2025
bb4e7ba
Generalize support_status geometry type
mikeingold Jun 24, 2025
39765dc
Bugfix, explicit import GeometryOrDomain
mikeingold Jun 24, 2025
c74e58e
Explicit use of non-exported union
mikeingold Jun 24, 2025
48ed10e
Explicit namespace bugfix
mikeingold Jun 24, 2025
3142142
Extend supports_autoenzyme to Domains
mikeingold Jun 24, 2025
ab3a5ad
Formatting changes
mikeingold Jun 27, 2025
f464327
Adjust test imports
mikeingold Jun 27, 2025
c9a71b1
Add tests for RegularGrid
mikeingold Jun 27, 2025
2de6f8d
Add tests for CartesianGrid, add missing ustrip import
mikeingold Jun 27, 2025
748b850
Apply suggestions from code review
mikeingold Jun 27, 2025
1549195
Add explicit rtol's, reduce dims to speed up RegularGrid tests
mikeingold Jun 28, 2025
186a50d
Generalize supports_autoenzyme from utils to Domains
mikeingold Jun 28, 2025
c2538a6
Bugfix update old name
mikeingold Jun 28, 2025
6ece30e
Make partitioned integral codes consistent
mikeingold Jul 6, 2025
93b4097
Add PolyArea tests
mikeingold Jul 17, 2025
7bacbd4
Apply suggestions from code review
mikeingold Jul 18, 2025
42fb93d
Bugfix
mikeingold Jul 18, 2025
f127361
Bugfix
mikeingold Jul 18, 2025
a0d57fe
Reverse hole region coord path
mikeingold Jul 18, 2025
9a83903
Apply suggestion
mikeingold Jul 19, 2025
242b3f0
Merge branch 'remesh' of github.com:JuliaGeometry/MeshIntegrals.jl in…
mikeingold Jul 19, 2025
7a70870
Mirror GeometryOrDomain internally
mikeingold Jul 19, 2025
43ddd4a
Bugfix
mikeingold Jul 19, 2025
79a1b46
Remove unnecessary use of GeometryOrDomain, switch usings to imports
mikeingold Jul 19, 2025
abc389e
Update docs and merge recent v0.16.3 release changes
mikeingold Jul 19, 2025
46f7240
Merge branch 'main' into remesh
mikeingold Jul 19, 2025
dc431e7
Add tests and docs for StructuredGrid
mikeingold Jul 20, 2025
20362c0
Merge branch 'remesh' of github.com:JuliaGeometry/MeshIntegrals.jl in…
mikeingold Jul 20, 2025
c68ee8a
Update test/combinations.jl
mikeingold Jul 20, 2025
f2a7ea0
Remove unnecessary method
mikeingold Jul 20, 2025
b44869a
Docstring and style updates
mikeingold Jul 20, 2025
8849bb1
Merge branch 'remesh' of github.com:JuliaGeometry/MeshIntegrals.jl in…
mikeingold Jul 20, 2025
a909838
Update docstrings for consistency and clarity, associated style impro…
mikeingold Jul 20, 2025
75e44dd
Add note to changelog
mikeingold Jul 20, 2025
fd2f0e6
Apply suggestions from code review [skip ci]
mikeingold Jul 21, 2025
4e7c1cd
Switch to function format due to line length
mikeingold Jul 21, 2025
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Adds integral methods for `PolyArea` and subtypes of `Domain` with explicit tests for `CartesianGrid`, `PolyArea`, `RegularGrid`, `SimpleMesh`, and `StructuredGrid`.

### Changed

- Generalizes the alias functions (e.g. `lineintegral`) to also accept `Domain`s.


## [0.16.3] - 2025-06-26

### Changed
Expand Down
12 changes: 7 additions & 5 deletions docs/src/support.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ The following Support Matrix captures the current state of support for all geome
combinations. Entries with a green check mark are fully supported and pass unit tests
designed to check for accuracy.

| `Meshes.Geometry` | `GaussKronrod` | `GaussLegendre` | `HAdaptiveCubature` |
| `Meshes.Geometry/Domain` | `GaussKronrod` | `GaussLegendre` | `HAdaptiveCubature` |
|----------|----------------|---------------|---------------------|
| `Ball` in `𝔼{2}` | ⚠️ | ✅ | ✅ |
| `Ball` in `𝔼{3}` | 🛑 | ✅ | ✅ |
| `BezierCurve` | ✅ | ✅ | ✅ |
| `Box` in `𝔼{1}` | ✅ | ✅ | ✅ |
| `Box` in `𝔼{2}` | ⚠️ | ✅ | ✅ |
| `Box` in `𝔼{≥3}` | 🛑 | ✅ | ✅ |
| `CartesianGrid` | ✅ | ✅ | ✅ |
| `Circle` | ✅ | ✅ | ✅ |
| `Cone` | 🛑 | ✅ | ✅ |
| `ConeSurface` | ⚠️ | ✅ | ✅ |
Expand All @@ -48,16 +49,18 @@ designed to check for accuracy.
| `ParaboloidSurface` | ⚠️ | ✅ | ✅ |
| `ParametrizedCurve` | ✅ | ✅ | ✅ |
| `Plane` | ✅ | ✅ | ✅ |
| `Polyarea` | 🛑 | [🎗️](https://github.com/JuliaGeometry/MeshIntegrals.jl/issues/28) | [🎗️](https://github.com/JuliaGeometry/MeshIntegrals.jl/issues/28) |
| `PolyArea` | ⚠️ | | |
| `Pyramid` | ⚠️ | ✅ | ✅ |
| `Quadrangle` | ⚠️ | ✅ | ✅ |
| `Ray` | ✅ | ✅ | ✅ |
| `RegularGrid` | ✅ | ✅ | ✅ |
| `Ring` | ✅ | ✅ | ✅ |
| `Rope` | ✅ | ✅ | ✅ |
| `Segment` | ✅ | ✅ | ✅ |
| `SimpleMesh` | 🛑 | [🎗️](https://github.com/JuliaGeometry/MeshIntegrals.jl/issues/27) | [🎗️](https://github.com/JuliaGeometry/MeshIntegrals.jl/issues/27) |
| `SimpleMesh` | ⚠️ | | |
| `Sphere` in `𝔼{2}` | ✅ | ✅ | ✅ |
| `Sphere` in `𝔼{3}` | ⚠️ | ✅ | ✅ |
| `StructuredGrid` | ✅ | ✅ | ✅ |
| `Tetrahedron` | ⚠️ | ✅ | ✅ |
| `Triangle` | ✅ | ✅ | ✅ |
| `Torus` | ⚠️ | ✅ | ✅ |
Expand All @@ -66,6 +69,5 @@ designed to check for accuracy.
| Symbol | Support Level |
|--------|---------|
| ✅ | Supported |
| 🎗️ | Planned to support in the future |
| ⚠️ | Deprecated |
| 🛑 | Not supported |
| 🛑 | Not supported |
13 changes: 7 additions & 6 deletions ext/MeshIntegralsEnzymeExt.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module MeshIntegralsEnzymeExt

using MeshIntegrals: MeshIntegrals, AutoEnzyme
using Meshes: Meshes
using Enzyme: Enzyme
import MeshIntegrals
import Meshes
import Enzyme

function MeshIntegrals.jacobian(
geometry::Meshes.Geometry,
ts::Union{AbstractVector{T}, Tuple{T, Vararg{T}}},
::AutoEnzyme
::MeshIntegrals.AutoEnzyme
) where {T <: AbstractFloat}
Dim = Meshes.paramdim(geometry)
if Dim != length(ts)
Expand All @@ -16,9 +16,10 @@ function MeshIntegrals.jacobian(
return Meshes.to.(Enzyme.jacobian(Enzyme.Forward, geometry, ts...))
end

# Supports all geometries except for those that throw errors
# See GitHub Issue #154 for more information
# Supports all geometries/domains by default
MeshIntegrals.supports_autoenzyme(::Type{<:Meshes.Geometry}) = true
MeshIntegrals.supports_autoenzyme(::Type{<:Meshes.Domain}) = true
# except for those that throw errors (see GitHub Issue #154)
MeshIntegrals.supports_autoenzyme(::Type{<:Meshes.BezierCurve}) = false
MeshIntegrals.supports_autoenzyme(::Type{<:Meshes.CylinderSurface}) = false
MeshIntegrals.supports_autoenzyme(::Type{<:Meshes.Cylinder}) = false
Expand Down
4 changes: 4 additions & 0 deletions src/MeshIntegrals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import LinearAlgebra
import QuadGK
import Unitful

# Same as the internal-only Meshes.GeometryOrDomain
const GeometryOrDomain = Union{Meshes.Geometry, Meshes.Domain}

include("differentiation.jl")
export DifferentiationMethod, FiniteDifference, AutoEnzyme, jacobian

Expand All @@ -31,6 +34,7 @@ include("specializations/CylinderSurface.jl")
include("specializations/FrustumSurface.jl")
include("specializations/Line.jl")
include("specializations/Plane.jl")
include("specializations/PolyArea.jl")
include("specializations/Ray.jl")
include("specializations/Ring.jl")
include("specializations/Rope.jl")
Expand Down
12 changes: 12 additions & 0 deletions src/integral.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ function integral(
_integral(f, geometry, rule; kwargs...)
end

function integral(
f,
domain::Meshes.Domain,
rule::I = Meshes.paramdim(domain) == 1 ? GaussKronrod() : HAdaptiveCubature();
kwargs...
) where {I <: IntegrationRule}
# Discretize the Domain into primitive geometries, sum the integrals over those
subintegral(geometry) = integral(f, geometry, rule; kwargs...)
subgeometries = Meshes.elements(Meshes.discretize(domain)) |> collect
return sum(subintegral, subgeometries)
end

################################################################################
# Integral Workers
################################################################################
Expand Down
6 changes: 3 additions & 3 deletions src/integral_aliases.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Rule types available:
"""
function lineintegral(
f,
geometry::Geometry,
geometry::GeometryOrDomain,
rule::IntegrationRule = GaussKronrod();
kwargs...
)
Expand Down Expand Up @@ -48,7 +48,7 @@ Algorithm types available:
"""
function surfaceintegral(
f,
geometry::Geometry,
geometry::GeometryOrDomain,
rule::IntegrationRule = HAdaptiveCubature();
kwargs...
)
Expand Down Expand Up @@ -80,7 +80,7 @@ Algorithm types available:
"""
function volumeintegral(
f,
geometry::Geometry,
geometry::GeometryOrDomain,
rule::IntegrationRule = HAdaptiveCubature();
kwargs...
)
Expand Down
60 changes: 60 additions & 0 deletions src/specializations/PolyArea.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
################################################################################
# Specialized Methods for PolyArea
#
# Why Specialized?
# The PolyArea geometry defines a surface bounded by a polygon, but Meshes.jl
# cannot define a parametric function for a polyarea because a general solution
# for one does not exist. However, they can be partitioned into simpler elements
# and integrated separately before finally summing the result.
################################################################################

"""
integral(f, area::PolyArea, rule = HAdaptiveCubature();
diff_method=FiniteDifference(), FP=Float64)

Like [`integral`](@ref) but integrates over the surface domain defined by a `PolyArea`.
The surface is first discretized into facets that are integrated independently using
the specified integration `rule`.

# Arguments
- `f`: an integrand function, i.e. any callable with a method `f(::Meshes.Point)`
- `area`: a `PolyArea` that defines the integration domain
- `rule = HAdaptiveCubature()`: optionally, the `IntegrationRule` used for integration

# Keyword Arguments
- `diff_method::DifferentiationMethod`: the method to use for
calculating Jacobians that are used to calculate differential elements
- `FP = Float64`: the floating point precision desired
"""
function integral(
f,
area::Meshes.PolyArea,
rule::I;
kwargs...
) where {I <: IntegrationRule}
# Partition the PolyArea, sum the integrals over each of those areas
subintegral(area) = integral(f, area, rule; kwargs...)
subgeometries = collect(Meshes.elements(Meshes.discretize(area)))
return sum(subintegral, subgeometries)
end

"""
surfaceintegral(f, area, rule = HAdaptiveCubature(); FP = Float64)

Numerically integrate a given function `f(::Point)` over the surface domain defined
by a `PolyArea`. The surface is first discretized into facets that are integrated
independently using the specified integration `rule`.

Algorithm types available:
- [`GaussKronrod`](@ref)
- [`GaussLegendre`](@ref)
- [`HAdaptiveCubature`](@ref) (default)
"""
function surfaceintegral(
f,
area::Meshes.PolyArea,
rule::IntegrationRule = HAdaptiveCubature();
kwargs...
)
return integral(f, area, rule; kwargs...)
end
3 changes: 2 additions & 1 deletion src/specializations/Ring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ function integral(
kwargs...
) where {I <: IntegrationRule}
# Convert the Ring into Segments, sum the integrals of those
return sum(segment -> _integral(f, segment, rule; kwargs...), Meshes.segments(ring))
subintegral(segment) = _integral(f, segment, rule; kwargs...)
return sum(subintegral, Meshes.segments(ring))
end
3 changes: 2 additions & 1 deletion src/specializations/Rope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ function integral(
kwargs...
) where {I <: IntegrationRule}
# Convert the Rope into Segments, sum the integrals of those
return sum(segment -> integral(f, segment, rule; kwargs...), Meshes.segments(rope))
subintegral(segment) = integral(f, segment, rule; kwargs...)
return sum(subintegral, Meshes.segments(rope))
end
4 changes: 2 additions & 2 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ end

"""
supports_autoenzyme(geometry::Geometry)
supports_autoenzyme(type::Type{<:Geometry})
supports_autoenzyme(type::Type{<:GeometryOrDomain})

Return whether a geometry or geometry type has a parametric function that can be
differentiated with Enzyme. See GitHub Issue #154 for more information.
Expand All @@ -25,7 +25,7 @@ function supports_autoenzyme end
supports_autoenzyme(::Type{<:Any}) = false

# If provided a geometry instance, re-run with the type as argument
supports_autoenzyme(::G) where {G <: Geometry} = supports_autoenzyme(G)
supports_autoenzyme(::G) where {G <: GeometryOrDomain} = supports_autoenzyme(G)

"""
_check_diff_method_support(::Geometry, ::DifferentiationMethod) -> nothing
Expand Down
Loading
Loading