#[derive(Debug, Clone, Copy)]
pub struct KerrMaterial {
pub n0: f64,
pub n2: f64,
}
impl KerrMaterial {
pub fn new(n0: f64, n2: f64) -> Self {
Self { n0, n2 }
}
pub fn silica() -> Self {
Self {
n0: 1.45,
n2: 2.6e-20,
} }
pub fn silicon() -> Self {
Self {
n0: 3.476,
n2: 6e-18,
} }
pub fn silicon_nitride() -> Self {
Self {
n0: 2.0,
n2: 2.4e-19,
} }
pub fn refractive_index(&self, intensity: f64) -> f64 {
self.n0 + self.n2 * intensity
}
pub fn spm_phase(&self, intensity: f64, k0: f64, length: f64) -> f64 {
self.n2 * k0 * intensity * length
}
pub fn gamma(&self, omega: f64, a_eff: f64) -> f64 {
use crate::units::conversion::SPEED_OF_LIGHT;
self.n2 * omega / (SPEED_OF_LIGHT * a_eff)
}
pub fn nonlinear_length(&self, gamma: f64, peak_power: f64) -> f64 {
if gamma * peak_power < 1e-30 {
f64::INFINITY
} else {
1.0 / (gamma * peak_power)
}
}
}
pub fn b_integral(n2: f64, wavelength: f64, intensity_profile: &[f64], dz: f64) -> f64 {
use std::f64::consts::PI;
let k0 = 2.0 * PI / wavelength;
k0 * n2 * intensity_profile.iter().sum::<f64>() * dz
}
#[cfg(test)]
mod tests {
use super::*;
use std::f64::consts::PI;
#[test]
fn kerr_silica_n2_physical() {
let mat = KerrMaterial::silica();
assert!(mat.n2 > 1e-21 && mat.n2 < 1e-19);
}
#[test]
fn kerr_refractive_index_increases_with_intensity() {
let mat = KerrMaterial::silica();
let i1 = 1e12; let i2 = 2e12;
assert!(mat.refractive_index(i2) > mat.refractive_index(i1));
}
#[test]
fn kerr_spm_phase_linear_in_length() {
let mat = KerrMaterial::silica();
let k0 = 2.0 * PI / 1550e-9;
let i = 1e12;
let phi1 = mat.spm_phase(i, k0, 1.0);
let phi2 = mat.spm_phase(i, k0, 2.0);
assert!((phi2 / phi1 - 2.0).abs() < 1e-10);
}
#[test]
fn kerr_gamma_si_larger_than_silica() {
use crate::units::conversion::SPEED_OF_LIGHT;
let si = KerrMaterial::silicon();
let sio2 = KerrMaterial::silica();
let omega = 2.0 * PI * SPEED_OF_LIGHT / 1550e-9;
let a_eff = 0.5e-12; let gamma_si = si.gamma(omega, a_eff);
let gamma_sio2 = sio2.gamma(omega, a_eff);
assert!(gamma_si > gamma_sio2, "Si has larger γ than silica");
}
#[test]
fn b_integral_zero_for_zero_intensity() {
let profile = vec![0.0f64; 100];
let b = b_integral(2.6e-20, 1550e-9, &profile, 1e-3);
assert_eq!(b, 0.0);
}
#[test]
fn nonlinear_length_decreases_with_power() {
let mat = KerrMaterial::silicon();
let omega = 2.0 * std::f64::consts::PI * crate::units::conversion::SPEED_OF_LIGHT / 1550e-9;
let a_eff = 0.5e-12;
let gamma = mat.gamma(omega, a_eff);
let l1 = mat.nonlinear_length(gamma, 1e-3); let l2 = mat.nonlinear_length(gamma, 10e-3); assert!(l1 > l2, "Higher power → shorter nonlinear length");
}
}