Merge branch 'main' of cau-git.rz.uni-kiel.de:nt/mitarbeiter/silas/imdd_simulation

This commit is contained in:
Silas Oettinghaus
2026-03-25 10:26:59 +01:00
46 changed files with 3112 additions and 622 deletions

View File

@@ -0,0 +1,68 @@
%% ============================================================
% IM/DD Power Fading Evolution GIF (1 km -> 20 km)
% Uses the provided GifWriter (serial mode)
% ============================================================
clear; close all; clc;
%% Fiber and system parameters
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
lambda = 1275e-9; % operating wavelength [m]
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
c = physconst('lightspeed');
%% Derived quantities (length-independent)
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
D_si = D_lambda * 1e-6; % s/m^2
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
%% Frequency grid
f_max = 150e9;
f = linspace(0, f_max, 4000); % [Hz]
%% Figure setup (keep it stable for nicer GIFs)
fig = figure('Color','w');
ax = axes(fig); %#ok<LAXES>
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
xlabel(ax,'Frequency [GHz]');
ylabel(ax,'Magnitude [dB]');
ylim(ax,[-30 0]);
xlim(ax,[0 f_max/1e9]);
%% GIF writer (serial mode; simplest)
g = GifWriter('Name','power_fading_evolution', 'DelayTime',0.12, 'Parallel',false);
%% Loop: 1 km to 20 km
L = [1:20,19:-1:1];
for L_km = L
L_meter = L_km * 1e3; % [m]
% IM/DD transfer function (power fading)
phi = 2*pi^2 * b2 * f.^2 * L_meter;
H = abs(cos(phi));
HdB = 10*log10(max(H, 1e-12)); % avoid -Inf for deep notches
% Clear and redraw (stable axes)
cla(ax);
plot(ax, f/1e9, HdB, 'LineWidth', 1.8, 'Color','black');
% Analytic first-null frequency marker
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L_meter));
xline(ax, f_null/1e9, 'r--', 'LineWidth', 1.2, ...
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
'LabelOrientation','horizontal', ...
'LabelVerticalAlignment','bottom');
title(ax, sprintf('Power Fading for: %.0f km @ 1275 nm', L_km));
drawnow;
% Add frame to GIF
g.addFrame(fig);
end
%% Done
g.compile(fig.Number);
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));

View File

@@ -0,0 +1,69 @@
%% ============================================================
% IM/DD Power Fading Evolution vs Wavelength (L = 10 km)
% ============================================================
clear; close all; clc;
%% Fixed fiber parameters
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
L = 10e3; % fiber length FIXED [m]
c = physconst('lightspeed');
%% Frequency grid
f_max = 150e9;
f = linspace(0, f_max, 4000); % [Hz]
%% Figure setup (stable axes for clean GIF)
fig = figure('Color','w');
ax = axes(fig);
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
xlabel(ax,'Frequency [GHz]');
ylabel(ax,'Magnitude [dB]');
ylim(ax,[-30 0]);
xlim(ax,[0 f_max/1e9]);
%% GIF writer
g = GifWriter('Name','power_fading_vs_wavelength', ...
'DelayTime',0.12, ...
'Parallel',false);
%% Wavelength sweep (around ZDW)
lambda_vec = linspace(1260e-9, 1360e-9, 25); % 12601360 nm
for k = 1:length(lambda_vec)
lambda = lambda_vec(k);
%% Dispersion for current wavelength
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
D_si = D_lambda * 1e-6; % s/m^2
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
%% Power fading transfer function
phi = 2*pi^2 * b2 * f.^2 * L;
H = abs(cos(phi));
HdB = 10*log10(max(H, 1e-12));
cla(ax)
plot(ax, f/1e9, HdB, 'LineWidth',1.8,'Color','black');
%% First-null frequency
if abs(D_si) > 0
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L));
xline(ax, f_null/1e9, 'r--', 'LineWidth',1.2, ...
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
'LabelOrientation','horizontal', ...
'LabelVerticalAlignment','bottom');
end
title(ax, sprintf('Power Fading for: 10 km @ %.0f nm', lambda*1e9));
drawnow;
g.addFrame(fig);
end
%% Compile GIF
g.compile(fig.Number);
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));

View File

@@ -1,120 +0,0 @@
function loss_curve_digitized(filename)
% PLOT_WPD_DATASETS Reads and plots scattering data from a CSV file.
% filename: String containing the path to the CSV file (e.g., 'wpd_datasets.csv')
%
% This function expects a CSV with the following structure:
% Row 1: Dataset Names (every 2nd column)
% Row 2: Variable Names (X, Y, X, Y...)
% Row 3+: Numeric Data (potentially with NaNs for unequal lengths)
% --- 1. Import Data ---
if nargin < 1
filename = 'wpd_datasets.csv'; % Default filename
end
% Read the numeric data, skipping the first 2 header lines
% 'TreatAsMissing' ensures empty cells become NaNs
raw_data = readmatrix(filename, 'NumHeaderLines', 2);
% Read the first line separately to parse Dataset Names
fid = fopen(filename, 'r');
if fid == -1
error('Could not open file: %s', filename);
end
header_line = fgetl(fid);
fclose(fid);
% Split header by comma to get names
raw_names = split(header_line, ',');
% Extract non-empty names (assuming names are in col 1, 3, 5...)
dataset_names = raw_names(~cellfun('isempty', raw_names));
% --- 2. Setup Plot ---
figure('Color', 'w', 'Position', [100, 100, 800, 600]);
ax = gca;
hold(ax, 'on');
line_styles = {'-', '-', '-', '-'};
% --- 3. Iterate and Plot Each Dataset ---
num_datasets = length(dataset_names);
for i = 1:num_datasets
% Calculate column indices for X and Y
% Dataset 1: Cols 1,2 | Dataset 2: Cols 3,4 | etc.
col_x = (i-1)*2 + 1;
col_y = (i-1)*2 + 2;
% Extract data
if col_y > size(raw_data, 2)
warning('Data columns missing for dataset %d', i);
break;
end
X = raw_data(:, col_x);
Y = raw_data(:, col_y);
% Remove NaNs (missing data due to unequal lengths)
valid_mask = ~isnan(X) & ~isnan(Y);
X = X(valid_mask);
Y = Y(valid_mask);
[X, sortIdx] = sort(X);
Y = Y(sortIdx);
% 3. Smooth the Data
if numel(X) > 20
if 1
Y = smoothdata(Y, 'sgolay', 15);
else
Y = movmean(Y, 15);
end
end
% Plotting
% Using semilogy because scattering data often spans orders of magnitude
% (Adjust to 'plot' if linear scale is preferred)
p = plot(ax, X, Y, ...
'LineStyle', line_styles{mod(i-1, length(line_styles)) + 1}, ...
'Marker', 'none', ...
'Color', 'black', ...
'LineWidth', 1.5, ...
'MarkerSize', 6, ...
'DisplayName', dataset_names{i});
% Optional: Fill marker faces for better visibility
% p.MarkerFaceColor = p.Color;
% p.MarkerFaceAlpha = 0.3; % Semi-transparent fill
end
% --- 4. Styling and Formatting ---
% Axis Labels (Inferred from typical scattering plots)
xlabel(ax, 'Wavelength (\mu m)', 'FontSize', 12, 'FontWeight', 'bold');
ylabel(ax, 'Intensity / Cross-Section (a.u.)', 'FontSize', 12, 'FontWeight', 'bold');
% Title
title(ax, 'Dataset Comparison', 'FontSize', 14);
% Legend
legend(ax, 'Location', 'best', 'Interpreter', 'none', 'Box', 'on');
% Grid
grid(ax, 'on');
ax.GridAlpha = 0.3;
ax.MinorGridAlpha = 0.1;
% Set Log Scale for Y (likely required for this data type)
set(ax, 'YScale', 'log');
% Enhance axis appearance
set(ax, 'Box', 'on', 'LineWidth', 1.2, 'FontSize', 10);
hold(ax, 'off');
end

View File

@@ -1,189 +0,0 @@
Rayleigh,,Experimental,,Infrared Absorption,
X,Y,X,Y,X,Y
0.7066005680911753,3.651009696525016,0.7072188355785799,4.848577786727532,1.4943918372804705,0.009324755400827079
0.7362740977034739,3.1008424465551374,0.7104385926007812,5.059236053617898,1.5870823136443164,0.04795688074913024
0.7704634954089999,2.559836201011587,0.7143024334187478,5.3165954733738054,1.6443739975494367,0.12666181795273013
0.8246453070916075,1.9963763545469397,0.7194723146571098,4.679249634272495,1.6900695253042852,0.3029389206853443
0.8846384359818439,1.4197559292837703,0.7194729766137344,4.646181068667172,1.7344762235109785,0.7194296259968607
0.9375334039861705,1.0762856922437043,0.7227053108118038,4.236869693191961,1.7975573800551148,2.1896107578891244
0.9929980876073115,0.9010620061822204,0.7272205169484065,4.147543538340177,,
1.0420225952274251,0.6977835411732736,0.7291487965959542,4.420849736815974,,
1.0845923638007697,0.5842349714248559,0.7310784001567514,4.645798669234298,,
1.129741777340298,0.4856980392071641,0.7355902965102309,4.71201487210429,,
1.1981066716622326,0.3841608204561696,0.738821306795051,4.358286713153517,,
1.24841405122088,0.31935666463679646,0.7414069093708566,4.059822180897163,,
1.289688370679823,0.2850148847474179,0.742705668268381,3.676053825899206,,
1.3541801567910463,0.23691184007300667,0.7440031032526563,3.376112267508452,,
1.4083573347772815,0.19416797258075097,0.7452965664971838,3.235432943532804,,
1.4618851333147547,0.16723647350379714,0.7459426361628229,3.1898499103097238,,
1.50315548103395,0.15574103754742674,0.7549743723492774,3.0137121806723157,,
1.5386251028515106,0.1419883611511702,0.7620678995388148,2.971117042589562,,
1.596665459699088,0.12316075278891304,0.765291628300764,2.971049114206588,,
1.6437444767994136,0.10759838849626362,0.7756075603390012,2.9708317538173317,,
1.683725994970454,0.09949510555249974,0.7762523060913911,2.9708181693210105,,
1.717258069747722,0.09398483395032568,0.7839919029465676,2.8875658983600925,,
1.7636903552257834,0.08387517688001396,0.7885090949530442,2.767180560538318,,
1.7940013490676008,0.07701567091052414,0.7917348095848672,2.7088647150205,,
,,0.7936723566251598,2.6144535948583694,,
,,0.7962546494178423,2.5233214143921474,,
,,0.8085087904529968,2.417989089048743,,
,,0.8104423657535417,2.435165393892523,,
,,0.8201175237791369,2.3335556930105406,,
,,0.8285065000830756,2.158298098247211,,
,,0.8317335386281479,2.083056634772393,,
,,0.8356046609689853,2.024737963659226,,
,,0.8407639509013534,1.996148150112612,,
,,0.8459232408337212,1.967962031984024,,
,,0.854951005280428,1.9401206794865944,,
,,0.8601116191260452,1.8857864945455538,,
,,0.8691446792257491,1.7565635929668848,,
,,0.8743052930713663,1.7073700288086895,,
,,0.8788211611645935,1.6595617469926904,,
,,0.8826916215488064,1.624580544751916,,
,,0.8891397410293294,1.6130257674984603,,
,,0.896234592132116,1.5678305544227285,,
,,0.903974850943917,1.5131252291764425,,
,,0.90784531132813,1.4812307005435945,,
,,0.9155829223134326,1.470682044636039,,
,,0.9220303798373308,1.4706147972609174,,
,,0.9310574823274131,1.460128389693264,,
,,0.9349259568417521,1.4600883304432553,,
,,0.9433056657529459,1.4913980336424177,,
,,0.9516853746641398,1.5233791328756299,,
,,0.956844002639883,1.512557980118849,,
,,0.9671632444612435,1.4597545460975296,,
,,0.9710370146285795,1.379199997932108,,
,,0.9736206313345113,1.3123773159521164,,
,,0.9774937395452226,1.2487807938448074,,
,,0.9826543533908398,1.213807976266501,,
,,0.9903926263327669,1.1966468122906808,,
,,0.9942630867169798,1.171423198750918,,
,,1.0045796807118417,1.1630595787371243,,
,,1.0097376467309604,1.163017033545686,,
,,1.0219851681998686,1.1963787227370668,,
,,1.0290753856062829,1.2220446908209617,,
,,1.0348774354211667,1.2306917801168409,,
,,1.0471421677623152,1.052809309517664,,
,,1.0510159379296513,0.9947114748787712,,
,,1.0445565651865096,1.1302083245776995,,
,,1.0458487045177878,1.0985863367418764,,
,,1.0542449623445975,0.9398239868494617,,
,,1.0613444471437565,0.8692481092753317,,
,,1.0690886776953055,0.8039684355922487,,
,,1.0768322462902296,0.7488836107091129,,
,,1.0800586228786773,0.7279206840193796,,
,,1.0858633205200596,0.7125673758820761,,
,,1.1013418522737881,0.677981252075927,,
,,1.105210326788127,0.6779626513688453,,
,,1.1193973811672016,0.6589337368401503,,
,,1.1206888585418553,0.6450561487842132,,
,,1.123272475247787,0.613802971613336,,
,,1.129077834845794,0.5966103416145675,,
,,1.1335910551125228,0.5965912453535225,,
,,1.1413266802279516,0.6050805792103379,,
,,1.147134687652457,0.5716821968068484,,
,,1.1581006610960811,0.5401075330241505,,
,,1.167774495208427,0.524964710284852,,
,,1.17357786893656,0.521233298948351,,
,,1.1890511050372914,0.5248855006959243,,
,,1.1974327998183592,0.5248543002000403,,
,,1.2051671010205385,0.5399272739697006,,
,,1.2161264548979165,0.5475977747039503,,
,,1.2225739124218147,0.5475727356323816,,
,,1.2232186581742046,0.5475702317881956,,
,,1.2257923455307669,0.5795255128326332,,
,,1.2264284858470365,0.635494312878344,,
,,1.2264218662807902,0.6822012488404363,,
,,1.2322133247896798,0.7695840678419278,,
,,1.2354304339853828,0.8261273126225834,,
,,1.2386382757883407,0.9793976812064772,,
,,1.2399224716401234,1.0365631680970249,,
,,1.2405632456527655,1.0816189618908738,,
,,1.2457119442791393,1.1944819289049535,,
,,1.2508619668187624,1.3005429730851226,,
,,1.2521488104970433,1.3379536598639075,,
,,1.2586068593269357,1.1943726953174758,,
,,1.2605516878900995,1.0662340854711274,,
,,1.263782036218295,0.9932116176633944,,
,,1.267659116168754,0.9057092045091463,,
,,1.2721796179583538,0.8377104911187728,,
,,1.277345527456968,0.7693377754021644,,
,,1.2818653672899432,0.7166420946785479,,
,,1.2954156193961235,0.639704291832398,,
,,1.298640672071322,0.6306801565443763,,
,,1.3018657247465204,0.6217833222901857,,
,,1.3147579919678183,0.6396165438362177,,
,,1.3179764250767705,0.6769403979817149,,
,,1.3244132912946747,0.7582491296621654,,
,,1.3295613279644238,0.8433295073010272,,
,,1.336000180052202,0.9247376324361347,,
,,1.3430738485430005,1.1278180580973283,,
,,1.3449988184074253,1.2455302076050567,,
,,1.3482112939067554,1.4050952527481475,,
,,1.351423769406086,1.585102197634859,,
,,1.3533487392705106,1.7505418140103943,,
,,1.3565618767264658,1.9608478952847546,,
,,1.3604177740649368,2.243642151072621,,
,,1.3681421459177467,2.5671506730013776,,
,,1.3720059867357133,2.6977396395227498,,
,,1.3700631440424236,2.9583331848749403,,
,,1.3745670969164077,3.267039328784058,,
,,1.3758446732019438,3.711862721055264,,
,,1.377124897313979,4.099294432098773,,
,,1.381620906708467,4.929210899363566,,
,,1.381610315402473,5.521521237053952,,
,,1.382885243861511,6.453816707451638,,
,,1.3828733286422676,7.332602493027707,,
,,1.3835048352621646,8.450022001983974,,
,,1.3847837354609505,9.465318121186383,,
,,1.3892850405084358,10.753821633797266,,
,,1.3950817946703227,11.46214012981349,,
,,1.406041810504325,11.542823048802346,,
,,1.4086254272102567,10.983569572223233,,
,,1.4125144223799593,8.815541223987582,,
,,1.4138145051907332,7.8697993951128655,,
,,1.4164106990725327,6.544455667464655,,
,,1.4170686839574151,5.678973743658009,,
,,1.419664877839215,4.722584406045411,,
,,1.422267691287261,3.6583795017467264,,
,,1.4274475018749921,2.894876829955794,,
,,1.4293982880477776,2.4244991059437035,,
,,1.4319891862765801,2.133892660567146,,
,,1.4365249130685465,1.6766244945281037,,
,,1.442346821582169,1.3648832144532748,,
,,1.44946086942707,1.0800176935856405,,
,,1.4539886527395407,0.9239641429706197,,
,,1.4617467843802068,0.7363233849854021,,
,,1.4701536335130105,0.5623407795094862,,
,,1.477900511891058,0.5055620724926202,,
,,1.4856487141823544,0.44811473438788657,,
,,1.4940482817922873,0.3699994982234866,,
,,1.5005089784486785,0.32105511462339426,,
,,1.5089019264923649,0.2845721176091456,,
,,1.5166481429137875,0.2576601983353233,,
,,1.5179396202884412,0.2522337011156551,,
,,1.5359997828782272,0.23327413205434572,,
,,1.5430966198508878,0.22196482072259285,,
,,1.5469697280615993,0.21120862244291763,,
,,1.5501980905199209,0.20097457800069773,,
,,1.565674636403775,0.1953318790229525,,
,,1.5688977032090996,0.19671762962317987,,
,,1.5785662416684487,0.20236426842871638,,
,,1.5837215598610688,0.2081796533603784,,
,,1.5914545371499988,0.21721757235346942,,
,,1.5991901622654274,0.22030852031094905,,
,,1.6088620105078997,0.21873658192521878,,
,,1.61208309144335,0.22502554836218797,,
,,1.6262602164730557,0.2432590831170723,,
,,1.626903638312196,0.2467330049135315,,
,,1.6281904819904773,0.25383038758817866,,
,,1.6410748057322797,0.28430548752659124,,
,,1.660414530477476,0.29244621369149987,,
,,1.6642816810785659,0.29661578287603696,,
,,1.6707152375133467,0.34423590359793155,,
,,1.6739290369259265,0.3828666146961718,,
,,1.6758540067903511,0.4228270071256609,,
,,1.690028483993558,0.4702407837690221,,
,,1.6964732936909575,0.48374976893430716,,
,,1.6996923887565347,0.5083600695634991,,
,,1.7003318388559272,0.5380344919079171,,
1 Rayleigh Experimental Infrared Absorption
2 X Y X Y X Y
3 0.7066005680911753 3.651009696525016 0.7072188355785799 4.848577786727532 1.4943918372804705 0.009324755400827079
4 0.7362740977034739 3.1008424465551374 0.7104385926007812 5.059236053617898 1.5870823136443164 0.04795688074913024
5 0.7704634954089999 2.559836201011587 0.7143024334187478 5.3165954733738054 1.6443739975494367 0.12666181795273013
6 0.8246453070916075 1.9963763545469397 0.7194723146571098 4.679249634272495 1.6900695253042852 0.3029389206853443
7 0.8846384359818439 1.4197559292837703 0.7194729766137344 4.646181068667172 1.7344762235109785 0.7194296259968607
8 0.9375334039861705 1.0762856922437043 0.7227053108118038 4.236869693191961 1.7975573800551148 2.1896107578891244
9 0.9929980876073115 0.9010620061822204 0.7272205169484065 4.147543538340177
10 1.0420225952274251 0.6977835411732736 0.7291487965959542 4.420849736815974
11 1.0845923638007697 0.5842349714248559 0.7310784001567514 4.645798669234298
12 1.129741777340298 0.4856980392071641 0.7355902965102309 4.71201487210429
13 1.1981066716622326 0.3841608204561696 0.738821306795051 4.358286713153517
14 1.24841405122088 0.31935666463679646 0.7414069093708566 4.059822180897163
15 1.289688370679823 0.2850148847474179 0.742705668268381 3.676053825899206
16 1.3541801567910463 0.23691184007300667 0.7440031032526563 3.376112267508452
17 1.4083573347772815 0.19416797258075097 0.7452965664971838 3.235432943532804
18 1.4618851333147547 0.16723647350379714 0.7459426361628229 3.1898499103097238
19 1.50315548103395 0.15574103754742674 0.7549743723492774 3.0137121806723157
20 1.5386251028515106 0.1419883611511702 0.7620678995388148 2.971117042589562
21 1.596665459699088 0.12316075278891304 0.765291628300764 2.971049114206588
22 1.6437444767994136 0.10759838849626362 0.7756075603390012 2.9708317538173317
23 1.683725994970454 0.09949510555249974 0.7762523060913911 2.9708181693210105
24 1.717258069747722 0.09398483395032568 0.7839919029465676 2.8875658983600925
25 1.7636903552257834 0.08387517688001396 0.7885090949530442 2.767180560538318
26 1.7940013490676008 0.07701567091052414 0.7917348095848672 2.7088647150205
27 0.7936723566251598 2.6144535948583694
28 0.7962546494178423 2.5233214143921474
29 0.8085087904529968 2.417989089048743
30 0.8104423657535417 2.435165393892523
31 0.8201175237791369 2.3335556930105406
32 0.8285065000830756 2.158298098247211
33 0.8317335386281479 2.083056634772393
34 0.8356046609689853 2.024737963659226
35 0.8407639509013534 1.996148150112612
36 0.8459232408337212 1.967962031984024
37 0.854951005280428 1.9401206794865944
38 0.8601116191260452 1.8857864945455538
39 0.8691446792257491 1.7565635929668848
40 0.8743052930713663 1.7073700288086895
41 0.8788211611645935 1.6595617469926904
42 0.8826916215488064 1.624580544751916
43 0.8891397410293294 1.6130257674984603
44 0.896234592132116 1.5678305544227285
45 0.903974850943917 1.5131252291764425
46 0.90784531132813 1.4812307005435945
47 0.9155829223134326 1.470682044636039
48 0.9220303798373308 1.4706147972609174
49 0.9310574823274131 1.460128389693264
50 0.9349259568417521 1.4600883304432553
51 0.9433056657529459 1.4913980336424177
52 0.9516853746641398 1.5233791328756299
53 0.956844002639883 1.512557980118849
54 0.9671632444612435 1.4597545460975296
55 0.9710370146285795 1.379199997932108
56 0.9736206313345113 1.3123773159521164
57 0.9774937395452226 1.2487807938448074
58 0.9826543533908398 1.213807976266501
59 0.9903926263327669 1.1966468122906808
60 0.9942630867169798 1.171423198750918
61 1.0045796807118417 1.1630595787371243
62 1.0097376467309604 1.163017033545686
63 1.0219851681998686 1.1963787227370668
64 1.0290753856062829 1.2220446908209617
65 1.0348774354211667 1.2306917801168409
66 1.0471421677623152 1.052809309517664
67 1.0510159379296513 0.9947114748787712
68 1.0445565651865096 1.1302083245776995
69 1.0458487045177878 1.0985863367418764
70 1.0542449623445975 0.9398239868494617
71 1.0613444471437565 0.8692481092753317
72 1.0690886776953055 0.8039684355922487
73 1.0768322462902296 0.7488836107091129
74 1.0800586228786773 0.7279206840193796
75 1.0858633205200596 0.7125673758820761
76 1.1013418522737881 0.677981252075927
77 1.105210326788127 0.6779626513688453
78 1.1193973811672016 0.6589337368401503
79 1.1206888585418553 0.6450561487842132
80 1.123272475247787 0.613802971613336
81 1.129077834845794 0.5966103416145675
82 1.1335910551125228 0.5965912453535225
83 1.1413266802279516 0.6050805792103379
84 1.147134687652457 0.5716821968068484
85 1.1581006610960811 0.5401075330241505
86 1.167774495208427 0.524964710284852
87 1.17357786893656 0.521233298948351
88 1.1890511050372914 0.5248855006959243
89 1.1974327998183592 0.5248543002000403
90 1.2051671010205385 0.5399272739697006
91 1.2161264548979165 0.5475977747039503
92 1.2225739124218147 0.5475727356323816
93 1.2232186581742046 0.5475702317881956
94 1.2257923455307669 0.5795255128326332
95 1.2264284858470365 0.635494312878344
96 1.2264218662807902 0.6822012488404363
97 1.2322133247896798 0.7695840678419278
98 1.2354304339853828 0.8261273126225834
99 1.2386382757883407 0.9793976812064772
100 1.2399224716401234 1.0365631680970249
101 1.2405632456527655 1.0816189618908738
102 1.2457119442791393 1.1944819289049535
103 1.2508619668187624 1.3005429730851226
104 1.2521488104970433 1.3379536598639075
105 1.2586068593269357 1.1943726953174758
106 1.2605516878900995 1.0662340854711274
107 1.263782036218295 0.9932116176633944
108 1.267659116168754 0.9057092045091463
109 1.2721796179583538 0.8377104911187728
110 1.277345527456968 0.7693377754021644
111 1.2818653672899432 0.7166420946785479
112 1.2954156193961235 0.639704291832398
113 1.298640672071322 0.6306801565443763
114 1.3018657247465204 0.6217833222901857
115 1.3147579919678183 0.6396165438362177
116 1.3179764250767705 0.6769403979817149
117 1.3244132912946747 0.7582491296621654
118 1.3295613279644238 0.8433295073010272
119 1.336000180052202 0.9247376324361347
120 1.3430738485430005 1.1278180580973283
121 1.3449988184074253 1.2455302076050567
122 1.3482112939067554 1.4050952527481475
123 1.351423769406086 1.585102197634859
124 1.3533487392705106 1.7505418140103943
125 1.3565618767264658 1.9608478952847546
126 1.3604177740649368 2.243642151072621
127 1.3681421459177467 2.5671506730013776
128 1.3720059867357133 2.6977396395227498
129 1.3700631440424236 2.9583331848749403
130 1.3745670969164077 3.267039328784058
131 1.3758446732019438 3.711862721055264
132 1.377124897313979 4.099294432098773
133 1.381620906708467 4.929210899363566
134 1.381610315402473 5.521521237053952
135 1.382885243861511 6.453816707451638
136 1.3828733286422676 7.332602493027707
137 1.3835048352621646 8.450022001983974
138 1.3847837354609505 9.465318121186383
139 1.3892850405084358 10.753821633797266
140 1.3950817946703227 11.46214012981349
141 1.406041810504325 11.542823048802346
142 1.4086254272102567 10.983569572223233
143 1.4125144223799593 8.815541223987582
144 1.4138145051907332 7.8697993951128655
145 1.4164106990725327 6.544455667464655
146 1.4170686839574151 5.678973743658009
147 1.419664877839215 4.722584406045411
148 1.422267691287261 3.6583795017467264
149 1.4274475018749921 2.894876829955794
150 1.4293982880477776 2.4244991059437035
151 1.4319891862765801 2.133892660567146
152 1.4365249130685465 1.6766244945281037
153 1.442346821582169 1.3648832144532748
154 1.44946086942707 1.0800176935856405
155 1.4539886527395407 0.9239641429706197
156 1.4617467843802068 0.7363233849854021
157 1.4701536335130105 0.5623407795094862
158 1.477900511891058 0.5055620724926202
159 1.4856487141823544 0.44811473438788657
160 1.4940482817922873 0.3699994982234866
161 1.5005089784486785 0.32105511462339426
162 1.5089019264923649 0.2845721176091456
163 1.5166481429137875 0.2576601983353233
164 1.5179396202884412 0.2522337011156551
165 1.5359997828782272 0.23327413205434572
166 1.5430966198508878 0.22196482072259285
167 1.5469697280615993 0.21120862244291763
168 1.5501980905199209 0.20097457800069773
169 1.565674636403775 0.1953318790229525
170 1.5688977032090996 0.19671762962317987
171 1.5785662416684487 0.20236426842871638
172 1.5837215598610688 0.2081796533603784
173 1.5914545371499988 0.21721757235346942
174 1.5991901622654274 0.22030852031094905
175 1.6088620105078997 0.21873658192521878
176 1.61208309144335 0.22502554836218797
177 1.6262602164730557 0.2432590831170723
178 1.626903638312196 0.2467330049135315
179 1.6281904819904773 0.25383038758817866
180 1.6410748057322797 0.28430548752659124
181 1.660414530477476 0.29244621369149987
182 1.6642816810785659 0.29661578287603696
183 1.6707152375133467 0.34423590359793155
184 1.6739290369259265 0.3828666146961718
185 1.6758540067903511 0.4228270071256609
186 1.690028483993558 0.4702407837690221
187 1.6964732936909575 0.48374976893430716
188 1.6996923887565347 0.5083600695634991
189 1.7003318388559272 0.5380344919079171

View File

@@ -0,0 +1,69 @@
w0 = [1290:2:1290+15*2]';
w0 = [1290:2:1290+15*2]';
w0 = [ 1302 1304 1306 1308]';
%w0 = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]';
m = 0.5*(numel(w0)^3 - numel(w0)^2);
a = [1,1,1]';
w = w0;
for o = 2:3
p = nchoosek(w,3);
q = [];
parfor i = 1:size(p,1)
q_ = perms(p(i,:));
q = [q;q_];
end
p = q;
%p = unique(q,"rows");
w_ = p(:,1) + p(:,2) - p(:,3);
a_ = ones(size(w_)).* 1/o;
w = [w ; w_];
a = [a ; a_];
% w = unique(w);
% a = unique(a);
m(end+1) = 0.5*(numel(w)^3 - numel(w)^2);
end
figure(11)
hold on
lambda = min(w):max(w);
gen = sum(lambda == w,1);
gen(gen==0) = NaN;
stem(lambda,gen,"filled",'LineWidth',1,'Marker','o','MarkerSize',2,'LineStyle',':')
initial = sum(lambda == w0,1);
initial(initial==0) = NaN;
stem(lambda,initial,"filled",'LineWidth',1.5,'MarkerSize',5,'Marker','^');
xlabel('Wavelength');
ylabel('number of FWM products');
grid minor
legend('Generated Products', 'Initial Channel Position')
AxesMain = gca;
fig = gcf;
fontsize(AxesMain,8,"points")
fig.Units = "centimeters";
fig.Position = [2 2 8.5 7];

View File

@@ -0,0 +1,43 @@
%% Laser Offset Statistics
figure
for i = 1
res = 1.7e6;
n_chann = 16;
df_T_exact = (-n_chann/2+0.5:n_chann/2).* 200e9;
for key = 1:100
laser_frequency_imperfection(key,:) = res .* round(randn(1,n_chann)*i*100);
df_T(key,:) = df_T_exact + laser_frequency_imperfection(key,:);
end
hold on
histogram(laser_frequency_imperfection.*1e-6,100,"Normalization","probability","EdgeColor","none","FaceAlpha",0.3,'DisplayName',['Std. Dev.: ',num2str(mean(std(laser_frequency_imperfection))*1e-6),' MHz']);
xlabel('Laser Frequency Offset in MHz');
ylabel('Probability');
title(['Laser deviations from exact grid.'])
end
%% ZDW Statistics
for k = 1:1000
% Set parameters
meanUniformMin = 1309;
meanUniformMax = 1315;
meanValue = 1310;
sigma = 2;
% Seed the random number generator (assuming Mersenne Twister)
rng(k);
% Generate normally distributed random numbers
randomNumbers(k,:) = normrnd(meanValue, sigma, [n_chann, 1]).';
end
figure;
histogram(randomNumbers,100,"Normalization","probability","EdgeColor","none");
xlabel('ZDW in nm');
ylabel('Probability');

View File

@@ -0,0 +1,65 @@
%%FWM analysis from "Analytical Calculation of the Number of
%%Four-Wave-Mixing Products in Optical Multichannel Communication Systems"
N_ = [4,8,16];
df_hz = 400e9;
center_nm = 1310;
figure()
for i = 1:length(N_)
vec = (2*N_(i)-1:-1:2-N_(i)) -(N_(i)/2+0.5);
channelplan_hz = nm2hz(center_nm) + (vec * df_hz) ;
channelplan_nm = hz2nm(channelplan_hz);
[Mndg,Mdg] = getProducts(N_(i));
total(i) = sum(Mndg) + sum(Mdg);
subplot(1,length(N_),i)
xline(calcWavelengthPlan(N_(i), df_hz, center_nm));
hold on
stem(channelplan_nm,(Mndg+Mdg),'filled','LineWidth',1,'Marker','o','MarkerSize',2)
stem(channelplan_nm,(Mdg),'filled','LineWidth',1,'Marker','none');
ylim([0,100])
xlim([1260, 1365]);
grid off
xlabel('O-band wavelength region in nm');
ylabel('Number of FWM products');
title([num2str(N_(i)),' ch.'])
end
function [Mndg,Mdg] = getProducts(N)
s = abs(2-N-1) ;
for n = 2-N:2*N-1
if n<-N
Mdg(n+s) = 0;
elseif (-N <= n)&&(n <= 0)
Mdg(n+s) = N - ceil((N-n)/2);
elseif (1 <= n)&&(n <= N)
Mdg(n+s) = N - 1 - floor(n/2) - ceil((N-n)/2);
elseif (N < n)&&(n <= 2*N)
Mdg(n+s) = N - floor(n/2);
elseif n > 2*N
Mdg(n+s) = 0;
end
if n<-N
Mndg(n+s) = 0;
elseif (-N <= n)&&(n < 1)
Mndg(n+s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
elseif (1 <= n)&&(n <= N)
Mndg(n+s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
elseif (N < n)&&(n <= 2*N)
Mndg(n+s) = floor(N^2 + n^2 /4 - N*n);
elseif n > 2*N
Mndg(n+s) = 0;
end
end
end

View File

@@ -0,0 +1,23 @@
function [eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm)
% FWM efficiency including phase mismatch and attenuation.
% alphaDbPerKm is the power attenuation in dB/km, Lkm is the fiber length in km.
deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds);
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
Lm = Lkm .* 1e3;
denominator = alphaNpPerM.^2 + deltaBeta.^2;
term1 = alphaNpPerM.^2 ./ denominator;
loss_term = 1 - exp(-alphaNpPerM .* Lm);
if abs(alphaNpPerM) < eps
term2 = 4 .* sin(deltaBeta .* Lm ./ 2).^2 ./ max((alphaNpPerM .* Lm).^2, eps);
else
term2 = 1 + 4 .* exp(-alphaNpPerM .* Lm) .* sin(deltaBeta .* Lm ./ 2).^2 ./ (loss_term.^2);
end
eta = term1 .* term2;
end

View File

@@ -0,0 +1,48 @@
function [P_fwm, eta, deltaBeta, Leff] = calcFwmPower( ...
f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm, ...
P_i, P_j, P_k, gammaWInvKmInv, degeneracyFactor)
% Calculate FWM power for a fiber with attenuation and phase mismatch.
%
% Inputs:
% f_i, f_j, f_k, f_0 : frequencies in Hz
% Ds : dispersion slope in ps / (nm^2 km)
% alphaDbPerKm : attenuation in dB/km
% Lkm : fiber length in km
% P_i, P_j, P_k : launch powers in W
% gammaWInvKmInv : nonlinear coefficient in 1/(W km)
% degeneracyFactor : typically 3 for degenerate FWM, 6 for non-degenerate
if nargin < 8 || isempty(P_i)
P_i = 1;
end
if nargin < 9 || isempty(P_j)
P_j = P_i;
end
if nargin < 10 || isempty(P_k)
P_k = 1;
end
if nargin < 11 || isempty(gammaWInvKmInv)
gammaWInvKmInv = 1;
end
if nargin < 12 || isempty(degeneracyFactor)
degeneracyFactor = 1;
end
[eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm);
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
Lm = Lkm .* 1e3;
gammaWInvMInv = gammaWInvKmInv ./ 1e3;
if abs(alphaNpPerM) < eps
Leff = Lm;
else
Leff = (1 - exp(-alphaNpPerM .* Lm)) ./ alphaNpPerM;
end
P_fwm = degeneracyFactor .* eta .* ...
(gammaWInvMInv .* Leff).^2 .* ...
P_i .* P_j .* P_k .* ...
exp(-alphaNpPerM .* Lm);
end

View File

@@ -0,0 +1,20 @@
function deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds)
% Approximate phase mismatch for degenerate FWM close to the ZDW.
% Inputs are frequencies in Hz.
% f_i, f_j : pump frequencies (equal in the degenerate case)
% f_k : signal frequency
% f_0 : zero-dispersion frequency
% Ds : dispersion slope in ps / (nm^2 km)
c = physconst('LightSpeed');
pump_frequency = 0.5 .* (f_i + f_j);
lambda_zdw_m = c ./ f_0;
dispersion_slope_si = Ds .* 1e3;
deltaBeta = -(2 .* pi .* lambda_zdw_m.^4 ./ c.^2) .* ...
dispersion_slope_si .* ...
(pump_frequency - f_0) .* ...
(pump_frequency - f_k).^2;
end

View File

@@ -0,0 +1,104 @@
clear;
clc;
% Sweep the degenerate pump frequency around its nominal wavelength.
pump_detuning_hz = (-800:0.01:800) .* 1e9;
% Degenerate FWM setup: two pump photons at f_p and one signal at f_s
% generate an idler at f_i = 2*f_p - f_s.
pump_wavelength_nm = 1310;
signal_wavelength_nm = 1308;
zdw_wavelength_nm = 1310;
f_pump_nominal = wavelength2frequency(pump_wavelength_nm, 'nm');
f_signal_scalar = wavelength2frequency(signal_wavelength_nm, 'nm');
f_zdw_scalar = wavelength2frequency(zdw_wavelength_nm, 'nm');
f_pump = f_pump_nominal + pump_detuning_hz;
f_signal = f_signal_scalar .* ones(size(f_pump));
f_zdw = f_zdw_scalar .* ones(size(f_pump));
f_idler = 2 .* f_pump - f_signal;
% Fiber parameters
dispersion_slope_ps_nm2_km = 0.07;
attenuation_db_per_km = 0.21;
fiber_length_km = 10;
% Launch powers and nonlinear coefficient
pump_power_dbm = 10;
signal_power_dbm = 10;
pump_power_w = dbm2watt(pump_power_dbm);
signal_power_w = dbm2watt(signal_power_dbm);
gamma_w_inv_km_inv = 1.3;
degeneracy_factor = 3;
[P_fwm, eta, delta_beta, L_eff_m] = calcFwmPower( ...
f_pump, f_pump, f_signal, f_zdw, ...
dispersion_slope_ps_nm2_km, attenuation_db_per_km, fiber_length_km, ...
pump_power_w, pump_power_w, signal_power_w, ...
gamma_w_inv_km_inv, degeneracy_factor);
f_pump_thz = f_pump .* 1e-12;
f_zdw_thz = f_zdw_scalar .* 1e-12;
f_signal_thz = f_signal_scalar .* 1e-12;
idler_power_dbm = 10 .* log10(max(P_fwm, realmin) ./ 1e-3);
figure;
tiledlayout(2,1);
ax1 = nexttile;
plot(ax1, f_pump_thz, eta, 'LineWidth', 2);
hold(ax1, 'on');
xline(ax1, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
xline(ax1, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
ylabel(ax1, 'FWM efficiency');
grid(ax1, 'on');
title(ax1, 'FWM Efficiency and Idler Power versus Pump Frequency');
ax2 = nexttile;
plot(ax2, f_pump_thz, idler_power_dbm, 'LineWidth', 2);
hold(ax2, 'on');
xline(ax2, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
xline(ax2, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
xlabel(ax2, 'Pump frequency (THz)');
ylabel(ax2, 'FWM idler power (dBm)');
grid(ax2, 'on');
fprintf('Pump wavelength : %.3f nm -> %.6f THz\n', ...
pump_wavelength_nm, f_pump_nominal .* 1e-12);
fprintf('Signal wavelength : %.3f nm -> %.6f THz\n', ...
signal_wavelength_nm, f_signal_scalar .* 1e-12);
fprintf('ZDW wavelength : %.3f nm -> %.6f THz\n', ...
zdw_wavelength_nm, f_zdw_scalar .* 1e-12);
fprintf('Pump launch power : %.2f dBm -> %.4g W\n', ...
pump_power_dbm, pump_power_w);
fprintf('Signal launch power : %.2f dBm -> %.4g W\n', ...
signal_power_dbm, signal_power_w);
fprintf('Peak FWM efficiency : %.4g\n', max(eta));
fprintf('Peak FWM idler power : %.4g W (%.2f dBm)\n', ...
max(P_fwm), 10 .* log10(max(P_fwm) ./ 1e-3));
fprintf('Effective fiber length : %.4f km\n', L_eff_m ./ 1e3);
fprintf('Idler wavelength range : %.3f nm to %.3f nm\n', ...
min(frequency2wavelength(f_idler, 'nm')), max(frequency2wavelength(f_idler, 'nm')));
fprintf('Max |delta beta| : %.4g 1/m\n', max(abs(delta_beta)));
function wavelength = frequency2wavelength(frequency, outputUnit)
c = physconst('LightSpeed');
wavelength = c ./ frequency;
switch lower(outputUnit)
case 'm'
case 'nm'
wavelength = wavelength .* 1e9;
otherwise
error('Unsupported output unit "%s". Use "m" or "nm".', outputUnit);
end
end
function power_w = dbm2watt(power_dbm)
power_w = 1e-3 .* 10.^(power_dbm ./ 10);
end

View File

@@ -0,0 +1,124 @@
%% Validate the analytical FWM product count against a brute-force reference
% The paper counts channel combinations, not only unique output frequencies:
% non-degenerate: i < j, k ~= i, k ~= j, n = i + j - k
% degenerate: i == j, k ~= i, n = 2*i - k
clear;
clc;
N_values = [4, 8, 16];
plot_N = 8;
fprintf('Validating analytical FWM product count from Goebel and Hanik (2008)\n');
for idxN = 1:numel(N_values)
N = N_values(idxN);
fprintf('\nN = %d\n', N);
[Mndg_ana, Mdg_ana] = getProducts(N);
[Mndg_brute, Mdg_brute, n_values] = getProductsBruteForce(N);
diff_ndg = Mndg_ana - Mndg_brute;
diff_dg = Mdg_ana - Mdg_brute;
fprintf(' Analytical total : %d\n', sum(Mndg_ana) + sum(Mdg_ana));
fprintf(' Brute-force total : %d\n', sum(Mndg_brute) + sum(Mdg_brute));
if all(diff_ndg == 0) && all(diff_dg == 0)
fprintf(' Match : yes\n');
else
fprintf(' Match : no\n');
fprintf(' Non-degenerate diff: %s\n', mat2str(diff_ndg));
fprintf(' Degenerate diff : %s\n', mat2str(diff_dg));
end
if N == plot_N
plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N);
end
end
function [Mndg, Mdg, n_values] = getProductsBruteForce(N)
n_values = (2 - N):(2*N - 1);
Mndg = zeros(size(n_values));
Mdg = zeros(size(n_values));
for idx = 1:numel(n_values)
n = n_values(idx);
% Degenerate products: two identical pumps and one different channel.
for i = 1:N
k = 2*i - n;
if isValidChannel(k, N) && (k ~= i)
Mdg(idx) = Mdg(idx) + 1;
end
end
% Non-degenerate products: unordered pump pair plus one third channel.
for i = 1:N
for j = (i + 1):N
k = i + j - n;
if isValidChannel(k, N) && (k ~= i) && (k ~= j)
Mndg(idx) = Mndg(idx) + 1;
end
end
end
end
end
function tf = isValidChannel(channel_idx, N)
tf = (channel_idx >= 1) && (channel_idx <= N) && (channel_idx == round(channel_idx));
end
function plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N)
figure;
subplot(1,2,1);
stem(n_values, Mndg_ana + Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
hold on;
stem(n_values, Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'none');
title(['Analytical (N=', num2str(N), ')']);
xlabel('Product index n');
ylabel('Number of FWM products');
legend('Total', 'Degenerate');
grid on;
subplot(1,2,2);
stem(n_values, Mndg_brute + Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
hold on;
stem(n_values, Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'none');
title(['Brute force (N=', num2str(N), ')']);
xlabel('Product index n');
ylabel('Number of FWM products');
legend('Total', 'Degenerate');
grid on;
end
function [Mndg, Mdg] = getProducts(N)
s = abs(2 - N - 1);
for n = 2 - N:2*N - 1
if n < -N
Mdg(n + s) = 0;
elseif (-N <= n) && (n <= 0)
Mdg(n + s) = N - ceil((N - n)/2);
elseif (1 <= n) && (n <= N)
Mdg(n + s) = N - 1 - floor(n/2) - ceil((N - n)/2);
elseif (N < n) && (n <= 2*N)
Mdg(n + s) = N - floor(n/2);
elseif n > 2*N
Mdg(n + s) = 0;
end
if n < -N
Mndg(n + s) = 0;
elseif (-N <= n) && (n < 1)
Mndg(n + s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
elseif (1 <= n) && (n <= N)
Mndg(n + s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
elseif (N < n) && (n <= 2*N)
Mndg(n + s) = floor(N^2 + n^2/4 - N*n);
elseif n > 2*N
Mndg(n + s) = 0;
end
end
end

View File

@@ -0,0 +1,18 @@
function frequency = wavelength2frequency(wavelength, inputUnit)
% Convert wavelength to optical frequency.
% Supported units: m, nm.
c = physconst('LightSpeed');
switch lower(inputUnit)
case 'm'
wavelength_m = wavelength;
case 'nm'
wavelength_m = wavelength .* 1e-9;
otherwise
error('Unsupported input unit "%s". Use "m" or "nm".', inputUnit);
end
frequency = c ./ wavelength_m;
end

View File

@@ -0,0 +1,25 @@
Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
Institute for Communications Engineering (LNT)
Technical University of Munich, Germany
www.lnt.ei.tum.de
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,24 @@
## MI-CG: Numerically Computing Achievable Rates of Memoryless Channels
This repository provides a MATLAB function mi_cg.m to numerically compute achievable rates for memoryless channels. The function uses a conditionally-Gaussian (CG) channel model to obtain a lower bound on the achievable rate of the true channel. The method is well-known, and it is explained in [this short document](https://mediatum.ub.tum.de/node?id=1533663). Two example scripts that compute several achievable rate curves are also provided.
### Citation
This software and the accompanying document are meant as a tutorial to get started with mutual information as a numerical figure of merit for a communications channel. The software is provided under the open-source [MIT license](https://opensource.org/licenses/MIT). If you use the software in your academic work, please cite the accompanying [document](https://mediatum.ub.tum.de/node?id=1533663) as follows:
> F. J. Garcia-Gomez, “Numerically computing achievable rates of memoryless channels,” TUM University Library, 2019. [Online]. Available: https://mediatum.ub.tum.de/node?id=1533663
The corresponding BibTeX entry is
```
@article{garcia2019numerically,
author = "Francisco Javier Garcia-Gomez",
title = "Numerically Computing Achievable Rates of Memoryless Channels",
year = "2019",
journal="TUM University Library",
url={https://mediatum.ub.tum.de/node?id=1533663}
}
```
### Acknowledgment
This work was supported by the German Research Foundation (DFG) under Grant KR 3517/8-2.

View File

@@ -0,0 +1,156 @@
function air = air(x,r,idx_tx,Px,M_training)
MAX_MEMORY = 200e6; % maximum allowed size for a matrix
if nargin == 3
Px = [];
M_training = [];
end
if nargin == 4
M_training = [];
end
% if input is complex, separate into real and imaginary parts
if any(imag(x(:))~=0) || any(imag(r(:))~=0)
x = [real(x); imag(x)];
r = [real(r); imag(r)];
end
D = size(x, 1); % D = 2 if complex x
N = size(x, 2); % number of constellation points
M = size(r, 2); % number of samples
% set default training set size
if isempty(M_training)
M_training = ceil(0.3*M);
end
M_testing = M - M_training;
% Training: estimate parameters of the conditionally Gaussian model
% sort according to transmit index
[idx_tx_training, idx_sort] = sort(idx_tx(1:M_training));
r_training = r(:, idx_sort);
i_bounds = zeros(1, N+1);
% compute conditional means and covariance matrices
C_n = zeros(D, D, N);
det_n = zeros(1, N);
for n=1:N
% find how many times x(:, n) was transmitted and update i_bounds
N_current_x = find(idx_tx_training((i_bounds(n)+1):end)==n, 1, 'last');
if isempty(N_current_x), N_current_x=0; end
i_bounds(n+1) = i_bounds(n) + N_current_x;
if N_current_x > 0
% Compute mu_n=E[Y|X=x_n] according to Eq. (14) and store it in
% x(:, n) to save space
x(:, n) = sum(r_training(:, (i_bounds(n)+1):i_bounds(n+1)), 2)/(i_bounds(n+1)-i_bounds(n));
% compute C_n=cov[Y|X=x_n] according to Eq. (15)
r_meanfree = r_training(:, (i_bounds(n)+1):i_bounds(n+1)) - x(:, n);
C_n(:, :, n) = (r_meanfree*r_meanfree')/(i_bounds(n+1)-i_bounds(n));
% store also the determinant of C(:, :, n)
det_n(n) = det(C_n(:, :, n));
% if the determinant is 0, or if the matrix is badly conditioned,
% regularize by adding a small identity matrix. Note that we do
% need the check for 0 determinant, in case a cloud has exactly 0
% variance according to the training set
if det_n(n)==0 || cond(C_n(:, :, n))>1e16
C_n(:, :, n) = C_n(:, :, n) + 5 * eps * eye(D);
det_n(n) = (5*eps)^D;
end
end
end
% uniform input pmf Px if not provided
if isempty(Px)
Px = repmat(1/N, [1, N]);
end
% extract testing set and sort it according to transmit index
[idx_tx_testing, idx_sort] = sort(idx_tx((M_training+1):M));
r_testing = r(:, M_training+idx_sort);
% computation of h(Y|X)
h_Y_X = 0;
i_bounds_testing = zeros(1, N+1);
% loop over constellation points to compute h(Y|X)
for n = 1:N
% find how many times x(:, n) was transmitted and update
% i_bounds_testing
N_current_x = find(idx_tx_testing((i_bounds_testing(n)+1):end)==n, 1, 'last');
if isempty(N_current_x), N_current_x=0; end
i_bounds_testing(n+1) = i_bounds_testing(n) + N_current_x;
% add the corresponding contribution to the mutual information (two
% first lines of Eq. (17)). This, together with
% D/2*log2(2*pi) after the end of the loop, gives h(Y|X)
h_Y_X = h_Y_X + N_current_x * log2(det_n(n))/2+...
sum(sum(conj(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)).*(C_n(:, :, n)\(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)))))/2/log(2);
end
h_Y_X = D/2*log2(2*pi) + h_Y_X/M_testing;
% When computing log(py), we might run out of memory. If necessary, we
% doe the computation in blocks
logpy = zeros(1, M_testing);
BLOCK_SIZE = floor(MAX_MEMORY/N);
N_blocks = ceil(M_testing/BLOCK_SIZE);
% loop over blocks of symbols. This loop can be replaced by parfor to allow
% parallel computation
for i_block = 1:N_blocks
logpy_cur = zeros(1, M_testing);
% beginning of block
i_start = (i_block-1) * BLOCK_SIZE + 1;
% end of block
i_end = min(M_testing, i_block*BLOCK_SIZE);
% block size
current_block_size = i_end-i_start+1;
% compute exponents of third line of (17)
exponents = zeros(N, current_block_size);
for n = 1:N
exponents(n, :) = -log(det_n(n))/2-real(sum(conj(r_testing(:, i_start:i_end)-x(:, n)).*(C_n(:, :, n)\(r_testing(:, i_start:i_end)-x(:, n))), 1))/2;
%sum über 2 einträge von r
end
% compute third line of Eq. (17). Use a custom function
% that computes log(sum(exp(x))) avoiding overflow errors
logpy_cur(i_start:i_end) = math_logsumexp(log(Px(:))+exponents, 1);
logpy = logpy + logpy_cur;
end
% output entropy h(Y)
h_Y = D/2*log2(2*pi) - mean(logpy)/log(2);%log basis change
% compute mutual information
air = h_Y - h_Y_X;
end
function [y] = math_logsumexp(x, dim)
%[y] = math_logsumexp(x, dim)
% Computes log(sum(exp(x), dim)), avoiding overflow errors when one of the
% x is large.
if nargin<2 || isempty(dim)
m = max(x);
y = m + log(sum(exp(x-m)));
else
m = max(x, [], dim);
y = m + log(sum(exp(x-m), dim));
end
end

View File

@@ -0,0 +1,124 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two complex sequences. This file simulates a
% one-dimensional complex AWGN channel with 16-QAM constellation for
% different SNRs, and then plots the achievable rate, which is equal to two
% times the 4-PAM curve of Fig. 1 of [1].
%
% Note that using mi_cg with complex sequences assumes that the channel
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
% received clouds are circular). This is not the case in a channel with
% phase noise: see example_it_mi_cg.m for an example of how to deal with
% non-circularly-symmetric channels.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
% close all;
%%% Simulation parameters
M_QAM=16; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
X=[real(X); imag(X)]; % separate real and imaginary parts
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));%+1i*randn([1, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(1);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn = s+w;
%%%%%%%%%%%%
clf
hold on
xlim([-20, 20]);
ylim([-20, 20]);
%received signal
scatter(r_awgn(1,:),r_awgn(2,:),1,"red",'.');
%tx signal constellation
scatter(s(1,:),s(2,:),4,"black",'o','filled');
%uni power transmit constallation
scatter(X(1,:),X(2,:),5,'blue','o','filled');
drawnow
pause(0.1)
%%%%%%%%%%%%
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
I_shannon=log2(1+SNR_values);
figure(2);
hold on
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,140 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%% example_mi_cg_real_2D_awgn_vs_phasenoise %%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two sequences. This file simulates a two-dimensional
% AWGN channel with 4-PAM constellation (or, equivalently, a complex AWGN
% channel with 16-QAM constellation) for different SNRs, and then plots
% the achievable rate, reproducing the 4-PAM curve of Fig. 1 of [1]. Note
% that this curve can also be reproduced by simulating a 1-dimensional
% channel with 4-PAM: this file is an example of how to deal with multiple
% dimensions.
%
% This file also simulates a complex phase-noise channel:
% r=s.*exp(1i*theta)+w
% where w is complex AWGN and theta is i.i.d. real Gaussian. As q(Y|X) for
% this channel is not circularly-symmetric, this complex channel needs to
% be separated into two real dimensions to compute the mutual information.
% The resulting achievable rate is, as expected, below the rate for the
% AWGN channel.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% [2]
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
close all;
%%% Simulation parameters
D=1; % number of complex dimensions
M_QAM=16; % QAM size
var_w=1; % noise variance
E_theta=0.2; % phase offset for the phase noise channel
var_theta=0.05; % phase noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
X=[real(X); imag(X)]; % separate real and imaginary parts
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM^D, [1, N]);
%%% AWGN noise (real and imaginary parts)
w=sqrt(var_w/2)*randn([2*D, N]);
%%% phase noise
theta=E_theta+sqrt(var_theta)*randn([D, N]);
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
MI_phasenoise=zeros(1, n_SNR);
fig = figure(1);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn=s+w;
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx)/D;
% The following also works but is slower
% MI_awgn(i_SNR)=air(s, r_awgn)/D;
% Phase-noise channel
s_complex=s(1:2:end, :)+1i*s(2:2:end, :); % transform to complex
r_phasenoise_complex=s_complex.*exp(1i*theta); % phase noise and AWGN
r_phasenoise=zeros(2*D, N); % transform to real
r_phasenoise(1:2:end, :)=real(r_phasenoise_complex);
r_phasenoise(2:2:end, :)=imag(r_phasenoise_complex);
r_phasenoise=r_phasenoise+w; % add AWGN
clf
fig = scatter(r_phasenoise(1,:),r_phasenoise(2,:),1,'.');
xlim([-20, 20]);
ylim([-20, 20]);
drawnow
pause(0.1)
% Compute MI
MI_phasenoise(i_SNR)=air(X, r_phasenoise, idx_tx)/D;
% The following also works but is slower
% MI_phasenoise(i_SNR)=air(s, r_phasenoise)/D;
end
% Shannon capacity of the AWGN channel
I_shannon=log2(1+SNR_values);
figure;
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', '16-QAM, AWGN');
plot(SNR_dB_values, MI_phasenoise, '-.', 'DisplayName', ['16-QAM, Phase noise, \sigma_\Theta^2=' num2str(var_theta)]);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of 16-QAM in AWGN and in a phase noise channel with \theta~N(' num2str(E_theta) ', ' num2str(var_theta) ')']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,164 @@
colored_noise = true;
I_shannon=[];
for cmplx = [0,1]
cnt = 1;
for M_PAM = [4,8,16]
complex_constellation = cmplx;
%%% Simulation parameters
% M_PAM=2; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):1:35; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M=sqrt(M_PAM); % number of points per real dimension
if complex_constellation
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
else
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
end
X_ = X_ ./ rms(unique(X_));
X_=[real(X_); imag(X_)];
%%%%%%%%%%%%
figure(10);
clf
hold on
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
%%%%%%%%%%%%
%%% Uniformly choose transmit indices
idx_tx=randi(M_PAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(2);
if colored_noise
for i_SNR = 1:n_SNR
% Transmitted signal for the given indices
signal = X_(:, idx_tx);
% Generate white Gaussian noise of the same size as the signal
noise_white = randn(size(signal));
% Define the filter coefficient for colored noise (adjust as needed)
a = 0; % A higher value gives more correlation
% Filter the white noise to create colored noise.
% Here we filter each row (dimension) independently.
noise_colored = zeros(size(signal));
noise_colored(1,:) = filter(1, [1, -a], noise_white(1,:));
noise_colored(2,:) = filter(1, [1, -a], noise_white(2,:));
% Compute signal and unscaled noise power for proper scaling.
signal_power = mean(abs(signal(:)).^2);
noise_power = mean(abs(noise_colored(:)).^2);
% Convert desired SNR from dB to linear scale.
SNR_linear = 10^(SNR_dB_values(i_SNR)/10);
% Scale the colored noise so that signal_power / noise_power equals SNR_linear.
scaling_factor = sqrt(signal_power / (SNR_linear * noise_power));
noise_colored_scaled = scaling_factor * noise_colored;
% Received signal is the sum of the signal and the scaled colored noise.
r_colored = signal + noise_colored_scaled;
% For SNR measurement, compute the noise actually added.
measured_noise = r_colored - signal;
snr_meas_(i_SNR) = snr(signal(1,:) + 1i*signal(2,:), ...
measured_noise(1,:) + 1i*measured_noise(2,:));
% Plotting the transmitted and received signal
clf;
hold on;
xlim([-4, 4]);
ylim([-4, 4]);
scatter(signal(1,:), signal(2,:), 3, "black", 'o', 'DisplayName','Tx Constellation');
scatter(r_colored(1,:), r_colored(2,:), 1, "red", 'x', 'DisplayName', 'Colored Noise Mapping');
drawnow;
% Compute Mutual Information (or any other metric) with the new channel
MI_awgn_(i_SNR) = air(X_, r_colored, idx_tx);
end
else
for i_SNR=1:n_SNR
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
% r_awgn_ = s_ + w;
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
%%%%%%%%%%%%
clf
hold on
xlim([-4, 4]);
ylim([-4, 4]);
%received signal
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
drawnow
%%%%%%%%%%%%
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
end
figure(3);
hold on
if isempty(I_shannon)
I_shannon=log2(1+db2pow(snr_meas_));
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
end
cols = [ 0.9047 0.1918 0.1988
0.2941 0.5447 0.7494
0.3718 0.7176 0.3612
1.0000 0.5482 0.1000
0.8650 0.8110 0.4330
0.6859 0.4035 0.2412];
if complex_constellation
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
else
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
end
hold off;
ylim([0,8]);
xlim([min(SNR_dB_values) max(SNR_dB_values)])
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
cnt = cnt+1;
end
end

View File

@@ -0,0 +1,104 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two complex sequences. This file simulates a
% one-dimensional complex AWGN channel with 16-QAM constellation for
% different SNRs, and then plots the achievable rate, which is equal to two
% times the 4-PAM curve of Fig. 1 of [1].
%
% Note that using mi_cg with complex sequences assumes that the channel
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
% received clouds are circular). This is not the case in a channel with
% phase noise: see example_it_mi_cg.m for an example of how to deal with
% non-circularly-symmetric channels.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
close all;
%%% Simulation parameters
M_QAM=16; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w/2)*(randn([1, N])+1i*randn([1, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn = s+w;
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
% The following also works but is slower: MI_awgn(i_SNR)=air(s, r_awgn);
end
I_shannon=log2(1+SNR_values);
figure;
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,135 @@
clear;
I_shannon=[];
for cmplx = [1,0]
cnt = 1;
for M_PAM = [2,4,8,16]
% close all;
usegarcia = 0;
complex_constellation = cmplx;
%%% Simulation parameters
% M_PAM=2; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):1:35; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M=sqrt(M_PAM); % number of points per real dimension
if complex_constellation
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
else
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
end
X_ = X_ ./ rms(unique(X_));
X_=[real(X_); imag(X_)];
%%%%%%%%%%%%
figure(10);
clf
hold on
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
%%%%%%%%%%%%
%%% Uniformly choose transmit indices
idx_tx=randi(M_PAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(2);
for i_SNR=1:n_SNR
if usegarcia
%scale transmitted points acc. to SNR condition (this is not correct I think, the papaer also show diff results)
% s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
%scale nosie acc. to snr condition
noise_power = mean(abs(X_(1, idx_tx)+1i*X_(2, idx_tx)).^2) / SNR_values(i_SNR); % Noise power
w_ = sqrt(noise_power) .* w / sqrt(2);
% AWGN channel
r_awgn = X(:, idx_tx)+w_;
% snr_meas(i_SNR) = snr(s(1,:)+1i*s(2,:),w(1,:)+1i*w(2,:));
snr_meas(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx),w_(1,:)+1i*w_(2,:));
end
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
% r_awgn_ = s_ + w;
if cmplx
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
else
r_awgn_ = awgn(X_(1, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(1,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx) , w_awgn_matlab(1,:));
end
%%%%%%%%%%%%
clf
hold on
xlim([-4, 4]);
ylim([-4, 4]);
%received signal
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
if cmplx
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
else
scatter(r_awgn_,zeros(size(r_awgn_)),1,"red",'x','DisplayName','Matlab Mapping');
end
drawnow
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
figure(4);
hold on
if isempty(I_shannon)
I_shannon=log2(1+db2pow(snr_meas_));
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
end
if usegarcia
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', ['GARCIA ',num2str(M_PAM) '-QAM, AWGN']);
end
cols = linspecer(6);
if complex_constellation
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
else
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
end
hold off;
ylim([0,8]);
xlim([min(SNR_dB_values) max(SNR_dB_values)])
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
autoArrangeFigures;
cnt = cnt+1;
end
end