#![allow(dead_code)]
use std::f64::consts::PI;
const HBAR_SI: f64 = 1.054_571_817e-34;
const M_ELECTRON: f64 = 9.109_383_7e-31;
const K_B: f64 = 1.380_649e-23;
const E_CHARGE: f64 = 1.602_176_634e-19;
const EPS_0: f64 = 8.854_187_8e-12;
const C_LIGHT: f64 = 2.997_924_58e8;
#[allow(dead_code)]
pub fn hall_petch_strength(sigma_0: f64, k_hp: f64, d: f64) -> f64 {
sigma_0 + k_hp / d.sqrt()
}
#[allow(dead_code)]
pub fn surface_to_volume_ratio(d: f64, shape: &str) -> f64 {
match shape {
"sphere" => 6.0 / d,
"cube" => 6.0 / d,
"rod_aspect10" => {
4.0 * 10.5 / (10.0 * d)
}
_ => 6.0 / d,
}
}
#[allow(dead_code)]
pub fn quantum_confinement_energy(d: f64, m_eff: f64, hbar: f64) -> f64 {
let n = 1.0_f64;
(n * PI * hbar).powi(2) / (2.0 * m_eff * d.powi(2))
}
#[allow(dead_code)]
pub fn carbon_nanotube_stiffness(chirality_n: usize, chirality_m: usize) -> f64 {
if chirality_n == chirality_m {
1.0e12 } else if chirality_m == 0 {
0.97e12 } else {
let theta = (chirality_m as f64 / (2.0 * chirality_n as f64 + chirality_m as f64))
.asin()
.abs();
let theta_max = PI / 6.0; let t = (theta / theta_max).min(1.0);
0.97e12 + t * (1.0e12 - 0.97e12)
}
}
#[allow(dead_code)]
pub fn nanoparticle_melting_point(bulk_tm: f64, d: f64, k_const: f64) -> f64 {
bulk_tm * (1.0 - k_const / d)
}
#[allow(dead_code)]
pub fn hamaker_van_der_waals(a1: f64, _a2: f64, d: f64) -> f64 {
let a_hamaker = 1.0e-19;
a_hamaker * a1 / (6.0 * d * d)
}
#[allow(dead_code)]
pub fn debye_length_nanoparticle(_zeta: f64, c_salt: f64, temperature: f64) -> f64 {
let eps_r = 80.0;
let n_a = 6.022_140_76e23;
let e = E_CHARGE;
let numerator = EPS_0 * eps_r * K_B * temperature;
let denominator = 2.0 * n_a * e * e * c_salt;
(numerator / denominator).sqrt()
}
#[allow(dead_code)]
pub fn nanofluid_viscosity(mu_f: f64, phi: f64) -> f64 {
mu_f * (1.0 + 2.5 * phi)
}
#[allow(dead_code)]
pub fn nanofluid_thermal_conductivity(k_f: f64, k_p: f64, phi: f64) -> f64 {
let num = k_p + 2.0 * k_f + 2.0 * phi * (k_p - k_f);
let den = k_p + 2.0 * k_f - phi * (k_p - k_f);
k_f * num / den
}
#[allow(dead_code)]
pub fn graphene_young_modulus() -> f64 {
1.0e12
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct QuantumDot {
pub diameter_nm: f64,
pub material: String,
pub bandgap_ev: f64,
}
impl QuantumDot {
pub fn new(d_nm: f64, material: impl Into<String>, bg_bulk: f64) -> Self {
Self {
diameter_nm: d_nm,
material: material.into(),
bandgap_ev: bg_bulk,
}
}
pub fn confinement_energy_ev(&self) -> f64 {
let d_m = self.diameter_nm * 1.0e-9;
let e_j = quantum_confinement_energy(d_m, M_ELECTRON, HBAR_SI);
e_j / E_CHARGE
}
fn emission_energy_ev(&self) -> f64 {
self.bandgap_ev + self.confinement_energy_ev()
}
pub fn emission_wavelength_nm(&self) -> f64 {
let h = 2.0 * PI * HBAR_SI;
let e_j = self.emission_energy_ev() * E_CHARGE;
h * C_LIGHT / e_j * 1.0e9
}
pub fn size_from_wavelength(wl_nm: f64, bg_bulk: f64) -> f64 {
let h = 2.0 * PI * HBAR_SI;
let e_total_j = h * C_LIGHT / (wl_nm * 1.0e-9);
let e_conf_j = e_total_j - bg_bulk * E_CHARGE;
if e_conf_j <= 0.0 {
return f64::NAN;
}
let d_m = PI * HBAR_SI / (2.0 * M_ELECTRON * e_conf_j).sqrt();
d_m * 1.0e9
}
}
#[cfg(test)]
mod tests {
use super::*;
const EPS: f64 = 1e-10;
#[test]
fn test_hall_petch_positive() {
let s = hall_petch_strength(200e6, 0.5e6, 10e-9);
assert!(s > 0.0, "Hall-Petch strength must be positive");
}
#[test]
fn test_hall_petch_increases_smaller_d() {
let s_large = hall_petch_strength(200e6, 0.5e6, 100e-9);
let s_small = hall_petch_strength(200e6, 0.5e6, 10e-9);
assert!(s_small > s_large, "Smaller grain → higher HP strength");
}
#[test]
fn test_hall_petch_zero_k_equals_sigma0() {
let s = hall_petch_strength(300e6, 0.0, 50e-9);
assert!((s - 300e6).abs() < EPS);
}
#[test]
fn test_hall_petch_formula() {
let sigma_0 = 200e6_f64;
let k = 1e6_f64;
let d = 4e-9_f64;
let expected = sigma_0 + k / d.sqrt();
let got = hall_petch_strength(sigma_0, k, d);
assert!((got - expected).abs() < 1.0);
}
#[test]
fn test_svr_sphere_formula() {
let svr = surface_to_volume_ratio(10e-9, "sphere");
let expected = 6.0 / 10e-9;
assert!((svr - expected).abs() < EPS);
}
#[test]
fn test_svr_cube_equals_sphere() {
let s = surface_to_volume_ratio(10e-9, "sphere");
let c = surface_to_volume_ratio(10e-9, "cube");
assert!((s - c).abs() < EPS);
}
#[test]
fn test_svr_increases_with_smaller_d() {
let svr_big = surface_to_volume_ratio(100e-9, "sphere");
let svr_small = surface_to_volume_ratio(10e-9, "sphere");
assert!(svr_small > svr_big, "Smaller particle → larger S/V");
}
#[test]
fn test_svr_rod_positive() {
let svr = surface_to_volume_ratio(10e-9, "rod_aspect10");
assert!(svr > 0.0);
}
#[test]
fn test_svr_rod_higher_than_sphere() {
let rod = surface_to_volume_ratio(10e-9, "rod_aspect10");
let sphere = surface_to_volume_ratio(10e-9, "sphere");
assert!(rod > 0.0 && rod.is_finite());
let _ = sphere;
}
#[test]
fn test_svr_unknown_shape_fallback() {
let svr = surface_to_volume_ratio(10e-9, "unknown");
let expected = 6.0 / 10e-9;
assert!((svr - expected).abs() < EPS);
}
#[test]
fn test_qce_positive() {
let e = quantum_confinement_energy(5e-9, M_ELECTRON, HBAR_SI);
assert!(e > 0.0, "Confinement energy must be positive");
}
#[test]
fn test_qce_increases_smaller_dot() {
let e_large = quantum_confinement_energy(10e-9, M_ELECTRON, HBAR_SI);
let e_small = quantum_confinement_energy(5e-9, M_ELECTRON, HBAR_SI);
assert!(e_small > e_large, "Smaller dot → larger confinement energy");
}
#[test]
fn test_qce_formula() {
let d = 5e-9_f64;
let expected = (PI * HBAR_SI).powi(2) / (2.0 * M_ELECTRON * d.powi(2));
let got = quantum_confinement_energy(d, M_ELECTRON, HBAR_SI);
assert!((got - expected).abs() / expected < 1e-12);
}
#[test]
fn test_cnt_armchair_stiffness() {
let e = carbon_nanotube_stiffness(10, 10);
assert!((e - 1.0e12).abs() < 1.0, "Armchair CNT should be ~1 TPa");
}
#[test]
fn test_cnt_zigzag_stiffness() {
let e = carbon_nanotube_stiffness(10, 0);
assert!((e - 0.97e12).abs() < 1.0, "Zigzag CNT should be ~0.97 TPa");
}
#[test]
fn test_cnt_chiral_stiffness_between_bounds() {
let e = carbon_nanotube_stiffness(10, 5);
assert!(
(0.97e12..=1.0e12).contains(&e),
"Chiral CNT stiffness should be between zigzag and armchair"
);
}
#[test]
fn test_cnt_stiffness_positive() {
assert!(carbon_nanotube_stiffness(8, 4) > 0.0);
}
#[test]
fn test_melting_point_depression() {
let tm_bulk = 1337.0; let tm_nano = nanoparticle_melting_point(tm_bulk, 5e-9, 1e-9);
assert!(
tm_nano < tm_bulk,
"Nanoparticle melting point should be depressed"
);
}
#[test]
fn test_melting_point_positive() {
let tm = nanoparticle_melting_point(1337.0, 5e-9, 0.5e-9);
assert!(tm > 0.0);
}
#[test]
fn test_melting_point_larger_particle_closer_to_bulk() {
let tm_small = nanoparticle_melting_point(1337.0, 2e-9, 0.5e-9);
let tm_large = nanoparticle_melting_point(1337.0, 20e-9, 0.5e-9);
assert!(tm_large > tm_small, "Larger nanoparticle closer to bulk Tm");
}
#[test]
fn test_hamaker_positive() {
let f = hamaker_van_der_waals(10e-9, 10e-9, 1e-9);
assert!(f > 0.0, "vdW force must be positive");
}
#[test]
fn test_hamaker_increases_smaller_separation() {
let f_far = hamaker_van_der_waals(10e-9, 10e-9, 5e-9);
let f_near = hamaker_van_der_waals(10e-9, 10e-9, 1e-9);
assert!(f_near > f_far, "vdW force increases at smaller separation");
}
#[test]
fn test_debye_length_positive() {
let ld = debye_length_nanoparticle(0.025, 1.0, 298.0);
assert!(ld > 0.0, "Debye length must be positive");
}
#[test]
fn test_debye_length_decreases_with_salt() {
let ld_low = debye_length_nanoparticle(0.025, 1.0, 298.0);
let ld_high = debye_length_nanoparticle(0.025, 100.0, 298.0);
assert!(ld_low > ld_high, "Higher salt → shorter Debye length");
}
#[test]
fn test_nanofluid_viscosity_greater_than_base() {
let mu = nanofluid_viscosity(1e-3, 0.02);
assert!(mu > 1e-3, "Nanofluid viscosity must exceed base fluid");
}
#[test]
fn test_nanofluid_viscosity_zero_phi_equals_base() {
let mu = nanofluid_viscosity(1e-3, 0.0);
assert!((mu - 1e-3).abs() < EPS);
}
#[test]
fn test_nanofluid_viscosity_increases_with_phi() {
let mu1 = nanofluid_viscosity(1e-3, 0.01);
let mu2 = nanofluid_viscosity(1e-3, 0.05);
assert!(mu2 > mu1);
}
#[test]
fn test_nanofluid_viscosity_einstein_formula() {
let mu_f = 1e-3;
let phi = 0.03;
let expected = mu_f * (1.0 + 2.5 * phi);
let got = nanofluid_viscosity(mu_f, phi);
assert!((got - expected).abs() < EPS);
}
#[test]
fn test_nanofluid_tc_greater_than_base_when_kp_gt_kf() {
let k = nanofluid_thermal_conductivity(0.6, 40.0, 0.03);
assert!(k > 0.6, "k_eff > k_f when k_p > k_f");
}
#[test]
fn test_nanofluid_tc_zero_phi_equals_base() {
let k = nanofluid_thermal_conductivity(0.6, 40.0, 0.0);
assert!((k - 0.6).abs() < 1e-9);
}
#[test]
fn test_nanofluid_tc_increases_with_phi() {
let k1 = nanofluid_thermal_conductivity(0.6, 40.0, 0.01);
let k2 = nanofluid_thermal_conductivity(0.6, 40.0, 0.05);
assert!(k2 > k1);
}
#[test]
fn test_nanofluid_tc_positive() {
let k = nanofluid_thermal_conductivity(0.6, 40.0, 0.02);
assert!(k > 0.0);
}
#[test]
fn test_graphene_young_modulus_1tpa() {
let e = graphene_young_modulus();
assert!(
(e - 1.0e12).abs() < 1.0,
"Graphene Young's modulus should be 1 TPa"
);
}
#[test]
fn test_quantum_dot_new_fields() {
let qd = QuantumDot::new(3.0, "CdSe", 1.74);
assert!((qd.diameter_nm - 3.0).abs() < EPS);
assert_eq!(qd.material, "CdSe");
assert!((qd.bandgap_ev - 1.74).abs() < EPS);
}
#[test]
fn test_quantum_dot_confinement_energy_positive() {
let qd = QuantumDot::new(3.0, "CdSe", 1.74);
assert!(
qd.confinement_energy_ev() > 0.0,
"Confinement energy must be positive"
);
}
#[test]
fn test_quantum_dot_smaller_dot_higher_confinement() {
let qd_large = QuantumDot::new(6.0, "CdSe", 1.74);
let qd_small = QuantumDot::new(3.0, "CdSe", 1.74);
assert!(qd_small.confinement_energy_ev() > qd_large.confinement_energy_ev());
}
#[test]
fn test_quantum_dot_emission_wavelength_positive() {
let qd = QuantumDot::new(4.0, "CdSe", 1.74);
assert!(qd.emission_wavelength_nm() > 0.0);
}
#[test]
fn test_quantum_dot_smaller_dot_shorter_wavelength() {
let qd_large = QuantumDot::new(6.0, "CdSe", 1.74);
let qd_small = QuantumDot::new(3.0, "CdSe", 1.74);
assert!(
qd_small.emission_wavelength_nm() < qd_large.emission_wavelength_nm(),
"Smaller QD → blue-shifted emission"
);
}
#[test]
fn test_quantum_dot_size_from_wavelength_positive() {
let d = QuantumDot::size_from_wavelength(500.0, 1.74);
assert!(
d > 0.0 && d.is_finite(),
"QD diameter from wavelength must be positive"
);
}
#[test]
fn test_quantum_dot_size_roundtrip() {
let qd = QuantumDot::new(4.0, "CdSe", 1.74);
let wl = qd.emission_wavelength_nm();
let d_recovered = QuantumDot::size_from_wavelength(wl, 1.74);
assert!(
(d_recovered - 4.0).abs() / 4.0 < 0.01,
"Roundtrip QD size: expected ~4 nm, got {d_recovered:.3} nm"
);
}
#[test]
fn test_quantum_dot_wavelength_finite() {
let qd = QuantumDot::new(5.0, "InP", 1.27);
assert!(qd.emission_wavelength_nm().is_finite());
}
}