use std::f64::consts::PI;
#[derive(Debug, Clone, Copy)]
pub struct RamanMaterial {
pub f_r: f64,
pub g_r_peak: f64,
pub omega_r: f64,
pub gamma_r: f64,
pub tau1: f64,
pub tau2: f64,
}
impl RamanMaterial {
pub fn silica() -> Self {
Self {
f_r: 0.18,
g_r_peak: 1e-13, omega_r: 2.0 * PI * 13.2e12, gamma_r: 2.0 * PI * 3.0e12, tau1: 12.2e-15, tau2: 32.0e-15, }
}
pub fn silicon() -> Self {
Self {
f_r: 0.043,
g_r_peak: 76e-11, omega_r: 2.0 * PI * 15.6e12, gamma_r: 2.0 * PI * 0.105e12, tau1: 10.2e-15,
tau2: 3.03e-12, }
}
pub fn diamond() -> Self {
Self {
f_r: 0.10,
g_r_peak: 75e-12, omega_r: 2.0 * PI * 40.0e12, gamma_r: 2.0 * PI * 0.5e12, tau1: 8.0e-15,
tau2: 0.64e-12,
}
}
pub fn raman_response(&self, delta_omega: f64) -> f64 {
if delta_omega <= 0.0 {
return 0.0;
}
let tau1 = self.tau1;
let tau2 = self.tau2;
let prefactor = (tau1 * tau1 + tau2 * tau2) / (tau1 * tau2 * tau2);
prefactor * (-delta_omega * tau2).exp() * (delta_omega * tau1).sin()
}
pub fn gain_spectrum(&self, delta_omega: f64) -> f64 {
let dw = delta_omega - self.omega_r;
let gr = self.gamma_r;
self.g_r_peak * gr * gr / (dw * dw + gr * gr)
}
pub fn peak_gain(&self) -> f64 {
self.g_r_peak
}
pub fn stokes_shift_wavelength(&self, lambda_pump: f64) -> f64 {
let c = 2.998e8;
lambda_pump * lambda_pump * self.omega_r / (2.0 * PI * c)
}
pub fn srs_threshold(&self, a_eff: f64, l_eff: f64) -> f64 {
16.0 * a_eff / (self.g_r_peak * l_eff)
}
pub fn gain_coefficient(&self, pump_power: f64, a_eff: f64) -> f64 {
self.g_r_peak * pump_power / a_eff
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn silica_raman_params_physical() {
let m = RamanMaterial::silica();
assert!(m.f_r > 0.0 && m.f_r < 1.0);
assert!(m.omega_r > 2.0 * PI * 10e12); assert!(m.g_r_peak > 0.0);
}
#[test]
fn raman_response_positive_at_stokes() {
let m = RamanMaterial::silica();
let h = m.raman_response(m.omega_r);
assert!(h > 0.0);
}
#[test]
fn raman_response_zero_for_negative_shift() {
let m = RamanMaterial::silica();
assert!(m.raman_response(-1e12) == 0.0);
}
#[test]
fn gain_spectrum_peaks_at_omega_r() {
let m = RamanMaterial::silica();
let at_peak = m.gain_spectrum(m.omega_r);
let off_peak = m.gain_spectrum(m.omega_r * 1.5);
assert!(at_peak > off_peak);
}
#[test]
fn stokes_shift_wavelength_positive() {
let m = RamanMaterial::silica();
let dl = m.stokes_shift_wavelength(1550e-9);
assert!(dl > 0.0 && dl < 200e-9); }
#[test]
fn srs_threshold_physical() {
let m = RamanMaterial::silica();
let p_th = m.srs_threshold(80e-12, 20e3);
assert!(p_th > 0.1 && p_th < 100.0);
}
#[test]
fn silicon_raman_higher_stokes_than_silica() {
let sio2 = RamanMaterial::silica();
let si = RamanMaterial::silicon();
assert!(si.omega_r > sio2.omega_r);
}
}