use coulomb::pairwise::Yukawa;
use coulomb::permittivity::ConstantPermittivity;
use interatomic::twobody::*;
use interatomic::Cutoff;
fn main() {
let epsilon = 0.8; let sigma = 3.0; let lambda = 0.5; let cutoff = 100.0;
let lj = LennardJones::new(epsilon, sigma);
let ah = AshbaughHatch::new(lj, lambda, cutoff);
let charge_product = 1.0; let permittivity = ConstantPermittivity::new(80.0);
let debye_length = 50.0; let yukawa_scheme = Yukawa::new(cutoff, Some(debye_length));
let yukawa = IonIon::new(charge_product, permittivity, yukawa_scheme);
let combined = Combined::new(ah, yukawa);
let rsq_min = combined.lower_cutoff().powi(2);
let spline_uniform = SplinedPotential::with_cutoff(
&combined,
cutoff,
SplineConfig::default()
.with_rsq_min(rsq_min)
.with_grid_type(GridType::UniformRsq),
);
let spline_powerlaw = SplinedPotential::with_cutoff(
&combined,
cutoff,
SplineConfig::default()
.with_rsq_min(rsq_min)
.with_grid_type(GridType::PowerLaw2),
);
let spline_inversersq = SplinedPotential::with_cutoff(
&combined,
cutoff,
SplineConfig::default()
.with_rsq_min(rsq_min)
.with_grid_type(GridType::InverseRsq),
);
println!();
println!("╔══════════════════════════════════════════════════════════════════════════════╗");
println!("║ Grid Type Comparison for AshbaughHatch + Yukawa (n=2000 points) ║");
println!("╠══════════════════════════════════════════════════════════════════════════════╣");
println!(
"║ AshbaughHatch: ε={:.1} kJ/mol, σ={:.1} Å, λ={:.1}, cutoff={:.0} Å ║",
epsilon, sigma, lambda, cutoff
);
println!(
"║ Yukawa: z₁z₂={:.1}, εᵣ={:.0}, λD={:.0} Å ║",
charge_product, 80.0, debye_length
);
println!(
"║ r_min = {:.2} Å (from lower_cutoff) ║",
rsq_min.sqrt()
);
println!("╚══════════════════════════════════════════════════════════════════════════════╝");
println!();
println!("┌────────┬──────────────┬────────────────────────┬────────────────────────┬────────────────────────┐");
println!("│ r (Å) │ U_exact │ UniformRsq │ PowerLaw2 │ InverseRsq │");
println!("│ │ (kJ/mol) │ abs rel │ abs rel │ abs rel │");
println!("├────────┼──────────────┼────────────────────────┼────────────────────────┼────────────────────────┤");
let test_distances = [2.0, 3.0, 4.0, 5.0, 10.0, 20.0, 30.0, 50.0, 70.0, 90.0];
for r in test_distances {
let rsq = r * r;
let u_exact = combined.isotropic_twobody_energy(rsq);
let u_uniform = spline_uniform.isotropic_twobody_energy(rsq);
let u_powerlaw = spline_powerlaw.isotropic_twobody_energy(rsq);
let u_inversersq = spline_inversersq.isotropic_twobody_energy(rsq);
let abs_u = (u_uniform - u_exact).abs();
let abs_p = (u_powerlaw - u_exact).abs();
let abs_i = (u_inversersq - u_exact).abs();
let rel_u = abs_u / u_exact.abs();
let rel_p = abs_p / u_exact.abs();
let rel_i = abs_i / u_exact.abs();
println!(
"│ {:>6.1} │ {:>12.4e} │ {:>9.2e} {:>9.2e} │ {:>9.2e} {:>9.2e} │ {:>9.2e} {:>9.2e} │",
r, u_exact, abs_u, rel_u, abs_p, rel_p, abs_i, rel_i
);
}
println!("└────────┴──────────────┴────────────────────────┴────────────────────────┴────────────────────────┘");
println!();
println!(
"Legend: abs = absolute error, rel = relative error (|U_spline - U_exact| / |U_exact|)"
);
println!();
println!("Summary:");
println!(" - UniformRsq: Sparse at short range → large errors where potential is steep");
println!(" - PowerLaw2: Balanced sampling → consistent accuracy across all distances");
println!(" - InverseRsq: Dense at short range → excellent short-range, poor long-range");
println!();
}