diff --git a/previews/PR139/.documenter-siteinfo.json b/previews/PR139/.documenter-siteinfo.json index 2acd6314..99b0c7d9 100644 --- a/previews/PR139/.documenter-siteinfo.json +++ b/previews/PR139/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-11-30T21:57:40","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-11-30T23:09:38","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/previews/PR139/api/index.html b/previews/PR139/api/index.html index 5e863e3f..26fb705b 100644 --- a/previews/PR139/api/index.html +++ b/previews/PR139/api/index.html @@ -1,5 +1,5 @@ -Public API · MeshIntegrals.jl

Public API

Integrals

MeshIntegrals.integralFunction
integral(f, geometry[, rule]; diff_method=_default_method(geometry), FP=Float64)

Numerically integrate a given function f(::Point) over the domain defined by a geometry using a particular numerical integration rule with floating point precision of type FP.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • geometry: some Meshes.Geometry that defines the integration domain
  • rule: optionally, the IntegrationRule used for integration (by default

GaussKronrod() in 1D and HAdaptiveCubature() else)

Keyword Arguments

  • diff_method::DifferentiationMethod = _default_method(geometry): the method to

use for calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired.
source

Specializations

MeshIntegrals.integralMethod
integral(f, curve::BezierCurve, rule = GaussKronrod();
-         diff_method=Analytical(), FP=Float64, alg=Meshes.Horner())

Like integral but integrates along the domain defined by curve.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • curve: a Meshes.BezierCurve that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = Analytical(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
  • alg = Meshes.Horner(): the method to use for parameterizing curve. Alternatively,

alg=Meshes.DeCasteljau() can be specified for increased accuracy, but comes with a steep performance cost, especially for curves with a large number of control points.

source
MeshIntegrals.integralMethod
integral(f, ring::Ring, rule = GaussKronrod();
-         diff_method=FiniteDifference(), FP=Float64)

Like integral but integrates along the domain defined by ring. The specified integration rule is applied independently to each segment formed by consecutive points in the Ring.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • ring: a Ring that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = FiniteDifference(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
source
MeshIntegrals.integralMethod
integral(f, rope::Rope, rule = GaussKronrod();
-         diff_method=FiniteDifference(), FP=Float64)

Like integral but integrates along the domain defined by rope. The specified integration rule is applied independently to each segment formed by consecutive points in the Rope.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • rope: a Rope that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = FiniteDifference(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
source
MeshIntegrals._ParametricGeometryType
_ParametricGeometry <: Meshes.Primitive <: Meshes.Geometry

_ParametricGeometry is used internally in MeshIntegrals.jl to behave like a generic wrapper for geometries with custom parametric functions. This type is used for transforming other geometries to enable integration over the standard rectangular [0,1]^n domain.

Meshes.jl adopted a ParametrizedCurve type that performs a similar role as of v0.51.20, but only supports geometries with one parametric dimension. Support is additionally planned for more types that span surfaces and volumes, at which time this custom type will probably no longer be required.

Fields

  • fun - anything callable representing a parametric function: (ts...) -> Meshes.Point

Type Structure

  • M <: Meshes.Manifold - same usage as in Meshes.Geometry{M, C}
  • C <: CoordRefSystems.CRS - same usage as in Meshes.Geometry{M, C}
  • F - type of the callable parametric function
  • Dim - number of parametric dimensions
source
MeshIntegrals._ParametricGeometryMethod
_ParametricGeometry(fun, dims)

Construct a _ParametricGeometry using a provided parametric function fun for a geometry with dims parametric dimensions.

Arguments

  • fun - anything callable representing a parametric function mapping (ts...) -> Meshes.Point
  • dims::Int64 - number of parametric dimensions, i.e. length(ts)
source
MeshIntegrals._parametricFunction
_parametric(geometry::G, ts...) where {G <: Meshes.Geometry}

Used in MeshIntegrals.jl for defining parametric functions that transform non-standard geometries into a form that can be integrated over the standard rectangular [0,1]^n limits.

source

Aliases

Integration Rules

MeshIntegrals.GaussKronrodType
GaussKronrod(kwargs...)

The h-adaptive Gauss-Kronrod quadrature rule implemented by QuadGK.jl. All standard QuadGK.quadgk keyword arguments are supported. This rule works natively for one dimensional geometries; some two- and three-dimensional geometries are additionally supported using nested integral solvers with the specified kwarg settings.

source
MeshIntegrals.GaussLegendreType
GaussLegendre(n)

An n'th-order Gauss-Legendre quadrature rule. Nodes and weights are efficiently calculated using FastGaussQuadrature.jl.

So long as the integrand function can be well-approximated by a polynomial of order 2n-1, this method should yield results with 16-digit accuracy in O(n) time. If the function is know to have some periodic content, then n should (at a minimum) be greater than the expected number of periods over the geometry, e.g. length(geometry)/λ.

source

Derivatives

MeshIntegrals.AnalyticalType
Analytical()

Use to specify use of analytically-derived solutions for calculating derivatives. These solutions are currently defined only for a subset of geometry types.

Supported Geometries:

  • BezierCurve
  • Line
  • Plane
  • Ray
  • Tetrahedron
  • Triangle
source
MeshIntegrals.FiniteDifferenceType
FiniteDifference(ε=1e-6)

Use to specify use of a finite-difference approximation method with a step size of ε for calculating derivatives.

source
MeshIntegrals.differentialMethod
differential(geometry, ts[, diff_method])

Calculate the differential element (length, area, volume, etc) of the parametric function for geometry at arguments ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.

Arguments

  • geometry: some Meshes.Geometry of N parametric dimensions
  • ts: a parametric point specified as a vector or tuple of length N
  • diff_method: the desired DifferentiationMethod to use
source
MeshIntegrals.jacobianMethod
jacobian(geometry, ts[, diff_method])

Calculate the Jacobian of a geometry's parametric function at some point ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.

Arguments

  • geometry: some Meshes.Geometry of N parametric dimensions
  • ts: a parametric point specified as a vector or tuple of length N
  • diff_method: the desired DifferentiationMethod to use
source
+Public API · MeshIntegrals.jl

Public API

Integrals

MeshIntegrals.integralFunction
integral(f, geometry[, rule]; diff_method=_default_method(geometry), FP=Float64)

Numerically integrate a given function f(::Point) over the domain defined by a geometry using a particular numerical integration rule with floating point precision of type FP.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • geometry: some Meshes.Geometry that defines the integration domain
  • rule: optionally, the IntegrationRule used for integration (by default

GaussKronrod() in 1D and HAdaptiveCubature() else)

Keyword Arguments

  • diff_method::DifferentiationMethod = _default_method(geometry): the method to

use for calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired.
source

Specializations

MeshIntegrals.integralMethod
integral(f, curve::BezierCurve, rule = GaussKronrod();
+         diff_method=Analytical(), FP=Float64, alg=Meshes.Horner())

Like integral but integrates along the domain defined by curve.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • curve: a Meshes.BezierCurve that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = Analytical(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
  • alg = Meshes.Horner(): the method to use for parameterizing curve. Alternatively,

alg=Meshes.DeCasteljau() can be specified for increased accuracy, but comes with a steep performance cost, especially for curves with a large number of control points.

source
MeshIntegrals.integralMethod
integral(f, ring::Ring, rule = GaussKronrod();
+         diff_method=FiniteDifference(), FP=Float64)

Like integral but integrates along the domain defined by ring. The specified integration rule is applied independently to each segment formed by consecutive points in the Ring.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • ring: a Ring that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = FiniteDifference(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
source
MeshIntegrals.integralMethod
integral(f, rope::Rope, rule = GaussKronrod();
+         diff_method=FiniteDifference(), FP=Float64)

Like integral but integrates along the domain defined by rope. The specified integration rule is applied independently to each segment formed by consecutive points in the Rope.

Arguments

  • f: an integrand function, i.e. any callable with a method f(::Meshes.Point)
  • rope: a Rope that defines the integration domain
  • rule = GaussKronrod(): optionally, the IntegrationRule used for integration

Keyword Arguments

  • diff_method::DifferentiationMethod = FiniteDifference(): the method to use for

calculating Jacobians that are used to calculate differential elements

  • FP = Float64: the floating point precision desired
source
MeshIntegrals._ParametricGeometryType
_ParametricGeometry <: Meshes.Primitive <: Meshes.Geometry

_ParametricGeometry is used internally in MeshIntegrals.jl to behave like a generic wrapper for geometries with custom parametric functions. This type is used for transforming other geometries to enable integration over the standard rectangular [0,1]^n domain.

Meshes.jl adopted a ParametrizedCurve type that performs a similar role as of v0.51.20, but only supports geometries with one parametric dimension. Support is additionally planned for more types that span surfaces and volumes, at which time this custom type will probably no longer be required.

Fields

  • fun - anything callable representing a parametric function: (ts...) -> Meshes.Point

Type Structure

  • M <: Meshes.Manifold - same usage as in Meshes.Geometry{M, C}
  • C <: CoordRefSystems.CRS - same usage as in Meshes.Geometry{M, C}
  • F - type of the callable parametric function
  • Dim - number of parametric dimensions
source
MeshIntegrals._ParametricGeometryMethod
_ParametricGeometry(fun, dims)

Construct a _ParametricGeometry using a provided parametric function fun for a geometry with dims parametric dimensions.

Arguments

  • fun - anything callable representing a parametric function mapping (ts...) -> Meshes.Point
  • dims::Int64 - number of parametric dimensions, i.e. length(ts)
source
MeshIntegrals._parametricFunction
_parametric(geometry::G) where {G <: Meshes.Geometry} -> Function

Used in MeshIntegrals.jl for defining parametric functions that transform non-standard geometries into a form that can be integrated over the standard rectangular [0,1]^n limits.

source

Aliases

Integration Rules

MeshIntegrals.GaussKronrodType
GaussKronrod(kwargs...)

The h-adaptive Gauss-Kronrod quadrature rule implemented by QuadGK.jl. All standard QuadGK.quadgk keyword arguments are supported. This rule works natively for one dimensional geometries; some two- and three-dimensional geometries are additionally supported using nested integral solvers with the specified kwarg settings.

source
MeshIntegrals.GaussLegendreType
GaussLegendre(n)

An n'th-order Gauss-Legendre quadrature rule. Nodes and weights are efficiently calculated using FastGaussQuadrature.jl.

So long as the integrand function can be well-approximated by a polynomial of order 2n-1, this method should yield results with 16-digit accuracy in O(n) time. If the function is know to have some periodic content, then n should (at a minimum) be greater than the expected number of periods over the geometry, e.g. length(geometry)/λ.

source

Derivatives

MeshIntegrals.AnalyticalType
Analytical()

Use to specify use of analytically-derived solutions for calculating derivatives. These solutions are currently defined only for a subset of geometry types.

Supported Geometries:

  • BezierCurve
  • Line
  • Plane
  • Ray
  • Tetrahedron
  • Triangle
source
MeshIntegrals.FiniteDifferenceType
FiniteDifference(ε=1e-6)

Use to specify use of a finite-difference approximation method with a step size of ε for calculating derivatives.

source
MeshIntegrals.differentialMethod
differential(geometry, ts[, diff_method])

Calculate the differential element (length, area, volume, etc) of the parametric function for geometry at arguments ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.

Arguments

  • geometry: some Meshes.Geometry of N parametric dimensions
  • ts: a parametric point specified as a vector or tuple of length N
  • diff_method: the desired DifferentiationMethod to use
source
MeshIntegrals.jacobianMethod
jacobian(geometry, ts[, diff_method])

Calculate the Jacobian of a geometry's parametric function at some point ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.

Arguments

  • geometry: some Meshes.Geometry of N parametric dimensions
  • ts: a parametric point specified as a vector or tuple of length N
  • diff_method: the desired DifferentiationMethod to use
source
diff --git a/previews/PR139/how_it_works/index.html b/previews/PR139/how_it_works/index.html index a2cbdd95..0b30631b 100644 --- a/previews/PR139/how_it_works/index.html +++ b/previews/PR139/how_it_works/index.html @@ -8,4 +8,4 @@ ball(tρ, tθ, tφ) # for args in range [0, 1], maps to a corresponding Meshes.Point -ball(0, tθ, tφ) == center

In effect, we can now use the geometry itself as a function that maps from three normalized ($0 \le t \le 1$) arguments to every point on the geometry. For the sake of generalization, let this parametric function be called $g$.

\[\text{g}: (t_1,~t_2,~t_3) ~\mapsto~ \text{Point}\big[ x, ~y, ~z \big] \]

Differential Forms

Using differential forms, the general solution for integrating a geometry with three parametric dimensions ($t_1$, $t_2$, and $t_3$) is

\[\iiint f(r̄) ~ \text{d}V = \iiint f(\bar{r}) ~ \bar{\text{d}t_1} \wedge \bar{\text{d}t_2} \wedge \bar{\text{d}t_3}\]

This resultant differential (volume) element is formed at each point in the integration domain by taking the Jacobian of the parametric function.

\[\mathbf{J}_f = \begin{bmatrix} \bar{\text{d}t_1} & \bar{\text{d}t_2} & \bar{\text{d}t_3} \end{bmatrix}\]

where

\[\bar{\text{d}t_n} = \frac{\partial}{\partial t_n} ~ \text{g}(t_1,~t_2,~t_3)\]

Each of these partial derivatives is a vector representing the direction that changing each parametric function argument will move the resultant point. The differential element ($E$) size is then calculated using geometric algebra as the magnitude of the exterior product ($\wedge$) of these three vectors.

\[E(t_1,~t_2,~t_3) = \left\| \bar{\text{d}t_1} \wedge \bar{\text{d}t_2} \wedge \bar{\text{d}t_3} \right\|\]

Finally, we use the parametric function itself, $g$, as a map to all points $\bar{r}$ in the integration domain. Since Meshes.Geometry parametric functions all operate on normalized domains, we can now solve any volume integral as simply

\[\int_0^1 \int_0^1 \int_0^1 f\Big(\text{g}\big(t_1,~t_2,~t_3\big)\Big) ~ E(t_1,~t_2,~t_3) ~ \text{d}t_1 ~ \text{d}t_2 ~ \text{d}t_3\]

This form of integral can be trivially generalized to support $n$-dimensional geometries in a form that enables the use of a wide range of numerical integration libraries.

+ball(0, tθ, tφ) == center

In effect, we can now use the geometry itself as a function that maps from three normalized ($0 \le t \le 1$) arguments to every point on the geometry. For the sake of generalization, let this parametric function be called $g$.

\[\text{g}: (t_1,~t_2,~t_3) ~\mapsto~ \text{Point}\big[ x, ~y, ~z \big] \]

Differential Forms

Using differential forms, the general solution for integrating a geometry with three parametric dimensions ($t_1$, $t_2$, and $t_3$) is

\[\iiint f(r̄) ~ \text{d}V = \iiint f(\bar{r}) ~ \bar{\text{d}t_1} \wedge \bar{\text{d}t_2} \wedge \bar{\text{d}t_3}\]

This resultant differential (volume) element is formed at each point in the integration domain by taking the Jacobian of the parametric function.

\[\mathbf{J}_f = \begin{bmatrix} \bar{\text{d}t_1} & \bar{\text{d}t_2} & \bar{\text{d}t_3} \end{bmatrix}\]

where

\[\bar{\text{d}t_n} = \frac{\partial}{\partial t_n} ~ \text{g}(t_1,~t_2,~t_3)\]

Each of these partial derivatives is a vector representing the direction that changing each parametric function argument will move the resultant point. The differential element ($E$) size is then calculated using geometric algebra as the magnitude of the exterior product ($\wedge$) of these three vectors.

\[E(t_1,~t_2,~t_3) = \left\| \bar{\text{d}t_1} \wedge \bar{\text{d}t_2} \wedge \bar{\text{d}t_3} \right\|\]

Finally, we use the parametric function itself, $g$, as a map to all points $\bar{r}$ in the integration domain. Since Meshes.Geometry parametric functions all operate on normalized domains, we can now solve any volume integral as simply

\[\int_0^1 \int_0^1 \int_0^1 f\Big(\text{g}\big(t_1,~t_2,~t_3\big)\Big) ~ E(t_1,~t_2,~t_3) ~ \text{d}t_1 ~ \text{d}t_2 ~ \text{d}t_3\]

This form of integral can be trivially generalized to support $n$-dimensional geometries in a form that enables the use of a wide range of numerical integration libraries.

diff --git a/previews/PR139/index.html b/previews/PR139/index.html index 4218df51..783c7851 100644 --- a/previews/PR139/index.html +++ b/previews/PR139/index.html @@ -1,4 +1,4 @@ About · MeshIntegrals.jl

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:

  • Gauss-Legendre quadrature rules from FastGaussQuadrature.jl: GaussLegendre(n)
  • H-adaptive Gauss-Kronrod quadrature rules from QuadGK.jl: GaussKronrod(kwargs...)
  • H-adaptive cubature rules from HCubature.jl: HAdaptiveCubature(kwargs...)

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

Basic

integral(f, geometry)

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

integral(f, geometry, rule)

Performs a numerical integration of some integrand function f over the domain specified by geometry using the specified integration rule, e.g. GaussKronrod(). The integrand function can be anything callable with a method f(::Meshes.Point).

Additionally, several optional keyword arguments are defined in the API to provide additional control over the integration mechanics.

Aliases

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

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

  • lineintegral is used for curve-like geometries or polytopes (e.g. Segment, Ray, BezierCurve, Rope, etc)
  • surfaceintegral is used for surfaces (e.g. Disk, Sphere, CylinderSurface, etc)
  • volumeintegral is used for (3D) volumes (e.g. Ball, Cone, Torus, etc)
+volumeintegral(f, geometry)

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

diff --git a/previews/PR139/search_index.js b/previews/PR139/search_index.js index 7a181047..656cffa2 100644 --- a/previews/PR139/search_index.js +++ b/previews/PR139/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"api/#Public-API","page":"Public API","title":"Public API","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"CurrentModule = MeshIntegrals","category":"page"},{"location":"api/#Integrals","page":"Public API","title":"Integrals","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integral.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.integral","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, geometry[, rule]; diff_method=_default_method(geometry), FP=Float64)\n\nNumerically integrate a given function f(::Point) over the domain defined by a geometry using a particular numerical integration rule with floating point precision of type FP.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\ngeometry: some Meshes.Geometry that defines the integration domain\nrule: optionally, the IntegrationRule used for integration (by default\n\nGaussKronrod() in 1D and HAdaptiveCubature() else)\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = _default_method(geometry): the method to\n\nuse for calculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired.\n\n\n\n\n\n","category":"function"},{"location":"api/#Specializations","page":"Public API","title":"Specializations","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = Main.SPECIALIZATIONS_FILES","category":"page"},{"location":"api/#MeshIntegrals.integral-Tuple{Any, Meshes.BezierCurve, IntegrationRule}","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, curve::BezierCurve, rule = GaussKronrod();\n diff_method=Analytical(), FP=Float64, alg=Meshes.Horner())\n\nLike integral but integrates along the domain defined by curve.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\ncurve: a Meshes.BezierCurve that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = Analytical(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\nalg = Meshes.Horner(): the method to use for parameterizing curve. Alternatively,\n\nalg=Meshes.DeCasteljau() can be specified for increased accuracy, but comes with a steep performance cost, especially for curves with a large number of control points.\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.integral-Union{Tuple{I}, Tuple{Any, Meshes.Ring, I}} where I<:IntegrationRule","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, ring::Ring, rule = GaussKronrod();\n diff_method=FiniteDifference(), FP=Float64)\n\nLike integral but integrates along the domain defined by ring. The specified integration rule is applied independently to each segment formed by consecutive points in the Ring.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\nring: a Ring that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = FiniteDifference(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.integral-Union{Tuple{I}, Tuple{Any, Meshes.Rope, I}} where I<:IntegrationRule","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, rope::Rope, rule = GaussKronrod();\n diff_method=FiniteDifference(), FP=Float64)\n\nLike integral but integrates along the domain defined by rope. The specified integration rule is applied independently to each segment formed by consecutive points in the Rope.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\nrope: a Rope that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = FiniteDifference(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals._ParametricGeometry","page":"Public API","title":"MeshIntegrals._ParametricGeometry","text":"_ParametricGeometry <: Meshes.Primitive <: Meshes.Geometry\n\n_ParametricGeometry is used internally in MeshIntegrals.jl to behave like a generic wrapper for geometries with custom parametric functions. This type is used for transforming other geometries to enable integration over the standard rectangular [0,1]^n domain.\n\nMeshes.jl adopted a ParametrizedCurve type that performs a similar role as of v0.51.20, but only supports geometries with one parametric dimension. Support is additionally planned for more types that span surfaces and volumes, at which time this custom type will probably no longer be required.\n\nFields\n\nfun - anything callable representing a parametric function: (ts...) -> Meshes.Point\n\nType Structure\n\nM <: Meshes.Manifold - same usage as in Meshes.Geometry{M, C}\nC <: CoordRefSystems.CRS - same usage as in Meshes.Geometry{M, C}\nF - type of the callable parametric function\nDim - number of parametric dimensions\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals._ParametricGeometry-Tuple{Any, Int64}","page":"Public API","title":"MeshIntegrals._ParametricGeometry","text":"_ParametricGeometry(fun, dims)\n\nConstruct a _ParametricGeometry using a provided parametric function fun for a geometry with dims parametric dimensions.\n\nArguments\n\nfun - anything callable representing a parametric function mapping (ts...) -> Meshes.Point\ndims::Int64 - number of parametric dimensions, i.e. length(ts)\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals._parametric","page":"Public API","title":"MeshIntegrals._parametric","text":"_parametric(geometry::G, ts...) where {G <: Meshes.Geometry}\n\nUsed in MeshIntegrals.jl for defining parametric functions that transform non-standard geometries into a form that can be integrated over the standard rectangular [0,1]^n limits.\n\n\n\n\n\n","category":"function"},{"location":"api/#Aliases","page":"Public API","title":"Aliases","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integral_aliases.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.lineintegral","page":"Public API","title":"MeshIntegrals.lineintegral","text":"lineintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) along a line-like geometry using a particular numerical integration rule with floating point precision of type FP.\n\nRule types available:\n\nGaussKronrod (default)\nGaussLegendre\nHAdaptiveCubature\n\n\n\n\n\n","category":"function"},{"location":"api/#MeshIntegrals.surfaceintegral","page":"Public API","title":"MeshIntegrals.surfaceintegral","text":"surfaceintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) along a surface geometry using a particular numerical integration rule with floating point precision of type FP.\n\nAlgorithm types available:\n\nGaussKronrod\nGaussLegendre\nHAdaptiveCubature (default)\n\n\n\n\n\n","category":"function"},{"location":"api/#MeshIntegrals.volumeintegral","page":"Public API","title":"MeshIntegrals.volumeintegral","text":"volumeintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) throughout a volumetric geometry using a particular numerical integration rule with floating point precision of type FP.\n\nAlgorithm types available:\n\nGaussKronrod\nGaussLegendre\nHAdaptiveCubature (default)\n\n\n\n\n\n","category":"function"},{"location":"api/#Integration-Rules","page":"Public API","title":"Integration Rules","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integration_rules.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.GaussKronrod","page":"Public API","title":"MeshIntegrals.GaussKronrod","text":"GaussKronrod(kwargs...)\n\nThe h-adaptive Gauss-Kronrod quadrature rule implemented by QuadGK.jl. All standard QuadGK.quadgk keyword arguments are supported. This rule works natively for one dimensional geometries; some two- and three-dimensional geometries are additionally supported using nested integral solvers with the specified kwarg settings.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.GaussLegendre","page":"Public API","title":"MeshIntegrals.GaussLegendre","text":"GaussLegendre(n)\n\nAn n'th-order Gauss-Legendre quadrature rule. Nodes and weights are efficiently calculated using FastGaussQuadrature.jl.\n\nSo long as the integrand function can be well-approximated by a polynomial of order 2n-1, this method should yield results with 16-digit accuracy in O(n) time. If the function is know to have some periodic content, then n should (at a minimum) be greater than the expected number of periods over the geometry, e.g. length(geometry)/λ.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.HAdaptiveCubature","page":"Public API","title":"MeshIntegrals.HAdaptiveCubature","text":"HAdaptiveCubature(kwargs...)\n\nThe h-adaptive cubature rule implemented by HCubature.jl. All standard HCubature.hcubature keyword arguments are supported.\n\n\n\n\n\n","category":"type"},{"location":"api/#Derivatives","page":"Public API","title":"Derivatives","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"differentiation.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.Analytical","page":"Public API","title":"MeshIntegrals.Analytical","text":"Analytical()\n\nUse to specify use of analytically-derived solutions for calculating derivatives. These solutions are currently defined only for a subset of geometry types.\n\nSupported Geometries:\n\nBezierCurve\nLine\nPlane\nRay\nTetrahedron\nTriangle\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.DifferentiationMethod","page":"Public API","title":"MeshIntegrals.DifferentiationMethod","text":"DifferentiationMethod\n\nA category of types used to specify the desired method for calculating derivatives. Derivatives are used to form Jacobian matrices when calculating the differential element size throughout the integration region.\n\nSee also FiniteDifference, Analytical.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.FiniteDifference","page":"Public API","title":"MeshIntegrals.FiniteDifference","text":"FiniteDifference(ε=1e-6)\n\nUse to specify use of a finite-difference approximation method with a step size of ε for calculating derivatives.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.differential-Union{Tuple{T}, Tuple{G}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}, DifferentiationMethod}} where {G<:Meshes.Geometry, T<:AbstractFloat}","page":"Public API","title":"MeshIntegrals.differential","text":"differential(geometry, ts[, diff_method])\n\nCalculate the differential element (length, area, volume, etc) of the parametric function for geometry at arguments ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.\n\nArguments\n\ngeometry: some Meshes.Geometry of N parametric dimensions\nts: a parametric point specified as a vector or tuple of length N\ndiff_method: the desired DifferentiationMethod to use\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.jacobian-Union{Tuple{T}, Tuple{G}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}}} where {G<:Meshes.Geometry, T<:AbstractFloat}","page":"Public API","title":"MeshIntegrals.jacobian","text":"jacobian(geometry, ts[, diff_method])\n\nCalculate the Jacobian of a geometry's parametric function at some point ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.\n\nArguments\n\ngeometry: some Meshes.Geometry of N parametric dimensions\nts: a parametric point specified as a vector or tuple of length N\ndiff_method: the desired DifferentiationMethod to use\n\n\n\n\n\n","category":"method"},{"location":"usage/#Example-Usage","page":"Example Usage","title":"Example Usage","text":"","category":"section"},{"location":"usage/#Integrating-along-a-Bezier-curve","page":"Example Usage","title":"Integrating along a Bezier curve","text":"","category":"section"},{"location":"usage/","page":"Example Usage","title":"Example Usage","text":"using Meshes\nusing MeshIntegrals\n\n# Define a unit circle on the xy-plane\norigin = Point(0,0,0)\nẑ = Vec(0,0,1)\nxy_plane = Plane(origin,ẑ)\nunit_circle_xy = Circle(xy_plane, 1.0)\n\n# Approximate unit_circle_xy with a high-order Bezier curve\nunit_circle_bz = BezierCurve(\n [Point(cos(t), sin(t), 0.0) for t in range(0,2pi,length=361)]\n)\n\n# A Real-valued function\nf(x, y, z) = abs(x + y)\nf(p) = f(to(p)...)\n\nintegral(f, unit_circle_xy, GaussKronrod())\n # 0.000170 seconds (5.00 k allocations: 213.531 KiB)\n # ans == 5.656854249525293 m^2\n\nintegral(f, unit_circle_bz, GaussKronrod())\n # 0.017122 seconds (18.93 k allocations: 78.402 MiB)\n # ans = 5.551055333711397 m^2","category":"page"},{"location":"supportmatrix/#Support-Matrix","page":"Support Matrix","title":"Support Matrix","text":"","category":"section"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"This library aims to enable users to calculate the value of integrals over all Meshes.jl geometry types using an array of numerical integration rules and techniques. However, some combinations of geometry types and integration rules are ill-suited, and some others are simply not yet implemented. The following Support Matrix captures the current state of support for all geometry/rule combinations. Entries with a green check mark are fully supported and pass unit tests designed to check for accuracy.","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"In general, Gauss-Kronrod integration rules are recommended (and the default) for geometries with one parametric dimension, e.g.: Segment, BezierCurve, and Rope. For geometries with more than one parametric dimension, e.g. surfaces and volumes, H-Adaptive Cubature rules are recommended (and the default).","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"While it is possible to apply nested Gauss-Kronrod rules to numerically integrate geometries with more than one parametric dimension, this produces results that are strictly inferior to using an equivalent H-Adaptive Cubature rule, so support for this usage is not recommended.","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"Symbol Support Level\n✅ Supported\n🎗️ Planned to support in the future\n⚠️ Deprecated\n🛑 Not supported","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"Meshes.Geometry Gauss-Legendre Gauss-Kronrod H-Adaptive Cubature\nBall in 𝔼{2} ✅ ⚠️ ✅\nBall in 𝔼{3} ✅ 🛑 ✅\nBezierCurve ✅ ✅ ✅\nBox in 𝔼{1} ✅ ✅ ✅\nBox in 𝔼{2} ✅ ⚠️ ✅\nBox in 𝔼{≥3} ✅ 🛑 ✅\nCircle ✅ ✅ ✅\nCone ✅ 🛑 ✅\nConeSurface ✅ ⚠️ ✅\nCylinder ✅ 🛑 ✅\nCylinderSurface ✅ ⚠️ ✅\nDisk ✅ ⚠️ ✅\nEllipsoid ✅ ✅ ✅\nFrustum 🎗️ 🎗️ 🎗️\nFrustumSurface ✅ ⚠️ ✅\nHexahedron ✅ ✅ ✅\nLine ✅ ✅ ✅\nParaboloidSurface ✅ ⚠️ ✅\nParametrizedCurve ✅ ✅ ✅\nPlane ✅ ✅ ✅\nPolyarea 🎗️ 🎗️ 🎗️\nPyramid 🎗️ 🎗️ 🎗️\nQuadrangle ✅ ⚠️ ✅\nRay ✅ ✅ ✅\nRing ✅ ✅ ✅\nRope ✅ ✅ ✅\nSegment ✅ ✅ ✅\nSimpleMesh 🎗️ 🎗️ 🎗️\nSphere in 𝔼{2} ✅ ✅ ✅\nSphere in 𝔼{3} ✅ ⚠️ ✅\nTetrahedron ✅ ⚠️ ✅\nTriangle ✅ ✅ ✅\nTorus ✅ ⚠️ ✅\nWedge 🎗️ 🎗️ 🎗️","category":"page"},{"location":"#MeshIntegrals.jl","page":"About","title":"MeshIntegrals.jl","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"(Image: Docs-stable) (Image: Docs-dev) (Image: License: MIT) (Image: ColPrac)","category":"page"},{"location":"","page":"About","title":"About","text":"(Image: Build Status) (Image: codecov) (Image: Coveralls) (Image: Aqua QA)","category":"page"},{"location":"","page":"About","title":"About","text":"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:","category":"page"},{"location":"","page":"About","title":"About","text":"Gauss-Legendre quadrature rules from FastGaussQuadrature.jl: GaussLegendre(n)\nH-adaptive Gauss-Kronrod quadrature rules from QuadGK.jl: GaussKronrod(kwargs...)\nH-adaptive cubature rules from HCubature.jl: HAdaptiveCubature(kwargs...)","category":"page"},{"location":"","page":"About","title":"About","text":"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.","category":"page"},{"location":"#Usage","page":"About","title":"Usage","text":"","category":"section"},{"location":"#Basic","page":"About","title":"Basic","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"integral(f, geometry)","category":"page"},{"location":"","page":"About","title":"About","text":"Performs a numerical integration of some integrand function f over the domain specified by geometry. The integrand function can be anything callable with a method f(::Meshes.Point). A default integration method will be automatically selected according to the geometry: GaussKronrod() for 1D, and HAdaptiveCubature() for all others.","category":"page"},{"location":"","page":"About","title":"About","text":"integral(f, geometry, rule)","category":"page"},{"location":"","page":"About","title":"About","text":"Performs a numerical integration of some integrand function f over the domain specified by geometry using the specified integration rule, e.g. GaussKronrod(). The integrand function can be anything callable with a method f(::Meshes.Point).","category":"page"},{"location":"","page":"About","title":"About","text":"Additionally, several optional keyword arguments are defined in the API to provide additional control over the integration mechanics.","category":"page"},{"location":"#Aliases","page":"About","title":"Aliases","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"lineintegral(f, geometry)\nsurfaceintegral(f, geometry)\nvolumeintegral(f, geometry)","category":"page"},{"location":"","page":"About","title":"About","text":"Alias functions are provided for convenience. These are simply wrappers for integral that also validate that the provided geometry has the expected number of parametric dimensions. Like with integral, a rule can also optionally be specified as a third argument.","category":"page"},{"location":"","page":"About","title":"About","text":"lineintegral is used for curve-like geometries or polytopes (e.g. Segment, Ray, BezierCurve, Rope, etc)\nsurfaceintegral is used for surfaces (e.g. Disk, Sphere, CylinderSurface, etc)\nvolumeintegral is used for (3D) volumes (e.g. Ball, Cone, Torus, etc)","category":"page"},{"location":"how_it_works/#How-it-Works-(By-Example)","page":"How it Works","title":"How it Works (By Example)","text":"","category":"section"},{"location":"how_it_works/#Example-Problem","page":"How it Works","title":"Example Problem","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Let f be a function of position barr in some space.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"function f(r̄::Meshes.Point)\n x, y, z = to(r̄)\n ...\nend","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Let the integration domain be the space (a ball) enclosed by a sphere centered on the origin with a radius of 5 meters.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"center = Meshes.Point(0u\"m\", 0u\"m\", 0u\"m\")\nradius = 5.0u\"m\"\nball = Meshes.Ball(center, radius)","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This integral is often expressed abstractly as simply the following, where the triple integral signs and textdV indicate that the integration domain is some three-dimensional volume.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"iiint f(barr) textdV","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Integrals like this are often solved manually by selecting an appropriate coordinate system and limits that neatly represent the integration domain, e.g.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"int_0^pi int_0^2pi int_0^5 f(barr) textdrhotextdthetatextdphi","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This works great for simple geometries, but requires integration code that is geometry-specific. This package leverages parametric functions defined in Meshes.jl and differential forms to define integral methods that are general solutions for all geometries.","category":"page"},{"location":"how_it_works/#how-parametric","page":"How it Works","title":"Parametric Functions","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Every supported Meshes.Geometry type is defined as having a parametric function that maps from a local parametric coordinate system to every point on the geometry. Curve-like geometries will have a single parametric dimension, surfaces will have two dimensions, and volumes will have three dimensions; this can be checked for a particular geometry via Meshes.paramdim(geometry).","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"For consistency across geometry types, with some notable exceptions, these parametric functions are defined to take coordinates inside a normalized range 01. In the example case of ball, Meshes.jl defines a parametric function mapped in normalized spherical coordinates (t_rho t_theta t_phi). We find, then:","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Meshes.paramdim(ball) == 3 # a volume\n\nball(tρ, tθ, tφ) # for args in range [0, 1], maps to a corresponding Meshes.Point\n\nball(0, tθ, tφ) == center","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"In effect, we can now use the geometry itself as a function that maps from three normalized (0 le t le 1) arguments to every point on the geometry. For the sake of generalization, let this parametric function be called g.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"textg (t_1t_2t_3) mapsto textPointbig x y z big ","category":"page"},{"location":"how_it_works/#Differential-Forms","page":"How it Works","title":"Differential Forms","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Using differential forms, the general solution for integrating a geometry with three parametric dimensions (t_1, t_2, and t_3) is","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"iiint f(r) textdV = iiint f(barr) bartextdt_1 wedge bartextdt_2 wedge bartextdt_3","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This resultant differential (volume) element is formed at each point in the integration domain by taking the Jacobian of the parametric function.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"mathbfJ_f = beginbmatrix bartextdt_1 bartextdt_2 bartextdt_3 endbmatrix","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"where","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"bartextdt_n = fracpartialpartial t_n textg(t_1t_2t_3)","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Each of these partial derivatives is a vector representing the direction that changing each parametric function argument will move the resultant point. The differential element (E) size is then calculated using geometric algebra as the magnitude of the exterior product (wedge) of these three vectors.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"E(t_1t_2t_3) = left bartextdt_1 wedge bartextdt_2 wedge bartextdt_3 right","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Finally, we use the parametric function itself, g, as a map to all points barr in the integration domain. Since Meshes.Geometry parametric functions all operate on normalized domains, we can now solve any volume integral as simply","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"int_0^1 int_0^1 int_0^1 fBig(textgbig(t_1t_2t_3big)Big) E(t_1t_2t_3) textdt_1 textdt_2 textdt_3","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This form of integral can be trivially generalized to support n-dimensional geometries in a form that enables the use of a wide range of numerical integration libraries.","category":"page"},{"location":"specializations/#specializations","page":"Specializations","title":"Specializations","text":"","category":"section"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"There are several notable exceptions to how Meshes.jl defines parametric functions.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Meshes.ConeSurface is essentially a composite type and has a parametric function that only maps the conical portion of the geometry, so the Meshes.Disk base element has to be integrated separately.\nMeshes.CylinderSurface is essentially a composite type and has a parametric function that only maps the cylindrical portion of the geometry, so the Meshes.Disk element has to be integrated separately.\nMeshes.FrustumSurface is essentially a composite type and has a parametric function that only maps the cylindrical portion of the geometry, so the top and bottom Meshes.Disk elements have to be integrated separately.\nMeshes.Line represents a line of infinite length that passes through two points, and it has a parametric function that is valid on the domain (-infty infty).\nMeshes.Plane represents a plane of infinite extent, and it has a parametric function that is valid on the domain (-infty infty)^2.\nMeshes.Ray represents a line that begins at a point and extends in a particular direction with infinite length, and it has a parametric function that is valid on the domain 0 infty).\nMeshes.Ring is a composite type that lacks a parametric function, but can be decomposed into Meshes.Segments and then integrated by adding together the individual integrals.\nMeshes.Rope is a composite type that lacks a parametric function, but can be decomposed into Meshes.Segments and then integrated by adding together the individual integrals.\nMeshes.Triangle has a parametric function that takes coordinates on a 2D barycentric coordinate system. So, for (::Meshes.Triangle)(t1, t2), the coordinates must obey: t_1 t_2 in 01 where t_1 + t_2 le 1.\nMeshes.Tetrahedron has a parametric function that takes coordinates on a 3D barycentric coordinate system. So, for (::Meshes.Tetrahedron)(t1, t2), the coordinates must obey: t_1 t_2 t_3 in 01 where t_1 + t_2 + t_3 le 1.","category":"page"},{"location":"specializations/#Triangle","page":"Specializations","title":"Triangle","text":"","category":"section"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"For a specified Meshes.Triangle surface with area A, let u and v be Barycentric coordinates that span the surface.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_triangle f(barr) textdA\n = iint_triangle fleft( barr(uv) right) left( textdu wedge textdv right)","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since the geometric transformation from the originally-arbitrary domain to a Barycentric domain is linear, the magnitude of the surface element textdu wedge textdv is constant throughout the integration domain. This constant will be equal to twice the magnitude of A.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_triangle f(barr) textdA\n = 2A int_0^1 int_0^1-v fleft( barr(uv) right) textdu textdv","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since the integral domain is a right-triangle in the Barycentric domain, a nested application of Gauss-Kronrod quadrature rules is capable of computing the result, albeit inefficiently. However, many numerical integration methods that require rectangular bounds can not be directly applied.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"In order to enable integration methods that operate over rectangular bounds, two coordinate system transformations are applied: the first maps from Barycentric coordinates (u v) to polar coordinates (r phi), and the second is a non-linear map from polar coordinates to a new curvilinear basis (R phi).","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"For the first transformation, let u = rcosphi and v = rsinphi where textdutextdv = rtextdrtextdphi. The Barycentric triangle's hypotenuse boundary line is described by the function v(u) = 1 - u. Substituting in the previous definitions leads to a new boundary line function in polar coordinate space r(phi) = 1 (sinphi + cosphi).","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^1 int_0^1-v fleft( barr(uv) right) textdu textdv =\n int_0^pi2 int_0^1(sinphi+cosphi) fleft( barr(rphi) right) r textdr textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"These integral boundaries remain non-rectangular, so an additional transformation will be applied to a curvilinear (R phi) space that normalizes all of the hypotenuse boundary line points to R=1. To achieve this, a function R(rphi) is required such that R(r_0 phi) = 1 where r_0 = 1 (sinphi + cosphi)","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"To achieve this, let R(r phi) = r(sinphi + cosphi). Now, substituting some terms leads to","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^pi2 int_0^1(sinphi+cosphi) fleft( barr(rphi) right) r textdr textdphi\n = int_0^pi2 int_0^r_0 fleft( barr(rphi) right) left(fracRsinphi + cosphiright) textdr textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since textdRtextdr = sinphi + cosphi, a change of integral domain leads to","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^pi2 int_0^r_0 fleft( barr(rphi) right) left(fracRsinphi + cosphiright) textdr textdphi\n = int_0^pi2 int_0^1 fleft( barr(Rphi) right) left(fracRleft(sinphi + cosphiright)^2right) textdR textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"The second term in this new integrand function serves as a correction factor that corrects for the impact of the non-linear domain transformation. Since all of the integration bounds are now constants, specialized integration methods can be defined for triangles that performs these domain transformations and then solve the new rectangular integration problem using a wider range of solver options.","category":"page"}] +[{"location":"api/#Public-API","page":"Public API","title":"Public API","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"CurrentModule = MeshIntegrals","category":"page"},{"location":"api/#Integrals","page":"Public API","title":"Integrals","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integral.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.integral","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, geometry[, rule]; diff_method=_default_method(geometry), FP=Float64)\n\nNumerically integrate a given function f(::Point) over the domain defined by a geometry using a particular numerical integration rule with floating point precision of type FP.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\ngeometry: some Meshes.Geometry that defines the integration domain\nrule: optionally, the IntegrationRule used for integration (by default\n\nGaussKronrod() in 1D and HAdaptiveCubature() else)\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = _default_method(geometry): the method to\n\nuse for calculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired.\n\n\n\n\n\n","category":"function"},{"location":"api/#Specializations","page":"Public API","title":"Specializations","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = Main.SPECIALIZATIONS_FILES","category":"page"},{"location":"api/#MeshIntegrals.integral-Tuple{Any, Meshes.BezierCurve, IntegrationRule}","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, curve::BezierCurve, rule = GaussKronrod();\n diff_method=Analytical(), FP=Float64, alg=Meshes.Horner())\n\nLike integral but integrates along the domain defined by curve.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\ncurve: a Meshes.BezierCurve that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = Analytical(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\nalg = Meshes.Horner(): the method to use for parameterizing curve. Alternatively,\n\nalg=Meshes.DeCasteljau() can be specified for increased accuracy, but comes with a steep performance cost, especially for curves with a large number of control points.\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.integral-Union{Tuple{I}, Tuple{Any, Meshes.Ring, I}} where I<:IntegrationRule","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, ring::Ring, rule = GaussKronrod();\n diff_method=FiniteDifference(), FP=Float64)\n\nLike integral but integrates along the domain defined by ring. The specified integration rule is applied independently to each segment formed by consecutive points in the Ring.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\nring: a Ring that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = FiniteDifference(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.integral-Union{Tuple{I}, Tuple{Any, Meshes.Rope, I}} where I<:IntegrationRule","page":"Public API","title":"MeshIntegrals.integral","text":"integral(f, rope::Rope, rule = GaussKronrod();\n diff_method=FiniteDifference(), FP=Float64)\n\nLike integral but integrates along the domain defined by rope. The specified integration rule is applied independently to each segment formed by consecutive points in the Rope.\n\nArguments\n\nf: an integrand function, i.e. any callable with a method f(::Meshes.Point)\nrope: a Rope that defines the integration domain\nrule = GaussKronrod(): optionally, the IntegrationRule used for integration\n\nKeyword Arguments\n\ndiff_method::DifferentiationMethod = FiniteDifference(): the method to use for\n\ncalculating Jacobians that are used to calculate differential elements\n\nFP = Float64: the floating point precision desired\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals._ParametricGeometry","page":"Public API","title":"MeshIntegrals._ParametricGeometry","text":"_ParametricGeometry <: Meshes.Primitive <: Meshes.Geometry\n\n_ParametricGeometry is used internally in MeshIntegrals.jl to behave like a generic wrapper for geometries with custom parametric functions. This type is used for transforming other geometries to enable integration over the standard rectangular [0,1]^n domain.\n\nMeshes.jl adopted a ParametrizedCurve type that performs a similar role as of v0.51.20, but only supports geometries with one parametric dimension. Support is additionally planned for more types that span surfaces and volumes, at which time this custom type will probably no longer be required.\n\nFields\n\nfun - anything callable representing a parametric function: (ts...) -> Meshes.Point\n\nType Structure\n\nM <: Meshes.Manifold - same usage as in Meshes.Geometry{M, C}\nC <: CoordRefSystems.CRS - same usage as in Meshes.Geometry{M, C}\nF - type of the callable parametric function\nDim - number of parametric dimensions\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals._ParametricGeometry-Tuple{Any, Int64}","page":"Public API","title":"MeshIntegrals._ParametricGeometry","text":"_ParametricGeometry(fun, dims)\n\nConstruct a _ParametricGeometry using a provided parametric function fun for a geometry with dims parametric dimensions.\n\nArguments\n\nfun - anything callable representing a parametric function mapping (ts...) -> Meshes.Point\ndims::Int64 - number of parametric dimensions, i.e. length(ts)\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals._parametric","page":"Public API","title":"MeshIntegrals._parametric","text":"_parametric(geometry::G) where {G <: Meshes.Geometry} -> Function\n\nUsed in MeshIntegrals.jl for defining parametric functions that transform non-standard geometries into a form that can be integrated over the standard rectangular [0,1]^n limits.\n\n\n\n\n\n","category":"function"},{"location":"api/#Aliases","page":"Public API","title":"Aliases","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integral_aliases.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.lineintegral","page":"Public API","title":"MeshIntegrals.lineintegral","text":"lineintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) along a line-like geometry using a particular numerical integration rule with floating point precision of type FP.\n\nRule types available:\n\nGaussKronrod (default)\nGaussLegendre\nHAdaptiveCubature\n\n\n\n\n\n","category":"function"},{"location":"api/#MeshIntegrals.surfaceintegral","page":"Public API","title":"MeshIntegrals.surfaceintegral","text":"surfaceintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) along a surface geometry using a particular numerical integration rule with floating point precision of type FP.\n\nAlgorithm types available:\n\nGaussKronrod\nGaussLegendre\nHAdaptiveCubature (default)\n\n\n\n\n\n","category":"function"},{"location":"api/#MeshIntegrals.volumeintegral","page":"Public API","title":"MeshIntegrals.volumeintegral","text":"volumeintegral(f, geometry[, rule]; FP=Float64)\n\nNumerically integrate a given function f(::Point) throughout a volumetric geometry using a particular numerical integration rule with floating point precision of type FP.\n\nAlgorithm types available:\n\nGaussKronrod\nGaussLegendre\nHAdaptiveCubature (default)\n\n\n\n\n\n","category":"function"},{"location":"api/#Integration-Rules","page":"Public API","title":"Integration Rules","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"integration_rules.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.GaussKronrod","page":"Public API","title":"MeshIntegrals.GaussKronrod","text":"GaussKronrod(kwargs...)\n\nThe h-adaptive Gauss-Kronrod quadrature rule implemented by QuadGK.jl. All standard QuadGK.quadgk keyword arguments are supported. This rule works natively for one dimensional geometries; some two- and three-dimensional geometries are additionally supported using nested integral solvers with the specified kwarg settings.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.GaussLegendre","page":"Public API","title":"MeshIntegrals.GaussLegendre","text":"GaussLegendre(n)\n\nAn n'th-order Gauss-Legendre quadrature rule. Nodes and weights are efficiently calculated using FastGaussQuadrature.jl.\n\nSo long as the integrand function can be well-approximated by a polynomial of order 2n-1, this method should yield results with 16-digit accuracy in O(n) time. If the function is know to have some periodic content, then n should (at a minimum) be greater than the expected number of periods over the geometry, e.g. length(geometry)/λ.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.HAdaptiveCubature","page":"Public API","title":"MeshIntegrals.HAdaptiveCubature","text":"HAdaptiveCubature(kwargs...)\n\nThe h-adaptive cubature rule implemented by HCubature.jl. All standard HCubature.hcubature keyword arguments are supported.\n\n\n\n\n\n","category":"type"},{"location":"api/#Derivatives","page":"Public API","title":"Derivatives","text":"","category":"section"},{"location":"api/","page":"Public API","title":"Public API","text":"Modules = [MeshIntegrals]\nPages = [\"differentiation.jl\"]","category":"page"},{"location":"api/#MeshIntegrals.Analytical","page":"Public API","title":"MeshIntegrals.Analytical","text":"Analytical()\n\nUse to specify use of analytically-derived solutions for calculating derivatives. These solutions are currently defined only for a subset of geometry types.\n\nSupported Geometries:\n\nBezierCurve\nLine\nPlane\nRay\nTetrahedron\nTriangle\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.DifferentiationMethod","page":"Public API","title":"MeshIntegrals.DifferentiationMethod","text":"DifferentiationMethod\n\nA category of types used to specify the desired method for calculating derivatives. Derivatives are used to form Jacobian matrices when calculating the differential element size throughout the integration region.\n\nSee also FiniteDifference, Analytical.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.FiniteDifference","page":"Public API","title":"MeshIntegrals.FiniteDifference","text":"FiniteDifference(ε=1e-6)\n\nUse to specify use of a finite-difference approximation method with a step size of ε for calculating derivatives.\n\n\n\n\n\n","category":"type"},{"location":"api/#MeshIntegrals.differential-Union{Tuple{T}, Tuple{G}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}, DifferentiationMethod}} where {G<:Meshes.Geometry, T<:AbstractFloat}","page":"Public API","title":"MeshIntegrals.differential","text":"differential(geometry, ts[, diff_method])\n\nCalculate the differential element (length, area, volume, etc) of the parametric function for geometry at arguments ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.\n\nArguments\n\ngeometry: some Meshes.Geometry of N parametric dimensions\nts: a parametric point specified as a vector or tuple of length N\ndiff_method: the desired DifferentiationMethod to use\n\n\n\n\n\n","category":"method"},{"location":"api/#MeshIntegrals.jacobian-Union{Tuple{T}, Tuple{G}, Tuple{G, Union{Tuple{T, Vararg{T}}, AbstractVector{T}}}} where {G<:Meshes.Geometry, T<:AbstractFloat}","page":"Public API","title":"MeshIntegrals.jacobian","text":"jacobian(geometry, ts[, diff_method])\n\nCalculate the Jacobian of a geometry's parametric function at some point ts. Optionally, direct the use of a particular differentiation method diff_method; by default use analytic solutions where possible and finite difference approximations otherwise.\n\nArguments\n\ngeometry: some Meshes.Geometry of N parametric dimensions\nts: a parametric point specified as a vector or tuple of length N\ndiff_method: the desired DifferentiationMethod to use\n\n\n\n\n\n","category":"method"},{"location":"usage/#Example-Usage","page":"Example Usage","title":"Example Usage","text":"","category":"section"},{"location":"usage/#Integrating-along-a-Bezier-curve","page":"Example Usage","title":"Integrating along a Bezier curve","text":"","category":"section"},{"location":"usage/","page":"Example Usage","title":"Example Usage","text":"using Meshes\nusing MeshIntegrals\n\n# Define a unit circle on the xy-plane\norigin = Point(0,0,0)\nẑ = Vec(0,0,1)\nxy_plane = Plane(origin,ẑ)\nunit_circle_xy = Circle(xy_plane, 1.0)\n\n# Approximate unit_circle_xy with a high-order Bezier curve\nunit_circle_bz = BezierCurve(\n [Point(cos(t), sin(t), 0.0) for t in range(0,2pi,length=361)]\n)\n\n# A Real-valued function\nf(x, y, z) = abs(x + y)\nf(p) = f(to(p)...)\n\nintegral(f, unit_circle_xy, GaussKronrod())\n # 0.000170 seconds (5.00 k allocations: 213.531 KiB)\n # ans == 5.656854249525293 m^2\n\nintegral(f, unit_circle_bz, GaussKronrod())\n # 0.017122 seconds (18.93 k allocations: 78.402 MiB)\n # ans = 5.551055333711397 m^2","category":"page"},{"location":"supportmatrix/#Support-Matrix","page":"Support Matrix","title":"Support Matrix","text":"","category":"section"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"This library aims to enable users to calculate the value of integrals over all Meshes.jl geometry types using an array of numerical integration rules and techniques. However, some combinations of geometry types and integration rules are ill-suited, and some others are simply not yet implemented. The following Support Matrix captures the current state of support for all geometry/rule combinations. Entries with a green check mark are fully supported and pass unit tests designed to check for accuracy.","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"In general, Gauss-Kronrod integration rules are recommended (and the default) for geometries with one parametric dimension, e.g.: Segment, BezierCurve, and Rope. For geometries with more than one parametric dimension, e.g. surfaces and volumes, H-Adaptive Cubature rules are recommended (and the default).","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"While it is possible to apply nested Gauss-Kronrod rules to numerically integrate geometries with more than one parametric dimension, this produces results that are strictly inferior to using an equivalent H-Adaptive Cubature rule, so support for this usage is not recommended.","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"Symbol Support Level\n✅ Supported\n🎗️ Planned to support in the future\n⚠️ Deprecated\n🛑 Not supported","category":"page"},{"location":"supportmatrix/","page":"Support Matrix","title":"Support Matrix","text":"Meshes.Geometry Gauss-Legendre Gauss-Kronrod H-Adaptive Cubature\nBall in 𝔼{2} ✅ ⚠️ ✅\nBall in 𝔼{3} ✅ 🛑 ✅\nBezierCurve ✅ ✅ ✅\nBox in 𝔼{1} ✅ ✅ ✅\nBox in 𝔼{2} ✅ ⚠️ ✅\nBox in 𝔼{≥3} ✅ 🛑 ✅\nCircle ✅ ✅ ✅\nCone ✅ 🛑 ✅\nConeSurface ✅ ⚠️ ✅\nCylinder ✅ 🛑 ✅\nCylinderSurface ✅ ⚠️ ✅\nDisk ✅ ⚠️ ✅\nEllipsoid ✅ ✅ ✅\nFrustum 🎗️ 🎗️ 🎗️\nFrustumSurface ✅ ⚠️ ✅\nHexahedron ✅ ✅ ✅\nLine ✅ ✅ ✅\nParaboloidSurface ✅ ⚠️ ✅\nParametrizedCurve ✅ ✅ ✅\nPlane ✅ ✅ ✅\nPolyarea 🎗️ 🎗️ 🎗️\nPyramid 🎗️ 🎗️ 🎗️\nQuadrangle ✅ ⚠️ ✅\nRay ✅ ✅ ✅\nRing ✅ ✅ ✅\nRope ✅ ✅ ✅\nSegment ✅ ✅ ✅\nSimpleMesh 🎗️ 🎗️ 🎗️\nSphere in 𝔼{2} ✅ ✅ ✅\nSphere in 𝔼{3} ✅ ⚠️ ✅\nTetrahedron ✅ ⚠️ ✅\nTriangle ✅ ✅ ✅\nTorus ✅ ⚠️ ✅\nWedge 🎗️ 🎗️ 🎗️","category":"page"},{"location":"#MeshIntegrals.jl","page":"About","title":"MeshIntegrals.jl","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"(Image: Docs-stable) (Image: Docs-dev) (Image: License: MIT) (Image: ColPrac)","category":"page"},{"location":"","page":"About","title":"About","text":"(Image: Build Status) (Image: codecov) (Image: Coveralls) (Image: Aqua QA)","category":"page"},{"location":"","page":"About","title":"About","text":"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:","category":"page"},{"location":"","page":"About","title":"About","text":"Gauss-Legendre quadrature rules from FastGaussQuadrature.jl: GaussLegendre(n)\nH-adaptive Gauss-Kronrod quadrature rules from QuadGK.jl: GaussKronrod(kwargs...)\nH-adaptive cubature rules from HCubature.jl: HAdaptiveCubature(kwargs...)","category":"page"},{"location":"","page":"About","title":"About","text":"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.","category":"page"},{"location":"#Usage","page":"About","title":"Usage","text":"","category":"section"},{"location":"#Basic","page":"About","title":"Basic","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"integral(f, geometry)","category":"page"},{"location":"","page":"About","title":"About","text":"Performs a numerical integration of some integrand function f over the domain specified by geometry. The integrand function can be anything callable with a method f(::Meshes.Point). A default integration method will be automatically selected according to the geometry: GaussKronrod() for 1D, and HAdaptiveCubature() for all others.","category":"page"},{"location":"","page":"About","title":"About","text":"integral(f, geometry, rule)","category":"page"},{"location":"","page":"About","title":"About","text":"Performs a numerical integration of some integrand function f over the domain specified by geometry using the specified integration rule, e.g. GaussKronrod(). The integrand function can be anything callable with a method f(::Meshes.Point).","category":"page"},{"location":"","page":"About","title":"About","text":"Additionally, several optional keyword arguments are defined in the API to provide additional control over the integration mechanics.","category":"page"},{"location":"#Aliases","page":"About","title":"Aliases","text":"","category":"section"},{"location":"","page":"About","title":"About","text":"lineintegral(f, geometry)\nsurfaceintegral(f, geometry)\nvolumeintegral(f, geometry)","category":"page"},{"location":"","page":"About","title":"About","text":"Alias functions are provided for convenience. These are simply wrappers for integral that also validate that the provided geometry has the expected number of parametric dimensions. Like with integral, a rule can also optionally be specified as a third argument.","category":"page"},{"location":"","page":"About","title":"About","text":"lineintegral is used for curve-like geometries or polytopes (e.g. Segment, Ray, BezierCurve, Rope, etc)\nsurfaceintegral is used for surfaces (e.g. Disk, Sphere, CylinderSurface, etc)\nvolumeintegral is used for (3D) volumes (e.g. Ball, Cone, Torus, etc)","category":"page"},{"location":"how_it_works/#How-it-Works-(By-Example)","page":"How it Works","title":"How it Works (By Example)","text":"","category":"section"},{"location":"how_it_works/#Example-Problem","page":"How it Works","title":"Example Problem","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Let f be a function of position barr in some space.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"function f(r̄::Meshes.Point)\n x, y, z = to(r̄)\n ...\nend","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Let the integration domain be the space (a ball) enclosed by a sphere centered on the origin with a radius of 5 meters.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"center = Meshes.Point(0u\"m\", 0u\"m\", 0u\"m\")\nradius = 5.0u\"m\"\nball = Meshes.Ball(center, radius)","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This integral is often expressed abstractly as simply the following, where the triple integral signs and textdV indicate that the integration domain is some three-dimensional volume.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"iiint f(barr) textdV","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Integrals like this are often solved manually by selecting an appropriate coordinate system and limits that neatly represent the integration domain, e.g.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"int_0^pi int_0^2pi int_0^5 f(barr) textdrhotextdthetatextdphi","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This works great for simple geometries, but requires integration code that is geometry-specific. This package leverages parametric functions defined in Meshes.jl and differential forms to define integral methods that are general solutions for all geometries.","category":"page"},{"location":"how_it_works/#how-parametric","page":"How it Works","title":"Parametric Functions","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Every supported Meshes.Geometry type is defined as having a parametric function that maps from a local parametric coordinate system to every point on the geometry. Curve-like geometries will have a single parametric dimension, surfaces will have two dimensions, and volumes will have three dimensions; this can be checked for a particular geometry via Meshes.paramdim(geometry).","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"For consistency across geometry types, with some notable exceptions, these parametric functions are defined to take coordinates inside a normalized range 01. In the example case of ball, Meshes.jl defines a parametric function mapped in normalized spherical coordinates (t_rho t_theta t_phi). We find, then:","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Meshes.paramdim(ball) == 3 # a volume\n\nball(tρ, tθ, tφ) # for args in range [0, 1], maps to a corresponding Meshes.Point\n\nball(0, tθ, tφ) == center","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"In effect, we can now use the geometry itself as a function that maps from three normalized (0 le t le 1) arguments to every point on the geometry. For the sake of generalization, let this parametric function be called g.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"textg (t_1t_2t_3) mapsto textPointbig x y z big ","category":"page"},{"location":"how_it_works/#Differential-Forms","page":"How it Works","title":"Differential Forms","text":"","category":"section"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Using differential forms, the general solution for integrating a geometry with three parametric dimensions (t_1, t_2, and t_3) is","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"iiint f(r) textdV = iiint f(barr) bartextdt_1 wedge bartextdt_2 wedge bartextdt_3","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This resultant differential (volume) element is formed at each point in the integration domain by taking the Jacobian of the parametric function.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"mathbfJ_f = beginbmatrix bartextdt_1 bartextdt_2 bartextdt_3 endbmatrix","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"where","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"bartextdt_n = fracpartialpartial t_n textg(t_1t_2t_3)","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Each of these partial derivatives is a vector representing the direction that changing each parametric function argument will move the resultant point. The differential element (E) size is then calculated using geometric algebra as the magnitude of the exterior product (wedge) of these three vectors.","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"E(t_1t_2t_3) = left bartextdt_1 wedge bartextdt_2 wedge bartextdt_3 right","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"Finally, we use the parametric function itself, g, as a map to all points barr in the integration domain. Since Meshes.Geometry parametric functions all operate on normalized domains, we can now solve any volume integral as simply","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"int_0^1 int_0^1 int_0^1 fBig(textgbig(t_1t_2t_3big)Big) E(t_1t_2t_3) textdt_1 textdt_2 textdt_3","category":"page"},{"location":"how_it_works/","page":"How it Works","title":"How it Works","text":"This form of integral can be trivially generalized to support n-dimensional geometries in a form that enables the use of a wide range of numerical integration libraries.","category":"page"},{"location":"specializations/#specializations","page":"Specializations","title":"Specializations","text":"","category":"section"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"There are several notable exceptions to how Meshes.jl defines parametric functions.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Meshes.ConeSurface is essentially a composite type and has a parametric function that only maps the conical portion of the geometry, so the Meshes.Disk base element has to be integrated separately.\nMeshes.CylinderSurface is essentially a composite type and has a parametric function that only maps the cylindrical portion of the geometry, so the Meshes.Disk element has to be integrated separately.\nMeshes.FrustumSurface is essentially a composite type and has a parametric function that only maps the cylindrical portion of the geometry, so the top and bottom Meshes.Disk elements have to be integrated separately.\nMeshes.Line represents a line of infinite length that passes through two points, and it has a parametric function that is valid on the domain (-infty infty).\nMeshes.Plane represents a plane of infinite extent, and it has a parametric function that is valid on the domain (-infty infty)^2.\nMeshes.Ray represents a line that begins at a point and extends in a particular direction with infinite length, and it has a parametric function that is valid on the domain 0 infty).\nMeshes.Ring is a composite type that lacks a parametric function, but can be decomposed into Meshes.Segments and then integrated by adding together the individual integrals.\nMeshes.Rope is a composite type that lacks a parametric function, but can be decomposed into Meshes.Segments and then integrated by adding together the individual integrals.\nMeshes.Triangle has a parametric function that takes coordinates on a 2D barycentric coordinate system. So, for (::Meshes.Triangle)(t1, t2), the coordinates must obey: t_1 t_2 in 01 where t_1 + t_2 le 1.\nMeshes.Tetrahedron has a parametric function that takes coordinates on a 3D barycentric coordinate system. So, for (::Meshes.Tetrahedron)(t1, t2), the coordinates must obey: t_1 t_2 t_3 in 01 where t_1 + t_2 + t_3 le 1.","category":"page"},{"location":"specializations/#Triangle","page":"Specializations","title":"Triangle","text":"","category":"section"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"For a specified Meshes.Triangle surface with area A, let u and v be Barycentric coordinates that span the surface.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_triangle f(barr) textdA\n = iint_triangle fleft( barr(uv) right) left( textdu wedge textdv right)","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since the geometric transformation from the originally-arbitrary domain to a Barycentric domain is linear, the magnitude of the surface element textdu wedge textdv is constant throughout the integration domain. This constant will be equal to twice the magnitude of A.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_triangle f(barr) textdA\n = 2A int_0^1 int_0^1-v fleft( barr(uv) right) textdu textdv","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since the integral domain is a right-triangle in the Barycentric domain, a nested application of Gauss-Kronrod quadrature rules is capable of computing the result, albeit inefficiently. However, many numerical integration methods that require rectangular bounds can not be directly applied.","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"In order to enable integration methods that operate over rectangular bounds, two coordinate system transformations are applied: the first maps from Barycentric coordinates (u v) to polar coordinates (r phi), and the second is a non-linear map from polar coordinates to a new curvilinear basis (R phi).","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"For the first transformation, let u = rcosphi and v = rsinphi where textdutextdv = rtextdrtextdphi. The Barycentric triangle's hypotenuse boundary line is described by the function v(u) = 1 - u. Substituting in the previous definitions leads to a new boundary line function in polar coordinate space r(phi) = 1 (sinphi + cosphi).","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^1 int_0^1-v fleft( barr(uv) right) textdu textdv =\n int_0^pi2 int_0^1(sinphi+cosphi) fleft( barr(rphi) right) r textdr textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"These integral boundaries remain non-rectangular, so an additional transformation will be applied to a curvilinear (R phi) space that normalizes all of the hypotenuse boundary line points to R=1. To achieve this, a function R(rphi) is required such that R(r_0 phi) = 1 where r_0 = 1 (sinphi + cosphi)","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"To achieve this, let R(r phi) = r(sinphi + cosphi). Now, substituting some terms leads to","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^pi2 int_0^1(sinphi+cosphi) fleft( barr(rphi) right) r textdr textdphi\n = int_0^pi2 int_0^r_0 fleft( barr(rphi) right) left(fracRsinphi + cosphiright) textdr textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"Since textdRtextdr = sinphi + cosphi, a change of integral domain leads to","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"int_0^pi2 int_0^r_0 fleft( barr(rphi) right) left(fracRsinphi + cosphiright) textdr textdphi\n = int_0^pi2 int_0^1 fleft( barr(Rphi) right) left(fracRleft(sinphi + cosphiright)^2right) textdR textdphi","category":"page"},{"location":"specializations/","page":"Specializations","title":"Specializations","text":"The second term in this new integrand function serves as a correction factor that corrects for the impact of the non-linear domain transformation. Since all of the integration bounds are now constants, specialized integration methods can be defined for triangles that performs these domain transformations and then solve the new rectangular integration problem using a wider range of solver options.","category":"page"}] } diff --git a/previews/PR139/specializations/index.html b/previews/PR139/specializations/index.html index b285fe97..48ca78f6 100644 --- a/previews/PR139/specializations/index.html +++ b/previews/PR139/specializations/index.html @@ -4,4 +4,4 @@ = 2A \int_0^1 \int_0^{1-v} f\left( \bar{r}(u,v) \right) \, \text{d}u \, \text{d}v\]

Since the integral domain is a right-triangle in the Barycentric domain, a nested application of Gauss-Kronrod quadrature rules is capable of computing the result, albeit inefficiently. However, many numerical integration methods that require rectangular bounds can not be directly applied.

In order to enable integration methods that operate over rectangular bounds, two coordinate system transformations are applied: the first maps from Barycentric coordinates $(u, v)$ to polar coordinates $(r, \phi)$, and the second is a non-linear map from polar coordinates to a new curvilinear basis $(R, \phi)$.

For the first transformation, let $u = r~\cos\phi$ and $v = r~\sin\phi$ where $\text{d}u~\text{d}v = r~\text{d}r~\text{d}\phi$. The Barycentric triangle's hypotenuse boundary line is described by the function $v(u) = 1 - u$. Substituting in the previous definitions leads to a new boundary line function in polar coordinate space $r(\phi) = 1 / (\sin\phi + \cos\phi)$.

\[\int_0^1 \int_0^{1-v} f\left( \bar{r}(u,v) \right) \, \text{d}u \, \text{d}v = \int_0^{\pi/2} \int_0^{1/(\sin\phi+\cos\phi)} f\left( \bar{r}(r,\phi) \right) \, r \, \text{d}r \, \text{d}\phi\]

These integral boundaries remain non-rectangular, so an additional transformation will be applied to a curvilinear $(R, \phi)$ space that normalizes all of the hypotenuse boundary line points to $R=1$. To achieve this, a function $R(r,\phi)$ is required such that $R(r_0, \phi) = 1$ where $r_0 = 1 / (\sin\phi + \cos\phi)$

To achieve this, let $R(r, \phi) = r~(\sin\phi + \cos\phi)$. Now, substituting some terms leads to

\[\int_0^{\pi/2} \int_0^{1/(\sin\phi+\cos\phi)} f\left( \bar{r}(r,\phi) \right) \, r \, \text{d}r \, \text{d}\phi = \int_0^{\pi/2} \int_0^{r_0} f\left( \bar{r}(r,\phi) \right) \, \left(\frac{R}{\sin\phi + \cos\phi}\right) \, \text{d}r \, \text{d}\phi\]

Since $\text{d}R/\text{d}r = \sin\phi + \cos\phi$, a change of integral domain leads to

\[\int_0^{\pi/2} \int_0^{r_0} f\left( \bar{r}(r,\phi) \right) \, \left(\frac{R}{\sin\phi + \cos\phi}\right) \, \text{d}r \, \text{d}\phi - = \int_0^{\pi/2} \int_0^1 f\left( \bar{r}(R,\phi) \right) \, \left(\frac{R}{\left(\sin\phi + \cos\phi\right)^2}\right) \, \text{d}R \, \text{d}\phi\]

The second term in this new integrand function serves as a correction factor that corrects for the impact of the non-linear domain transformation. Since all of the integration bounds are now constants, specialized integration methods can be defined for triangles that performs these domain transformations and then solve the new rectangular integration problem using a wider range of solver options.

+ = \int_0^{\pi/2} \int_0^1 f\left( \bar{r}(R,\phi) \right) \, \left(\frac{R}{\left(\sin\phi + \cos\phi\right)^2}\right) \, \text{d}R \, \text{d}\phi\]

The second term in this new integrand function serves as a correction factor that corrects for the impact of the non-linear domain transformation. Since all of the integration bounds are now constants, specialized integration methods can be defined for triangles that performs these domain transformations and then solve the new rectangular integration problem using a wider range of solver options.

diff --git a/previews/PR139/supportmatrix/index.html b/previews/PR139/supportmatrix/index.html index 97baefb7..045c4ec1 100644 --- a/previews/PR139/supportmatrix/index.html +++ b/previews/PR139/supportmatrix/index.html @@ -1,2 +1,2 @@ -Support Matrix · MeshIntegrals.jl

Support Matrix

This library aims to enable users to calculate the value of integrals over all Meshes.jl geometry types using an array of numerical integration rules and techniques. However, some combinations of geometry types and integration rules are ill-suited, and some others are simply not yet implemented. The following Support Matrix captures the current state of support for all geometry/rule combinations. Entries with a green check mark are fully supported and pass unit tests designed to check for accuracy.

In general, Gauss-Kronrod integration rules are recommended (and the default) for geometries with one parametric dimension, e.g.: Segment, BezierCurve, and Rope. For geometries with more than one parametric dimension, e.g. surfaces and volumes, H-Adaptive Cubature rules are recommended (and the default).

While it is possible to apply nested Gauss-Kronrod rules to numerically integrate geometries with more than one parametric dimension, this produces results that are strictly inferior to using an equivalent H-Adaptive Cubature rule, so support for this usage is not recommended.

SymbolSupport Level
Supported
🎗️Planned to support in the future
⚠️Deprecated
🛑Not supported
Meshes.GeometryGauss-LegendreGauss-KronrodH-Adaptive Cubature
Ball in 𝔼{2}⚠️
Ball in 𝔼{3}🛑
BezierCurve
Box in 𝔼{1}
Box in 𝔼{2}⚠️
Box in 𝔼{≥3}🛑
Circle
Cone🛑
ConeSurface⚠️
Cylinder🛑
CylinderSurface⚠️
Disk⚠️
Ellipsoid
Frustum🎗️🎗️🎗️
FrustumSurface⚠️
Hexahedron
Line
ParaboloidSurface⚠️
ParametrizedCurve
Plane
Polyarea🎗️🎗️🎗️
Pyramid🎗️🎗️🎗️
Quadrangle⚠️
Ray
Ring
Rope
Segment
SimpleMesh🎗️🎗️🎗️
Sphere in 𝔼{2}
Sphere in 𝔼{3}⚠️
Tetrahedron⚠️
Triangle
Torus⚠️
Wedge🎗️🎗️🎗️
+Support Matrix · MeshIntegrals.jl

Support Matrix

This library aims to enable users to calculate the value of integrals over all Meshes.jl geometry types using an array of numerical integration rules and techniques. However, some combinations of geometry types and integration rules are ill-suited, and some others are simply not yet implemented. The following Support Matrix captures the current state of support for all geometry/rule combinations. Entries with a green check mark are fully supported and pass unit tests designed to check for accuracy.

In general, Gauss-Kronrod integration rules are recommended (and the default) for geometries with one parametric dimension, e.g.: Segment, BezierCurve, and Rope. For geometries with more than one parametric dimension, e.g. surfaces and volumes, H-Adaptive Cubature rules are recommended (and the default).

While it is possible to apply nested Gauss-Kronrod rules to numerically integrate geometries with more than one parametric dimension, this produces results that are strictly inferior to using an equivalent H-Adaptive Cubature rule, so support for this usage is not recommended.

SymbolSupport Level
Supported
🎗️Planned to support in the future
⚠️Deprecated
🛑Not supported
Meshes.GeometryGauss-LegendreGauss-KronrodH-Adaptive Cubature
Ball in 𝔼{2}⚠️
Ball in 𝔼{3}🛑
BezierCurve
Box in 𝔼{1}
Box in 𝔼{2}⚠️
Box in 𝔼{≥3}🛑
Circle
Cone🛑
ConeSurface⚠️
Cylinder🛑
CylinderSurface⚠️
Disk⚠️
Ellipsoid
Frustum🎗️🎗️🎗️
FrustumSurface⚠️
Hexahedron
Line
ParaboloidSurface⚠️
ParametrizedCurve
Plane
Polyarea🎗️🎗️🎗️
Pyramid🎗️🎗️🎗️
Quadrangle⚠️
Ray
Ring
Rope
Segment
SimpleMesh🎗️🎗️🎗️
Sphere in 𝔼{2}
Sphere in 𝔼{3}⚠️
Tetrahedron⚠️
Triangle
Torus⚠️
Wedge🎗️🎗️🎗️
diff --git a/previews/PR139/usage/index.html b/previews/PR139/usage/index.html index ecded21c..3442b81b 100644 --- a/previews/PR139/usage/index.html +++ b/previews/PR139/usage/index.html @@ -23,4 +23,4 @@ integral(f, unit_circle_bz, GaussKronrod()) # 0.017122 seconds (18.93 k allocations: 78.402 MiB) - # ans = 5.551055333711397 m^2 + # ans = 5.551055333711397 m^2