use crate::vector3::Vector3;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AfmStructure {
TypeI,
TypeII,
Collinear,
NonCollinear,
}
#[derive(Debug, Clone)]
pub struct Antiferromagnet {
pub name: String,
pub structure: AfmStructure,
pub neel_temperature: f64,
pub sublattice_magnetization: f64,
pub exchange_field: f64,
pub anisotropy_field: f64,
pub easy_axis: Vector3<f64>,
pub resonance_frequency: f64,
pub electrical_conductivity: f64,
pub spin_hall_angle: f64,
}
impl Antiferromagnet {
pub fn nio() -> Self {
Self {
name: "NiO".to_string(),
structure: AfmStructure::TypeII,
neel_temperature: 523.0, sublattice_magnetization: 1.77e5, exchange_field: 660.0, anisotropy_field: 0.02, easy_axis: Vector3::new(1.0, 1.0, 1.0).normalize(), resonance_frequency: 1.0, electrical_conductivity: 1.0e-10, spin_hall_angle: 0.0, }
}
pub fn mn2au() -> Self {
Self {
name: "Mn₂Au".to_string(),
structure: AfmStructure::Collinear,
neel_temperature: 1500.0, sublattice_magnetization: 2.0e6,
exchange_field: 800.0,
anisotropy_field: 1.0,
easy_axis: Vector3::new(0.0, 0.0, 1.0), resonance_frequency: 0.9,
electrical_conductivity: 1.0e6, spin_hall_angle: 0.02, }
}
pub fn cumnas() -> Self {
Self {
name: "CuMnAs".to_string(),
structure: AfmStructure::Collinear,
neel_temperature: 480.0,
sublattice_magnetization: 1.5e6,
exchange_field: 700.0,
anisotropy_field: 0.5,
easy_axis: Vector3::new(0.0, 0.0, 1.0),
resonance_frequency: 0.8,
electrical_conductivity: 5.0e5,
spin_hall_angle: 0.015,
}
}
pub fn irmn3() -> Self {
Self {
name: "IrMn₃".to_string(),
structure: AfmStructure::TypeI,
neel_temperature: 960.0,
sublattice_magnetization: 1.2e6,
exchange_field: 500.0,
anisotropy_field: 10.0, easy_axis: Vector3::new(1.0, 0.0, 0.0),
resonance_frequency: 0.5,
electrical_conductivity: 2.0e6,
spin_hall_angle: 0.05, }
}
pub fn fe2o3() -> Self {
Self {
name: "α-Fe₂O₃".to_string(),
structure: AfmStructure::TypeII, neel_temperature: 948.0, sublattice_magnetization: 2.5e6,
exchange_field: 600.0,
anisotropy_field: 0.05,
easy_axis: Vector3::new(0.0, 0.0, 1.0),
resonance_frequency: 0.6,
electrical_conductivity: 1.0e-6, spin_hall_angle: 0.0,
}
}
pub fn mnf2() -> Self {
Self {
name: "MnF₂".to_string(),
structure: AfmStructure::TypeI,
neel_temperature: 67.0, sublattice_magnetization: 5.0e5,
exchange_field: 55.0,
anisotropy_field: 8.8, easy_axis: Vector3::new(0.0, 0.0, 1.0),
resonance_frequency: 0.25,
electrical_conductivity: 1.0e-12, spin_hall_angle: 0.0,
}
}
pub fn calculate_resonance_frequency(&self) -> f64 {
let gamma = 2.8e10; let omega = gamma * (2.0 * self.exchange_field * self.anisotropy_field).sqrt();
omega * 1e-12 }
pub fn exchange_stiffness(&self) -> f64 {
let mu_0 = 4.0 * std::f64::consts::PI * 1e-7;
let a = 3.0e-10; let h_e_si = self.exchange_field * mu_0;
self.sublattice_magnetization * h_e_si * a / 2.0
}
pub fn is_room_temperature_stable(&self) -> bool {
self.neel_temperature > 300.0
}
pub fn is_electrically_switchable(&self) -> bool {
self.electrical_conductivity > 1.0e4 && self.spin_hall_angle > 0.01
}
pub fn is_thz_active(&self) -> bool {
self.resonance_frequency > 0.1 && self.neel_temperature > 77.0 }
pub fn neel_sot_efficiency(&self) -> f64 {
let structure_factor = match self.structure {
AfmStructure::Collinear => 1.0,
AfmStructure::NonCollinear => 0.8,
_ => 0.5,
};
self.spin_hall_angle * structure_factor
}
pub fn with_neel_temperature(mut self, tn: f64) -> Self {
self.neel_temperature = tn;
self
}
pub fn with_easy_axis(mut self, axis: Vector3<f64>) -> Self {
self.easy_axis = axis.normalize();
self
}
pub fn with_sublattice_magnetization(mut self, ms: f64) -> Self {
self.sublattice_magnetization = ms;
self
}
pub fn with_exchange_field(mut self, h_ex: f64) -> Self {
self.exchange_field = h_ex;
self
}
pub fn with_anisotropy_field(mut self, h_k: f64) -> Self {
self.anisotropy_field = h_k;
self
}
pub fn with_resonance_frequency(mut self, freq: f64) -> Self {
self.resonance_frequency = freq;
self
}
pub fn with_spin_hall_angle(mut self, theta_sh: f64) -> Self {
self.spin_hall_angle = theta_sh;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nio() {
let nio = Antiferromagnet::nio();
assert_eq!(nio.structure, AfmStructure::TypeII);
assert!(nio.neel_temperature > 500.0);
assert!(nio.electrical_conductivity < 1.0e-8); }
#[test]
fn test_mn2au_metallic() {
let mn2au = Antiferromagnet::mn2au();
assert!(mn2au.is_room_temperature_stable());
assert!(mn2au.is_electrically_switchable());
assert!(mn2au.electrical_conductivity > 1.0e5);
}
#[test]
fn test_cumnas_switching() {
let cumnas = Antiferromagnet::cumnas();
assert!(cumnas.is_electrically_switchable());
assert!(cumnas.is_room_temperature_stable());
}
#[test]
fn test_irmn3_pinning() {
let irmn3 = Antiferromagnet::irmn3();
assert!(irmn3.anisotropy_field > 5.0);
assert!(irmn3.neel_temperature > 900.0);
}
#[test]
fn test_mnf2_low_tn() {
let mnf2 = Antiferromagnet::mnf2();
assert!(!mnf2.is_room_temperature_stable());
assert!(mnf2.neel_temperature < 100.0);
assert!(mnf2.anisotropy_field > 5.0);
}
#[test]
fn test_resonance_frequency() {
let nio = Antiferromagnet::nio();
let f_r = nio.calculate_resonance_frequency();
assert!(f_r > 0.1);
assert!(f_r < 10.0);
}
#[test]
fn test_exchange_stiffness() {
let nio = Antiferromagnet::nio();
let a_ex = nio.exchange_stiffness();
assert!(a_ex > 0.0);
assert!(a_ex.is_finite());
}
#[test]
fn test_thz_activity() {
let nio = Antiferromagnet::nio();
let mnf2 = Antiferromagnet::mnf2();
assert!(nio.is_thz_active());
assert!(!mnf2.is_thz_active()); }
#[test]
fn test_electrical_switchability() {
let mn2au = Antiferromagnet::mn2au();
let nio = Antiferromagnet::nio();
assert!(mn2au.is_electrically_switchable());
assert!(!nio.is_electrically_switchable()); }
#[test]
fn test_neel_sot_efficiency() {
let mn2au = Antiferromagnet::mn2au();
let nio = Antiferromagnet::nio();
let eff_mn2au = mn2au.neel_sot_efficiency();
let eff_nio = nio.neel_sot_efficiency();
assert!(eff_mn2au > eff_nio);
assert!(eff_mn2au > 0.01);
}
#[test]
fn test_room_temperature_stability() {
let mn2au = Antiferromagnet::mn2au();
let cumnas = Antiferromagnet::cumnas();
let mnf2 = Antiferromagnet::mnf2();
assert!(mn2au.is_room_temperature_stable());
assert!(cumnas.is_room_temperature_stable());
assert!(!mnf2.is_room_temperature_stable());
}
#[test]
fn test_builder_pattern() {
let custom = Antiferromagnet::nio()
.with_neel_temperature(600.0)
.with_easy_axis(Vector3::new(1.0, 0.0, 0.0));
assert_eq!(custom.neel_temperature, 600.0);
assert!((custom.easy_axis.x - 1.0).abs() < 1e-10);
}
}