use std::f64::consts::PI;
use std::fmt;
#[derive(Debug, Clone)]
pub struct TopologicalHall {
pub name: String,
pub hall_coefficient: f64,
pub anomalous_hall_coeff: f64,
pub resistivity: f64,
pub magnetization: f64,
pub skyrmion_diameter: f64,
}
impl Default for TopologicalHall {
fn default() -> Self {
Self::mnsi()
}
}
impl TopologicalHall {
pub fn mnsi() -> Self {
Self {
name: "MnSi".to_string(),
hall_coefficient: 1.5e-10, anomalous_hall_coeff: 2.0e-8, resistivity: 1.0e-5, magnetization: 1.8e5, skyrmion_diameter: 18.0, }
}
pub fn mnge() -> Self {
Self {
name: "MnGe".to_string(),
hall_coefficient: 2.0e-10,
anomalous_hall_coeff: 3.0e-8,
resistivity: 2.0e-5,
magnetization: 1.5e5,
skyrmion_diameter: 3.0, }
}
pub fn fege() -> Self {
Self {
name: "FeGe".to_string(),
hall_coefficient: 1.8e-10,
anomalous_hall_coeff: 2.5e-8,
resistivity: 1.2e-5,
magnetization: 3.84e5, skyrmion_diameter: 70.0, }
}
pub fn co2mnga() -> Self {
Self {
name: "Co₂MnGa".to_string(),
hall_coefficient: 1.0e-10,
anomalous_hall_coeff: 1.5e-8,
resistivity: 5.0e-6,
magnetization: 6.0e5,
skyrmion_diameter: 50.0,
}
}
pub fn topological_hall_resistivity(
&self,
skyrmion_density: f64,
topological_charge: f64,
) -> f64 {
let alpha = self.hall_coefficient * 1.0e-4; alpha * skyrmion_density * topological_charge
}
pub fn topological_hall_angle(&self, skyrmion_density: f64, topological_charge: f64) -> f64 {
let rho_the = self.topological_hall_resistivity(skyrmion_density, topological_charge);
(rho_the / self.resistivity).atan()
}
pub fn emergent_magnetic_field(&self, topological_charge: f64) -> f64 {
let phi_0 = 4.136e-15; let radius = self.skyrmion_diameter * 0.5 * 1e-9; let area = PI * radius * radius;
(phi_0 * topological_charge.abs() / area) * 1e-4 }
pub fn estimate_skyrmion_density(&self, measured_rho_the: f64, assumed_charge: f64) -> f64 {
let alpha = self.hall_coefficient * 1.0e-4;
measured_rho_the / (alpha * assumed_charge)
}
pub fn hall_voltage(
&self,
current: f64,
thickness: f64,
skyrmion_density: f64,
topological_charge: f64,
) -> f64 {
let rho_the = self.topological_hall_resistivity(skyrmion_density, topological_charge);
let thickness_cm = thickness * 1e-7; (rho_the / thickness_cm) * current
}
pub fn is_the_measurable(&self, skyrmion_density: f64) -> bool {
let rho_the = self.topological_hall_resistivity(skyrmion_density, 1.0);
rho_the / self.resistivity > 0.01
}
pub fn with_skyrmion_diameter(mut self, diameter: f64) -> Self {
self.skyrmion_diameter = diameter;
self
}
pub fn with_hall_coefficient(mut self, r0: f64) -> Self {
self.hall_coefficient = r0;
self
}
}
impl fmt::Display for TopologicalHall {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}: R₀={:.2e} Ω·cm/T, d_sk={:.1} nm, M_s={:.2e} A/m",
self.name, self.hall_coefficient, self.skyrmion_diameter, self.magnetization
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mnsi() {
let mnsi = TopologicalHall::mnsi();
assert_eq!(mnsi.name, "MnSi");
assert!(mnsi.skyrmion_diameter > 15.0);
assert!(mnsi.skyrmion_diameter < 20.0);
}
#[test]
fn test_mnge_small_skyrmions() {
let mnge = TopologicalHall::mnge();
assert!(mnge.skyrmion_diameter < 5.0);
}
#[test]
fn test_topological_hall_resistivity() {
let mnsi = TopologicalHall::mnsi();
let n_sk = 1.0e14; let q = 1.0;
let rho_the = mnsi.topological_hall_resistivity(n_sk, q);
assert!(rho_the > 0.0);
assert!(rho_the.is_finite());
}
#[test]
fn test_topological_hall_angle() {
let mnsi = TopologicalHall::mnsi();
let n_sk = 5.0e14;
let theta = mnsi.topological_hall_angle(n_sk, 1.0);
assert!(theta > 0.0);
assert!(theta.is_finite());
}
#[test]
fn test_emergent_magnetic_field() {
let mnsi = TopologicalHall::mnsi();
let b_eff = mnsi.emergent_magnetic_field(1.0);
assert!(b_eff > 0.0);
assert!(b_eff.is_finite());
}
#[test]
fn test_estimate_skyrmion_density() {
let mnsi = TopologicalHall::mnsi();
let n_sk_actual = 1.0e14;
let rho_the = mnsi.topological_hall_resistivity(n_sk_actual, 1.0);
let n_sk_estimated = mnsi.estimate_skyrmion_density(rho_the, 1.0);
assert!((n_sk_estimated - n_sk_actual).abs() / n_sk_actual < 0.01);
}
#[test]
fn test_hall_voltage() {
let mnsi = TopologicalHall::mnsi();
let current = 1.0e-6; let thickness = 100.0; let n_sk = 1.0e14;
let v_h = mnsi.hall_voltage(current, thickness, n_sk, 1.0);
assert!(v_h > 0.0);
assert!(v_h.is_finite());
}
#[test]
fn test_chirality_sign() {
let mnsi = TopologicalHall::mnsi();
let n_sk = 1.0e14;
let rho_plus = mnsi.topological_hall_resistivity(n_sk, 1.0);
let rho_minus = mnsi.topological_hall_resistivity(n_sk, -1.0);
assert!((rho_plus + rho_minus).abs() < 1e-15);
}
#[test]
fn test_the_measurability() {
let mnsi = TopologicalHall::mnsi();
let high_density = 1.0e15; let low_density = 1.0e6;
assert!(mnsi.is_the_measurable(high_density));
assert!(!mnsi.is_the_measurable(low_density));
}
#[test]
fn test_density_dependence() {
let mnsi = TopologicalHall::mnsi();
let n_sk1 = 1.0e14;
let n_sk2 = 2.0e14;
let rho1 = mnsi.topological_hall_resistivity(n_sk1, 1.0);
let rho2 = mnsi.topological_hall_resistivity(n_sk2, 1.0);
assert!((rho2 / rho1 - 2.0).abs() < 0.01);
}
#[test]
fn test_builder_pattern() {
let custom = TopologicalHall::mnsi()
.with_skyrmion_diameter(100.0)
.with_hall_coefficient(5.0e-10);
assert_eq!(custom.skyrmion_diameter, 100.0);
assert_eq!(custom.hall_coefficient, 5.0e-10);
}
}