use std::f64::consts::PI;
#[derive(Debug, Clone, Copy)]
pub struct SiliconRingModulator {
pub radius: f64,
pub n_eff: f64,
pub n_g: f64,
pub kappa_sq: f64,
pub a_sq: f64,
pub wavelength: f64,
pub confinement: f64,
}
impl SiliconRingModulator {
pub fn new(
radius: f64,
n_eff: f64,
n_g: f64,
kappa_sq: f64,
a_sq: f64,
wavelength: f64,
) -> Self {
Self {
radius,
n_eff,
n_g,
kappa_sq,
a_sq,
wavelength,
confinement: 0.8,
}
}
pub fn standard_si_ring() -> Self {
Self {
radius: 5e-6,
n_eff: 2.44,
n_g: 4.18,
kappa_sq: 0.05, a_sq: 0.99, wavelength: 1550e-9,
confinement: 0.85,
}
}
pub fn fsr(&self) -> f64 {
self.wavelength * self.wavelength / (2.0 * PI * self.radius * self.n_g)
}
pub fn resonance_wavelength(&self) -> f64 {
let circumference = 2.0 * PI * self.radius;
let m = (circumference * self.n_eff / self.wavelength).round();
circumference * self.n_eff / m
}
pub fn transmission(&self, wavelength: f64, delta_n: f64) -> f64 {
let n_eff_mod = self.n_eff + delta_n * self.confinement;
let circumference = 2.0 * PI * self.radius;
let phi = 2.0 * PI * n_eff_mod * circumference / wavelength;
let a2 = self.a_sq;
let t2 = 1.0 - self.kappa_sq; let a = a2.sqrt();
let t = t2.sqrt();
let cos_phi = phi.cos();
let num = a2 - 2.0 * a * t * cos_phi + t2;
let den = 1.0 - 2.0 * a * t * cos_phi + a2 * t2;
num / den
}
pub fn resonance_shift_per_carrier(&self) -> f64 {
let dn_per_carrier = -8.8e-22; let lambda_res = self.resonance_wavelength();
lambda_res * self.confinement * dn_per_carrier / self.n_g
}
pub fn extinction_ratio_db(&self) -> f64 {
let t_min = self.transmission(self.resonance_wavelength(), 0.0);
let t_max = 1.0;
if t_min < 1e-20 {
return 100.0; }
10.0 * (t_max / t_min).log10()
}
pub fn bandwidth_3db_hz(&self) -> f64 {
let fsr_hz = 2.998e8 / (2.0 * PI * self.radius * self.n_g);
let r_eff = (self.a_sq * (1.0 - self.kappa_sq)).sqrt();
let finesse = PI * r_eff.sqrt() / (1.0 - r_eff);
fsr_hz / finesse
}
pub fn energy_per_bit_joules(&self, v_drive: f64, capacitance: f64) -> f64 {
capacitance * v_drive * v_drive / 4.0
}
pub fn carrier_density_for_shift(&self, delta_lambda: f64) -> f64 {
let shift_per_carrier = self.resonance_shift_per_carrier();
delta_lambda / shift_per_carrier
}
pub fn finesse(&self) -> f64 {
let r_eff = (self.a_sq * (1.0 - self.kappa_sq)).sqrt();
PI * r_eff.sqrt() / (1.0 - r_eff)
}
pub fn q_factor(&self) -> f64 {
let lambda_res = self.resonance_wavelength();
let fsr = self.fsr();
let finesse = self.finesse();
lambda_res * finesse / fsr
}
}
#[derive(Debug, Clone, Copy)]
pub struct ElectroAbsorptionRing {
pub ring: SiliconRingModulator,
pub dk_per_field: f64,
pub ge_thickness: f64,
}
impl ElectroAbsorptionRing {
pub fn gesi_1310nm() -> Self {
let ring = SiliconRingModulator {
radius: 10e-6,
n_eff: 3.6,
n_g: 4.5,
kappa_sq: 0.08,
a_sq: 0.95,
wavelength: 1310e-9,
confinement: 0.4,
};
Self {
ring,
dk_per_field: 1e-7,
ge_thickness: 100e-9,
}
}
pub fn loss_per_volt(&self, v: f64) -> f64 {
let field = v / self.ge_thickness;
let dk = self.dk_per_field * field;
4.0 * PI * dk / self.ring.wavelength
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fsr_physical_range() {
let m = SiliconRingModulator::standard_si_ring();
let fsr = m.fsr();
assert!(fsr > 5e-9 && fsr < 30e-9, "FSR={:.2e}", fsr);
}
#[test]
fn resonance_wavelength_near_operating() {
let m = SiliconRingModulator::standard_si_ring();
let lres = m.resonance_wavelength();
assert!((lres - m.wavelength).abs() < m.fsr());
}
#[test]
fn transmission_at_resonance_below_unity() {
let m = SiliconRingModulator::standard_si_ring();
let lres = m.resonance_wavelength();
let t = m.transmission(lres, 0.0);
assert!((0.0..1.0).contains(&t), "T={t:.4}");
}
#[test]
fn transmission_off_resonance_near_unity() {
let m = SiliconRingModulator::standard_si_ring();
let lres = m.resonance_wavelength();
let t = m.transmission(lres + m.fsr() * 0.5, 0.0);
assert!(t > 0.9, "T off-res={t:.4}");
}
#[test]
fn extinction_ratio_positive() {
let m = SiliconRingModulator::standard_si_ring();
let er = m.extinction_ratio_db();
assert!(er > 0.0);
}
#[test]
fn bandwidth_3db_positive() {
let m = SiliconRingModulator::standard_si_ring();
let bw = m.bandwidth_3db_hz();
assert!(bw > 1e6); }
#[test]
fn q_factor_positive() {
let m = SiliconRingModulator::standard_si_ring();
let q = m.q_factor();
assert!(q > 100.0, "Q={q:.0}");
}
#[test]
fn energy_per_bit_picojoules_range() {
let m = SiliconRingModulator::standard_si_ring();
let e = m.energy_per_bit_joules(2.0, 50e-15);
assert!(e > 1e-15 && e < 1e-9, "E={e:.2e} J");
}
}