← All examples Fractional differential equations replace the integer-order derivative
with a non-local Caputo operator D^α (for α ∈ (0, 1]). The
relaxation problem D^α y = -λ y, y(0) = 1 has a closed-form solution
in terms of the Mittag-Leffler function E_α(-λ t^α) — when α = 1
this reduces to ordinary exponential decay, and for α < 1 the
solution decays slower-than-exponentially with a heavy tail typical of
viscoelastic and anomalous-diffusion systems.
This example uses the L1 quadrature scheme and validates against the
exact Mittag-Leffler reference.
Run it:
cargo run --release --example fractional_relaxation numra/examples/fractional_relaxation.rs on GitHub ↗ · Related book chapter ↗
use numra_fde :: {mittag_leffler_1, FdeOptions , FdeSolver , FdeSystem , L1Solver };
/// Fractional relaxation system: D^α y = -λy
struct FractionalRelaxation {
lambda : f64 ,
alpha : f64 ,
}
impl FractionalRelaxation {
fn new (lambda : f64 , alpha : f64 ) -> Self {
Self { lambda, alpha }
}
/// Exact solution using Mittag-Leffler function
fn exact_solution ( & self , t : f64 ) -> f64 {
mittag_leffler_1 ( - self . lambda * t . powf ( self . alpha), self . alpha)
}
}
impl FdeSystem < f64 > for FractionalRelaxation {
fn dim ( & self ) -> usize {
1
}
fn alpha ( & self ) -> f64 {
self . alpha
}
fn rhs ( & self , _t : f64 , y : & [ f64 ], f : &mut [ f64 ]) {
f[ 0 ] = - self . lambda * y[ 0 ];
}
}
fn main () {
println! ( "=== Fractional Relaxation Example === \n " );
let lambda = 1.0 ;
let t_final = 3.0 ;
let y0 = [ 1.0 ];
// Compare different fractional orders
let alphas = [ 1.0 , 0.9 , 0.7 , 0.5 ];
println! ( "Fractional relaxation: D^α y = -{:.1} y, y(0) = 1" , lambda);
println! ( "Comparing orders α = {:?} \n " , alphas);
for alpha in alphas {
let system = FractionalRelaxation :: new (lambda, alpha);
let options = FdeOptions :: default () . dt ( 0.01 );
let result =
L1Solver :: solve ( & system, 0.0 , t_final, & y0, & options) . expect ( "FDE solve failed" );
// Get solution at specific time points
let check_times = [ 0.5 , 1.0 , 2.0 , 3.0 ];
println! ( "α = {:.1}:" , alpha);
println! ( " t \t Computed \t Exact \t\t Error" );
println! (
" {} \t {} \t {} \t {}" ,
"-" . repeat ( 4 ),
"-" . repeat ( 8 ),
"-" . repeat ( 8 ),
"-" . repeat ( 8 )
);
for & t_check in & check_times {
// Find closest index
let idx = (t_check / 0.01_ f64 ) . round () as usize ;
if idx < result . t . len () {
let y_computed = result . y_at (idx)[ 0 ];
let y_exact = system . exact_solution (t_check);
let error = (y_computed - y_exact) . abs ();
println! (
" {:.1} \t {:.6} \t {:.6} \t {:.2e}" ,
t_check, y_computed, y_exact, error
);
}
}
println! ();
}
// Demonstrate the "heavy tail" property
println! ( "=== Heavy Tail Behavior ===" );
println! ( "At t = 3.0, comparing decay rates: \n " );
for alpha in alphas {
let system = FractionalRelaxation :: new (lambda, alpha);
let y_alpha = system . exact_solution ( 3.0 );
let y_exp = ( - lambda * 3.0_ f64 ) . exp (); // Standard exponential
println! (
"α = {:.1}: y(3) = {:.6}, ratio to exp(-3) = {:.2}" ,
alpha,
y_alpha,
y_alpha / y_exp
);
}
println! ( " \n Smaller α = slower decay (longer memory)" );
println! ( "This models anomalous diffusion and viscoelastic relaxation." );
// Solver statistics
println! ( " \n === Solver Statistics (α = 0.5) ===" );
let system = FractionalRelaxation :: new (lambda, 0.5 );
let options = FdeOptions :: default () . dt ( 0.01 );
let result = L1Solver :: solve ( & system, 0.0 , t_final, & y0, & options) . unwrap ();
println! ( "Steps taken: {}" , result . stats . n_steps);
println! ( "RHS evaluations: {}" , result . stats . n_rhs);
println! ( "Final time: {:.2}" , result . t_final () . unwrap ());
println! ( "Final value: {:.6}" , result . y_final () . unwrap ()[ 0 ]);
}