Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename _default_method and absorb _gausslegendre #147

Merged
merged 19 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
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
4 changes: 2 additions & 2 deletions src/differentiation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function jacobian(
geometry::G,
ts::Union{AbstractVector{T}, Tuple{T, Vararg{T}}}
) where {G <: Geometry, T <: AbstractFloat}
return jacobian(geometry, ts, _default_method(G))
return jacobian(geometry, ts, _default_diff_method(G))
end

function jacobian(
Expand Down Expand Up @@ -107,7 +107,7 @@ possible and finite difference approximations otherwise.
function differential(
geometry::G,
ts::Union{AbstractVector{T}, Tuple{T, Vararg{T}}},
diff_method::DifferentiationMethod = _default_method(G)
diff_method::DifferentiationMethod = _default_diff_method(G)
) where {G <: Geometry, T <: AbstractFloat}
J = Iterators.map(_KVector, jacobian(geometry, ts, diff_method))
return LinearAlgebra.norm(foldl(∧, J))
Expand Down
22 changes: 13 additions & 9 deletions src/integral.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function _integral(
geometry,
rule::GaussKronrod;
FP::Type{T} = Float64,
diff_method::DM = _default_method(geometry)
diff_method::DM = _default_diff_method(geometry)
) where {DM <: DifferentiationMethod, T <: AbstractFloat}
# Implementation depends on number of parametric dimensions over which to integrate
N = Meshes.paramdim(geometry)
Expand Down Expand Up @@ -70,24 +70,28 @@ function _integral(
geometry,
rule::GaussLegendre;
FP::Type{T} = Float64,
diff_method::DM = _default_method(geometry)
diff_method::DM = _default_diff_method(geometry)
) where {DM <: DifferentiationMethod, T <: AbstractFloat}
N = Meshes.paramdim(geometry)

# Get Gauss-Legendre nodes and weights for a region [-1,1]^N
xs, ws = _gausslegendre(FP, rule.n)
weights = Iterators.product(ntuple(Returns(ws), N)...)
nodes = Iterators.product(ntuple(Returns(xs), N)...)
# Get Gauss-Legendre nodes and weights of type FP for a region [-1,1]ᴺ
xs, ws = FastGaussQuadrature.gausslegendre(rule.n)
xsFP = Iterators.map(FP, xs)
wsFP = Iterators.map(FP, ws)
weight_grid = Iterators.product(ntuple(Returns(wsFP), N)...)
node_grid = Iterators.product(ntuple(Returns(xsFP), N)...)

# Domain transformation: x [-1,1] ↦ t [0,1]
t(x) = (1 // 2) * x + (1 // 2)

function integrand((weights, nodes))
ts = t.(nodes)
# Transforms nodes/xs, store in an NTuple
ts = ntuple(i -> t(nodes[i]), length(nodes))
# Integrand function
prod(weights) * f(geometry(ts...)) * differential(geometry, ts, diff_method)
end

return (1 // (2^N)) .* sum(integrand, zip(weights, nodes))
return (1 // (2^N)) .* sum(integrand, zip(weight_grid, node_grid))
end

# HAdaptiveCubature
Expand All @@ -96,7 +100,7 @@ function _integral(
geometry,
rule::HAdaptiveCubature;
FP::Type{T} = Float64,
diff_method::DM = _default_method(geometry)
diff_method::DM = _default_diff_method(geometry)
) where {DM <: DifferentiationMethod, T <: AbstractFloat}
N = Meshes.paramdim(geometry)

Expand Down
50 changes: 31 additions & 19 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,62 @@
# Misc. Internal Tools
################################################################################

# Calculate Gauss-Legendre nodes/weights and convert to type T
function _gausslegendre(T, n)
xs, ws = FastGaussQuadrature.gausslegendre(n)
return T.(xs), T.(ws)
end

# Common error message structure
function _error_unsupported_combination(geometry, rule)
msg = "Integrating a $geometry using a $rule rule not supported."
throw(ArgumentError(msg))
end

# Return an NTuple{N, T} of zeros; same interface as Base.zeros() but faster
_zeros(T::DataType, N::Int64) = ntuple(_ -> zero(T), N)
_zeros(N::Int) = _zeros(Float64, N)

# Return an NTuple{N, T} of ones; same interface as Base.ones() but faster
_ones(T::DataType, N::Int64) = ntuple(_ -> one(T), N)
_ones(N::Int) = _ones(Float64, N)

################################################################################
# DifferentiationMethod
################################################################################

# Return the default DifferentiationMethod instance for a particular geometry type
function _default_method(
function _default_diff_method(
g::Type{G}
) where {G <: Geometry}
return FiniteDifference()
end

# Return the default DifferentiationMethod instance for a particular geometry instance
_default_method(g::G) where {G <: Geometry} = _default_method(G)
_default_diff_method(g::G) where {G <: Geometry} = _default_diff_method(G)

################################################################################
# CliffordNumbers and Units
# Numerical Tools
################################################################################

# Meshes.Vec -> Unitful.Quantity{CliffordNumber.KVector}
"""
_KVector(v::Meshes.Vec) -> Unitful.Quantity{CliffordNumbers.KVector}

Convert a `Vec` to a Unitful KVector.
"""
function _KVector(v::Meshes.Vec{Dim, T}) where {Dim, T}
ucoords = Iterators.map(Unitful.ustrip, v.coords)
return CliffordNumbers.KVector{1, VGA(Dim)}(ucoords...) * _units(v)
end

# Extract the length units used by the CRS of a Geometry
"""
_units(geometry)

Return the Unitful units associated with a particular `geometry`.
mikeingold marked this conversation as resolved.
Show resolved Hide resolved
"""
_units(::Geometry{M, CRS}) where {M, CRS} = Unitful.unit(CoordRefSystems.lentype(CRS))
_units(::Meshes.Vec{Dim, T}) where {Dim, T} = Unitful.unit(T)

"""
_zeros(T = Float64, N)

Return an `NTuple{N, T}` filled with zeros. This method avoids allocating an array, which
happens when using `Base.zeros`.
"""
_zeros(T::DataType, N::Int64) = ntuple(_ -> zero(T), N)
_zeros(N::Int) = _zeros(Float64, N)

"""
_ones(T = Float64, N)

Return an `NTuple{N, T}` filled with ones. This method avoids allocating an array, which
happens when using `Base.ones`.
"""
_ones(T::DataType, N::Int64) = ntuple(_ -> one(T), N)
_ones(N::Int) = _ones(Float64, N)
4 changes: 1 addition & 3 deletions test/combinations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ end
end

@testitem "Meshes.BezierCurve" setup=[Setup] begin
curve = BezierCurve(
[Point(t * u"m", sin(t) * u"m", 0.0u"m") for t in range(-pi, pi, length = 361)]
)
curve = BezierCurve([Point(t, sin(t), 0) for t in range(-pi, pi, length = 361)])

function f(p::P) where {P <: Meshes.Point}
ux = ustrip(p.coords.x)
Expand Down
11 changes: 4 additions & 7 deletions test/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,12 @@
end

@testitem "DifferentiationMethod" setup=[Setup] begin
using MeshIntegrals: _default_method

# Test geometries
sphere = Sphere(Point(0, 0, 0), 1.0)
triangle = Triangle(Point(0, 0, 0), Point(0, 1, 0), Point(1, 0, 0))
using MeshIntegrals: _default_diff_method

# _default_method
mikeingold marked this conversation as resolved.
Show resolved Hide resolved
@test _default_method(Meshes.Sphere) isa FiniteDifference
@test _default_method(sphere) isa FiniteDifference
sphere = Sphere(Point(0, 0, 0), 1.0)
@test _default_diff_method(Meshes.Sphere) isa FiniteDifference
@test _default_diff_method(sphere) isa FiniteDifference

# FiniteDifference
@test FiniteDifference().ε ≈ 1e-6
Expand Down
Loading