use std::fmt;
use crate::constants::HBAR;
use crate::vector3::Vector3;
#[derive(Debug, Clone)]
pub struct RashbaSystem {
pub name: String,
pub alpha_r: f64,
pub fermi_energy: f64,
pub effective_mass: f64,
pub carrier_density: f64,
pub surface_normal: Vector3<f64>,
}
impl Default for RashbaSystem {
fn default() -> Self {
Self::ag_bi()
}
}
impl RashbaSystem {
pub fn ag_bi() -> Self {
Self {
name: "Ag/Bi".to_string(),
alpha_r: 3.05, fermi_energy: 0.1,
effective_mass: 0.15,
carrier_density: 5.0e17, surface_normal: Vector3::new(0.0, 0.0, 1.0),
}
}
pub fn au_111() -> Self {
Self {
name: "Au(111)".to_string(),
alpha_r: 0.33, fermi_energy: 0.4,
effective_mass: 0.25,
carrier_density: 1.0e18,
surface_normal: Vector3::new(0.0, 0.0, 1.0),
}
}
pub fn bitei() -> Self {
Self {
name: "BiTeI".to_string(),
alpha_r: 3.8, fermi_energy: 0.05,
effective_mass: 0.15,
carrier_density: 3.0e17,
surface_normal: Vector3::new(0.0, 0.0, 1.0),
}
}
pub fn gaas_2deg(gate_voltage: f64) -> Self {
let alpha_r = 0.07 * (1.0 + gate_voltage / 1.0);
Self {
name: format!("GaAs/AlGaAs (V_g = {:.2} V)", gate_voltage),
alpha_r,
fermi_energy: 0.02,
effective_mass: 0.067,
carrier_density: 1.0e16,
surface_normal: Vector3::new(0.0, 0.0, 1.0),
}
}
pub fn lao_sto() -> Self {
Self {
name: "LaAlO₃/SrTiO₃".to_string(),
alpha_r: 0.1, fermi_energy: 0.03,
effective_mass: 1.0, carrier_density: 5.0e16,
surface_normal: Vector3::new(0.0, 0.0, 1.0),
}
}
pub fn spin_splitting(&self, k_momentum: Vector3<f64>) -> f64 {
let k_inplane = k_momentum - self.surface_normal * k_momentum.dot(&self.surface_normal);
2.0 * self.alpha_r * k_inplane.magnitude()
}
#[inline]
pub fn spin_texture(&self, k_momentum: Vector3<f64>) -> Vector3<f64> {
let k_inplane = k_momentum - self.surface_normal * k_momentum.dot(&self.surface_normal);
self.surface_normal.cross(&k_inplane).normalize()
}
#[inline]
pub fn edelstein_spin_density(
&self,
current_density: f64,
current_direction: Vector3<f64>,
) -> Vector3<f64> {
let lambda_e = self.alpha_r / (2.0 * self.fermi_energy); let lambda_e_si = lambda_e * 1e-10;
let spin_direction = self.surface_normal.cross(¤t_direction.normalize());
spin_direction * (lambda_e_si * current_density)
}
#[inline]
pub fn inverse_edelstein_current(&self, spin_density: Vector3<f64>) -> Vector3<f64> {
let e = 1.602e-19; let alpha_r_si = self.alpha_r * 1.602e-19 * 1e-10;
let current_direction = self.surface_normal.cross(&spin_density);
current_direction * (2.0 * e / HBAR * alpha_r_si)
}
pub fn fermi_momentum(&self) -> f64 {
let k_f_si = (2.0 * std::f64::consts::PI * self.carrier_density).sqrt(); k_f_si * 1e-10 }
pub fn spin_precession_length(&self) -> f64 {
let m_e = 9.109e-31; let m_eff = self.effective_mass * m_e;
let alpha_r_si = self.alpha_r * 1.602e-19 * 1e-10;
let l_so = std::f64::consts::PI * HBAR * HBAR / (m_eff * alpha_r_si);
l_so * 1e9 }
pub fn is_suitable_for_spintronics(&self) -> bool {
self.alpha_r > 0.1 && self.fermi_energy > 0.01 }
pub fn with_alpha_r(mut self, alpha_r: f64) -> Self {
self.alpha_r = alpha_r;
self
}
pub fn with_carrier_density(mut self, density: f64) -> Self {
self.carrier_density = density;
self
}
}
impl fmt::Display for RashbaSystem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}: α_R={:.2} eV·Å, E_F={:.2} eV, m*={:.2} m_e",
self.name, self.alpha_r, self.fermi_energy, self.effective_mass
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ag_bi() {
let rashba = RashbaSystem::ag_bi();
assert!(rashba.alpha_r > 3.0);
assert!(rashba.is_suitable_for_spintronics());
}
#[test]
fn test_au_111() {
let rashba = RashbaSystem::au_111();
assert!(rashba.alpha_r > 0.3);
assert!(rashba.alpha_r < 0.4);
}
#[test]
fn test_bitei() {
let bitei = RashbaSystem::bitei();
assert!(bitei.alpha_r > 3.5); assert!(bitei.is_suitable_for_spintronics());
}
#[test]
fn test_gaas_gate_tuning() {
let gaas_0v = RashbaSystem::gaas_2deg(0.0);
let gaas_1v = RashbaSystem::gaas_2deg(1.0);
assert!(gaas_1v.alpha_r > gaas_0v.alpha_r);
}
#[test]
fn test_spin_splitting() {
let rashba = RashbaSystem::ag_bi();
let k = Vector3::new(0.1, 0.0, 0.0);
let splitting = rashba.spin_splitting(k);
assert!((splitting - 2.0 * rashba.alpha_r * 0.1).abs() < 1e-6);
}
#[test]
fn test_spin_texture_perpendicularity() {
let rashba = RashbaSystem::au_111();
let k = Vector3::new(1.0, 0.0, 0.0);
let spin = rashba.spin_texture(k);
assert!(spin.dot(&k).abs() < 1e-10);
assert!((spin.magnitude() - 1.0).abs() < 1e-10);
assert!(spin.y.abs() > 0.9);
}
#[test]
fn test_edelstein_effect() {
let rashba = RashbaSystem::ag_bi();
let j_c = 1.0e10; let j_dir = Vector3::new(1.0, 0.0, 0.0);
let spin_density = rashba.edelstein_spin_density(j_c, j_dir);
assert!(spin_density.magnitude() > 0.0);
assert!(spin_density.dot(&j_dir).abs() < 1e-10);
}
#[test]
fn test_inverse_edelstein() {
let rashba = RashbaSystem::bitei();
let spin_dens = Vector3::new(0.0, 1.0e10, 0.0);
let current = rashba.inverse_edelstein_current(spin_dens);
assert!(current.magnitude() > 0.0);
assert!(current.dot(&spin_dens).abs() < 1e-5);
}
#[test]
fn test_fermi_momentum() {
let rashba = RashbaSystem::au_111();
let k_f = rashba.fermi_momentum();
assert!(k_f > 0.0);
assert!(k_f > 0.01);
assert!(k_f < 1.0);
}
#[test]
fn test_spin_precession_length() {
let rashba = RashbaSystem::gaas_2deg(1.0);
let l_so = rashba.spin_precession_length();
assert!(l_so > 1.0); assert!(l_so < 1000.0);
}
#[test]
fn test_spintronics_suitability() {
let strong = RashbaSystem::ag_bi();
let weak = RashbaSystem::au_111().with_alpha_r(0.01);
assert!(strong.is_suitable_for_spintronics());
assert!(!weak.is_suitable_for_spintronics());
}
#[test]
fn test_builder_pattern() {
let custom = RashbaSystem::ag_bi()
.with_alpha_r(5.0)
.with_carrier_density(1.0e18);
assert_eq!(custom.alpha_r, 5.0);
assert_eq!(custom.carrier_density, 1.0e18);
}
}