Initial commit

This commit is contained in:
redclawsystems
2026-03-04 00:08:42 +00:00
commit 4d88dc0584
4449 changed files with 1556714 additions and 0 deletions
@@ -0,0 +1,297 @@
// Copyright (c) 2024 RustyTorch++ Team
// Licensed under the Apache License, Version 2.0
//! Numerical integration (quadrature) rules for finite elements.
//!
//! This module provides comprehensive Gauss quadrature implementations
//! for all supported element types with optimized GPU operations.
pub mod quadrature_adaptive;
pub mod quadrature_types;
pub use quadrature_adaptive::*;
pub use quadrature_types::*;
#[cfg(disabled)]
mod tests {
use super::*;
#[test]
fn test_1d_gauss_legendre() {
let rule = QuadratureRule::gauss_legendre_1d(2).unwrap();
assert_eq!(rule.num_points(), 2);
assert_eq!(rule.dimension, 1);
// Test integration of f(x) = x^2 from -1 to 1
// Exact integral is 2/3
let result = rule.integrate(|coords| coords.xi() * coords.xi());
assert!((result - 2.0 / 3.0).abs() < 1e-14);
}
#[test]
fn test_2d_quad_rule() {
let rule = QuadratureRule::quad(2).unwrap();
assert_eq!(rule.num_points(), 4);
assert_eq!(rule.dimension, 2);
// Test integration of f(x,y) = 1 over [-1,1]^2
// Exact integral is 4
let result = rule.integrate(|_| 1.0);
assert!((result - 4.0).abs() < 1e-14);
}
#[test]
fn test_3d_hex_rule() {
let rule = QuadratureRule::hex(2).unwrap();
assert_eq!(rule.num_points(), 8);
assert_eq!(rule.dimension, 3);
// Test integration of f(x,y,z) = 1 over [-1,1]^3
// Exact integral is 8
let result = rule.integrate(|_| 1.0);
assert!((result - 8.0).abs() < 1e-14);
}
#[test]
fn test_triangle_rule() {
let rule = QuadratureRule::triangle(1).unwrap();
assert_eq!(rule.num_points(), 1);
// Test integration of f(x,y) = 1 over unit triangle
// Area of reference triangle is 0.5
let result = rule.integrate(|_| 1.0);
assert!((result - 0.5).abs() < 1e-14);
}
#[test]
fn test_tetrahedron_rule() {
let rule = QuadratureRule::tetrahedron(1).unwrap();
assert_eq!(rule.num_points(), 1);
// Test integration of f(x,y,z) = 1 over unit tetrahedron
// Volume of reference tetrahedron is 1/6
let result = rule.integrate(|_| 1.0);
assert!((result - 1.0 / 6.0).abs() < 1e-14);
}
#[test]
fn test_high_order_accuracy() {
// Test that higher order rules are more accurate
let rule_2 = QuadratureRule::gauss_legendre_1d(2).unwrap();
let rule_4 = QuadratureRule::gauss_legendre_1d(4).unwrap();
// Integrate f(x) = x^4
let exact = 2.0 / 5.0;
let result_2 = rule_2.integrate(|coords| coords.xi().powi(4));
let result_4 = rule_4.integrate(|coords| coords.xi().powi(4));
let error_2 = (result_2 - exact).abs();
let error_4 = (result_4 - exact).abs();
assert!(error_4 < error_2);
assert!(error_4 < 1e-14);
}
#[test]
fn test_vector_integration() {
use nalgebra::DVector;
let rule = QuadratureRule::quad(2).unwrap();
// Integrate vector function [x, y]
let result = rule.integrate_vector(
|coords| DVector::from_vec(vec![coords.xi(), coords.eta()]),
2,
);
// Both components should integrate to 0 over symmetric domain
assert!(result[0].abs() < 1e-14);
assert!(result[1].abs() < 1e-14);
}
#[test]
fn test_quadrature_validation() {
let rule = QuadratureRule::quad(3).unwrap();
assert!(rule.validate().is_ok());
// Test that weights sum correctly
let weight_sum: f64 = rule.points.iter().map(|p| p.weight).sum();
assert!((weight_sum - 4.0).abs() < 1e-14);
}
#[test]
fn test_quadrature_point_access() {
let rule = QuadratureRule::line(2).unwrap();
// Valid access
let point = rule.point(0).unwrap();
assert!(point.weight > 0.0);
// Invalid access
let invalid = rule.point(100);
assert!(invalid.is_err());
}
#[test]
fn test_gauss_lobatto_rule() {
let rule = HighOrderQuadrature::gauss_lobatto_1d(3).unwrap();
assert_eq!(rule.num_points(), 3);
// Check that endpoints are included
assert_eq!(rule.points[0].coords.xi(), -1.0);
assert_eq!(rule.points[2].coords.xi(), 1.0);
// Test integration
let result = rule.integrate(|_| 1.0);
assert!((result - 2.0).abs() < 1e-14);
}
#[test]
fn test_pyramid_rule() {
let rule = HighOrderQuadrature::pyramid(1).unwrap();
assert_eq!(rule.num_points(), 1);
// Basic integration test
let result = rule.integrate(|_| 1.0);
assert!(result > 0.0);
}
#[test]
fn test_wedge_rule() {
let rule = HighOrderQuadrature::wedge(2).unwrap();
assert!(rule.num_points() > 0);
// Test that it's a valid 3D rule
assert_eq!(rule.dimension, 3);
}
#[test]
fn test_adaptive_quadrature_1d() {
let base_rule = QuadratureRule::line(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test function: f(x) = x^2, integral from -1 to 1 = 2/3
let result = adaptive
.integrate(|coords| coords.xi() * coords.xi())
.unwrap();
assert!((result - 2.0 / 3.0).abs() < 1e-6);
}
#[test]
fn test_adaptive_quadrature_2d() {
let base_rule = QuadratureRule::quad(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test function: f(x,y) = x*y, integral over [-1,1]^2 = 0
let result = adaptive
.integrate(|coords| coords.xi() * coords.eta())
.unwrap();
assert!(result.abs() < 1e-10, "Expected 0, got {}", result);
}
#[test]
fn test_adaptive_quadrature_3d() {
let base_rule = QuadratureRule::hex(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test function: f(x,y,z) = x*y*z, integral over [-1,1]^3 = 0
let result = adaptive
.integrate(|coords| coords.xi() * coords.eta() * coords.zeta())
.unwrap();
assert!(result.abs() < 1e-10, "Expected 0, got {}", result);
}
#[test]
fn test_adaptive_quadrature_discontinuous_function() {
let base_rule = QuadratureRule::line(4).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-4, 5);
// Test discontinuous function (requires subdivision for accuracy)
let result = adaptive
.integrate(|coords| if coords.xi() > 0.0 { 1.0 } else { -1.0 })
.unwrap();
// Integral should be 0 (equal positive and negative areas)
assert!(result.abs() < 1e-3, "Expected ~0, got {}", result);
}
#[test]
fn test_adaptive_quadrature_polynomial() {
let base_rule = QuadratureRule::line(3).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-8, 4);
// Test polynomial: f(x) = x^4, integral from -1 to 1 = 2/5
let result = adaptive.integrate(|coords| coords.xi().powi(4)).unwrap();
let expected = 2.0 / 5.0;
assert!(
(result - expected).abs() < 1e-12,
"Expected {}, got {}",
expected,
result
);
}
#[test]
fn test_adaptive_quadrature_convergence() {
let base_rule = QuadratureRule::line(2).unwrap();
// Test with tight tolerance
let adaptive_tight = AdaptiveQuadrature::new(base_rule.clone(), 1e-10, 5);
let result_tight = adaptive_tight
.integrate(|coords| coords.xi().exp())
.unwrap();
// Test with loose tolerance
let adaptive_loose = AdaptiveQuadrature::new(base_rule, 1e-4, 2);
let result_loose = adaptive_loose
.integrate(|coords| coords.xi().exp())
.unwrap();
// Tight tolerance should be more accurate
let expected = (1.0_f64.exp() - (-1.0_f64).exp()); // e - e^(-1)
assert!((result_tight - expected).abs() < (result_loose - expected).abs());
}
#[test]
fn test_subdomain_creation_1d() {
let base_rule = QuadratureRule::line(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test subdomain rule creation
let subdomain_rule = adaptive.create_subdomain_rule_1d(-1.0, 0.0).unwrap();
// Verify the subdomain rule integrates correctly over [-1, 0]
let result = subdomain_rule.integrate(|_| 1.0); // Constant function
assert!((result - 1.0).abs() < 1e-10, "Expected 1.0, got {}", result); // Length of interval
}
#[test]
fn test_subdomain_creation_2d() {
let base_rule = QuadratureRule::quad(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test 2D subdomain rule creation
let subdomain_rule = adaptive
.create_subdomain_rule_2d(-1.0, 0.0, -1.0, 0.0)
.unwrap();
// Verify the subdomain rule integrates correctly over [-1,0] x [-1,0]
let result = subdomain_rule.integrate(|_| 1.0); // Constant function
assert!((result - 1.0).abs() < 1e-10, "Expected 1.0, got {}", result); // Area of quarter
}
#[test]
fn test_subdomain_creation_3d() {
let base_rule = QuadratureRule::hex(2).unwrap();
let adaptive = AdaptiveQuadrature::new(base_rule, 1e-6, 3);
// Test 3D subdomain rule creation
let subdomain_rule = adaptive
.create_subdomain_rule_3d(-1.0, 0.0, -1.0, 0.0, -1.0, 0.0)
.unwrap();
// Verify the subdomain rule integrates correctly over [-1,0]^3
let result = subdomain_rule.integrate(|_| 1.0); // Constant function
assert!((result - 1.0).abs() < 1e-10, "Expected 1.0, got {}", result); // Volume of eighth
}
}