Refactor: create a function to set one single band amplifier

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I00018c38b0cc0ceefcd21d50dd0cdc639019cc70
This commit is contained in:
EstherLerouzic
2024-06-21 13:55:44 +02:00
committed by Esther Le Rouzic
parent 0813332adc
commit c384af8062

View File

@@ -398,42 +398,31 @@ def check_oms_single_type(oms_edges: List[Tuple]) -> List[str]:
return list(types)
def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_db, verbose):
"""This node can be a transceiver or a ROADM (same function called in both cases).
go through each link staring from this_node until next Roadm or Transceiver and
set gain and delta_p according to configurations set by user.
power_mode = True, set amplifiers delta_p and effective_gain
power_mode = False, set amplifiers effective_gain and ignore delta_p config: set it to None
def set_one_amplifier(node: elements.Edfa, prev_node, next_node, power_mode: bool, prev_voa: float, prev_dp: float,
pref_ch_db: float, pref_total_db: float, network: DiGraph, equipment: dict, verbose: bool) \
-> Tuple[float, float]:
"""Set the EDFA amplifier configuration based on power targets:
This function adjusts the amplifier settings according to the specified parameters and
ensures compliance with power and gain targets. It handles both cases where the
amplifier type is specified or needs to be selected based on restrictions.
Args:
node (elements.Edfa): The EDFA amplifier node to configure.
prev_node (elements.Node): The previous node in the network.
next_node (elements.Node): The next node in the network.
power_mode (bool): Indicates if the amplifier is in power mode.
prev_voa (float): The previous amplifier variable optical attenuator value.
prev_dp (float): The previous amplifier delta power.
pref_ch_db (float): reference per channel power in dB.
pref_total_db (float): reference total power in dB.
network (DiGraph): The network graph.
equipment (dict): Equipment library.
verbose (bool): Flag for verbose logging.
Returns:
tuple[float, float]: The updated delta power and variable optical attenuator values.
"""
power_mode = equipment['Span']['default'].power_mode
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
for oms in next_oms:
# go through all the OMS departing from the ROADM
prev_node = this_node
node = oms
if isinstance(this_node, elements.Transceiver):
# todo change pref to a ref channel
if equipment['SI']['default'].tx_power_dbm is not None:
this_node_out_power = equipment['SI']['default'].tx_power_dbm
else:
this_node_out_power = pref_ch_db
if isinstance(this_node, elements.Roadm):
# get target power out from ROADM for the reference carrier based on equalization settings
this_node_out_power = this_node.get_per_degree_ref_power(degree=node.uid)
# use the target power on this degree
prev_dp = this_node_out_power - pref_ch_db
dp = prev_dp
prev_voa = 0
voa = 0
visited_nodes = []
while not (isinstance(node, elements.Roadm) or isinstance(node, elements.Transceiver)):
# go through all nodes in the OMS (loop until next Roadm instance)
next_node = get_next_node(node, network)
visited_nodes.append(node)
if next_node in visited_nodes:
raise NetworkTopologyError(f'Loop detected for {type(node).__name__} {node.uid}, '
+ 'please check network topology')
if isinstance(node, elements.Edfa):
node_loss = span_loss(network, prev_node, equipment)
voa = node.out_voa if node.out_voa else 0
if node.operational.delta_p is None:
@@ -487,11 +476,11 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
dp += power_reduction
gain_target += power_reduction
if node.params.raman and not raman_allowed:
if isinstance(prev_node, elements.Fiber):
if isinstance(prev_node, elements.Fiber) and verbose:
logger.warning(f'\n\tWARNING: raman is used in node {node.uid}\n '
+ '\tbut fiber lineic loss is above threshold\n')
else:
logger.critical(f'\n\tWARNING: raman is used in node {node.uid}\n '
logger.warning(f'\n\tWARNING: raman is used in node {node.uid}\n '
+ '\tbut previous node is not a fiber\n')
# if variety is imposed by user, and if the gain_target (computed or imposed) is also above
# variety max gain + extended range, then warn that gain > max_gain + extended range
@@ -522,37 +511,69 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
node.target_pch_out_dbm = round(node.delta_p + pref_ch_db, 2)
elif node.delta_p is None:
node.target_pch_out_dbm = None
return dp, voa
def set_egress_amplifier(network: DiGraph, this_node: Union[elements.Roadm, elements.Transceiver], equipment: dict,
pref_ch_db: float, pref_total_db: float, verbose: bool):
"""This node can be a transceiver or a ROADM (same function called in both cases).
Go through each link starting from this_node until next Roadm or Transceiver and
set the amplifiers (Edfa and multiband) according to configurations set by user.
Computes the gain for Raman finers and records it as the gain for reference design.
power_mode = True, set amplifiers delta_p and effective_gain
power_mode = False, set amplifiers effective_gain and ignore delta_p config: set it to None.
records the computed dp in an internal variable for autodesign purpose.
Args:
network (DiGraph): The network graph containing nodes and links.
this_node (Union[elements.Roadm, elements.Transceiver]): The starting node for OMS link configuration.
equipment (dict): Equipment specifications.
pref_ch_db (float): Reference channel power in dB.
pref_total_db (float): Reference total power in dB.
verbose (bool): Flag for verbose logging.
Raises:
NetworkTopologyError: If a loop is detected in the network topology.
"""
power_mode = equipment['Span']['default'].power_mode
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
for oms in next_oms:
# go through all the OMS departing from the ROADM
prev_node = this_node
node = oms
if isinstance(this_node, elements.Transceiver):
# todo change pref to a ref channel
if equipment['SI']['default'].tx_power_dbm is not None:
this_node_out_power = equipment['SI']['default'].tx_power_dbm
else:
this_node_out_power = pref_ch_db
if isinstance(this_node, elements.Roadm):
# get target power out from ROADM for the reference carrier based on equalization settings
this_node_out_power = this_node.get_per_degree_ref_power(degree=node.uid)
# use the target power on this degree
prev_dp = this_node_out_power - pref_ch_db
dp = prev_dp
prev_voa = 0
voa = 0
visited_nodes = []
while not (isinstance(node, elements.Roadm) or isinstance(node, elements.Transceiver)):
# go through all nodes in the OMS (loop until next Roadm instance)
next_node = get_next_node(node, network)
visited_nodes.append(node)
if next_node in visited_nodes:
raise NetworkTopologyError(f'Loop detected for {type(node).__name__} {node.uid}, '
+ 'please check network topology')
if isinstance(node, elements.Edfa):
dp, voa = set_one_amplifier(node, prev_node, next_node, power_mode, prev_voa, prev_dp,
pref_ch_db, pref_total_db, network, equipment, verbose)
elif isinstance(node, elements.RamanFiber):
# this is to record the expected gain in Raman fiber in its .estimated_gain attribute.
_ = span_loss(network, node, equipment, input_power=pref_ch_db + dp)
if isinstance(node, elements.Multiband_amplifier):
for amp in node.amplifiers.values():
node_loss = span_loss(network, prev_node, equipment)
voa = amp.out_voa if amp.out_voa else 0
if amp.delta_p is None:
dp = target_power(network, next_node, equipment) + voa
else:
dp = amp.delta_p
if amp.effective_gain is None or power_mode:
gain_target = node_loss + dp - prev_dp + prev_voa
else: # gain mode with effective_gain
gain_target = amp.effective_gain
dp = prev_dp - node_loss - prev_voa + gain_target
power_target = pref_total_db + dp
amp.delta_p = dp if power_mode else None
amp.effective_gain = gain_target
set_amplifier_voa(amp, power_target, power_mode)
amp._delta_p = amp.delta_p if power_mode else dp
# target_pch_out_dbm records target power for design: If user defines one, then this is displayed,
# else display the one computed during design
if amp.delta_p is not None and amp.operational.delta_p is not None:
# use the user defined target
amp.target_pch_out_dbm = round(amp.operational.delta_p + pref_ch_db, 2)
elif amp.delta_p is not None:
# use the design target if no target were set
amp.target_pch_out_dbm = round(amp.delta_p + pref_ch_db, 2)
elif amp.delta_p is None:
amp.target_pch_out_dbm = None
dp, voa = set_one_amplifier(amp, prev_node, next_node, power_mode, prev_voa, prev_dp,
pref_ch_db, pref_total_db, network, equipment, verbose)
prev_dp = dp
prev_voa = voa
prev_node = node