mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-31 18:18:00 +00:00
Refactoring with some incompatible changes
Please be advised that there were incompatible changes in the Raman options, including a `s/phase_shift_tollerance/phase_shift_tolerance/`. Signed-off-by: AndreaDAmico <andrea.damico@polito.it> Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com> Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
This commit is contained in:
committed by
Jan Kundrát
parent
2960d307fa
commit
80eced85ec
@@ -412,7 +412,6 @@ parameters:
|
|||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params":
|
"params":
|
||||||
{
|
{
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 120.0,
|
"length": 120.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"raman_computed_channels": [1, 18, 37, 56, 75],
|
|
||||||
"raman_parameters": {
|
"raman_parameters": {
|
||||||
"flag_raman": true,
|
"flag_raman": true,
|
||||||
"space_resolution": 10e3,
|
"space_resolution": 10e3,
|
||||||
@@ -9,6 +8,7 @@
|
|||||||
"nli_method_name": "ggn_spectrally_separated",
|
"nli_method_name": "ggn_spectrally_separated",
|
||||||
"wdm_grid_size": 50e9,
|
"wdm_grid_size": 50e9,
|
||||||
"dispersion_tolerance": 1,
|
"dispersion_tolerance": 1,
|
||||||
"phase_shift_tollerance": 0.1
|
"phase_shift_tolerance": 0.1,
|
||||||
|
"computed_channels": [1, 18, 37, 56, 75]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,14 @@ from numpy import linspace, mean, log10
|
|||||||
from matplotlib.pyplot import show, axis, figure, title, text
|
from matplotlib.pyplot import show, axis, figure, title, text
|
||||||
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
||||||
draw_networkx_labels, dijkstra_path)
|
draw_networkx_labels, dijkstra_path)
|
||||||
from gnpy.core.network import load_network, build_network, save_network, load_sim_params, configure_network
|
from gnpy.core.network import load_network, build_network, save_network
|
||||||
from gnpy.core.elements import Transceiver, Fiber, RamanFiber, Edfa, Roadm
|
from gnpy.core.elements import Transceiver, Fiber, RamanFiber, Edfa, Roadm
|
||||||
from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power, Pref
|
from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power, Pref
|
||||||
from gnpy.core.request import Path_request, RequestParams, compute_constrained_path, propagate2
|
from gnpy.core.request import Path_request, RequestParams, compute_constrained_path, propagate2
|
||||||
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError
|
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError
|
||||||
|
from gnpy.core.parameters import SimParams
|
||||||
|
from gnpy.core.science_utils import Simulation
|
||||||
|
from gnpy.core.utils import load_json
|
||||||
import gnpy.core.ansi_escapes as ansi_escapes
|
import gnpy.core.ansi_escapes as ansi_escapes
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
@@ -126,14 +129,16 @@ def main(network, equipment, source, destination, sim_params, req=None):
|
|||||||
build_network(network, equipment, pref_ch_db, pref_total_db)
|
build_network(network, equipment, pref_ch_db, pref_total_db)
|
||||||
path = compute_constrained_path(network, req)
|
path = compute_constrained_path(network, req)
|
||||||
|
|
||||||
if len([s.length for s in path if isinstance(s, RamanFiber)]):
|
if sim_params:
|
||||||
|
Simulation.set_params(sim_params)
|
||||||
|
|
||||||
|
if len([s.params.length for s in path if isinstance(s, RamanFiber)]):
|
||||||
if sim_params is None:
|
if sim_params is None:
|
||||||
print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
|
print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
|
||||||
f'RamanFiber requires passing simulation params via --sim-params')
|
f'RamanFiber requires passing simulation params via --sim-params')
|
||||||
exit(1)
|
exit(1)
|
||||||
configure_network(network, sim_params)
|
|
||||||
|
|
||||||
spans = [s.length for s in path if isinstance(s, RamanFiber) or isinstance(s, Fiber)]
|
spans = [s.params.length for s in path if isinstance(s, RamanFiber) or isinstance(s, Fiber)]
|
||||||
print(f'\nThere are {len(spans)} fiber spans over {sum(spans)/1000:.0f} km between {source.uid} '
|
print(f'\nThere are {len(spans)} fiber spans over {sum(spans)/1000:.0f} km between {source.uid} '
|
||||||
f'and {destination.uid}')
|
f'and {destination.uid}')
|
||||||
print(f'\nNow propagating between {source.uid} and {destination.uid}:')
|
print(f'\nNow propagating between {source.uid} and {destination.uid}:')
|
||||||
@@ -215,7 +220,7 @@ if __name__ == '__main__':
|
|||||||
try:
|
try:
|
||||||
equipment = load_equipment(args.equipment)
|
equipment = load_equipment(args.equipment)
|
||||||
network = load_network(args.filename, equipment, args.names_matching)
|
network = load_network(args.filename, equipment, args.names_matching)
|
||||||
sim_params = load_sim_params(args.sim_params) if args.sim_params is not None else None
|
sim_params = SimParams(**load_json(args.sim_params)) if args.sim_params is not None else None
|
||||||
except EquipmentConfigError as e:
|
except EquipmentConfigError as e:
|
||||||
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
|
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|||||||
@@ -18,15 +18,16 @@ Network elements MUST implement two attributes .uid and .name representing a
|
|||||||
unique identifier and a printable name.
|
unique identifier and a printable name.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from numpy import abs, arange, array, exp, divide, errstate
|
from numpy import abs, arange, array, exp, divide, errstate, ones, squeeze
|
||||||
from numpy import interp, log10, mean, pi, polyfit, polyval, sum
|
from numpy import interp, log10, mean, pi, polyfit, polyval, sum
|
||||||
from scipy.constants import c, h
|
from scipy.constants import c, h
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from gnpy.core.node import Node
|
from gnpy.core.node import Node
|
||||||
from gnpy.core.units import UNITS
|
|
||||||
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
|
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
|
||||||
from gnpy.core.science_utils import propagate_raman_fiber, _psi
|
from gnpy.core.parameters import FiberParams, PumpParams
|
||||||
|
from gnpy.core.science_utils import NliSolver, RamanSolver, propagate_raman_fiber, _psi
|
||||||
|
|
||||||
|
|
||||||
class Transceiver(Node):
|
class Transceiver(Node):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -224,37 +225,15 @@ class Fused(Node):
|
|||||||
pref = self.update_pref(spectral_info.pref)
|
pref = self.update_pref(spectral_info.pref)
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||||
|
|
||||||
FiberParams = namedtuple('FiberParams', 'type_variety length loss_coef length_units \
|
|
||||||
att_in con_in con_out dispersion gamma')
|
|
||||||
|
|
||||||
class Fiber(Node):
|
class Fiber(Node):
|
||||||
def __init__(self, *args, params=None, **kwargs):
|
def __init__(self, *args, params=None, **kwargs):
|
||||||
if params is None:
|
if not params:
|
||||||
params = {}
|
params = {}
|
||||||
if 'con_in' not in params:
|
|
||||||
# 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]
|
|
||||||
params['con_in'] = None
|
|
||||||
params['con_out'] = None
|
|
||||||
if 'att_in' not in params:
|
|
||||||
#fixed attenuator for padding
|
|
||||||
params['att_in'] = 0
|
|
||||||
|
|
||||||
super().__init__(*args, params=FiberParams(**params), **kwargs)
|
super().__init__(*args, params=FiberParams(**params), **kwargs)
|
||||||
self.type_variety = self.params.type_variety
|
|
||||||
self.length = self.params.length * UNITS[self.params.length_units] # in m
|
|
||||||
self.loss_coef = self.params.loss_coef * 1e-3 # lineic loss dB/m
|
|
||||||
self.lin_loss_coef = self.params.loss_coef / (20 * log10(exp(1)))
|
|
||||||
self.att_in = self.params.att_in
|
|
||||||
self.con_in = self.params.con_in
|
|
||||||
self.con_out = self.params.con_out
|
|
||||||
self.dispersion = self.params.dispersion # s/m/m
|
|
||||||
self.gamma = self.params.gamma # 1/W/m
|
|
||||||
self.pch_out_db = None
|
|
||||||
self.carriers_in = None
|
self.carriers_in = None
|
||||||
self.carriers_out = None
|
self.carriers_out = None
|
||||||
# TODO|jla: discuss factor 2 in the linear lineic attenuation
|
self.nli_solver = NliSolver(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@@ -263,13 +242,12 @@ class Fiber(Node):
|
|||||||
'type_variety' : self.type_variety,
|
'type_variety' : self.type_variety,
|
||||||
'params' : {
|
'params' : {
|
||||||
#have to specify each because namedtupple cannot be updated :(
|
#have to specify each because namedtupple cannot be updated :(
|
||||||
'type_variety' : self.type_variety,
|
'length' : round(self.params.length * 1e-3, 6),
|
||||||
'length' : self.length/UNITS[self.params.length_units],
|
'loss_coef' : self.params.loss_coef * 1e3,
|
||||||
'loss_coef' : self.loss_coef*1e3,
|
'length_units' : 'km',
|
||||||
'length_units' : self.params.length_units,
|
'att_in' : self.params.att_in,
|
||||||
'att_in' : self.att_in,
|
'con_in' : self.params.con_in,
|
||||||
'con_in' : self.con_in,
|
'con_out' : self.params.con_out
|
||||||
'con_out' : self.con_out
|
|
||||||
},
|
},
|
||||||
'metadata' : {
|
'metadata' : {
|
||||||
'location': self.metadata['location']._asdict()
|
'location': self.metadata['location']._asdict()
|
||||||
@@ -277,48 +255,36 @@ class Fiber(Node):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{type(self).__name__}(uid={self.uid!r}, length={round(self.length*1e-3,1)!r}km, loss={round(self.loss,1)!r}dB)'
|
return f'{type(self).__name__}(uid={self.uid!r}, ' \
|
||||||
|
f'length={round(self.params.length * 1e-3,1)!r}km, ' \
|
||||||
|
f'loss={round(self.loss,1)!r}dB)'
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||||
f' type_variety: {self.type_variety}',
|
f' type_variety: {self.type_variety}',
|
||||||
f' length (km): {round(self.length*1e-3):.2f}',
|
f' length (km): '
|
||||||
f' pad att_in (dB): {self.att_in:.2f}',
|
f'{round(self.params.length * 1e-3):.2f}',
|
||||||
|
f' pad att_in (dB): {self.params.att_in:.2f}',
|
||||||
f' total loss (dB): {self.loss:.2f}',
|
f' total loss (dB): {self.loss:.2f}',
|
||||||
f' (includes conn loss (dB) in: {self.con_in:.2f} out: {self.con_out:.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' (conn loss out includes EOL margin defined in eqpt_config.json)',
|
||||||
f' pch out (dBm): {self.pch_out_db!r}'])
|
f' pch out (dBm): {self.pch_out_db!r}'])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fiber_loss(self):
|
def fiber_loss(self):
|
||||||
"""Fiber loss in dB, not including padding attenuator"""
|
"""Fiber loss in dB, not including padding attenuator"""
|
||||||
return self.loss_coef * self.length + self.con_in + self.con_out
|
return self.params.loss_coef * self.params.length + self.params.con_in + self.params.con_out
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def loss(self):
|
def loss(self):
|
||||||
"""total loss including padding att_in: useful for polymorphism with roadm loss"""
|
"""total loss including padding att_in: useful for polymorphism with roadm loss"""
|
||||||
return self.loss_coef * self.length + self.con_in + self.con_out + self.att_in
|
return self.params.loss_coef * self.params.length + self.params.con_in\
|
||||||
|
+ self.params.con_out + self.params.att_in
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def passive(self):
|
def passive(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
|
||||||
def lin_attenuation(self):
|
|
||||||
return db2lin(self.length * self.loss_coef)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def effective_length(self):
|
|
||||||
_, alpha = self.dbkm_2_lin()
|
|
||||||
leff = (1 - exp(-2 * alpha * self.length)) / (2 * alpha)
|
|
||||||
return leff
|
|
||||||
|
|
||||||
@property
|
|
||||||
def asymptotic_length(self):
|
|
||||||
_, alpha = self.dbkm_2_lin()
|
|
||||||
aleff = 1 / (2 * alpha)
|
|
||||||
return aleff
|
|
||||||
|
|
||||||
def carriers(self, loc, attr):
|
def carriers(self, loc, attr):
|
||||||
"""retrieve carriers information
|
"""retrieve carriers information
|
||||||
|
|
||||||
@@ -335,25 +301,27 @@ class Fiber(Node):
|
|||||||
else:
|
else:
|
||||||
yield c.power._asdict().get(attr, None)
|
yield c.power._asdict().get(attr, None)
|
||||||
|
|
||||||
def beta2(self, ref_wavelength=1550e-9):
|
def alpha(self, frequencies):
|
||||||
"""Returns beta2 from dispersion parameter.
|
""" It returns the values of the series expansion of attenuation coefficient alpha(f) for all f in frequencies
|
||||||
Dispersion is entered in ps/nm/km.
|
|
||||||
Disperion can be a numpy array or a single value.
|
|
||||||
|
|
||||||
:param ref_wavelength: can be a numpy array; default: 1550nm
|
:param frequencies: frequencies of series expansion [Hz]
|
||||||
|
:return: alpha: power attenuation coefficient for f in frequencies [Neper/m]
|
||||||
"""
|
"""
|
||||||
# TODO|jla: discuss beta2 as method or attribute
|
if type(self.params.loss_coef) == dict:
|
||||||
D = abs(self.dispersion)
|
alpha = interp(frequencies, self.params.f_loss_ref, self.params.lin_loss_exp)
|
||||||
b2 = (ref_wavelength ** 2) * D / (2 * pi * c) # 10^21 scales [ps^2/km]
|
else:
|
||||||
return b2 # s/Hz/m
|
alpha = self.params.lin_loss_exp * ones(frequencies.shape)
|
||||||
|
|
||||||
def dbkm_2_lin(self):
|
return alpha
|
||||||
"""calculates the linear loss coefficient"""
|
|
||||||
# linear loss coefficient in dB/km^-1
|
def alpha0(self, f_ref=193.5e12):
|
||||||
alpha_pcoef = self.loss_coef
|
""" It returns the zero element of the series expansion of attenuation coefficient alpha(f) in the
|
||||||
# linear loss field amplitude coefficient in m^-1
|
reference frequency f_ref
|
||||||
alpha_acoef = alpha_pcoef / (2 * 10 * log10(exp(1)))
|
|
||||||
return alpha_pcoef, alpha_acoef
|
:param f_ref: reference frequency of series expansion [Hz]
|
||||||
|
:return: alpha0: power attenuation coefficient in f_ref [Neper/m]
|
||||||
|
"""
|
||||||
|
return self.alpha(f_ref * ones(1))[0]
|
||||||
|
|
||||||
def _gn_analytic(self, carrier, *carriers):
|
def _gn_analytic(self, carrier, *carriers):
|
||||||
"""Computes the nonlinear interference power on a single carrier.
|
"""Computes the nonlinear interference power on a single carrier.
|
||||||
@@ -366,12 +334,13 @@ class Fiber(Node):
|
|||||||
|
|
||||||
g_nli = 0
|
g_nli = 0
|
||||||
for interfering_carrier in carriers:
|
for interfering_carrier in carriers:
|
||||||
psi = _psi(carrier, interfering_carrier, beta2=self.beta2(), asymptotic_length=self.asymptotic_length)
|
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 \
|
g_nli += (interfering_carrier.power.signal/interfering_carrier.baud_rate)**2 \
|
||||||
* (carrier.power.signal/carrier.baud_rate) * psi
|
* (carrier.power.signal/carrier.baud_rate) * psi
|
||||||
|
|
||||||
g_nli *= (16 / 27) * (self.gamma * self.effective_length)**2 \
|
g_nli *= (16 / 27) * (self.params.gamma * self.params.effective_length)**2 \
|
||||||
/ (2 * pi * abs(self.beta2()) * self.asymptotic_length)
|
/ (2 * pi * abs(self.params.beta2) * self.params.asymptotic_length)
|
||||||
|
|
||||||
carrier_nli = carrier.baud_rate * g_nli
|
carrier_nli = carrier.baud_rate * g_nli
|
||||||
return carrier_nli
|
return carrier_nli
|
||||||
@@ -379,7 +348,7 @@ class Fiber(Node):
|
|||||||
def propagate(self, *carriers):
|
def propagate(self, *carriers):
|
||||||
|
|
||||||
# apply connector_att_in on all carriers before computing gn analytics premiere partie pas bonne
|
# apply connector_att_in on all carriers before computing gn analytics premiere partie pas bonne
|
||||||
attenuation = db2lin(self.con_in + self.att_in)
|
attenuation = db2lin(self.params.con_in + self.params.att_in)
|
||||||
|
|
||||||
chan = []
|
chan = []
|
||||||
for carrier in carriers:
|
for carrier in carriers:
|
||||||
@@ -393,13 +362,13 @@ class Fiber(Node):
|
|||||||
carriers = tuple(f for f in chan)
|
carriers = tuple(f for f in chan)
|
||||||
|
|
||||||
# propagate in the fiber and apply attenuation out
|
# propagate in the fiber and apply attenuation out
|
||||||
attenuation = db2lin(self.con_out)
|
attenuation = db2lin(self.params.con_out)
|
||||||
for carrier in carriers:
|
for carrier in carriers:
|
||||||
pwr = carrier.power
|
pwr = carrier.power
|
||||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
carrier_nli = self._gn_analytic(carrier, *carriers)
|
||||||
pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation/attenuation,
|
pwr = pwr._replace(signal=pwr.signal/self.params.lin_attenuation/attenuation,
|
||||||
nli=(pwr.nli+carrier_nli)/self.lin_attenuation/attenuation,
|
nli=(pwr.nli+carrier_nli)/self.params.lin_attenuation/attenuation,
|
||||||
ase=pwr.ase/self.lin_attenuation/attenuation)
|
ase=pwr.ase/self.params.lin_attenuation/attenuation)
|
||||||
yield carrier._replace(power=pwr)
|
yield carrier._replace(power=pwr)
|
||||||
|
|
||||||
def update_pref(self, pref):
|
def update_pref(self, pref):
|
||||||
@@ -413,46 +382,16 @@ class Fiber(Node):
|
|||||||
self.carriers_out = carriers
|
self.carriers_out = carriers
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
return spectral_info._replace(carriers=carriers, pref=pref)
|
||||||
|
|
||||||
RamanFiberParams = namedtuple('RamanFiberParams', 'type_variety length loss_coef length_units \
|
|
||||||
att_in con_in con_out dispersion gamma raman_efficiency')
|
|
||||||
|
|
||||||
class RamanFiber(Fiber):
|
class RamanFiber(Fiber):
|
||||||
def __init__(self, *args, params=None, **kwargs):
|
def __init__(self, *args, params=None, **kwargs):
|
||||||
if params is None:
|
super().__init__(*args, params=params, **kwargs)
|
||||||
params = {}
|
if self.operational and 'raman_pumps' in self.operational:
|
||||||
if 'con_in' not in params:
|
self.raman_pumps = tuple(PumpParams(p['power'], p['frequency'], p['propagation_direction'])
|
||||||
# if not defined in the network json connector loss in/out
|
for p in self.operational['raman_pumps'])
|
||||||
# the None value will be updated in network.py[build_network]
|
else:
|
||||||
# with default values from eqpt_config.json[Spans]
|
self.raman_pumps = None
|
||||||
params['con_in'] = None
|
self.raman_solver = RamanSolver(self)
|
||||||
params['con_out'] = None
|
|
||||||
if 'att_in' not in params:
|
|
||||||
#fixed attenuator for padding
|
|
||||||
params['att_in'] = 0
|
|
||||||
|
|
||||||
# TODO: can we re-use the Fiber constructor in a better way?
|
|
||||||
Node.__init__(self, *args, params=RamanFiberParams(**params), **kwargs)
|
|
||||||
self.type_variety = self.params.type_variety
|
|
||||||
self.length = self.params.length * UNITS[self.params.length_units] # in m
|
|
||||||
self.loss_coef = self.params.loss_coef * 1e-3 # lineic loss dB/m
|
|
||||||
self.lin_loss_coef = self.params.loss_coef / (20 * log10(exp(1)))
|
|
||||||
self.att_in = self.params.att_in
|
|
||||||
self.con_in = self.params.con_in
|
|
||||||
self.con_out = self.params.con_out
|
|
||||||
self.dispersion = self.params.dispersion # s/m/m
|
|
||||||
self.gamma = self.params.gamma # 1/W/m
|
|
||||||
self.pch_out_db = None
|
|
||||||
self.carriers_in = None
|
|
||||||
self.carriers_out = None
|
|
||||||
# TODO|jla: discuss factor 2 in the linear lineic attenuation
|
|
||||||
|
|
||||||
@property
|
|
||||||
def sim_params(self):
|
|
||||||
return self._sim_params
|
|
||||||
|
|
||||||
@sim_params.setter
|
|
||||||
def sim_params(self, sim_params=None):
|
|
||||||
self._sim_params = sim_params
|
|
||||||
|
|
||||||
def update_pref(self, pref, *carriers):
|
def update_pref(self, pref, *carriers):
|
||||||
pch_out_db = lin2db(mean([carrier.power.signal for carrier in carriers])) + 30
|
pch_out_db = lin2db(mean([carrier.power.signal for carrier in carriers])) + 30
|
||||||
@@ -488,13 +427,11 @@ class EdfaParams:
|
|||||||
# self.allowed_for_design = None
|
# self.allowed_for_design = None
|
||||||
|
|
||||||
def update_params(self, kwargs):
|
def update_params(self, kwargs):
|
||||||
for k,v in kwargs.items() :
|
for k, v in kwargs.items():
|
||||||
setattr(self, k, update_params(**v)
|
setattr(self, k, self.update_params(**v) if isinstance(v, dict) else v)
|
||||||
if isinstance(v, dict) else v)
|
|
||||||
|
|
||||||
class EdfaOperational:
|
class EdfaOperational:
|
||||||
default_values = \
|
default_values = {
|
||||||
{
|
|
||||||
'gain_target': None,
|
'gain_target': None,
|
||||||
'delta_p': None,
|
'delta_p': None,
|
||||||
'out_voa': None,
|
'out_voa': None,
|
||||||
|
|||||||
@@ -17,3 +17,8 @@ class EquipmentConfigError(ConfigurationError):
|
|||||||
|
|
||||||
class NetworkTopologyError(ConfigurationError):
|
class NetworkTopologyError(ConfigurationError):
|
||||||
'''Topology of user-provided network is wrong'''
|
'''Topology of user-provided network is wrong'''
|
||||||
|
|
||||||
|
class ParametersError(ConfigurationError):
|
||||||
|
'''Incomplete or wrong configurations within parameters json'''
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ from gnpy.core.elements import Fiber, Edfa, Transceiver, Roadm, Fused, RamanFibe
|
|||||||
from gnpy.core.equipment import edfa_nf
|
from gnpy.core.equipment import edfa_nf
|
||||||
from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError
|
from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError
|
||||||
from gnpy.core.units import UNITS
|
from gnpy.core.units import UNITS
|
||||||
from gnpy.core.science_utils import SimParams
|
|
||||||
from gnpy.core.utils import (load_json, save_json, round2float, db2lin, merge_amplifier_restrictions)
|
from gnpy.core.utils import (load_json, save_json, round2float, db2lin, merge_amplifier_restrictions)
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -56,9 +55,10 @@ def network_from_json(json_data, equipment):
|
|||||||
temp = el_config.setdefault('params', {})
|
temp = el_config.setdefault('params', {})
|
||||||
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
|
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
|
||||||
el_config['params'] = temp
|
el_config['params'] = temp
|
||||||
elif typ in ['Edfa', 'Fiber']: # catch it now because the code will crash later!
|
el_config['type_variety'] = variety
|
||||||
|
elif typ in ['Edfa', 'Fiber', 'RamanFiber']: # catch it now because the code will crash later!
|
||||||
raise ConfigurationError(f'The {typ} of variety type {variety} was not recognized:'
|
raise ConfigurationError(f'The {typ} of variety type {variety} was not recognized:'
|
||||||
'\nplease check it is properly defined in the eqpt_config json file')
|
'\nplease check it is properly defined in the eqpt_config json file')
|
||||||
cls = getattr(elements, typ)
|
cls = getattr(elements, typ)
|
||||||
el = cls(**el_config)
|
el = cls(**el_config)
|
||||||
g.add_node(el)
|
g.add_node(el)
|
||||||
@@ -440,7 +440,7 @@ def calculate_new_length(fiber_length, bounds, target_length):
|
|||||||
|
|
||||||
|
|
||||||
def split_fiber(network, fiber, bounds, target_length, equipment):
|
def split_fiber(network, fiber, bounds, target_length, equipment):
|
||||||
new_length, n_spans = calculate_new_length(fiber.length, bounds, target_length)
|
new_length, n_spans = calculate_new_length(fiber.params.length, bounds, target_length)
|
||||||
if n_spans == 1:
|
if n_spans == 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -452,17 +452,15 @@ def split_fiber(network, fiber, bounds, target_length, equipment):
|
|||||||
|
|
||||||
network.remove_node(fiber)
|
network.remove_node(fiber)
|
||||||
|
|
||||||
fiber_params = fiber.params._asdict()
|
fiber.params.length = new_length
|
||||||
fiber_params['length'] = new_length / UNITS[fiber.params.length_units]
|
|
||||||
fiber_params['con_in'] = fiber.con_in
|
|
||||||
fiber_params['con_out'] = fiber.con_out
|
|
||||||
|
|
||||||
f = interp1d([prev_node.lng, next_node.lng], [prev_node.lat, next_node.lat])
|
f = interp1d([prev_node.lng, next_node.lng], [prev_node.lat, next_node.lat])
|
||||||
xpos = [prev_node.lng + (next_node.lng - prev_node.lng) * (n+1)/(n_spans+1) for n in range(n_spans)]
|
xpos = [prev_node.lng + (next_node.lng - prev_node.lng) * (n+1)/(n_spans+1) for n in range(n_spans)]
|
||||||
ypos = f(xpos)
|
ypos = f(xpos)
|
||||||
for span, lng, lat in zip(range(n_spans), xpos, ypos):
|
for span, lng, lat in zip(range(n_spans), xpos, ypos):
|
||||||
new_span = Fiber(uid = f'{fiber.uid}_({span+1}/{n_spans})',
|
new_span = Fiber(uid=f'{fiber.uid}_({span+1}/{n_spans})',
|
||||||
metadata = {
|
type_variety=fiber.type_variety,
|
||||||
|
metadata={
|
||||||
'location': {
|
'location': {
|
||||||
'latitude': lat,
|
'latitude': lat,
|
||||||
'longitude': lng,
|
'longitude': lng,
|
||||||
@@ -470,8 +468,8 @@ def split_fiber(network, fiber, bounds, target_length, equipment):
|
|||||||
'region': fiber.loc.region,
|
'region': fiber.loc.region,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
params = fiber_params)
|
params=fiber.params.asdict())
|
||||||
if isinstance(prev_node,Fiber):
|
if isinstance(prev_node, Fiber):
|
||||||
edgeweight = prev_node.params.length
|
edgeweight = prev_node.params.length
|
||||||
else:
|
else:
|
||||||
edgeweight = 0.01
|
edgeweight = 0.01
|
||||||
@@ -485,11 +483,11 @@ def split_fiber(network, fiber, bounds, target_length, equipment):
|
|||||||
|
|
||||||
def add_connector_loss(network, fibers, default_con_in, default_con_out, EOL):
|
def add_connector_loss(network, fibers, default_con_in, default_con_out, EOL):
|
||||||
for fiber in fibers:
|
for fiber in fibers:
|
||||||
if fiber.con_in is None: fiber.con_in = default_con_in
|
if fiber.params.con_in is None: fiber.params.con_in = default_con_in
|
||||||
if fiber.con_out is None: fiber.con_out = default_con_out
|
if fiber.params.con_out is None: fiber.params.con_out = default_con_out
|
||||||
next_node = next(n for n in network.successors(fiber))
|
next_node = next(n for n in network.successors(fiber))
|
||||||
if not isinstance(next_node, Fused):
|
if not isinstance(next_node, Fused):
|
||||||
fiber.con_out += EOL
|
fiber.params.con_out += EOL
|
||||||
|
|
||||||
def add_fiber_padding(network, fibers, padding):
|
def add_fiber_padding(network, fibers, padding):
|
||||||
"""last_fibers = (fiber for n in network.nodes()
|
"""last_fibers = (fiber for n in network.nodes()
|
||||||
@@ -509,10 +507,10 @@ def add_fiber_padding(network, fibers, padding):
|
|||||||
# in order to support no booster , fused might be placed
|
# in order to support no booster , fused might be placed
|
||||||
# just after a roadm: need to check that first_fiber is really a fiber
|
# just after a roadm: need to check that first_fiber is really a fiber
|
||||||
if isinstance(first_fiber,Fiber):
|
if isinstance(first_fiber,Fiber):
|
||||||
if first_fiber.att_in is None:
|
if first_fiber.params.att_in is None:
|
||||||
first_fiber.att_in = padding - this_span_loss
|
first_fiber.params.att_in = padding - this_span_loss
|
||||||
else:
|
else:
|
||||||
first_fiber.att_in = first_fiber.att_in + padding - this_span_loss
|
first_fiber.params.att_in = first_fiber.params.att_in + padding - this_span_loss
|
||||||
|
|
||||||
def build_network(network, equipment, pref_ch_db, pref_total_db):
|
def build_network(network, equipment, pref_ch_db, pref_total_db):
|
||||||
default_span_data = equipment['Span']['default']
|
default_span_data = equipment['Span']['default']
|
||||||
@@ -547,12 +545,3 @@ def build_network(network, equipment, pref_ch_db, pref_total_db):
|
|||||||
trx = [t for t in network.nodes() if isinstance(t, Transceiver)]
|
trx = [t for t in network.nodes() if isinstance(t, Transceiver)]
|
||||||
for t in trx:
|
for t in trx:
|
||||||
set_egress_amplifier(network, t, equipment, pref_total_db)
|
set_egress_amplifier(network, t, equipment, pref_total_db)
|
||||||
|
|
||||||
def load_sim_params(filename):
|
|
||||||
sim_params = load_json(filename)
|
|
||||||
return SimParams(params=sim_params)
|
|
||||||
|
|
||||||
def configure_network(network, sim_params):
|
|
||||||
for node in network.nodes:
|
|
||||||
if isinstance(node, RamanFiber):
|
|
||||||
node.sim_params = sim_params
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Location(namedtuple('Location', 'latitude longitude city region')):
|
|||||||
return super().__new__(cls, latitude, longitude, city, region)
|
return super().__new__(cls, latitude, longitude, city, region)
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self, uid, name=None, params=None, metadata=None, operational=None):
|
def __init__(self, uid, name=None, params=None, metadata=None, operational=None, type_variety=None):
|
||||||
if name is None:
|
if name is None:
|
||||||
name = uid
|
name = uid
|
||||||
self.uid, self.name = uid, name
|
self.uid, self.name = uid, name
|
||||||
@@ -35,6 +35,8 @@ class Node:
|
|||||||
if metadata and not isinstance(metadata.get('location'), Location):
|
if metadata and not isinstance(metadata.get('location'), Location):
|
||||||
metadata['location'] = Location(**metadata.pop('location', {}))
|
metadata['location'] = Location(**metadata.pop('location', {}))
|
||||||
self.params, self.metadata, self.operational = params, metadata, operational
|
self.params, self.metadata, self.operational = params, metadata, operational
|
||||||
|
if type_variety:
|
||||||
|
self.type_variety = type_variety
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coords(self):
|
def coords(self):
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from collections import namedtuple
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import scipy.constants as ph
|
import scipy.constants as ph
|
||||||
from scipy.integrate import solve_bvp
|
from scipy.integrate import solve_bvp
|
||||||
@@ -9,154 +8,19 @@ from scipy.interpolate import interp1d
|
|||||||
from scipy.optimize import OptimizeResult
|
from scipy.optimize import OptimizeResult
|
||||||
|
|
||||||
from gnpy.core.utils import db2lin
|
from gnpy.core.utils import db2lin
|
||||||
|
from gnpy.core.parameters import SimParams
|
||||||
|
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RamanParams():
|
|
||||||
def __init__(self, params):
|
|
||||||
self._flag_raman = params['flag_raman']
|
|
||||||
self._space_resolution = params['space_resolution']
|
|
||||||
self._tolerance = params['tolerance']
|
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
||||||
class NLIParams():
|
|
||||||
def __init__(self, params):
|
|
||||||
self._nli_method_name = params['nli_method_name']
|
|
||||||
self._wdm_grid_size = params['wdm_grid_size']
|
|
||||||
self._dispersion_tolerance = params['dispersion_tolerance']
|
|
||||||
self._phase_shift_tollerance = params['phase_shift_tollerance']
|
|
||||||
self._f_cut_resolution = None
|
|
||||||
self._f_pump_resolution = 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_tollerance(self):
|
|
||||||
return self._phase_shift_tollerance
|
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
||||||
class SimParams():
|
|
||||||
def __init__(self, params):
|
|
||||||
self._raman_computed_channels = params['raman_computed_channels']
|
|
||||||
self._raman_params = RamanParams(params=params['raman_parameters'])
|
|
||||||
self._nli_params = NLIParams(params=params['nli_parameters'])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def raman_computed_channels(self):
|
|
||||||
return self._raman_computed_channels
|
|
||||||
|
|
||||||
@property
|
|
||||||
def raman_params(self):
|
|
||||||
return self._raman_params
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nli_params(self):
|
|
||||||
return self._nli_params
|
|
||||||
|
|
||||||
class FiberParams():
|
|
||||||
def __init__(self, fiber):
|
|
||||||
self._loss_coef = 2 * fiber.dbkm_2_lin()[1]
|
|
||||||
self._length = fiber.length
|
|
||||||
self._gamma = fiber.gamma
|
|
||||||
self._beta2 = fiber.beta2()
|
|
||||||
self._beta3 = fiber.beta3 if hasattr(fiber, 'beta3') else 0
|
|
||||||
self._f_ref_beta = fiber.f_ref_beta if hasattr(fiber, 'f_ref_beta') else 0
|
|
||||||
self._raman_efficiency = fiber.params.raman_efficiency
|
|
||||||
self._temperature = fiber.operational['temperature']
|
|
||||||
|
|
||||||
@property
|
|
||||||
def loss_coef(self):
|
|
||||||
return self._loss_coef
|
|
||||||
|
|
||||||
@property
|
|
||||||
def length(self):
|
|
||||||
return self._length
|
|
||||||
|
|
||||||
@property
|
|
||||||
def gamma(self):
|
|
||||||
return self._gamma
|
|
||||||
|
|
||||||
@property
|
|
||||||
def beta2(self):
|
|
||||||
return self._beta2
|
|
||||||
|
|
||||||
@property
|
|
||||||
def beta3(self):
|
|
||||||
return self._beta3
|
|
||||||
|
|
||||||
@property
|
|
||||||
def f_ref_beta(self):
|
|
||||||
return self._f_ref_beta
|
|
||||||
|
|
||||||
@property
|
|
||||||
def raman_efficiency(self):
|
|
||||||
return self._raman_efficiency
|
|
||||||
|
|
||||||
@property
|
|
||||||
def temperature(self):
|
|
||||||
return self._temperature
|
|
||||||
|
|
||||||
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]
|
|
||||||
"""
|
|
||||||
if not hasattr(self.loss_coef, 'alpha_power'):
|
|
||||||
alpha0 = self.loss_coef
|
|
||||||
else:
|
|
||||||
alpha_interp = interp1d(self.loss_coef['frequency'],
|
|
||||||
self.loss_coef['alpha_power'])
|
|
||||||
alpha0 = alpha_interp(f_ref)
|
|
||||||
return alpha0
|
|
||||||
|
|
||||||
pump = namedtuple('RamanPump', 'power frequency propagation_direction')
|
|
||||||
|
|
||||||
def propagate_raman_fiber(fiber, *carriers):
|
def propagate_raman_fiber(fiber, *carriers):
|
||||||
sim_params = fiber.sim_params
|
simulation = Simulation.get_simulation()
|
||||||
raman_params = fiber.sim_params.raman_params
|
sim_params = simulation.sim_params
|
||||||
nli_params = fiber.sim_params.nli_params
|
raman_params = sim_params.raman_params
|
||||||
|
nli_params = sim_params.nli_params
|
||||||
# apply input attenuation to carriers
|
# apply input attenuation to carriers
|
||||||
attenuation_in = db2lin(fiber.con_in + fiber.att_in)
|
attenuation_in = db2lin(fiber.params.con_in + fiber.params.att_in)
|
||||||
chan = []
|
chan = []
|
||||||
for carrier in carriers:
|
for carrier in carriers:
|
||||||
pwr = carrier.power
|
pwr = carrier.power
|
||||||
@@ -166,36 +30,32 @@ def propagate_raman_fiber(fiber, *carriers):
|
|||||||
carrier = carrier._replace(power=pwr)
|
carrier = carrier._replace(power=pwr)
|
||||||
chan.append(carrier)
|
chan.append(carrier)
|
||||||
carriers = tuple(f for f in chan)
|
carriers = tuple(f for f in chan)
|
||||||
fiber_params = FiberParams(fiber)
|
|
||||||
|
|
||||||
# evaluate fiber attenuation involving also SRS if required by sim_params
|
# evaluate fiber attenuation involving also SRS if required by sim_params
|
||||||
if 'raman_pumps' in fiber.operational:
|
raman_solver = fiber.raman_solver
|
||||||
raman_pumps = tuple(pump(p['power'], p['frequency'], p['propagation_direction'])
|
raman_solver.carriers = carriers
|
||||||
for p in fiber.operational['raman_pumps'])
|
raman_solver.raman_pumps = fiber.raman_pumps
|
||||||
else:
|
stimulated_raman_scattering = raman_solver.stimulated_raman_scattering
|
||||||
raman_pumps = None
|
|
||||||
raman_solver = RamanSolver(raman_params=raman_params, fiber_params=fiber_params)
|
|
||||||
stimulated_raman_scattering = raman_solver.stimulated_raman_scattering(carriers=carriers,
|
|
||||||
raman_pumps=raman_pumps)
|
|
||||||
fiber_attenuation = (stimulated_raman_scattering.rho[:, -1])**-2
|
fiber_attenuation = (stimulated_raman_scattering.rho[:, -1])**-2
|
||||||
if not raman_params.flag_raman:
|
if not raman_params.flag_raman:
|
||||||
fiber_attenuation = tuple(fiber.lin_attenuation for _ in carriers)
|
fiber_attenuation = tuple(fiber.params.lin_attenuation for _ in carriers)
|
||||||
|
|
||||||
# evaluate Raman ASE noise if required by sim_params and if raman pumps are present
|
# evaluate Raman ASE noise if required by sim_params and if raman pumps are present
|
||||||
if raman_params.flag_raman and raman_pumps:
|
if raman_params.flag_raman and fiber.raman_pumps:
|
||||||
raman_ase = raman_solver.spontaneous_raman_scattering.power[:, -1]
|
raman_ase = raman_solver.spontaneous_raman_scattering.power[:, -1]
|
||||||
else:
|
else:
|
||||||
raman_ase = tuple(0 for _ in carriers)
|
raman_ase = tuple(0 for _ in carriers)
|
||||||
|
|
||||||
# evaluate nli and propagate in fiber
|
# evaluate nli and propagate in fiber
|
||||||
attenuation_out = db2lin(fiber.con_out)
|
attenuation_out = db2lin(fiber.params.con_out)
|
||||||
nli_solver = NliSolver(nli_params=nli_params, fiber_params=fiber_params)
|
nli_solver = fiber.nli_solver
|
||||||
nli_solver.stimulated_raman_scattering = stimulated_raman_scattering
|
nli_solver.stimulated_raman_scattering = stimulated_raman_scattering
|
||||||
|
|
||||||
nli_frequencies = []
|
nli_frequencies = []
|
||||||
computed_nli = []
|
computed_nli = []
|
||||||
for carrier in (c for c in carriers if c.channel_number in sim_params.raman_computed_channels):
|
for carrier in (c for c in carriers if c.channel_number in sim_params.nli_params.computed_channels):
|
||||||
resolution_param = frequency_resolution(carrier, carriers, sim_params, fiber_params)
|
resolution_param = frequency_resolution(carrier, carriers, sim_params, fiber)
|
||||||
f_cut_resolution, f_pump_resolution, _, _ = resolution_param
|
f_cut_resolution, f_pump_resolution, _, _ = resolution_param
|
||||||
nli_params.f_cut_resolution = f_cut_resolution
|
nli_params.f_cut_resolution = f_cut_resolution
|
||||||
nli_params.f_pump_resolution = f_pump_resolution
|
nli_params.f_pump_resolution = f_pump_resolution
|
||||||
@@ -212,7 +72,8 @@ def propagate_raman_fiber(fiber, *carriers):
|
|||||||
new_carriers.append(carrier._replace(power=pwr))
|
new_carriers.append(carrier._replace(power=pwr))
|
||||||
return new_carriers
|
return new_carriers
|
||||||
|
|
||||||
def frequency_resolution(carrier, carriers, sim_params, fiber_params):
|
|
||||||
|
def frequency_resolution(carrier, carriers, sim_params, fiber):
|
||||||
def _get_freq_res_k_phi(delta_count, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol):
|
def _get_freq_res_k_phi(delta_count, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol):
|
||||||
res_phi = _get_freq_res_phase_rotation(delta_count, grid_size, delta_z, beta2, phi_tol)
|
res_phi = _get_freq_res_phase_rotation(delta_count, grid_size, delta_z, beta2, phi_tol)
|
||||||
res_k = _get_freq_res_dispersion_attenuation(delta_count, grid_size, alpha0, beta2, k_tol)
|
res_k = _get_freq_res_dispersion_attenuation(delta_count, grid_size, alpha0, beta2, k_tol)
|
||||||
@@ -228,10 +89,10 @@ def frequency_resolution(carrier, carriers, sim_params, fiber_params):
|
|||||||
|
|
||||||
grid_size = sim_params.nli_params.wdm_grid_size
|
grid_size = sim_params.nli_params.wdm_grid_size
|
||||||
delta_z = sim_params.raman_params.space_resolution
|
delta_z = sim_params.raman_params.space_resolution
|
||||||
alpha0 = fiber_params.alpha0()
|
alpha0 = fiber.alpha0()
|
||||||
beta2 = fiber_params.beta2
|
beta2 = fiber.params.beta2
|
||||||
k_tol = sim_params.nli_params.dispersion_tolerance
|
k_tol = sim_params.nli_params.dispersion_tolerance
|
||||||
phi_tol = sim_params.nli_params.phase_shift_tollerance
|
phi_tol = sim_params.nli_params.phase_shift_tolerance
|
||||||
f_pump_resolution, method_f_pump, res_dict_pump = \
|
f_pump_resolution, method_f_pump, res_dict_pump = \
|
||||||
_get_freq_res_k_phi(0, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol)
|
_get_freq_res_k_phi(0, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol)
|
||||||
f_cut_resolution = {}
|
f_cut_resolution = {}
|
||||||
@@ -247,6 +108,7 @@ def frequency_resolution(carrier, carriers, sim_params, fiber_params):
|
|||||||
res_dict_cut[delta_number] = res_dict
|
res_dict_cut[delta_number] = res_dict
|
||||||
return [f_cut_resolution, f_pump_resolution, (method_f_cut, method_f_pump), (res_dict_cut, res_dict_pump)]
|
return [f_cut_resolution, f_pump_resolution, (method_f_cut, method_f_pump), (res_dict_cut, res_dict_pump)]
|
||||||
|
|
||||||
|
|
||||||
def raised_cosine_comb(f, *carriers):
|
def raised_cosine_comb(f, *carriers):
|
||||||
""" Returns an array storing the PSD of a WDM comb of raised cosine shaped
|
""" Returns an array storing the PSD of a WDM comb of raised cosine shaped
|
||||||
channels at the input frequencies defined in array f
|
channels at the input frequencies defined in array f
|
||||||
@@ -270,30 +132,59 @@ def raised_cosine_comb(f, *carriers):
|
|||||||
np.where(tf > 0, 1., 0.) * np.where(np.abs(ff) <= stopband, 1., 0.)) + psd
|
np.where(tf > 0, 1., 0.) * np.where(np.abs(ff) <= stopband, 1., 0.)) + psd
|
||||||
return psd
|
return psd
|
||||||
|
|
||||||
|
|
||||||
|
class Simulation:
|
||||||
|
_shared_dict = {}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
if type(self) == Simulation:
|
||||||
|
raise NotImplementedError('Simulation cannot be instatiated')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_params(cls, sim_params):
|
||||||
|
cls._shared_dict['sim_params'] = sim_params
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_simulation(cls):
|
||||||
|
self = cls.__new__(cls)
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sim_params(self):
|
||||||
|
return self._shared_dict['sim_params']
|
||||||
|
|
||||||
|
|
||||||
|
class SpontaneousRamanScattering:
|
||||||
|
def __init__(self, frequency, z, power):
|
||||||
|
self.frequency = frequency
|
||||||
|
self.z = z
|
||||||
|
self.power = power
|
||||||
|
|
||||||
|
|
||||||
|
class StimulatedRamanScattering:
|
||||||
|
def __init__(self, frequency, z, rho, power):
|
||||||
|
self.frequency = frequency
|
||||||
|
self.z = z
|
||||||
|
self.rho = rho
|
||||||
|
self.power = power
|
||||||
|
|
||||||
|
|
||||||
class RamanSolver:
|
class RamanSolver:
|
||||||
def __init__(self, raman_params=None, fiber_params=None):
|
def __init__(self, fiber=None):
|
||||||
""" Initialize the fiber object with its physical parameters
|
""" Initialize the Raman solver object.
|
||||||
:param length: fiber length in m.
|
:param fiber: instance of elements.py/Fiber.
|
||||||
:param alphap: fiber power attenuation coefficient vs frequency in 1/m. numpy array
|
:param carriers: tuple of carrier objects
|
||||||
:param freq_alpha: frequency axis of alphap in Hz. numpy array
|
:param raman_pumps: tuple containing pumps characteristics
|
||||||
:param cr_raman: Raman efficiency vs frequency offset in 1/W/m. numpy array
|
|
||||||
:param freq_cr: reference frequency offset axis for cr_raman. numpy array
|
|
||||||
:param raman_params: namedtuple containing the solver parameters (optional).
|
|
||||||
"""
|
"""
|
||||||
self.fiber_params = fiber_params
|
self._fiber = fiber
|
||||||
self.raman_params = raman_params
|
|
||||||
self._carriers = None
|
self._carriers = None
|
||||||
|
self._raman_pumps = None
|
||||||
self._stimulated_raman_scattering = None
|
self._stimulated_raman_scattering = None
|
||||||
self._spontaneous_raman_scattering = None
|
self._spontaneous_raman_scattering = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fiber_params(self):
|
def fiber(self):
|
||||||
return self._fiber_params
|
return self._fiber
|
||||||
|
|
||||||
@fiber_params.setter
|
|
||||||
def fiber_params(self, fiber_params):
|
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
self._fiber_params = fiber_params
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def carriers(self):
|
def carriers(self):
|
||||||
@@ -301,11 +192,8 @@ class RamanSolver:
|
|||||||
|
|
||||||
@carriers.setter
|
@carriers.setter
|
||||||
def carriers(self, carriers):
|
def carriers(self, carriers):
|
||||||
"""
|
|
||||||
:param carriers: tuple of namedtuples containing information about carriers
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._carriers = carriers
|
self._carriers = carriers
|
||||||
|
self._spontaneous_raman_scattering = None
|
||||||
self._stimulated_raman_scattering = None
|
self._stimulated_raman_scattering = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -318,62 +206,44 @@ class RamanSolver:
|
|||||||
self._stimulated_raman_scattering = None
|
self._stimulated_raman_scattering = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raman_params(self):
|
def stimulated_raman_scattering(self):
|
||||||
return self._raman_params
|
if self._stimulated_raman_scattering is None:
|
||||||
|
self.calculate_stimulated_raman_scattering(self.carriers, self.raman_pumps)
|
||||||
@raman_params.setter
|
return self._stimulated_raman_scattering
|
||||||
def raman_params(self, raman_params):
|
|
||||||
"""
|
|
||||||
:param raman_params: namedtuple containing the solver parameters (optional).
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._raman_params = raman_params
|
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
self._spontaneous_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def spontaneous_raman_scattering(self):
|
def spontaneous_raman_scattering(self):
|
||||||
if self._spontaneous_raman_scattering is None:
|
if self._spontaneous_raman_scattering is None:
|
||||||
# SET STUFF
|
self.calculate_spontaneous_raman_scattering(self.carriers, self.raman_pumps)
|
||||||
loss_coef = self.fiber_params.loss_coef
|
|
||||||
raman_efficiency = self.fiber_params.raman_efficiency
|
|
||||||
temperature = self.fiber_params.temperature
|
|
||||||
carriers = self.carriers
|
|
||||||
raman_pumps = self.raman_pumps
|
|
||||||
|
|
||||||
logger.debug('Start computing fiber Spontaneous Raman Scattering')
|
|
||||||
power_spectrum, freq_array, prop_direct, bn_array = self._compute_power_spectrum(carriers, raman_pumps)
|
|
||||||
|
|
||||||
if not hasattr(loss_coef, 'alpha_power'):
|
|
||||||
alphap_fiber = loss_coef * np.ones(freq_array.shape)
|
|
||||||
else:
|
|
||||||
interp_alphap = interp1d(loss_coef['frequency'], loss_coef['alpha_power'])
|
|
||||||
alphap_fiber = interp_alphap(freq_array)
|
|
||||||
|
|
||||||
freq_diff = abs(freq_array - np.reshape(freq_array, (len(freq_array), 1)))
|
|
||||||
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
|
||||||
cr = interp_cr(freq_diff)
|
|
||||||
|
|
||||||
# z propagation axis
|
|
||||||
z_array = self._stimulated_raman_scattering.z
|
|
||||||
ase_bc = np.zeros(freq_array.shape)
|
|
||||||
|
|
||||||
# calculate ase power
|
|
||||||
spontaneous_raman_scattering = self._int_spontaneous_raman(z_array, self._stimulated_raman_scattering.power,
|
|
||||||
alphap_fiber, freq_array, cr, freq_diff, ase_bc,
|
|
||||||
bn_array, temperature)
|
|
||||||
|
|
||||||
setattr(spontaneous_raman_scattering, 'frequency', freq_array)
|
|
||||||
setattr(spontaneous_raman_scattering, 'z', z_array)
|
|
||||||
setattr(spontaneous_raman_scattering, 'power', spontaneous_raman_scattering.x)
|
|
||||||
delattr(spontaneous_raman_scattering, 'x')
|
|
||||||
|
|
||||||
logger.debug(spontaneous_raman_scattering.message)
|
|
||||||
|
|
||||||
self._spontaneous_raman_scattering = spontaneous_raman_scattering
|
|
||||||
|
|
||||||
return self._spontaneous_raman_scattering
|
return self._spontaneous_raman_scattering
|
||||||
|
|
||||||
|
def calculate_spontaneous_raman_scattering(self, carriers, raman_pumps):
|
||||||
|
raman_efficiency = self.fiber.params.raman_efficiency
|
||||||
|
temperature = self.fiber.operational['temperature']
|
||||||
|
|
||||||
|
logger.debug('Start computing fiber Spontaneous Raman Scattering')
|
||||||
|
power_spectrum, freq_array, prop_direct, bn_array = self._compute_power_spectrum(carriers, raman_pumps)
|
||||||
|
|
||||||
|
alphap_fiber = self.fiber.alpha(freq_array)
|
||||||
|
|
||||||
|
freq_diff = abs(freq_array - np.reshape(freq_array, (len(freq_array), 1)))
|
||||||
|
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
||||||
|
cr = interp_cr(freq_diff)
|
||||||
|
|
||||||
|
# z propagation axis
|
||||||
|
z_array = self.stimulated_raman_scattering.z
|
||||||
|
ase_bc = np.zeros(freq_array.shape)
|
||||||
|
|
||||||
|
# calculate ase power
|
||||||
|
int_spontaneous_raman = self._int_spontaneous_raman(z_array, self._stimulated_raman_scattering.power,
|
||||||
|
alphap_fiber, freq_array, cr, freq_diff, ase_bc,
|
||||||
|
bn_array, temperature)
|
||||||
|
|
||||||
|
spontaneous_raman_scattering = SpontaneousRamanScattering(freq_array, z_array, int_spontaneous_raman.x)
|
||||||
|
logger.debug("Spontaneous Raman Scattering evaluated successfully")
|
||||||
|
self._spontaneous_raman_scattering = spontaneous_raman_scattering
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _compute_power_spectrum(carriers, raman_pumps=None):
|
def _compute_power_spectrum(carriers, raman_pumps=None):
|
||||||
"""
|
"""
|
||||||
@@ -412,10 +282,14 @@ class RamanSolver:
|
|||||||
|
|
||||||
return pow_array, f_array, propagation_direction, noise_bandwidth_array
|
return pow_array, f_array, propagation_direction, noise_bandwidth_array
|
||||||
|
|
||||||
def _int_spontaneous_raman(self, z_array, raman_matrix, alphap_fiber, freq_array, cr_raman_matrix, freq_diff, ase_bc, bn_array, temperature):
|
def _int_spontaneous_raman(self, z_array, raman_matrix, alphap_fiber, freq_array,
|
||||||
|
cr_raman_matrix, freq_diff, ase_bc, bn_array, temperature):
|
||||||
spontaneous_raman_scattering = OptimizeResult()
|
spontaneous_raman_scattering = OptimizeResult()
|
||||||
|
|
||||||
dx = self.raman_params.space_resolution
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
|
|
||||||
|
dx = sim_params.raman_params.space_resolution
|
||||||
h = ph.value('Planck constant')
|
h = ph.value('Planck constant')
|
||||||
kb = ph.value('Boltzmann constant')
|
kb = ph.value('Boltzmann constant')
|
||||||
|
|
||||||
@@ -428,12 +302,14 @@ class RamanSolver:
|
|||||||
eta = 1/(np.exp((h*freq_diff[f_ind, f_ind+1:])/(kb*temperature)) - 1)
|
eta = 1/(np.exp((h*freq_diff[f_ind, f_ind+1:])/(kb*temperature)) - 1)
|
||||||
|
|
||||||
int_fiber_loss = -alphap_fiber[f_ind] * z_array
|
int_fiber_loss = -alphap_fiber[f_ind] * z_array
|
||||||
int_raman_loss = np.sum((cr_raman[:f_ind] * vibrational_loss * int_pump[:f_ind, :].transpose()).transpose(), axis=0)
|
int_raman_loss = np.sum((cr_raman[:f_ind] * vibrational_loss * int_pump[:f_ind, :].transpose()).transpose(),
|
||||||
|
axis=0)
|
||||||
int_raman_gain = np.sum((cr_raman[f_ind + 1:] * int_pump[f_ind + 1:, :].transpose()).transpose(), axis=0)
|
int_raman_gain = np.sum((cr_raman[f_ind + 1:] * int_pump[f_ind + 1:, :].transpose()).transpose(), axis=0)
|
||||||
|
|
||||||
int_gain_loss = int_fiber_loss + int_raman_gain + int_raman_loss
|
int_gain_loss = int_fiber_loss + int_raman_gain + int_raman_loss
|
||||||
|
|
||||||
new_ase = np.sum((cr_raman[f_ind+1:] * (1 + eta) * raman_matrix[f_ind+1:, :].transpose()).transpose() * h * f_ase * bn_array[f_ind], axis=0)
|
new_ase = np.sum((cr_raman[f_ind+1:] * (1 + eta) * raman_matrix[f_ind+1:, :].transpose()).transpose()
|
||||||
|
* h * f_ase * bn_array[f_ind], axis=0)
|
||||||
|
|
||||||
bc_evolution = ase_bc[f_ind] * np.exp(int_gain_loss)
|
bc_evolution = ase_bc[f_ind] * np.exp(int_gain_loss)
|
||||||
ase_evolution = np.exp(int_gain_loss) * cumtrapz(new_ase*np.exp(-int_gain_loss), z_array, dx=dx, initial=0)
|
ase_evolution = np.exp(int_gain_loss) * cumtrapz(new_ase*np.exp(-int_gain_loss), z_array, dx=dx, initial=0)
|
||||||
@@ -441,69 +317,51 @@ class RamanSolver:
|
|||||||
power_ase[f_ind, :] = bc_evolution + ase_evolution
|
power_ase[f_ind, :] = bc_evolution + ase_evolution
|
||||||
|
|
||||||
spontaneous_raman_scattering.x = 2 * power_ase
|
spontaneous_raman_scattering.x = 2 * power_ase
|
||||||
spontaneous_raman_scattering.success = True
|
|
||||||
spontaneous_raman_scattering.message = "Spontaneous Raman Scattering evaluated successfully"
|
|
||||||
|
|
||||||
return spontaneous_raman_scattering
|
return spontaneous_raman_scattering
|
||||||
|
|
||||||
def stimulated_raman_scattering(self, carriers, raman_pumps=None):
|
def calculate_stimulated_raman_scattering(self, carriers, raman_pumps):
|
||||||
""" Returns stimulated Raman scattering solution including
|
""" Returns stimulated Raman scattering solution including
|
||||||
fiber gain/loss profile.
|
fiber gain/loss profile.
|
||||||
:return: self._stimulated_raman_scattering: the SRS problem solution.
|
:return: None
|
||||||
scipy.interpolate.PPoly instance
|
|
||||||
"""
|
"""
|
||||||
|
# fiber parameters
|
||||||
|
fiber_length = self.fiber.params.length
|
||||||
|
loss_coef = self.fiber.params.lin_loss_exp
|
||||||
|
raman_efficiency = self.fiber.params.raman_efficiency
|
||||||
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
|
|
||||||
if self._stimulated_raman_scattering is None:
|
if not sim_params.raman_params.flag_raman:
|
||||||
# fiber parameters
|
raman_efficiency['cr'] = np.zeros(len(raman_efficiency['cr']))
|
||||||
fiber_length = self.fiber_params.length
|
# raman solver parameters
|
||||||
loss_coef = self.fiber_params.loss_coef
|
z_resolution = sim_params.raman_params.space_resolution
|
||||||
if self.raman_params.flag_raman:
|
tolerance = sim_params.raman_params.tolerance
|
||||||
raman_efficiency = self.fiber_params.raman_efficiency
|
|
||||||
else:
|
|
||||||
raman_efficiency = self.fiber_params.raman_efficiency
|
|
||||||
raman_efficiency['cr'] = np.array(raman_efficiency['cr']) * 0
|
|
||||||
# raman solver parameters
|
|
||||||
z_resolution = self.raman_params.space_resolution
|
|
||||||
tolerance = self.raman_params.tolerance
|
|
||||||
|
|
||||||
logger.debug('Start computing fiber Stimulated Raman Scattering')
|
logger.debug('Start computing fiber Stimulated Raman Scattering')
|
||||||
|
|
||||||
power_spectrum, freq_array, prop_direct, _ = self._compute_power_spectrum(carriers, raman_pumps)
|
power_spectrum, freq_array, prop_direct, _ = self._compute_power_spectrum(carriers, raman_pumps)
|
||||||
|
|
||||||
if not hasattr(loss_coef, 'alpha_power'):
|
alphap_fiber = self.fiber.alpha(freq_array)
|
||||||
alphap_fiber = loss_coef * np.ones(freq_array.shape)
|
|
||||||
else:
|
|
||||||
interp_alphap = interp1d(loss_coef['frequency'], loss_coef['alpha_power'])
|
|
||||||
alphap_fiber = interp_alphap(freq_array)
|
|
||||||
|
|
||||||
freq_diff = abs(freq_array - np.reshape(freq_array, (len(freq_array), 1)))
|
freq_diff = abs(freq_array - np.reshape(freq_array, (len(freq_array), 1)))
|
||||||
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
||||||
cr = interp_cr(freq_diff)
|
cr = interp_cr(freq_diff)
|
||||||
|
|
||||||
# z propagation axis
|
# z propagation axis
|
||||||
z = np.arange(0, fiber_length+1, z_resolution)
|
z = np.arange(0, fiber_length + 1, z_resolution)
|
||||||
|
|
||||||
ode_function = lambda z, p: self._ode_stimulated_raman(z, p, alphap_fiber, freq_array, cr, prop_direct)
|
ode_function = lambda z, p: self._ode_stimulated_raman(z, p, alphap_fiber, freq_array, cr, prop_direct)
|
||||||
boundary_residual = lambda ya, yb: self._residuals_stimulated_raman(ya, yb, power_spectrum, prop_direct)
|
boundary_residual = lambda ya, yb: self._residuals_stimulated_raman(ya, yb, power_spectrum, prop_direct)
|
||||||
initial_guess_conditions = self._initial_guess_stimulated_raman(z, power_spectrum, alphap_fiber, prop_direct)
|
initial_guess_conditions = self._initial_guess_stimulated_raman(z, power_spectrum, alphap_fiber, prop_direct)
|
||||||
|
|
||||||
# ODE SOLVER
|
# ODE SOLVER
|
||||||
stimulated_raman_scattering = solve_bvp(ode_function, boundary_residual, z, initial_guess_conditions, tol=tolerance)
|
bvp_solution = solve_bvp(ode_function, boundary_residual, z, initial_guess_conditions, tol=tolerance)
|
||||||
|
|
||||||
rho = (stimulated_raman_scattering.y.transpose() / power_spectrum).transpose()
|
rho = (bvp_solution.y.transpose() / power_spectrum).transpose()
|
||||||
rho = np.sqrt(rho) # From power attenuation to field attenuation
|
rho = np.sqrt(rho) # From power attenuation to field attenuation
|
||||||
setattr(stimulated_raman_scattering, 'frequency', freq_array)
|
stimulated_raman_scattering = StimulatedRamanScattering(freq_array, bvp_solution.x, rho, bvp_solution.y)
|
||||||
setattr(stimulated_raman_scattering, 'z', stimulated_raman_scattering.x)
|
|
||||||
setattr(stimulated_raman_scattering, 'rho', rho)
|
|
||||||
setattr(stimulated_raman_scattering, 'power', stimulated_raman_scattering.y)
|
|
||||||
delattr(stimulated_raman_scattering, 'x')
|
|
||||||
delattr(stimulated_raman_scattering, 'y')
|
|
||||||
|
|
||||||
self.carriers = carriers
|
self._stimulated_raman_scattering = stimulated_raman_scattering
|
||||||
self.raman_pumps = raman_pumps
|
|
||||||
self._stimulated_raman_scattering = stimulated_raman_scattering
|
|
||||||
|
|
||||||
return self._stimulated_raman_scattering
|
|
||||||
|
|
||||||
def _residuals_stimulated_raman(self, ya, yb, power_spectrum, prop_direct):
|
def _residuals_stimulated_raman(self, ya, yb, power_spectrum, prop_direct):
|
||||||
|
|
||||||
@@ -520,11 +378,14 @@ class RamanSolver:
|
|||||||
def _initial_guess_stimulated_raman(self, z, power_spectrum, alphap_fiber, prop_direct):
|
def _initial_guess_stimulated_raman(self, z, power_spectrum, alphap_fiber, prop_direct):
|
||||||
""" Computes the initial guess knowing the boundary conditions
|
""" Computes the initial guess knowing the boundary conditions
|
||||||
:param z: patial axis [m]. numpy array
|
:param z: patial axis [m]. numpy array
|
||||||
:param power_spectrum: power in each frequency slice [W]. Frequency axis is defined by freq_array. numpy array
|
:param power_spectrum: power in each frequency slice [W].
|
||||||
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m]. Frequency defined by freq_array. numpy array
|
Frequency axis is defined by freq_array. numpy array
|
||||||
|
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m].
|
||||||
|
Frequency defined by freq_array. numpy array
|
||||||
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
||||||
+1 for forward propagation and -1 for backward propagation. Frequency defined by freq_array. numpy array
|
+1 for forward propagation and -1 for backward propagation. Frequency defined by freq_array. numpy array
|
||||||
:return: power_guess: guess on the initial conditions [W]. The first ndarray index identifies the frequency slice,
|
:return: power_guess: guess on the initial conditions [W].
|
||||||
|
The first ndarray index identifies the frequency slice,
|
||||||
the second ndarray index identifies the step in z. ndarray
|
the second ndarray index identifies the step in z. ndarray
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -538,14 +399,19 @@ class RamanSolver:
|
|||||||
return power_guess
|
return power_guess
|
||||||
|
|
||||||
def _ode_stimulated_raman(self, z, power_spectrum, alphap_fiber, freq_array, cr_raman_matrix, prop_direct):
|
def _ode_stimulated_raman(self, z, power_spectrum, alphap_fiber, freq_array, cr_raman_matrix, prop_direct):
|
||||||
""" Aim of ode_raman is to implement the set of ordinary differential equations (ODEs) describing the Raman effect.
|
""" Aim of ode_raman is to implement the set of ordinary differential equations (ODEs)
|
||||||
|
describing the Raman effect.
|
||||||
:param z: spatial axis (unused).
|
:param z: spatial axis (unused).
|
||||||
:param power_spectrum: power in each frequency slice [W]. Frequency axis is defined by freq_array. numpy array. Size n
|
:param power_spectrum: power in each frequency slice [W].
|
||||||
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m]. Frequency defined by freq_array. numpy array. Size n
|
Frequency axis is defined by freq_array. numpy array. Size n
|
||||||
|
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m].
|
||||||
|
Frequency defined by freq_array. numpy array. Size n
|
||||||
:param freq_array: reference frequency axis [Hz]. numpy array. Size n
|
:param freq_array: reference frequency axis [Hz]. numpy array. Size n
|
||||||
:param cr_raman: Cr(f) Raman gain efficiency variation in frequency [1/W/m]. Frequency defined by freq_array. numpy ndarray. Size nxn
|
:param cr_raman: Cr(f) Raman gain efficiency variation in frequency [1/W/m].
|
||||||
|
Frequency defined by freq_array. numpy ndarray. Size nxn
|
||||||
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
||||||
+1 for forward propagation and -1 for backward propagation. Frequency defined by freq_array. numpy array. Size n
|
+1 for forward propagation and -1 for backward propagation.
|
||||||
|
Frequency defined by freq_array. numpy array. Size n
|
||||||
:return: dP/dz: the power variation in dz [W/m]. numpy array. Size n
|
:return: dP/dz: the power variation in dz [W/m]. numpy array. Size n
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -563,28 +429,24 @@ class RamanSolver:
|
|||||||
|
|
||||||
return np.vstack(dpdz)
|
return np.vstack(dpdz)
|
||||||
|
|
||||||
|
|
||||||
class NliSolver:
|
class NliSolver:
|
||||||
""" This class implements the NLI models.
|
""" This class implements the NLI models.
|
||||||
Model and method can be specified in `self.nli_params.method`.
|
Model and method can be specified in `sim_params.nli_params.method`.
|
||||||
List of implemented methods:
|
List of implemented methods:
|
||||||
'gn_model_analytic': brute force triple integral solution
|
'gn_model_analytic': brute force triple integral solution
|
||||||
'ggn_spectrally_separated_xpm_spm': XPM plus SPM
|
'ggn_spectrally_separated_xpm_spm': XPM plus SPM
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, fiber=None):
|
||||||
def __init__(self, nli_params=None, fiber_params=None):
|
""" Initialize the Nli solver object.
|
||||||
""" Initialize the fiber object with its physical parameters
|
:param fiber: instance of elements.py/Fiber.
|
||||||
"""
|
"""
|
||||||
self.fiber_params = fiber_params
|
self._fiber = fiber
|
||||||
self.nli_params = nli_params
|
self._stimulated_raman_scattering = None
|
||||||
self.stimulated_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fiber_params(self):
|
def fiber(self):
|
||||||
return self._fiber_params
|
return self._fiber
|
||||||
|
|
||||||
@fiber_params.setter
|
|
||||||
def fiber_params(self, fiber_params):
|
|
||||||
self._fiber_params = fiber_params
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def stimulated_raman_scattering(self):
|
def stimulated_raman_scattering(self):
|
||||||
@@ -594,28 +456,19 @@ class NliSolver:
|
|||||||
def stimulated_raman_scattering(self, stimulated_raman_scattering):
|
def stimulated_raman_scattering(self, stimulated_raman_scattering):
|
||||||
self._stimulated_raman_scattering = stimulated_raman_scattering
|
self._stimulated_raman_scattering = stimulated_raman_scattering
|
||||||
|
|
||||||
@property
|
|
||||||
def nli_params(self):
|
|
||||||
return self._nli_params
|
|
||||||
|
|
||||||
@nli_params.setter
|
|
||||||
def nli_params(self, nli_params):
|
|
||||||
"""
|
|
||||||
:param model_params: namedtuple containing the parameters used to compute the NLI.
|
|
||||||
"""
|
|
||||||
self._nli_params = nli_params
|
|
||||||
|
|
||||||
def compute_nli(self, carrier, *carriers):
|
def compute_nli(self, carrier, *carriers):
|
||||||
""" Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
|
""" Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
|
||||||
at the end of the fiber span.
|
at the end of the fiber span.
|
||||||
"""
|
"""
|
||||||
if 'gn_model_analytic' == self.nli_params.nli_method_name.lower():
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
|
if 'gn_model_analytic' == sim_params.nli_params.nli_method_name.lower():
|
||||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
carrier_nli = self._gn_analytic(carrier, *carriers)
|
||||||
elif 'ggn_spectrally_separated' in self.nli_params.nli_method_name.lower():
|
elif 'ggn_spectrally_separated' in sim_params.nli_params.nli_method_name.lower():
|
||||||
eta_matrix = self._compute_eta_matrix(carrier, *carriers)
|
eta_matrix = self._compute_eta_matrix(carrier, *carriers)
|
||||||
carrier_nli = self._carrier_nli_from_eta_matrix(eta_matrix, carrier, *carriers)
|
carrier_nli = self._carrier_nli_from_eta_matrix(eta_matrix, carrier, *carriers)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'Method {self.nli_params.method_nli} not implemented.')
|
raise ValueError(f'Method {sim_params.nli_params.method_nli} not implemented.')
|
||||||
|
|
||||||
return carrier_nli
|
return carrier_nli
|
||||||
|
|
||||||
@@ -632,6 +485,8 @@ class NliSolver:
|
|||||||
|
|
||||||
def _compute_eta_matrix(self, carrier_cut, *carriers):
|
def _compute_eta_matrix(self, carrier_cut, *carriers):
|
||||||
cut_index = carrier_cut.channel_number - 1
|
cut_index = carrier_cut.channel_number - 1
|
||||||
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
# Matrix initialization
|
# Matrix initialization
|
||||||
matrix_size = max(carriers, key=lambda x: getattr(x, 'channel_number')).channel_number
|
matrix_size = max(carriers, key=lambda x: getattr(x, 'channel_number')).channel_number
|
||||||
eta_matrix = np.zeros(shape=(matrix_size, matrix_size))
|
eta_matrix = np.zeros(shape=(matrix_size, matrix_size))
|
||||||
@@ -639,10 +494,10 @@ class NliSolver:
|
|||||||
# SPM
|
# SPM
|
||||||
logger.debug(f'Start computing SPM on channel #{carrier_cut.channel_number}')
|
logger.debug(f'Start computing SPM on channel #{carrier_cut.channel_number}')
|
||||||
# SPM GGN
|
# SPM GGN
|
||||||
if 'ggn' in self.nli_params.nli_method_name.lower():
|
if 'ggn' in sim_params.nli_params.nli_method_name.lower():
|
||||||
partial_nli = self._generalized_spectrally_separated_spm(carrier_cut)
|
partial_nli = self._generalized_spectrally_separated_spm(carrier_cut)
|
||||||
# SPM GN
|
# SPM GN
|
||||||
elif 'gn' in self.nli_params.nli_method_name.lower():
|
elif 'gn' in sim_params.nli_params.nli_method_name.lower():
|
||||||
partial_nli = self._gn_analytic(carrier_cut, *[carrier_cut])
|
partial_nli = self._gn_analytic(carrier_cut, *[carrier_cut])
|
||||||
eta_matrix[cut_index, cut_index] = partial_nli / (carrier_cut.power.signal**3)
|
eta_matrix[cut_index, cut_index] = partial_nli / (carrier_cut.power.signal**3)
|
||||||
|
|
||||||
@@ -653,10 +508,10 @@ class NliSolver:
|
|||||||
logger.debug(f'Start computing XPM on channel #{carrier_cut.channel_number} '
|
logger.debug(f'Start computing XPM on channel #{carrier_cut.channel_number} '
|
||||||
f'from channel #{pump_carrier.channel_number}')
|
f'from channel #{pump_carrier.channel_number}')
|
||||||
# XPM GGN
|
# XPM GGN
|
||||||
if 'ggn' in self.nli_params.nli_method_name.lower():
|
if 'ggn' in sim_params.nli_params.nli_method_name.lower():
|
||||||
partial_nli = self._generalized_spectrally_separated_xpm(carrier_cut, pump_carrier)
|
partial_nli = self._generalized_spectrally_separated_xpm(carrier_cut, pump_carrier)
|
||||||
# XPM GGN
|
# XPM GGN
|
||||||
elif 'gn' in self.nli_params.nli_method_name.lower():
|
elif 'gn' in sim_params.nli_params.nli_method_name.lower():
|
||||||
partial_nli = self._gn_analytic(carrier_cut, *[pump_carrier])
|
partial_nli = self._gn_analytic(carrier_cut, *[pump_carrier])
|
||||||
eta_matrix[pump_index, pump_index] = partial_nli /\
|
eta_matrix[pump_index, pump_index] = partial_nli /\
|
||||||
(carrier_cut.power.signal * pump_carrier.power.signal**2)
|
(carrier_cut.power.signal * pump_carrier.power.signal**2)
|
||||||
@@ -670,47 +525,51 @@ class NliSolver:
|
|||||||
:param carriers: the full WDM comb
|
:param carriers: the full WDM comb
|
||||||
:return: carrier_nli: the amount of nonlinear interference in W on the carrier under analysis
|
:return: carrier_nli: the amount of nonlinear interference in W on the carrier under analysis
|
||||||
"""
|
"""
|
||||||
alpha = self.fiber_params.alpha0() / 2
|
beta2 = self.fiber.params.beta2
|
||||||
beta2 = self.fiber_params.beta2
|
gamma = self.fiber.params.gamma
|
||||||
gamma = self.fiber_params.gamma
|
effective_length = self.fiber.params.effective_length
|
||||||
length = self.fiber_params.length
|
asymptotic_length = self.fiber.params.asymptotic_length
|
||||||
effective_length = (1 - np.exp(-2 * alpha * length)) / (2 * alpha)
|
|
||||||
asymptotic_length = 1 / (2 * alpha)
|
|
||||||
|
|
||||||
g_nli = 0
|
g_nli = 0
|
||||||
for interfering_carrier in carriers:
|
for interfering_carrier in carriers:
|
||||||
g_interfearing = interfering_carrier.power.signal / interfering_carrier.baud_rate
|
g_interfearing = interfering_carrier.power.signal / interfering_carrier.baud_rate
|
||||||
g_signal = carrier.power.signal / carrier.baud_rate
|
g_signal = carrier.power.signal / carrier.baud_rate
|
||||||
g_nli += g_interfearing**2 * g_signal \
|
g_nli += g_interfearing**2 * g_signal \
|
||||||
* _psi(carrier, interfering_carrier, beta2=self.fiber_params.beta2, asymptotic_length=1/self.fiber_params.alpha0())
|
* _psi(carrier, interfering_carrier, beta2=beta2, asymptotic_length=asymptotic_length)
|
||||||
g_nli *= (16.0 / 27.0) * (gamma * effective_length)**2 /\
|
g_nli *= (16.0 / 27.0) * (gamma * effective_length) ** 2 /\
|
||||||
(2 * np.pi * abs(beta2) * asymptotic_length)
|
(2 * np.pi * abs(beta2) * asymptotic_length)
|
||||||
carrier_nli = carrier.baud_rate * g_nli
|
carrier_nli = carrier.baud_rate * g_nli
|
||||||
return carrier_nli
|
return carrier_nli
|
||||||
|
|
||||||
# Methods for computing the GGN-model
|
# Methods for computing the GGN-model
|
||||||
def _generalized_spectrally_separated_spm(self, carrier):
|
def _generalized_spectrally_separated_spm(self, carrier):
|
||||||
f_cut_resolution = self.nli_params.f_cut_resolution['delta_0']
|
gamma = self.fiber.params.gamma
|
||||||
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
|
f_cut_resolution = sim_params.nli_params.f_cut_resolution['delta_0']
|
||||||
f_eval = carrier.frequency
|
f_eval = carrier.frequency
|
||||||
g_cut = (carrier.power.signal / carrier.baud_rate)
|
g_cut = (carrier.power.signal / carrier.baud_rate)
|
||||||
|
|
||||||
spm_nli = carrier.baud_rate * (16.0 / 27.0) * self.fiber_params.gamma**2 * g_cut**3 * \
|
spm_nli = carrier.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_cut ** 3 * \
|
||||||
self._generalized_psi(carrier, carrier, f_eval, f_cut_resolution, f_cut_resolution)
|
self._generalized_psi(carrier, carrier, f_eval, f_cut_resolution, f_cut_resolution)
|
||||||
return spm_nli
|
return spm_nli
|
||||||
|
|
||||||
def _generalized_spectrally_separated_xpm(self, carrier_cut, pump_carrier):
|
def _generalized_spectrally_separated_xpm(self, carrier_cut, pump_carrier):
|
||||||
|
gamma = self.fiber.params.gamma
|
||||||
|
simulation = Simulation.get_simulation()
|
||||||
|
sim_params = simulation.sim_params
|
||||||
delta_index = pump_carrier.channel_number - carrier_cut.channel_number
|
delta_index = pump_carrier.channel_number - carrier_cut.channel_number
|
||||||
f_cut_resolution = self.nli_params.f_cut_resolution[f'delta_{delta_index}']
|
f_cut_resolution = sim_params.nli_params.f_cut_resolution[f'delta_{delta_index}']
|
||||||
f_pump_resolution = self.nli_params.f_pump_resolution
|
f_pump_resolution = sim_params.nli_params.f_pump_resolution
|
||||||
f_eval = carrier_cut.frequency
|
f_eval = carrier_cut.frequency
|
||||||
g_pump = (pump_carrier.power.signal / pump_carrier.baud_rate)
|
g_pump = (pump_carrier.power.signal / pump_carrier.baud_rate)
|
||||||
g_cut = (carrier_cut.power.signal / carrier_cut.baud_rate)
|
g_cut = (carrier_cut.power.signal / carrier_cut.baud_rate)
|
||||||
frequency_offset_threshold = self._frequency_offset_threshold(pump_carrier.baud_rate)
|
frequency_offset_threshold = self._frequency_offset_threshold(pump_carrier.baud_rate)
|
||||||
if abs(carrier_cut.frequency - pump_carrier.frequency) <= frequency_offset_threshold:
|
if abs(carrier_cut.frequency - pump_carrier.frequency) <= frequency_offset_threshold:
|
||||||
xpm_nli = carrier_cut.baud_rate * (16.0 / 27.0) * self.fiber_params.gamma**2 * g_pump**2 * g_cut * \
|
xpm_nli = carrier_cut.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_pump**2 * g_cut * \
|
||||||
2 * self._generalized_psi(carrier_cut, pump_carrier, f_eval, f_cut_resolution, f_pump_resolution)
|
2 * self._generalized_psi(carrier_cut, pump_carrier, f_eval, f_cut_resolution, f_pump_resolution)
|
||||||
else:
|
else:
|
||||||
xpm_nli = carrier_cut.baud_rate * (16.0 / 27.0) * self.fiber_params.gamma**2 * g_pump**2 * g_cut * \
|
xpm_nli = carrier_cut.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_pump**2 * g_cut * \
|
||||||
2 * self._fast_generalized_psi(carrier_cut, pump_carrier, f_eval, f_cut_resolution)
|
2 * self._fast_generalized_psi(carrier_cut, pump_carrier, f_eval, f_cut_resolution)
|
||||||
return xpm_nli
|
return xpm_nli
|
||||||
|
|
||||||
@@ -719,10 +578,10 @@ class NliSolver:
|
|||||||
:return: generalized_psi
|
:return: generalized_psi
|
||||||
"""
|
"""
|
||||||
# Fiber parameters
|
# Fiber parameters
|
||||||
alpha0 = self.fiber_params.alpha0(f_eval)
|
alpha0 = self.fiber.alpha0(f_eval)
|
||||||
beta2 = self.fiber_params.beta2
|
beta2 = self.fiber.params.beta2
|
||||||
beta3 = self.fiber_params.beta3
|
beta3 = self.fiber.params.beta3
|
||||||
f_ref_beta = self.fiber_params.f_ref_beta
|
f_ref_beta = self.fiber.params.ref_frequency
|
||||||
z = self.stimulated_raman_scattering.z
|
z = self.stimulated_raman_scattering.z
|
||||||
frequency_rho = self.stimulated_raman_scattering.frequency
|
frequency_rho = self.stimulated_raman_scattering.frequency
|
||||||
rho_norm = self.stimulated_raman_scattering.rho * np.exp(np.abs(alpha0) * z / 2)
|
rho_norm = self.stimulated_raman_scattering.rho * np.exp(np.abs(alpha0) * z / 2)
|
||||||
@@ -752,10 +611,10 @@ class NliSolver:
|
|||||||
:return: generalized_psi
|
:return: generalized_psi
|
||||||
"""
|
"""
|
||||||
# Fiber parameters
|
# Fiber parameters
|
||||||
alpha0 = self.fiber_params.alpha0(f_eval)
|
alpha0 = self.fiber.alpha0(f_eval)
|
||||||
beta2 = self.fiber_params.beta2
|
beta2 = self.fiber.params.beta2
|
||||||
beta3 = self.fiber_params.beta3
|
beta3 = self.fiber.params.beta3
|
||||||
f_ref_beta = self.fiber_params.f_ref_beta
|
f_ref_beta = self.fiber.params.ref_frequency
|
||||||
z = self.stimulated_raman_scattering.z
|
z = self.stimulated_raman_scattering.z
|
||||||
frequency_rho = self.stimulated_raman_scattering.frequency
|
frequency_rho = self.stimulated_raman_scattering.frequency
|
||||||
rho_norm = self.stimulated_raman_scattering.rho * np.exp(np.abs(alpha0) * z / 2)
|
rho_norm = self.stimulated_raman_scattering.rho * np.exp(np.abs(alpha0) * z / 2)
|
||||||
@@ -803,7 +662,8 @@ class NliSolver:
|
|||||||
beta2_ref = 21.3e-27
|
beta2_ref = 21.3e-27
|
||||||
delta_f_ref = 50e9
|
delta_f_ref = 50e9
|
||||||
rs_ref = 32e9
|
rs_ref = 32e9
|
||||||
freq_offset_th = ((k_ref * delta_f_ref) * rs_ref * beta2_ref) / (self.fiber_params.beta2 * symbol_rate)
|
beta2 = self.fiber.params.beta2
|
||||||
|
freq_offset_th = ((k_ref * delta_f_ref) * rs_ref * beta2_ref) / (beta2 * symbol_rate)
|
||||||
return freq_offset_th
|
return freq_offset_th
|
||||||
|
|
||||||
def _psi(carrier, interfering_carrier, beta2, asymptotic_length):
|
def _psi(carrier, interfering_carrier, beta2, asymptotic_length):
|
||||||
|
|||||||
@@ -544,7 +544,6 @@ Additional details of the simulation are controlled via ``sim_params.json``:
|
|||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"raman_computed_channels": [1, 18, 37, 56, 75],
|
|
||||||
"raman_parameters": {
|
"raman_parameters": {
|
||||||
"flag_raman": true,
|
"flag_raman": true,
|
||||||
"space_resolution": 10e3,
|
"space_resolution": 10e3,
|
||||||
@@ -554,6 +553,7 @@ Additional details of the simulation are controlled via ``sim_params.json``:
|
|||||||
"nli_method_name": "ggn_spectrally_separated",
|
"nli_method_name": "ggn_spectrally_separated",
|
||||||
"wdm_grid_size": 50e9,
|
"wdm_grid_size": 50e9,
|
||||||
"dispersion_tolerance": 1,
|
"dispersion_tolerance": 1,
|
||||||
"phase_shift_tollerance": 0.1
|
"phase_shift_tolerance": 0.1,
|
||||||
|
"computed_channels": [1, 18, 37, 56, 75]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"raman_computed_channels": [1, 18, 37, 56, 75],
|
|
||||||
"raman_parameters": {
|
"raman_parameters": {
|
||||||
"flag_raman": true,
|
"flag_raman": true,
|
||||||
"space_resolution": 10e3,
|
"space_resolution": 10e3,
|
||||||
"tolerance": 1e-8
|
"tolerance": 1e-8
|
||||||
},
|
},
|
||||||
"nli_parameters": {
|
"nli_parameters": {
|
||||||
"nli_method_name": "ggn_spectrally_separated",
|
"nli_method_name": "ggn_spectrally_separated",
|
||||||
"wdm_grid_size": 50e9,
|
"wdm_grid_size": 50e9,
|
||||||
"dispersion_tolerance": 1,
|
"dispersion_tolerance": 1,
|
||||||
"phase_shift_tollerance": 0.1
|
"phase_shift_tolerance": 0.1,
|
||||||
|
"computed_channels": [1, 18, 37, 56, 75]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,48 +251,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"uid": "roadm a",
|
|
||||||
"type": "Roadm",
|
|
||||||
"params": {
|
|
||||||
"target_pch_out_db": -20,
|
|
||||||
"restrictions": {
|
|
||||||
"preamp_variety_list": [],
|
|
||||||
"booster_variety_list": [
|
|
||||||
"std_booster"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 6.0,
|
|
||||||
"longitude": 0.0,
|
|
||||||
"city": "a",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "roadm b",
|
|
||||||
"type": "Roadm",
|
|
||||||
"params": {
|
|
||||||
"target_pch_out_db": -20,
|
|
||||||
"restrictions": {
|
|
||||||
"preamp_variety_list": [
|
|
||||||
"std_low_gain"
|
|
||||||
],
|
|
||||||
"booster_variety_list": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 5.0,
|
|
||||||
"longitude": 0.0,
|
|
||||||
"city": "b",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"uid": "roadm c",
|
"uid": "roadm c",
|
||||||
"type": "Roadm",
|
"type": "Roadm",
|
||||||
@@ -407,6 +365,48 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"uid": "roadm a",
|
||||||
|
"type": "Roadm",
|
||||||
|
"params": {
|
||||||
|
"target_pch_out_db": -20,
|
||||||
|
"restrictions": {
|
||||||
|
"preamp_variety_list": [],
|
||||||
|
"booster_variety_list": [
|
||||||
|
"std_booster"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 6.0,
|
||||||
|
"longitude": 0.0,
|
||||||
|
"city": "a",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "roadm b",
|
||||||
|
"type": "Roadm",
|
||||||
|
"params": {
|
||||||
|
"target_pch_out_db": -20,
|
||||||
|
"restrictions": {
|
||||||
|
"preamp_variety_list": [
|
||||||
|
"std_low_gain"
|
||||||
|
],
|
||||||
|
"booster_variety_list": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 5.0,
|
||||||
|
"longitude": 0.0,
|
||||||
|
"city": "b",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"uid": "west fused spans in Corlay",
|
"uid": "west fused spans in Corlay",
|
||||||
"type": "Fused",
|
"type": "Fused",
|
||||||
@@ -502,7 +502,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 20.0,
|
"length": 20.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -524,7 +523,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 50.0,
|
"length": 50.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -546,7 +544,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -568,7 +565,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 10.0,
|
"length": 10.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -590,7 +586,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -612,7 +607,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 65.0,
|
"length": 65.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -634,7 +628,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 40.0,
|
"length": 40.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -656,7 +649,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 35.0,
|
"length": 35.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -678,7 +670,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 75.0,
|
"length": 75.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -700,7 +691,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 70.0,
|
"length": 70.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -722,7 +712,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 50.0,
|
"length": 50.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -744,7 +733,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 55.0,
|
"length": 55.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -766,7 +754,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 30.0,
|
"length": 30.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -788,7 +775,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 30.0,
|
"length": 30.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -810,7 +796,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 10.0,
|
"length": 10.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -832,7 +817,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -854,7 +838,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 70.0,
|
"length": 70.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -876,7 +859,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 80.0,
|
"length": 80.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -898,7 +880,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 90.0,
|
"length": 90.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -920,7 +901,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 100.0,
|
"length": 100.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -942,7 +922,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 110.0,
|
"length": 110.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -964,7 +943,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 20.0,
|
"length": 20.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -986,7 +964,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 50.0,
|
"length": 50.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1008,7 +985,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1030,7 +1006,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 10.0,
|
"length": 10.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1052,7 +1027,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1074,7 +1048,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 65.0,
|
"length": 65.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1096,7 +1069,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 40.0,
|
"length": 40.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1118,7 +1090,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 35.0,
|
"length": 35.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1140,7 +1111,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 75.0,
|
"length": 75.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1162,7 +1132,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 70.0,
|
"length": 70.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1184,7 +1153,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 50.0,
|
"length": 50.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1206,7 +1174,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 55.0,
|
"length": 55.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1228,7 +1195,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 30.0,
|
"length": 30.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1250,7 +1216,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 30.0,
|
"length": 30.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1272,7 +1237,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 10.0,
|
"length": 10.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1294,7 +1258,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 60.0,
|
"length": 60.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1316,7 +1279,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 70.0,
|
"length": 70.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1338,7 +1300,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 80.0,
|
"length": 80.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1360,7 +1321,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 90.0,
|
"length": 90.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1382,7 +1342,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 100.0,
|
"length": 100.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1404,7 +1363,6 @@
|
|||||||
"type": "Fiber",
|
"type": "Fiber",
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"params": {
|
"params": {
|
||||||
"type_variety": "SSMF",
|
|
||||||
"length": 110.0,
|
"length": 110.0,
|
||||||
"loss_coef": 0.2,
|
"loss_coef": 0.2,
|
||||||
"length_units": "km",
|
"length_units": "km",
|
||||||
@@ -1459,25 +1417,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"uid": "east edfa in Stbrieuc to Rennes_STA",
|
|
||||||
"type": "Edfa",
|
|
||||||
"type_variety": "std_medium_gain",
|
|
||||||
"operational": {
|
|
||||||
"gain_target": 18.5,
|
|
||||||
"delta_p": null,
|
|
||||||
"tilt_target": 0,
|
|
||||||
"out_voa": 0
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 3.0,
|
|
||||||
"longitude": 0.0,
|
|
||||||
"city": "Stbrieuc",
|
|
||||||
"region": "RLD"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"uid": "east edfa in Lannion_CAS to Morlaix",
|
"uid": "east edfa in Lannion_CAS to Morlaix",
|
||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
@@ -1497,6 +1436,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"uid": "east edfa in Stbrieuc to Rennes_STA",
|
||||||
|
"type": "Edfa",
|
||||||
|
"type_variety": "std_medium_gain",
|
||||||
|
"operational": {
|
||||||
|
"gain_target": 18.5,
|
||||||
|
"delta_p": null,
|
||||||
|
"tilt_target": 0,
|
||||||
|
"out_voa": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 3.0,
|
||||||
|
"longitude": 0.0,
|
||||||
|
"city": "Stbrieuc",
|
||||||
|
"region": "RLD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"uid": "east edfa in Brest_KLA to Quimper",
|
"uid": "east edfa in Brest_KLA to Quimper",
|
||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
@@ -1593,7 +1551,7 @@
|
|||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
"type_variety": "test_fixed_gain",
|
"type_variety": "test_fixed_gain",
|
||||||
"operational": {
|
"operational": {
|
||||||
"gain_target": 20.0,
|
"gain_target": 20,
|
||||||
"delta_p": null,
|
"delta_p": null,
|
||||||
"tilt_target": 0,
|
"tilt_target": 0,
|
||||||
"out_voa": 0
|
"out_voa": 0
|
||||||
@@ -1612,7 +1570,7 @@
|
|||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
"type_variety": "test_fixed_gain",
|
"type_variety": "test_fixed_gain",
|
||||||
"operational": {
|
"operational": {
|
||||||
"gain_target": 20.0,
|
"gain_target": 20,
|
||||||
"delta_p": null,
|
"delta_p": null,
|
||||||
"tilt_target": 0,
|
"tilt_target": 0,
|
||||||
"out_voa": 0
|
"out_voa": 0
|
||||||
@@ -1740,88 +1698,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"uid": "Edfa0_roadm a",
|
|
||||||
"type": "Edfa",
|
|
||||||
"type_variety": "std_booster",
|
|
||||||
"operational": {
|
|
||||||
"gain_target": 20,
|
|
||||||
"delta_p": null,
|
|
||||||
"tilt_target": 0,
|
|
||||||
"out_voa": 0
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 5.75,
|
|
||||||
"longitude": 0.0,
|
|
||||||
"city": "a",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "Edfa1_roadm a",
|
|
||||||
"type": "Edfa",
|
|
||||||
"type_variety": "std_booster",
|
|
||||||
"operational": {
|
|
||||||
"gain_target": 20,
|
|
||||||
"delta_p": null,
|
|
||||||
"tilt_target": 0,
|
|
||||||
"out_voa": 0
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 6.0,
|
|
||||||
"longitude": 0.25,
|
|
||||||
"city": "a",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "Edfa0_roadm b",
|
|
||||||
"type": "Edfa",
|
|
||||||
"type_variety": "test_fixed_gain",
|
|
||||||
"operational": {
|
|
||||||
"gain_target": 20,
|
|
||||||
"delta_p": null,
|
|
||||||
"tilt_target": 0,
|
|
||||||
"out_voa": 0
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 5.25,
|
|
||||||
"longitude": 0.0,
|
|
||||||
"city": "b",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "Edfa1_roadm b",
|
|
||||||
"type": "Edfa",
|
|
||||||
"type_variety": "test_fixed_gain",
|
|
||||||
"operational": {
|
|
||||||
"gain_target": 20,
|
|
||||||
"delta_p": null,
|
|
||||||
"tilt_target": 0,
|
|
||||||
"out_voa": 0
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 5.0,
|
|
||||||
"longitude": 0.25,
|
|
||||||
"city": "b",
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"uid": "Edfa0_roadm c",
|
"uid": "Edfa0_roadm c",
|
||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
"type_variety": "test_fixed_gain",
|
"type_variety": "test_fixed_gain",
|
||||||
"operational": {
|
"operational": {
|
||||||
"gain_target": 22,
|
"gain_target": 22.0,
|
||||||
"delta_p": null,
|
"delta_p": null,
|
||||||
"tilt_target": 0,
|
"tilt_target": 0,
|
||||||
"out_voa": 0
|
"out_voa": 0
|
||||||
@@ -1840,7 +1722,7 @@
|
|||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
"type_variety": "test_fixed_gain",
|
"type_variety": "test_fixed_gain",
|
||||||
"operational": {
|
"operational": {
|
||||||
"gain_target": 22,
|
"gain_target": 22.0,
|
||||||
"delta_p": null,
|
"delta_p": null,
|
||||||
"tilt_target": 0,
|
"tilt_target": 0,
|
||||||
"out_voa": 0
|
"out_voa": 0
|
||||||
@@ -2063,6 +1945,82 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"uid": "Edfa0_roadm a",
|
||||||
|
"type": "Edfa",
|
||||||
|
"type_variety": "std_booster",
|
||||||
|
"operational": {
|
||||||
|
"gain_target": 20,
|
||||||
|
"delta_p": null,
|
||||||
|
"tilt_target": 0,
|
||||||
|
"out_voa": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 5.75,
|
||||||
|
"longitude": 0.0,
|
||||||
|
"city": "a",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "Edfa1_roadm a",
|
||||||
|
"type": "Edfa",
|
||||||
|
"type_variety": "std_booster",
|
||||||
|
"operational": {
|
||||||
|
"gain_target": 20,
|
||||||
|
"delta_p": null,
|
||||||
|
"tilt_target": 0,
|
||||||
|
"out_voa": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 6.0,
|
||||||
|
"longitude": 0.25,
|
||||||
|
"city": "a",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "Edfa0_roadm b",
|
||||||
|
"type": "Edfa",
|
||||||
|
"type_variety": "test_fixed_gain",
|
||||||
|
"operational": {
|
||||||
|
"gain_target": 20,
|
||||||
|
"delta_p": null,
|
||||||
|
"tilt_target": 0,
|
||||||
|
"out_voa": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 5.25,
|
||||||
|
"longitude": 0.0,
|
||||||
|
"city": "b",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "Edfa1_roadm b",
|
||||||
|
"type": "Edfa",
|
||||||
|
"type_variety": "test_fixed_gain",
|
||||||
|
"operational": {
|
||||||
|
"gain_target": 20,
|
||||||
|
"delta_p": null,
|
||||||
|
"tilt_target": 0,
|
||||||
|
"out_voa": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 5.0,
|
||||||
|
"longitude": 0.25,
|
||||||
|
"city": "b",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"uid": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
|
"uid": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
|
||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
@@ -2797,30 +2755,6 @@
|
|||||||
"from_node": "roadm c",
|
"from_node": "roadm c",
|
||||||
"to_node": "east edfa in c to d"
|
"to_node": "east edfa in c to d"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"from_node": "roadm a",
|
|
||||||
"to_node": "trx a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "roadm a",
|
|
||||||
"to_node": "Edfa0_roadm a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "roadm a",
|
|
||||||
"to_node": "Edfa1_roadm a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "roadm b",
|
|
||||||
"to_node": "trx b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "roadm b",
|
|
||||||
"to_node": "Edfa0_roadm b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "roadm b",
|
|
||||||
"to_node": "Edfa1_roadm b"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"from_node": "roadm c",
|
"from_node": "roadm c",
|
||||||
"to_node": "trx c"
|
"to_node": "trx c"
|
||||||
@@ -2897,6 +2831,30 @@
|
|||||||
"from_node": "roadm h",
|
"from_node": "roadm h",
|
||||||
"to_node": "Edfa1_roadm h"
|
"to_node": "Edfa1_roadm h"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm a",
|
||||||
|
"to_node": "trx a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm a",
|
||||||
|
"to_node": "Edfa0_roadm a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm a",
|
||||||
|
"to_node": "Edfa1_roadm a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm b",
|
||||||
|
"to_node": "trx b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm b",
|
||||||
|
"to_node": "Edfa0_roadm b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "roadm b",
|
||||||
|
"to_node": "Edfa1_roadm b"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"from_node": "west fused spans in Corlay",
|
"from_node": "west fused spans in Corlay",
|
||||||
"to_node": "fiber (Corlay → Loudeac)-F010"
|
"to_node": "fiber (Corlay → Loudeac)-F010"
|
||||||
@@ -3097,14 +3055,14 @@
|
|||||||
"from_node": "east edfa in Lannion_CAS to Stbrieuc",
|
"from_node": "east edfa in Lannion_CAS to Stbrieuc",
|
||||||
"to_node": "fiber (Lannion_CAS → Stbrieuc)-F056"
|
"to_node": "fiber (Lannion_CAS → Stbrieuc)-F056"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"from_node": "east edfa in Stbrieuc to Rennes_STA",
|
|
||||||
"to_node": "fiber (Stbrieuc → Rennes_STA)-F057"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"from_node": "east edfa in Lannion_CAS to Morlaix",
|
"from_node": "east edfa in Lannion_CAS to Morlaix",
|
||||||
"to_node": "fiber (Lannion_CAS → Morlaix)-F059"
|
"to_node": "fiber (Lannion_CAS → Morlaix)-F059"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from_node": "east edfa in Stbrieuc to Rennes_STA",
|
||||||
|
"to_node": "fiber (Stbrieuc → Rennes_STA)-F057"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"from_node": "east edfa in Brest_KLA to Quimper",
|
"from_node": "east edfa in Brest_KLA to Quimper",
|
||||||
"to_node": "fiber (Brest_KLA → Quimper)-"
|
"to_node": "fiber (Brest_KLA → Quimper)-"
|
||||||
@@ -3157,22 +3115,6 @@
|
|||||||
"from_node": "Edfa0_roadm Brest_KLA",
|
"from_node": "Edfa0_roadm Brest_KLA",
|
||||||
"to_node": "fiber (Brest_KLA → Morlaix)-F060"
|
"to_node": "fiber (Brest_KLA → Morlaix)-F060"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"from_node": "Edfa0_roadm a",
|
|
||||||
"to_node": "fiber (a → b)-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "Edfa1_roadm a",
|
|
||||||
"to_node": "fiber (a → c)-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "Edfa0_roadm b",
|
|
||||||
"to_node": "fiber (b → a)-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_node": "Edfa1_roadm b",
|
|
||||||
"to_node": "fiber (b → f)-"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"from_node": "Edfa0_roadm c",
|
"from_node": "Edfa0_roadm c",
|
||||||
"to_node": "fiber (c → a)-"
|
"to_node": "fiber (c → a)-"
|
||||||
@@ -3225,6 +3167,22 @@
|
|||||||
"from_node": "Edfa1_roadm h",
|
"from_node": "Edfa1_roadm h",
|
||||||
"to_node": "fiber (h → g)-"
|
"to_node": "fiber (h → g)-"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from_node": "Edfa0_roadm a",
|
||||||
|
"to_node": "fiber (a → b)-"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "Edfa1_roadm a",
|
||||||
|
"to_node": "fiber (a → c)-"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "Edfa0_roadm b",
|
||||||
|
"to_node": "fiber (b → a)-"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "Edfa1_roadm b",
|
||||||
|
"to_node": "fiber (b → f)-"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"from_node": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
|
"from_node": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
|
||||||
"to_node": "roadm Lorient_KMA"
|
"to_node": "roadm Lorient_KMA"
|
||||||
@@ -3354,4 +3312,4 @@
|
|||||||
"to_node": "roadm h"
|
"to_node": "roadm h"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
14
tests/data/test_sim_params.json
Normal file
14
tests/data/test_sim_params.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"raman_parameters": {
|
||||||
|
"flag_raman": true,
|
||||||
|
"space_resolution": 10e3,
|
||||||
|
"tolerance": 1e-8
|
||||||
|
},
|
||||||
|
"nli_parameters": {
|
||||||
|
"nli_method_name": "ggn_spectrally_separated",
|
||||||
|
"wdm_grid_size": 50e9,
|
||||||
|
"dispersion_tolerance": 1,
|
||||||
|
"phase_shift_tolerance": 0.1,
|
||||||
|
"raman_computed_channels": [1, 18, 37, 56, 75]
|
||||||
|
}
|
||||||
|
}
|
||||||
40
tests/test_parameters.py
Normal file
40
tests/test_parameters.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import json, pytest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from gnpy.core.parameters import SimParams
|
||||||
|
from gnpy.core.science_utils import Simulation
|
||||||
|
from gnpy.core.elements import Fiber
|
||||||
|
|
||||||
|
TEST_DIR = Path(__file__).parent
|
||||||
|
DATA_DIR = TEST_DIR / 'data'
|
||||||
|
|
||||||
|
def test_sim_parameters():
|
||||||
|
f = open(DATA_DIR / 'test_sim_params.json')
|
||||||
|
j = json.load(f)
|
||||||
|
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
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from logging import getLogger, basicConfig, INFO
|
||||||
|
logger = getLogger(__name__)
|
||||||
|
basicConfig(level=INFO)
|
||||||
|
|
||||||
|
test_sim_parameters()
|
||||||
|
|
||||||
|
print('\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -39,9 +39,9 @@ def propagation(input_power, con_in, con_out,dest):
|
|||||||
# (assumes all spans are identical)
|
# (assumes all spans are identical)
|
||||||
for e in network.nodes():
|
for e in network.nodes():
|
||||||
if isinstance(e, Fiber):
|
if isinstance(e, Fiber):
|
||||||
loss = e.loss_coef * e.length
|
loss = e.params.loss_coef * e.params.length
|
||||||
e.con_in = con_in
|
e.params.con_in = con_in
|
||||||
e.con_out = con_out
|
e.params.con_out = con_out
|
||||||
if isinstance(e, Edfa):
|
if isinstance(e, Edfa):
|
||||||
e.operational.gain_target = loss + con_in + con_out
|
e.operational.gain_target = loss + con_in + con_out
|
||||||
|
|
||||||
@@ -63,30 +63,30 @@ def propagation(input_power, con_in, con_out,dest):
|
|||||||
print(f'pw: {input_power} conn in: {con_in} con out: {con_out}',
|
print(f'pw: {input_power} conn in: {con_in} con out: {con_out}',
|
||||||
f'OSNR@0.1nm: {round(mean(sink.osnr_ase_01nm),2)}',
|
f'OSNR@0.1nm: {round(mean(sink.osnr_ase_01nm),2)}',
|
||||||
f'SNR@bandwitdth: {round(mean(sink.snr),2)}')
|
f'SNR@bandwitdth: {round(mean(sink.snr),2)}')
|
||||||
return sink , nf
|
return sink, nf
|
||||||
|
|
||||||
test = {'a':(-1,1,0),'b':(-1,1,1),'c':(0,1,0),'d':(1,1,1)}
|
test = {'a':(-1,1,0),'b':(-1,1,1),'c':(0,1,0),'d':(1,1,1)}
|
||||||
expected = {'a':(-2,0,0),'b':(-2,0,1),'c':(-1,0,0),'d':(0,0,1)}
|
expected = {'a': (-2, 0, 0), 'b': (-2, 0, 1), 'c': (-1, 0, 0), 'd': (0, 0, 1)}
|
||||||
|
|
||||||
@pytest.mark.parametrize("dest",['trx B','trx F'])
|
@pytest.mark.parametrize("dest",['trx B','trx F'])
|
||||||
@pytest.mark.parametrize("osnr_test", ['a','b','c','d'])
|
@pytest.mark.parametrize("osnr_test", ['a', 'b', 'c', 'd'])
|
||||||
def test_snr(osnr_test, dest):
|
def test_snr(osnr_test, dest):
|
||||||
pw = test[osnr_test][0]
|
pw = test[osnr_test][0]
|
||||||
conn_in = test[osnr_test][1]
|
conn_in = test[osnr_test][1]
|
||||||
conn_out =test[osnr_test][2]
|
conn_out = test[osnr_test][2]
|
||||||
sink,nf = propagation(pw,conn_in,conn_out,dest)
|
sink, nf = propagation(pw, conn_in, conn_out, dest)
|
||||||
osnr = round(mean(sink.osnr_ase),3)
|
osnr = round(mean(sink.osnr_ase), 3)
|
||||||
nli = 1.0/db2lin(round(mean(sink.snr),3)) - 1.0/db2lin(osnr)
|
nli = 1.0/db2lin(round(mean(sink.snr), 3)) - 1.0/db2lin(osnr)
|
||||||
pw = expected[osnr_test][0]
|
pw = expected[osnr_test][0]
|
||||||
conn_in = expected[osnr_test][1]
|
conn_in = expected[osnr_test][1]
|
||||||
conn_out = expected[osnr_test][2]
|
conn_out = expected[osnr_test][2]
|
||||||
sink,exp_nf = propagation(pw,conn_in,conn_out,dest)
|
sink,exp_nf = propagation(pw, conn_in, conn_out, dest)
|
||||||
expected_osnr = round(mean(sink.osnr_ase),3)
|
expected_osnr = round(mean(sink.osnr_ase), 3)
|
||||||
expected_nli = 1.0/db2lin(round(mean(sink.snr),3)) - 1.0/db2lin(expected_osnr)
|
expected_nli = 1.0/db2lin(round(mean(sink.snr), 3)) - 1.0/db2lin(expected_osnr)
|
||||||
# compare OSNR taking into account nf change of amps
|
# compare OSNR taking into account nf change of amps
|
||||||
osnr_diff = abs(osnr - expected_osnr + nf - exp_nf)
|
osnr_diff = abs(osnr - expected_osnr + nf - exp_nf)
|
||||||
nli_diff = abs((nli-expected_nli)/nli)
|
nli_diff = abs((nli-expected_nli)/nli)
|
||||||
assert osnr_diff <0.01 and nli_diff<0.01
|
assert osnr_diff < 0.01 and nli_diff < 0.01
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@@ -94,6 +94,6 @@ if __name__ == '__main__':
|
|||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
basicConfig(level=INFO)
|
basicConfig(level=INFO)
|
||||||
|
|
||||||
for a in test :
|
for a in test:
|
||||||
test_snr(a,'trx F')
|
test_snr(a, 'trx F')
|
||||||
print('\n')
|
print('\n')
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ from pandas import read_csv
|
|||||||
from numpy.testing import assert_allclose
|
from numpy.testing import assert_allclose
|
||||||
from gnpy.core.info import create_input_spectral_information
|
from gnpy.core.info import create_input_spectral_information
|
||||||
from gnpy.core.elements import RamanFiber
|
from gnpy.core.elements import RamanFiber
|
||||||
from gnpy.core.network import load_sim_params
|
from gnpy.core.parameters import SimParams
|
||||||
|
from gnpy.core.science_utils import Simulation
|
||||||
|
from gnpy.core.utils import load_json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
TEST_DIR = Path(__file__).parent
|
TEST_DIR = Path(__file__).parent
|
||||||
|
|
||||||
@@ -29,12 +31,9 @@ def test_raman_fiber():
|
|||||||
spectral_info_params.pop('sys_margins')
|
spectral_info_params.pop('sys_margins')
|
||||||
spectral_info_input = create_input_spectral_information(power=power, **spectral_info_params)
|
spectral_info_input = create_input_spectral_information(power=power, **spectral_info_params)
|
||||||
|
|
||||||
# RamanFiber
|
sim_params = SimParams(**load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||||
with open(TEST_DIR / 'data' / 'raman_fiber_config.json', 'r') as file:
|
Simulation.set_params(sim_params)
|
||||||
raman_fiber_params = json.load(file)
|
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'raman_fiber_config.json'))
|
||||||
sim_params = load_sim_params(TEST_DIR / 'data' / 'sim_params.json')
|
|
||||||
fiber = RamanFiber(**raman_fiber_params)
|
|
||||||
fiber.sim_params = sim_params
|
|
||||||
|
|
||||||
# propagation
|
# propagation
|
||||||
spectral_info_out = fiber(spectral_info_input)
|
spectral_info_out = fiber(spectral_info_input)
|
||||||
|
|||||||
Reference in New Issue
Block a user