use std::fmt;
use crate::vector3::Vector3;
#[derive(Debug, Clone)]
pub struct SpinNernst {
pub name: String,
pub spin_nernst_angle: f64,
pub thermal_conductivity: f64,
pub electrical_conductivity: f64,
pub seebeck_coefficient: f64,
}
impl Default for SpinNernst {
fn default() -> Self {
Self::platinum()
}
}
impl SpinNernst {
pub fn platinum() -> Self {
Self {
name: "Pt".to_string(),
spin_nernst_angle: 0.01, thermal_conductivity: 71.6, electrical_conductivity: 9.43e6, seebeck_coefficient: -5.0e-6, }
}
pub fn tungsten() -> Self {
Self {
name: "W".to_string(),
spin_nernst_angle: 0.015, thermal_conductivity: 173.0,
electrical_conductivity: 1.79e7,
seebeck_coefficient: 4.5e-6,
}
}
pub fn tantalum() -> Self {
Self {
name: "Ta".to_string(),
spin_nernst_angle: 0.005, thermal_conductivity: 57.5,
electrical_conductivity: 7.41e6,
seebeck_coefficient: 4.0e-6,
}
}
pub fn bismuth() -> Self {
Self {
name: "Bi".to_string(),
spin_nernst_angle: 0.02, thermal_conductivity: 7.97,
electrical_conductivity: 7.7e5,
seebeck_coefficient: -72.0e-6, }
}
#[inline]
pub fn spin_current(&self, grad_t: Vector3<f64>, spin_direction: Vector3<f64>) -> Vector3<f64> {
grad_t.cross(&spin_direction) * self.spin_nernst_angle
}
#[inline]
pub fn heat_current(&self, grad_t: Vector3<f64>) -> Vector3<f64> {
grad_t * (-self.thermal_conductivity)
}
pub fn mott_relation_estimate(&self, spin_hall_angle: f64) -> f64 {
let e = 1.602e-19; spin_hall_angle * (self.seebeck_coefficient / e).abs()
}
pub fn thermal_spin_hall_conductivity(&self, temperature: f64) -> f64 {
self.spin_nernst_angle * self.thermal_conductivity / temperature
}
pub fn thermal_spin_injection_efficiency(&self) -> f64 {
self.spin_nernst_angle * self.thermal_conductivity / 100.0
}
pub fn is_suitable_for_thermal_spintronics(&self) -> bool {
self.spin_nernst_angle > 0.001 && self.thermal_conductivity > 10.0 }
pub fn with_spin_nernst_angle(mut self, angle: f64) -> Self {
self.spin_nernst_angle = angle;
self
}
pub fn with_thermal_conductivity(mut self, kappa: f64) -> Self {
self.thermal_conductivity = kappa;
self
}
}
impl fmt::Display for SpinNernst {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}: θ_SN={:.4}, κ={:.1} W/(m·K), S={:.2e} V/K",
self.name, self.spin_nernst_angle, self.thermal_conductivity, self.seebeck_coefficient
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_platinum() {
let pt = SpinNernst::platinum();
assert!(pt.spin_nernst_angle > 0.0);
assert!(pt.thermal_conductivity > 70.0);
assert!(pt.is_suitable_for_thermal_spintronics());
}
#[test]
fn test_tungsten() {
let pt = SpinNernst::platinum();
let w = SpinNernst::tungsten();
assert!(w.spin_nernst_angle > pt.spin_nernst_angle);
assert!(w.thermal_conductivity > 170.0);
}
#[test]
fn test_bismuth_strong_soc() {
let bi = SpinNernst::bismuth();
assert!(bi.spin_nernst_angle > 0.01);
assert!(bi.seebeck_coefficient.abs() > 50.0e-6);
}
#[test]
fn test_spin_current_perpendicularity() {
let pt = SpinNernst::platinum();
let grad_t = Vector3::new(1000.0, 0.0, 0.0); let spin_dir = Vector3::new(0.0, 0.0, 1.0);
let j_s = pt.spin_current(grad_t, spin_dir);
assert!(j_s.dot(&grad_t).abs() < 1e-10);
assert!(j_s.dot(&spin_dir).abs() < 1e-10);
assert!(j_s.y.abs() > 0.0);
assert!(j_s.x.abs() < 1e-10);
assert!(j_s.z.abs() < 1e-10);
}
#[test]
fn test_spin_current_magnitude() {
let pt = SpinNernst::platinum();
let grad_t = Vector3::new(1.0e6, 0.0, 0.0); let spin_dir = Vector3::new(0.0, 0.0, 1.0);
let j_s = pt.spin_current(grad_t, spin_dir);
let expected_magnitude = pt.spin_nernst_angle * 1.0e6;
assert!((j_s.magnitude() - expected_magnitude).abs() < 1.0);
}
#[test]
fn test_heat_current() {
let pt = SpinNernst::platinum();
let grad_t = Vector3::new(100.0, 0.0, 0.0);
let j_q = pt.heat_current(grad_t);
let expected = -pt.thermal_conductivity * 100.0;
assert!((j_q.x - expected).abs() < 0.1);
}
#[test]
fn test_mott_relation() {
let pt = SpinNernst::platinum();
let theta_sh = 0.07;
let theta_sn_estimate = pt.mott_relation_estimate(theta_sh);
assert!(theta_sn_estimate > 0.0);
assert!(theta_sn_estimate.is_finite());
}
#[test]
fn test_thermal_spin_hall_conductivity() {
let pt = SpinNernst::platinum();
let temp = 300.0;
let sigma_sn = pt.thermal_spin_hall_conductivity(temp);
assert!(sigma_sn > 0.0);
assert!(sigma_sn < 10.0);
}
#[test]
fn test_thermal_spin_injection_efficiency() {
let pt = SpinNernst::platinum();
let w = SpinNernst::tungsten();
let bi = SpinNernst::bismuth();
let eff_pt = pt.thermal_spin_injection_efficiency();
let eff_w = w.thermal_spin_injection_efficiency();
let eff_bi = bi.thermal_spin_injection_efficiency();
assert!(eff_pt > 0.0);
assert!(eff_w > 0.0);
assert!(eff_bi > 0.0);
assert!(eff_w > eff_pt);
}
#[test]
fn test_thermal_spintronics_suitability() {
let strong = SpinNernst::tungsten();
let weak = SpinNernst::platinum().with_spin_nernst_angle(0.0001);
assert!(strong.is_suitable_for_thermal_spintronics());
assert!(!weak.is_suitable_for_thermal_spintronics());
}
#[test]
fn test_builder_pattern() {
let custom = SpinNernst::platinum()
.with_spin_nernst_angle(0.05)
.with_thermal_conductivity(100.0);
assert_eq!(custom.spin_nernst_angle, 0.05);
assert_eq!(custom.thermal_conductivity, 100.0);
}
}