Add per degree channel power target out

- add the per degree info using the EXACT next node uid as identifier
  of the degree when a node is a roadm
- add the degree identifier on the propagate and on the call functions
- use the per degree target_pch_out_db defined in json entry for the
  target power in network build
- verifies existence of the per degree power target in order to support
  partial per degree target power definition
- correct test data files for expected auto design results that now
  should include the per degree information, even if it is the same
  for all degree.
- in order to enable per degree power definition on direction where
  booster is not defined, enable the declaration of edfas in json without
  specifying type variety

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5004cbb250ca5fd6b6498ac9d4b9c4f28a65efee
This commit is contained in:
EstherLerouzic
2019-10-28 16:29:14 +00:00
committed by Jan Kundrát
parent a5398a5c57
commit c56ea898a6
6 changed files with 582 additions and 19 deletions

View File

@@ -184,17 +184,20 @@ class Transceiver(_Node):
return spectral_info
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr pmd restrictions')
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr pmd restrictions per_degree_pch_out_db')
class Roadm(_Node):
def __init__(self, *args, params, **kwargs):
if 'per_degree_pch_out_db' not in params.keys():
params['per_degree_pch_out_db'] = {}
super().__init__(*args, params=RoadmParams(**params), **kwargs)
self.loss = 0 # auto-design interest
self.effective_loss = None
self.effective_pch_out_db = self.params.target_pch_out_db
self.passive = True
self.restrictions = self.params.restrictions
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db
@property
def to_json(self):
@@ -202,8 +205,9 @@ class Roadm(_Node):
'type': type(self).__name__,
'params': {
'target_pch_out_db': self.effective_pch_out_db,
'restrictions': self.restrictions
},
'restrictions': self.restrictions,
'per_degree_pch_out_db': self.per_degree_pch_out_db
},
'metadata': {
'location': self.metadata['location']._asdict()
}
@@ -220,15 +224,21 @@ class Roadm(_Node):
f' effective loss (dB): {self.effective_loss:.2f}',
f' pch out (dBm): {self.effective_pch_out_db!r}'])
def propagate(self, pref, *carriers):
def propagate(self, pref, *carriers, degree):
# pin_target and loss are read from eqpt_config.json['Roadm']
# all ingress channels in xpress are set to this power level
# but add channels are not, so we define an effective loss
# in the case of add channels
self.effective_pch_out_db = min(pref.p_spani, self.params.target_pch_out_db)
# find the target power on this degree:
# if a target power has been defined for this degree use it else use the global one.
# if the input power is lower than the target one, use the input power instead because
# a ROADM doesn't amplify, it can only attenuate
# TODO maybe add a minimum loss for the ROADM
per_degree_pch = self.per_degree_pch_out_db[degree] if degree in self.per_degree_pch_out_db.keys() else self.params.target_pch_out_db
self.effective_pch_out_db = min(pref.p_spani, per_degree_pch)
self.effective_loss = pref.p_spani - self.effective_pch_out_db
carriers_power = array([c.power.signal + c.power.nli + c.power.ase for c in carriers])
carriers_att = list(map(lambda x: lin2db(x * 1e3) - self.params.target_pch_out_db, carriers_power))
carriers_att = list(map(lambda x: lin2db(x * 1e3) - per_degree_pch, carriers_power))
exceeding_att = -min(list(filter(lambda x: x < 0, carriers_att)), default=0)
carriers_att = list(map(lambda x: db2lin(x + exceeding_att), carriers_att))
for carrier_att, carrier in zip(carriers_att, carriers):
@@ -242,8 +252,8 @@ class Roadm(_Node):
def update_pref(self, pref):
return pref._replace(p_span0=pref.p_span0, p_spani=self.effective_pch_out_db)
def __call__(self, spectral_info):
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers))
def __call__(self, spectral_info, degree):
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers, degree=degree))
pref = self.update_pref(spectral_info.pref)
return spectral_info._replace(carriers=carriers, pref=pref)

View File

@@ -239,18 +239,34 @@ def set_amplifier_voa(amp, power_target, power_mode):
amp.out_voa = voa
def set_egress_amplifier(network, roadm, equipment, pref_total_db):
def set_egress_amplifier(network, this_node, equipment, pref_total_db):
""" this node can be a transceiver or a ROADM (same function called in both cases)
"""
power_mode = equipment['Span']['default'].power_mode
next_oms = (n for n in network.successors(roadm) if not isinstance(n, elements.Transceiver))
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()} if hasattr(this_node, 'per_degree_pch_out_db') else {}
for oms in next_oms:
# go through all the OMS departing from the Roadm
prev_node = roadm
# go through all the OMS departing from the ROADM
prev_node = this_node
node = oms
# if isinstance(next_node, elements.Fused): #support ROADM wo egress amp for metro applications
# node = find_last_node(next_node)
# next_node = next(n for n in network.successors(node))
# next_node = find_last_node(next_node)
prev_dp = getattr(roadm.params, 'target_pch_out_db', 0)
if this_node_degree:
# find the target power on this degree
if node.uid in this_node_degree.keys():
prev_dp = this_node_degree[node.uid]
else:
# if no target power is defined on this degree use the global one
# if target_pch_out_db is not an attribute, then the element must be a transceiver
prev_dp = getattr(this_node.params, 'target_pch_out_db', 0)
this_node_degree[node.uid] = prev_dp
else:
# if no per degree target power is given use the global one
# if target_pch_out_db is not an attribute, then the element must be a transceiver
prev_dp = getattr(this_node.params, 'target_pch_out_db', 0)
this_node_degree[node.uid] = prev_dp
dp = prev_dp
prev_voa = 0
voa = 0
@@ -313,6 +329,8 @@ def set_egress_amplifier(network, roadm, equipment, pref_total_db):
node = next_node
# print(f'{node.uid}')
if isinstance(this_node, elements.Roadm):
this_node.per_degree_pch_out_db = {k: v for k, v in this_node_degree.items()}
def add_egress_amplifier(network, node):
next_nodes = [n for n in network.successors(node)

View File

@@ -349,7 +349,7 @@ def network_from_json(json_data, equipment):
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
el_config['params'] = temp
el_config['type_variety'] = variety
elif typ in ['Edfa', 'Fiber', 'RamanFiber']: # catch it now because the code will crash later!
elif typ in ['Fiber', 'RamanFiber']: # catch it now because the code will crash later!
raise ConfigurationError(f'The {typ} of variety type {variety} was not recognized:'
'\nplease check it is properly defined in the eqpt_config json file')
el = cls(**el_config)

View File

@@ -333,8 +333,11 @@ def propagate(path, req, equipment):
si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate,
req.power, req.spacing)
for el in path:
si = el(si)
for i, el in enumerate(path):
if isinstance(el, Roadm):
si = el(si, degree=path[i+1].uid)
else:
si = el(si)
path[0].update_snr(req.tx_osnr)
if any(isinstance(el, Roadm) for el in path):
path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
@@ -366,8 +369,11 @@ def propagate_and_optimize_mode(path, req, equipment):
spc_info = create_input_spectral_information(req.f_min, req.f_max,
equipment['SI']['default'].roll_off,
this_br, req.power, req.spacing)
for el in path:
spc_info = el(spc_info)
for i, el in enumerate(path):
if isinstance(el, Roadm):
spc_info = el(spc_info, degree=path[i+1].uid)
else:
spc_info = el(spc_info)
for this_mode in modes_to_explore:
if path[-1].snr is not None:
path[0].update_snr(this_mode['tx_osnr'])

File diff suppressed because it is too large Load Diff

View File

@@ -164,6 +164,11 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"east edfa in Lannion_CAS to Corlay": -20,
"east edfa in Lannion_CAS to Stbrieuc": -20,
"east edfa in Lannion_CAS to Morlaix": -20
}
},
"metadata": {
@@ -183,6 +188,11 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm Lorient_KMA": -20,
"Edfa1_roadm Lorient_KMA": -20,
"Edfa2_roadm Lorient_KMA": -20
}
},
"metadata": {
@@ -202,6 +212,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm Vannes_KBE": -20,
"Edfa1_roadm Vannes_KBE": -20
}
},
"metadata": {
@@ -221,7 +235,12 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm Rennes_STA": -20,
"Edfa1_roadm Rennes_STA": -20
}
},
"metadata": {
"location": {
@@ -240,6 +259,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"east edfa in Brest_KLA to Quimper": -20,
"Edfa0_roadm Brest_KLA": -20
}
},
"metadata": {
@@ -259,6 +282,11 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"east edfa in c to d": -20,
"Edfa0_roadm c": -20,
"Edfa1_roadm c": -20
}
},
"metadata": {
@@ -278,6 +306,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db":{
"Edfa0_roadm d": -20,
"Edfa1_roadm d": -20
}
},
"metadata": {
@@ -297,6 +329,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db":{
"Edfa0_roadm e": -20,
"Edfa1_roadm e": -20
}
},
"metadata": {
@@ -316,6 +352,11 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm f": -20,
"Edfa1_roadm f": -20,
"Edfa2_roadm f": -20
}
},
"metadata": {
@@ -335,6 +376,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm g": -20,
"Edfa1_roadm g": -20
}
},
"metadata": {
@@ -354,6 +399,10 @@
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm h": -20,
"Edfa1_roadm h": -20
}
},
"metadata": {
@@ -375,7 +424,11 @@
"booster_variety_list": [
"std_booster"
]
}
},
"per_degree_pch_out_db": {
"Edfa0_roadm a": -20,
"Edfa1_roadm a": -20
}
},
"metadata": {
"location": {
@@ -396,6 +449,10 @@
"std_low_gain"
],
"booster_variety_list": []
},
"per_degree_pch_out_db": {
"Edfa0_roadm b": -20,
"Edfa1_roadm b": -20
}
},
"metadata": {