mod common;
use std::process::ExitCode;
use photonoxide::Complex64 as c64;
use photonoxide::mode::vector::{
self, Boundaries, Boundary, CrossSection, Permittivity, Pml, graded_nodes, richardson,
};
use photonoxide::units::Wavelength;
fn wire(h: f64) -> photonoxide::Result<CrossSection> {
let (si, ox) = (3.5, 1.45);
let x = graded_nodes(0.0, 1.6, (0.0, 0.35), h, 0.0125, 0.01, &[0.25]);
let y = graded_nodes(
-2.6,
1.5,
(-0.1, 0.32),
h,
0.0125,
0.01,
&[0.0, 0.22, -1.0, -1.6],
);
let mut cells = Vec::new();
for i in 0..x.len() - 1 {
let xc = 0.5 * (x[i] + x[i + 1]);
for j in 0..y.len() - 1 {
let yc = 0.5 * (y[j] + y[j + 1]);
let n: f64 = match yc {
yc if yc > 0.22 => 1.0,
yc if yc > 0.0 => {
if xc < 0.25 {
si
} else {
1.0
}
}
yc if yc > -1.0 => ox,
_ => si,
};
cells.push(Permittivity::isotropic(c64::new(n * n, 0.0)));
}
}
CrossSection::new(x, y, cells)?
.with_boundaries(Boundaries {
west: Boundary::ElectricWall,
..Boundaries::default()
})?
.with_pml(Pml {
south: 1.0,
strength: 3.0,
..Pml::default()
})
}
pub fn main() -> photonoxide::Result<ExitCode> {
let w = Wavelength::um(1.55)?;
let reference = c64::new(2.412372, 2.9135e-8);
println!(
"Bienstman et al.'s leaky wire, TE; reference (CAMFR) {:.6} + {:.4e}i",
reference.re, reference.im
);
let mut found = [c64::new(0.0, 0.0); 3];
for (k, h) in [0.005, 0.0025, 0.00125].into_iter().enumerate() {
let cs = wire(h)?;
let n = vector::modes(&cs, w, 1, Some(2.41))?[0].effective_index();
println!(
" core grid {:.2} nm ({} x {} nodes): {:.6} + {:.4e}i, Re error {:+.2e}, Im / reference {:.4}",
h * 1000.0,
cs.x().len(),
cs.y().len(),
n.re,
n.im,
n.re - reference.re,
n.im / reference.im
);
found[k] = n;
}
let (limit, order) = richardson(found);
println!(
" extrapolated (order {order:.2}): {:.6} + {:.4e}i",
limit.re, limit.im
);
let mut checks = common::Checks::default();
checks.compare("Re n_eff, extrapolated", limit.re, reference.re, 2e-4);
checks.compare("Im n_eff x 1e8, extrapolated", limit.im * 1e8, 2.9135, 0.06);
Ok(checks.finish())
}