### Example: create and solve DriftDiffusionDevice Source: https://docs.rs/oxiphoton/latest/oxiphoton/solar/drift_diffusion/struct.DriftDiffusionDevice.html Shows how to create a DriftDiffusionDevice with silicon material and a pn-junction doping profile, then solve for equilibrium. The example expects device creation and equilibrium solve to succeed. ```rust let mat = SemiconductorMaterial::silicon(); let doping = DopingProfile::pn_junction(100, 1e16, 1e16); let mut device = DriftDiffusionDevice::new(mat, doping, 5e-4, 100) .expect("device creation should succeed"); let _n_iters = device.solve_equilibrium().expect("equilibrium solve"); ``` -------------------------------- ### Parametric sweep example using ParamSweep and WavelengthSweep Source: https://docs.rs/oxiphoton/latest/oxiphoton/fdtd/sweep/index.html Shows how to create a linear parameter sweep with ParamSweep::linspace and a wavelength sweep with WavelengthSweep::new. The example runs a simple function over the sweep and retrieves the wavelength values in nanometers. ```rust use oxiphoton::fdtd::sweep::parameter::{ParamSweep, WavelengthSweep}; // Linear sweep let sweep = ParamSweep::linspace("thickness_nm", 100.0, 500.0, 5); let results = sweep.run(|t| t * t); // Wavelength sweep from 1000 nm to 1600 nm let ws = WavelengthSweep::new(1000.0, 1600.0, 61); let _lambdas = ws.wavelengths_nm(); ``` -------------------------------- ### Example: Creating and using BandStructureCalc Source: https://docs.rs/oxiphoton/latest/oxiphoton/fdtd/boundary/bloch/struct.BandStructureCalc.html Example usage of BandStructureCalc: creates a square lattice path, constructs the calculator, and computes the band structure. ```rust let path = BandStructureCalc::square_lattice_path(20, 500e-9); let calc = BandStructureCalc::new(path, 512, (1e13, 1e15), 2000); let bands = calc.compute(500e-9, |_x, _y, _z| 1.0); ``` -------------------------------- ### expect example: panicking on Err Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows how to use expect to return the contained Ok value, panicking if the Result is Err. The example demonstrates the panic message format. ```rust let x: Result = Err("emergency failure"); x.expect("Testing expect"); // panics with `Testing expect: emergency failure` ``` -------------------------------- ### Example: convert 0.8 eV to wavelength Source: https://docs.rs/oxiphoton/latest/oxiphoton/units/conversion/fn.ev_to_wavelength_nm.html Example usage of ev_to_wavelength_nm. Converts 0.8 eV to wavelength and asserts the result is approximately 1549.8 nm. ```rust use oxiphoton::units::conversion::ev_to_wavelength_nm; let wl = ev_to_wavelength_nm(0.8); // ~1550 nm assert!((wl - 1549.8).abs() < 1.0); ``` -------------------------------- ### Vec::from_parts examples: rebuild from parts and from allocated memory Source: https://docs.rs/oxiphoton/latest/oxiphoton/smatrix/eigenmode/type.CMatrix.html Shows how to reconstruct a Vec from its parts after using into_parts, and how to build a Vec from memory allocated elsewhere with the global allocator. The second example uses unsafe code and requires the pointer to satisfy all safety invariants of Vec::from_parts. ```rust let v = vec![1, 2, 3]; // Deconstruct the vector into parts. let (p, len, cap) = v.into_parts(); unsafe { // Overwrite memory with 4, 5, 6 for i in 0..len { p.add(i).write(4 + i); } // Put everything back together into a Vec let rebuilt = Vec::from_parts(p, len, cap); assert_eq!(rebuilt, [4, 5, 6]); } ``` ```rust use std::alloc::{alloc, Layout}; use std::ptr::NonNull; fn main() { let layout = Layout::array::(16).expect("16 u32s take 64 bytes, so it shouldn't overflow"); let vec = unsafe { let Some(mem) = NonNull::new(alloc(layout).cast::()) else { return; }; mem.write(1_000_000); Vec::from_parts(mem, 1, 16) }; assert_eq!(vec, &[1_000_000]); assert_eq!(vec.capacity(), 16); } ``` -------------------------------- ### Test PTC threshold behavior Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/temporal_photonics/photonic_time_crystal.rs.html Example test setup for a PhotonicTimeCrystal instance. ```rust fn default_ptc() -> PhotonicTimeCrystal { PhotonicTimeCrystal { eps0: 2.25, // n₀ = 1.5 delta_eps: 0.5, omega_mod: 4e14, // Ω_m = 2ω₀ with ω₀ = 2×10¹⁴ loss_rate: 1e10, } } #[test] fn ptc_above_threshold() { let ptc = default_ptc(); ``` -------------------------------- ### iter_mut example: mutating the Ok value via iterator Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows how to use iter_mut to get a mutable iterator over the possibly contained value. The example mutates the Ok value to 40. ```rust let mut x: Result = Ok(7); match x.iter_mut().next() { Some(v) => *v = 40, None => {}, } assert_eq!(x, Ok(40)); let mut x: Result = Err("nothing!"); assert_eq!(x.iter_mut().next(), None); ``` -------------------------------- ### NanopostLibrary::new constructor Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/devices/metalens/nanopost.rs.html Initializes a new NanopostLibrary using an analytic waveguide phase model. This is an approximation; accurate results for specific designs should use RCWA. ```rust pub fn new(pitch: f64, height: f64, n_post: f64, n_sub: f64, wavelength: f64) -> Self { let n_pts = 50; let d_min = 0.05 * pitch; let d_max = 0.85 * pitch; let k0 = 2.0 * PI / wavelength; let diameters: Vec = (0..n_pts) .map(|i| d_min + (d_max - d_min) * i as f64 / (n_pts - 1) as f64) .collect(); let phase: Vec = diameters .iter() .map(|&d| { // Approximate n_eff via EIM for a cylindrical post: // Fill fraction f = π(d/2)²/Λ² let f = PI * (d / 2.0).powi(2) / (pitch * pitch); let f = f.clamp(0.0, 0.95); let n_eff = (f * n_post * n_post + (1.0 - f) * n_sub * n_sub).sqrt(); // Phase accumulation let phi = k0 * (n_eff - n_sub) * height; phi.rem_euclid(2.0 * PI) }) .collect(); // Assume high transmission (simplified model) let transmittance = vec![0.95; n_pts]; Self { pitch, height, n_post, n_sub, n_sup: 1.0, wavelength, diameters, transmittance, phase, } } ``` -------------------------------- ### iter example: iterating over Ok value Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows how to use iter to get an iterator over the possibly contained value. The iterator yields one value if Ok, otherwise none. ```rust let x: Result = Ok(7); assert_eq!(x.iter().next(), Some(&7)); let x: Result = Err("nothing!"); assert_eq!(x.iter().next(), None); ``` -------------------------------- ### Initialize MemosFabryPerot and Calculate Pull-in Voltage Source: https://docs.rs/oxiphoton/latest/oxiphoton/mems/fabry_perot_mems/struct.MemosFabryPerot.html Example showing how to instantiate a MemosFabryPerot object and calculate its pull-in voltage. ```rust use oxiphoton::mems::fabry_perot_mems::MemosFabryPerot; let mut fp = MemosFabryPerot::new(5e-6, 0.95, 0.95, 50.0, 100e-12); let vpi = fp.pull_in_voltage(); assert!(vpi > 0.0); ``` -------------------------------- ### MemosTiltMirror example: construction and Lissajous scan Source: https://docs.rs/oxiphoton/latest/oxiphoton/mems/mems_mirror/struct.MemosTiltMirror.html Shows how to construct a MemosTiltMirror and call scan_lissajous to get instantaneous scan angles. The assertion verifies the fast-axis angle stays within the configured maximum. ```rust use oxiphoton::mems::mems_mirror::MemosTiltMirror; let m = MemosTiltMirror::new(1e-3, 1000.0, 500.0, 200.0, 150.0); let [tx, ty] = m.scan_lissajous(0.0, 1.5); assert!((tx).abs() < m.max_angle_x + 1e-10); ``` -------------------------------- ### Test optical damping with blue detuning (incomplete) Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/optical_force/optomechanics.rs.html Starts testing blue-detuned driving (Δ = +Ω_m) for optical damping, which should lead to amplification. The snippet is incomplete in the source, showing only the setup and comment. ```rust let cav = standard_cavity(); let n_bar = 1000.0; // Blue detuning Δ = +Ω_m → amplification ``` -------------------------------- ### ThzWaveguide::new Source: https://docs.rs/oxiphoton/latest/oxiphoton/thz/tds/struct.ThzWaveguide.html General constructor for creating a ThzWaveguide instance with specified width, length, guide type, and material index. ```APIDOC ## ThzWaveguide::new ### Description General constructor for creating a ThzWaveguide instance. ### Method Constructor ### Signature pub fn new(width_mm: f64, length_mm: f64, guide_type: ThzGuideType, material_index: f64) -> Self ### Parameters - **width_mm** (f64) - Required - Primary transverse dimension (plate separation or inner width) in mm. - **length_mm** (f64) - Required - Guide axial length in mm. - **guide_type** (ThzGuideType) - Required - Geometry and secondary dimensions. - **material_index** (f64) - Required - Refractive index of the filling medium (1.0 for air). ### Returns - **Self** - A new ThzWaveguide instance. ``` -------------------------------- ### Get effective index for LP_{l,m} mode Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/sdm/lp_modes.rs.html Returns the effective index of a specific LP_{l,m} mode by searching the modes found by `find_modes()`. Returns `None` if the mode is not guided at the current V number. ```rust let modes = self.find_modes(); modes .iter() .find(|md| md.l == l && md.m == m) .map(|md| md.n_eff) ``` -------------------------------- ### ok example Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Demonstrates converting a Result to an Option, returning Some(value) for Ok and None for Err. ```rust let x: Result = Ok(2); assert_eq!(x.ok(), Some(2)); let x: Result = Err("Nothing here"); assert_eq!(x.ok(), None); ``` -------------------------------- ### Initialize BeamQuality and calculate parameters Source: https://docs.rs/oxiphoton/latest/oxiphoton/beam_quality/index.html Demonstrates how to instantiate the BeamQuality struct with wavelength, M² factor, waist size, and position, then calculate the Rayleigh range and Beam Parameter Product (BPP). ```rust use oxiphoton::beam_quality::m2_factor::BeamQuality; // 1064 nm beam with M² = 1.3, 0.5 mm waist at z = 0 let bq = BeamQuality::new(1064e-9, 1.3, 0.5e-3, 0.0); println!("Rayleigh range: {:.3} mm", bq.rayleigh_range_m() * 1e3); println!("BPP: {:.3} mm·mrad", bq.beam_parameter_product() * 1e6); ``` -------------------------------- ### Get a raw pointer to the Vec buffer with as_ptr Source: https://docs.rs/oxiphoton/latest/oxiphoton/smatrix/eigenmode/type.CMatrix.html Returns a raw pointer to the vector's buffer. The caller must ensure the vector outlives the pointer and that the memory is not written to (except inside `UnsafeCell`). This example reads elements through the pointer. ```rust let x = vec![1, 2, 4]; let x_ptr = x.as_ptr(); unsafe { for i in 0..x.len() { assert_eq!(*x_ptr.add(i), 1 << i); } } ``` -------------------------------- ### Create MimWaveguide with new constructor Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/plasmonics/spp.rs.html Constructs a MimWaveguide from a DrudeMetal, insulator thickness in nanometers, and insulator permittivity. ```rust impl MimWaveguide { pub fn new(metal: DrudeMetal, thickness_nm: f64, eps_ins: f64) -> Self { Self { metal, insulator_thickness_nm: thickness_nm, eps_insulator: eps_ins, } } ``` -------------------------------- ### strip_waveguide_eim: Effective Index Method for 2D strip waveguide Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/mode/effective_index.rs.html Implements the Effective Index Method (EIM) for a 2D strip waveguide. It first solves the vertical slab (height H) to get n_eff_v, then uses that as the core index for the horizontal slab (width W). Returns None if the vertical mode is not guided (n_eff_v <= n_clad). ```rust pub fn strip_waveguide_eim( n_core: f64, n_clad: f64, width: f64, height: f64, wavelength: f64, pol: Polarization, ) -> Option { let vert = SlabWaveguide::new(n_core, n_clad, height); let vert_modes = vert.solve_modes(wavelength, pol); let n_eff_v = vert_modes.first()?.n_eff; if n_eff_v <= n_clad { return None; } let horiz = SlabWaveguide::new(n_eff_v, n_clad, width); let horiz_modes = horiz.solve_modes(wavelength, pol); Some(horiz_modes.first()?.n_eff) } ``` -------------------------------- ### compute_modes: Power-iteration BPM for guided modes Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/bpm/fd_bpm.rs.html Computes the n_modes lowest-order modes of the current index profile using imaginary-distance BPM. Each mode starts with a Hermite-Gaussian trial field, orthogonalizes against previously found modes via Gram-Schmidt, iterates 200 imaginary steps, and estimates effective index from phase accumulation. The effective index is clamped to [1.0, 5.0]. ```rust pub fn compute_modes(&self, n_modes: usize) -> Vec { let nx = self.inner.nx; let dx = self.inner.dx; let wavelength = self.inner.wavelength; let n_ref = self.inner.n_ref; // Use imaginary propagation (imag-distance BPM) to find modes. // For each mode order, start with a trial Hermite-Gaussian and // iterate until convergence. let mut modes: Vec = Vec::with_capacity(n_modes); let xc = nx as f64 * dx / 2.0; for order in 0..n_modes { // Trial field: Hermite-Gaussian of the appropriate order let mut trial: Vec = (0..nx) .map(|i| { let x = i as f64 * dx - xc; let w = dx * nx as f64 / 8.0; let h = hermite_polynomial(order, x / w); let env = (-x * x / (2.0 * w * w)).exp(); Complex64::new(h * env, 0.0) }) .collect(); // Orthogonalise against already-found modes (Gram-Schmidt) for prev in &modes { let overlap = inner_product(&trial, &prev.field, dx); for (ti, pi) in trial.iter_mut().zip(prev.field.iter()) { *ti -= overlap * pi; } } // Normalise normalise_field(&mut trial, dx); // Imaginary-distance BPM iterations let n_iter = 200; let idz = -dx * 10.0; // imaginary step for _iter in 0..n_iter { let mut bpm_iter = FdBpm1d::new(nx, dx, n_ref, wavelength); if let Some(ref np) = self.inner.n_profile { bpm_iter.set_index_profile(np.clone()); } bpm_iter.set_field(trial.clone()); // One imaginary step: multiply diagonal phase by exp(dz·H) // For imaginary propagation, use a real dz with sign flipped bpm_iter.step(idz.abs()); trial = bpm_iter.field; // Re-orthogonalise for prev in &modes { let overlap = inner_product(&trial, &prev.field, dx); for (ti, pi) in trial.iter_mut().zip(prev.field.iter()) { *ti -= overlap * pi; } } normalise_field(&mut trial, dx); } // Estimate effective index from phase accumulation let k0 = 2.0 * PI / wavelength; let phase_avg: f64 = trial.iter().map(|e| e.arg() * e.norm_sqr()).sum::() / trial.iter().map(|e| e.norm_sqr()).sum::().max(1e-30); let n_eff = n_ref + phase_avg / (k0 * idz.abs() * n_iter as f64); let n_eff = n_eff.clamp(1.0, 5.0); modes.push(ModeField { field: trial, n_eff, order, }); } modes } ``` -------------------------------- ### Quick start with OpticalOrthogonalCode Source: https://docs.rs/oxiphoton/latest/oxiphoton/optical_cdma/index.html Demonstrates initializing an Optical Orthogonal Code (OOC) with specific parameters and generating the corresponding codewords. ```rust use oxiphoton::optical_cdma::spreading_codes::OpticalOrthogonalCode; let ooc = OpticalOrthogonalCode::new(13, 3, 1, 1); println!("Max codewords: {}", ooc.max_codewords()); // 2 let codes = ooc.generate_codes(); assert_eq!(codes.len(), 2); ``` -------------------------------- ### Initialize WgmMicroresonator Source: https://docs.rs/oxiphoton/latest/oxiphoton/mems/coupling/struct.WgmMicroresonator.html Example of creating a new WgmMicroresonator instance and verifying its free spectral range. ```rust use oxiphoton::mems::coupling::WgmMicroresonator; let wgm = WgmMicroresonator::new(50e-6, 1.44, 1550e-9); assert!(wgm.free_spectral_range() > 1e11); ``` -------------------------------- ### Example usage of irradiance_from_e_field Source: https://docs.rs/oxiphoton/latest/oxiphoton/units/field/fn.irradiance_from_e_field.html A basic example demonstrating how to call the function and verify the output is positive. ```rust use oxiphoton::units::field::irradiance_from_e_field; let i = irradiance_from_e_field(1e6, 1.0); assert!(i > 0.0); ``` -------------------------------- ### Pre-configured NanopostLibrary instances Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/devices/metalens/nanopost.rs.html Convenience methods for creating common metalens material systems. ```rust /// TiO₂ nanopost on glass at 532 nm (visible metalens). /// /// Pitch = 350 nm, height = 600 nm, n_TiO₂ ≈ 2.35 at 532 nm. pub fn tio2_532nm() -> Self { Self::new(350e-9, 600e-9, 2.35, 1.46, 532e-9) } /// GaN nanopost at 405 nm (UV-vis metalens). /// /// Pitch = 280 nm, height = 500 nm, n_GaN ≈ 2.55. pub fn gan_405nm() -> Self { Self::new(280e-9, 500e-9, 2.55, 1.46, 405e-9) } /// Si nanopost at 1550 nm (NIR metalens). /// /// Pitch = 700 nm, height = 600 nm, n_Si ≈ 3.48. pub fn si_1550nm() -> Self { Self::new(700e-9, 600e-9, 3.48, 1.46, 1550e-9) } ``` -------------------------------- ### VTK legacy format example output Source: https://docs.rs/oxiphoton/latest/oxiphoton/io/vtk/index.html An example of the VTK legacy ASCII format structure used for FDTD field visualization. ```text # vtk DataFile Version 3.0 OxiPhoton FDTD Ez field ASCII DATASET STRUCTURED_POINTS DIMENSIONS 100 100 1 ORIGIN 0 0 0 SPACING 10e-9 10e-9 1 POINT_DATA 10000 SCALARS Ez float 1 LOOKUP_TABLE default 0.0 0.1 0.2 ... ``` -------------------------------- ### WavelengthSweep usage example Source: https://docs.rs/oxiphoton/latest/oxiphoton/fdtd/sweep/parameter/struct.WavelengthSweep.html Shows how to create a WavelengthSweep and verify the generated wavelengths in nanometres. ```rust use oxiphoton::fdtd::sweep::parameter::WavelengthSweep; let sweep = WavelengthSweep::new(1000.0, 1600.0, 61); let lambdas_nm = sweep.wavelengths_nm(); assert!((lambdas_nm[0] - 1000.0).abs() < 1e-9); assert!((lambdas_nm[60] - 1600.0).abs() < 1e-9); ``` -------------------------------- ### Quick Example: MachZehnderInterferometer symmetric() Source: https://docs.rs/oxiphoton/latest/oxiphoton/pic_simulation/circuit_elements/index.html Creates a symmetric Mach-Zehnder interferometer and verifies that the sum of through and cross transmissions equals 1 within 1e-10, confirming energy conservation. ```rust use oxiphoton::pic_simulation::circuit_elements::{DirectionalCoupler, MachZehnderInterferometer}; let mzi = MachZehnderInterferometer::symmetric(); let t_through = mzi.through_transmission(); let t_cross = mzi.cross_transmission(); assert!((t_through + t_cross - 1.0).abs() < 1e-10); ``` -------------------------------- ### ParamSweep usage example with linspace and run Source: https://docs.rs/oxiphoton/latest/oxiphoton/fdtd/sweep/parameter/struct.ParamSweep.html Shows how to create a linearly-spaced sweep and run it with a closure, collecting results. ```rust use oxiphoton::fdtd::sweep::parameter::ParamSweep; let sweep = ParamSweep::linspace("gap_nm", 50.0, 500.0, 10); let results: Vec = sweep.run(|g| g * g); assert_eq!(results.len(), 10); ``` -------------------------------- ### map example Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows applying a function to the Ok value of a Result, leaving Err untouched. Example prints doubled numbers from each line of a string. ```rust let line = "1\n2\n3\n4\n"; for num in line.lines() { match num.parse::().map(|i| i * 2) { Ok(n) => println!("{n}"), Err(..) => {} } } ``` -------------------------------- ### Test HBT Setup Calculations Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/single_photon/photon_statistics.rs.html Validates HBT setup accidental rates, coincidence rates for ideal SPE, and corrected g²(0) calculations. ```rust #[test] fn test_hbt_accidentals_positive() { let hbt = HbtSetup::new(0.5, 50.0); let acc = hbt.accidental_rate(1e6); assert!(acc > 0.0, "Accidental rate must be positive; got {acc}"); } #[test] fn test_hbt_coincidences_zero_for_ideal_spe() { let hbt = HbtSetup::new(0.5, 50.0); let r_c = hbt.coincidence_rate(1e6, 0.0); // g²(0) = 0 → only dark count contribution (very small) assert!(r_c < 1.0, "Coincidences should be near zero for ideal SPE"); } #[test] fn test_hbt_corrected_g2_sensible() { let hbt = HbtSetup::new(0.5, 50.0); // If measured and lateral coincidences are equal → g²(0) = 1 let g2_c = hbt.g2_zero_corrected(100.0, 100.0); assert!( (g2_c - 1.0).abs() < 0.01, "Corrected g²(0) should be 1 for equal peaks" ); } ``` -------------------------------- ### new Source: https://docs.rs/oxiphoton/latest/oxiphoton/optical_computing/photonic_nn/struct.PhotonicNeuralNetwork.html Build a network with given layer sizes and activations. The layer_sizes length is L+1 and activations length is L. ```APIDOC ## new ### Description Build a network with given layer sizes and activations. The layer_sizes length is L+1 and activations length is L. ### Method new ### Signature pub fn new(layer_sizes: &[usize], activations: Vec) -> Self ### Parameters - `layer_sizes` (&[usize]) - Required - Layer sizes, length L+1. - `activations` (Vec) - Required - Activation functions, length L. ### Returns Self - A new PhotonicNeuralNetwork instance. ``` -------------------------------- ### OxirsConnection SPARQL Query Example Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/io/oxirs_bridge.rs.html Demonstrates how to initialize an OxirsConnection and perform a SPARQL query. This requires the `io-oxirs` feature flag. ```rust # #[cfg(feature = "io-oxirs")] let conn = OxirsConnection::new("http://localhost:3030/dataset/sparql"); let rows = conn.query("SELECT * WHERE { ?s ?p ?o } LIMIT 10")?; ``` -------------------------------- ### OpticalWaveBreaking broadening factor setup Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/fiber/supercontinuum.rs.html Constructs an OpticalWaveBreaking instance with gamma=20e-27, beta2=1.3e-3, pulse width=1e-12, and peak power=100.0. This is the setup for the broadening factor test. ```rust let owb = OpticalWaveBreaking::new(20e-27, 1.3e-3, 1e-12, 100.0); ``` -------------------------------- ### VectorBpm1d initialization and propagation Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/bpm/vector_bpm.rs.html Examples for initializing the VectorBpm1d solver, setting birefringence, and propagating fields. ```rust #[test] fn vector_bpm_new_signature_two_args() { // new(n_x, dx, wavelength) — no n_ref argument let bpm = VectorBpm1d::new(64, 1e-6, 1550e-9); assert_eq!(bpm.n_x, 64); assert!((bpm.wavelength - 1550e-9).abs() < 1e-20); } ``` ```rust #[test] fn vector_bpm_set_birefringence_slice() { let mut bpm = VectorBpm1d::new(64, 1e-6, 1550e-9); let dn = vec![0.005; 64]; bpm.set_birefringence(&dn); assert!((bpm.birefringence[0] - 0.005).abs() < 1e-12); } ``` ```rust #[test] fn vector_bpm_propagate_dz_preserves_power() { let mut bpm = VectorBpm1d::new(128, 0.25e-6, 1550e-9); let x0 = 128_f64 / 2.0 * 0.25e-6; let w0 = 5e-6; let mut ex: Vec = (0..128) .map(|i| { let x = i as f64 * 0.25e-6; let d = x - x0; Complex64::new((-d * d / (w0 * w0)).exp(), 0.0) }) .collect(); let mut ey: Vec = vec![Complex64::new(0.0, 0.0); 128]; let p_in: f64 = ex.iter().map(|c| c.norm_sqr()).sum::() * 0.25e-6; bpm.propagate_dz(&mut ex, &mut ey, 1.5, 2e-6); } ``` -------------------------------- ### StepIndexFiberModes Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/sdm/lp_modes.rs.html Provides methods to compute V-number, numerical aperture, approximate guided mode count, and to find all guided LP modes in a step-index fiber. ```APIDOC ## StepIndexFiberModes ### Description Solves the characteristic equation for LP modes in a step-index fiber, returning guided modes with effective indices and cutoff V-numbers. ### Constructor `StepIndexFiberModes::new(core_um: f64, n_core: f64, n_clad: f64, wavelength: f64) -> Self` ### Methods #### `v_number(&self) -> f64` Computes the V-number: V = 2π·a·NA/λ. #### `numerical_aperture(&self) -> f64` Computes the numerical aperture: NA = sqrt(n1² − n2²). #### `n_guided_modes(&self) -> usize` Approximates the number of guided modes: N ≈ V²/2. #### `find_modes(&self) -> Vec` Finds all guided LP modes via bisection on the characteristic equation, returning a vector of `LpMode` structs sorted by effective index descending. ### Fields - `core_radius_um` (f64) - Core radius in micrometres. - `n_core` (f64) - Core refractive index n₁. - `n_clad` (f64) - Cladding refractive index n₂. - `wavelength` (f64) - Free-space wavelength in metres. ### Characteristic Equation For mode LP_{l,m}: u · J_{l-1}(u) · K_l(w) + w · K_{l-1}(w) · J_l(u) = 0 where: - u² + w² = V² - u = a · sqrt(k0²·n1² − β²) - w = a · sqrt(β² − k0²·n2²) ### Return Value `Vec` containing modes with fields `l`, `m`, `n_eff`, and `cutoff_v`. ``` -------------------------------- ### power_iteration_dominant: solve dominant guided mode via power iteration Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/mode/fem_solver.rs.html Solves for the dominant guided mode (highest β²) using power iteration with a shift by beta_sq_lo. Returns None if the initial norm is below 1e-30 or if no guided mode is found after max_iter iterations. The code is truncated at the Rayleigh quotient step in the source. ```rust fn power_iteration_dominant( a_mat: &[f64], n: usize, beta_sq_lo: f64, max_iter: usize, tol: f64, ) -> Option<(f64, Vec)> { use std::f64; // Shift the matrix so the largest eigenvalue of (A - shift·I) is the guided mode // We shift by beta_sq_lo to make guided modes have positive eigenvalues let shift = beta_sq_lo; // Initial random-ish unit vector (use a fixed pattern to be deterministic) let mut v: Vec = (0..n).map(|i| ((i + 1) as f64).sin()).collect(); let norm0: f64 = v.iter().map(|&x| x * x).sum::().sqrt(); if norm0 < 1e-30 { return None; } for vi in &mut v { *vi /= norm0; } let mut lambda_old = f64::NEG_INFINITY; let mut w = vec![0.0f64; n]; for _ in 0..max_iter { // w = (A - shift·I)·v for i in 0..n { let diag = a_mat[i * n + i] - shift; w[i] = diag * v[i]; if i > 0 { w[i] += a_mat[i * n + (i - 1)] * v[i - 1]; } if i + 1 < n { w[i] += a_mat[i * n + (i + 1)] * v[i + 1]; } } // Rayleigh quotient: λ = v^T·w / v^T·v } ``` -------------------------------- ### Vec::from_raw_parts_in examples (allocator_api) Source: https://docs.rs/oxiphoton/latest/oxiphoton/smatrix/eigenmode/type.CMatrix.html Two examples for the nightly-only `allocator_api` feature. The first shows reconstructing a `Vec` from parts obtained via `into_raw_parts_with_allocator`, overwriting memory with `ptr::write` and then rebuilding with `Vec::from_raw_parts_in`. The second shows using memory allocated directly with `Global.allocate`, writing a value, and constructing a `Vec` from that raw pointer. Both require `#![feature(allocator_api)]` and the `std::alloc` items shown. ```rust #![feature(allocator_api)] use std::alloc::System; use std::ptr; let mut v = Vec::with_capacity_in(3, System); v.push(1); v.push(2); v.push(3); // Deconstruct the vector into parts. let (p, len, cap, alloc) = v.into_raw_parts_with_allocator(); unsafe { // Overwrite memory with 4, 5, 6 for i in 0..len { ptr::write(p.add(i), 4 + i); } // Put everything back together into a Vec let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); assert_eq!(rebuilt, [4, 5, 6]); } ``` ```rust #![feature(allocator_api)] use std::alloc::{AllocError, Allocator, Global, Layout}; fn main() { let layout = Layout::array::(16).expect("16 u32s take 64 bytes, so it shouldn't overflow"); let vec = unsafe { let mem = match Global.allocate(layout) { Ok(mem) => mem.cast::().as_ptr(), Err(AllocError) => return, }; mem.write(1_000_000); Vec::from_raw_parts_in(mem, 1, 16, Global) }; assert_eq!(vec, &[1_000_000]); assert_eq!(vec.capacity(), 16); } ``` -------------------------------- ### OpticalSystem::new Source: https://docs.rs/oxiphoton/latest/oxiphoton/ray/tracer/struct.OpticalSystem.html Creates a new empty OpticalSystem instance. ```APIDOC ## OpticalSystem::new ### Description Creates a new empty OpticalSystem instance. ### Method new ### Signature pub fn new() -> Self ### Parameters None ### Returns - **Self** - A new OpticalSystem instance. ``` -------------------------------- ### Example usage of skin_depth Source: https://docs.rs/oxiphoton/latest/oxiphoton/units/electromagnetic/fn.skin_depth.html Example Rust code that imports `skin_depth` and calculates the skin depth for copper at 1 GHz, asserting the result is within the expected range. ```rust use oxiphoton::units::electromagnetic::skin_depth; // Copper: σ≈5.8e7 S/m, μ_r=1, f=1 GHz → δ ≈ 2.1 µm let delta = skin_depth(5.8e7, 1.0, 1e9); assert!(delta > 1e-6 && delta < 5e-6); ``` -------------------------------- ### Initialize DftMonitor3d Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/fdtd/monitor/dft.rs.html Demonstrates the instantiation of a 3D DFT monitor with a specific region, field component, and frequency list. ```rust #[test] fn dft_monitor_3d_new() { let mon = DftMonitor3d::new( MonitorRegion3d::SliceXY { k: 4 }, FieldComp3d::Ex, vec![100e12, 200e12], 1e-17, 8, 8, 8, ); assert_eq!(mon.n_frequencies(), 2); assert_eq!(mon.n_cells, 8 * 8); assert_eq!(mon.n_samples, 0); } ``` -------------------------------- ### TimeRefraction Usage: TemporalInterface Example Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/temporal_photonics/mod.rs.html Use `TemporalInterface` with `n_before`, `n_after`, and `omega_incident` to verify k-conservation during sudden index change. The `verify_k_conservation()` method returns a boolean; the example asserts it. ```rust use oxiphoton::temporal_photonics::time_refraction::TemporalInterface; let ti = TemporalInterface { n_before: 1.5, n_after: 2.0, omega_incident: 2e15 }; assert!(ti.verify_k_conservation()); ``` -------------------------------- ### LinkBudget summary and required_tx_power methods Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/interconnect/link.rs.html Defines `LinkBudget` with a `summary` method that returns a formatted string of the optical link budget, and a `required_tx_power` method that computes the required TX power for a positive margin. ```rust pub struct LinkBudget { pub link: OpticalLink, } impl LinkBudget { pub fn new(link: OpticalLink) -> Self { Self { link } } /// Print a human-readable budget summary (returns as String). pub fn summary(&self) -> String { let l = &self.link; let mut s = String::new(); s.push_str("=== Optical Link Budget ===\n"); s.push_str(&format!("TX Power: {:+.1} dBm\n", l.tx_power_dbm)); s.push_str(&format!( "WG Propagation: -{:.1} dB ({:.1}mm × {:.1}dB/cm)\n", l.propagation_loss_db(), l.wg_length_m * 1e3, l.wg_loss_db_per_m / 100.0 )); for e in &l.elements { s.push_str(&format!(" {:25} -{:.1} dB\n", e.name, e.loss_db)); } s.push_str(&format!("Total Loss: -{:.1} dB\n", l.total_loss_db())); s.push_str(&format!( "RX Power: {:+.1} dBm\n", l.received_power_dbm() )); s.push_str(&format!( "RX Sensitivity: {:+.1} dBm\n", l.rx_sensitivity_dbm )); s.push_str(&format!( "System Margin: -{:.1} dB\n", l.system_margin_db )); s.push_str(&format!( "Link Margin: {:+.1} dB {}\n", l.link_margin_db(), if l.is_feasible() { "(PASS)" } else { "(FAIL)" } )); s } /// Required TX power (dBm) for positive margin with current elements. pub fn required_tx_power(&self) -> f64 { let l = &self.link; l.rx_sensitivity_dbm + l.total_loss_db() + l.system_margin_db } } ``` -------------------------------- ### GNLSE lossless power conservation setup Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/fiber/supercontinuum.rs.html Sets up a lossless GNLSE solver with no Raman or SPM, creates a Gaussian pulse, and computes the input power. This is the beginning of a power conservation test. ```rust let mut solver = GnlseSolver::new_silica(0.1, 0.0, -20e-27, 0.0); solver.alpha = 0.0; solver.raman_fraction = 0.0; let n = solver.n_time_points; // Gaussian pulse at centre let t0 = 50e-15; let field: Vec = (0..n) .map(|i| { let t = (i as f64 - n as f64 / 2.0) * solver.dt; Complex64::new((-0.5 * (t / t0).powi(2)).exp(), 0.0) }) .collect(); let power_in: f64 = field.iter().map(|a| a.norm_sqr()).sum::() * solver.dt; ``` -------------------------------- ### Usage example: convert 1 mW to dBm Source: https://docs.rs/oxiphoton/latest/oxiphoton/units/conversion/fn.watts_to_dbm.html Example usage of `watts_to_dbm` to convert 1 mW (0.001 W) to 0 dBm, with an assertion that the result is near zero. ```rust use oxiphoton::units::conversion::watts_to_dbm; let dbm = watts_to_dbm(1e-3); // 1 mW = 0 dBm assert!(dbm.abs() < 1e-10); ``` -------------------------------- ### Quick-start: Calculate BER from Q-factor Source: https://docs.rs/oxiphoton/latest/oxiphoton/comms/index.html Shows how to use BerCalculator::ber_from_q to compute bit error rate from a Q-factor value. The example asserts that a Q of 6.0 yields a BER below 1e-8. ```rust use oxiphoton::comms::metrics::BerCalculator; let ber = BerCalculator::ber_from_q(6.0); assert!(ber < 1e-8); ``` -------------------------------- ### Example: is_ok_and() on Result Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Returns true if the result is Ok and the value inside matches a predicate. The example also shows using as_ref() to avoid moving the value. ```rust let x: Result = Ok(2); assert_eq!(x.is_ok_and(|x| x > 1), true); let x: Result = Ok(0); assert_eq!(x.is_ok_and(|x| x > 1), false); let x: Result = Err("hey"); assert_eq!(x.is_ok_and(|x| x > 1), false); let x: Result = Ok("ownership".to_string()); assert_eq!(x.as_ref().is_ok_and(|x| x.len() > 1), true); println!("still alive {:?}", x); ``` -------------------------------- ### new Source: https://docs.rs/oxiphoton/latest/oxiphoton/interconnect/network/struct.PhotonicTopology.html Creates an empty topology. Initializes a new PhotonicTopology with no nodes or edges. ```APIDOC ## pub fn new() -> Self ### Description Creates a new empty PhotonicTopology instance. ### Method pub fn new() -> Self ### Parameters None ### Returns A new PhotonicTopology with empty node and edge lists, and default loss set to the default value. ``` -------------------------------- ### new Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/photonic_antenna/phased_array.rs.html Constructs a 2D OPA with all phases set to zero. ```APIDOC ## new ### Description Constructs a 2D OPA with all phases set to zero. ### Method new ### Parameters - **nx** (usize) - Required - Number of columns (x-direction) - **ny** (usize) - Required - Number of rows (y-direction) - **pitch_x_m** (f64) - Required - Pitch in x (m) - **pitch_y_m** (f64) - Required - Pitch in y (m) - **wavelength_m** (f64) - Required - Free-space wavelength (m) ### Returns - **OpticalPhasedArray2d** - New 2D OPA instance ``` -------------------------------- ### unwrap() on Ok and Err Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows the behavior of `unwrap` on `Ok` and `Err` values. The first example asserts the returned value for an `Ok`. The second example demonstrates the panic message when called on an `Err`. ```rust let x: Result = Ok(2); assert_eq!(x.unwrap(), 2); ``` ```rust let x: Result = Err("emergency failure"); x.unwrap(); // panics with `emergency failure` ``` -------------------------------- ### Test dispersion monotone in silicon Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/mode/fem_solver.rs.html Tests dispersion monotonicity for a strongly guided Si/SiO2 waveguide. Verifies n_eff stays within the guiding range (1.44 to 3.48) across the wavelength range. ```rust let solver = si_sio2_slab(); let disp = solver.compute_dispersion(1, 3, (1450e-9, 1650e-9), 1.44); if disp.is_empty() || disp[0].len() < 2 { return; } // n_eff should be in the guiding range at all wavelengths for &neff in &disp[0] { assert!(neff > 1.44 && neff < 3.48, "n_eff={neff} out of range"); } ``` -------------------------------- ### Initialize Photofrin PDT parameters Source: https://docs.rs/oxiphoton/latest/src/oxiphoton/biophotonics/tissue.rs.html Creates a new instance with standard Photofrin parameters at 630 nm. ```rust pub fn photofrin_630nm(irradiance_mw: f64) -> Self { Self::new( TissueOpticalProperties::skin_dermis_630nm(), 2.0, // 2 μM photosensitizer concentration 1170.0, // M⁻¹cm⁻¹ 0.89, // singlet oxygen quantum yield irradiance_mw, ) } ``` -------------------------------- ### expect recommended message style example Source: https://docs.rs/oxiphoton/latest/oxiphoton/error/type.Result.html Shows the recommended style for expect messages: describe the reason you expect the Result to be Ok, focusing on the word 'should'. ```rust let path = std::env::var("IMPORTANT_PATH") .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); ``` -------------------------------- ### insert_mut example Source: https://docs.rs/oxiphoton/latest/oxiphoton/smatrix/eigenmode/type.CMatrix.html Demonstrates `insert_mut` on a `Vec` of integers. The method inserts the element at the given index and returns a mutable reference to it; the example increments the inserted value through that reference. The assertion verifies the final vector. ```rust let mut vec = vec![1, 3, 5, 9]; let x = vec.insert_mut(3, 6); *x += 1; assert_eq!(vec, [1, 3, 5, 7, 9]); ```