#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::vector3::Vector3;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct OnsagerMatrix {
pub temperature: f64,
pub conductivity: f64,
pub seebeck: f64,
pub spin_seebeck: f64,
pub hall_angle: f64,
pub thermal_conductivity: f64,
}
impl OnsagerMatrix {
pub fn new(
temperature: f64,
conductivity: f64,
seebeck: f64,
spin_seebeck: f64,
hall_angle: f64,
thermal_conductivity: f64,
) -> Self {
Self {
temperature,
conductivity,
seebeck,
spin_seebeck,
hall_angle,
thermal_conductivity,
}
}
pub fn yig_pt(temperature: f64) -> Self {
Self {
temperature,
conductivity: 5.0e6,
seebeck: -5.0e-6,
spin_seebeck: 1.0e-3,
hall_angle: 0.1,
thermal_conductivity: 46.0,
}
}
pub fn fe_pt(temperature: f64) -> Self {
Self {
temperature,
conductivity: 1.0e7,
seebeck: -15.0e-6,
spin_seebeck: 5.0e-3,
hall_angle: 0.08,
thermal_conductivity: 80.0,
}
}
pub fn cofeb_pt(temperature: f64) -> Self {
Self {
temperature,
conductivity: 8.0e6,
seebeck: -10.0e-6,
spin_seebeck: 3.0e-3,
hall_angle: 0.06,
thermal_conductivity: 60.0,
}
}
pub fn reciprocity_error(&self) -> f64 {
let l_cq = self.conductivity * self.seebeck;
let l_qc = self.temperature * self.conductivity * self.seebeck;
let l_sq = self.spin_seebeck * self.conductivity;
let l_qs = self.temperature * self.spin_seebeck * self.conductivity;
let charge_err = if l_qc.abs() > f64::EPSILON {
(l_qc - self.temperature * l_cq).abs() / l_qc.abs()
} else {
0.0
};
let spin_err = if l_qs.abs() > f64::EPSILON {
(l_qs - self.temperature * l_sq).abs() / l_qs.abs()
} else {
0.0
};
charge_err + spin_err
}
pub fn spin_current_from_grad_t(&self, grad_t: &Vector3<f64>) -> Vector3<f64> {
let prefactor = self.spin_seebeck * self.conductivity;
Vector3::new(
prefactor * grad_t.x,
prefactor * grad_t.y,
prefactor * grad_t.z,
)
}
pub fn heat_current_from_spin_current(&self, j_spin: &Vector3<f64>) -> Vector3<f64> {
let pi_s = self.temperature * self.spin_seebeck;
Vector3::new(pi_s * j_spin.x, pi_s * j_spin.y, pi_s * j_spin.z)
}
pub fn nernst_voltage(&self, grad_t: f64) -> f64 {
-self.seebeck * self.hall_angle * grad_t
}
pub fn all_currents(&self, grad_t: &Vector3<f64>, e_field: &Vector3<f64>) -> AllCurrents {
let seebeck_force_x = self.seebeck * grad_t.x;
let seebeck_force_y = self.seebeck * grad_t.y;
let seebeck_force_z = self.seebeck * grad_t.z;
let charge_current = Vector3::new(
self.conductivity * (e_field.x + seebeck_force_x),
self.conductivity * (e_field.y + seebeck_force_y),
self.conductivity * (e_field.z + seebeck_force_z),
);
let spin_current = self.spin_current_from_grad_t(grad_t);
let peltier_coeff = self.temperature * self.seebeck;
let heat_current = Vector3::new(
peltier_coeff * self.conductivity * e_field.x - self.thermal_conductivity * grad_t.x,
peltier_coeff * self.conductivity * e_field.y - self.thermal_conductivity * grad_t.y,
peltier_coeff * self.conductivity * e_field.z - self.thermal_conductivity * grad_t.z,
);
AllCurrents {
charge_current,
spin_current,
heat_current,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AllCurrents {
pub charge_current: Vector3<f64>,
pub spin_current: Vector3<f64>,
pub heat_current: Vector3<f64>,
}