quadraturerules 0.9.1

quadrature rules library
Documentation
//! Quadrature rules
#![cfg_attr(feature = "strict", deny(warnings), deny(unused_crate_dependencies))]
#![warn(missing_docs)]

mod rules;

/// A domain of an integral.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[repr(u8)]
pub enum Domain {
    /// interval
    Interval = 0,
    /// quadrilateral
    Quadrilateral = 1,
    /// edge-adjacent quadrilaterals
    EdgeAdjacentQuadrilaterals = 2,
    /// vertex-adjacent quadrilaterals
    VertexAdjacentQuadrilaterals = 3,
    /// triangle
    Triangle = 4,
    /// edge-adjacent triangle and quadrilateral
    EdgeAdjacentTriangleAndQuadrilateral = 5,
    /// vertex-adjacent triangle and quadrilateral
    VertexAdjacentTriangleAndQuadrilateral = 6,
    /// edge-adjacent triangles
    EdgeAdjacentTriangles = 7,
    /// vertex-adjacent triangles
    VertexAdjacentTriangles = 8,
    /// hexahedron
    Hexahedron = 9,
    /// tetrahedron
    Tetrahedron = 10,
    /// square-based pyramid
    SquareBasedPyramid = 11,
    /// triangular prism
    TriangularPrism = 12,
}

/// A quadrature rule family.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[repr(u8)]
pub enum QuadratureRule {
    /// Gauss--Legendre
    GaussLegendre = 1,
    /// Gauss--Lobatto--Legendre
    GaussLobattoLegendre = 3,
    /// Hammer--Marlowe--Stroud
    HammerMarloweStroud = 6,
    /// Sauter--Schwab
    SauterSchwab = 7,
    /// Xiao--Gimbutas
    XiaoGimbutas = 2,
    /// centroid quadrature
    CentroidQuadrature = 5,
    /// closed Newton--Cotes
    ClosedNewtonCotes = 8,
    /// open Newton--Cotes
    OpenNewtonCotes = 9,
    /// vertex quadrature
    VertexQuadrature = 4,
}

/// Get a quadrature rule for a single integral.
pub fn single_integral_quadrature(
    rtype: QuadratureRule,
    domain: Domain,
    order: usize,
) -> Result<(Vec<f64>, Vec<f64>), &'static str> {
    match rtype {
        QuadratureRule::GaussLegendre => rules::gauss_legendre(domain, order),
        QuadratureRule::GaussLobattoLegendre => rules::gauss_lobatto_legendre(domain, order),
        QuadratureRule::HammerMarloweStroud => rules::hammer_marlowe_stroud(domain, order),
        QuadratureRule::XiaoGimbutas => rules::xiao_gimbutas(domain, order),
        QuadratureRule::CentroidQuadrature => rules::centroid_quadrature(domain, order),
        QuadratureRule::ClosedNewtonCotes => rules::closed_newton_cotes(domain, order),
        QuadratureRule::OpenNewtonCotes => rules::open_newton_cotes(domain, order),
        QuadratureRule::VertexQuadrature => rules::vertex_quadrature(domain, order),
        _ => Err("Unsupported rule for single integral"),
    }
}

/// Get a quadrature rule for a double integral.
pub fn double_integral_quadrature(
    rtype: QuadratureRule,
    domain: Domain,
    order: usize,
) -> Result<(Vec<f64>, Vec<f64>, Vec<f64>), &'static str> {
    match rtype {
        QuadratureRule::SauterSchwab => rules::sauter_schwab(domain, order),
        _ => Err("Unsupported rule for double integral"),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use approx::*;

    #[test]
    fn test_sum_weights_1() {
        let weights =
            single_integral_quadrature(QuadratureRule::GaussLegendre, Domain::Interval, 1)
                .unwrap()
                .1;
        assert_relative_eq!(weights.iter().sum::<f64>(), 1.0);
    }

    #[test]
    fn test_sum_weights_2() {
        let weights =
            single_integral_quadrature(QuadratureRule::GaussLegendre, Domain::Interval, 2)
                .unwrap()
                .1;
        assert_relative_eq!(weights.iter().sum::<f64>(), 1.0);
    }

    #[test]
    fn test_sum_weights_3() {
        let weights =
            single_integral_quadrature(QuadratureRule::GaussLegendre, Domain::Interval, 3)
                .unwrap()
                .1;
        assert_relative_eq!(weights.iter().sum::<f64>(), 1.0);
    }
}