%% ============================================================ % IM/DD Fading Notch Design Map % Shows λ_null vs. bandwidth (f_target) and fiber length (L) % ============================================================ clear; close all; clc; %% Parameters lambda0 = 1310e-9; % Zero-dispersion wavelength [m] S0 = 0.08; % Dispersion slope at ZDW [ps/(nm²·km)] c = physconst('lightspeed'); % Frequency and length sweep f_targets = linspace(20e9, 140e9, 80); % [Hz] → x-axis L_values = linspace(0.5e3, 12e3, 80); % [m] → y-axis % Preallocate result matrices lambda_surface = zeros(numel(L_values), numel(f_targets)); Dacc_surface = zeros(numel(L_values), numel(f_targets)); %% Compute λ_null and Dacc for each (f_target, L) for iL = 1:numel(L_values) L = L_values(iL); [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0); lambda_surface(iL, :) = lambda_vec; % [m] Dacc_surface(iL, :) = Dacc_vec; % [ps/nm] end %% Convert to display units lambda_surface_nm = lambda_surface * 1e9; % [nm] L_km = L_values / 1000; % [km] f_GHz = f_targets / 1e9; % [GHz] %% ------------------------------------------------------------ % Contour plot (λ_null as function of f_null and L) % ------------------------------------------------------------ figure('Color','w'); % Define wavelength contour levels [nm] lambda_levels = [1260:10:1290, 1290:5:1300, 1300:2:1310]; contourf(f_GHz, L_km, lambda_surface_nm, lambda_levels, ... 'LineWidth', 1.5, ... 'ShowText', 'on', ... 'LabelFormat', '%1.1d nm'); % Colormap and colorbar colormap(flip(cbrewer2('RdYlGn',100))); clim([1260 1310]); % c = colorbar; % ylabel(c, 'λ_{null} [nm]', 'Rotation', 90); % Axis formatting xlabel('Signal Bandwidth [GHz]'); ylabel('Fiber length L [km]'); % X-axis ticks (every 16 GHz starting at 56 GHz) xticks(56:8:120); xlim([56,120]) grid on; box on; %% Optional overlay: accumulated dispersion contours hold on; [CS, h] = contour(f_GHz, L_km, Dacc_surface, 10, 'k--', 'LineWidth', 0.8); clabel(CS, h, 'Color','k', 'FontSize',8); legend('λ_{null} contours','|D_{acc}| [ps/nm]','Location','best'); %% ============================================================ % Helper function: lambda_for_first_null_full % Stable, single-branch, clamped to O-band % ============================================================ function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0) c = physconst('lightspeed'); S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³) % Define O-band boundaries (in meters) lambda_min = 1260e-9; lambda_max = 1360e-9; % Force column vector f_target = f_target(:); N = numel(f_target); lambda_vec = zeros(N,1); Dacc_vec = zeros(N,1); for k = 1:N RHS = c * 0.5 / (f_target(k)^2 * L); % Normal-dispersion branch (λ < λ0) fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS; % Solve within the normal-dispersion range try lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]); catch lambda_sol = lambda_min; end % Clamp to O-band range lambda_sol = min(max(lambda_sol, lambda_min), lambda_max); lambda_vec(k) = lambda_sol; % Compute D(lambda) and accumulated dispersion D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km) Dacc_val = D_lambda * (L/1000); % ps/nm % Clamp to physical range Dacc_val = min(max(Dacc_val, -100), 100); Dacc_vec(k) = Dacc_val; end end