Introduce computation of the chromatic dispersion

Change-Id: I3ee039154568d4255444fa8db5e89945851010f4
This commit is contained in:
Alessio Ferrari
2020-05-21 11:00:17 +02:00
committed by Jan Kundrát
parent b74d0a4919
commit 94949d955b
5 changed files with 76 additions and 16 deletions

View File

@@ -22,7 +22,7 @@ instance as a result.
from numpy import abs, arange, array, divide, errstate, ones
from numpy import interp, mean, pi, polyfit, polyval, sum
from scipy.constants import h
from scipy.constants import h, c
from collections import namedtuple
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
@@ -82,6 +82,12 @@ class Transceiver(_Node):
self.snr = None
self.passive = False
self.baud_rate = None
self.chromatic_dispersion = None
def _calc_cd(self, spectral_info):
""" Updates the Transceiver property with the CD of the received channels. CD in ps/nm.
"""
self.chromatic_dispersion = [carrier.chromatic_dispersion * 1e3 for carrier in spectral_info.carriers]
def _calc_snr(self, spectral_info):
with errstate(divide='ignore'):
@@ -141,7 +147,8 @@ class Transceiver(_Node):
f'osnr_ase_01nm={self.osnr_ase_01nm!r}, '
f'osnr_ase={self.osnr_ase!r}, '
f'osnr_nli={self.osnr_nli!r}, '
f'snr={self.snr!r})')
f'snr={self.snr!r}, '
f'chromatic_dispersion={self.chromatic_dispersion!r})')
def __str__(self):
if self.snr is None or self.osnr_ase is None:
@@ -151,16 +158,19 @@ class Transceiver(_Node):
osnr_ase = round(mean(self.osnr_ase), 2)
osnr_ase_01nm = round(mean(self.osnr_ase_01nm), 2)
snr_01nm = round(mean(self.snr_01nm), 2)
cd = mean(self.chromatic_dispersion)
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}',
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}',
f' SNR total (signal bw, dB): {snr:.2f}',
f' SNR total (0.1nm, dB): {snr_01nm:.2f}'])
f' SNR total (0.1nm, dB): {snr_01nm:.2f}',
f' CD (ps/nm): {cd:.2f}'])
def __call__(self, spectral_info):
self._calc_snr(spectral_info)
self._calc_cd(spectral_info)
return spectral_info
@@ -377,6 +387,20 @@ class Fiber(_Node):
"""
return self.alpha(f_ref * ones(1))[0]
def chromatic_dispersion(self, freq=193.5e12):
""" Returns accumulated chromatic dispersion (CD).
:param freq: the frequency at which the chromatic dispersion is computed
:return: chromatic dispersion: the accumulated dispersion [s/m]
"""
beta2 = self.params.beta2
beta3 = self.params.beta3
ref_f = self.params.ref_frequency
length = self.params.length
beta = beta2 + 2 * pi * beta3 * (freq - ref_f)
dispersion = -beta * 2 * pi * ref_f**2 / c
return dispersion * length
def _gn_analytic(self, carrier, *carriers):
"""Computes the nonlinear interference power on a single carrier.
The method uses eq. 120 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__.
@@ -423,7 +447,8 @@ class Fiber(_Node):
pwr = pwr._replace(signal=pwr.signal / self.params.lin_attenuation / attenuation,
nli=(pwr.nli + carrier_nli) / self.params.lin_attenuation / attenuation,
ase=pwr.ase / self.params.lin_attenuation / attenuation)
yield carrier._replace(power=pwr)
chromatic_dispersion = carrier.chromatic_dispersion + self.chromatic_dispersion(carrier.frequency)
yield carrier._replace(power=pwr, chromatic_dispersion=chromatic_dispersion)
def update_pref(self, pref):
self.pch_out_db = round(pref.p_spani - self.loss, 2)
@@ -461,6 +486,9 @@ class RamanFiber(Fiber):
def propagate(self, *carriers):
for propagated_carrier in propagate_raman_fiber(self, *carriers):
chromatic_dispersion = propagated_carrier.chromatic_dispersion + \
self.chromatic_dispersion(propagated_carrier.frequency)
propagated_carrier = propagated_carrier._replace(chromatic_dispersion=chromatic_dispersion)
yield propagated_carrier