use std::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::constants::KB;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MagnonThermalConductivity {
pub kappa_magnon: f64,
pub temperature: f64,
pub mean_free_path: f64,
}
impl Default for MagnonThermalConductivity {
fn default() -> Self {
Self {
kappa_magnon: 1.0, temperature: 300.0,
mean_free_path: 1.0e-6,
}
}
}
impl MagnonThermalConductivity {
#[inline]
pub fn conductivity_at_temperature(&self, temp: f64) -> f64 {
if temp < 1.0 {
return 0.0;
}
let t_ratio = temp / self.temperature;
if temp < 50.0 {
self.kappa_magnon * t_ratio.powi(2)
} else {
self.kappa_magnon * (1.0 - (-t_ratio).exp())
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ThermalMagnonTransport {
pub conductivity: MagnonThermalConductivity,
pub seebeck_coefficient: f64,
}
impl Default for ThermalMagnonTransport {
fn default() -> Self {
Self {
conductivity: MagnonThermalConductivity::default(),
seebeck_coefficient: 1.0e-6, }
}
}
impl ThermalMagnonTransport {
pub fn yig() -> Self {
Self {
conductivity: MagnonThermalConductivity {
kappa_magnon: 1.0,
temperature: 300.0,
mean_free_path: 10.0e-6, },
seebeck_coefficient: 1.0e-6,
}
}
#[inline]
pub fn heat_flux(&self, grad_t_magnitude: f64, temperature: f64) -> f64 {
let kappa = self.conductivity.conductivity_at_temperature(temperature);
kappa * grad_t_magnitude
}
#[inline]
pub fn magnon_chemical_potential(&self, grad_t_magnitude: f64) -> f64 {
self.seebeck_coefficient * grad_t_magnitude
}
#[inline]
pub fn thermal_magnon_accumulation(&self, grad_t_magnitude: f64, temperature: f64) -> f64 {
if temperature < 1.0 {
return 0.0;
}
let mu_m = self.magnon_chemical_potential(grad_t_magnitude);
mu_m / (KB * temperature)
}
}
impl fmt::Display for MagnonThermalConductivity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"MagnonThermalConductivity: κ={:.2} W/(m·K), T={:.0} K, λ={:.2} μm",
self.kappa_magnon,
self.temperature,
self.mean_free_path * 1e6
)
}
}
impl fmt::Display for ThermalMagnonTransport {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ThermalMagnonTransport: S={:.2e} V/K, {}",
self.seebeck_coefficient, self.conductivity
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_thermal_conductivity_temperature_dependence() {
let kappa = MagnonThermalConductivity::default();
let k_low = kappa.conductivity_at_temperature(10.0);
let k_mid = kappa.conductivity_at_temperature(100.0);
let k_high = kappa.conductivity_at_temperature(300.0);
assert!(k_low < k_mid);
assert!(k_mid < k_high);
}
#[test]
fn test_heat_flux_proportional_to_gradient() {
let transport = ThermalMagnonTransport::yig();
let q1 = transport.heat_flux(1000.0, 300.0);
let q2 = transport.heat_flux(2000.0, 300.0);
assert!((q2 / q1 - 2.0).abs() < 0.1);
}
#[test]
fn test_zero_gradient_zero_flux() {
let transport = ThermalMagnonTransport::default();
let q = transport.heat_flux(0.0, 300.0);
assert!(q.abs() < 1e-30);
}
#[test]
fn test_magnon_accumulation() {
let transport = ThermalMagnonTransport::yig();
let accumulation = transport.thermal_magnon_accumulation(1.0e6, 300.0);
assert!(accumulation > 0.0);
}
}