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:
AndreaDAmico
2019-12-16 18:45:10 +01:00
committed by Jan Kundrát
parent 2960d307fa
commit 80eced85ec
16 changed files with 3394 additions and 7366 deletions

View File

@@ -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",

View File

@@ -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]
} }
} }

View File

@@ -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)

View File

@@ -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
@@ -489,12 +428,10 @@ class EdfaParams:
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,

View File

@@ -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'''

View File

@@ -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,7 +55,8 @@ 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)
@@ -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,16 +452,14 @@ 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})',
type_variety=fiber.type_variety,
metadata={ metadata={
'location': { 'location': {
'latitude': lat, 'latitude': lat,
@@ -470,7 +468,7 @@ 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:
@@ -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

View File

@@ -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):

View File

@@ -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,61 +206,43 @@ 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 return self._spontaneous_raman_scattering
raman_efficiency = self.fiber_params.raman_efficiency
temperature = self.fiber_params.temperature def calculate_spontaneous_raman_scattering(self, carriers, raman_pumps):
carriers = self.carriers raman_efficiency = self.fiber.params.raman_efficiency
raman_pumps = self.raman_pumps temperature = self.fiber.operational['temperature']
logger.debug('Start computing fiber Spontaneous Raman Scattering') logger.debug('Start computing fiber Spontaneous Raman Scattering')
power_spectrum, freq_array, prop_direct, bn_array = self._compute_power_spectrum(carriers, raman_pumps) power_spectrum, freq_array, prop_direct, bn_array = 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_array = self._stimulated_raman_scattering.z z_array = self.stimulated_raman_scattering.z
ase_bc = np.zeros(freq_array.shape) ase_bc = np.zeros(freq_array.shape)
# calculate ase power # calculate ase power
spontaneous_raman_scattering = self._int_spontaneous_raman(z_array, self._stimulated_raman_scattering.power, int_spontaneous_raman = self._int_spontaneous_raman(z_array, self._stimulated_raman_scattering.power,
alphap_fiber, freq_array, cr, freq_diff, ase_bc, alphap_fiber, freq_array, cr, freq_diff, ase_bc,
bn_array, temperature) bn_array, temperature)
setattr(spontaneous_raman_scattering, 'frequency', freq_array) spontaneous_raman_scattering = SpontaneousRamanScattering(freq_array, z_array, int_spontaneous_raman.x)
setattr(spontaneous_raman_scattering, 'z', z_array) logger.debug("Spontaneous Raman Scattering evaluated successfully")
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 self._spontaneous_raman_scattering = spontaneous_raman_scattering
return self._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,40 +317,31 @@ 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
""" """
if self._stimulated_raman_scattering is None:
# fiber parameters # fiber parameters
fiber_length = self.fiber_params.length fiber_length = self.fiber.params.length
loss_coef = self.fiber_params.loss_coef loss_coef = self.fiber.params.lin_loss_exp
if self.raman_params.flag_raman: raman_efficiency = self.fiber.params.raman_efficiency
raman_efficiency = self.fiber_params.raman_efficiency simulation = Simulation.get_simulation()
else: sim_params = simulation.sim_params
raman_efficiency = self.fiber_params.raman_efficiency
raman_efficiency['cr'] = np.array(raman_efficiency['cr']) * 0 if not sim_params.raman_params.flag_raman:
raman_efficiency['cr'] = np.zeros(len(raman_efficiency['cr']))
# raman solver parameters # raman solver parameters
z_resolution = self.raman_params.space_resolution z_resolution = sim_params.raman_params.space_resolution
tolerance = self.raman_params.tolerance tolerance = sim_params.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'])
@@ -488,23 +355,14 @@ class RamanSolver:
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.raman_pumps = raman_pumps
self._stimulated_raman_scattering = stimulated_raman_scattering 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):
computed_boundary_value = np.zeros(ya.size) computed_boundary_value = np.zeros(ya.size)
@@ -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,19 +525,17 @@ 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
@@ -690,27 +543,33 @@ class NliSolver:
# 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):

View File

@@ -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

View File

@@ -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]
} }
} }

View File

@@ -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"

View 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
View 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')

View File

@@ -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

View File

@@ -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)