ErrorsGrid1DUnion

Enum ErrorsGrid1DUnion 

Source
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

§Construction Errors

§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 grid
  • domain_grid_b: The domain of the second input grid
  • backtrace: 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:

  1. Domain trimming: Reduce both grids to their common intersection
  2. Domain extension: Extend one grid to match the other’s domain
  3. Coordinate transformation: Transform one grid to match the other’s coordinate system
  4. 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 underlying ErrorsGrid1D 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:

  1. Input validation: Verify individual grids before union
  2. Precision management: Use appropriate scalar types for coordinate precision
  3. Memory management: Ensure sufficient memory for large unions
  4. 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

Variants§

§

DomainsMismatch

Fields

§domain_grid_a: Domain1D
§domain_grid_b: Domain1D
§backtrace: Backtrace
§

FromGrid1DConstructor

Fields

§source: ErrorsGrid1D<Domain1D>

Trait Implementations§

Source§

impl<Domain1D: Debug + IntervalFinitePositiveLengthTrait> Debug for ErrorsGrid1DUnion<Domain1D>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<Domain1D: IntervalFinitePositiveLengthTrait> Display for ErrorsGrid1DUnion<Domain1D>

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<Domain1D: IntervalFinitePositiveLengthTrait> Error for ErrorsGrid1DUnion<Domain1D>
where ErrorsGrid1D<Domain1D>: Error + 'static, Self: Debug + Display,

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
Source§

fn provide<'_request>(&'_request self, request: &mut Request<'_request>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

impl<Domain1D: IntervalFinitePositiveLengthTrait> From<ErrorsGrid1D<Domain1D>> for ErrorsGrid1DUnion<Domain1D>

Source§

fn from(source: ErrorsGrid1D<Domain1D>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<Domain1D> !Freeze for ErrorsGrid1DUnion<Domain1D>

§

impl<Domain1D> RefUnwindSafe for ErrorsGrid1DUnion<Domain1D>
where Domain1D: RefUnwindSafe, <Domain1D as IntervalOperations>::RealType: RefUnwindSafe,

§

impl<Domain1D> Send for ErrorsGrid1DUnion<Domain1D>
where Domain1D: Send,

§

impl<Domain1D> Sync for ErrorsGrid1DUnion<Domain1D>
where Domain1D: Sync,

§

impl<Domain1D> Unpin for ErrorsGrid1DUnion<Domain1D>
where Domain1D: Unpin, <Domain1D as IntervalOperations>::RealType: Unpin,

§

impl<Domain1D> UnwindSafe for ErrorsGrid1DUnion<Domain1D>
where Domain1D: UnwindSafe, <Domain1D as IntervalOperations>::RealType: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.