use crate::material::Ferromagnet;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MultilayerType {
GmrSpinValve,
TmrJunction,
SyntheticAntiferromagnet,
ExchangeBiased,
}
#[derive(Debug, Clone)]
pub struct SpacerLayer {
pub material: String,
pub thickness: f64,
pub resistivity: f64,
pub is_insulator: bool,
pub spin_diffusion_length: f64,
}
impl SpacerLayer {
pub fn copper(thickness: f64) -> Self {
Self {
material: "Cu".to_string(),
thickness,
resistivity: 1.7e-8, is_insulator: false,
spin_diffusion_length: 500.0, }
}
pub fn chromium(thickness: f64) -> Self {
Self {
material: "Cr".to_string(),
thickness,
resistivity: 1.3e-7,
is_insulator: false,
spin_diffusion_length: 5.0, }
}
pub fn mgo(thickness: f64) -> Self {
Self {
material: "MgO".to_string(),
thickness,
resistivity: 1.0e14, is_insulator: true,
spin_diffusion_length: 0.0, }
}
pub fn al2o3(thickness: f64) -> Self {
Self {
material: "Al₂O₃".to_string(),
thickness,
resistivity: 1.0e13,
is_insulator: true,
spin_diffusion_length: 0.0,
}
}
}
#[derive(Debug, Clone)]
pub struct MagneticMultilayer {
pub structure_type: MultilayerType,
pub bottom_layer: Ferromagnet,
pub bottom_thickness: f64,
pub spacer: SpacerLayer,
pub top_layer: Ferromagnet,
pub top_thickness: f64,
pub rkky_coupling: f64,
pub exchange_bias: f64,
}
impl MagneticMultilayer {
pub fn gmr_co_cu_co() -> Self {
Self {
structure_type: MultilayerType::GmrSpinValve,
bottom_layer: Ferromagnet::cobalt(),
bottom_thickness: 10.0, spacer: SpacerLayer::copper(2.0),
top_layer: Ferromagnet::cobalt(),
top_thickness: 5.0,
rkky_coupling: 0.0,
exchange_bias: 0.0,
}
}
pub fn gmr_py_cu_py() -> Self {
Self {
structure_type: MultilayerType::GmrSpinValve,
bottom_layer: Ferromagnet::permalloy(),
bottom_thickness: 8.0,
spacer: SpacerLayer::copper(2.5),
top_layer: Ferromagnet::permalloy(),
top_thickness: 4.0,
rkky_coupling: 0.0,
exchange_bias: 0.0,
}
}
pub fn tmr_cofeb_mgo_cofeb() -> Self {
Self {
structure_type: MultilayerType::TmrJunction,
bottom_layer: Ferromagnet::cofeb(),
bottom_thickness: 3.0,
spacer: SpacerLayer::mgo(1.2), top_layer: Ferromagnet::cofeb(),
top_thickness: 2.0,
rkky_coupling: 0.0,
exchange_bias: 0.0,
}
}
pub fn saf_cofe_ru_cofe() -> Self {
let mut cofe = Ferromagnet::cofe();
cofe.ms = 1.4e6;
Self {
structure_type: MultilayerType::SyntheticAntiferromagnet,
bottom_layer: cofe.clone(),
bottom_thickness: 4.0,
spacer: SpacerLayer {
material: "Ru".to_string(),
thickness: 0.8, resistivity: 7.1e-8,
is_insulator: false,
spin_diffusion_length: 10.0,
},
top_layer: cofe,
top_thickness: 4.0,
rkky_coupling: -1.0e-3, exchange_bias: 0.0,
}
}
pub fn gmr_ratio(&self, angle: f64) -> f64 {
if self.structure_type != MultilayerType::GmrSpinValve {
return 0.0;
}
let gmr_max = 0.15; gmr_max * (1.0 - angle.cos()) / 2.0
}
pub fn tmr_ratio(&self, angle: f64) -> f64 {
if self.structure_type != MultilayerType::TmrJunction {
return 0.0;
}
let p1 = 0.7; let p2 = 0.7;
let tmr_max = 2.0 * p1 * p2 / (1.0 - p1 * p2);
tmr_max * (1.0 - angle.cos()) / 2.0
}
pub fn rkky_field(&self) -> f64 {
if self.rkky_coupling == 0.0 {
return 0.0;
}
let mu_0 = 4.0 * std::f64::consts::PI * 1e-7;
let t = self.top_thickness * 1e-9; let ms = self.top_layer.ms;
self.rkky_coupling / (mu_0 * ms * t)
}
pub fn resistance(&self, angle: f64, area: f64) -> f64 {
let r0 = 1.0e-12;
let mr = match self.structure_type {
MultilayerType::GmrSpinValve => self.gmr_ratio(angle),
MultilayerType::TmrJunction => self.tmr_ratio(angle),
_ => 0.0,
};
r0 * (1.0 + mr) / area
}
pub fn is_properly_coupled_saf(&self) -> bool {
self.structure_type == MultilayerType::SyntheticAntiferromagnet &&
self.rkky_coupling < 0.0 && self.spacer.thickness < 2.0 }
pub fn with_rkky_coupling(mut self, j_rkky: f64) -> Self {
self.rkky_coupling = j_rkky;
self
}
pub fn with_spacer_thickness(mut self, thickness: f64) -> Self {
self.spacer.thickness = thickness;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gmr_co_cu_co() {
let gmr = MagneticMultilayer::gmr_co_cu_co();
assert_eq!(gmr.structure_type, MultilayerType::GmrSpinValve);
assert!(!gmr.spacer.is_insulator);
assert_eq!(gmr.spacer.material, "Cu");
}
#[test]
fn test_tmr_cofeb_mgo() {
let tmr = MagneticMultilayer::tmr_cofeb_mgo_cofeb();
assert_eq!(tmr.structure_type, MultilayerType::TmrJunction);
assert!(tmr.spacer.is_insulator);
assert_eq!(tmr.spacer.material, "MgO");
}
#[test]
fn test_saf_structure() {
let saf = MagneticMultilayer::saf_cofe_ru_cofe();
assert_eq!(saf.structure_type, MultilayerType::SyntheticAntiferromagnet);
assert!(saf.rkky_coupling < 0.0); assert!(saf.is_properly_coupled_saf());
}
#[test]
fn test_gmr_ratio_parallel() {
let gmr = MagneticMultilayer::gmr_co_cu_co();
let ratio_p = gmr.gmr_ratio(0.0); assert!(ratio_p.abs() < 0.01); }
#[test]
fn test_gmr_ratio_antiparallel() {
let gmr = MagneticMultilayer::gmr_co_cu_co();
let ratio_ap = gmr.gmr_ratio(std::f64::consts::PI); assert!(ratio_ap > 0.1); }
#[test]
fn test_tmr_ratio() {
let tmr = MagneticMultilayer::tmr_cofeb_mgo_cofeb();
let ratio_ap = tmr.tmr_ratio(std::f64::consts::PI);
assert!(ratio_ap > 1.0); }
#[test]
fn test_rkky_field() {
let saf = MagneticMultilayer::saf_cofe_ru_cofe();
let h_rkky = saf.rkky_field();
assert!(h_rkky < 0.0); assert!(h_rkky.abs() > 0.01); }
#[test]
fn test_resistance_calculation() {
let gmr = MagneticMultilayer::gmr_co_cu_co();
let area = 1.0e-14;
let r_p = gmr.resistance(0.0, area);
let r_ap = gmr.resistance(std::f64::consts::PI, area);
assert!(r_ap > r_p); }
#[test]
fn test_builder_pattern() {
let saf = MagneticMultilayer::saf_cofe_ru_cofe()
.with_rkky_coupling(-2.0e-3)
.with_spacer_thickness(0.9);
assert_eq!(saf.rkky_coupling, -2.0e-3);
assert_eq!(saf.spacer.thickness, 0.9);
}
}