RustedSciThe 0.3.30

Rust framework for symbolic and numerical computing: symbolic calculations, nonlinear systems, IVP and BVP for ODE, optimization, fitting and more
Documentation
# Grid Refinement Algorithm Comparison: Fortran vs Rust

## Overview

Comparing the TWOPNT grid refinement algorithm from the original Fortran implementation with the Rust rewrite attempt.

## Key Differences Found

### 1. **Algorithm Structure**

**Fortran Original (`refine` subroutine)**:
- **Location**: Lines ~3800-4200 in `twopnt_core.f90`
- **Structure**: Single comprehensive subroutine with multiple phases
- **Error Handling**: Extensive validation with detailed error messages

**Rust Rewrite**:
- **Location**: `adaptive_grid_twopoint.rs`
- **Structure**: Object-oriented with `Grid` struct and methods
- **Error Handling**: Basic assertions and logging

### 2. **Mathematical Criteria**

**Fortran**:
```fortran
! Component significance test
if (.not. abs(range)>toler0*max(one,maxmag)) cycle active_components

! Gradient threshold (toler1 = 0.2)
if (toler1 * range<differ) vary1(k) = vary1(k) + 1

! Curvature threshold (toler2 = 0.2)  
if (toler2 * range < differ) vary2(k) = vary2(k) + 1
```

**Rust**:
```rust
// Component significance test
if !(range_y_j.abs() > abs_tol * f64::max(1.0, maxmag_j)) {
    continue;
}

// Gradient threshold (d = 0.2 equivalent)
if dy_i.abs() > delta {
    vary_y[i] += 1;
}

// Curvature threshold (g = 0.2 equivalent)
if differ_dy > gamma {
    vary_dy_dx[i] += 1;
}
```

### 3. **Critical Implementation Differences**

#### **Parameter Mapping**:
- **Fortran**: `toler0`, `toler1`, `toler2` (0.2 default)
- **Rust**: `abs_tol`, `d`, `g` (user-provided)

#### **Gradient Calculation**:
**Fortran**:
```fortran
pure real(RK) function grad(u,_x,comp,point)
    grad = (u(comp,point+1)-u(comp,point)) / (_x(point+1)-_x(point))
end function grad
```

**Rust**:
```rust
fn grad(&self, y_j: DVector<f64>, i: usize) -> f64 {
    let dy = y_j[i + 1] - y_j[i];
    let dx = x_vector[i + 1] - x_vector[i];
    dy / dx
}
```

#### **Curvature Analysis**:
**Fortran** (more sophisticated):
```fortran
! Calculate gradient at first point and store in right
right = temp
for i in 1..n-1 {
    left = right;
    right = list_dy_i[i];
    differ_dy = (right - left).abs();
    // Check against gamma threshold
}
```

**Rust** (simplified):
```rust
let temp = list_dy_i[0];
let right = temp;
for i in 1..n-1 {
    let left = right;
    let right = list_dy_i[i];
    let differ_dy = (right - left).abs();
    // Check against gamma threshold
}
```

### 4. **Weight Calculation**

**Fortran**:
```fortran
! Weight intervals based on violations
do k = 1, vars%points - 1
   weight(k) = vary1(k)
   if (1<k) weight(k) = weight(k) + vary2(k)
   if (k<vars%points - 1) weight(k) = weight(k) + vary2(k + 1)
   if (0<weight(k)) most = most + 1
end do
```

**Rust**:
```rust
for i in 0..self.n - 1 {
    weights[i] = vary_y[i];
    if i > 0 {
        weights[i] += vary_dy_dx[i]
    }
    if i < self.n - 1 {
        weights[i] += vary_dy_dx[i + 1]
    }
    if weights[i] > 0 {
        most += 1
    }
}
```

### 5. **Point Insertion Strategy**

**Fortran** (backward iteration):
```fortran
new_points: do old = vars%points, 2, -1
   ! Copy right boundary
   vars%_x(new) = vars%_x(old)
   u(:,new) = u(:,old)
   new = new - 1
   
   ! Interpolate if marked
   if (mark(old-1)) then
      vars%_x(new) = half*(vars%_x(old)+vars%_x(old-1))
      u(:,new) = half*(u(:,old)+u(:,old-1))
      new = new - 1
   end if
end do new_points
```

**Rust** (similar backward iteration):
```rust
for i_old in (1..n_former).rev() {
    new_grid[n_new - 1] = x[i_old];
    new_initial_guess.column_mut(n_new - 1).copy_from(&y.column(i_old));
    n_new -= 1;

    if mark[i_old - 1] {
        new_grid[n_new - 1] = 0.5 * (x[i_old] + x[i_old - 1]);
        let dy_i = y_min_1 + 0.5 * (y_i - y_min_1);
        new_initial_guess.column_mut(n_new - 1).copy_from(&dy_i);
        n_new -= 1;
    }
}
```

## Major Issues in Rust Implementation

### 1. **Missing Active Component Check**
- **Fortran**: Only processes `vars%active(j)` components
- **Rust**: Processes all components without filtering

### 2. **Incomplete Curvature Analysis**
- **Fortran**: Proper left/right gradient comparison
- **Rust**: Simplified implementation missing gradient range calculation

### 3. **Parameter Inconsistency**
- **Fortran**: Uses relative thresholds (fraction of range)
- **Rust**: Uses absolute thresholds (delta, gamma)

### 4. **Missing Degeneracy Checks**
- **Fortran**: Extensive validation for degenerate intervals
- **Rust**: Basic monotonicity check only

### 5. **Error Handling**
- **Fortran**: Comprehensive error reporting with specific failure modes
- **Rust**: Basic logging without detailed diagnostics

## Recommendations for Rust Implementation

1. **Add Active Component Filtering**:
```rust
if !self.active_components[j] { continue; }
```

2. **Fix Curvature Calculation**:
```rust
let derivative_range = grad_max - grad_min;
let gamma = derivative_range * self.g;
```

3. **Implement Relative Thresholds**:
```rust
let delta = self.d * range_y_j;  // Relative to component range
```

4. **Add Comprehensive Validation**:
```rust
// Check for degenerate intervals
// Validate monotonicity
// Check bounds consistency
```

5. **Improve Error Reporting**:
```rust
// Detailed error messages matching Fortran implementation
// Specific failure mode identification
```

## Conclusion

The Rust implementation captures the basic structure but misses several critical details from the Fortran original:
- Active component filtering
- Proper relative threshold calculation
- Complete curvature analysis
- Comprehensive error handling

The mathematical core is similar, but the implementation details significantly affect the algorithm's robustness and accuracy.