spintronics 0.3.0

Pure Rust library for simulating spin dynamics, spin current generation, and conversion phenomena in magnetic and topological materials
Documentation
//! Inverse Spin Hall Effect (ISHE)
//!
//! The inverse spin Hall effect converts a spin current into a transverse charge current
//! (or equivalently, generates an electric field) via spin-orbit coupling.
//!
//! # Mathematical Formulation
//!
//! The electric field generated by ISHE is:
//!
//! $$
//! \mathbf{E}_{\text{ISHE}} = \rho \, \theta_{\text{SH}} \left(\mathbf{j}_s \times \boldsymbol{\sigma}\right)
//! $$
//!
//! where:
//! - $\mathbf{E}_{\text{ISHE}}$ is the generated electric field (V/m)
//! - $\rho$ is the resistivity of the material (Ω·m)
//! - $\theta_{\text{SH}}$ is the spin Hall angle (dimensionless)
//! - $\mathbf{j}_s$ is the spatial flow direction of spin current
//! - $\boldsymbol{\sigma}$ is the spin polarization direction
//!
//! The measured voltage across a strip of width $w$ is:
//!
//! $$
//! V_{\text{ISHE}} = w \, \rho \, \theta_{\text{SH}} |\mathbf{j}_s \times \boldsymbol{\sigma}|
//! $$
//!
//! # Spin Hall Angles
//!
//! Typical values for common materials:
//! - Platinum (Pt): $\theta_{\text{SH}} \approx 0.07$ to $0.12$
//! - Tantalum (Ta): $\theta_{\text{SH}} \approx 0.12$ to $0.15$
//! - Tungsten (W): $\theta_{\text{SH}} \approx -0.3$ (negative polarity)
//! - Topological insulators: $\theta_{\text{SH}}$ can exceed 1 (surface states)
//!
//! # Physical Mechanism
//!
//! In heavy metals with strong spin-orbit coupling, a flowing spin current
//! experiences a transverse force that deflects opposite spins in opposite
//! directions, creating a charge accumulation and electric field perpendicular
//! to both the spin flow and polarization directions.
//!
//! # References
//!
//! - E. Saitoh et al., "Conversion of spin current into charge current at room
//!   temperature: Inverse spin-Hall effect", Appl. Phys. Lett. 88, 182509 (2006)
//! - T. Kimura et al., "Room-Temperature Reversible Spin Hall Effect",
//!   Phys. Rev. Lett. 98, 156601 (2007)
//! - J. Sinova et al., "Spin Hall effects", Rev. Mod. Phys. 87, 1213 (2015)

use std::fmt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::vector3::Vector3;

/// Inverse Spin Hall Effect converter
///
/// Converts spin current into electric field via spin-orbit coupling
///
/// # Example
/// ```
/// use spintronics::effect::ishe::InverseSpinHall;
/// use spintronics::Vector3;
///
/// // Platinum detector
/// let pt = InverseSpinHall::platinum();
///
/// // Spin current flowing in z-direction
/// let js_flow = Vector3::new(0.0, 0.0, 1.0);
/// // Spin polarization in x-direction
/// let js_pol = Vector3::new(1.0e8, 0.0, 0.0); // \[A/m²\]
///
/// // Convert spin current to electric field
/// let e_field = pt.convert(js_flow, js_pol);
///
/// // Electric field should be in y-direction (z × x = y)
/// assert!(e_field.y.abs() > 0.0);
/// ```
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct InverseSpinHall {
    /// Spin Hall angle (dimensionless)
    ///
    /// This parameter determines the conversion efficiency from spin current
    /// to charge current. Typical values:
    /// - Pt: 0.07-0.12
    /// - Ta: 0.12-0.15
    /// - W: -0.3 (negative sign indicates opposite polarity)
    /// - Topological insulators: can be >1 due to surface states
    pub theta_sh: f64,

    /// Resistivity [Ω·m]
    ///
    /// Electrical resistivity of the normal metal
    /// Pt: ~2.0e-7, Ta: ~1.8e-7, W: ~5.0e-8
    pub rho: f64,
}

impl Default for InverseSpinHall {
    fn default() -> Self {
        Self {
            theta_sh: 0.08, // Typical for Pt
            rho: 2.0e-7,    // Pt resistivity
        }
    }
}

impl InverseSpinHall {
    /// Create ISHE properties for Platinum
    pub fn platinum() -> Self {
        Self {
            theta_sh: 0.08,
            rho: 2.0e-7,
        }
    }

    /// Create ISHE properties for Tantalum
    pub fn tantalum() -> Self {
        Self {
            theta_sh: 0.12,
            rho: 1.8e-7,
        }
    }

    /// Create ISHE properties for Tungsten
    pub fn tungsten() -> Self {
        Self {
            theta_sh: -0.3,
            rho: 5.0e-8,
        }
    }

    /// Calculate the generated electric field from ISHE
    ///
    /// # Arguments
    /// * `js_flow` - Direction of spin current flow (spatial propagation direction)
    /// * `js_polarization` - Direction of spin polarization (magnitude is current density)
    ///
    /// # Returns
    /// Electric field vector [V/m]
    ///
    /// # Physical Interpretation
    /// When a spin current with polarization σ flows in direction j, spin-orbit
    /// coupling causes the spins to deflect charge carriers transversely,
    /// generating an electric field perpendicular to both j and σ.
    ///
    /// # Convention
    /// Following Saitoh Lab's convention:
    /// E = ρ * θ_SH * (j × σ)
    #[inline]
    pub fn convert(&self, js_flow: Vector3<f64>, js_polarization: Vector3<f64>) -> Vector3<f64> {
        // Cross product: j × σ
        // Physical meaning: The ISHE electric field is perpendicular to BOTH the
        // spin current flow direction (j) and the spin polarization (σ). This is
        // a consequence of spin-orbit coupling in heavy metals: when spin-polarized
        // electrons flow, they experience a transverse force (like the Hall effect,
        // but for spins). The cross product captures this three-way orthogonal geometry:
        //   - j: direction spin current propagates (e.g., z: into Pt layer)
        //   - σ: direction of electron spin (e.g., x: set by ferromagnet)
        //   - E: resulting electric field (e.g., y: measurable voltage)
        let cross = js_flow.cross(&js_polarization);

        // E_ISHE = ρ θ_SH (j × σ) [V/m]
        // Physical meaning of each factor:
        //   - ρ (resistivity): Converts current density to electric field (Ohm's law)
        //   - θ_SH (spin Hall angle): Conversion efficiency from spin to charge current
        //     Typical: Pt ~8%, Ta ~12%, W ~30% (negative means opposite polarity)
        //   - (j × σ): Geometric factor ensuring E ⊥ j and E ⊥ σ
        cross * (self.rho * self.theta_sh)
    }

    /// Calculate voltage across a strip of given dimensions
    ///
    /// # Arguments
    /// * `js_flow` - Spin current flow direction
    /// * `js_polarization` - Spin polarization direction
    /// * `strip_width` - Width of the conducting strip \[m\]
    ///
    /// # Returns
    /// Voltage \[V\] that can be measured across the strip
    ///
    /// # Example
    /// ```
    /// use spintronics::effect::ishe::InverseSpinHall;
    /// use spintronics::Vector3;
    ///
    /// // Pt detector strip: 0.1 mm wide
    /// let pt = InverseSpinHall::platinum();
    /// let width = 0.1e-3; // 0.1 mm
    ///
    /// // Spin current from spin pumping (typical FMR experiment)
    /// let js_flow = Vector3::new(0.0, 0.0, 1.0); // Flow into Pt
    /// let js_pol = Vector3::new(1.0e8, 0.0, 0.0); // 100 MA/m² polarization
    ///
    /// // Calculate ISHE voltage: V = w × ρ × θ_SH × |j × σ|
    /// let voltage = pt.voltage(js_flow, js_pol, width);
    ///
    /// // Voltage should be detectable (order of μV to mV)
    /// assert!(voltage > 1e-20);
    /// assert!(voltage.is_finite());
    ///
    /// // Compare with Saitoh 2006 experiment (~1 μV)
    /// println!("ISHE voltage: {:.3} μV", voltage * 1e6);
    /// ```
    #[inline]
    pub fn voltage(
        &self,
        js_flow: Vector3<f64>,
        js_polarization: Vector3<f64>,
        strip_width: f64,
    ) -> f64 {
        let e_field = self.convert(js_flow, js_polarization);
        e_field.magnitude() * strip_width
    }

    /// Calculate the conversion efficiency (V/W ratio)
    ///
    /// This is useful for comparing different material systems
    pub fn efficiency(&self) -> f64 {
        self.rho * self.theta_sh.abs()
    }

    /// Builder method to set spin Hall angle
    pub fn with_theta_sh(mut self, theta_sh: f64) -> Self {
        self.theta_sh = theta_sh;
        self
    }

    /// Builder method to set resistivity
    pub fn with_rho(mut self, rho: f64) -> Self {
        self.rho = rho;
        self
    }
}

impl fmt::Display for InverseSpinHall {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "InverseSpinHall(θ_SH={:.3}, ρ={:.2e} Ω·m)",
            self.theta_sh, self.rho
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ishe_perpendicularity() {
        let ishe = InverseSpinHall::default();
        let js_flow = Vector3::new(1.0, 0.0, 0.0);
        let js_pol = Vector3::new(0.0, 1.0, 0.0);

        let e_field = ishe.convert(js_flow, js_pol);

        // E field should be perpendicular to both flow and polarization
        assert!(e_field.dot(&js_flow).abs() < 1e-10);
        assert!(e_field.dot(&js_pol).abs() < 1e-10);
    }

    #[test]
    fn test_ishe_zero_current() {
        let ishe = InverseSpinHall::default();
        let js_flow = Vector3::new(0.0, 0.0, 0.0);
        let js_pol = Vector3::new(0.0, 1.0, 0.0);

        let e_field = ishe.convert(js_flow, js_pol);
        assert!(e_field.magnitude() < 1e-50);
    }

    #[test]
    fn test_ishe_parallel_vectors() {
        let ishe = InverseSpinHall::default();
        let js_flow = Vector3::new(1.0, 0.0, 0.0);
        let js_pol = Vector3::new(1.0, 0.0, 0.0);

        let e_field = ishe.convert(js_flow, js_pol);
        // Parallel vectors give zero cross product
        assert!(e_field.magnitude() < 1e-50);
    }

    #[test]
    fn test_material_properties() {
        let pt = InverseSpinHall::platinum();
        let ta = InverseSpinHall::tantalum();
        let w = InverseSpinHall::tungsten();

        assert!(pt.theta_sh > 0.0);
        assert!(ta.theta_sh > 0.0);
        assert!(w.theta_sh < 0.0); // Tungsten has negative spin Hall angle
    }
}