mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-29 17:22:42 +00:00
Compare commits
29 Commits
v2.10
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9924acbf1 | ||
|
|
0a98744938 | ||
|
|
2d5909560e | ||
|
|
4c6f381e61 | ||
|
|
ceeb28f57e | ||
|
|
7c90ae4809 | ||
|
|
603b28ac08 | ||
|
|
79059e13e8 | ||
|
|
a9d616818a | ||
|
|
f0b56bcaff | ||
|
|
4b94481ecb | ||
|
|
e851220f81 | ||
|
|
496ec25661 | ||
|
|
93dfadca35 | ||
|
|
12e58e3dbf | ||
|
|
5c32805073 | ||
|
|
c5b3914e25 | ||
|
|
4f9193fab4 | ||
|
|
72edade853 | ||
|
|
541ee734a4 | ||
|
|
d312c99ee1 | ||
|
|
839f4fea6c | ||
|
|
05da89fbf2 | ||
|
|
3377906002 | ||
|
|
ac16df54d1 | ||
|
|
def82b6515 | ||
|
|
3910803dfa | ||
|
|
c75d66b46d | ||
|
|
e8db766eec |
@@ -61,25 +61,33 @@ Fiber
|
||||
|
||||
The fiber library currently describes SSMF and NZDF but additional fiber types can be entered by the user following the same model:
|
||||
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
| field | type | description |
|
||||
+======================+===========+==========================================+
|
||||
| ``type_variety`` | (string) | a unique name to ID the fiber in the |
|
||||
| | | JSON or Excel template topology input |
|
||||
| | | file |
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
| ``dispersion`` | (number) | In :math:`s \times m^{-1} \times m^{-1}`.|
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
| ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} |
|
||||
| | | \times m^{-1}` |
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
| ``gamma`` | (number) | :math:`2\pi\times n^2/(\lambda*A_{eff})`,|
|
||||
| | | in :math:`w^{-1} \times m^{-1}`. |
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
|
||||
| | | coefficient. In |
|
||||
| | | :math:`s\times\sqrt{m}^{-1}`. |
|
||||
+----------------------+-----------+------------------------------------------+
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| field | type | description |
|
||||
+============================+===========+==========================================+
|
||||
| ``type_variety`` | (string) | a unique name to ID the fiber in the |
|
||||
| | | JSON or Excel template topology input |
|
||||
| | | file |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``dispersion`` | (number) | In :math:`s \times m^{-1} \times m^{-1}`.|
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} |
|
||||
| | | \times m^{-1}` |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``gamma`` | (number) | :math:`2\pi\times n^2/(\lambda*A_{eff})`,|
|
||||
| | | in :math:`w^{-1} \times m^{-1}`. |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
|
||||
| | | coefficient. In |
|
||||
| | | :math:`s\times\sqrt{m}^{-1}`. |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``lumped_losses.loss`` | (number) | Array of lumped loss , expressed in dB, |
|
||||
| | | values along the fiber due to spool |
|
||||
| | | junctions. |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
| ``lumped_losses.position`` | (number) | Array of positions, expressed in km, |
|
||||
| | | of the lumped losses along the fiber |
|
||||
| | | due to spool junctions. |
|
||||
+----------------------------+-----------+------------------------------------------+
|
||||
|
||||
Transceiver
|
||||
~~~~~~~~~~~
|
||||
@@ -176,6 +184,33 @@ Only the EDFA that are marked ``'allowed_for_design': true`` are considered.
|
||||
|
||||
For amplifiers defined in the topology JSON input but whose ``gain = 0`` (placeholder), auto-design will set its gain automatically: see ``power_mode`` in the ``Spans`` library to find out how the gain is calculated.
|
||||
|
||||
The file ``sim_params.json`` contains the tuning parameters used within both the ``gnpy.science_utils.RamanSolver`` and
|
||||
the ``gnpy.science_utils.NliSolver`` for the evaluation of the Raman profile and the NLI generation, respectively.
|
||||
A global variable of ``gnpy.parameters.SimParams`` is created for each simulation and it is shared between all the fiber
|
||||
instances, assuring a coherent simulation.
|
||||
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| field | type | description |
|
||||
+============================================+===========+=============================================+
|
||||
| ``raman_params.flag`` | (boolean) | Enable/Disable Raman profile evaluation |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``raman_params.result_spatial_resolution`` | (number) | Spatial resolution of the output |
|
||||
| | | Raman profile |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``raman_params.solver_spatial_resolution`` | (number) | Spatial step for the iterative solution |
|
||||
| | | of the first order differential equation |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``nli_params.method`` | (string) | Model used for the NLI evaluation |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``nli_params.dispersion_tolerance`` | (number) | Tuning parameter for the NliSolver |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``nli_params.phase_shift_tolerance`` | (number) | Tuning parameter for the NliSolver |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
| ``nli_params.computed_channels`` | (number) | The channels on which the NLI is |
|
||||
| | | explicitly evaluated |
|
||||
+--------------------------------------------+-----------+---------------------------------------------+
|
||||
|
||||
|
||||
Span
|
||||
~~~~
|
||||
|
||||
|
||||
@@ -20,13 +20,19 @@ unique identifier and a printable name, and provide the :py:meth:`__call__` meth
|
||||
instance as a result.
|
||||
"""
|
||||
|
||||
from numpy import abs, arange, array, divide, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt
|
||||
from numpy import abs, array, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt, log10, exp, asarray, full,\
|
||||
squeeze, zeros, append, flip, outer, minimum
|
||||
from scipy.constants import h, c
|
||||
from scipy.interpolate import interp1d
|
||||
from collections import namedtuple
|
||||
|
||||
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
|
||||
from gnpy.core.parameters import FiberParams, PumpParams
|
||||
from gnpy.core.science_utils import NliSolver, RamanSolver, propagate_raman_fiber, _psi
|
||||
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum, per_label_summary, pretty_summary_print,\
|
||||
watt2dbm, psd2powerdbm, psdmwperghz, powerdbm2psdmwperghz
|
||||
from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational
|
||||
from gnpy.core.science_utils import NliSolver, RamanSolver
|
||||
from gnpy.core.info import SpectralInformation
|
||||
from gnpy.core import ansi_escapes
|
||||
from gnpy.core.exceptions import NetworkTopologyError, ParametersError
|
||||
|
||||
|
||||
class Location(namedtuple('Location', 'latitude longitude city region')):
|
||||
@@ -83,28 +89,24 @@ class Transceiver(_Node):
|
||||
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]
|
||||
self.chromatic_dispersion = spectral_info.chromatic_dispersion * 1e3
|
||||
|
||||
def _calc_pmd(self, spectral_info):
|
||||
"""Updates the Transceiver property with the PMD of the received channels. PMD in ps.
|
||||
"""
|
||||
self.pmd = [carrier.pmd*1e12 for carrier in spectral_info.carriers]
|
||||
self.pmd = spectral_info.pmd * 1e12
|
||||
|
||||
def _calc_snr(self, spectral_info):
|
||||
with errstate(divide='ignore'):
|
||||
self.baud_rate = [c.baud_rate for c in spectral_info.carriers]
|
||||
ratio_01nm = [lin2db(12.5e9 / b_rate) for b_rate in self.baud_rate]
|
||||
self.label = spectral_info.label
|
||||
self.baud_rate = spectral_info.baud_rate
|
||||
ratio_01nm = lin2db(12.5e9 / self.baud_rate)
|
||||
# set raw values to record original calculation, before update_snr()
|
||||
self.raw_osnr_ase = [lin2db(divide(c.power.signal, c.power.ase))
|
||||
for c in spectral_info.carriers]
|
||||
self.raw_osnr_ase_01nm = [ase - ratio for ase, ratio
|
||||
in zip(self.raw_osnr_ase, ratio_01nm)]
|
||||
self.raw_osnr_nli = [lin2db(divide(c.power.signal, c.power.nli))
|
||||
for c in spectral_info.carriers]
|
||||
self.raw_snr = [lin2db(divide(c.power.signal, c.power.nli + c.power.ase))
|
||||
for c in spectral_info.carriers]
|
||||
self.raw_snr_01nm = [snr - ratio for snr, ratio
|
||||
in zip(self.raw_snr, ratio_01nm)]
|
||||
self.raw_osnr_ase = lin2db(spectral_info.signal / spectral_info.ase)
|
||||
self.raw_osnr_ase_01nm = self.raw_osnr_ase - ratio_01nm
|
||||
self.raw_osnr_nli = lin2db(spectral_info.signal / spectral_info.nli)
|
||||
self.raw_snr = lin2db(spectral_info.signal / (spectral_info.ase + spectral_info.nli))
|
||||
self.raw_snr_01nm = self.raw_snr - ratio_01nm
|
||||
|
||||
self.osnr_ase = self.raw_osnr_ase
|
||||
self.osnr_ase_01nm = self.raw_osnr_ase_01nm
|
||||
@@ -124,14 +126,10 @@ class Transceiver(_Node):
|
||||
for s in args:
|
||||
snr_added += db2lin(-s)
|
||||
snr_added = -lin2db(snr_added)
|
||||
self.osnr_ase = list(map(lambda x, y: snr_sum(x, y, snr_added),
|
||||
self.raw_osnr_ase, self.baud_rate))
|
||||
self.snr = list(map(lambda x, y: snr_sum(x, y, snr_added),
|
||||
self.raw_snr, self.baud_rate))
|
||||
self.osnr_ase_01nm = list(map(lambda x: snr_sum(x, 12.5e9, snr_added),
|
||||
self.raw_osnr_ase_01nm))
|
||||
self.snr_01nm = list(map(lambda x: snr_sum(x, 12.5e9, snr_added),
|
||||
self.raw_snr_01nm))
|
||||
self.osnr_ase = snr_sum(self.raw_osnr_ase, self.baud_rate, snr_added)
|
||||
self.snr = snr_sum(self.raw_snr, self.baud_rate, snr_added)
|
||||
self.osnr_ase_01nm = snr_sum(self.raw_osnr_ase_01nm, 12.5e9, snr_added)
|
||||
self.snr_01nm = snr_sum(self.raw_snr_01nm, 12.5e9, snr_added)
|
||||
|
||||
@property
|
||||
def to_json(self):
|
||||
@@ -156,19 +154,19 @@ class Transceiver(_Node):
|
||||
if self.snr is None or self.osnr_ase is None:
|
||||
return f'{type(self).__name__} {self.uid}'
|
||||
|
||||
snr = round(mean(self.snr), 2)
|
||||
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)
|
||||
snr = per_label_summary(self.snr, self.label)
|
||||
osnr_ase = per_label_summary(self.osnr_ase, self.label)
|
||||
osnr_ase_01nm = per_label_summary(self.osnr_ase_01nm, self.label)
|
||||
snr_01nm = per_label_summary(self.snr_01nm, self.label)
|
||||
cd = mean(self.chromatic_dispersion)
|
||||
pmd = mean(self.pmd)
|
||||
|
||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||
|
||||
f' GSNR (0.1nm, dB): {snr_01nm:.2f}',
|
||||
f' GSNR (signal bw, dB): {snr:.2f}',
|
||||
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}',
|
||||
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}',
|
||||
f' GSNR (0.1nm, dB): {pretty_summary_print(snr_01nm)}',
|
||||
f' GSNR (signal bw, dB): {pretty_summary_print(snr)}',
|
||||
f' OSNR ASE (0.1nm, dB): {pretty_summary_print(osnr_ase_01nm)}',
|
||||
f' OSNR ASE (signal bw, dB): {pretty_summary_print(osnr_ase)}',
|
||||
f' CD (ps/nm): {cd:.2f}',
|
||||
f' PMD (ps): {pmd:.2f}'])
|
||||
|
||||
@@ -179,29 +177,41 @@ class Transceiver(_Node):
|
||||
return spectral_info
|
||||
|
||||
|
||||
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr pmd restrictions per_degree_pch_out_db')
|
||||
|
||||
|
||||
class Roadm(_Node):
|
||||
def __init__(self, *args, params, **kwargs):
|
||||
if 'per_degree_pch_out_db' not in params.keys():
|
||||
params['per_degree_pch_out_db'] = {}
|
||||
super().__init__(*args, params=RoadmParams(**params), **kwargs)
|
||||
def __init__(self, *args, params=None, **kwargs):
|
||||
if not params:
|
||||
params = {}
|
||||
try:
|
||||
super().__init__(*args, params=RoadmParams(**params), **kwargs)
|
||||
except ParametersError as e:
|
||||
raise ParametersError('Config error in ', kwargs['uid'], ' .', e)
|
||||
# target power as defined by user
|
||||
self.target_pch_out_dbm = self.params.target_pch_out_db
|
||||
# reference power is target power by default. depending on propagation this may change (due to equalization)
|
||||
self.ref_pch_out_dbm = self.params.target_pch_out_db
|
||||
self.loss = 0 # auto-design interest
|
||||
self.effective_loss = None
|
||||
self.effective_pch_out_db = self.params.target_pch_out_db
|
||||
self.ref_effective_loss = None
|
||||
self.passive = True
|
||||
self.restrictions = self.params.restrictions
|
||||
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db
|
||||
# element contains the two types of equalisation parameters, but only one is not None or empty
|
||||
self.target_psd_out_mWperGHz = self.params.target_psd_out_mWperGHz
|
||||
self.per_degree_pch_psd = self.params.per_degree_pch_psd
|
||||
|
||||
@property
|
||||
def to_json(self):
|
||||
if self.ref_pch_out_dbm:
|
||||
equalisation, value = 'target_pch_out_db', self.ref_pch_out_dbm
|
||||
perdegree, perdegreevalue = 'per_degree_pch_out_db', self.per_degree_pch_out_db
|
||||
if self.target_psd_out_mWperGHz:
|
||||
equalisation, value = 'target_psd_out_mWperGHz', self.target_psd_out_mWperGHz
|
||||
perdegree, perdegreevalue = 'per_degree_psd_out_mWperGHz', self.per_degree_pch_psd
|
||||
return {'uid': self.uid,
|
||||
'type': type(self).__name__,
|
||||
'params': {
|
||||
'target_pch_out_db': self.effective_pch_out_db,
|
||||
equalisation: value,
|
||||
'restrictions': self.restrictions,
|
||||
'per_degree_pch_out_db': self.per_degree_pch_out_db
|
||||
perdegree: perdegreevalue
|
||||
},
|
||||
'metadata': {
|
||||
'location': self.metadata['location']._asdict()
|
||||
@@ -212,14 +222,16 @@ class Roadm(_Node):
|
||||
return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})'
|
||||
|
||||
def __str__(self):
|
||||
if self.effective_loss is None:
|
||||
if self.ref_effective_loss is None:
|
||||
return f'{type(self).__name__} {self.uid}'
|
||||
|
||||
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
|
||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||
f' effective loss (dB): {self.effective_loss:.2f}',
|
||||
f' pch out (dBm): {self.effective_pch_out_db:.2f}'])
|
||||
f' effective loss (dB): {self.ref_effective_loss:.2f}',
|
||||
f' pch out (dBm): {self.ref_pch_out_dbm:.2f}',
|
||||
f' total pch (dBm): {total_pch}'])
|
||||
|
||||
def propagate(self, pref, *carriers, degree):
|
||||
def propagate(self, spectral_info, degree):
|
||||
# pin_target and loss are read from eqpt_config.json['Roadm']
|
||||
# all ingress channels in xpress are set to this power level
|
||||
# but add channels are not, so we define an effective loss
|
||||
@@ -228,39 +240,72 @@ class Roadm(_Node):
|
||||
# if a target power has been defined for this degree use it else use the global one.
|
||||
# if the input power is lower than the target one, use the input power instead because
|
||||
# a ROADM doesn't amplify, it can only attenuate
|
||||
# TODO maybe add a minimum loss for the ROADM
|
||||
per_degree_pch = self.per_degree_pch_out_db[degree] if degree in self.per_degree_pch_out_db.keys() else self.params.target_pch_out_db
|
||||
self.effective_pch_out_db = min(pref.p_spani, per_degree_pch)
|
||||
self.effective_loss = pref.p_spani - self.effective_pch_out_db
|
||||
carriers_power = array([c.power.signal + c.power.nli + c.power.ase for c in carriers])
|
||||
carriers_att = list(map(lambda x: lin2db(x * 1e3) - per_degree_pch, carriers_power))
|
||||
exceeding_att = -min(list(filter(lambda x: x < 0, carriers_att)), default=0)
|
||||
carriers_att = list(map(lambda x: db2lin(x + exceeding_att), carriers_att))
|
||||
for carrier_att, carrier in zip(carriers_att, carriers):
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=pwr.signal / carrier_att,
|
||||
nli=pwr.nli / carrier_att,
|
||||
ase=pwr.ase / carrier_att)
|
||||
pmd = sqrt(carrier.pmd**2 + self.params.pmd**2)
|
||||
yield carrier._replace(power=pwr, pmd=pmd)
|
||||
|
||||
def update_pref(self, pref):
|
||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.effective_pch_out_db)
|
||||
# TODO maybe add a minimum loss for the ROADM
|
||||
# check equalization: if ref_pch_out_dbm is defined then use it
|
||||
# change per_degree_pch from scalar to an array / add a ref_power, ref_baudrate ...
|
||||
ref_baud_rate = spectral_info.pref.ref_carrier['baud_rate']
|
||||
if self.target_pch_out_dbm:
|
||||
per_degree_pch = self.per_degree_pch_out_db[degree] \
|
||||
if degree in self.per_degree_pch_out_db else self.target_pch_out_dbm
|
||||
ref_per_degree_pch = per_degree_pch
|
||||
per_degree_pch = per_degree_pch * ones(len(spectral_info.channel_number))
|
||||
elif self.target_psd_out_mWperGHz:
|
||||
per_degree_pch = psd2powerdbm(self.per_degree_pch_psd[degree], spectral_info.baud_rate) \
|
||||
if degree in self.per_degree_pch_psd \
|
||||
else psd2powerdbm(self.target_psd_out_mWperGHz, spectral_info.baud_rate)
|
||||
ref_per_degree_pch = psd2powerdbm(self.per_degree_pch_psd[degree], ref_baud_rate) \
|
||||
if degree in self.per_degree_pch_psd \
|
||||
else psd2powerdbm(self.target_psd_out_mWperGHz, ref_baud_rate)
|
||||
# definition of ref_pch_out_db for the reference channel: depending on propagation input power (p_spani) might
|
||||
# be smaller than the target power out of the roadm on this degree then use the min value between both
|
||||
self.ref_pch_out_dbm = min(spectral_info.pref.p_spani, ref_per_degree_pch)
|
||||
# definition of effective_loss: value for the reference channel
|
||||
self.ref_effective_loss = spectral_info.pref.p_spani - self.ref_pch_out_dbm
|
||||
input_power = spectral_info.signal + spectral_info.nli + spectral_info.ase
|
||||
# computation of the per channel target power according to equalization policy
|
||||
if self.target_pch_out_dbm:
|
||||
min_power = watt2dbm(min(input_power))
|
||||
per_degree_pch = minimum(per_degree_pch, min_power)
|
||||
elif self.target_psd_out_mWperGHz:
|
||||
# Assume that channels with same baudrate are equalized to the same power.
|
||||
# Applies the same min strategy if the input power is lower than the target one:
|
||||
# use the min psd of all carriers.
|
||||
# If all carriers have identical baud_rate, the target power is the min power
|
||||
# of the carrier compared to per_degree_pch (same as power equalization)
|
||||
min_psd = min(psdmwperghz(input_power, spectral_info.baud_rate))
|
||||
temp = powerdbm2psdmwperghz(per_degree_pch, spectral_info.baud_rate)
|
||||
per_degree_pch = psd2powerdbm(minimum(temp, min_psd), spectral_info.baud_rate)
|
||||
# target power should follow same delta power as in p_span0_per_channel
|
||||
# if no specific delta, then apply equalization (later on)
|
||||
pref = spectral_info.pref
|
||||
delta_channel_power = pref.p_span0_per_channel - pref.p_span0
|
||||
delta_power = watt2dbm(input_power) - (per_degree_pch + delta_channel_power)
|
||||
spectral_info.apply_attenuation_db(delta_power)
|
||||
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
|
||||
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
|
||||
self.label = spectral_info.label
|
||||
|
||||
def update_pref(self, spectral_info):
|
||||
""" updates the value in Pref in spectral_info. p_span0 and p_span0_per_channel are unchanged, only p_spani
|
||||
which contains the power for the reference channel after propagation in the ROADM.
|
||||
p_span0_per_channel corresponds exactly to the current mix of channels {freq: pow},
|
||||
it serves as reference to compute delta_power wrt ref channel.
|
||||
So, we implement two main equalisation: all channels with same power or same psd plus
|
||||
a user defined delta power based on p_span0_per_channel vector
|
||||
"""
|
||||
spectral_info.pref = spectral_info.pref._replace(p_spani=self.ref_pch_out_dbm)
|
||||
|
||||
def __call__(self, spectral_info, degree):
|
||||
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers, degree=degree))
|
||||
pref = self.update_pref(spectral_info.pref)
|
||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||
|
||||
|
||||
FusedParams = namedtuple('FusedParams', 'loss')
|
||||
self.propagate(spectral_info, degree=degree)
|
||||
self.update_pref(spectral_info)
|
||||
return spectral_info
|
||||
|
||||
|
||||
class Fused(_Node):
|
||||
def __init__(self, *args, params=None, **kwargs):
|
||||
if params is None:
|
||||
# default loss value if not mentioned in loaded network json
|
||||
params = {'loss': 1}
|
||||
if not params:
|
||||
params = {}
|
||||
super().__init__(*args, params=FusedParams(**params), **kwargs)
|
||||
self.loss = self.params.loss
|
||||
self.passive = True
|
||||
@@ -284,23 +329,17 @@ class Fused(_Node):
|
||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||
f' loss (dB): {self.loss:.2f}'])
|
||||
|
||||
def propagate(self, *carriers):
|
||||
attenuation = db2lin(self.loss)
|
||||
def propagate(self, spectral_info):
|
||||
spectral_info.apply_attenuation_db(self.loss)
|
||||
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=pwr.signal / attenuation,
|
||||
nli=pwr.nli / attenuation,
|
||||
ase=pwr.ase / attenuation)
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def update_pref(self, pref):
|
||||
return pref._replace(p_span0=pref.p_span0, p_spani=pref.p_spani - self.loss)
|
||||
def update_pref(self, spectral_info):
|
||||
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||
p_spani=spectral_info.pref.p_spani - self.loss)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
pref = self.update_pref(spectral_info.pref)
|
||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||
self.propagate(spectral_info)
|
||||
self.update_pref(spectral_info)
|
||||
return spectral_info
|
||||
|
||||
|
||||
class Fiber(_Node):
|
||||
@@ -309,7 +348,31 @@ class Fiber(_Node):
|
||||
params = {}
|
||||
super().__init__(*args, params=FiberParams(**params), **kwargs)
|
||||
self.pch_out_db = None
|
||||
self.nli_solver = NliSolver(self)
|
||||
self.passive = True
|
||||
|
||||
# Raman efficiency matrix function of the delta frequency
|
||||
if self.params.raman_efficiency:
|
||||
frequency_offset = self.params.raman_efficiency['frequency_offset']
|
||||
frequency_offset = append(-flip(frequency_offset[1:]), frequency_offset)
|
||||
cr = self.params.raman_efficiency['cr']
|
||||
cr = append(- flip(cr[1:]), cr)
|
||||
self._cr_function = lambda frequency: interp(frequency, frequency_offset, cr)
|
||||
else:
|
||||
self._cr_function = lambda frequency: zeros(squeeze(frequency).shape)
|
||||
|
||||
# Lumped losses
|
||||
if self.params.lumped_losses:
|
||||
z_lumped_losses = array([lumped['position'] for lumped in self.params.lumped_losses]) # km
|
||||
lumped_losses_power = array([lumped['loss'] for lumped in self.params.lumped_losses]) # dB
|
||||
if not ((z_lumped_losses > 0) * (z_lumped_losses < 1e-3 * self.params.length)).all():
|
||||
raise NetworkTopologyError(
|
||||
f"Lumped loss positions must be between 0 and the fiber length ({1e-3 * self.params.length} km), " +
|
||||
f"boundaries excluded.")
|
||||
self.lumped_losses = db2lin(- lumped_losses_power) # [linear units]
|
||||
self.z_lumped_losses = array(z_lumped_losses) * 1e3 # [m]
|
||||
else:
|
||||
self.lumped_losses = None
|
||||
self.z_lumped_losses = None
|
||||
|
||||
@property
|
||||
def to_json(self):
|
||||
@@ -339,6 +402,7 @@ class Fiber(_Node):
|
||||
if self.pch_out_db is None:
|
||||
return f'{type(self).__name__} {self.uid}'
|
||||
|
||||
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
|
||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||
f' type_variety: {self.type_variety}',
|
||||
f' length (km): {self.params.length * 1e-3:.2f}',
|
||||
@@ -346,38 +410,52 @@ class Fiber(_Node):
|
||||
f' total loss (dB): {self.loss:.2f}',
|
||||
f' (includes conn loss (dB) in: {self.params.con_in:.2f} out: {self.params.con_out:.2f})',
|
||||
f' (conn loss out includes EOL margin defined in eqpt_config.json)',
|
||||
f' pch out (dBm): {self.pch_out_db:.2f}'])
|
||||
f' pch out (dBm): {self.pch_out_db:.2f}',
|
||||
f' total pch (dBm): {total_pch}'])
|
||||
|
||||
def loss_coef_func(self, frequency):
|
||||
frequency = asarray(frequency)
|
||||
if self.params.loss_coef.size > 1:
|
||||
try:
|
||||
loss_coef = interp1d(self.params.f_loss_ref, self.params.loss_coef)(frequency)
|
||||
except ValueError as e:
|
||||
print(ansi_escapes.red +
|
||||
f'\n WARNING {e} ' + 'Value extrapolated.' + ansi_escapes.reset)
|
||||
loss_coef = interp1d(self.params.f_loss_ref, self.params.loss_coef, bounds_error=False,
|
||||
fill_value='extrapolate')(frequency)
|
||||
else:
|
||||
loss_coef = full(frequency.size, self.params.loss_coef)
|
||||
return squeeze(loss_coef)
|
||||
|
||||
|
||||
@property
|
||||
def loss(self):
|
||||
"""total loss including padding att_in: useful for polymorphism with roadm loss"""
|
||||
return self.params.loss_coef * self.params.length + self.params.con_in + self.params.con_out + self.params.att_in
|
||||
return self.loss_coef_func(self.params.ref_frequency) * self.params.length + \
|
||||
self.params.con_in + self.params.con_out + self.params.att_in
|
||||
|
||||
@property
|
||||
def passive(self):
|
||||
return True
|
||||
def lin_attenuation(self, frequency):
|
||||
return 1 / db2lin(self.params.length * self.loss_coef_func(frequency))
|
||||
|
||||
def alpha(self, frequencies):
|
||||
"""It returns the values of the series expansion of attenuation coefficient alpha(f) for all f in frequencies
|
||||
def alpha(self, frequency):
|
||||
"""Returns the linear exponent attenuation coefficient such that
|
||||
:math: `lin_attenuation = e^{- alpha length}`
|
||||
|
||||
:param frequencies: frequencies of series expansion [Hz]
|
||||
:return: alpha: power attenuation coefficient for f in frequencies [Neper/m]
|
||||
:param frequency: the frequency at which alpha is computed [Hz]
|
||||
:return: alpha: power attenuation coefficient for f in frequency [Neper/m]
|
||||
"""
|
||||
if type(self.params.loss_coef) == dict:
|
||||
alpha = interp(frequencies, self.params.f_loss_ref, self.params.lin_loss_exp)
|
||||
else:
|
||||
alpha = self.params.lin_loss_exp * ones(frequencies.shape)
|
||||
return self.loss_coef_func(frequency) / (10 * log10(exp(1)))
|
||||
|
||||
return alpha
|
||||
def cr(self, frequency):
|
||||
"""Returns the raman efficiency matrix including the vibrational loss
|
||||
|
||||
def alpha0(self, f_ref=193.5e12):
|
||||
"""It returns the zero element of the series expansion of attenuation coefficient alpha(f) in the
|
||||
reference frequency f_ref
|
||||
|
||||
:param f_ref: reference frequency of series expansion [Hz]
|
||||
:return: alpha0: power attenuation coefficient in f_ref [Neper/m]
|
||||
:param frequency: the frequency at which cr is computed [Hz]
|
||||
:return: cr: raman efficiency matrix [1 / (W m)]
|
||||
"""
|
||||
return self.alpha(f_ref * ones(1))[0]
|
||||
df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
|
||||
cr = self._cr_function(df)
|
||||
vibrational_loss = outer(frequency, ones(frequency.shape)) / outer(ones(frequency.shape), frequency)
|
||||
return cr * (cr >= 0) + cr * (cr < 0) * vibrational_loss # Raman efficiency [1/(W m)]
|
||||
|
||||
def chromatic_dispersion(self, freq=193.5e12):
|
||||
"""Returns accumulated chromatic dispersion (CD).
|
||||
@@ -398,70 +476,50 @@ class Fiber(_Node):
|
||||
"""differential group delay (PMD) [s]"""
|
||||
return self.params.pmd_coef * sqrt(self.params.length)
|
||||
|
||||
def _gn_analytic(self, carrier, *carriers):
|
||||
r"""Computes the nonlinear interference power on a single carrier.
|
||||
The method uses eq. 120 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__.
|
||||
|
||||
:param carrier: the signal under analysis
|
||||
:param \*carriers: the full WDM comb
|
||||
:return: carrier_nli: the amount of nonlinear interference in W on the under analysis
|
||||
def propagate(self, spectral_info: SpectralInformation):
|
||||
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
|
||||
the CD and PMD accumulation.
|
||||
"""
|
||||
# apply the attenuation due to the input connector loss
|
||||
attenuation_in_db = self.params.con_in + self.params.att_in
|
||||
spectral_info.apply_attenuation_db(attenuation_in_db)
|
||||
|
||||
g_nli = 0
|
||||
for interfering_carrier in carriers:
|
||||
psi = _psi(carrier, interfering_carrier, beta2=self.params.beta2,
|
||||
asymptotic_length=self.params.asymptotic_length)
|
||||
g_nli += (interfering_carrier.power.signal / interfering_carrier.baud_rate)**2 \
|
||||
* (carrier.power.signal / carrier.baud_rate) * psi
|
||||
# inter channels Raman effect
|
||||
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
|
||||
|
||||
g_nli *= (16 / 27) * (self.params.gamma * self.params.effective_length)**2 \
|
||||
/ (2 * pi * abs(self.params.beta2) * self.params.asymptotic_length)
|
||||
# NLI noise evaluated at the fiber input
|
||||
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
|
||||
|
||||
carrier_nli = carrier.baud_rate * g_nli
|
||||
return carrier_nli
|
||||
# chromatic dispersion and pmd variations
|
||||
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
|
||||
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
|
||||
|
||||
def propagate(self, *carriers):
|
||||
r"""Generator that computes the fiber propagation: attenuation, non-linear interference generation, CD
|
||||
accumulation and PMD accumulation.
|
||||
# apply the attenuation due to the fiber losses
|
||||
attenuation_fiber = stimulated_raman_scattering.loss_profile[:, -1]
|
||||
spectral_info.apply_attenuation_lin(attenuation_fiber)
|
||||
|
||||
:param: \*carriers: the channels at the input of the fiber
|
||||
:yield: carrier: the next channel at the output of the fiber
|
||||
"""
|
||||
# apply the attenuation due to the output connector loss
|
||||
attenuation_out_db = self.params.con_out
|
||||
spectral_info.apply_attenuation_db(attenuation_out_db)
|
||||
|
||||
# apply connector_att_in on all carriers before computing gn analytics premiere partie pas bonne
|
||||
attenuation = db2lin(self.params.con_in + self.params.att_in)
|
||||
|
||||
chan = []
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=pwr.signal / attenuation,
|
||||
nli=pwr.nli / attenuation,
|
||||
ase=pwr.ase / attenuation)
|
||||
carrier = carrier._replace(power=pwr)
|
||||
chan.append(carrier)
|
||||
|
||||
carriers = tuple(f for f in chan)
|
||||
|
||||
# propagate in the fiber and apply attenuation out
|
||||
attenuation = db2lin(self.params.con_out)
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
||||
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)
|
||||
chromatic_dispersion = carrier.chromatic_dispersion + self.chromatic_dispersion(carrier.frequency)
|
||||
pmd = sqrt(carrier.pmd**2 + self.pmd**2)
|
||||
yield carrier._replace(power=pwr, chromatic_dispersion=chromatic_dispersion, pmd=pmd)
|
||||
|
||||
def update_pref(self, pref):
|
||||
self.pch_out_db = round(pref.p_spani - self.loss, 2)
|
||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.pch_out_db)
|
||||
def update_pref(self, spectral_info):
|
||||
# in case of Raman, the resulting loss of the fiber is not equivalent to self.loss
|
||||
# because of Raman gain. In order to correctly update pref, we need the resulting loss:
|
||||
# power_out - power_in. We use the total signal power (sum on all channels) to compute
|
||||
# this loss, because pref is a noiseless reference.
|
||||
loss = round(lin2db(self._psig_in / sum(spectral_info.signal)), 2)
|
||||
self.pch_out_db = spectral_info.pref.p_spani - loss
|
||||
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
|
||||
self.label = spectral_info.label
|
||||
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||
p_spani=self.pch_out_db)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
pref = self.update_pref(spectral_info.pref)
|
||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||
# _psig_in records the total signal power of the spectral information before propagation.
|
||||
self._psig_in = sum(spectral_info.signal)
|
||||
self.propagate(spectral_info)
|
||||
self.update_pref(spectral_info)
|
||||
return spectral_info
|
||||
|
||||
|
||||
class RamanFiber(Fiber):
|
||||
@@ -471,74 +529,39 @@ class RamanFiber(Fiber):
|
||||
self.raman_pumps = tuple(PumpParams(p['power'], p['frequency'], p['propagation_direction'])
|
||||
for p in self.operational['raman_pumps'])
|
||||
else:
|
||||
self.raman_pumps = None
|
||||
self.raman_solver = RamanSolver(self)
|
||||
raise NetworkTopologyError(f'Fiber element uid:{self.uid} '
|
||||
f'defined as RamanFiber without raman pumps description')
|
||||
self.temperature = self.operational['temperature'] if 'temperature' in self.operational else None
|
||||
|
||||
@property
|
||||
def to_json(self):
|
||||
return dict(super().to_json, operational=self.operational)
|
||||
def propagate(self, spectral_info: SpectralInformation):
|
||||
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
|
||||
the CD and PMD accumulation.
|
||||
"""
|
||||
# apply the attenuation due to the input connector loss
|
||||
attenuation_in_db = self.params.con_in + self.params.att_in
|
||||
spectral_info.apply_attenuation_db(attenuation_in_db)
|
||||
|
||||
def update_pref(self, pref, *carriers):
|
||||
pch_out_db = lin2db(mean([carrier.power.signal for carrier in carriers])) + 30
|
||||
self.pch_out_db = round(pch_out_db, 2)
|
||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.pch_out_db)
|
||||
# Raman pumps and inter channel Raman effect
|
||||
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
|
||||
spontaneous_raman_scattering = \
|
||||
RamanSolver.calculate_spontaneous_raman_scattering(spectral_info, stimulated_raman_scattering, self)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
pref = self.update_pref(spectral_info.pref, *carriers)
|
||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||
# nli and ase noise evaluated at the fiber input
|
||||
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
|
||||
spectral_info.ase += spontaneous_raman_scattering
|
||||
|
||||
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)
|
||||
pmd = sqrt(propagated_carrier.pmd**2 + self.pmd**2)
|
||||
propagated_carrier = propagated_carrier._replace(chromatic_dispersion=chromatic_dispersion, pmd=pmd)
|
||||
yield propagated_carrier
|
||||
# chromatic dispersion and pmd variations
|
||||
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
|
||||
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
|
||||
|
||||
# apply the attenuation due to the fiber losses
|
||||
attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1]
|
||||
|
||||
class EdfaParams:
|
||||
def __init__(self, **params):
|
||||
self.update_params(params)
|
||||
if params == {}:
|
||||
self.type_variety = ''
|
||||
self.type_def = ''
|
||||
# self.gain_flatmax = 0
|
||||
# self.gain_min = 0
|
||||
# self.p_max = 0
|
||||
# self.nf_model = None
|
||||
# self.nf_fit_coeff = None
|
||||
# self.nf_ripple = None
|
||||
# self.dgt = None
|
||||
# self.gain_ripple = None
|
||||
# self.out_voa_auto = False
|
||||
# self.allowed_for_design = None
|
||||
spectral_info.apply_attenuation_lin(attenuation_fiber)
|
||||
|
||||
def update_params(self, kwargs):
|
||||
for k, v in kwargs.items():
|
||||
setattr(self, k, self.update_params(**v) if isinstance(v, dict) else v)
|
||||
|
||||
|
||||
class EdfaOperational:
|
||||
default_values = {
|
||||
'gain_target': None,
|
||||
'delta_p': None,
|
||||
'out_voa': None,
|
||||
'tilt_target': 0
|
||||
}
|
||||
|
||||
def __init__(self, **operational):
|
||||
self.update_attr(operational)
|
||||
|
||||
def update_attr(self, kwargs):
|
||||
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
||||
for k, v in self.default_values.items():
|
||||
setattr(self, k, clean_kwargs.get(k, v))
|
||||
|
||||
def __repr__(self):
|
||||
return (f'{type(self).__name__}('
|
||||
f'gain_target={self.gain_target!r}, '
|
||||
f'tilt_target={self.tilt_target!r})')
|
||||
# apply the attenuation due to the output connector loss
|
||||
attenuation_out_db = self.params.con_out
|
||||
spectral_info.apply_attenuation_db(attenuation_out_db)
|
||||
|
||||
|
||||
class Edfa(_Node):
|
||||
@@ -548,12 +571,7 @@ class Edfa(_Node):
|
||||
if operational is None:
|
||||
operational = {}
|
||||
self.variety_list = kwargs.pop('variety_list', None)
|
||||
super().__init__(
|
||||
*args,
|
||||
params=EdfaParams(**params),
|
||||
operational=EdfaOperational(**operational),
|
||||
**kwargs
|
||||
)
|
||||
super().__init__(*args, params=EdfaParams(**params), operational=EdfaOperational(**operational), **kwargs)
|
||||
self.interpol_dgt = None # interpolated dynamic gain tilt
|
||||
self.interpol_gain_ripple = None # gain ripple
|
||||
self.interpol_nf_ripple = None # nf_ripple
|
||||
@@ -605,6 +623,7 @@ class Edfa(_Node):
|
||||
if self.pin_db is None or self.pout_db is None:
|
||||
return f'{type(self).__name__} {self.uid}'
|
||||
nf = mean(self.nf)
|
||||
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
|
||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||
f' type_variety: {self.params.type_variety}',
|
||||
f' effective gain(dB): {self.effective_gain:.2f}',
|
||||
@@ -617,36 +636,45 @@ class Edfa(_Node):
|
||||
f' Delta_P (dB): ' + (f'{self.delta_p:.2f}' if self.delta_p is not None else 'None'),
|
||||
f' target pch (dBm): ' + (f'{self.target_pch_out_db:.2f}' if self.target_pch_out_db is not None else 'None'),
|
||||
f' effective pch (dBm): {self.effective_pch_out_db:.2f}',
|
||||
f' total pch (dBm): {total_pch}',
|
||||
f' output VOA (dB): {self.out_voa:.2f}'])
|
||||
|
||||
def interpol_params(self, frequencies, pin, baud_rates, pref):
|
||||
def interpol_params(self, spectral_info):
|
||||
"""interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from JSON
|
||||
:param spectral_info: instance of gnpy.core.info.SpectralInformation
|
||||
:return: None
|
||||
"""
|
||||
# TODO|jla: read amplifier actual frequencies from additional params in json
|
||||
self.channel_freq = frequencies
|
||||
|
||||
self.channel_freq = spectral_info.frequency
|
||||
amplifier_freq = arrange_frequencies(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
|
||||
self.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt)
|
||||
self.interpol_dgt = interp(spectral_info.frequency, amplifier_freq, self.params.dgt)
|
||||
|
||||
amplifier_freq = arrange_frequencies(len(self.params.gain_ripple), self.params.f_min, self.params.f_max) # Hz
|
||||
self.interpol_gain_ripple = interp(self.channel_freq, amplifier_freq, self.params.gain_ripple)
|
||||
self.interpol_gain_ripple = interp(spectral_info.frequency, amplifier_freq, self.params.gain_ripple)
|
||||
|
||||
amplifier_freq = arrange_frequencies(len(self.params.nf_ripple), self.params.f_min, self.params.f_max) # Hz
|
||||
self.interpol_nf_ripple = interp(self.channel_freq, amplifier_freq, self.params.nf_ripple)
|
||||
self.interpol_nf_ripple = interp(spectral_info.frequency, amplifier_freq, self.params.nf_ripple)
|
||||
|
||||
self.nch = frequencies.size
|
||||
self.nch = spectral_info.number_of_channels
|
||||
pin = spectral_info.signal + spectral_info.ase + spectral_info.nli
|
||||
self.pin_db = lin2db(sum(pin * 1e3))
|
||||
|
||||
"""in power mode: delta_p is defined and can be used to calculate the power target
|
||||
This power target is used calculate the amplifier gain"""
|
||||
pref = spectral_info.pref
|
||||
if self.delta_p is not None:
|
||||
self.target_pch_out_db = round(self.delta_p + pref.p_span0, 2)
|
||||
self.effective_gain = self.target_pch_out_db - pref.p_spani
|
||||
|
||||
"""check power saturation and correct effective gain & power accordingly:"""
|
||||
# compute the sum of powers of carriers at the input of the amplifier accounting for the expected power mixt
|
||||
delta_channel_power = pref.p_span0_per_channel - pref.p_span0
|
||||
input_total_power = lin2db(sum([db2lin(pref.p_spani + d) for d in delta_channel_power]))
|
||||
self.effective_gain = min(
|
||||
self.effective_gain,
|
||||
self.params.p_max - (pref.p_spani + pref.neq_ch)
|
||||
# self.params.p_max - (pref.p_spani + pref.neq_ch)
|
||||
self.params.p_max - input_total_power
|
||||
)
|
||||
#print(self.uid, self.effective_gain, self.operational.gain_target)
|
||||
self.effective_pch_out_db = round(pref.p_spani + self.effective_gain, 2)
|
||||
@@ -656,7 +684,7 @@ class Edfa(_Node):
|
||||
self.nf = self._calc_nf()
|
||||
self.gprofile = self._gain_profile(pin)
|
||||
|
||||
pout = (pin + self.noise_profile(baud_rates)) * db2lin(self.gprofile)
|
||||
pout = (pin + self.noise_profile(spectral_info)) * db2lin(self.gprofile)
|
||||
self.pout_db = lin2db(sum(pout * 1e3))
|
||||
# ase & nli are only calculated in signal bandwidth
|
||||
# pout_db is not the absolute full output power (negligible if sufficient channels)
|
||||
@@ -725,14 +753,10 @@ class Edfa(_Node):
|
||||
else:
|
||||
return self.interpol_nf_ripple + nf_avg # input VOA = 1 for 1 NF degradation
|
||||
|
||||
def noise_profile(self, df):
|
||||
"""noise_profile(bw) computes amplifier ASE (W) in signal bandwidth (Hz)
|
||||
|
||||
Noise is calculated at amplifier input
|
||||
|
||||
:bw: signal bandwidth = baud rate in Hz
|
||||
:type bw: float
|
||||
def noise_profile(self, spectral_info):
|
||||
"""Computes amplifier ASE noise integrated over the signal bandwidth. This is calculated at amplifier input.
|
||||
|
||||
:param spectral_info: instance of gnpy.core.info.SpectralInformation
|
||||
:return: the asepower in W in the signal bandwidth bw for 96 channels
|
||||
:return type: numpy array of float
|
||||
|
||||
@@ -767,7 +791,7 @@ class Edfa(_Node):
|
||||
quoting power spectral density in the same BW for both signal and ASE,
|
||||
e.g. 12.5GHz."""
|
||||
|
||||
ase = h * df * self.channel_freq * db2lin(self.nf) # W
|
||||
ase = h * spectral_info.baud_rate * spectral_info.frequency * db2lin(self.nf) # W
|
||||
return ase # in W at amplifier input
|
||||
|
||||
def _gain_profile(self, pin, err_tolerance=1.0e-11, simple_opt=True):
|
||||
@@ -873,30 +897,24 @@ class Edfa(_Node):
|
||||
|
||||
return g1st - voa + array(self.interpol_dgt) * dgts3
|
||||
|
||||
def propagate(self, pref, *carriers):
|
||||
def propagate(self, spectral_info):
|
||||
"""add ASE noise to the propagating carriers of :class:`.info.SpectralInformation`"""
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in carriers]) # pin in W
|
||||
freq = array([c.frequency for c in carriers])
|
||||
brate = array([c.baud_rate for c in carriers])
|
||||
# interpolate the amplifier vectors with the carriers freq, calculate nf & gain profile
|
||||
self.interpol_params(freq, pin, brate, pref)
|
||||
self.interpol_params(spectral_info)
|
||||
|
||||
gains = db2lin(self.gprofile)
|
||||
carrier_ases = self.noise_profile(brate)
|
||||
att = db2lin(self.out_voa)
|
||||
ase = self.noise_profile(spectral_info)
|
||||
spectral_info.ase += ase
|
||||
|
||||
for gain, carrier_ase, carrier in zip(gains, carrier_ases, carriers):
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=pwr.signal * gain / att,
|
||||
nli=pwr.nli * gain / att,
|
||||
ase=(pwr.ase + carrier_ase) * gain / att)
|
||||
yield carrier._replace(power=pwr)
|
||||
spectral_info.apply_gain_db(self.gprofile - self.out_voa)
|
||||
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
|
||||
self.label = spectral_info.label
|
||||
|
||||
def update_pref(self, pref):
|
||||
return pref._replace(p_span0=pref.p_span0,
|
||||
p_spani=pref.p_spani + self.effective_gain - self.out_voa)
|
||||
def update_pref(self, spectral_info):
|
||||
spectral_info.pref = \
|
||||
spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||
p_spani=spectral_info.pref.p_spani + self.effective_gain - self.out_voa)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers))
|
||||
pref = self.update_pref(spectral_info.pref)
|
||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||
self.propagate(spectral_info)
|
||||
self.update_pref(spectral_info)
|
||||
return spectral_info
|
||||
|
||||
@@ -66,7 +66,6 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
|
||||
trx_params['min_spacing'] = None
|
||||
nch = automatic_nch(trx_params['f_min'], trx_params['f_max'], trx_params['spacing'])
|
||||
trx_params['nb_channel'] = nch
|
||||
print(f'There are {nch} channels propagating')
|
||||
|
||||
trx_params['power'] = db2lin(default_si_data.power_dbm) * 1e-3
|
||||
|
||||
|
||||
@@ -8,20 +8,31 @@ gnpy.core.info
|
||||
This module contains classes for modelling :class:`SpectralInformation`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from collections import namedtuple
|
||||
from gnpy.core.utils import automatic_nch, lin2db
|
||||
from collections.abc import Iterable
|
||||
from typing import Union
|
||||
from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray
|
||||
|
||||
from gnpy.core.utils import automatic_nch, db2lin, watt2dbm
|
||||
from gnpy.core.exceptions import SpectrumError
|
||||
|
||||
DEFAULT_SLOT_WIDTH_STEP = 12.5e9 # Hz
|
||||
"""Channels with unspecified slot width will have their slot width evaluated as the baud rate rounded up to the minimum
|
||||
multiple of the DEFAULT_SLOT_WIDTH_STEP (the baud rate is extended including the roll off in this evaluation)"""
|
||||
|
||||
|
||||
class Power(namedtuple('Power', 'signal nli ase')):
|
||||
"""carriers power in W"""
|
||||
|
||||
|
||||
class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off power chromatic_dispersion pmd')):
|
||||
class Channel(namedtuple('Channel', 'channel_number frequency baud_rate slot_width ' +
|
||||
'roll_off power chromatic_dispersion pmd')):
|
||||
""" Class containing the parameters of a WDM signal.
|
||||
|
||||
:param channel_number: channel number in the WDM grid
|
||||
:param frequency: central frequency of the signal (Hz)
|
||||
:param baud_rate: the symbol rate of the signal (Baud)
|
||||
:param slot_width: the slot width (Hz)
|
||||
:param roll_off: the roll off of the signal. It is a pure number between 0 and 1
|
||||
:param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
|
||||
:param chromatic_dispersion: chromatic dispersion (s/m)
|
||||
@@ -29,28 +40,257 @@ class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off
|
||||
"""
|
||||
|
||||
|
||||
class Pref(namedtuple('Pref', 'p_span0, p_spani, neq_ch ')):
|
||||
class Pref(namedtuple('Pref', 'p_span0, p_spani, p_span0_per_channel, ref_carrier')):
|
||||
"""noiseless reference power in dBm:
|
||||
p_span0: inital target carrier power
|
||||
p_spani: carrier power after element i
|
||||
neq_ch: equivalent channel count in dB"""
|
||||
p_span0: inital target carrier power for a reference channel defined by user
|
||||
p_spani: carrier power after element i for a reference channel defined by user
|
||||
neq_ch: equivalent channel count in dB -> almost never used : suppress it
|
||||
p_span0_per_channel: (per frequency) target per channel power for the actual mix
|
||||
of channels
|
||||
"""
|
||||
|
||||
|
||||
class SpectralInformation(namedtuple('SpectralInformation', 'pref carriers')):
|
||||
class SpectralInformation(object):
|
||||
""" Class containing the parameters of the entire WDM comb."""
|
||||
|
||||
def __new__(cls, pref, carriers):
|
||||
return super().__new__(cls, pref, carriers)
|
||||
def __init__(self, frequency: array, baud_rate: array, slot_width: array, signal: array, nli: array, ase: array,
|
||||
roll_off: array, chromatic_dispersion: array, pmd: array, ref_power: Pref, label: str):
|
||||
indices = argsort(frequency)
|
||||
self._frequency = frequency[indices]
|
||||
self._df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
|
||||
self._number_of_channels = len(self._frequency)
|
||||
self._channel_number = [*range(1, self._number_of_channels + 1)]
|
||||
self._slot_width = slot_width[indices]
|
||||
self._baud_rate = baud_rate[indices]
|
||||
overlap = self._frequency[:-1] + self._slot_width[:-1] / 2 > self._frequency[1:] - self._slot_width[1:] / 2
|
||||
if any(overlap):
|
||||
overlap = [pair for pair in zip(overlap * self._channel_number[:-1], overlap * self._channel_number[1:])
|
||||
if pair != (0, 0)]
|
||||
raise SpectrumError(f'Spectrum required slot widths larger than the frequency spectral distances '
|
||||
f'between channels: {overlap}.')
|
||||
exceed = self._baud_rate > self._slot_width
|
||||
if any(exceed):
|
||||
raise SpectrumError(f'Spectrum baud rate, including the roll off, larger than the slot width for channels: '
|
||||
f'{[ch for ch in exceed * self._channel_number if ch]}.')
|
||||
self._signal = signal[indices]
|
||||
self._nli = nli[indices]
|
||||
self._ase = ase[indices]
|
||||
self._roll_off = roll_off[indices]
|
||||
self._chromatic_dispersion = chromatic_dispersion[indices]
|
||||
self._pmd = pmd[indices]
|
||||
self._channel_number = [*range(1, self._number_of_channels + 1)]
|
||||
self._pref = ref_power
|
||||
self._label = label
|
||||
|
||||
@property
|
||||
def pref(self):
|
||||
"""Instance of gnpy.info.Pref"""
|
||||
return self._pref
|
||||
|
||||
@pref.setter
|
||||
def pref(self, pref: Pref):
|
||||
self._pref = pref
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
return self._frequency
|
||||
|
||||
@property
|
||||
def df(self):
|
||||
"""Matrix of relative frequency distances between all channels. Positive elements in the upper right side."""
|
||||
return self._df
|
||||
|
||||
@property
|
||||
def slot_width(self):
|
||||
return self._slot_width
|
||||
|
||||
@property
|
||||
def baud_rate(self):
|
||||
return self._baud_rate
|
||||
|
||||
@property
|
||||
def number_of_channels(self):
|
||||
return self._number_of_channels
|
||||
|
||||
@property
|
||||
def powers(self):
|
||||
powers = zip(self.signal, self.nli, self.ase)
|
||||
return [Power(*p) for p in powers]
|
||||
|
||||
@property
|
||||
def signal(self):
|
||||
return self._signal
|
||||
|
||||
@signal.setter
|
||||
def signal(self, signal):
|
||||
self._signal = signal
|
||||
|
||||
@property
|
||||
def nli(self):
|
||||
return self._nli
|
||||
|
||||
@nli.setter
|
||||
def nli(self, nli):
|
||||
self._nli = nli
|
||||
|
||||
@property
|
||||
def ase(self):
|
||||
return self._ase
|
||||
|
||||
@ase.setter
|
||||
def ase(self, ase):
|
||||
self._ase = ase
|
||||
|
||||
@property
|
||||
def roll_off(self):
|
||||
return self._roll_off
|
||||
|
||||
@property
|
||||
def chromatic_dispersion(self):
|
||||
return self._chromatic_dispersion
|
||||
|
||||
@chromatic_dispersion.setter
|
||||
def chromatic_dispersion(self, chromatic_dispersion):
|
||||
self._chromatic_dispersion = chromatic_dispersion
|
||||
|
||||
@property
|
||||
def pmd(self):
|
||||
return self._pmd
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return self._label
|
||||
|
||||
@pmd.setter
|
||||
def pmd(self, pmd):
|
||||
self._pmd = pmd
|
||||
|
||||
@property
|
||||
def channel_number(self):
|
||||
return self._channel_number
|
||||
|
||||
@property
|
||||
def carriers(self):
|
||||
entries = zip(self.channel_number, self.frequency, self.baud_rate, self.slot_width,
|
||||
self.roll_off, self.powers, self.chromatic_dispersion, self.pmd)
|
||||
return [Channel(*entry) for entry in entries]
|
||||
|
||||
def apply_attenuation_lin(self, attenuation_lin):
|
||||
self.signal *= attenuation_lin
|
||||
self.nli *= attenuation_lin
|
||||
self.ase *= attenuation_lin
|
||||
|
||||
def apply_attenuation_db(self, attenuation_db):
|
||||
attenuation_lin = 1 / db2lin(attenuation_db)
|
||||
self.apply_attenuation_lin(attenuation_lin)
|
||||
|
||||
def apply_gain_lin(self, gain_lin):
|
||||
self.signal *= gain_lin
|
||||
self.nli *= gain_lin
|
||||
self.ase *= gain_lin
|
||||
|
||||
def apply_gain_db(self, gain_db):
|
||||
gain_lin = db2lin(gain_db)
|
||||
self.apply_gain_lin(gain_lin)
|
||||
|
||||
def __add__(self, other: SpectralInformation):
|
||||
try:
|
||||
pref = Pref(self.pref.p_span0, self.pref.p_spani,
|
||||
append(self.pref.p_span0_per_channel, other.pref.p_span0_per_channel), self.pref.ref_carrier)
|
||||
return SpectralInformation(frequency=append(self.frequency, other.frequency),
|
||||
slot_width=append(self.slot_width, other.slot_width),
|
||||
signal=append(self.signal, other.signal), nli=append(self.nli, other.nli),
|
||||
ase=append(self.ase, other.ase),
|
||||
baud_rate=append(self.baud_rate, other.baud_rate),
|
||||
roll_off=append(self.roll_off, other.roll_off),
|
||||
chromatic_dispersion=append(self.chromatic_dispersion,
|
||||
other.chromatic_dispersion),
|
||||
pmd=append(self.pmd, other.pmd),
|
||||
ref_power=pref,
|
||||
label=append(self.label, other.label))
|
||||
except SpectrumError:
|
||||
raise SpectrumError('Spectra cannot be summed: channels overlapping.')
|
||||
|
||||
|
||||
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing):
|
||||
# pref in dB : convert power lin into power in dB
|
||||
pref = lin2db(power * 1e3)
|
||||
def _replace(self, carriers, pref):
|
||||
self.chromatic_dispersion = array([c.chromatic_dispersion for c in carriers])
|
||||
self.pmd = array([c.pmd for c in carriers])
|
||||
self.signal = array([c.power.signal for c in carriers])
|
||||
self.nli = array([c.power.nli for c in carriers])
|
||||
self.ase = array([c.power.ase for c in carriers])
|
||||
self.pref = pref
|
||||
return self
|
||||
|
||||
|
||||
def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, int, float],
|
||||
signal: Union[int, float, ndarray, Iterable],
|
||||
baud_rate: Union[int, float, ndarray, Iterable],
|
||||
slot_width: Union[int, float, ndarray, Iterable] = None,
|
||||
roll_off: Union[int, float, ndarray, Iterable] = 0.,
|
||||
chromatic_dispersion: Union[int, float, ndarray, Iterable] = 0.,
|
||||
pmd: Union[int, float, ndarray, Iterable] = 0.,
|
||||
ref_power: Pref = None,
|
||||
label: string = None):
|
||||
"""This is just a wrapper around the SpectralInformation.__init__() that simplifies the creation of
|
||||
a non-uniform spectral information with NLI and ASE powers set to zero."""
|
||||
frequency = asarray(frequency)
|
||||
number_of_channels = frequency.size
|
||||
try:
|
||||
signal = full(number_of_channels, signal)
|
||||
baud_rate = full(number_of_channels, baud_rate)
|
||||
roll_off = full(number_of_channels, roll_off)
|
||||
slot_width = full(number_of_channels, slot_width) if slot_width is not None else \
|
||||
ceil((1 + roll_off) * baud_rate / DEFAULT_SLOT_WIDTH_STEP) * DEFAULT_SLOT_WIDTH_STEP
|
||||
chromatic_dispersion = full(number_of_channels, chromatic_dispersion)
|
||||
pmd = full(number_of_channels, pmd)
|
||||
nli = zeros(number_of_channels)
|
||||
ase = zeros(number_of_channels)
|
||||
return SpectralInformation(frequency=frequency, slot_width=slot_width,
|
||||
signal=signal, nli=nli, ase=ase,
|
||||
baud_rate=baud_rate, roll_off=roll_off,
|
||||
chromatic_dispersion=chromatic_dispersion, pmd=pmd,
|
||||
ref_power=ref_power, label=label)
|
||||
except ValueError as e:
|
||||
if 'could not broadcast' in str(e):
|
||||
raise SpectrumError('Dimension mismatch in input fields.')
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing, ref_carrier=None):
|
||||
""" Creates a fixed slot width spectral information with flat power.
|
||||
all arguments are scalar values"""
|
||||
nb_channel = automatic_nch(f_min, f_max, spacing)
|
||||
si = SpectralInformation(
|
||||
pref=Pref(pref, pref, lin2db(nb_channel)),
|
||||
carriers=[
|
||||
Channel(f, (f_min + spacing * f),
|
||||
baud_rate, roll_off, Power(power, 0, 0), 0, 0) for f in range(1, nb_channel + 1)
|
||||
]
|
||||
)
|
||||
return si
|
||||
frequency = [(f_min + spacing * i) for i in range(1, nb_channel + 1)]
|
||||
p_span0 = watt2dbm(power)
|
||||
p_spani = watt2dbm(power)
|
||||
p_span0_per_channel = watt2dbm(power) * ones(nb_channel)
|
||||
label = ["0" for i in range(nb_channel)]
|
||||
return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate,
|
||||
roll_off=roll_off,
|
||||
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
|
||||
p_span0_per_channel=p_span0_per_channel,
|
||||
ref_carrier=ref_carrier),
|
||||
label=label)
|
||||
|
||||
|
||||
def use_initial_spectrum(initial_spectrum, ref_carrier):
|
||||
""" initial spectrum is a dict with key = carrier frequency, and value a dict with power,
|
||||
baudrate and roll off for this carrier. ref_carrier contains the reference carrier (power, baudrate, ...)
|
||||
used for the reference channel
|
||||
"""
|
||||
frequency = list(initial_spectrum.keys())
|
||||
signal = [s['power'] for s in initial_spectrum.values()]
|
||||
roll_off = [s['roll_off'] for s in initial_spectrum.values()]
|
||||
baud_rate = [s['baud_rate'] for s in initial_spectrum.values()]
|
||||
slot_width = [s['spacing'] for s in initial_spectrum.values()]
|
||||
label = [s['label'] for s in initial_spectrum.values()]
|
||||
p_span0 = watt2dbm(ref_carrier['req_power'])
|
||||
p_spani = watt2dbm(ref_carrier['req_power'])
|
||||
p_span0_per_channel = [watt2dbm(s['power']) for s in initial_spectrum.values()]
|
||||
return create_arbitrary_spectral_information(frequency=frequency, signal=signal, baud_rate=baud_rate,
|
||||
slot_width=slot_width, roll_off=roll_off,
|
||||
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
|
||||
p_span0_per_channel=p_span0_per_channel,
|
||||
ref_carrier=ref_carrier),
|
||||
label=label)
|
||||
|
||||
@@ -11,7 +11,7 @@ Working with networks which consist of network elements
|
||||
from operator import attrgetter
|
||||
from gnpy.core import ansi_escapes, elements
|
||||
from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError
|
||||
from gnpy.core.utils import round2float, convert_length
|
||||
from gnpy.core.utils import round2float, convert_length, psd2powerdbm
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
@@ -236,8 +236,15 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
||||
""" this node can be a transceiver or a ROADM (same function called in both cases)
|
||||
"""
|
||||
power_mode = equipment['Span']['default'].power_mode
|
||||
ref_br = equipment['SI']['default'].baud_rate
|
||||
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
|
||||
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()} if hasattr(this_node, 'per_degree_pch_out_db') else {}
|
||||
this_node_degree = {}
|
||||
this_node_degree_psd = {}
|
||||
if hasattr(this_node, 'per_degree_pch_out_db'):
|
||||
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()}
|
||||
if hasattr(this_node, 'per_degree_pch_psd'):
|
||||
this_node_degree_psd = {k: v for k, v in this_node.per_degree_pch_psd.items()}
|
||||
# TODO: check that the same degree does not appear in both dicts
|
||||
for oms in next_oms:
|
||||
# go through all the OMS departing from the ROADM
|
||||
prev_node = this_node
|
||||
@@ -246,12 +253,22 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
||||
# node = find_last_node(next_node)
|
||||
# next_node = next(n for n in network.successors(node))
|
||||
# next_node = find_last_node(next_node)
|
||||
if node.uid not in this_node_degree:
|
||||
if node.uid not in this_node_degree and node.uid not in this_node_degree_psd:
|
||||
# if no target power is defined on this degree or no per degree target power is given use the global one
|
||||
# if target_pch_out_db is not an attribute, then the element must be a transceiver
|
||||
this_node_degree[node.uid] = getattr(this_node.params, 'target_pch_out_db', 0)
|
||||
this_node_degree[node.uid] = 0 # default value if this_node is a transceiver
|
||||
if isinstance(this_node, elements.Roadm):
|
||||
if this_node.params.target_pch_out_db:
|
||||
this_node_degree[node.uid] = this_node.params.target_pch_out_db
|
||||
elif this_node.params.target_psd_out_mWperGHz:
|
||||
this_node_degree_psd[node.uid] = this_node.params.target_psd_out_mWperGHz
|
||||
else:
|
||||
raise ConfigurationError(this_node.uid,
|
||||
'needs either a target_pch_out_db or a target_psd_out_mWperGHz')
|
||||
# use the target power on this degree
|
||||
prev_dp = this_node_degree[node.uid] - pref_ch_db
|
||||
if node.uid in this_node_degree:
|
||||
prev_dp = this_node_degree[node.uid] - pref_ch_db
|
||||
if node.uid in this_node_degree_psd:
|
||||
prev_dp = psd2powerdbm(this_node_degree_psd[node.uid], ref_br) - pref_ch_db
|
||||
dp = prev_dp
|
||||
prev_voa = 0
|
||||
voa = 0
|
||||
@@ -329,6 +346,7 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
||||
|
||||
if isinstance(this_node, elements.Roadm):
|
||||
this_node.per_degree_pch_out_db = {k: v for k, v in this_node_degree.items()}
|
||||
this_node.per_degree_pch_psd = {k: v for k, v in this_node_degree_psd.items()}
|
||||
|
||||
|
||||
def add_roadm_booster(network, roadm):
|
||||
|
||||
@@ -9,9 +9,9 @@ This module contains all parameters to configure standard network elements.
|
||||
"""
|
||||
|
||||
from scipy.constants import c, pi
|
||||
from numpy import squeeze, log10, exp
|
||||
from numpy import asarray
|
||||
|
||||
from gnpy.core.utils import db2lin, convert_length
|
||||
from gnpy.core.utils import convert_length
|
||||
from gnpy.core.exceptions import ParametersError
|
||||
|
||||
|
||||
@@ -28,110 +28,89 @@ class Parameters:
|
||||
|
||||
class PumpParams(Parameters):
|
||||
def __init__(self, power, frequency, propagation_direction):
|
||||
self._power = power
|
||||
self._frequency = frequency
|
||||
self._propagation_direction = propagation_direction
|
||||
|
||||
@property
|
||||
def power(self):
|
||||
return self._power
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
return self._frequency
|
||||
|
||||
@property
|
||||
def propagation_direction(self):
|
||||
return self._propagation_direction
|
||||
self.power = power
|
||||
self.frequency = frequency
|
||||
self.propagation_direction = propagation_direction.lower()
|
||||
|
||||
|
||||
class RamanParams(Parameters):
|
||||
def __init__(self, **kwargs):
|
||||
self._flag_raman = kwargs['flag_raman']
|
||||
self._space_resolution = kwargs['space_resolution'] if 'space_resolution' in kwargs else None
|
||||
self._tolerance = kwargs['tolerance'] if 'tolerance' in kwargs else None
|
||||
|
||||
@property
|
||||
def flag_raman(self):
|
||||
return self._flag_raman
|
||||
|
||||
@property
|
||||
def space_resolution(self):
|
||||
return self._space_resolution
|
||||
|
||||
@property
|
||||
def tolerance(self):
|
||||
return self._tolerance
|
||||
def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_resolution=50):
|
||||
""" Simulation parameters used within the Raman Solver
|
||||
:params flag: boolean for enabling/disable the evaluation of the Raman power profile in frequency and position
|
||||
:params result_spatial_resolution: spatial resolution of the evaluated Raman power profile
|
||||
:params solver_spatial_resolution: spatial step for the iterative solution of the first order ode
|
||||
"""
|
||||
self.flag = flag
|
||||
self.result_spatial_resolution = result_spatial_resolution # [m]
|
||||
self.solver_spatial_resolution = solver_spatial_resolution # [m]
|
||||
|
||||
|
||||
class NLIParams(Parameters):
|
||||
def __init__(self, **kwargs):
|
||||
self._nli_method_name = kwargs['nli_method_name']
|
||||
self._wdm_grid_size = kwargs['wdm_grid_size']
|
||||
self._dispersion_tolerance = kwargs['dispersion_tolerance']
|
||||
self._phase_shift_tolerance = kwargs['phase_shift_tolerance']
|
||||
self._f_cut_resolution = None
|
||||
self._f_pump_resolution = None
|
||||
self._computed_channels = kwargs['computed_channels'] if 'computed_channels' in kwargs else None
|
||||
|
||||
@property
|
||||
def nli_method_name(self):
|
||||
return self._nli_method_name
|
||||
|
||||
@property
|
||||
def wdm_grid_size(self):
|
||||
return self._wdm_grid_size
|
||||
|
||||
@property
|
||||
def dispersion_tolerance(self):
|
||||
return self._dispersion_tolerance
|
||||
|
||||
@property
|
||||
def phase_shift_tolerance(self):
|
||||
return self._phase_shift_tolerance
|
||||
|
||||
@property
|
||||
def f_cut_resolution(self):
|
||||
return self._f_cut_resolution
|
||||
|
||||
@f_cut_resolution.setter
|
||||
def f_cut_resolution(self, f_cut_resolution):
|
||||
self._f_cut_resolution = f_cut_resolution
|
||||
|
||||
@property
|
||||
def f_pump_resolution(self):
|
||||
return self._f_pump_resolution
|
||||
|
||||
@f_pump_resolution.setter
|
||||
def f_pump_resolution(self, f_pump_resolution):
|
||||
self._f_pump_resolution = f_pump_resolution
|
||||
|
||||
@property
|
||||
def computed_channels(self):
|
||||
return self._computed_channels
|
||||
def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1,
|
||||
computed_channels=None):
|
||||
""" Simulation parameters used within the Nli Solver
|
||||
:params method: formula for NLI calculation
|
||||
:params dispersion_tolerance: tuning parameter for ggn model solution
|
||||
:params phase_shift_tolerance: tuning parameter for ggn model solution
|
||||
:params computed_channels: the NLI is evaluated for these channels and extrapolated for the others
|
||||
"""
|
||||
self.method = method.lower()
|
||||
self.dispersion_tolerance = dispersion_tolerance
|
||||
self.phase_shift_tolerance = phase_shift_tolerance
|
||||
self.computed_channels = computed_channels
|
||||
|
||||
|
||||
class SimParams(Parameters):
|
||||
def __init__(self, **kwargs):
|
||||
try:
|
||||
if 'nli_parameters' in kwargs:
|
||||
self._nli_params = NLIParams(**kwargs['nli_parameters'])
|
||||
else:
|
||||
self._nli_params = None
|
||||
if 'raman_parameters' in kwargs:
|
||||
self._raman_params = RamanParams(**kwargs['raman_parameters'])
|
||||
else:
|
||||
self._raman_params = None
|
||||
except KeyError as e:
|
||||
raise ParametersError(f'Simulation parameters must include {e}. Configuration: {kwargs}')
|
||||
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
|
||||
|
||||
def __init__(self):
|
||||
if type(self) == SimParams:
|
||||
raise NotImplementedError('Instances of SimParams cannot be generated')
|
||||
|
||||
@classmethod
|
||||
def set_params(cls, sim_params):
|
||||
cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {}))
|
||||
cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {}))
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
self = cls.__new__(cls)
|
||||
return self
|
||||
|
||||
@property
|
||||
def nli_params(self):
|
||||
return self._nli_params
|
||||
return self._shared_dict['nli_params']
|
||||
|
||||
@property
|
||||
def raman_params(self):
|
||||
return self._raman_params
|
||||
return self._shared_dict['raman_params']
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
cls._shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
|
||||
|
||||
|
||||
class RoadmParams(Parameters):
|
||||
def __init__(self, **kwargs):
|
||||
self.target_pch_out_db = kwargs['target_pch_out_db'] if 'target_pch_out_db' in kwargs else None
|
||||
self.target_psd_out_mWperGHz = \
|
||||
kwargs['target_psd_out_mWperGHz'] if 'target_psd_out_mWperGHz' in kwargs else None
|
||||
if self.target_pch_out_db is not None and self.target_psd_out_mWperGHz is not None:
|
||||
raise ParametersError('ROADM config contains per channel power and psd. Please choose only one', kwargs)
|
||||
self.per_degree_pch_out_db = kwargs['per_degree_pch_out_db'] if 'per_degree_pch_out_db' in kwargs else {}
|
||||
self.per_degree_pch_psd = \
|
||||
kwargs['per_degree_psd_out_mWperGHz'] if 'per_degree_psd_out_mWperGHz' in kwargs else {}
|
||||
try:
|
||||
self.add_drop_osnr = kwargs['add_drop_osnr']
|
||||
self.pmd = kwargs['pmd']
|
||||
self.restrictions = kwargs['restrictions']
|
||||
except KeyError as e:
|
||||
raise ParametersError(f'ROADM configurations json must include {e}. Configuration: {kwargs}')
|
||||
|
||||
|
||||
class FusedParams(Parameters):
|
||||
def __init__(self, **kwargs):
|
||||
self.loss = kwargs['loss'] if 'loss' in kwargs else 1
|
||||
|
||||
|
||||
class FiberParams(Parameters):
|
||||
@@ -139,24 +118,24 @@ class FiberParams(Parameters):
|
||||
try:
|
||||
self._length = convert_length(kwargs['length'], kwargs['length_units'])
|
||||
# fixed attenuator for padding
|
||||
self._att_in = kwargs['att_in'] if 'att_in' in kwargs else 0
|
||||
self._att_in = kwargs.get('att_in', 0)
|
||||
# if not defined in the network json connector loss in/out
|
||||
# the None value will be updated in network.py[build_network]
|
||||
# with default values from eqpt_config.json[Spans]
|
||||
self._con_in = kwargs['con_in'] if 'con_in' in kwargs else None
|
||||
self._con_out = kwargs['con_out'] if 'con_out' in kwargs else None
|
||||
self._con_in = kwargs.get('con_in')
|
||||
self._con_out = kwargs.get('con_out')
|
||||
if 'ref_wavelength' in kwargs:
|
||||
self._ref_wavelength = kwargs['ref_wavelength']
|
||||
self._ref_frequency = c / self.ref_wavelength
|
||||
self._ref_frequency = c / self._ref_wavelength
|
||||
elif 'ref_frequency' in kwargs:
|
||||
self._ref_frequency = kwargs['ref_frequency']
|
||||
self._ref_wavelength = c / self.ref_frequency
|
||||
self._ref_wavelength = c / self._ref_frequency
|
||||
else:
|
||||
self._ref_wavelength = 1550e-9
|
||||
self._ref_frequency = c / self.ref_wavelength
|
||||
self._ref_frequency = 193.5e12 # conventional central C band frequency [Hz]
|
||||
self._ref_wavelength = c / self._ref_frequency
|
||||
self._dispersion = kwargs['dispersion'] # s/m/m
|
||||
self._dispersion_slope = kwargs['dispersion_slope'] if 'dispersion_slope' in kwargs else \
|
||||
-2 * self._dispersion/self.ref_wavelength # s/m/m/m
|
||||
self._dispersion_slope = \
|
||||
kwargs.get('dispersion_slope', -2 * self._dispersion/self.ref_wavelength) # s/m/m/m
|
||||
self._beta2 = -(self.ref_wavelength ** 2) * self.dispersion / (2 * pi * c) # 1/(m * Hz^2)
|
||||
# Eq. (3.23) in Abramczyk, Halina. "Dispersion phenomena in optical fibers." Virtual European University
|
||||
# on Lasers. Available online: http://mitr.p.lodz.pl/evu/lectures/Abramczyk3.pdf
|
||||
@@ -166,18 +145,15 @@ class FiberParams(Parameters):
|
||||
self._gamma = kwargs['gamma'] # 1/W/m
|
||||
self._pmd_coef = kwargs['pmd_coef'] # s/sqrt(m)
|
||||
if type(kwargs['loss_coef']) == dict:
|
||||
self._loss_coef = squeeze(kwargs['loss_coef']['loss_coef_power']) * 1e-3 # lineic loss dB/m
|
||||
self._f_loss_ref = squeeze(kwargs['loss_coef']['frequency']) # Hz
|
||||
self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m
|
||||
self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz
|
||||
else:
|
||||
self._loss_coef = kwargs['loss_coef'] * 1e-3 # lineic loss dB/m
|
||||
self._f_loss_ref = 193.5e12 # Hz
|
||||
self._lin_attenuation = db2lin(self.length * self.loss_coef)
|
||||
self._lin_loss_exp = self.loss_coef / (10 * log10(exp(1))) # linear power exponent loss Neper/m
|
||||
self._effective_length = (1 - exp(- self.lin_loss_exp * self.length)) / self.lin_loss_exp
|
||||
self._asymptotic_length = 1 / self.lin_loss_exp
|
||||
self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m
|
||||
self._f_loss_ref = asarray(193.5e12) # Hz
|
||||
# raman parameters (not compulsory)
|
||||
self._raman_efficiency = kwargs['raman_efficiency'] if 'raman_efficiency' in kwargs else None
|
||||
self._pumps_loss_coef = kwargs['pumps_loss_coef'] if 'pumps_loss_coef' in kwargs else None
|
||||
# lumped losses
|
||||
self._lumped_losses = kwargs['lumped_losses'] if 'lumped_losses' in kwargs else None
|
||||
except KeyError as e:
|
||||
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
|
||||
|
||||
@@ -210,6 +186,10 @@ class FiberParams(Parameters):
|
||||
def con_out(self):
|
||||
return self._con_out
|
||||
|
||||
@property
|
||||
def lumped_losses(self):
|
||||
return self._lumped_losses
|
||||
|
||||
@con_out.setter
|
||||
def con_out(self, con_out):
|
||||
self._con_out = con_out
|
||||
@@ -254,32 +234,60 @@ class FiberParams(Parameters):
|
||||
def f_loss_ref(self):
|
||||
return self._f_loss_ref
|
||||
|
||||
@property
|
||||
def lin_loss_exp(self):
|
||||
return self._lin_loss_exp
|
||||
|
||||
@property
|
||||
def lin_attenuation(self):
|
||||
return self._lin_attenuation
|
||||
|
||||
@property
|
||||
def effective_length(self):
|
||||
return self._effective_length
|
||||
|
||||
@property
|
||||
def asymptotic_length(self):
|
||||
return self._asymptotic_length
|
||||
|
||||
@property
|
||||
def raman_efficiency(self):
|
||||
return self._raman_efficiency
|
||||
|
||||
@property
|
||||
def pumps_loss_coef(self):
|
||||
return self._pumps_loss_coef
|
||||
|
||||
def asdict(self):
|
||||
dictionary = super().asdict()
|
||||
dictionary['loss_coef'] = self.loss_coef * 1e3
|
||||
dictionary['length_units'] = 'm'
|
||||
if not self.lumped_losses:
|
||||
dictionary.pop('lumped_losses')
|
||||
if not self.raman_efficiency:
|
||||
dictionary.pop('raman_efficiency')
|
||||
return dictionary
|
||||
|
||||
|
||||
class EdfaParams:
|
||||
def __init__(self, **params):
|
||||
self.update_params(params)
|
||||
if params == {}:
|
||||
self.type_variety = ''
|
||||
self.type_def = ''
|
||||
# self.gain_flatmax = 0
|
||||
# self.gain_min = 0
|
||||
# self.p_max = 0
|
||||
# self.nf_model = None
|
||||
# self.nf_fit_coeff = None
|
||||
# self.nf_ripple = None
|
||||
# self.dgt = None
|
||||
# self.gain_ripple = None
|
||||
# self.out_voa_auto = False
|
||||
# self.allowed_for_design = None
|
||||
|
||||
def update_params(self, kwargs):
|
||||
for k, v in kwargs.items():
|
||||
setattr(self, k, self.update_params(**v) if isinstance(v, dict) else v)
|
||||
|
||||
|
||||
class EdfaOperational:
|
||||
default_values = {
|
||||
'gain_target': None,
|
||||
'delta_p': None,
|
||||
'out_voa': None,
|
||||
'tilt_target': 0
|
||||
}
|
||||
|
||||
def __init__(self, **operational):
|
||||
self.update_attr(operational)
|
||||
|
||||
def update_attr(self, kwargs):
|
||||
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
||||
for k, v in self.default_values.items():
|
||||
setattr(self, k, clean_kwargs.get(k, v))
|
||||
|
||||
def __repr__(self):
|
||||
return (f'{type(self).__name__}('
|
||||
f'gain_target={self.gain_target!r}, '
|
||||
f'tilt_target={self.tilt_target!r})')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,9 @@ This module contains utility functions that are used with gnpy.
|
||||
"""
|
||||
|
||||
from csv import writer
|
||||
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and
|
||||
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and, mean
|
||||
from scipy import constants
|
||||
from copy import deepcopy
|
||||
|
||||
from gnpy.core.exceptions import ConfigurationError
|
||||
|
||||
@@ -106,6 +107,69 @@ def db2lin(value):
|
||||
return 10**(value / 10)
|
||||
|
||||
|
||||
def watt2dbm(value):
|
||||
""" Convert watt units to dbm
|
||||
|
||||
>>> round(watt2dbm(0.001), 1)
|
||||
0.0
|
||||
>>> round(watt2dbm(0.02), 1)
|
||||
13.0
|
||||
"""
|
||||
return lin2db(value * 1e3)
|
||||
|
||||
|
||||
def dbm2watt(value):
|
||||
""" Convert dbm units to watt
|
||||
|
||||
>>> round(dbm2watt(0), 4)
|
||||
0.001
|
||||
>>> round(dbm2watt(-3), 4)
|
||||
0.0005
|
||||
>>> round(dbm2watt(13), 4)
|
||||
0.02
|
||||
"""
|
||||
return db2lin(value) * 1e-3
|
||||
|
||||
|
||||
def psd2powerdbm(psd_mwperghz, baudrate_baud):
|
||||
""" computes power in dbm based on baudrate in bauds and psd in mw/GHz
|
||||
|
||||
>>> round(psd2powerdbm(0.031176, 64e9),3)
|
||||
3.0
|
||||
>>> round(psd2powerdbm(0.062352, 32e9),3)
|
||||
3.0
|
||||
>>> round(psd2powerdbm(0.015625, 64e9),3)
|
||||
0.0
|
||||
"""
|
||||
return lin2db(baudrate_baud * psd_mwperghz * 1e-9)
|
||||
|
||||
|
||||
def powerdbm2psdmwperghz(power_dbm, baudrate_baud):
|
||||
""" computes power spectral density in mW/GHz based on baudrate in bauds and power in dBm
|
||||
|
||||
>>> powerdbm2psdmwperghz(0, 64e9)
|
||||
0.015625
|
||||
>>> round(powerdbm2psdmwperghz(3, 64e9), 6)
|
||||
0.031176
|
||||
>>> round(powerdbm2psdmwperghz(3, 32e9), 6)
|
||||
0.062352
|
||||
"""
|
||||
return db2lin(power_dbm) / (baudrate_baud * 1e-9)
|
||||
|
||||
|
||||
def psdmwperghz(power_watt, baudrate_baud):
|
||||
""" computes power spectral density in mW/GHz based on baudrate in bauds and power in W
|
||||
|
||||
>>> psdmwperghz(2e-3, 32e9)
|
||||
0.0625
|
||||
>>> psdmwperghz(1e-3, 64e9)
|
||||
0.015625
|
||||
>>> psdmwperghz(0.5e-3, 32e9)
|
||||
0.015625
|
||||
"""
|
||||
return power_watt * 1e3 / (baudrate_baud * 1e-9)
|
||||
|
||||
|
||||
def round2float(number, step):
|
||||
"""Round a floating point number so that its "resolution" is not bigger than 'step'
|
||||
|
||||
@@ -166,6 +230,30 @@ def snr_sum(snr, bw, snr_added, bw_added=12.5e9):
|
||||
return snr
|
||||
|
||||
|
||||
def per_label_summary(values, labels):
|
||||
""" computes the average per defined spectrum band, using labels
|
||||
|
||||
"""
|
||||
|
||||
label_set = sorted(set(labels))
|
||||
summary = {}
|
||||
for label in label_set:
|
||||
vals = [values[i] for i, lab in enumerate(labels) if lab == label]
|
||||
summary[label] = round(mean(vals), 2)
|
||||
return summary
|
||||
|
||||
|
||||
def pretty_summary_print(summary):
|
||||
"""
|
||||
"""
|
||||
if len(summary) == 1:
|
||||
return f'{round(list(summary.values())[0], 2):.2f}'
|
||||
text = ''
|
||||
for label, value in summary.items():
|
||||
text += f'{label}: {value:.2f}, '
|
||||
return text
|
||||
|
||||
|
||||
def deltawl2deltaf(delta_wl, wavelength):
|
||||
""" deltawl2deltaf(delta_wl, wavelength):
|
||||
delta_wl is BW in wavelength units
|
||||
@@ -228,6 +316,30 @@ def rrc(ffs, baud_rate, alpha):
|
||||
return sqrt(hf)
|
||||
|
||||
|
||||
def merge_equalization(params, extra_params):
|
||||
""" Updates equalization type
|
||||
if target_pch_out_db in params, then do not add target_psd_out_mWperGHz from extra_params
|
||||
and reversaly. if both exist: raise an error, if none exist add the one in extra_params
|
||||
"""
|
||||
extra = deepcopy(extra_params)
|
||||
if 'target_pch_out_db' in params.keys() and params['target_pch_out_db'] is not None and\
|
||||
'target_psd_out_mWperGHz' in params.keys() and params['target_psd_out_mWperGHz'] is not None:
|
||||
return None
|
||||
if 'target_pch_out_db' in params.keys() and params['target_pch_out_db'] is not None:
|
||||
extra.__dict__.pop('target_psd_out_mWperGHz')
|
||||
return extra
|
||||
if 'target_psd_out_mWperGHz' in params.keys() and params['target_psd_out_mWperGHz'] is not None:
|
||||
extra.__dict__.pop('target_pch_out_db')
|
||||
return extra
|
||||
if extra.target_pch_out_db is not None:
|
||||
extra.__dict__.pop('target_psd_out_mWperGHz')
|
||||
return extra
|
||||
if extra.target_psd_out_mWperGHz is not None:
|
||||
extra.__dict__.pop('target_pch_out_db')
|
||||
return extra
|
||||
return None
|
||||
|
||||
|
||||
def merge_amplifier_restrictions(dict1, dict2):
|
||||
"""Updates contents of dicts recursively
|
||||
|
||||
|
||||
@@ -181,19 +181,45 @@
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": {
|
||||
"cr":[
|
||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
||||
2E-07, 1E-07
|
||||
],
|
||||
"frequency_offset":[
|
||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
||||
41.5e12, 42e12
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type_variety": "NZDF",
|
||||
"dispersion": 0.5e-05,
|
||||
"gamma": 0.00146,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": null
|
||||
},
|
||||
{
|
||||
"type_variety": "LOF",
|
||||
"dispersion": 2.2e-05,
|
||||
"gamma": 0.000843,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": null
|
||||
}
|
||||
],
|
||||
"RamanFiber":[{
|
||||
|
||||
@@ -39,19 +39,45 @@
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": {
|
||||
"cr":[
|
||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
||||
2E-07, 1E-07
|
||||
],
|
||||
"frequency_offset":[
|
||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
||||
41.5e12, 42e12
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type_variety": "NZDF",
|
||||
"dispersion": 0.5e-05,
|
||||
"gamma": 0.00146,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": null
|
||||
},
|
||||
{
|
||||
"type_variety": "LOF",
|
||||
"dispersion": 2.2e-05,
|
||||
"gamma": 0.000843,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": null
|
||||
}
|
||||
],
|
||||
"RamanFiber":[
|
||||
|
||||
12
gnpy/example-data/initial_spectrum1.json
Normal file
12
gnpy/example-data/initial_spectrum1.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"SI":[
|
||||
{
|
||||
"f_min": 191.3e12,
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": 32e9,
|
||||
"spacing": 50e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}
|
||||
]
|
||||
}
|
||||
21
gnpy/example-data/initial_spectrum2.json
Normal file
21
gnpy/example-data/initial_spectrum2.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"SI":[
|
||||
{
|
||||
"f_min": 191.35e12,
|
||||
"f_max":193.1e12,
|
||||
"baud_rate": 32e9,
|
||||
"spacing": 50e9,
|
||||
"power_dbm": 0,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
},
|
||||
{
|
||||
"f_min": 193.1625e12,
|
||||
"f_max":195.1e12,
|
||||
"baud_rate": 64e9,
|
||||
"spacing": 75e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"raman_parameters": {
|
||||
"flag_raman": true,
|
||||
"space_resolution": 10e3,
|
||||
"tolerance": 1e-8
|
||||
"raman_params": {
|
||||
"flag": true,
|
||||
"result_spatial_resolution": 10e3,
|
||||
"solver_spatial_resolution": 50
|
||||
},
|
||||
"nli_parameters": {
|
||||
"nli_method_name": "ggn_spectrally_separated",
|
||||
"wdm_grid_size": 50e9,
|
||||
"dispersion_tolerance": 1,
|
||||
"phase_shift_tolerance": 0.1,
|
||||
"computed_channels": [1, 18, 37, 56, 75]
|
||||
"nli_params": {
|
||||
"method": "ggn_spectrally_separated",
|
||||
"dispersion_tolerance": 1,
|
||||
"phase_shift_tolerance": 0.1,
|
||||
"computed_channels": [1, 18, 37, 56, 75]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,23 @@ import sys
|
||||
from math import ceil
|
||||
from numpy import linspace, mean
|
||||
from pathlib import Path
|
||||
from copy import deepcopy
|
||||
|
||||
import gnpy.core.ansi_escapes as ansi_escapes
|
||||
from gnpy.core.elements import Transceiver, Fiber, RamanFiber
|
||||
from gnpy.core.equipment import trx_mode_params
|
||||
import gnpy.core.exceptions as exceptions
|
||||
from gnpy.core.network import build_network
|
||||
from gnpy.core.parameters import SimParams
|
||||
from gnpy.core.science_utils import Simulation
|
||||
from gnpy.core.utils import db2lin, lin2db, automatic_nch
|
||||
from gnpy.topology.request import (ResultElement, jsontocsv, compute_path_dsjctn, requests_aggregation,
|
||||
BLOCKING_NOPATH, correct_json_route_list,
|
||||
deduplicate_disjunctions, compute_path_with_disjunction,
|
||||
PathRequest, compute_constrained_path, propagate)
|
||||
PathRequest, compute_constrained_path, propagate, update_spectrum_power)
|
||||
from gnpy.topology.spectrum_assignment import build_oms_list, pth_assign_spectrum
|
||||
from gnpy.tools.json_io import load_equipment, load_network, load_json, load_requests, save_network, \
|
||||
requests_from_json, disjunctions_from_json, save_json
|
||||
requests_from_json, disjunctions_from_json, save_json, load_initial_spectrum,\
|
||||
_spectrum_from_json
|
||||
from gnpy.tools.plots import plot_baseline, plot_results
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -57,14 +59,14 @@ def load_common_data(equipment_filename, topology_filename, simulation_filename,
|
||||
if save_raw_network_filename is not None:
|
||||
save_network(network, save_raw_network_filename)
|
||||
print(f'{ansi_escapes.blue}Raw network (no optimizations) saved to {save_raw_network_filename}{ansi_escapes.reset}')
|
||||
sim_params = SimParams(**load_json(simulation_filename)) if simulation_filename is not None else None
|
||||
if not sim_params:
|
||||
if not simulation_filename:
|
||||
SimParams.default()
|
||||
if next((node for node in network if isinstance(node, RamanFiber)), None) is not None:
|
||||
print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
|
||||
f'RamanFiber requires passing simulation params via --sim-params')
|
||||
sys.exit(1)
|
||||
else:
|
||||
Simulation.set_params(sim_params)
|
||||
SimParams.set_params(load_json(simulation_filename))
|
||||
except exceptions.EquipmentConfigError as e:
|
||||
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
|
||||
sys.exit(1)
|
||||
@@ -119,6 +121,7 @@ def transmission_main_example(args=None):
|
||||
parser.add_argument('-pl', '--plot', action='store_true')
|
||||
parser.add_argument('-l', '--list-nodes', action='store_true', help='list all transceiver nodes')
|
||||
parser.add_argument('-po', '--power', default=0, help='channel ref power in dBm')
|
||||
parser.add_argument('-spectrum', '--mixed-rate-spectrum-file', help='user defined mixed rate spectrum json file')
|
||||
parser.add_argument('source', nargs='?', help='source node')
|
||||
parser.add_argument('destination', nargs='?', help='destination node')
|
||||
|
||||
@@ -196,11 +199,18 @@ def transmission_main_example(args=None):
|
||||
trx_params['power'] = db2lin(float(args.power)) * 1e-3
|
||||
params.update(trx_params)
|
||||
req = PathRequest(**params)
|
||||
|
||||
if args.mixed_rate_spectrum_file:
|
||||
req.initial_spectrum = load_initial_spectrum(args.mixed_rate_spectrum_file, equipment)
|
||||
print('warning: user input for spectrum used for propagation instead of SI')
|
||||
nb_channels = len(req.initial_spectrum)
|
||||
else:
|
||||
nb_channels = req.nb_channel
|
||||
print(f'There are {nb_channels} channels propagating')
|
||||
power_mode = equipment['Span']['default'].power_mode
|
||||
print('\n'.join([f'Power mode is set to {power_mode}',
|
||||
f'=> it can be modified in eqpt_config.json - Span']))
|
||||
|
||||
# Keep the reference channel for design: the one from SI, with full load same channels
|
||||
pref_ch_db = lin2db(req.power * 1e3) # reference channel power / span (SL=20dB)
|
||||
pref_total_db = pref_ch_db + lin2db(req.nb_channel) # reference total power / span (SL=20dB)
|
||||
try:
|
||||
@@ -227,9 +237,20 @@ def transmission_main_example(args=None):
|
||||
power_range = list(linspace(p_start, p_stop, p_num))
|
||||
except TypeError:
|
||||
print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]')
|
||||
|
||||
if hasattr(req, 'initial_spectrum'):
|
||||
record_intial_spectrum = req.initial_spectrum
|
||||
for dp_db in power_range:
|
||||
req.power = db2lin(pref_ch_db + dp_db) * 1e-3
|
||||
# if initial spectrum did not contain any power, now we need to use this one.
|
||||
# note the initial power defines a differential wrt req.power so that if req.power is set to 2mW (3dBm)
|
||||
# and initial spectrum was set to 0, this sets a initial per channel delta power to -3dB, so that
|
||||
# whatever the equalization, -3 dB is applied on all channels (ie initial power in initial spectrum pre-empts
|
||||
# pow option)
|
||||
if hasattr(req, 'initial_spectrum'):
|
||||
# without deepcopy, the previous dp setting is recorded as a user defined and spectrum is not properly
|
||||
# updated for the power sweep dp_db
|
||||
req.initial_spectrum = deepcopy(record_intial_spectrum)
|
||||
update_spectrum_power(req)
|
||||
if power_mode:
|
||||
print(f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:')
|
||||
else:
|
||||
@@ -265,9 +286,9 @@ def transmission_main_example(args=None):
|
||||
ch_freq = final_carrier.frequency * 1e-12
|
||||
ch_power = lin2db(final_carrier.power.signal * 1e3)
|
||||
print(
|
||||
'{:5}{:26.2f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format(
|
||||
'{:5}{:26.5f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format(
|
||||
final_carrier.channel_number, round(
|
||||
ch_freq, 2), round(
|
||||
ch_freq, 5), round(
|
||||
ch_power, 2), round(
|
||||
ch_osnr, 2), round(
|
||||
ch_snr_nl, 2), round(
|
||||
|
||||
@@ -17,7 +17,8 @@ from gnpy.core import ansi_escapes, elements
|
||||
from gnpy.core.equipment import trx_mode_params
|
||||
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError
|
||||
from gnpy.core.science_utils import estimate_nf_model
|
||||
from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions
|
||||
from gnpy.core.utils import (automatic_nch, automatic_fmax, merge_amplifier_restrictions, dbm2watt,
|
||||
merge_equalization)
|
||||
from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth
|
||||
from gnpy.tools.convert import xls_to_json_data
|
||||
from gnpy.tools.service_sheet import read_service_sheet
|
||||
@@ -46,7 +47,9 @@ class _JsonThing:
|
||||
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
||||
for k, v in default_values.items():
|
||||
setattr(self, k, clean_kwargs.get(k, v))
|
||||
if k not in clean_kwargs and name != 'Amp':
|
||||
if k not in clean_kwargs and name != 'Amp' and \
|
||||
(k == 'target_psd_out_mWperGHz' and 'target_pch_out_db' not in clean_kwargs) and \
|
||||
(k == 'target_pch_out_db' and 'target_psd_out_mWperGHz' not in clean_kwargs):
|
||||
print(ansi_escapes.red +
|
||||
f'\n WARNING missing {k} attribute in eqpt_config.json[{name}]' +
|
||||
f'\n default value is {k} = {v}' +
|
||||
@@ -91,7 +94,8 @@ class Span(_JsonThing):
|
||||
|
||||
class Roadm(_JsonThing):
|
||||
default_values = {
|
||||
'target_pch_out_db': -17,
|
||||
'target_pch_out_db': None,
|
||||
'target_psd_out_mWperGHz': None,
|
||||
'add_drop_osnr': 100,
|
||||
'pmd': 0,
|
||||
'restrictions': {
|
||||
@@ -116,18 +120,6 @@ class Transceiver(_JsonThing):
|
||||
|
||||
|
||||
class Fiber(_JsonThing):
|
||||
default_values = {
|
||||
'type_variety': '',
|
||||
'dispersion': None,
|
||||
'gamma': 0,
|
||||
'pmd_coef': 0
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.update_attr(self.default_values, kwargs, 'Fiber')
|
||||
|
||||
|
||||
class RamanFiber(_JsonThing):
|
||||
default_values = {
|
||||
'type_variety': '',
|
||||
'dispersion': None,
|
||||
@@ -136,6 +128,17 @@ class RamanFiber(_JsonThing):
|
||||
'raman_efficiency': None
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.update_attr(self.default_values, kwargs, 'Fiber')
|
||||
if self.raman_efficiency is not None:
|
||||
for param in ('cr', 'frequency_offset'):
|
||||
if param not in self.raman_efficiency:
|
||||
raise EquipmentConfigError(f'Fiber.raman_efficiency: missing "{param}" parameter')
|
||||
if self.raman_efficiency['frequency_offset'] != sorted(self.raman_efficiency['frequency_offset']):
|
||||
raise EquipmentConfigError(f'Fiber.raman_efficiency.frequency_offset is not sorted')
|
||||
|
||||
|
||||
class RamanFiber(Fiber):
|
||||
def __init__(self, **kwargs):
|
||||
self.update_attr(self.default_values, kwargs, 'RamanFiber')
|
||||
for param in ('cr', 'frequency_offset'):
|
||||
@@ -237,11 +240,50 @@ def _automatic_spacing(baud_rate):
|
||||
return min((s[1] for s in spacing_list if s[0] > baud_rate), default=baud_rate * 1.2)
|
||||
|
||||
|
||||
def _spectrum_from_json(json_data, equipment):
|
||||
""" json_data is a list of spectrum partitions each with {fmin, fmax, baudrate, roll_off, power and tx_osnr}
|
||||
creates the per freq dict of carrier's dict
|
||||
"""
|
||||
spectrum = {}
|
||||
# min freq is fmin - spacing/2 (numbering starts at 0)
|
||||
previous_part_max_freq = json_data[0]['f_min'] - json_data[0]['spacing'] / 2
|
||||
for index, part in enumerate(json_data):
|
||||
# add a label to the partition for the printings
|
||||
if 'label' not in part.keys():
|
||||
part['label'] = f'{index}-{round(part["baud_rate"] * 1e-9, 2)}'
|
||||
index = 1 # starting freq is exactly f_min + spacing to be consistent with utils.automatic_nch
|
||||
# first partition min frequency is f_min + spacing - spacing/2
|
||||
current_part_min_freq = part['f_min'] + part['spacing'] / 2 # supposes that carriers are centered on frequency
|
||||
if 'power_dbm' in part:
|
||||
# user defined partition power.
|
||||
part['power'] = dbm2watt(part['power_dbm'])
|
||||
else:
|
||||
part['power'] = None
|
||||
if previous_part_max_freq <= current_part_min_freq:
|
||||
# check that previous part last channel does not overlap on next part first channel
|
||||
# TODO use functions from andrea to check consistency of spectrum instead
|
||||
current_freq = part['f_min'] + index * part['spacing']
|
||||
while current_freq <= part['f_max']:
|
||||
spectrum[current_freq] = part
|
||||
index += 1
|
||||
current_freq = part['f_min'] + index * part['spacing']
|
||||
previous_part_max_freq = current_freq - part['spacing'] / 2
|
||||
else:
|
||||
raise ValueError('not a valid initial spectrum definition')
|
||||
|
||||
return spectrum
|
||||
|
||||
|
||||
def load_equipment(filename):
|
||||
json_data = load_json(filename)
|
||||
return _equipment_from_json(json_data, filename)
|
||||
|
||||
|
||||
def load_initial_spectrum(filename, equipment):
|
||||
json_data = load_json(filename)
|
||||
return _spectrum_from_json(json_data['SI'], equipment)
|
||||
|
||||
|
||||
def _update_dual_stage(equipment):
|
||||
edfa_dict = equipment['Edfa']
|
||||
for edfa in edfa_dict.values():
|
||||
@@ -374,6 +416,10 @@ def network_from_json(json_data, equipment):
|
||||
elif variety in equipment[typ]:
|
||||
extra_params = equipment[typ][variety]
|
||||
temp = el_config.setdefault('params', {})
|
||||
if typ == 'Roadm':
|
||||
# if equalisation is not defined in the element config, then retrieve the general one from SI
|
||||
# else use the one from the element config. Only one type of equalisation is allowed.
|
||||
extra_params = merge_equalization(temp, extra_params)
|
||||
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
|
||||
el_config['params'] = temp
|
||||
el_config['type_variety'] = variety
|
||||
|
||||
@@ -22,8 +22,8 @@ from networkx import (dijkstra_path, NetworkXNoPath,
|
||||
from networkx.utils import pairwise
|
||||
from numpy import mean
|
||||
from gnpy.core.elements import Transceiver, Roadm
|
||||
from gnpy.core.utils import lin2db
|
||||
from gnpy.core.info import create_input_spectral_information
|
||||
from gnpy.core.utils import lin2db, dbm2watt
|
||||
from gnpy.core.info import create_input_spectral_information, use_initial_spectrum
|
||||
from gnpy.core.exceptions import ServiceError, DisjunctionError
|
||||
import gnpy.core.ansi_escapes as ansi_escapes
|
||||
from copy import deepcopy
|
||||
@@ -338,10 +338,34 @@ def compute_constrained_path(network, req):
|
||||
return total_path
|
||||
|
||||
|
||||
def ref_carrier(req_power, equipment):
|
||||
""" the function creates a reference with SI information, and carries also request's power
|
||||
"""
|
||||
ref_carrier = {key: getattr(equipment['SI']['default'], key) for key in
|
||||
['f_min', 'f_max', 'baud_rate', 'spacing', 'roll_off', 'tx_osnr']}
|
||||
ref_carrier['power'] = dbm2watt(equipment['SI']['default'].power_dbm)
|
||||
ref_carrier['req_power'] = req_power
|
||||
return ref_carrier
|
||||
|
||||
|
||||
def update_spectrum_power(req):
|
||||
""" Initial user defined spectrum may not contain power, in this case use the request's one
|
||||
as default value.
|
||||
"""
|
||||
for spectrum in req.initial_spectrum.values():
|
||||
if spectrum['power'] is None:
|
||||
spectrum['power'] = req.power
|
||||
|
||||
|
||||
def propagate(path, req, equipment):
|
||||
si = create_input_spectral_information(
|
||||
req.f_min, req.f_max, req.roll_off, req.baud_rate,
|
||||
req.power, req.spacing)
|
||||
""" propagates signals in each element according to initial spectrum set by user
|
||||
"""
|
||||
if hasattr(req, 'initial_spectrum'):
|
||||
si = use_initial_spectrum(req.initial_spectrum, ref_carrier=ref_carrier(req.power, equipment))
|
||||
else:
|
||||
si = create_input_spectral_information(
|
||||
req.f_min, req.f_max, req.roll_off, req.baud_rate,
|
||||
req.power, req.spacing, ref_carrier=ref_carrier(req.power, equipment))
|
||||
for i, el in enumerate(path):
|
||||
if isinstance(el, Roadm):
|
||||
si = el(si, degree=path[i+1].uid)
|
||||
@@ -375,9 +399,18 @@ def propagate_and_optimize_mode(path, req, equipment):
|
||||
# step2: computes propagation for each baudrate: stop and select the first that passes
|
||||
# TODO: the case of roll of is not included: for now use SI one
|
||||
# TODO: if the loop in mode optimization does not have a feasible path, then bugs
|
||||
spc_info = create_input_spectral_information(req.f_min, req.f_max,
|
||||
equipment['SI']['default'].roll_off,
|
||||
this_br, req.power, req.spacing)
|
||||
if hasattr(req, 'initial_spectrum'):
|
||||
# add the current explored mode caracteristic on the initial spectrum
|
||||
# maybe use a copy instead of changing the request ?
|
||||
for e in req.initial_spectrum.values():
|
||||
if e['baud_rate'] is None:
|
||||
e['baud_rate'] = this_br
|
||||
spc_info = use_initial_spectrum(req.initial_spectrum, ref_carrier=ref_carrier(req.power, equipment))
|
||||
else:
|
||||
spc_info = create_input_spectral_information(req.f_min, req.f_max,
|
||||
equipment['SI']['default'].roll_off,
|
||||
this_br, req.power, req.spacing,
|
||||
ref_carrier=ref_carrier(req.power, equipment))
|
||||
for i, el in enumerate(path):
|
||||
if isinstance(el, Roadm):
|
||||
spc_info = el(spc_info, degree=path[i+1].uid)
|
||||
|
||||
@@ -64,7 +64,31 @@
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": {
|
||||
"cr":[
|
||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
||||
2E-07, 1E-07
|
||||
],
|
||||
"frequency_offset":[
|
||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
||||
41.5e12, 42e12
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"Span":[{
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"raman_parameters": {
|
||||
"flag_raman": true,
|
||||
"space_resolution": 10e3,
|
||||
"tolerance": 1e-8
|
||||
"raman_params": {
|
||||
"flag": true,
|
||||
"result_spatial_resolution": 10e3,
|
||||
"solver_spatial_resolution": 50
|
||||
},
|
||||
"nli_parameters": {
|
||||
"nli_method_name": "ggn_spectrally_separated",
|
||||
"wdm_grid_size": 50e9,
|
||||
"nli_params": {
|
||||
"method": "ggn_spectrally_separated",
|
||||
"dispersion_tolerance": 1,
|
||||
"phase_shift_tolerance": 0.1,
|
||||
"computed_channels": [1, 18, 37, 56, 75]
|
||||
}
|
||||
}
|
||||
}
|
||||
97
tests/data/test_fiber_fix_expected_results.csv
Normal file
97
tests/data/test_fiber_fix_expected_results.csv
Normal file
@@ -0,0 +1,97 @@
|
||||
signal,nli
|
||||
1.9952623149688793e-05,1.1158426495504604e-08
|
||||
1.9952623149688793e-05,1.263949624403159e-08
|
||||
1.9952623149688793e-05,1.3358478621325285e-08
|
||||
1.9952623149688793e-05,1.3830775406251184e-08
|
||||
1.9952623149688793e-05,1.4180462471172083e-08
|
||||
1.9952623149688793e-05,1.4456701012984246e-08
|
||||
1.9952623149688793e-05,1.4683973899785875e-08
|
||||
1.9952623149688793e-05,1.487624147046227e-08
|
||||
1.9952623149688793e-05,1.5042217041806274e-08
|
||||
1.9952623149688793e-05,1.5187703614492153e-08
|
||||
1.9952623149688793e-05,1.5316759790785317e-08
|
||||
1.9952623149688793e-05,1.543233485150211e-08
|
||||
1.9952623149688793e-05,1.553663885878994e-08
|
||||
1.9952623149688793e-05,1.5631370249579246e-08
|
||||
1.9952623149688793e-05,1.5717862065800704e-08
|
||||
1.9952623149688793e-05,1.57971793985894e-08
|
||||
1.9952623149688793e-05,1.5870186356579704e-08
|
||||
1.9952623149688793e-05,1.593759332223716e-08
|
||||
1.9952623149688793e-05,1.5999991070923486e-08
|
||||
1.9952623149688793e-05,1.6057875903450682e-08
|
||||
1.9952623149688793e-05,1.6111668489205982e-08
|
||||
1.9952623149688793e-05,1.6161728217386366e-08
|
||||
1.9952623149688793e-05,1.6208364281630228e-08
|
||||
1.9952623149688793e-05,1.6251844350226973e-08
|
||||
1.9952623149688793e-05,1.629240142540359e-08
|
||||
1.9952623149688793e-05,1.6330239326114482e-08
|
||||
1.9952623149688793e-05,1.6365537111728e-08
|
||||
1.9952623149688793e-05,1.6398452681655655e-08
|
||||
1.9952623149688793e-05,1.642912572715412e-08
|
||||
1.9952623149688793e-05,1.6457680168940455e-08
|
||||
1.9952623149688793e-05,1.6484226183026747e-08
|
||||
1.9952623149688793e-05,1.6508861894003893e-08
|
||||
1.9952623149688793e-05,1.6531674797617433e-08
|
||||
1.9952623149688793e-05,1.655274296130114e-08
|
||||
1.9952623149688793e-05,1.657213604125123e-08
|
||||
1.9952623149688793e-05,1.6589916146838222e-08
|
||||
1.9952623149688793e-05,1.660613857708963e-08
|
||||
1.9952623149688793e-05,1.6620852449214096e-08
|
||||
1.9952623149688793e-05,1.6634101235366932e-08
|
||||
1.9952623149688793e-05,1.664592322084737e-08
|
||||
1.9952623149688793e-05,1.6656351894496074e-08
|
||||
1.9952623149688793e-05,1.666541628009631e-08
|
||||
1.9952623149688793e-05,1.6673141215973025e-08
|
||||
1.9952623149688793e-05,1.6679547588653583e-08
|
||||
1.9952623149688793e-05,1.6684652525341145e-08
|
||||
1.9952623149688793e-05,1.668846954900963e-08
|
||||
1.9952623149688793e-05,1.66910086991187e-08
|
||||
1.9952623149688793e-05,1.6692276620238304e-08
|
||||
1.9952623149688793e-05,1.6692276620238304e-08
|
||||
1.9952623149688793e-05,1.6691008699118703e-08
|
||||
1.9952623149688793e-05,1.6688469549009633e-08
|
||||
1.9952623149688793e-05,1.6684652525341148e-08
|
||||
1.9952623149688793e-05,1.6679547588653586e-08
|
||||
1.9952623149688793e-05,1.6673141215973028e-08
|
||||
1.9952623149688793e-05,1.666541628009631e-08
|
||||
1.9952623149688793e-05,1.6656351894496084e-08
|
||||
1.9952623149688793e-05,1.6645923220847374e-08
|
||||
1.9952623149688793e-05,1.6634101235366935e-08
|
||||
1.9952623149688793e-05,1.66208524492141e-08
|
||||
1.9952623149688793e-05,1.6606138577089633e-08
|
||||
1.9952623149688793e-05,1.6589916146838225e-08
|
||||
1.9952623149688793e-05,1.6572136041251237e-08
|
||||
1.9952623149688793e-05,1.6552742961301146e-08
|
||||
1.9952623149688793e-05,1.653167479761744e-08
|
||||
1.9952623149688793e-05,1.6508861894003893e-08
|
||||
1.9952623149688793e-05,1.648422618302675e-08
|
||||
1.9952623149688793e-05,1.645768016894046e-08
|
||||
1.9952623149688793e-05,1.6429125727154126e-08
|
||||
1.9952623149688793e-05,1.6398452681655658e-08
|
||||
1.9952623149688793e-05,1.6365537111728004e-08
|
||||
1.9952623149688793e-05,1.6330239326114482e-08
|
||||
1.9952623149688793e-05,1.6292401425403594e-08
|
||||
1.9952623149688793e-05,1.6251844350226973e-08
|
||||
1.9952623149688793e-05,1.6208364281630228e-08
|
||||
1.9952623149688793e-05,1.616172821738637e-08
|
||||
1.9952623149688793e-05,1.6111668489205982e-08
|
||||
1.9952623149688793e-05,1.605787590345069e-08
|
||||
1.9952623149688793e-05,1.5999991070923493e-08
|
||||
1.9952623149688793e-05,1.5937593322237167e-08
|
||||
1.9952623149688793e-05,1.5870186356579704e-08
|
||||
1.9952623149688793e-05,1.5797179398589402e-08
|
||||
1.9952623149688793e-05,1.571786206580071e-08
|
||||
1.9952623149688793e-05,1.5631370249579252e-08
|
||||
1.9952623149688793e-05,1.5536638858789946e-08
|
||||
1.9952623149688793e-05,1.5432334851502114e-08
|
||||
1.9952623149688793e-05,1.531675979078532e-08
|
||||
1.9952623149688793e-05,1.5187703614492156e-08
|
||||
1.9952623149688793e-05,1.5042217041806274e-08
|
||||
1.9952623149688793e-05,1.4876241470462273e-08
|
||||
1.9952623149688793e-05,1.4683973899785879e-08
|
||||
1.9952623149688793e-05,1.4456701012984246e-08
|
||||
1.9952623149688793e-05,1.4180462471172086e-08
|
||||
1.9952623149688793e-05,1.3830775406251184e-08
|
||||
1.9952623149688793e-05,1.3358478621325285e-08
|
||||
1.9952623149688793e-05,1.2639496244031593e-08
|
||||
1.9952623149688793e-05,1.1158426495504613e-08
|
||||
|
6
tests/data/test_fiber_flex_expected_results.csv
Normal file
6
tests/data/test_fiber_flex_expected_results.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
signal,nli
|
||||
1.9952623149688793e-05,5.522326183599433e-09
|
||||
1.7957360834719913e-05,4.5606601423111315e-09
|
||||
2.593841009459543e-05,6.633717697038881e-09
|
||||
1.5962098519751036e-05,4.3237017878447286e-09
|
||||
2.3943147779626553e-05,8.311382502260195e-09
|
||||
|
810
tests/data/test_long_network.json
Normal file
810
tests/data/test_long_network.json
Normal file
@@ -0,0 +1,810 @@
|
||||
{
|
||||
"network_name": "Example Network - long path",
|
||||
"elements": [{
|
||||
"uid": "Site_A",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Site A",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "booster A",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span1",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa1",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span2",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa2",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span3",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa3",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span4",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa4",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span5",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa5",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Site C",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "booster C",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span6",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa6",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span7",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa7",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span8",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa8",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span9",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa9",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span10",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa10",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Site D",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "booster D",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span11",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa11",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span12",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa12",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Site E",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "booster E",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span13",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa13",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span14",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa14",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test_fixed_gain",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span15",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa15",
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Site B",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site B",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "Site_B",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site B",
|
||||
"region": "",
|
||||
"latitude": 3,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"connections": [{
|
||||
"from_node": "Site_A",
|
||||
"to_node": "roadm Site A"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Site A",
|
||||
"to_node": "booster A"
|
||||
},
|
||||
{
|
||||
"from_node": "booster A",
|
||||
"to_node": "Span1"
|
||||
},
|
||||
{
|
||||
"from_node": "Span1",
|
||||
"to_node": "Edfa1"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa1",
|
||||
"to_node": "Span2"
|
||||
},
|
||||
{
|
||||
"from_node": "Span2",
|
||||
"to_node": "Edfa2"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa2",
|
||||
"to_node": "Span3"
|
||||
},
|
||||
{
|
||||
"from_node": "Span3",
|
||||
"to_node": "Edfa3"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa3",
|
||||
"to_node": "Span4"
|
||||
},
|
||||
{
|
||||
"from_node": "Span4",
|
||||
"to_node": "Edfa4"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa4",
|
||||
"to_node": "Span5"
|
||||
},
|
||||
{
|
||||
"from_node": "Span5",
|
||||
"to_node": "Edfa5"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa5",
|
||||
"to_node": "roadm Site C"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Site C",
|
||||
"to_node": "booster C"
|
||||
},
|
||||
{
|
||||
"from_node": "booster C",
|
||||
"to_node": "Span6"
|
||||
},
|
||||
{
|
||||
"from_node": "Span6",
|
||||
"to_node": "Edfa6"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa6",
|
||||
"to_node": "Span7"
|
||||
},
|
||||
{
|
||||
"from_node": "Span7",
|
||||
"to_node": "Edfa7"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa7",
|
||||
"to_node": "Span8"
|
||||
},
|
||||
{
|
||||
"from_node": "Span8",
|
||||
"to_node": "Edfa8"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa8",
|
||||
"to_node": "Span9"
|
||||
},
|
||||
{
|
||||
"from_node": "Span9",
|
||||
"to_node": "Edfa9"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa9",
|
||||
"to_node": "Span10"
|
||||
},
|
||||
{
|
||||
"from_node": "Span10",
|
||||
"to_node": "Edfa10"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa10",
|
||||
"to_node": "roadm Site D"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Site D",
|
||||
"to_node": "booster D"
|
||||
},
|
||||
{
|
||||
"from_node": "booster D",
|
||||
"to_node": "Span11"
|
||||
},
|
||||
{
|
||||
"from_node": "Span11",
|
||||
"to_node": "Edfa11"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa11",
|
||||
"to_node": "Span12"
|
||||
},
|
||||
{
|
||||
"from_node": "Span12",
|
||||
"to_node": "Edfa12"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa12",
|
||||
"to_node": "roadm Site E"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Site E",
|
||||
"to_node": "booster E"
|
||||
},
|
||||
{
|
||||
"from_node": "booster E",
|
||||
"to_node": "Span13"
|
||||
},
|
||||
{
|
||||
"from_node": "Span13",
|
||||
"to_node": "Edfa13"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa13",
|
||||
"to_node": "Span14"
|
||||
},
|
||||
{
|
||||
"from_node": "Span14",
|
||||
"to_node": "Edfa14"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa14",
|
||||
"to_node": "Span15"
|
||||
},
|
||||
{
|
||||
"from_node": "Span15",
|
||||
"to_node": "Edfa15"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa15",
|
||||
"to_node": "roadm Site B"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Site B",
|
||||
"to_node": "Site_B"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
212
tests/data/test_lumped_losses_fiber_config.json
Normal file
212
tests/data/test_lumped_losses_fiber_config.json
Normal file
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"uid": "Span1",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0,
|
||||
"con_in": 0.5,
|
||||
"con_out": 0.5,
|
||||
"lumped_losses": [
|
||||
{"position": 7, "loss": 0.5}
|
||||
],
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 0.0000167,
|
||||
"pmd_coef": 1.265e-15,
|
||||
"gamma": 0.00127,
|
||||
"raman_efficiency": {
|
||||
"cr": [
|
||||
0,
|
||||
0.0000094,
|
||||
0.0000292,
|
||||
0.0000488,
|
||||
0.0000682,
|
||||
0.0000831,
|
||||
0.000094,
|
||||
0.0001014,
|
||||
0.0001069,
|
||||
0.0001119,
|
||||
0.0001217,
|
||||
0.0001268,
|
||||
0.0001365,
|
||||
0.000149,
|
||||
0.000165,
|
||||
0.000181,
|
||||
0.0001977,
|
||||
0.0002192,
|
||||
0.0002469,
|
||||
0.0002749,
|
||||
0.0002999,
|
||||
0.0003206,
|
||||
0.0003405,
|
||||
0.0003592,
|
||||
0.000374,
|
||||
0.0003826,
|
||||
0.0003841,
|
||||
0.0003826,
|
||||
0.0003802,
|
||||
0.0003756,
|
||||
0.0003549,
|
||||
0.0003795,
|
||||
0.000344,
|
||||
0.0002933,
|
||||
0.0002024,
|
||||
0.0001158,
|
||||
0.0000846,
|
||||
0.0000714,
|
||||
0.0000686,
|
||||
0.000085,
|
||||
0.0000893,
|
||||
0.0000901,
|
||||
0.0000815,
|
||||
0.0000667,
|
||||
0.0000437,
|
||||
0.0000328,
|
||||
0.0000296,
|
||||
0.0000265,
|
||||
0.0000257,
|
||||
0.0000281,
|
||||
0.0000308,
|
||||
0.0000367,
|
||||
0.0000585,
|
||||
0.0000663,
|
||||
0.0000636,
|
||||
0.000055,
|
||||
0.0000406,
|
||||
0.0000277,
|
||||
0.0000242,
|
||||
0.0000187,
|
||||
0.000016,
|
||||
0.000014,
|
||||
0.0000113,
|
||||
0.0000105,
|
||||
0.0000098,
|
||||
0.0000098,
|
||||
0.0000113,
|
||||
0.0000164,
|
||||
0.0000195,
|
||||
0.0000238,
|
||||
0.0000226,
|
||||
0.0000203,
|
||||
0.0000148,
|
||||
0.0000109,
|
||||
0.0000098,
|
||||
0.0000105,
|
||||
0.0000117,
|
||||
0.0000125,
|
||||
0.0000121,
|
||||
0.0000109,
|
||||
0.0000098,
|
||||
0.0000082,
|
||||
0.0000066,
|
||||
0.0000047,
|
||||
0.0000027,
|
||||
0.0000019,
|
||||
0.0000012,
|
||||
4e-7,
|
||||
2e-7,
|
||||
1e-7
|
||||
],
|
||||
"frequency_offset": [
|
||||
0,
|
||||
500000000000,
|
||||
1000000000000,
|
||||
1500000000000,
|
||||
2000000000000,
|
||||
2500000000000,
|
||||
3000000000000,
|
||||
3500000000000,
|
||||
4000000000000,
|
||||
4500000000000,
|
||||
5000000000000,
|
||||
5500000000000,
|
||||
6000000000000,
|
||||
6500000000000,
|
||||
7000000000000,
|
||||
7500000000000,
|
||||
8000000000000,
|
||||
8500000000000,
|
||||
9000000000000,
|
||||
9500000000000,
|
||||
10000000000000,
|
||||
10500000000000,
|
||||
11000000000000,
|
||||
11500000000000,
|
||||
12000000000000,
|
||||
12500000000000,
|
||||
12750000000000,
|
||||
13000000000000,
|
||||
13250000000000,
|
||||
13500000000000,
|
||||
14000000000000,
|
||||
14500000000000,
|
||||
14750000000000,
|
||||
15000000000000,
|
||||
15500000000000,
|
||||
16000000000000,
|
||||
16500000000000,
|
||||
17000000000000,
|
||||
17500000000000,
|
||||
18000000000000,
|
||||
18250000000000,
|
||||
18500000000000,
|
||||
18750000000000,
|
||||
19000000000000,
|
||||
19500000000000,
|
||||
20000000000000,
|
||||
20500000000000,
|
||||
21000000000000,
|
||||
21500000000000,
|
||||
22000000000000,
|
||||
22500000000000,
|
||||
23000000000000,
|
||||
23500000000000,
|
||||
24000000000000,
|
||||
24500000000000,
|
||||
25000000000000,
|
||||
25500000000000,
|
||||
26000000000000,
|
||||
26500000000000,
|
||||
27000000000000,
|
||||
27500000000000,
|
||||
28000000000000,
|
||||
28500000000000,
|
||||
29000000000000,
|
||||
29500000000000,
|
||||
30000000000000,
|
||||
30500000000000,
|
||||
31000000000000,
|
||||
31500000000000,
|
||||
32000000000000,
|
||||
32500000000000,
|
||||
33000000000000,
|
||||
33500000000000,
|
||||
34000000000000,
|
||||
34500000000000,
|
||||
35000000000000,
|
||||
35500000000000,
|
||||
36000000000000,
|
||||
36500000000000,
|
||||
37000000000000,
|
||||
37500000000000,
|
||||
38000000000000,
|
||||
38500000000000,
|
||||
39000000000000,
|
||||
39500000000000,
|
||||
40000000000000,
|
||||
40500000000000,
|
||||
41000000000000,
|
||||
41500000000000,
|
||||
42000000000000
|
||||
]
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1,
|
||||
"longitude": 0,
|
||||
"city": null,
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
tests/data/test_lumped_losses_fiber_no_pumps.npy
Normal file
BIN
tests/data/test_lumped_losses_fiber_no_pumps.npy
Normal file
Binary file not shown.
BIN
tests/data/test_lumped_losses_fiber_no_raman.npy
Normal file
BIN
tests/data/test_lumped_losses_fiber_no_raman.npy
Normal file
Binary file not shown.
BIN
tests/data/test_lumped_losses_raman_fiber.npy
Normal file
BIN
tests/data/test_lumped_losses_raman_fiber.npy
Normal file
Binary file not shown.
227
tests/data/test_lumped_losses_raman_fiber_config.json
Normal file
227
tests/data/test_lumped_losses_raman_fiber_config.json
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"uid": "Span1",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0,
|
||||
"con_in": 0.5,
|
||||
"con_out": 0.5,
|
||||
"lumped_losses": [
|
||||
{"position": 7, "loss": 0.5}
|
||||
],
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 0.0000167,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": {
|
||||
"cr": [
|
||||
0,
|
||||
0.0000094,
|
||||
0.0000292,
|
||||
0.0000488,
|
||||
0.0000682,
|
||||
0.0000831,
|
||||
0.000094,
|
||||
0.0001014,
|
||||
0.0001069,
|
||||
0.0001119,
|
||||
0.0001217,
|
||||
0.0001268,
|
||||
0.0001365,
|
||||
0.000149,
|
||||
0.000165,
|
||||
0.000181,
|
||||
0.0001977,
|
||||
0.0002192,
|
||||
0.0002469,
|
||||
0.0002749,
|
||||
0.0002999,
|
||||
0.0003206,
|
||||
0.0003405,
|
||||
0.0003592,
|
||||
0.000374,
|
||||
0.0003826,
|
||||
0.0003841,
|
||||
0.0003826,
|
||||
0.0003802,
|
||||
0.0003756,
|
||||
0.0003549,
|
||||
0.0003795,
|
||||
0.000344,
|
||||
0.0002933,
|
||||
0.0002024,
|
||||
0.0001158,
|
||||
0.0000846,
|
||||
0.0000714,
|
||||
0.0000686,
|
||||
0.000085,
|
||||
0.0000893,
|
||||
0.0000901,
|
||||
0.0000815,
|
||||
0.0000667,
|
||||
0.0000437,
|
||||
0.0000328,
|
||||
0.0000296,
|
||||
0.0000265,
|
||||
0.0000257,
|
||||
0.0000281,
|
||||
0.0000308,
|
||||
0.0000367,
|
||||
0.0000585,
|
||||
0.0000663,
|
||||
0.0000636,
|
||||
0.000055,
|
||||
0.0000406,
|
||||
0.0000277,
|
||||
0.0000242,
|
||||
0.0000187,
|
||||
0.000016,
|
||||
0.000014,
|
||||
0.0000113,
|
||||
0.0000105,
|
||||
0.0000098,
|
||||
0.0000098,
|
||||
0.0000113,
|
||||
0.0000164,
|
||||
0.0000195,
|
||||
0.0000238,
|
||||
0.0000226,
|
||||
0.0000203,
|
||||
0.0000148,
|
||||
0.0000109,
|
||||
0.0000098,
|
||||
0.0000105,
|
||||
0.0000117,
|
||||
0.0000125,
|
||||
0.0000121,
|
||||
0.0000109,
|
||||
0.0000098,
|
||||
0.0000082,
|
||||
0.0000066,
|
||||
0.0000047,
|
||||
0.0000027,
|
||||
0.0000019,
|
||||
0.0000012,
|
||||
4e-7,
|
||||
2e-7,
|
||||
1e-7
|
||||
],
|
||||
"frequency_offset": [
|
||||
0,
|
||||
500000000000,
|
||||
1000000000000,
|
||||
1500000000000,
|
||||
2000000000000,
|
||||
2500000000000,
|
||||
3000000000000,
|
||||
3500000000000,
|
||||
4000000000000,
|
||||
4500000000000,
|
||||
5000000000000,
|
||||
5500000000000,
|
||||
6000000000000,
|
||||
6500000000000,
|
||||
7000000000000,
|
||||
7500000000000,
|
||||
8000000000000,
|
||||
8500000000000,
|
||||
9000000000000,
|
||||
9500000000000,
|
||||
10000000000000,
|
||||
10500000000000,
|
||||
11000000000000,
|
||||
11500000000000,
|
||||
12000000000000,
|
||||
12500000000000,
|
||||
12750000000000,
|
||||
13000000000000,
|
||||
13250000000000,
|
||||
13500000000000,
|
||||
14000000000000,
|
||||
14500000000000,
|
||||
14750000000000,
|
||||
15000000000000,
|
||||
15500000000000,
|
||||
16000000000000,
|
||||
16500000000000,
|
||||
17000000000000,
|
||||
17500000000000,
|
||||
18000000000000,
|
||||
18250000000000,
|
||||
18500000000000,
|
||||
18750000000000,
|
||||
19000000000000,
|
||||
19500000000000,
|
||||
20000000000000,
|
||||
20500000000000,
|
||||
21000000000000,
|
||||
21500000000000,
|
||||
22000000000000,
|
||||
22500000000000,
|
||||
23000000000000,
|
||||
23500000000000,
|
||||
24000000000000,
|
||||
24500000000000,
|
||||
25000000000000,
|
||||
25500000000000,
|
||||
26000000000000,
|
||||
26500000000000,
|
||||
27000000000000,
|
||||
27500000000000,
|
||||
28000000000000,
|
||||
28500000000000,
|
||||
29000000000000,
|
||||
29500000000000,
|
||||
30000000000000,
|
||||
30500000000000,
|
||||
31000000000000,
|
||||
31500000000000,
|
||||
32000000000000,
|
||||
32500000000000,
|
||||
33000000000000,
|
||||
33500000000000,
|
||||
34000000000000,
|
||||
34500000000000,
|
||||
35000000000000,
|
||||
35500000000000,
|
||||
36000000000000,
|
||||
36500000000000,
|
||||
37000000000000,
|
||||
37500000000000,
|
||||
38000000000000,
|
||||
38500000000000,
|
||||
39000000000000,
|
||||
39500000000000,
|
||||
40000000000000,
|
||||
40500000000000,
|
||||
41000000000000,
|
||||
41500000000000,
|
||||
42000000000000
|
||||
]
|
||||
}
|
||||
},
|
||||
"operational": {
|
||||
"temperature": 283,
|
||||
"raman_pumps": [
|
||||
{
|
||||
"power": 0.2,
|
||||
"frequency": 205000000000000,
|
||||
"propagation_direction": "counterprop"
|
||||
},
|
||||
{
|
||||
"power": 0.206,
|
||||
"frequency": 201000000000000,
|
||||
"propagation_direction": "counterprop"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1,
|
||||
"longitude": 0,
|
||||
"city": null,
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
97
tests/data/test_raman_fiber_expected_results.csv
Normal file
97
tests/data/test_raman_fiber_expected_results.csv
Normal file
@@ -0,0 +1,97 @@
|
||||
signal,nli,ase
|
||||
0,0.0002866705468946441,2.177394829242565e-07,3.4557191793558825e-08
|
||||
1,0.00028429526393394377,2.2012781143543237e-07,3.4445502692391435e-08
|
||||
2,0.00028194056061390773,2.224623221237509e-07,3.433445887467792e-08
|
||||
3,0.00027960624613715477,2.247437720846811e-07,3.422405538481241e-08
|
||||
4,0.0002758942662605477,2.2582870905131877e-07,3.3956503060525654e-08
|
||||
5,0.0002722323881863356,2.2684591469841408e-07,3.369116031853938e-08
|
||||
6,0.000268619918350984,2.277970173994804e-07,3.342800240189267e-08
|
||||
7,0.000265053715317489,2.2868149265452554e-07,3.31669825978832e-08
|
||||
8,0.0002615332083291819,2.2950088648412205e-07,3.2908077452451265e-08
|
||||
9,0.0002577026598717891,2.29939807349622e-07,3.260943794608576e-08
|
||||
10,0.0002539265998701895,2.303151728478784e-07,3.23135112959506e-08
|
||||
11,0.000250197552301535,2.3062250247045e-07,3.2020149186684304e-08
|
||||
12,0.0002465150832963999,2.3086346975365183e-07,3.172932441983654e-08
|
||||
13,0.00024287876009092854,2.3103972369261411e-07,3.144100993235306e-08
|
||||
14,0.00023918814592805183,2.31056283673814e-07,3.114286828089368e-08
|
||||
15,0.00023554582204055567,2.310113542844721e-07,3.084739480128956e-08
|
||||
16,0.00023195130631956971,2.3090659197839515e-07,3.055456016860592e-08
|
||||
17,0.00022840433901323014,2.307438494055778e-07,3.026433722256217e-08
|
||||
18,0.0002249044309608348,2.2685792845882788e-07,2.997669682160718e-08
|
||||
19,0.00022103550529979762,2.2261125752357212e-07,2.963927431547004e-08
|
||||
20,0.0002172262095203314,2.184365961387324e-07,2.9305346170341454e-08
|
||||
21,0.0002134758798406954,2.1433299933606587e-07,2.8974869975180298e-08
|
||||
22,0.0002097837429161198,2.102994164488689e-07,2.8647801621001083e-08
|
||||
23,0.00020614903259761412,2.063348088289235e-07,2.8324097353256504e-08
|
||||
24,0.00020282505012919792,2.0269204338245043e-07,2.8034743773023506e-08
|
||||
25,0.00019954846914292654,1.9910692504926397e-07,2.7748188517931413e-08
|
||||
26,0.0001963187365960183,1.955786814668348e-07,2.7464399406269038e-08
|
||||
27,0.00019313601236366093,1.9210725283739872e-07,2.71833510938317e-08
|
||||
28,0.00018999971525214364,1.886918423998114e-07,2.6905011507090682e-08
|
||||
29,0.00018690926921963096,1.8533166212086657e-07,2.6629348802784474e-08
|
||||
30,0.00018386410436192706,1.820259336310992e-07,2.635633143849771e-08
|
||||
31,0.00018086374979011733,1.7877397998150293e-07,2.6085929795727407e-08
|
||||
32,0.00017790764094943303,1.7557503471789446e-07,2.5818112682654427e-08
|
||||
33,0.00017499521851272397,1.724283400529523e-07,2.5552849119349174e-08
|
||||
34,0.00017219248535735765,1.6939862390063425e-07,2.529836490008028e-08
|
||||
35,0.00016943017410898177,1.664173382700801e-07,2.5046323660212428e-08
|
||||
36,0.0001667077872998461,1.634838065100415e-07,2.4796697985876285e-08
|
||||
37,0.0001640259411699002,1.6034105983552547e-07,2.4549471241938992e-08
|
||||
38,0.00016138409116954428,1.5725405329068436e-07,2.430461590519894e-08
|
||||
39,0.00015878169900055325,1.542218889375427e-07,2.4062104674963863e-08
|
||||
40,0.000156218232533133,1.5124368154127442e-07,2.38219104669703e-08
|
||||
41,0.00015369496700007087,1.4832029668067725e-07,2.3584040136547525e-08
|
||||
42,0.00015121129156099526,1.4545076976680713e-07,2.3348465494119215e-08
|
||||
43,0.0001487666043717642,1.4263415247435296e-07,2.3115158601715748e-08
|
||||
44,0.00014623128236243723,1.3974620462259893e-07,2.286438328716338e-08
|
||||
45,0.0001437380524819555,1.3691420205996233e-07,2.2616176641497093e-08
|
||||
46,0.00014128623388642375,1.341371036381095e-07,2.237050551788219e-08
|
||||
47,0.00013887622989024388,1.3141490263262782e-07,2.212734756671424e-08
|
||||
48,0.0001365073237114033,1.2874653085981584e-07,2.188666974535913e-08
|
||||
49,0.0001341788110461389,1.261309408287838e-07,2.164843935312404e-08
|
||||
50,0.00013188999957562474,1.2356710508422937e-07,2.1412624001807218e-08
|
||||
51,0.00012964156315983818,1.2105528052343852e-07,2.1179217737017218e-08
|
||||
52,0.00012743276140549773,1.1859439945261603e-07,2.0948187545405114e-08
|
||||
53,0.00012526286812817946,1.1618341661515935e-07,2.0719500766867955e-08
|
||||
54,0.00012308488924719652,1.1377852622228216e-07,2.0485476408751836e-08
|
||||
55,0.00012094599744462103,1.1142326262451022e-07,2.0253866505294597e-08
|
||||
56,0.00011884546514357594,1.0900764486089363e-07,2.0024636879854262e-08
|
||||
57,0.00011678359442245642,1.0664431621844869e-07,1.979776381558453e-08
|
||||
58,0.00011475963058254594,1.0433212166698539e-07,1.957321328901385e-08
|
||||
59,0.0001127728345582037,1.0206993253017356e-07,1.9350951640370864e-08
|
||||
60,0.00011082248211829082,9.98566454499784e-08,1.9130945525479478e-08
|
||||
61,0.00010890886205398466,9.769207746885406e-08,1.891318169113191e-08
|
||||
62,0.00010703122613605297,9.557511493642398e-08,1.869762647432104e-08
|
||||
63,0.00010518884252011888,9.350467086701759e-08,1.8484246571416752e-08
|
||||
64,0.0001035307857887024,9.161223068914851e-08,1.8300456694513304e-08
|
||||
65,0.00010190164256706024,8.97586650563189e-08,1.8118434361985188e-08
|
||||
66,0.00010030086086057541,8.79431393062173e-08,1.7938156675563083e-08
|
||||
67,9.872793827240711e-05,8.616487098950027e-08,1.77596013840066e-08
|
||||
68,9.718234354198392e-05,8.44230607070921e-08,1.7582746084973536e-08
|
||||
69,9.56635564008908e-05,8.271692715563019e-08,1.7407568625796667e-08
|
||||
70,9.417106698591262e-05,8.10457064001203e-08,1.7234047067791308e-08
|
||||
71,9.270483837325431e-05,7.94090478608544e-08,1.7062169097342785e-08
|
||||
72,9.12643590341385e-05,7.780619693716166e-08,1.6891912824320277e-08
|
||||
73,8.984912830909168e-05,7.623641652299821e-08,1.672325659984075e-08
|
||||
74,8.845966357642775e-05,7.469983729150625e-08,1.6557160644411184e-08
|
||||
75,8.709444598783118e-05,7.354697815082507e-08,1.6392702347411626e-08
|
||||
76,8.575300679829195e-05,7.241419869922277e-08,1.6229862344426664e-08
|
||||
77,8.443491979213314e-05,7.130113901851255e-08,1.606862190142917e-08
|
||||
78,8.313973419504378e-05,7.020741845194848e-08,1.5908962221377164e-08
|
||||
79,8.186700872392319e-05,6.913266435764513e-08,1.5750864795797952e-08
|
||||
80,8.061631115512539e-05,6.807651174398117e-08,1.559431138284531e-08
|
||||
81,7.938732282855929e-05,6.703869151817475e-08,1.5439286199449887e-08
|
||||
82,7.817962449101943e-05,6.601884964150396e-08,1.5285771474772338e-08
|
||||
83,7.699280573302815e-05,6.50166395433403e-08,1.513374972211717e-08
|
||||
84,7.592454893921724e-05,6.411454919552573e-08,1.5006080388275954e-08
|
||||
85,7.487353856336685e-05,6.322702259986013e-08,1.4879767295630751e-08
|
||||
86,7.383946010084118e-05,6.235379417263942e-08,1.475480276556073e-08
|
||||
87,7.282054160428152e-05,6.149336759142648e-08,1.4631164089327954e-08
|
||||
88,7.181654482227581e-05,6.064554166461607e-08,1.4508845066183491e-08
|
||||
89,7.082723551235707e-05,5.981011858595996e-08,1.4387839898262193e-08
|
||||
90,6.985238328334553e-05,5.8986903801432673e-08,1.4268143194153057e-08
|
||||
91,6.889088892692634e-05,5.8174969083648444e-08,1.4149731300144923e-08
|
||||
92,6.794256749705261e-05,5.737415825476245e-08,1.4032600405332526e-08
|
||||
93,6.700723666457587e-05,5.658431734677192e-08,1.3916747132522929e-08
|
||||
94,6.59402843027997e-05,5.5683328527685944e-08,1.3765832836854687e-08
|
||||
95,6.489024990134964e-05,5.479662609442341e-08,1.3616406761560667e-08
|
||||
|
@@ -1,97 +0,0 @@
|
||||
,signal,ase,nli
|
||||
0,0.0002869472910749756,3.829244288314411e-08,2.1570435023738975e-07
|
||||
1,0.0002844264441819097,3.810807396068084e-08,2.1799950841473497e-07
|
||||
2,0.00028192866252406385,3.792544000755193e-08,2.2023841125047751e-07
|
||||
3,0.0002794537215642667,3.7744517714620316e-08,2.2242189941355056e-07
|
||||
4,0.00027562432957345563,3.739256592350871e-08,2.2343448272115905e-07
|
||||
5,0.0002718482755003939,3.7044482870002475e-08,2.2437826192962336e-07
|
||||
6,0.00026812479793132313,3.670020704375223e-08,2.2525495466693408e-07
|
||||
7,0.000264450700138397,3.635954085714981e-08,2.2606415187873477e-07
|
||||
8,0.0002608253488030976,3.602242835595967e-08,2.2680748521505387e-07
|
||||
9,0.0002569046888856947,3.564392097524325e-08,2.2718285844823122e-07
|
||||
10,0.0002530414048172964,3.52696660940159e-08,2.2749429758474536e-07
|
||||
11,0.0002492279873569917,3.489974200864255e-08,2.277374766527899e-07
|
||||
12,0.00024546394589921574,3.453407358954537e-08,2.2791414400785136e-07
|
||||
13,0.00024174879169001578,3.4172586853993816e-08,2.280260208417818e-07
|
||||
14,0.00023798746912554602,3.3802283179520985e-08,2.2798420759778034e-07
|
||||
15,0.00023427697848580554,3.343627022987542e-08,2.2788101592695744e-07
|
||||
16,0.0002306167836320285,3.307447309241581e-08,2.2771816297650914e-07
|
||||
17,0.00022700656967539738,3.2716831574363364e-08,2.274975560288182e-07
|
||||
18,0.00022344579480967338,3.236327278261661e-08,2.2361822442592406e-07
|
||||
19,0.00021953361935365365,3.195819964288877e-08,2.1939761734541424e-07
|
||||
20,0.000215683131390894,3.155821693631402e-08,2.152494588710531e-07
|
||||
21,0.0002118936126056039,3.116322947665684e-08,2.1117277567387026e-07
|
||||
22,0.00020816423698459974,3.0773146233359933e-08,2.0716649124095414e-07
|
||||
23,0.000204494186708796,3.0387877710694614e-08,2.0322954179937734e-07
|
||||
24,0.0002011608152067422,3.0044038268833097e-08,1.9963693210325328e-07
|
||||
25,0.0001978756946189507,2.9704204306604607e-08,1.9610141536963302e-07
|
||||
26,0.00019463824873067792,2.9368307297032184e-08,1.9262221997374404e-07
|
||||
27,0.00019144860669288407,2.903632861769827e-08,1.8919927457566036e-07
|
||||
28,0.00018830616497929743,2.870820070744311e-08,1.8583178406705711e-07
|
||||
29,0.0001852103256336822,2.838385708911634e-08,1.8251896218718027e-07
|
||||
30,0.0001821604972098109,2.8063232252848876e-08,1.7926003240910756e-07
|
||||
31,0.00017915618670059162,2.774625963676283e-08,1.76054318231953e-07
|
||||
32,0.00017619680881745593,2.7432875871797347e-08,1.729010553429381e-07
|
||||
33,0.0001732817839023698,2.712301856538676e-08,1.6979948820365403e-07
|
||||
34,0.0001704966413678542,2.6828122477482957e-08,1.6683312331765736e-07
|
||||
35,0.00016775189226190024,2.6536528664560742e-08,1.639139770351803e-07
|
||||
36,0.00016504703499518105,2.624818226917535e-08,1.6104139135569604e-07
|
||||
37,0.00016238266779776653,2.5963117448579666e-08,1.5795381794641793e-07
|
||||
38,0.0001597582427278871,2.568127942199337e-08,1.5492098715709327e-07
|
||||
39,0.0001571732182027887,2.5402614261982925e-08,1.5194201541883415e-07
|
||||
40,0.00015462705891567335,2.5127068868391087e-08,1.4901603171959048e-07
|
||||
41,0.00015212101646395513,2.4854550603641668e-08,1.4614388817380648e-07
|
||||
42,0.00014965447757985992,2.4585009902449718e-08,1.4332463586635585e-07
|
||||
43,0.0001472268380950584,2.4318397887399997e-08,1.4055734193945962e-07
|
||||
44,0.0001447164668892332,2.4034551917480693e-08,1.377259000826997e-07
|
||||
45,0.00014224784112376056,2.3753930444781328e-08,1.3494914625940223e-07
|
||||
46,0.000139820283675003,2.3476479506890216e-08,1.3222606385781202e-07
|
||||
47,0.00013743418748444287,2.3202247900619965e-08,1.295566531341862e-07
|
||||
48,0.00013508884015386686,2.2931181973013504e-08,1.2693987096025158e-07
|
||||
49,0.00013278354172498307,2.2663228905058608e-08,1.2437469442130953e-07
|
||||
50,0.00013051760419724657,2.2398336706395863e-08,1.2186012017917007e-07
|
||||
51,0.00012829168984638487,2.2136423459712534e-08,1.1939640981689728e-07
|
||||
52,0.00012610506317956756,2.1877440279108582e-08,1.1698252030563078e-07
|
||||
53,0.00012395700285919374,2.1621338937233993e-08,1.1461743054419825e-07
|
||||
54,0.00012180241033650921,2.136015630373758e-08,1.1225922783040025e-07
|
||||
55,0.0001196865090578088,2.11019103466444e-08,1.0994951537260489e-07
|
||||
56,0.00011760857776205185,2.0846552296319304e-08,1.0757395097863843e-07
|
||||
57,0.00011556891128259512,2.0594154864038522e-08,1.0524972555992818e-07
|
||||
58,0.00011356676177304645,2.0344670536408355e-08,1.0297570549834491e-07
|
||||
59,0.00011160139690545148,2.009805268169949e-08,1.007507830554809e-07
|
||||
60,0.00010967209909252316,1.9854255584746143e-08,9.857387536569294e-08
|
||||
61,0.00010777915187088834,1.961321154131787e-08,9.644480679617587e-08
|
||||
62,0.00010592181397175025,1.9374877782865603e-08,9.43624842461164e-08
|
||||
63,0.00010409936038609485,1.913921236065976e-08,9.232584080120623e-08
|
||||
64,0.00010246447558376296,1.8936229484424864e-08,9.046927135292076e-08
|
||||
65,0.00010085803630103994,1.873544193319646e-08,8.865067925960422e-08
|
||||
66,9.927950010555374e-05,1.8536821682157304e-08,8.686925127148483e-08
|
||||
67,9.772837346090753e-05,1.834034757300294e-08,8.512422533827403e-08
|
||||
68,9.62041343011343e-05,1.8145993316507615e-08,8.341482250640209e-08
|
||||
69,9.470627135912848e-05,1.7953733512786736e-08,8.174028142913557e-08
|
||||
70,9.32342835979764e-05,1.776354374489084e-08,8.009985766376519e-08
|
||||
71,9.178813743816069e-05,1.757538990695628e-08,7.849321446941075e-08
|
||||
72,9.036733009485282e-05,1.7389250225057777e-08,7.691961625609573e-08
|
||||
73,8.897136946428169e-05,1.7205104136353174e-08,7.537834446343352e-08
|
||||
74,8.760740745801088e-05,1.7025340034280735e-08,7.38751341742058e-08
|
||||
75,8.626710469266231e-05,1.6847609082084475e-08,7.274492099364066e-08
|
||||
76,8.495000573672366e-05,1.6671897815367364e-08,7.16342744751107e-08
|
||||
77,8.365569697520734e-05,1.6498202874185357e-08,7.054284583689086e-08
|
||||
78,8.238374036673638e-05,1.6326516066391613e-08,6.94702656996508e-08
|
||||
79,8.11337070649851e-05,1.615683240442047e-08,6.84161724378069e-08
|
||||
80,7.990517700271111e-05,1.5989150837085435e-08,6.738021182875641e-08
|
||||
81,7.869784230919362e-05,1.5823472723367315e-08,6.63621242598539e-08
|
||||
82,7.751129541079501e-05,1.5659808141896922e-08,6.536156604375558e-08
|
||||
83,7.634513730458697e-05,1.5498175122781168e-08,6.437820072038669e-08
|
||||
84,7.530262080974513e-05,1.5364277079429572e-08,6.349909645089698e-08
|
||||
85,7.427675504203511e-05,1.523236493234819e-08,6.263403294276124e-08
|
||||
86,7.326723873728716e-05,1.510251249079146e-08,6.178275615432246e-08
|
||||
87,7.227232864620995e-05,1.4974078108462424e-08,6.094379608687809e-08
|
||||
88,7.1291797553153e-05,1.4847055996011248e-08,6.011696114034367e-08
|
||||
89,7.032542203609039e-05,1.4721440784517874e-08,5.930206291361685e-08
|
||||
90,6.937298231673965e-05,1.4597227547292096e-08,5.849891607818969e-08
|
||||
91,6.843339696762385e-05,1.447443282270653e-08,5.7706608718023645e-08
|
||||
92,6.750649045006057e-05,1.4353051811356354e-08,5.6924992809748396e-08
|
||||
93,6.65920896785063e-05,1.4233080214004659e-08,5.615392239860827e-08
|
||||
94,6.554258932109667e-05,1.407504972937325e-08,5.5268928972034444e-08
|
||||
95,6.450957734109368e-05,1.3918655180382722e-08,5.439783940506079e-08
|
||||
|
@@ -17,6 +17,7 @@ Transceiver trx_Stockholm
|
||||
Roadm roadm_Stockholm
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -29,6 +30,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: SSMF
|
||||
@@ -37,7 +39,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
|
||||
total loss (dB): 16.33
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.33
|
||||
pch out (dBm): -14.33
|
||||
total pch (dBm): -14.31
|
||||
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: openroadm_ila_low_noise
|
||||
effective gain(dB): 16.33
|
||||
@@ -50,6 +53,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Stockholm → Norrköping)_(2/2)
|
||||
type_variety: SSMF
|
||||
@@ -58,7 +62,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
|
||||
total loss (dB): 16.33
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.33
|
||||
pch out (dBm): -14.33
|
||||
total pch (dBm): -14.30
|
||||
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
|
||||
type_variety: openroadm_mw_mw_preamp
|
||||
effective gain(dB): 16.33
|
||||
@@ -71,10 +76,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.04
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Norrköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -87,6 +94,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Norrköping → Linköping)
|
||||
type_variety: SSMF
|
||||
@@ -95,7 +103,8 @@ Fiber fiber (Norrköping → Linköping)
|
||||
total loss (dB): 11.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -9.00
|
||||
pch out (dBm): -9.00
|
||||
total pch (dBm): -9.00
|
||||
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
|
||||
type_variety: openroadm_mw_mw_preamp
|
||||
effective gain(dB): 11.00
|
||||
@@ -108,10 +117,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.01
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Linköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -124,6 +135,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Linköping → Jönköping)
|
||||
type_variety: SSMF
|
||||
@@ -132,7 +144,8 @@ Fiber fiber (Linköping → Jönköping)
|
||||
total loss (dB): 26.80
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -24.80
|
||||
pch out (dBm): -24.80
|
||||
total pch (dBm): -24.79
|
||||
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
|
||||
type_variety: openroadm_mw_mw_preamp
|
||||
effective gain(dB): 26.80
|
||||
@@ -145,10 +158,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.04
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Jönköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -161,6 +176,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Jönköping → Borås)
|
||||
type_variety: SSMF
|
||||
@@ -169,7 +185,8 @@ Fiber fiber (Jönköping → Borås)
|
||||
total loss (dB): 17.82
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -15.82
|
||||
pch out (dBm): -15.82
|
||||
total pch (dBm): -15.81
|
||||
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
|
||||
type_variety: openroadm_mw_mw_preamp
|
||||
effective gain(dB): 17.82
|
||||
@@ -182,10 +199,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.02
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Borås
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -198,6 +217,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Borås → Gothenburg)
|
||||
type_variety: SSMF
|
||||
@@ -206,7 +226,8 @@ Fiber fiber (Borås → Gothenburg)
|
||||
total loss (dB): 13.53
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -11.53
|
||||
pch out (dBm): -11.53
|
||||
total pch (dBm): -11.52
|
||||
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
|
||||
type_variety: openroadm_mw_mw_preamp
|
||||
effective gain(dB): 13.53
|
||||
@@ -219,10 +240,12 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.02
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Gothenburg
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Transceiver trx_Gothenburg
|
||||
GSNR (0.1nm, dB): 18.90
|
||||
GSNR (signal bw, dB): 14.88
|
||||
|
||||
@@ -17,6 +17,7 @@ Transceiver trx_Stockholm
|
||||
Roadm roadm_Stockholm
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -29,6 +30,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: SSMF
|
||||
@@ -37,7 +39,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
|
||||
total loss (dB): 16.33
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.33
|
||||
pch out (dBm): -14.33
|
||||
total pch (dBm): -14.31
|
||||
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
|
||||
type_variety: openroadm_ila_low_noise
|
||||
effective gain(dB): 16.33
|
||||
@@ -50,6 +53,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Stockholm → Norrköping)_(2/2)
|
||||
type_variety: SSMF
|
||||
@@ -58,7 +62,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
|
||||
total loss (dB): 16.33
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.33
|
||||
pch out (dBm): -14.33
|
||||
total pch (dBm): -14.30
|
||||
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
|
||||
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||
effective gain(dB): 16.33
|
||||
@@ -71,10 +76,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.04
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Norrköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -87,6 +94,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Norrköping → Linköping)
|
||||
type_variety: SSMF
|
||||
@@ -95,7 +103,8 @@ Fiber fiber (Norrköping → Linköping)
|
||||
total loss (dB): 11.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -9.00
|
||||
pch out (dBm): -9.00
|
||||
total pch (dBm): -9.00
|
||||
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
|
||||
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||
effective gain(dB): 11.00
|
||||
@@ -108,10 +117,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.01
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Linköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -124,6 +135,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Linköping → Jönköping)
|
||||
type_variety: SSMF
|
||||
@@ -132,7 +144,8 @@ Fiber fiber (Linköping → Jönköping)
|
||||
total loss (dB): 26.80
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -24.80
|
||||
pch out (dBm): -24.80
|
||||
total pch (dBm): -24.79
|
||||
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
|
||||
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||
effective gain(dB): 26.80
|
||||
@@ -145,10 +158,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.04
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Jönköping
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -161,6 +176,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Jönköping → Borås)
|
||||
type_variety: SSMF
|
||||
@@ -169,7 +185,8 @@ Fiber fiber (Jönköping → Borås)
|
||||
total loss (dB): 17.82
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -15.82
|
||||
pch out (dBm): -15.82
|
||||
total pch (dBm): -15.81
|
||||
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
|
||||
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||
effective gain(dB): 17.82
|
||||
@@ -182,10 +199,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.01
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Borås
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
|
||||
type_variety: openroadm_mw_mw_booster
|
||||
effective gain(dB): 22.00
|
||||
@@ -198,6 +217,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.00
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Borås → Gothenburg)
|
||||
type_variety: SSMF
|
||||
@@ -206,7 +226,8 @@ Fiber fiber (Borås → Gothenburg)
|
||||
total loss (dB): 13.53
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -11.53
|
||||
pch out (dBm): -11.53
|
||||
total pch (dBm): -11.52
|
||||
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
|
||||
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||
effective gain(dB): 13.53
|
||||
@@ -219,12 +240,14 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 2.00
|
||||
effective pch (dBm): 2.00
|
||||
total pch (dBm): 2.02
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm_Gothenburg
|
||||
effective loss (dB): 22.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Transceiver trx_Gothenburg
|
||||
GSNR (0.1nm, dB): 19.27
|
||||
GSNR (0.1nm, dB): 19.26
|
||||
GSNR (signal bw, dB): 15.24
|
||||
OSNR ASE (0.1nm, dB): 21.84
|
||||
OSNR ASE (signal bw, dB): 17.82
|
||||
@@ -232,7 +255,7 @@ Transceiver trx_Gothenburg
|
||||
PMD (ps): 0.89
|
||||
|
||||
Transmission result for input power = 2.00 dBm:
|
||||
Final GSNR (0.1 nm): [1;36;40m19.27 dB[0m
|
||||
Final GSNR (0.1 nm): [1;36;40m19.26 dB[0m
|
||||
|
||||
(No source node specified: picked trx_Stockholm)
|
||||
|
||||
|
||||
98
tests/invocation/spectrum1_transmission_main_example
Normal file
98
tests/invocation/spectrum1_transmission_main_example
Normal file
@@ -0,0 +1,98 @@
|
||||
warning: user input for spectrum used for propagation instead of SI
|
||||
There are 96 channels propagating
|
||||
Power mode is set to True
|
||||
=> it can be modified in eqpt_config.json - Span
|
||||
|
||||
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
|
||||
|
||||
Now propagating between trx Lannion_CAS and trx Lorient_KMA:
|
||||
|
||||
Propagating with input power = [1;36;40m0.00 dBm[0m:
|
||||
Transceiver trx Lannion_CAS
|
||||
GSNR (0.1nm, dB): 40.00
|
||||
GSNR (signal bw, dB): 35.92
|
||||
OSNR ASE (0.1nm, dB): 40.00
|
||||
OSNR ASE (signal bw, dB): 35.92
|
||||
CD (ps/nm): 0.00
|
||||
PMD (ps): 0.00
|
||||
Roadm roadm Lannion_CAS
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa east edfa in Lannion_CAS to Corlay
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 21.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.36
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -0.18
|
||||
Power Out (dBm): 20.83
|
||||
Delta_P (dB): 1.00
|
||||
target pch (dBm): 1.00
|
||||
effective pch (dBm): 1.00
|
||||
total pch (dBm): 1.01
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Lannion_CAS → Corlay)-F061
|
||||
type_variety: SSMF
|
||||
length (km): 20.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 4.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -3.00
|
||||
total pch (dBm): -2.99
|
||||
Fused west fused spans in Corlay
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Corlay → Loudeac)-F010
|
||||
type_variety: SSMF
|
||||
length (km): 50.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 10.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.00
|
||||
total pch (dBm): -13.99
|
||||
Fused west fused spans in Loudeac
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Loudeac → Lorient_KMA)-F054
|
||||
type_variety: SSMF
|
||||
length (km): 60.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 12.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -27.00
|
||||
total pch (dBm): -26.99
|
||||
Edfa west edfa in Lorient_KMA to Loudeac
|
||||
type_variety: std_high_gain
|
||||
effective gain(dB): 28.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 5.92
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -7.17
|
||||
Power Out (dBm): 20.87
|
||||
Delta_P (dB): 1.00
|
||||
target pch (dBm): 1.00
|
||||
effective pch (dBm): 1.00
|
||||
total pch (dBm): 1.05
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Lorient_KMA
|
||||
effective loss (dB): 21.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Transceiver trx Lorient_KMA
|
||||
GSNR (0.1nm, dB): 23.58
|
||||
GSNR (signal bw, dB): 19.50
|
||||
OSNR ASE (0.1nm, dB): 23.88
|
||||
OSNR ASE (signal bw, dB): 19.80
|
||||
CD (ps/nm): 2171.00
|
||||
PMD (ps): 0.46
|
||||
|
||||
Transmission result for input power = 0.00 dBm:
|
||||
Final GSNR (0.1 nm): [1;36;40m23.58 dB[0m
|
||||
|
||||
(No source node specified: picked trx Lannion_CAS)
|
||||
|
||||
(No destination node specified: picked trx Lorient_KMA)
|
||||
98
tests/invocation/spectrum2_transmission_main_example
Normal file
98
tests/invocation/spectrum2_transmission_main_example
Normal file
@@ -0,0 +1,98 @@
|
||||
warning: user input for spectrum used for propagation instead of SI
|
||||
There are 60 channels propagating
|
||||
Power mode is set to True
|
||||
=> it can be modified in eqpt_config.json - Span
|
||||
|
||||
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
|
||||
|
||||
Now propagating between trx Lannion_CAS and trx Lorient_KMA:
|
||||
|
||||
Propagating with input power = [1;36;40m0.00 dBm[0m:
|
||||
Transceiver trx Lannion_CAS
|
||||
GSNR (0.1nm, dB): 0-32.0: 40.00, 1-64.0: 40.00,
|
||||
GSNR (signal bw, dB): 0-32.0: 35.92, 1-64.0: 32.91,
|
||||
OSNR ASE (0.1nm, dB): 0-32.0: 40.00, 1-64.0: 40.00,
|
||||
OSNR ASE (signal bw, dB): 0-32.0: 35.92, 1-64.0: 32.91,
|
||||
CD (ps/nm): 0.00
|
||||
PMD (ps): 0.00
|
||||
Roadm roadm Lannion_CAS
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): 0-32.0: -20.00, 1-64.0: -20.00,
|
||||
Edfa east edfa in Lannion_CAS to Corlay
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 21.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.36
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -2.22
|
||||
Power Out (dBm): 18.79
|
||||
Delta_P (dB): 1.00
|
||||
target pch (dBm): 1.00
|
||||
effective pch (dBm): 1.00
|
||||
total pch (dBm): 0-32.0: 1.01, 1-64.0: 1.02,
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Lannion_CAS → Corlay)-F061
|
||||
type_variety: SSMF
|
||||
length (km): 20.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 4.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -3.00
|
||||
total pch (dBm): 0-32.0: -2.99, 1-64.0: -2.98,
|
||||
Fused west fused spans in Corlay
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Corlay → Loudeac)-F010
|
||||
type_variety: SSMF
|
||||
length (km): 50.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 10.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -14.00
|
||||
total pch (dBm): 0-32.0: -13.99, 1-64.0: -13.98,
|
||||
Fused west fused spans in Loudeac
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Loudeac → Lorient_KMA)-F054
|
||||
type_variety: SSMF
|
||||
length (km): 60.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 12.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -27.00
|
||||
total pch (dBm): 0-32.0: -26.99, 1-64.0: -26.98,
|
||||
Edfa west edfa in Lorient_KMA to Loudeac
|
||||
type_variety: std_high_gain
|
||||
effective gain(dB): 28.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 5.92
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -9.21
|
||||
Power Out (dBm): 18.84
|
||||
Delta_P (dB): 1.00
|
||||
target pch (dBm): 1.00
|
||||
effective pch (dBm): 1.00
|
||||
total pch (dBm): 0-32.0: 1.04, 1-64.0: 1.09,
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Lorient_KMA
|
||||
effective loss (dB): 21.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): 0-32.0: -20.00, 1-64.0: -20.00,
|
||||
Transceiver trx Lorient_KMA
|
||||
GSNR (0.1nm, dB): 0-32.0: 23.66, 1-64.0: 23.81,
|
||||
GSNR (signal bw, dB): 0-32.0: 19.57, 1-64.0: 16.72,
|
||||
OSNR ASE (0.1nm, dB): 0-32.0: 23.91, 1-64.0: 23.87,
|
||||
OSNR ASE (signal bw, dB): 0-32.0: 19.83, 1-64.0: 16.78,
|
||||
CD (ps/nm): 2171.00
|
||||
PMD (ps): 0.46
|
||||
|
||||
Transmission result for input power = 0.00 dBm:
|
||||
Final GSNR (0.1 nm): [1;36;40m23.72 dB[0m
|
||||
|
||||
(No source node specified: picked trx Lannion_CAS)
|
||||
|
||||
(No destination node specified: picked trx Lorient_KMA)
|
||||
@@ -21,7 +21,8 @@ Fiber Span1
|
||||
total loss (dB): 17.00
|
||||
(includes conn loss (dB) in: 0.50 out: 0.50)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -17.00
|
||||
pch out (dBm): -17.00
|
||||
total pch (dBm): -17.00
|
||||
Edfa Edfa1
|
||||
type_variety: std_low_gain
|
||||
effective gain(dB): 15.00
|
||||
@@ -34,6 +35,7 @@ Edfa Edfa1
|
||||
Delta_P (dB): -2.00
|
||||
target pch (dBm): -2.00
|
||||
effective pch (dBm): -2.00
|
||||
total pch (dBm): -1.99
|
||||
output VOA (dB): 0.00
|
||||
Transceiver Site_B
|
||||
GSNR (0.1nm, dB): 31.17
|
||||
|
||||
@@ -21,109 +21,111 @@ RamanFiber Span1
|
||||
total loss (dB): 17.00
|
||||
(includes conn loss (dB) in: 0.50 out: 0.50)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -7.74
|
||||
pch out (dBm): -7.71
|
||||
total pch (dBm): -7.96
|
||||
Edfa Edfa1
|
||||
type_variety: std_low_gain
|
||||
effective gain(dB): 5.74
|
||||
effective gain(dB): 5.71
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 13.26
|
||||
noise figure (dB): 13.29
|
||||
(including att_in)
|
||||
pad att_in (dB): 2.26
|
||||
Power In (dBm): 11.07
|
||||
pad att_in (dB): 2.29
|
||||
Power In (dBm): 11.11
|
||||
Power Out (dBm): 16.82
|
||||
Delta_P (dB): -2.00
|
||||
target pch (dBm): -2.00
|
||||
effective pch (dBm): -2.00
|
||||
total pch (dBm): -2.25
|
||||
output VOA (dB): 0.00
|
||||
Transceiver Site_B
|
||||
GSNR (0.1nm, dB): 31.43
|
||||
GSNR (signal bw, dB): 27.35
|
||||
OSNR ASE (0.1nm, dB): 34.18
|
||||
OSNR ASE (signal bw, dB): 30.10
|
||||
GSNR (0.1nm, dB): 31.44
|
||||
GSNR (signal bw, dB): 27.36
|
||||
OSNR ASE (0.1nm, dB): 34.22
|
||||
OSNR ASE (signal bw, dB): 30.14
|
||||
CD (ps/nm): 1336.00
|
||||
PMD (ps): 0.36
|
||||
|
||||
Transmission result for input power = 0.00 dBm:
|
||||
Final GSNR (0.1 nm): [1;36;40m31.43 dB[0m
|
||||
Final GSNR (0.1 nm): [1;36;40m31.44 dB[0m
|
||||
|
||||
The GSNR per channel at the end of the line is:
|
||||
Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB)
|
||||
1 191.35 0.21 31.56 31.47 28.50
|
||||
2 191.40 0.17 31.54 31.38 28.45
|
||||
3 191.45 0.14 31.52 31.30 28.40
|
||||
4 191.50 0.10 31.50 31.22 28.34
|
||||
5 191.55 0.04 31.47 31.14 28.29
|
||||
6 191.60 -0.02 31.44 31.06 28.23
|
||||
7 191.65 -0.08 31.41 30.98 28.18
|
||||
8 191.70 -0.14 31.37 30.90 28.12
|
||||
9 191.75 -0.20 31.34 30.83 28.07
|
||||
10 191.80 -0.26 31.31 30.75 28.01
|
||||
11 191.85 -0.33 31.27 30.68 27.96
|
||||
12 191.90 -0.39 31.24 30.61 27.90
|
||||
13 191.95 -0.46 31.20 30.54 27.85
|
||||
14 192.00 -0.52 31.17 30.47 27.79
|
||||
15 192.05 -0.59 31.13 30.40 27.74
|
||||
16 192.10 -0.66 31.10 30.33 27.69
|
||||
17 192.15 -0.72 31.06 30.26 27.63
|
||||
18 192.20 -0.79 31.02 30.20 27.58
|
||||
19 192.25 -0.86 30.98 30.21 27.57
|
||||
20 192.30 -0.94 30.94 30.21 27.55
|
||||
21 192.35 -1.01 30.90 30.22 27.54
|
||||
22 192.40 -1.09 30.86 30.23 27.52
|
||||
23 192.45 -1.16 30.81 30.23 27.50
|
||||
24 192.50 -1.24 30.77 30.24 27.49
|
||||
25 192.55 -1.31 30.73 30.25 27.47
|
||||
26 192.60 -1.38 30.69 30.25 27.46
|
||||
27 192.65 -1.45 30.65 30.26 27.44
|
||||
28 192.70 -1.52 30.61 30.27 27.42
|
||||
29 192.75 -1.59 30.56 30.28 27.41
|
||||
30 192.80 -1.66 30.52 30.28 27.39
|
||||
31 192.85 -1.73 30.48 30.29 27.37
|
||||
32 192.90 -1.80 30.44 30.30 27.36
|
||||
33 192.95 -1.87 30.39 30.30 27.34
|
||||
34 193.00 -1.94 30.35 30.31 27.32
|
||||
35 193.05 -2.01 30.31 30.32 27.30
|
||||
36 193.10 -2.08 30.27 30.33 27.29
|
||||
37 193.15 -2.15 30.22 30.33 27.27
|
||||
38 193.20 -2.22 30.18 30.35 27.25
|
||||
39 193.25 -2.29 30.14 30.37 27.24
|
||||
40 193.30 -2.36 30.09 30.39 27.23
|
||||
41 193.35 -2.43 30.05 30.40 27.21
|
||||
42 193.40 -2.49 30.01 30.42 27.20
|
||||
43 193.45 -2.56 29.96 30.44 27.18
|
||||
44 193.50 -2.63 29.92 30.46 27.17
|
||||
45 193.55 -2.70 29.87 30.47 27.15
|
||||
46 193.60 -2.78 29.83 30.49 27.13
|
||||
47 193.65 -2.85 29.78 30.51 27.12
|
||||
48 193.70 -2.92 29.73 30.53 27.10
|
||||
49 193.75 -2.99 29.68 30.54 27.08
|
||||
50 193.80 -3.06 29.64 30.56 27.06
|
||||
51 193.85 -3.14 29.59 30.58 27.05
|
||||
52 193.90 -3.21 29.54 30.60 27.03
|
||||
53 193.95 -3.28 29.49 30.62 27.01
|
||||
54 194.00 -3.35 29.44 30.64 26.99
|
||||
55 194.05 -3.42 29.39 30.65 26.97
|
||||
56 194.10 -3.50 29.34 30.67 26.95
|
||||
57 194.15 -3.57 29.29 30.73 26.94
|
||||
58 194.20 -3.64 29.24 30.79 26.94
|
||||
59 194.25 -3.72 29.19 30.85 26.93
|
||||
60 194.30 -3.79 29.14 30.91 26.93
|
||||
61 194.35 -3.86 29.09 30.97 26.92
|
||||
62 194.40 -3.93 29.04 31.03 26.91
|
||||
63 194.45 -4.01 28.99 31.09 26.90
|
||||
64 194.50 -4.08 28.94 31.15 26.90
|
||||
65 194.55 -4.14 28.89 31.22 26.89
|
||||
66 194.60 -4.21 28.85 31.28 26.88
|
||||
67 194.65 -4.28 28.80 31.35 26.88
|
||||
68 194.70 -4.34 28.75 31.41 26.87
|
||||
69 194.75 -4.41 28.70 31.48 26.86
|
||||
70 194.80 -4.47 28.66 31.55 26.86
|
||||
71 194.85 -4.54 28.61 31.62 26.85
|
||||
72 194.90 -4.60 28.56 31.69 26.84
|
||||
73 194.95 -4.67 28.51 31.77 26.83
|
||||
74 195.00 -4.73 28.47 31.84 26.82
|
||||
75 195.05 -4.80 28.42 31.91 26.81
|
||||
76 195.10 -4.86 28.37 31.91 26.78
|
||||
1 191.35000 0.18 31.61 31.42 28.51
|
||||
2 191.40000 0.14 31.59 31.34 28.45
|
||||
3 191.45000 0.11 31.57 31.25 28.40
|
||||
4 191.50000 0.07 31.55 31.17 28.35
|
||||
5 191.55000 0.02 31.52 31.09 28.29
|
||||
6 191.60000 -0.04 31.49 31.01 28.23
|
||||
7 191.65000 -0.10 31.46 30.93 28.18
|
||||
8 191.70000 -0.16 31.43 30.86 28.12
|
||||
9 191.75000 -0.21 31.40 30.78 28.07
|
||||
10 191.80000 -0.28 31.36 30.71 28.01
|
||||
11 191.85000 -0.34 31.33 30.64 27.96
|
||||
12 191.90000 -0.40 31.29 30.56 27.90
|
||||
13 191.95000 -0.47 31.26 30.49 27.85
|
||||
14 192.00000 -0.53 31.22 30.43 27.80
|
||||
15 192.05000 -0.60 31.18 30.36 27.74
|
||||
16 192.10000 -0.66 31.15 30.29 27.69
|
||||
17 192.15000 -0.73 31.11 30.23 27.64
|
||||
18 192.20000 -0.79 31.07 30.16 27.58
|
||||
19 192.25000 -0.86 31.04 30.17 27.57
|
||||
20 192.30000 -0.94 30.99 30.18 27.55
|
||||
21 192.35000 -1.01 30.95 30.18 27.54
|
||||
22 192.40000 -1.08 30.91 30.19 27.52
|
||||
23 192.45000 -1.16 30.86 30.20 27.51
|
||||
24 192.50000 -1.23 30.82 30.21 27.49
|
||||
25 192.55000 -1.30 30.78 30.21 27.48
|
||||
26 192.60000 -1.37 30.74 30.22 27.46
|
||||
27 192.65000 -1.44 30.70 30.23 27.45
|
||||
28 192.70000 -1.51 30.65 30.24 27.43
|
||||
29 192.75000 -1.58 30.61 30.25 27.41
|
||||
30 192.80000 -1.65 30.57 30.25 27.40
|
||||
31 192.85000 -1.72 30.53 30.26 27.38
|
||||
32 192.90000 -1.79 30.48 30.27 27.36
|
||||
33 192.95000 -1.86 30.44 30.28 27.35
|
||||
34 193.00000 -1.93 30.40 30.28 27.33
|
||||
35 193.05000 -2.00 30.35 30.29 27.31
|
||||
36 193.10000 -2.07 30.31 30.30 27.30
|
||||
37 193.15000 -2.14 30.27 30.31 27.28
|
||||
38 193.20000 -2.20 30.22 30.33 27.26
|
||||
39 193.25000 -2.27 30.18 30.34 27.25
|
||||
40 193.30000 -2.34 30.14 30.36 27.24
|
||||
41 193.35000 -2.41 30.09 30.38 27.22
|
||||
42 193.40000 -2.48 30.05 30.40 27.21
|
||||
43 193.45000 -2.55 30.00 30.41 27.19
|
||||
44 193.50000 -2.61 29.96 30.43 27.18
|
||||
45 193.55000 -2.69 29.91 30.45 27.16
|
||||
46 193.60000 -2.76 29.86 30.47 27.15
|
||||
47 193.65000 -2.83 29.82 30.49 27.13
|
||||
48 193.70000 -2.90 29.77 30.51 27.11
|
||||
49 193.75000 -2.98 29.72 30.52 27.09
|
||||
50 193.80000 -3.05 29.67 30.54 27.08
|
||||
51 193.85000 -3.12 29.62 30.56 27.06
|
||||
52 193.90000 -3.19 29.58 30.58 27.04
|
||||
53 193.95000 -3.26 29.53 30.60 27.02
|
||||
54 194.00000 -3.33 29.48 30.62 27.00
|
||||
55 194.05000 -3.41 29.43 30.64 26.98
|
||||
56 194.10000 -3.48 29.38 30.66 26.96
|
||||
57 194.15000 -3.55 29.33 30.71 26.96
|
||||
58 194.20000 -3.63 29.28 30.77 26.95
|
||||
59 194.25000 -3.70 29.23 30.83 26.94
|
||||
60 194.30000 -3.77 29.18 30.89 26.94
|
||||
61 194.35000 -3.85 29.12 30.95 26.93
|
||||
62 194.40000 -3.92 29.07 31.01 26.92
|
||||
63 194.45000 -3.99 29.02 31.07 26.92
|
||||
64 194.50000 -4.06 28.97 31.14 26.91
|
||||
65 194.55000 -4.13 28.92 31.20 26.90
|
||||
66 194.60000 -4.19 28.88 31.27 26.90
|
||||
67 194.65000 -4.26 28.83 31.33 26.89
|
||||
68 194.70000 -4.33 28.78 31.40 26.89
|
||||
69 194.75000 -4.39 28.73 31.47 26.88
|
||||
70 194.80000 -4.46 28.68 31.54 26.87
|
||||
71 194.85000 -4.52 28.64 31.61 26.86
|
||||
72 194.90000 -4.59 28.59 31.68 26.85
|
||||
73 194.95000 -4.65 28.54 31.75 26.85
|
||||
74 195.00000 -4.72 28.49 31.83 26.84
|
||||
75 195.05000 -4.78 28.44 31.90 26.83
|
||||
76 195.10000 -4.85 28.39 31.90 26.79
|
||||
|
||||
(No source node specified: picked Site_A)
|
||||
|
||||
|
||||
451
tests/invocation/transmission_main_example_long
Normal file
451
tests/invocation/transmission_main_example_long
Normal file
@@ -0,0 +1,451 @@
|
||||
There are 96 channels propagating
|
||||
Power mode is set to True
|
||||
=> it can be modified in eqpt_config.json - Span
|
||||
|
||||
There are 15 fiber spans over 1200 km between Site_A and Site_B
|
||||
|
||||
Now propagating between Site_A and Site_B:
|
||||
|
||||
Propagating with input power = [1;36;40m0.00 dBm[0m:
|
||||
Transceiver Site_A
|
||||
GSNR (0.1nm, dB): 100.00
|
||||
GSNR (signal bw, dB): 95.92
|
||||
OSNR ASE (0.1nm, dB): 100.00
|
||||
OSNR ASE (signal bw, dB): 95.92
|
||||
CD (ps/nm): 0.00
|
||||
PMD (ps): 0.00
|
||||
Roadm roadm Site A
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa booster A
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 20.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.58
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -0.18
|
||||
Power Out (dBm): 19.83
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.01
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span1
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.99
|
||||
Edfa Edfa1
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.84
|
||||
Power Out (dBm): 19.84
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span2
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.98
|
||||
Edfa Edfa2
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.84
|
||||
Power Out (dBm): 19.85
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.03
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span3
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.97
|
||||
Edfa Edfa3
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.85
|
||||
Power Out (dBm): 19.86
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.04
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span4
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.96
|
||||
Edfa Edfa4
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.86
|
||||
Power Out (dBm): 19.87
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.05
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span5
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.95
|
||||
Edfa Edfa5
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.87
|
||||
Power Out (dBm): 19.88
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.06
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Site C
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa booster C
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 20.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.58
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -0.18
|
||||
Power Out (dBm): 19.83
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.01
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span6
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.99
|
||||
Edfa Edfa6
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.83
|
||||
Power Out (dBm): 19.84
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span7
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.98
|
||||
Edfa Edfa7
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.84
|
||||
Power Out (dBm): 19.85
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.03
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span8
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.97
|
||||
Edfa Edfa8
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.85
|
||||
Power Out (dBm): 19.86
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.04
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span9
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.96
|
||||
Edfa Edfa9
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.86
|
||||
Power Out (dBm): 19.87
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.05
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span10
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.95
|
||||
Edfa Edfa10
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.87
|
||||
Power Out (dBm): 19.88
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.06
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Site D
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa booster D
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 20.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.58
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -0.18
|
||||
Power Out (dBm): 19.83
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.01
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span11
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.99
|
||||
Edfa Edfa11
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.83
|
||||
Power Out (dBm): 19.84
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span12
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.98
|
||||
Edfa Edfa12
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.84
|
||||
Power Out (dBm): 19.85
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.03
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Site E
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa booster E
|
||||
type_variety: std_medium_gain
|
||||
effective gain(dB): 20.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 6.58
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): -0.18
|
||||
Power Out (dBm): 19.83
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.01
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span13
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.99
|
||||
Edfa Edfa13
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.83
|
||||
Power Out (dBm): 19.84
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.02
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span14
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.98
|
||||
Edfa Edfa14
|
||||
type_variety: test_fixed_gain
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 9.00
|
||||
(including att_in)
|
||||
pad att_in (dB): 4.00
|
||||
Power In (dBm): 3.84
|
||||
Power Out (dBm): 19.85
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.03
|
||||
output VOA (dB): 0.00
|
||||
Fiber Span15
|
||||
type_variety: SSMF
|
||||
length (km): 80.00
|
||||
pad att_in (dB): 0.00
|
||||
total loss (dB): 16.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -16.00
|
||||
total pch (dBm): -15.97
|
||||
Edfa Edfa15
|
||||
type_variety: test
|
||||
effective gain(dB): 16.00
|
||||
(before att_in and before output VOA)
|
||||
noise figure (dB): 8.86
|
||||
(including att_in)
|
||||
pad att_in (dB): 0.00
|
||||
Power In (dBm): 3.85
|
||||
Power Out (dBm): 19.86
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 0.00
|
||||
effective pch (dBm): 0.00
|
||||
total pch (dBm): 0.04
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Site B
|
||||
effective loss (dB): 20.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Transceiver Site_B
|
||||
GSNR (0.1nm, dB): 17.85
|
||||
GSNR (signal bw, dB): 13.77
|
||||
OSNR ASE (0.1nm, dB): 19.70
|
||||
OSNR ASE (signal bw, dB): 15.62
|
||||
CD (ps/nm): 20040.00
|
||||
PMD (ps): 1.39
|
||||
|
||||
Transmission result for input power = 0.00 dBm:
|
||||
Final GSNR (0.1 nm): [1;36;40m17.85 dB[0m
|
||||
|
||||
(No source node specified: picked Site_A)
|
||||
|
||||
(No destination node specified: picked Site_B)
|
||||
@@ -253,6 +253,7 @@ Transceiver trx Lannion_CAS
|
||||
Roadm roadm Lannion_CAS
|
||||
effective loss (dB): 23.00
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Edfa east edfa in Lannion_CAS to Corlay
|
||||
type_variety: test
|
||||
effective gain(dB): 21.18
|
||||
@@ -265,6 +266,7 @@ Edfa east edfa in Lannion_CAS to Corlay
|
||||
Delta_P (dB): 0.00
|
||||
target pch (dBm): 3.00
|
||||
effective pch (dBm): 1.18
|
||||
total pch (dBm): 1.18
|
||||
output VOA (dB): 0.00
|
||||
Fiber fiber (Lannion_CAS → Corlay)-F061
|
||||
type_variety: SSMF
|
||||
@@ -273,7 +275,8 @@ Fiber fiber (Lannion_CAS → Corlay)-F061
|
||||
total loss (dB): 4.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -2.82
|
||||
pch out (dBm): -2.82
|
||||
total pch (dBm): -2.81
|
||||
Fused west fused spans in Corlay
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Corlay → Loudeac)-F010
|
||||
@@ -283,7 +286,8 @@ Fiber fiber (Corlay → Loudeac)-F010
|
||||
total loss (dB): 10.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -13.82
|
||||
pch out (dBm): -13.82
|
||||
total pch (dBm): -13.81
|
||||
Fused west fused spans in Loudeac
|
||||
loss (dB): 1.00
|
||||
Fiber fiber (Loudeac → Lorient_KMA)-F054
|
||||
@@ -293,7 +297,8 @@ Fiber fiber (Loudeac → Lorient_KMA)-F054
|
||||
total loss (dB): 12.00
|
||||
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||
pch out (dBm): -26.82
|
||||
pch out (dBm): -26.82
|
||||
total pch (dBm): -26.81
|
||||
Edfa west edfa in Lorient_KMA to Loudeac
|
||||
type_variety: test
|
||||
effective gain(dB): 28.00
|
||||
@@ -306,10 +311,12 @@ Edfa west edfa in Lorient_KMA to Loudeac
|
||||
Delta_P (dB): -1.82
|
||||
target pch (dBm): 1.18
|
||||
effective pch (dBm): 1.18
|
||||
total pch (dBm): 1.22
|
||||
output VOA (dB): 0.00
|
||||
Roadm roadm Lorient_KMA
|
||||
effective loss (dB): 21.18
|
||||
pch out (dBm): -20.00
|
||||
total pch (dBm): -20.00
|
||||
Transceiver trx Lorient_KMA
|
||||
GSNR (0.1nm, dB): 23.94
|
||||
GSNR (signal bw, dB): 19.85
|
||||
|
||||
@@ -80,13 +80,12 @@ def si(nch_and_spacing, bw):
|
||||
def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
||||
"""=> unitary test for variable gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
||||
edfa = setup_edfa_variable_gain
|
||||
frequencies = array([c.frequency for c in si.carriers])
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
pin = pin / db2lin(gain)
|
||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
||||
si.signal /=db2lin(gain)
|
||||
si.nli /= db2lin(gain)
|
||||
si.ase /= db2lin(gain)
|
||||
edfa.operational.gain_target = gain
|
||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
||||
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
|
||||
edfa.interpol_params(si)
|
||||
result = edfa.nf
|
||||
assert pytest.approx(nf_expected, abs=0.01) == result[0]
|
||||
|
||||
@@ -95,23 +94,20 @@ def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
||||
def test_fixed_gain_nf(gain, nf_expected, setup_edfa_fixed_gain, si):
|
||||
"""=> unitary test for fixed gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
||||
edfa = setup_edfa_fixed_gain
|
||||
frequencies = array([c.frequency for c in si.carriers])
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
pin = pin / db2lin(gain)
|
||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
||||
si.signal /= db2lin(gain)
|
||||
si.nli /= db2lin(gain)
|
||||
si.ase /= db2lin(gain)
|
||||
edfa.operational.gain_target = gain
|
||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
||||
|
||||
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
|
||||
edfa.interpol_params(si)
|
||||
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
|
||||
|
||||
|
||||
def test_si(si, nch_and_spacing):
|
||||
"""basic total power check of the channel comb generation"""
|
||||
nb_channel = nch_and_spacing[0]
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
p_tot = pin.sum()
|
||||
expected_p_tot = si.carriers[0].power.signal * nb_channel
|
||||
p_tot = sum(si.signal + si.ase + si.nli)
|
||||
expected_p_tot = si.signal[0] * nb_channel
|
||||
assert pytest.approx(expected_p_tot, abs=0.01) == p_tot
|
||||
|
||||
|
||||
@@ -122,14 +118,13 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
|
||||
between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB
|
||||
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
|
||||
edfa = setup_edfa_variable_gain
|
||||
frequencies = array([c.frequency for c in si.carriers])
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
pin = pin / db2lin(gain)
|
||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
||||
si.signal /=db2lin(gain)
|
||||
si.nli /= db2lin(gain)
|
||||
si.ase /= db2lin(gain)
|
||||
edfa.operational.gain_target = gain
|
||||
# edfa is variable gain type
|
||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
||||
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
|
||||
edfa.interpol_params(si)
|
||||
nf_model = edfa.nf[0]
|
||||
|
||||
# change edfa type variety to a polynomial
|
||||
@@ -155,7 +150,7 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
|
||||
edfa = Edfa(**el_config)
|
||||
|
||||
# edfa is variable gain type
|
||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
||||
edfa.interpol_params(si)
|
||||
nf_poly = edfa.nf[0]
|
||||
print(nf_poly, nf_model)
|
||||
assert pytest.approx(nf_model, abs=0.5) == nf_poly
|
||||
@@ -183,21 +178,16 @@ def test_ase_noise(gain, si, setup_trx, bw):
|
||||
si = span(si)
|
||||
print(span)
|
||||
|
||||
frequencies = array([c.frequency for c in si.carriers])
|
||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
||||
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
|
||||
edfa.interpol_params(si)
|
||||
nf = edfa.nf
|
||||
print('nf', nf)
|
||||
pin = lin2db(pin[0] * 1e3)
|
||||
pin = lin2db((si.signal[0] + si.ase[0] + si.nli[0]) * 1e3)
|
||||
osnr_expected = pin - nf[0] + 58
|
||||
|
||||
si = edfa(si)
|
||||
print(edfa)
|
||||
pout = array([c.power.signal for c in si.carriers])
|
||||
pase = array([c.power.ase for c in si.carriers])
|
||||
osnr = lin2db(pout[0] / pase[0]) - lin2db(12.5e9 / bw)
|
||||
osnr = lin2db(si.signal[0] / si.ase[0]) - lin2db(12.5e9 / bw)
|
||||
assert pytest.approx(osnr_expected, abs=0.01) == osnr
|
||||
|
||||
trx = setup_trx
|
||||
|
||||
317
tests/test_equalization.py
Normal file
317
tests/test_equalization.py
Normal file
@@ -0,0 +1,317 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Author: Esther Le Rouzic
|
||||
# @Date: 2019-05-22
|
||||
"""
|
||||
@author: esther.lerouzic
|
||||
checks that new equalization option give the same output as old one:
|
||||
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
from numpy.testing import assert_allclose, assert_array_equal, assert_raises
|
||||
|
||||
from gnpy.core.utils import lin2db, automatic_nch, dbm2watt, powerdbm2psdmwperghz, watt2dbm
|
||||
from gnpy.core.network import build_network
|
||||
from gnpy.core.elements import Roadm
|
||||
from gnpy.core.info import create_input_spectral_information
|
||||
from gnpy.core.equipment import trx_mode_params
|
||||
from gnpy.tools.json_io import network_from_json, load_equipment, load_network, _spectrum_from_json, load_json
|
||||
from gnpy.topology.request import PathRequest, compute_constrained_path, propagate, update_spectrum_power, ref_carrier
|
||||
|
||||
|
||||
TEST_DIR = Path(__file__).parent
|
||||
EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json'
|
||||
NETWORK_FILENAME = TEST_DIR / 'data/testTopology_expected.json'
|
||||
|
||||
|
||||
def net_setup(equipment):
|
||||
""" common setup for tests: builds network, equipment and oms only once
|
||||
"""
|
||||
network = load_network(NETWORK_FILENAME, equipment)
|
||||
spectrum = equipment['SI']['default']
|
||||
p_db = spectrum.power_dbm
|
||||
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
|
||||
build_network(network, equipment, p_db, p_total_db)
|
||||
return network
|
||||
|
||||
|
||||
def create_voyager_req(equipment, source, dest, bidir, nodes_list, loose_list, mode, spacing, power_dbm):
|
||||
""" create the usual request list according to parameters
|
||||
"""
|
||||
params = {'request_id': 'test_request',
|
||||
'source': source,
|
||||
'bidir': bidir,
|
||||
'destination': dest,
|
||||
'trx_type': 'Voyager',
|
||||
'trx_mode': mode,
|
||||
'format': mode,
|
||||
'spacing': spacing,
|
||||
'nodes_list': nodes_list,
|
||||
'loose_list': loose_list,
|
||||
'path_bandwidth': 100.0e9,
|
||||
'effective_freq_slot': None}
|
||||
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
|
||||
params.update(trx_params)
|
||||
params['power'] = dbm2watt(power_dbm) if power_dbm else dbm2watt(equipment['SI']['default'].power_dbm)
|
||||
f_min = params['f_min']
|
||||
f_max_from_si = params['f_max']
|
||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||
return PathRequest(**params)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('power_dbm', [0, 1, -2, None])
|
||||
@pytest.mark.parametrize('mode, spacing', (['mode 1', 50e9], ['mode 2', 75e9]))
|
||||
def test_initial_spectrum(mode, spacing, power_dbm):
|
||||
""" checks that propagation using the user defined spectrum identical to SI, gives same result as SI
|
||||
"""
|
||||
# first propagate without any req.initial_spectrum attribute
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
mode, spacing, power_dbm)
|
||||
network = net_setup(equipment)
|
||||
path = compute_constrained_path(network, req)
|
||||
infos_expected = propagate(path, req, equipment)
|
||||
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
|
||||
temp = [{
|
||||
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": req.baud_rate,
|
||||
"spacing": spacing,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}]
|
||||
if power_dbm:
|
||||
temp[0]['power_dbm'] = power_dbm
|
||||
req.initial_spectrum = _spectrum_from_json(temp, equipment)
|
||||
update_spectrum_power(req)
|
||||
infos_actual = propagate(path, req, equipment)
|
||||
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
|
||||
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
|
||||
assert_array_equal(infos_expected.signal, infos_actual.signal)
|
||||
assert_array_equal(infos_expected.nli, infos_actual.nli)
|
||||
assert_array_equal(infos_expected.ase, infos_actual.ase)
|
||||
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
|
||||
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
|
||||
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
|
||||
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
|
||||
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
|
||||
|
||||
|
||||
def test_initial_spectrum_not_identical():
|
||||
""" checks that user defined spectrum overrides spectrum defined in SI
|
||||
"""
|
||||
# first propagate without any req.initial_spectrum attribute
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
'mode 1', 50e9, 0)
|
||||
network = net_setup(equipment)
|
||||
path = compute_constrained_path(network, req)
|
||||
infos_expected = propagate(path, req, equipment)
|
||||
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
|
||||
temp = [{
|
||||
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": 40e9,
|
||||
"spacing": 62.5e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}]
|
||||
req.initial_spectrum = _spectrum_from_json(temp, equipment)
|
||||
update_spectrum_power(req)
|
||||
infos_actual = propagate(path, req, equipment)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.baud_rate, infos_actual.baud_rate)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.slot_width, infos_actual.slot_width)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.signal, infos_actual.signal)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.nli, infos_actual.nli)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.ase, infos_actual.ase)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.channel_number, infos_actual.channel_number)
|
||||
assert_raises(AssertionError, assert_array_equal, infos_expected.number_of_channels, infos_actual.number_of_channels)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('with_initial_spectrum', [None, 0, +2, -0.5])
|
||||
def test_target_psd_out_mwperghz(with_initial_spectrum):
|
||||
""" checks that if target_psd_out_mWperGHz is defined, it is used as equalization, and it gives same result if
|
||||
computed target is the same
|
||||
"""
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
network = net_setup(equipment)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
'mode 1', 50e9, 0)
|
||||
if with_initial_spectrum:
|
||||
temp = [{
|
||||
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_max and not SI !
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": req.baud_rate,
|
||||
"power_dbm": with_initial_spectrum,
|
||||
"spacing": 50e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}]
|
||||
req.initial_spectrum = _spectrum_from_json(temp, equipment)
|
||||
path = compute_constrained_path(network, req)
|
||||
infos_expected = propagate(path, req, equipment)
|
||||
# change default equalization to power spectral density
|
||||
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
|
||||
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', powerdbm2psdmwperghz(-20, 32e9))
|
||||
# create a second instance with this roadm settings,
|
||||
network2 = net_setup(equipment)
|
||||
path2 = compute_constrained_path(network2, req)
|
||||
infos_actual = propagate(path2, req, equipment)
|
||||
# since baudrate is the same, resulting propagation should be the same as for power equalization
|
||||
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
|
||||
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
|
||||
assert_array_equal(infos_expected.signal, infos_actual.signal)
|
||||
assert_array_equal(infos_expected.nli, infos_actual.nli)
|
||||
assert_array_equal(infos_expected.ase, infos_actual.ase)
|
||||
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
|
||||
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
|
||||
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
|
||||
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
|
||||
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
|
||||
|
||||
|
||||
def ref_network():
|
||||
""" Create a network instance with a instance of propagated path
|
||||
"""
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
network = net_setup(equipment)
|
||||
req0 = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
'mode 1', 50e9, 0)
|
||||
path0 = compute_constrained_path(network, req0)
|
||||
_ = propagate(path0, req0, equipment)
|
||||
return network
|
||||
|
||||
|
||||
@pytest.mark.parametrize('deltap', [0, +1.2, -0.5])
|
||||
def test_target_psd_out_mwperghz_deltap(deltap):
|
||||
""" checks that if target_psd_out_mWperGHz is defined, delta_p of amps is correctly updated
|
||||
Power over 1.2dBm saturate amp with this test: TODO add a test on this saturation
|
||||
"""
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
network = net_setup(equipment)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
'mode 1', 50e9, deltap)
|
||||
temp = [{
|
||||
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": req.baud_rate,
|
||||
"spacing": 50e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}]
|
||||
req.initial_spectrum = _spectrum_from_json(temp, equipment)
|
||||
update_spectrum_power(req)
|
||||
path = compute_constrained_path(network, req)
|
||||
_ = propagate(path, req, equipment)
|
||||
# check that gain of booster is changed accordingly whereas gain of preamp and ila is not (no saturation case)
|
||||
boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Vannes_KBE']
|
||||
ila_preamps = ['east edfa in Quimper to Lorient_KMA', 'west edfa in Lorient_KMA to Quimper',
|
||||
'west edfa in Vannes_KBE to Lorient_KMA']
|
||||
for amp in boosters + ila_preamps:
|
||||
expected_amp = next(n for n in ref_network() if n.uid == amp)
|
||||
actual_amp = next(n for n in network.nodes() if n.uid == amp)
|
||||
expected_gain = expected_amp.pout_db - expected_amp.pin_db
|
||||
actual_gain = actual_amp.pout_db - actual_amp.pin_db
|
||||
print(actual_amp)
|
||||
if amp in boosters:
|
||||
assert expected_gain + deltap == pytest.approx(actual_gain, rel=1e-3)
|
||||
if amp in ila_preamps:
|
||||
assert expected_gain == pytest.approx(actual_gain, rel=1e-3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('case', ['SI', 'nodes'])
|
||||
@pytest.mark.parametrize('deltap', [0, +2, -0.5])
|
||||
@pytest.mark.parametrize('target', [-20, -21, -18])
|
||||
@pytest.mark.parametrize('mode, spacing', (['mode 1', 50e9], ['mode 2', 75e9]))
|
||||
def test_equalization(case, deltap, target, mode, spacing):
|
||||
"""check that power target on roadm is correct for these cases; check on booster
|
||||
- SI : target_pch_out_db / target_psd_out_mWperGHz
|
||||
- node : target_pch_out_db / target_psd_out_mWperGHz
|
||||
- per degree : target_pch_out_db / target_psd_out_mWperGHz
|
||||
for these cases with and without power from user
|
||||
"""
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
setattr(equipment['Roadm']['default'], 'target_pch_out_db', target)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Rennes_STA', False,
|
||||
['east edfa in Brest_KLA to Quimper', 'roadm Lannion_CAS', 'trx Rennes_STA'],
|
||||
['STRICT', 'STRICT', 'STRICT'],
|
||||
mode, spacing, deltap)
|
||||
roadms = ['roadm Brest_KLA', 'roadm Lorient_KMA', 'roadm Lannion_CAS', 'roadm Rennes_STA']
|
||||
# degree = {'roadm Brest_KLA': 'east edfa in Brest_KLA to Quimper',
|
||||
# 'roadm Lorient_KMA': 'east edfa in Lorient_KMA to Loudeac'}
|
||||
# boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Loudeac',
|
||||
# 'east edfa in Lannion_CAS to Stbrieuc']
|
||||
target_psd = powerdbm2psdmwperghz(target, 32e9)
|
||||
ref = ref_carrier(req.power, equipment)
|
||||
if case == 'SI':
|
||||
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
|
||||
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz',
|
||||
target_psd)
|
||||
network = net_setup(equipment)
|
||||
elif case == 'nodes':
|
||||
json_data = load_json(NETWORK_FILENAME)
|
||||
for el in json_data['elements']:
|
||||
if el['uid'] in roadms:
|
||||
el['params'] = {'target_psd_out_mWperGHz': target_psd}
|
||||
network = network_from_json(json_data, equipment)
|
||||
spectrum = equipment['SI']['default']
|
||||
p_db = spectrum.power_dbm
|
||||
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
|
||||
build_network(network, equipment, p_db, p_total_db)
|
||||
# check that nodes not in roadms have target_pch_out_db not None
|
||||
pw_roadms = [r for r in network.nodes() if r.uid not in roadms and isinstance(r, Roadm)]
|
||||
for roadm in pw_roadms:
|
||||
assert roadm.target_psd_out_mWperGHz is None
|
||||
assert roadm.target_pch_out_dbm == target
|
||||
path = compute_constrained_path(network, req)
|
||||
si = create_input_spectral_information(
|
||||
req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing, ref_carrier=ref)
|
||||
for i, el in enumerate(path):
|
||||
if isinstance(el, Roadm):
|
||||
si = el(si, degree=path[i+1].uid)
|
||||
if case in ['SI', 'nodes', 'degrees']:
|
||||
assert_allclose(powerdbm2psdmwperghz(watt2dbm(si.signal + si.ase + si.nli), si.baud_rate),
|
||||
target_psd, rtol=1e-3)
|
||||
else:
|
||||
si = el(si)
|
||||
print(el.uid)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('req_power', [0, 2, -1.5])
|
||||
def test_power_option(req_power):
|
||||
"""check that --po option adds correctly power with spectral information
|
||||
"""
|
||||
equipment = load_equipment(EQPT_FILENAME)
|
||||
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
|
||||
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', powerdbm2psdmwperghz(-20, 32e9))
|
||||
network = net_setup(equipment)
|
||||
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
|
||||
'mode 1', 50e9, req_power)
|
||||
path = compute_constrained_path(network, req)
|
||||
infos_expected = propagate(path, req, equipment)
|
||||
|
||||
temp = [{
|
||||
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_max and not SI !
|
||||
"f_max": 196.1e12,
|
||||
"baud_rate": req.baud_rate,
|
||||
"spacing": 50e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40
|
||||
}]
|
||||
req.initial_spectrum = _spectrum_from_json(temp, equipment)
|
||||
update_spectrum_power(req)
|
||||
network2 = net_setup(equipment)
|
||||
path2 = compute_constrained_path(network2, req)
|
||||
infos_actual = propagate(path2, req, equipment)
|
||||
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
|
||||
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
|
||||
assert_array_equal(infos_expected.signal, infos_actual.signal)
|
||||
assert_array_equal(infos_expected.nli, infos_actual.nli)
|
||||
assert_array_equal(infos_expected.ase, infos_actual.ase)
|
||||
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
|
||||
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
|
||||
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
|
||||
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
|
||||
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
|
||||
53
tests/test_info.py
Normal file
53
tests/test_info.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pytest
|
||||
from numpy import array, zeros, ones
|
||||
from numpy.testing import assert_array_equal
|
||||
from gnpy.core.info import create_arbitrary_spectral_information, Pref
|
||||
from gnpy.core.exceptions import SpectrumError
|
||||
|
||||
|
||||
def test_create_arbitrary_spectral_information():
|
||||
si = create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12],
|
||||
baud_rate=32e9, signal=[1, 1, 1],
|
||||
ref_power=Pref(1, 1, array([1, 1, 1]), None))
|
||||
assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9]))
|
||||
assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9]))
|
||||
assert_array_equal(si.signal, ones(3))
|
||||
assert_array_equal(si.nli, zeros(3))
|
||||
assert_array_equal(si.ase, zeros(3))
|
||||
assert_array_equal(si.roll_off, zeros(3))
|
||||
assert_array_equal(si.chromatic_dispersion, zeros(3))
|
||||
assert_array_equal(si.pmd, zeros(3))
|
||||
assert_array_equal(si.channel_number, array([1, 2, 3]))
|
||||
assert_array_equal(si.number_of_channels, 3)
|
||||
assert_array_equal(si.df, array([[0, 50e9, 100e9], [-50e9, 0, 50e9], [-100e9, -50e9, 0]]))
|
||||
|
||||
with pytest.raises(SpectrumError, match='Spectra cannot be summed: channels overlapping.'):
|
||||
si += si
|
||||
|
||||
si = create_arbitrary_spectral_information(frequency=array([193.35e12, 193.3e12, 193.25e12]),
|
||||
slot_width=array([50e9, 50e9, 50e9]),
|
||||
baud_rate=32e9, signal=array([1, 2, 3]),
|
||||
ref_power=Pref(1, 1, array([1, 2, 3]), None))
|
||||
assert_array_equal(si.signal, array([3, 2, 1]))
|
||||
|
||||
with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, '
|
||||
r'larger than the slot width for channels: \[1, 3\].'):
|
||||
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1,
|
||||
baud_rate=[64e9, 32e9, 64e9], slot_width=50e9,
|
||||
ref_power=Pref(1, 1, 1, None))
|
||||
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
|
||||
r'distances between channels: \[\(1, 2\), \(3, 4\)\].'):
|
||||
create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1,
|
||||
baud_rate=32e9, slot_width=50e9, ref_power=Pref(1, 1, 1, None))
|
||||
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
|
||||
r'distances between channels: \[\(1, 2\), \(2, 3\)\].'):
|
||||
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9,
|
||||
roll_off=0.1, ref_power=Pref(1, 1, 1, None))
|
||||
|
||||
with pytest.raises(SpectrumError,
|
||||
match='Dimension mismatch in input fields.'):
|
||||
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9,
|
||||
ref_power=Pref(1, 1, [1, 2], None))
|
||||
@@ -20,7 +20,15 @@ SRC_ROOT = Path(__file__).parent.parent
|
||||
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', 'gnpy/example-data/Sweden_OpenROADMv4_example_network.json', ]),
|
||||
('openroadm-v5-Stockholm-Gothenburg', transmission_main_example,
|
||||
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', 'gnpy/example-data/Sweden_OpenROADMv5_example_network.json', ]),
|
||||
))
|
||||
('transmission_main_example_long', transmission_main_example,
|
||||
['-e', 'tests/data/eqpt_config.json', 'tests/data/test_long_network.json']),
|
||||
('spectrum1_transmission_main_example', transmission_main_example,
|
||||
['-spectrum', 'gnpy/example-data/initial_spectrum1.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]),
|
||||
('spectrum2_transmission_main_example', transmission_main_example,
|
||||
['-spectrum', 'gnpy/example-data/initial_spectrum2.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]),
|
||||
))
|
||||
|
||||
|
||||
def test_example_invocation(capfd, output, handler, args):
|
||||
'''Make sure that our examples produce useful output'''
|
||||
os.chdir(SRC_ROOT)
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pathlib import Path
|
||||
"""
|
||||
Checks that the class SimParams behaves as a mutable Singleton.
|
||||
"""
|
||||
|
||||
from gnpy.core.parameters import SimParams
|
||||
from gnpy.core.science_utils import Simulation
|
||||
from gnpy.tools.json_io import load_json
|
||||
|
||||
TEST_DIR = Path(__file__).parent
|
||||
DATA_DIR = TEST_DIR / 'data'
|
||||
import pytest
|
||||
from gnpy.core.parameters import SimParams, NLIParams, RamanParams
|
||||
|
||||
|
||||
def test_sim_parameters():
|
||||
j = load_json(DATA_DIR / 'sim_params.json')
|
||||
sim_params = SimParams(**j)
|
||||
Simulation.set_params(sim_params)
|
||||
s1 = Simulation.get_simulation()
|
||||
assert s1.sim_params.raman_params.flag_raman
|
||||
s2 = Simulation.get_simulation()
|
||||
assert s2.sim_params.raman_params.flag_raman
|
||||
j['raman_parameters']['flag_raman'] = False
|
||||
sim_params = SimParams(**j)
|
||||
Simulation.set_params(sim_params)
|
||||
assert not s2.sim_params.raman_params.flag_raman
|
||||
assert not s1.sim_params.raman_params.flag_raman
|
||||
class MockSimParams(SimParams):
|
||||
"""Mock simulation parameters for monkey patch"""
|
||||
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def set_sim_params(monkeypatch):
|
||||
monkeypatch.setattr(SimParams, '_shared_dict', MockSimParams._shared_dict)
|
||||
|
||||
|
||||
def test_sim_parameters(set_sim_params):
|
||||
sim_params = {'nli_params': {}, 'raman_params': {}}
|
||||
MockSimParams.set_params(sim_params)
|
||||
s1 = SimParams.get()
|
||||
assert s1.nli_params.method == 'gn_model_analytic'
|
||||
s2 = SimParams.get()
|
||||
assert not s1.raman_params.flag
|
||||
sim_params['raman_params']['flag'] = True
|
||||
MockSimParams.set_params(sim_params)
|
||||
assert s2.raman_params.flag
|
||||
assert s1.raman_params.flag
|
||||
|
||||
@@ -12,12 +12,14 @@ checks that restrictions in roadms are correctly applied during autodesign
|
||||
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
from numpy.testing import assert_allclose
|
||||
|
||||
from gnpy.core.utils import lin2db, automatic_nch
|
||||
from gnpy.core.elements import Fused, Roadm, Edfa
|
||||
from gnpy.core.network import build_network
|
||||
from gnpy.tools.json_io import network_from_json, load_equipment, load_json, Amp
|
||||
from gnpy.core.equipment import trx_mode_params
|
||||
from gnpy.topology.request import PathRequest, compute_constrained_path
|
||||
from gnpy.topology.request import PathRequest, compute_constrained_path, ref_carrier
|
||||
from gnpy.core.info import create_input_spectral_information
|
||||
from gnpy.core.utils import db2lin
|
||||
|
||||
@@ -251,38 +253,26 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
|
||||
path = compute_constrained_path(network, req)
|
||||
si = create_input_spectral_information(
|
||||
req.f_min, req.f_max, req.roll_off, req.baud_rate,
|
||||
req.power, req.spacing)
|
||||
req.power, req.spacing, ref_carrier(req.power, equipment))
|
||||
for i, el in enumerate(path):
|
||||
if isinstance(el, Roadm):
|
||||
carriers_power_in_roadm = min([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
||||
si = el(si, degree=path[i + 1].uid)
|
||||
min_power_in_roadm = min(si.signal + si.ase + si.nli)
|
||||
si = el(si, degree=path[i+1].uid)
|
||||
power_out_roadm = si.signal + si.ase + si.nli
|
||||
if el.uid == 'roadm node B':
|
||||
print('input', carriers_power_in_roadm)
|
||||
# if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its
|
||||
# target power (as specified in equipment ie -20 dBm)
|
||||
# if it is a Fused, the input power to the ROADM is smaller than the target power, and the
|
||||
# ROADM cannot apply this target. In this case, it is assumed that the ROADM has 0 dB loss
|
||||
# so the output power will be the same as the input power, which for this particular case
|
||||
# corresponds to -22dBm + power_dbm
|
||||
# next step (for ROADM modelling) will be to apply a minimum loss for ROADMs !
|
||||
print('input', min_power_in_roadm)
|
||||
if prev_node_type == 'edfa':
|
||||
assert el.effective_pch_out_db == effective_pch_out_db
|
||||
if prev_node_type == 'fused':
|
||||
# then output power == input_power == effective_pch_out_db + power_dbm
|
||||
assert effective_pch_out_db + power_dbm == \
|
||||
pytest.approx(lin2db(carriers_power_in_roadm * 1e3), rel=1e-3)
|
||||
assert el.effective_pch_out_db == effective_pch_out_db + power_dbm
|
||||
for carrier in si.carriers:
|
||||
print(carrier.power.signal + carrier.power.nli + carrier.power.ase)
|
||||
power = carrier.power.signal + carrier.power.nli + carrier.power.ase
|
||||
if prev_node_type == 'edfa':
|
||||
# edfa prev_node sets input power to roadm to a high enough value:
|
||||
# Check that egress power of roadm is equal to target power
|
||||
assert power == pytest.approx(db2lin(effective_pch_out_db - 30), rel=1e-3)
|
||||
elif prev_node_type == 'fused':
|
||||
# fused prev_node does reamplfy power after fiber propagation, so input power
|
||||
# to roadm is low.
|
||||
# Check that egress power of roadm is equalized to the min carrier input power.
|
||||
assert power == pytest.approx(carriers_power_in_roadm, rel=1e-3)
|
||||
# edfa prev_node sets input power to roadm to a high enough value:
|
||||
# check that target power is correctly set in the ROADM
|
||||
assert_allclose(el.ref_pch_out_dbm, effective_pch_out_db, rtol=1e-3)
|
||||
# Check that egress power of roadm is equal to target power
|
||||
assert_allclose(power_out_roadm, db2lin(effective_pch_out_db - 30), rtol=1e-3)
|
||||
elif prev_node_type == 'fused':
|
||||
# fused prev_node does reamplfy power after fiber propagation, so input power
|
||||
# to roadm is low.
|
||||
# check that target power correctly reports power_dbm from previous propagation
|
||||
assert_allclose(el.ref_pch_out_dbm, effective_pch_out_db + power_dbm, rtol=1e-3)
|
||||
# Check that egress power of roadm is equalized to the min carrier input power.
|
||||
assert_allclose(power_out_roadm, min_power_in_roadm, rtol=1e-3)
|
||||
else:
|
||||
si = el(si)
|
||||
|
||||
@@ -1,48 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Author: Alessio Ferrari
|
||||
|
||||
"""
|
||||
Checks that RamanFiber propagates properly the spectral information. In this way, also the RamanSolver and the NliSolver
|
||||
are tested.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from pandas import read_csv
|
||||
from numpy.testing import assert_allclose
|
||||
from numpy import array, load
|
||||
|
||||
from gnpy.core.info import create_input_spectral_information
|
||||
from gnpy.core.elements import RamanFiber
|
||||
from gnpy.core.parameters import SimParams
|
||||
from gnpy.core.science_utils import Simulation
|
||||
from gnpy.core.info import create_input_spectral_information, create_arbitrary_spectral_information, Pref
|
||||
from gnpy.core.elements import Fiber, RamanFiber
|
||||
from gnpy.tools.json_io import load_json
|
||||
from gnpy.core.exceptions import NetworkTopologyError
|
||||
from gnpy.core.science_utils import RamanSolver
|
||||
|
||||
from tests.test_parameters import MockSimParams, set_sim_params
|
||||
|
||||
TEST_DIR = Path(__file__).parent
|
||||
|
||||
|
||||
def test_raman_fiber():
|
||||
""" Test the accuracy of propagating the RamanFiber."""
|
||||
# spectral information generation
|
||||
power = 1e-3
|
||||
eqpt_params = load_json(TEST_DIR / 'data' / 'eqpt_config.json')
|
||||
spectral_info_params = eqpt_params['SI'][0]
|
||||
spectral_info_params.pop('power_dbm')
|
||||
spectral_info_params.pop('power_range_db')
|
||||
spectral_info_params.pop('tx_osnr')
|
||||
spectral_info_params.pop('sys_margins')
|
||||
spectral_info_input = create_input_spectral_information(power=power, **spectral_info_params)
|
||||
def test_fiber():
|
||||
""" Test the accuracy of propagating the Fiber."""
|
||||
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
|
||||
|
||||
sim_params = SimParams(**load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||
Simulation.set_params(sim_params)
|
||||
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'raman_fiber_config.json'))
|
||||
# fix grid spectral information generation
|
||||
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||
# propagation
|
||||
spectral_info_out = fiber(spectral_info_input)
|
||||
|
||||
p_signal = spectral_info_out.signal
|
||||
p_nli = spectral_info_out.nli
|
||||
|
||||
expected_results = read_csv(TEST_DIR / 'data' / 'test_fiber_fix_expected_results.csv')
|
||||
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||
|
||||
# flex grid spectral information generation
|
||||
frequency = 191e12 + array([0, 50e9, 150e9, 225e9, 275e9])
|
||||
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
|
||||
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
|
||||
signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4])
|
||||
pref = Pref(p_span0=0, p_spani=0, p_span0_per_channel=list(signal), ref_carrier=None)
|
||||
spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
|
||||
signal=signal, baud_rate=baud_rate, roll_off=0.15,
|
||||
ref_power=pref)
|
||||
|
||||
# propagation
|
||||
spectral_info_out = fiber(spectral_info_input)
|
||||
|
||||
p_signal = [carrier.power.signal for carrier in spectral_info_out.carriers]
|
||||
p_ase = [carrier.power.ase for carrier in spectral_info_out.carriers]
|
||||
p_nli = [carrier.power.nli for carrier in spectral_info_out.carriers]
|
||||
p_signal = spectral_info_out.signal
|
||||
p_nli = spectral_info_out.nli
|
||||
|
||||
expected_results = read_csv(TEST_DIR / 'data' / 'test_science_utils_expected_results.csv')
|
||||
expected_results = read_csv(TEST_DIR / 'data' / 'test_fiber_flex_expected_results.csv')
|
||||
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||
|
||||
|
||||
def test_raman_fiber(set_sim_params):
|
||||
""" Test the accuracy of propagating the RamanFiber."""
|
||||
# spectral information generation
|
||||
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||
MockSimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
|
||||
|
||||
# propagation
|
||||
spectral_info_out = fiber(spectral_info_input)
|
||||
|
||||
p_signal = spectral_info_out.signal
|
||||
p_ase = spectral_info_out.ase
|
||||
p_nli = spectral_info_out.nli
|
||||
|
||||
expected_results = read_csv(TEST_DIR / 'data' / 'test_raman_fiber_expected_results.csv')
|
||||
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||
assert_allclose(p_ase, expected_results['ase'], rtol=1e-3)
|
||||
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("loss, position, errmsg", (
|
||||
(0.5, -2, f"Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded."),
|
||||
(0.5, 81, f"Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded.")))
|
||||
def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params):
|
||||
""" Check on Fiber with lumped losses."""
|
||||
MockSimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||
fiber_dict = load_json(TEST_DIR / 'data' / 'test_lumped_losses_fiber_config.json')
|
||||
fiber_dict['params']['lumped_losses'] = [{'position': position, 'loss': loss}]
|
||||
with pytest.raises(NetworkTopologyError) as e:
|
||||
Fiber(**fiber_dict)
|
||||
assert str(e.value) == errmsg
|
||||
|
||||
|
||||
def test_fiber_lumped_losses_srs(set_sim_params):
|
||||
""" Test the accuracy of Fiber with lumped losses propagation."""
|
||||
# spectral information generation
|
||||
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||
|
||||
MockSimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||
sim_params = MockSimParams.get()
|
||||
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_fiber_config.json'))
|
||||
raman_fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json'))
|
||||
|
||||
# propagation
|
||||
# without Raman pumps
|
||||
expected_power_profile = load(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_pumps.npy')
|
||||
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
|
||||
spectral_info_input, fiber)
|
||||
power_profile = stimulated_raman_scattering.power_profile
|
||||
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||
|
||||
# with Raman pumps
|
||||
expected_power_profile = load(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber.npy')
|
||||
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
|
||||
spectral_info_input, raman_fiber)
|
||||
power_profile = stimulated_raman_scattering.power_profile
|
||||
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||
|
||||
# without Stimulated Raman Scattering
|
||||
expected_power_profile = load(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_raman.npy')
|
||||
stimulated_raman_scattering = RamanSolver.calculate_attenuation_profile(spectral_info_input, fiber)
|
||||
power_profile = stimulated_raman_scattering.power_profile
|
||||
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||
|
||||
Reference in New Issue
Block a user