mod common;
use std::process::ExitCode;
use num_complex::Complex64 as c64;
use photonoxide::mode::Polarization;
use photonoxide::mode::dispersion::{group_index, track};
use photonoxide::mode::eim::Ridge;
use photonoxide::mode::vector::{Boundaries, Boundary, CrossSection, Permittivity};
use photonoxide::units::{Length, Wavelength};
fn strip(width: f64) -> photonoxide::Result<CrossSection> {
CrossSection::uniform((0.0, 1.05, 168), (0.0, 0.75, 150), |x, y| {
let n: f64 = if x < width / 2.0 && y < 0.11 {
3.473
} else {
1.444
};
Permittivity::isotropic(c64::new(n * n, 0.0))
})?
.with_boundaries(Boundaries {
west: Boundary::ElectricWall,
south: Boundary::MagneticWall,
..Boundaries::default()
})
}
fn main() -> photonoxide::Result<ExitCode> {
let wavelengths = [1.54, 1.55, 1.56]
.iter()
.map(|&l| Wavelength::um(l))
.collect::<photonoxide::Result<Vec<_>>>()?;
let mut checks = common::Checks::default();
println!("220 nm strips of 3.473 in 1.444, TE-like; 2D: 6.25 x 5 nm grid");
println!(" width EIM n_eff 2D n_eff error EIM n_g 2D n_g error");
for width in [0.40, 0.45, 0.50, 0.55, 0.60] {
let ridge = Ridge::strip(1.444, 3.473, 1.444, Length::nm(220.0), Length::um(width))?;
let eim: Vec<f64> = wavelengths
.iter()
.map(|&l| ridge.mode(Polarization::Te, l).map(|m| m.effective_index))
.collect::<photonoxide::Result<_>>()?;
let full: Vec<f64> = track(|_| strip(width), &wavelengths, None, 3)?
.iter()
.map(|m| m.effective_index().re)
.collect();
let (ng_eim, ng_full) = (
group_index(&wavelengths, &eim)?[1],
group_index(&wavelengths, &full)?[1],
);
println!(
" {:.0} nm {:.4} {:.4} {:+.2} % {:.3} {:.3} {:+.2} %",
width * 1000.0,
eim[1],
full[1],
100.0 * (eim[1] / full[1] - 1.0),
ng_eim,
ng_full,
100.0 * (ng_eim / ng_full - 1.0)
);
if width == 0.50 {
checks.compare("EIM n_eff, 500 nm strip", eim[1], 2.489, 1e-3);
}
}
Ok(checks.finish())
}