pub enum ErrorsGrid1DUnion<Domain1D: IntervalFinitePositiveLengthTrait> {
DomainsMismatch {
domain_grid_a: Domain1D,
domain_grid_b: Domain1D,
backtrace: Backtrace,
},
FromGrid1DConstructor {
source: ErrorsGrid1D<Domain1D>,
},
}
Expand description
FINAL DOC Comprehensive error types for 1D grid union construction and operations.
ErrorsGrid1DUnion
provides specific error information for all failure modes
in grid union operations, enabling robust error handling and debugging when
combining multiple 1D grids into a unified partition.
Grid union operations require strict mathematical consistency between input grids, and this error type captures the specific ways these operations can fail.
§Error Philosophy
The error design follows the library’s principle of mathematical correctness first:
- Domain compatibility: Input grids must have identical domains
- Early failure detection: Errors are caught at construction time, not during use
- Detailed diagnostics: Each error provides specific information about what went wrong
- Type safety: Generic over domain types to provide compile-time guarantees
§Error Variants
§Domain Compatibility Errors
ErrorsGrid1DUnion::DomainsMismatch
: Input grids have incompatible domains
§Construction Errors
ErrorsGrid1DUnion::FromGrid1DConstructor
: Error from underlying unified grid construction
§Design Rationale
§Why Domain Matching is Required
Grid union operations create a unified partition that must be mathematically consistent with both input grids. This requires:
domain(grid_a) = domain(grid_b) = domain(unified_grid)
If domains don’t match, the resulting unified grid would be:
- Mathematically undefined: Cannot create consistent interval mappings
- Physically meaningless: Points from different physical domains cannot be combined
- Computationally invalid: Algorithms expecting domain consistency would fail
§Error Propagation Strategy
The enum uses #[from]
delegation for construction errors, ensuring that:
- Root cause preservation: Original error information is maintained
- Error chain clarity: Developers can trace errors back to their source
- Consistent error handling: Same patterns across the library
§Usage Examples
§Handling Domain Mismatch Errors
use grid1d::{*, intervals::*, scalars::*};
use sorted_vec::partial::SortedSet;
let domain_a = IntervalClosed::new(0.0, 1.0);
let domain_b = IntervalClosed::new(0.0, 2.0); // Different upper bound!
let grid_a = Grid1D::try_from_sorted(
domain_a,
SortedSet::from_unsorted(vec![0.0, 0.5, 1.0])
).unwrap();
let grid_b = Grid1D::try_from_sorted(
domain_b,
SortedSet::from_unsorted(vec![0.0, 1.0, 2.0])
).unwrap();
match Grid1DUnion::try_new(&grid_a, &grid_b) {
Err(ErrorsGrid1DUnion::DomainsMismatch {
domain_grid_a,
domain_grid_b,
..
}) => {
println!("Cannot union grids with different domains:");
println!(" Grid A domain: [{}, {}]",
domain_grid_a.lower_bound_value(),
domain_grid_a.upper_bound_value());
println!(" Grid B domain: [{}, {}]",
domain_grid_b.lower_bound_value(),
domain_grid_b.upper_bound_value());
// Suggest potential fixes
println!("Potential solutions:");
println!(" 1. Ensure both grids cover the same physical domain");
println!(" 2. Trim grids to their common domain intersection");
println!(" 3. Extend the smaller grid to match the larger domain");
}
Ok(union) => {
println!("Successfully created grid union");
}
Err(e) => {
println!("Other error: {}", e);
}
}
§Handling Propagated Construction Errors
use grid1d::{*, intervals::*, scalars::*};
use sorted_vec::partial::SortedSet;
use try_create::TryNew;
fn safe_grid_union<D>(
grid_a: &Grid1D<D>,
grid_b: &Grid1D<D>,
) -> Result<Grid1DUnion<D>, String>
where
D: IntervalInPartitionBuilder + std::fmt::Debug + Clone,
{
Grid1DUnion::try_new(grid_a, grid_b)
.map_err(|e| match e {
ErrorsGrid1DUnion::DomainsMismatch { domain_grid_a, domain_grid_b, .. } => {
format!("Domain mismatch: {:?} vs {:?}", domain_grid_a, domain_grid_b)
}
ErrorsGrid1DUnion::FromGrid1DConstructor { source } => {
format!("Failed to construct unified grid: {}", source)
}
})
}
// Usage
let domain = IntervalClosed::new(0.0, 1.0);
let grid_a = Grid1D::uniform(domain.clone(), NumIntervals::try_new(4).unwrap());
let grid_b = Grid1D::uniform(domain, NumIntervals::try_new(8).unwrap());
match safe_grid_union(&grid_a, &grid_b) {
Ok(union) => println!("Union successful: {} intervals",
union.num_refined_intervals().as_ref()),
Err(msg) => println!("Union failed: {}", msg),
}
§Domain Validation Before Union
use grid1d::{*, intervals::*, scalars::*};
use sorted_vec::partial::SortedSet;
fn validate_grids_for_union<D>(
grid_a: &Grid1D<D>,
grid_b: &Grid1D<D>,
) -> Result<(), String>
where
D: IntervalInPartitionBuilder + PartialEq + std::fmt::Debug,
{
// Pre-validate domains to provide better error messages
if grid_a.domain() != grid_b.domain() {
return Err(format!(
"Grids have incompatible domains:\n Grid A: {:?}\n Grid B: {:?}",
grid_a.domain(),
grid_b.domain()
));
}
// Check for degenerate cases
if grid_a.num_intervals().as_ref() < &1 || grid_b.num_intervals().as_ref() < &1 {
return Err("Both grids must have at least one interval".to_string());
}
Ok(())
}
fn create_validated_union<D>(
grid_a: &Grid1D<D>,
grid_b: &Grid1D<D>,
) -> Result<Grid1DUnion<D>, String>
where
D: IntervalInPartitionBuilder + PartialEq + std::fmt::Debug + Clone,
{
// Validate first for better error messages
validate_grids_for_union(grid_a, grid_b)?;
// Then attempt union
Grid1DUnion::try_new(grid_a, grid_b)
.map_err(|e| format!("Union failed despite validation: {}", e))
}
§Integration with Error Handling Frameworks
use grid1d::{*, intervals::*, scalars::*};
use sorted_vec::partial::SortedSet;
use std::collections::HashMap;
#[derive(Debug)]
enum MultiGridError {
DomainMismatch(String),
ConstructionFailure(String),
InvalidInput(String),
}
impl From<ErrorsGrid1DUnion<IntervalClosed<f64>>> for MultiGridError {
fn from(error: ErrorsGrid1DUnion<IntervalClosed<f64>>) -> Self {
match error {
ErrorsGrid1DUnion::DomainsMismatch { domain_grid_a, domain_grid_b, .. } => {
MultiGridError::DomainMismatch(format!(
"Grid domains don't match: [{}, {}] vs [{}, {}]",
domain_grid_a.lower_bound_value(),
domain_grid_a.upper_bound_value(),
domain_grid_b.lower_bound_value(),
domain_grid_b.upper_bound_value()
))
}
ErrorsGrid1DUnion::FromGrid1DConstructor { source } => {
MultiGridError::ConstructionFailure(format!(
"Failed to build unified grid: {}", source
))
}
}
}
}
fn multi_grid_union(
grids: &[Grid1D<IntervalClosed<f64>>]
) -> Result<Grid1D<IntervalClosed<f64>>, MultiGridError> {
if grids.len() < 2 {
return Err(MultiGridError::InvalidInput(
"Need at least 2 grids for union".to_string()
));
}
let (mut result, _, _) = Grid1DUnion::try_new(&grids[0], &grids[1])?.into_parts();
for grid in &grids[2..] {
let union = Grid1DUnion::try_new(&result, grid)?;
(result, _, _) = union.into_parts();
}
Ok(result)
}
§Error Variant Details
§DomainsMismatch
When it occurs: When attempting to create a union of grids with different domains.
Root cause: The mathematical requirement that unified grids must have identical domains.
Fields:
domain_grid_a
: The domain of the first input griddomain_grid_b
: The domain of the second input gridbacktrace
: Stack trace for debugging (when backtrace capture is enabled)
Common scenarios:
- Grids created for different physical regions
- Grids with different coordinate systems or units
- Programming errors where wrong grids are passed to union
- Floating-point precision issues in domain bounds
Resolution strategies:
- Domain trimming: Reduce both grids to their common intersection
- Domain extension: Extend one grid to match the other’s domain
- Coordinate transformation: Transform one grid to match the other’s coordinate system
- Input validation: Check domain compatibility before attempting union
§FromGrid1DConstructor
When it occurs: When the unified grid construction fails due to invalid coordinate sets.
Root cause: The merged coordinate set violates Grid1D
construction requirements.
Fields:
source
: The underlyingErrorsGrid1D
that caused the failure
Common scenarios:
- Merged coordinates create an invalid grid structure
- Numerical precision issues during coordinate merging
- Boundary coordinate mismatches after merging
- Memory allocation failures for large unified grids
Resolution strategies:
- Input validation: Verify individual grids before union
- Precision management: Use appropriate scalar types for coordinate precision
- Memory management: Ensure sufficient memory for large unions
- Graceful degradation: Fall back to simpler union strategies
§Performance Implications
§Error Construction Costs
- Domain comparison: O(1) for scalar bounds, O(k) for complex domains
- Error message formatting: Deferred until error is formatted (lazy evaluation)
- Backtrace capture: Significant overhead when enabled, zero when disabled
- Memory allocation: Minimal - errors store references and small data
§Error Handling Best Practices
use grid1d::{*, intervals::*, scalars::*};
// Efficient: Check domains before expensive operations
fn efficient_union<D>(
grid_a: &Grid1D<D>,
grid_b: &Grid1D<D>,
) -> Result<Grid1DUnion<D>, ErrorsGrid1DUnion<D>>
where
D: IntervalInPartitionBuilder + PartialEq + Clone,
{
// Fast domain check before expensive union
if grid_a.domain() != grid_b.domain() {
return Err(ErrorsGrid1DUnion::DomainsMismatch {
domain_grid_a: grid_a.domain().clone(),
domain_grid_b: grid_b.domain().clone(),
backtrace: std::backtrace::Backtrace::force_capture(),
});
}
Grid1DUnion::try_new(grid_a, grid_b)
}
// Memory-efficient: Use references where possible
fn analyze_union_error<D>(error: &ErrorsGrid1DUnion<D>) -> String
where
D: IntervalFinitePositiveLengthTrait,
{
match error {
ErrorsGrid1DUnion::DomainsMismatch { domain_grid_a, domain_grid_b, .. } => {
format!("Domain mismatch: {:?} ≠ {:?}", domain_grid_a, domain_grid_b)
}
ErrorsGrid1DUnion::FromGrid1DConstructor { source } => {
format!("Construction error: {}", source)
}
}
}
§Integration with the other numerical Ecosystem
§Error Propagation Patterns
use grid1d::{*, intervals::*, scalars::*};
// Pattern 1: Direct error propagation
fn create_multi_physics_union(
fluid_grid: &Grid1D<IntervalClosed<f64>>,
thermal_grid: &Grid1D<IntervalClosed<f64>>,
) -> Result<Grid1DUnion<IntervalClosed<f64>>, ErrorsGrid1DUnion<IntervalClosed<f64>>> {
Grid1DUnion::try_new(fluid_grid, thermal_grid)
}
// Pattern 2: Error transformation
fn create_union_with_context(
grid_a: &Grid1D<IntervalClosed<f64>>,
grid_b: &Grid1D<IntervalClosed<f64>>,
context: &str,
) -> Result<Grid1DUnion<IntervalClosed<f64>>, String> {
Grid1DUnion::try_new(grid_a, grid_b)
.map_err(|e| format!("Union failed in {}: {}", context, e))
}
// Pattern 3: Error aggregation
fn create_union_with_fallback(
primary_a: &Grid1D<IntervalClosed<f64>>,
primary_b: &Grid1D<IntervalClosed<f64>>,
fallback_a: &Grid1D<IntervalClosed<f64>>,
fallback_b: &Grid1D<IntervalClosed<f64>>,
) -> Result<Grid1DUnion<IntervalClosed<f64>>, Vec<ErrorsGrid1DUnion<IntervalClosed<f64>>>> {
let mut errors = Vec::new();
// Try primary union
match Grid1DUnion::try_new(primary_a, primary_b) {
Ok(union) => return Ok(union),
Err(e) => errors.push(e),
}
// Try fallback union
match Grid1DUnion::try_new(fallback_a, fallback_b) {
Ok(union) => Ok(union),
Err(e) => {
errors.push(e);
Err(errors)
}
}
}
§Mathematical Properties and Guarantees
§Error Correctness
∀ grids A, B: Grid1DUnion::try_new(A, B) fails ⟺
domain(A) ≠ domain(B) ∨ unified_coords_invalid
Errors occur if and only if there’s a genuine mathematical incompatibility.
§Error Determinism
∀ grids A, B:
Grid1DUnion::try_new(A, B) = Grid1DUnion::try_new(A, B) (same error or success)
Error conditions are deterministic and reproducible.
§Error Completeness
∀ error conditions: ∃ variant ∈ ErrorsGrid1DUnion that captures the condition
All meaningful failure modes are represented by error variants.
§See Also
Grid1DUnion
: The struct that uses this error typeErrorsGrid1D
: Related error type for general grid constructionGrid1D
: The fundamental grid type used in unionsIntervalPartition
: The trait providing partition operationsHasDomain1D
: Core trait for domain access and comparison- Error handling patterns in the module-level documentation
Variants§
Trait Implementations§
Source§impl<Domain1D: Debug + IntervalFinitePositiveLengthTrait> Debug for ErrorsGrid1DUnion<Domain1D>
impl<Domain1D: Debug + IntervalFinitePositiveLengthTrait> Debug for ErrorsGrid1DUnion<Domain1D>
Source§impl<Domain1D: IntervalFinitePositiveLengthTrait> Display for ErrorsGrid1DUnion<Domain1D>
impl<Domain1D: IntervalFinitePositiveLengthTrait> Display for ErrorsGrid1DUnion<Domain1D>
Source§impl<Domain1D: IntervalFinitePositiveLengthTrait> Error for ErrorsGrid1DUnion<Domain1D>
impl<Domain1D: IntervalFinitePositiveLengthTrait> Error for ErrorsGrid1DUnion<Domain1D>
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
Source§fn provide<'_request>(&'_request self, request: &mut Request<'_request>)
fn provide<'_request>(&'_request self, request: &mut Request<'_request>)
error_generic_member_access
)