JuliaGeometry / MeshIntegrals.jl

Numerical integration over Meshes.jl geometry domains
https://juliageometry.github.io/MeshIntegrals.jl/
MIT License
24 stars 4 forks source link
differential-geometry julia numerical-integration quadrature-methods scientific-computing

MeshIntegrals.jl

Docs-stable Docs-dev License: MIT ColPrac

Build Status codecov Coveralls Aqua QA

MeshIntegrals.jl uses differential forms to enable fast and easy numerical integration of arbitrary integrand functions over domains defined via Meshes.jl geometries. This is achieved using:

These solvers have support for integrand functions that produce scalars, vectors, and Unitful.jl Quantity types. While HCubature.jl does not natively support Quantity type integrands, this package provides a compatibility layer to enable this feature.

Usage

integral(f, geometry)

Performs a numerical integration of some integrand function f(p::Meshes.Point) over the domain specified by geometry. A default integration method will be automatically selected according to the geometry: GaussKronrod() for 1D, and HAdaptiveCubature() for all others.

integral(f, geometry, rule, FP=Float64)

Performs a numerical integration of some integrand function f(p::Meshes.Point) over the domain specified by geometry using the specified integration rule, e.g. GaussKronrod().

Optionally, a fourth argument can be provided to specify the floating point precision level desired. This setting can be manipulated if your integrand function produces outputs with alternate floating point precision (e.g. Float16, BigFloat, etc) AND you'd prefer to avoid implicit type promotions.

lineintegral(f, geometry)
surfaceintegral(f, geometry)
volumeintegral(f, geometry)

Alias functions are provided for convenience. These are simply wrappers for integral that first validate that the provided geometry has the expected number of parametric/manifold dimensions. Like with integral in the examples above, the rule can also be specified as a third-argument.

Demo

using Meshes
using MeshIntegrals
using Unitful

# Define a path that approximates a sine-wave on the xy-plane
mypath = BezierCurve(
    [Point(t*u"m", sin(t)*u"m", 0.0u"m") for t in range(-pi, pi, length=361)]
)

# Map f(::Point) -> f(x, y, z) in unitless coordinates
f(p::Meshes.Point) = f(ustrip(to(p))...)

# Integrand function in units of Ohms/meter
f(x, y, z) = (1 / sqrt(1 + cos(x)^2)) * u"Ω/m"

integral(f, mypath)
# -> Approximately 2*Pi Ω