use std::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::vector3::Vector3;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WeylType {
TypeI,
TypeII,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum MagneticState {
Nonmagnetic,
Ferromagnetic,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WeylSemimetal {
pub name: String,
pub weyl_type: WeylType,
pub magnetic_state: MagneticState,
pub num_weyl_nodes: usize,
pub fermi_velocity: f64,
pub node_separation_energy: f64,
pub node_separation_momentum: f64,
pub anomalous_hall_conductivity: f64,
pub electrical_conductivity: f64,
pub carrier_density: f64,
}
impl Default for WeylSemimetal {
fn default() -> Self {
Self::taas()
}
}
impl WeylSemimetal {
pub fn taas() -> Self {
Self {
name: "TaAs".to_string(),
weyl_type: WeylType::TypeI,
magnetic_state: MagneticState::Nonmagnetic,
num_weyl_nodes: 12, fermi_velocity: 6.0e5, node_separation_energy: 0.02, node_separation_momentum: 0.03, anomalous_hall_conductivity: 1.0e4, electrical_conductivity: 5.0e5, carrier_density: 1.0e25, }
}
pub fn co3sn2s2() -> Self {
Self {
name: "Co₃Sn₂S₂".to_string(),
weyl_type: WeylType::TypeI,
magnetic_state: MagneticState::Ferromagnetic,
num_weyl_nodes: 2, fermi_velocity: 4.0e5,
node_separation_energy: 0.06, node_separation_momentum: 0.1,
anomalous_hall_conductivity: 1.5e6, electrical_conductivity: 2.0e6,
carrier_density: 5.0e26,
}
}
pub fn wte2() -> Self {
Self {
name: "WTe₂".to_string(),
weyl_type: WeylType::TypeII,
magnetic_state: MagneticState::Nonmagnetic,
num_weyl_nodes: 4, fermi_velocity: 3.0e5,
node_separation_energy: 0.05,
node_separation_momentum: 0.02,
anomalous_hall_conductivity: 5.0e4,
electrical_conductivity: 1.0e6,
carrier_density: 2.0e25,
}
}
pub fn nbas() -> Self {
Self {
name: "NbAs".to_string(),
weyl_type: WeylType::TypeI,
magnetic_state: MagneticState::Nonmagnetic,
num_weyl_nodes: 12,
fermi_velocity: 5.5e5,
node_separation_energy: 0.018,
node_separation_momentum: 0.028,
anomalous_hall_conductivity: 8.0e3,
electrical_conductivity: 4.5e5,
carrier_density: 8.0e24,
}
}
pub fn tap() -> Self {
Self {
name: "TaP".to_string(),
weyl_type: WeylType::TypeI,
magnetic_state: MagneticState::Nonmagnetic,
num_weyl_nodes: 12,
fermi_velocity: 6.5e5,
node_separation_energy: 0.025,
node_separation_momentum: 0.032,
anomalous_hall_conductivity: 1.2e4,
electrical_conductivity: 6.0e5,
carrier_density: 1.2e25,
}
}
pub fn anomalous_hall_angle(&self) -> f64 {
self.anomalous_hall_conductivity / self.electrical_conductivity
}
pub fn chiral_anomaly_conductivity(&self, e_field: Vector3<f64>, b_field: Vector3<f64>) -> f64 {
let e_dot_b = e_field.dot(&b_field);
let coeff = self.node_separation_momentum * 1e10 * 1e-6;
coeff * e_dot_b.abs()
}
pub fn magnetoresistance(&self, b_field_magnitude: f64) -> f64 {
let mr_coeff = 0.01 * self.node_separation_momentum; -mr_coeff * b_field_magnitude * b_field_magnitude
}
pub fn berry_curvature(&self, k_distance: f64) -> f64 {
if k_distance < 1e-6 {
1.0e6
} else {
1.0 / (k_distance * k_distance)
}
}
pub fn is_suitable_for_spintronics(&self) -> bool {
self.anomalous_hall_angle() > 0.01 ||
self.magnetic_state == MagneticState::Ferromagnetic
}
pub fn with_num_nodes(mut self, num: usize) -> Self {
self.num_weyl_nodes = num;
self
}
pub fn with_fermi_velocity(mut self, vf: f64) -> Self {
self.fermi_velocity = vf;
self
}
}
impl fmt::Display for WeylType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WeylType::TypeI => write!(f, "Type-I"),
WeylType::TypeII => write!(f, "Type-II"),
}
}
}
impl fmt::Display for MagneticState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MagneticState::Nonmagnetic => write!(f, "Non-magnetic"),
MagneticState::Ferromagnetic => write!(f, "Ferromagnetic"),
}
}
}
impl fmt::Display for WeylSemimetal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} [{}, {}]: {} Weyl nodes, v_F={:.2e} m/s, σ_AH={:.2e} S/m",
self.name,
self.weyl_type,
self.magnetic_state,
self.num_weyl_nodes * 2,
self.fermi_velocity,
self.anomalous_hall_conductivity
)
}
}
impl super::traits::SpinChargeConverter for WeylSemimetal {
fn spin_hall_angle(&self) -> f64 {
self.anomalous_hall_angle()
}
fn spin_hall_conductivity(&self) -> f64 {
self.anomalous_hall_conductivity
}
}
impl super::traits::TopologicalMaterial for WeylSemimetal {
fn bulk_gap(&self) -> f64 {
self.node_separation_energy
}
fn surface_fermi_velocity(&self) -> f64 {
self.fermi_velocity
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_taas() {
let taas = WeylSemimetal::taas();
assert_eq!(taas.name, "TaAs");
assert_eq!(taas.weyl_type, WeylType::TypeI);
assert_eq!(taas.magnetic_state, MagneticState::Nonmagnetic);
assert_eq!(taas.num_weyl_nodes, 12);
}
#[test]
fn test_co3sn2s2_magnetic() {
let co3sn2s2 = WeylSemimetal::co3sn2s2();
assert_eq!(co3sn2s2.magnetic_state, MagneticState::Ferromagnetic);
assert!(co3sn2s2.num_weyl_nodes >= 2);
assert!(co3sn2s2.anomalous_hall_conductivity > 1.0e6);
}
#[test]
fn test_wte2_type_ii() {
let wte2 = WeylSemimetal::wte2();
assert_eq!(wte2.weyl_type, WeylType::TypeII);
assert_eq!(wte2.magnetic_state, MagneticState::Nonmagnetic);
}
#[test]
fn test_anomalous_hall_angle() {
let taas = WeylSemimetal::taas();
let theta_ah = taas.anomalous_hall_angle();
assert!(theta_ah > 0.0);
assert!(theta_ah < 0.1);
}
#[test]
fn test_co3sn2s2_giant_ahe() {
let co3sn2s2 = WeylSemimetal::co3sn2s2();
let theta_ah = co3sn2s2.anomalous_hall_angle();
assert!(theta_ah > 0.1);
}
#[test]
fn test_chiral_anomaly() {
let taas = WeylSemimetal::taas();
let e_field = Vector3::new(1000.0, 0.0, 0.0); let b_field = Vector3::new(1.0, 0.0, 0.0);
let delta_sigma = taas.chiral_anomaly_conductivity(e_field, b_field);
assert!(delta_sigma > 0.0);
}
#[test]
fn test_chiral_anomaly_perpendicular() {
let taas = WeylSemimetal::taas();
let e_field = Vector3::new(1000.0, 0.0, 0.0);
let b_field = Vector3::new(0.0, 1.0, 0.0);
let delta_sigma = taas.chiral_anomaly_conductivity(e_field, b_field);
assert!(delta_sigma.abs() < 1e-10);
}
#[test]
fn test_negative_magnetoresistance() {
let taas = WeylSemimetal::taas();
let b_field = 5.0;
let mr = taas.magnetoresistance(b_field);
assert!(mr < 0.0);
}
#[test]
fn test_magnetoresistance_quadratic() {
let taas = WeylSemimetal::taas();
let b1 = 1.0;
let b2 = 2.0;
let mr1 = taas.magnetoresistance(b1);
let mr2 = taas.magnetoresistance(b2);
assert!((mr2 / mr1 - 4.0).abs() < 0.01);
}
#[test]
fn test_berry_curvature_divergence() {
let taas = WeylSemimetal::taas();
let omega_far = taas.berry_curvature(0.1); let omega_near = taas.berry_curvature(0.01);
assert!(omega_near > omega_far);
}
#[test]
fn test_spintronics_suitability() {
let co3sn2s2 = WeylSemimetal::co3sn2s2(); let taas = WeylSemimetal::taas();
assert!(co3sn2s2.is_suitable_for_spintronics());
assert!(taas.anomalous_hall_conductivity > 0.0);
}
#[test]
fn test_builder_pattern() {
let custom = WeylSemimetal::taas()
.with_num_nodes(24)
.with_fermi_velocity(1.0e6);
assert_eq!(custom.num_weyl_nodes, 24);
assert_eq!(custom.fermi_velocity, 1.0e6);
}
#[test]
fn test_material_family() {
let taas = WeylSemimetal::taas();
let nbas = WeylSemimetal::nbas();
let tap = WeylSemimetal::tap();
assert_eq!(taas.weyl_type, WeylType::TypeI);
assert_eq!(nbas.weyl_type, WeylType::TypeI);
assert_eq!(tap.weyl_type, WeylType::TypeI);
assert_eq!(taas.num_weyl_nodes, nbas.num_weyl_nodes);
assert_eq!(taas.num_weyl_nodes, tap.num_weyl_nodes);
}
}