Source code for Examples.GuiEtAl2018
# This file is part of NFDMLab.
#
# NFDMLab is free software; you can redistribute it and/or
# modify it under the terms of the version 2 of the GNU General
# Public License as published by the Free Software Foundation.
#
# NFDMLab is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with NFDMLab; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Contributors:
# Sander Wahls (TU Delft) 2018-2019
# Shrinivas Chimmalgi (TU Delft) 2018
import numpy as np
import math
from Examples import BaseExample
[docs]class GuiEtAl2018(BaseExample):
'''This example loosely recreates the experiment presented in the paper
"Nonlinear frequency division multiplexing with b-modulation: shifting the
energy barrier " by T. Gui, G. Zhou, C. Lu, A.P.T. Lau, and S. Wahls
published in Optics Express 26(21), 2018.'''
def __init__(self):
# Fiber parameters
self.beta2 = -5e-27
"""Dispersion parameter in s**2/m."""
self.gamma = 1.2e-3
"""Nonlinearity parameter in (W m)**(-1)."""
self.Tscale = 1.25e-9 # s
"""Time scale used during normalization in s."""
self.alpha = np.array([0.2e-3])
"""Loss coefficient in 1/m."""
self.post_boost = True
"""Boost at the end of each span (lumped amplification). True or
False."""
self.path_average = True
"""Use path-averaged fiber parameters during normalization. True or
False."""
self.noise = True
"""Add ASE noise during amplification (only if post_boost == True).
True or False."""
self.noise_figure = 3
"""Noise figure in dB."""
self.n_spans = 8
"""Number of fiber spans."""
self.fiber_span_length = 80e3
"""Length of a fiber span in m."""
self.n_steps_per_span = 40
"""Number of spatial steps per span during the numerical simulation of
the fiber transmission."""
# Modulator parameters
self.constellation_level = 16
"""Level of the QAM constellation used as input for the reshaping
process (4, 16, 256, ...)."""
self.n_symbols_per_block = 9
"""Number of carriers."""
self.Ed = 4
"""Desired average pulse energy in normalized units. Used during the
reshaping of the constellation. (See the paper for details.)"""
# Filters
self.tx_bandwidth = 33e9
"""Bandwidth of the (ideal) low-pass filter at the transmitter in Hz."""
self.rx_bandwidth = 33e9 # in GHz
"""Bandwidth of the (ideal) low-pass filter at the receiver in Hz."""
self.reconfigure()
[docs] def reconfigure(self):
distance = self.n_spans*self.fiber_span_length #m
from Modulators.CarrierWaveforms import flat_top
carrier_waveform = lambda xi : flat_top(xi, T0)
self._carrier_spacing = 15.0
T0 = 4.5
T = np.array([-1.0, 1.0])
# Normalization
if self.path_average == True:
from Normalization import Lumped
self._normalization = Lumped(self.beta2,
self.gamma,
self.Tscale,
alpha=np.mean(self.alpha)*np.log(10)*0.1,
zamp=self.fiber_span_length)
else:
from Normalization import Lossless
self._normalization = Lossless(self.beta2, self.gamma, self.Tscale)
# Constellation
from Constellations import ReshapedQAMConstellation
m = int(math.sqrt(self.constellation_level))
assert self.constellation_level == m*m
bnds = np.array([0, 4/np.abs(carrier_waveform(0.0))])
self._constellation = ReshapedQAMConstellation(m, m,
carrier_waveform,
self.Ed, bnds)
# Modulator
from Modulators import ContSpecModulator
normalized_distance = self.normalization.norm_dist(distance)
normalized_duration = T[1] - T[0]
required_normalized_dt = normalized_duration/self.n_symbols_per_block/8
required_dxi = self._carrier_spacing / 8
self._modulator = ContSpecModulator(carrier_waveform,
self._carrier_spacing,
self.n_symbols_per_block,
normalized_distance,
T,
required_normalized_dt,
required_dxi,
"b")
# Link
from Links import SMFSplitStep
dt = self._normalization.denorm_time(self.modulator.normalized_dt)
dz = self.fiber_span_length/self.n_steps_per_span
self._link = SMFSplitStep(dt, dz, self.n_steps_per_span, self.alpha,
self.beta2, self.gamma, False, self.n_spans,
self.post_boost, self.noise, self.noise_figure)
# Filters
from Filters import PassThrough
self._tx_filter = PassThrough()
from Filters import FFTLowPass
self._rx_filter = FFTLowPass(self.rx_bandwidth/2, dt)