def load_files(gnpy_topology): """ Load GNPy equipment Library and create network from topology""" eqpt_library = load_equipment( '../examples/default_equipment_data/eqpt_config.json') gnpy_network = network_from_json(topology_to_json(gnpy_topology), eqpt_library) return eqpt_library, gnpy_network
def test_target_pch_out_db_global(case): """ check that per degree attributes are correctly created with global values if none are given """ json_network = setup_per_degree(case) per_degree = {} for elem in json_network['elements']: if 'type' in elem.keys() and elem['type'] == 'Roadm' and 'params' in elem.keys() \ and 'per_degree_pch_out_db' in elem['params']: # records roadms that have a per degree target per_degree[elem['uid']] = { k: v for k, v in elem['params']['per_degree_pch_out_db'].items() } network = network_from_json(json_network, equipment) # Build the network once using the default power defined in SI in eqpt config # power density: db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by # spacing, f_min and f_max p_db = equipment['SI']['default'].power_dbm p_total_db = p_db + lin2db( automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) build_network(network, equipment, p_db, p_total_db) data = network_to_json(network) for elem in data['elements']: if 'type' in elem.keys() and elem['type'] == 'Roadm': # check that power target attributes exist and are filled with correct values # first check that global 'target_pch_out_db' is correctly filled assert elem['params']['target_pch_out_db'] == equipment['Roadm'][ 'default'].target_pch_out_db for degree, power in elem['params']['per_degree_pch_out_db'].items( ): if elem['uid'] not in per_degree.keys(): # second: check that per degree 'target_pch_out_db' is correctly filled with global value # when there was no per degree specification on network input assert power == equipment['Roadm'][ 'default'].target_pch_out_db else: if degree not in per_degree[elem['uid']].keys(): # third: check that per degree 'target_pch_out_db' is correctly filled with global value # on degrees that had no specification when other degrees are filled assert power == equipment['Roadm'][ 'default'].target_pch_out_db else: # fourth: check that per degree 'target_pch_out_db' is correctly filled with specified values assert power == per_degree[elem['uid']][degree]
def test_no_amp_feature(node_uid): ''' Check that booster is not placed on a roadm if fused is specified test_parser covers partly this behaviour. This test should guaranty that the feature is preserved even if convert is changed ''' equipment = load_equipment(EQPT_LIBRARY_NAME) json_network = load_json(NETWORK_FILE_NAME) for elem in json_network['elements']: if elem['uid'] == node_uid: # replace edfa node by a fused node in the topology elem['type'] = 'Fused' elem.pop('type_variety') elem.pop('operational') elem['params'] = {'loss': 0} next_node_uid = next(conn['to_node'] for conn in json_network['connections'] if conn['from_node'] == node_uid) previous_node_uid = next(conn['from_node'] for conn in json_network['connections'] if conn['to_node'] == node_uid) network = network_from_json(json_network, equipment) # Build the network once using the default power defined in SI in eqpt config # power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by # spacing, f_min and f_max p_db = equipment['SI']['default'].power_dbm p_total_db = p_db + lin2db( automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) build_network(network, equipment, p_db, p_total_db) node = next(nd for nd in network.nodes() if nd.uid == node_uid) next_node = next(network.successors(node)) previous_node = next(network.predecessors(node)) if not isinstance(node, Fused): raise AssertionError() if not node.params.loss == 0.0: raise AssertionError() if not next_node_uid == next_node.uid: raise AssertionError() if not previous_node_uid == previous_node.uid: raise AssertionError()
def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm): ''' Check that egress power of roadm is equal to target power if input power is greater than target power else, that it is equal to input power. Use a simple two hops A-B-C topology for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target power can not be met in this last case. ''' equipment = load_equipment(EQPT_LIBRARY_NAME) json_network = load_json(TEST_DIR / 'data/twohops_roadm_power_test.json') prev_node = next(n for n in json_network['elements'] if n['uid'] == 'west edfa in node B to ila2') json_network['elements'].remove(prev_node) if prev_node_type == 'edfa': prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Edfa'} elif prev_node_type == 'fused': prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Fused'} prev_node['params'] = {'loss': 0} json_network['elements'].append(prev_node) network = network_from_json(json_network, equipment) p_total_db = power_dbm + lin2db( automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) build_network(network, equipment, power_dbm, p_total_db) params = { 'request_id': 0, 'trx_type': '', 'trx_mode': '', 'source': 'trx node A', 'destination': 'trx node C', 'bidir': False, 'nodes_list': ['trx node C'], 'loose_list': ['strict'], 'format': '', 'path_bandwidth': 100e9, 'effective_freq_slot': None, } trx_params = trx_mode_params(equipment) params.update(trx_params) req = PathRequest(**params) req.power = db2lin(power_dbm - 30) path = compute_constrained_path(network, req) si = create_input_spectral_information(req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing) for i, el in enumerate(path): if isinstance(el, Roadm): carriers_power_in_roadm = min([ c.power.signal + c.power.nli + c.power.ase for c in si.carriers ]) si = el(si, degree=path[i + 1].uid) if el.uid == 'roadm node B': print('input', carriers_power_in_roadm) # if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its # target power (as specified in equipment ie -20 dBm) # if it is a Fused, the input power to the ROADM is smaller than the target power, and the # ROADM cannot apply this target. In this case, it is assumed that the ROADM has 0 dB loss # so the output power will be the same as the input power, which for this particular case # corresponds to -22dBm + power_dbm # next step (for ROADM modelling) will be to apply a minimum loss for ROADMs ! if prev_node_type == 'edfa': assert el.effective_pch_out_db == effective_pch_out_db if prev_node_type == 'fused': # then output power == input_power == effective_pch_out_db + power_dbm assert effective_pch_out_db + power_dbm == \ pytest.approx(lin2db(carriers_power_in_roadm * 1e3), rel=1e-3) assert el.effective_pch_out_db == effective_pch_out_db + power_dbm for carrier in si.carriers: print(carrier.power.signal + carrier.power.nli + carrier.power.ase) power = carrier.power.signal + carrier.power.nli + carrier.power.ase if prev_node_type == 'edfa': # edfa prev_node sets input power to roadm to a high enough value: # Check that egress power of roadm is equal to target power assert power == pytest.approx( db2lin(effective_pch_out_db - 30), rel=1e-3) elif prev_node_type == 'fused': # fused prev_node does reamplfy power after fiber propagation, so input power # to roadm is low. # Check that egress power of roadm is equalized to the min carrier input power. assert power == pytest.approx(carriers_power_in_roadm, rel=1e-3) else: si = el(si)
def test_restrictions(restrictions, equipment): ''' test that restriction is correctly applied if provided in eqpt_config and if no Edfa type were provided in the network json ''' # add restrictions equipment['Roadm']['default'].restrictions = restrictions # build network json_network = load_json(NETWORK_FILE_NAME) network = network_from_json(json_network, equipment) amp_nodes_nobuild_uid = [ nd.uid for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.predecessors(nd)), Roadm) ] preamp_nodes_nobuild_uid = [ nd.uid for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.successors(nd)), Roadm) ] amp_nodes_nobuild = { nd.uid: nd for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.predecessors(nd)), Roadm) } preamp_nodes_nobuild = { nd.uid: nd for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.successors(nd)), Roadm) } # roadm dict with restrictions before build roadms = {nd.uid: nd for nd in network.nodes() if isinstance(nd, Roadm)} # Build the network once using the default power defined in SI in eqpt config # power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by # spacing, f_min and f_max p_db = equipment['SI']['default'].power_dbm p_total_db = p_db + lin2db( automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) build_network(network, equipment, p_db, p_total_db) amp_nodes = [ nd for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.predecessors(nd)), Roadm) and next(network.predecessors(nd)).restrictions['booster_variety_list'] ] preamp_nodes = [ nd for nd in network.nodes() if isinstance(nd, Edfa) and isinstance(next(network.successors(nd)), Roadm) and next(network.successors(nd)).restrictions['preamp_variety_list'] ] # check that previously existing amp are not changed for amp in amp_nodes: if amp.uid in amp_nodes_nobuild_uid: print(amp.uid, amp.params.type_variety) if not amp.params.type_variety == amp_nodes_nobuild[ amp.uid].params.type_variety: raise AssertionError() for amp in preamp_nodes: if amp.uid in preamp_nodes_nobuild_uid: if not amp.params.type_variety == preamp_nodes_nobuild[ amp.uid].params.type_variety: raise AssertionError() # check that restrictions are correctly applied for amp in amp_nodes: if amp.uid not in amp_nodes_nobuild_uid: # and if roadm had no restrictions before build: if restrictions['booster_variety_list'] and \ not roadms[next(network.predecessors(amp)).uid]\ .restrictions['booster_variety_list']: if amp.params.type_variety not in restrictions[ 'booster_variety_list']: raise AssertionError() for amp in preamp_nodes: if amp.uid not in preamp_nodes_nobuild_uid: if restrictions['preamp_variety_list'] and\ not roadms[next(network.successors(amp)).uid].restrictions['preamp_variety_list']: if amp.params.type_variety not in restrictions[ 'preamp_variety_list']: raise AssertionError()
def test_roadm_target_power(prev_node_type, effective_pch_out_db): ''' Check that egress power of roadm is equal to target power if input power is greater than target power else, that it is equal to input power. Use a simple two hops A-B-C topology for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target power can not be met in this last case. ''' equipment = load_equipment(EQPT_LIBRARY_NAME) json_network = load_json(TEST_DIR / 'data/twohops_roadm_power_test.json') prev_node = next(n for n in json_network['elements'] if n['uid'] == 'west edfa in node B to ila2') json_network['elements'].remove(prev_node) if prev_node_type == 'edfa': prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Edfa'} elif prev_node_type == 'fused': prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Fused'} prev_node['params'] = {'loss': 0} json_network['elements'].append(prev_node) network = network_from_json(json_network, equipment) # Build the network once using the default power defined in SI in eqpt config p_db = equipment['SI']['default'].power_dbm p_total_db = p_db + lin2db( automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) build_network(network, equipment, p_db, p_total_db) params = {} params['request_id'] = 0 params['trx_type'] = '' params['trx_mode'] = '' params['source'] = 'trx node A' params['destination'] = 'trx node C' params['bidir'] = False params['nodes_list'] = ['trx node C'] params['loose_list'] = ['strict'] params['format'] = '' params['path_bandwidth'] = 100e9 trx_params = trx_mode_params(equipment) params.update(trx_params) req = PathRequest(**params) path = compute_constrained_path(network, req) si = create_input_spectral_information(req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing) for i, el in enumerate(path): if isinstance(el, Roadm): carriers_power_in_roadm = min([ c.power.signal + c.power.nli + c.power.ase for c in si.carriers ]) si = el(si, degree=path[i + 1].uid) if el.uid == 'roadm node B': print('input', carriers_power_in_roadm) assert el.effective_pch_out_db == effective_pch_out_db for carrier in si.carriers: print(carrier.power.signal + carrier.power.nli + carrier.power.ase) power = carrier.power.signal + carrier.power.nli + carrier.power.ase if prev_node_type == 'edfa': # edfa prev_node sets input power to roadm to a high enough value: # Check that egress power of roadm is equal to target power assert power == pytest.approx( db2lin(effective_pch_out_db - 30), rel=1e-3) elif prev_node_type == 'fused': # fused prev_node does reamplfy power after fiber propagation, so input power # to roadm is low. # Check that egress power of roadm is equalized to the min carrier input power. assert power == pytest.approx(carriers_power_in_roadm, rel=1e-3) else: si = el(si)