mod common;
use std::process::ExitCode;
use num_complex::Complex64 as c64;
use photonoxide::mode::vector::{self, Boundaries, Boundary, CrossSection, Permittivity, Pml};
use photonoxide::units::Wavelength;
fn main() -> photonoxide::Result<ExitCode> {
let h = 0.0025;
let index = |y: f64| match y {
y if y > 0.0 => 1.0,
y if y > -0.5 => 1.66,
y if y > -1.0 => 1.53,
y if y > -1.5 => 1.60,
y if y > -2.0 => 1.66,
_ => 1.5,
};
let (bottom, top) = (-5.0, 1.0);
let guide = CrossSection::uniform(
(0.0, 4.0 * h, 4),
(bottom, top, ((top - bottom) / h).round() as usize),
|_, y| Permittivity::isotropic(c64::new(index(y) * index(y), 0.0)),
)?
.with_boundaries(Boundaries {
west: Boundary::ElectricWall,
east: Boundary::ElectricWall,
..Boundaries::default()
})?
.with_pml(Pml {
south: 2.0,
strength: 5.0,
..Pml::default()
})?;
let wavelength = Wavelength::nm(632.8)?;
println!("Chilwell & Hodgkinson's guide, flat, 2.5 nm grid, PML below the substrate");
let mut checks = common::Checks::default();
for (order, re, im, tolerance) in [
(4, 1.46186, 0.00716, 5e-5),
(5, 1.38250, 0.01817, 5e-5),
(6, 1.28136, 0.03588, 5e-5),
(7, 1.14231, 0.05288, 5e-5),
(8, 1.00304, 0.07077, 2e-4),
] {
let printed = c64::new(re, im);
let found = vector::modes(&guide, wavelength, 3, Some(re))?
.iter()
.map(|m| m.effective_index())
.min_by(|a, b| (a - printed).norm().total_cmp(&(b - printed).norm()))
.unwrap_or(c64::new(f64::NAN, f64::NAN));
checks.compare(&format!("TE{order} Re n_eff"), found.re, re, tolerance);
checks.compare(&format!("TE{order} Im n_eff"), found.im, im, tolerance);
}
Ok(checks.finish())
}