Exemple #1
0
def si(nch_and_spacing, bw):
    """parametrize a channel comb with nb_channel, spacing and signal bw"""
    nb_channel, spacing = nch_and_spacing
    f_min = 191.3e12
    f_max = automatic_fmax(f_min, spacing, nb_channel)
    return create_input_spectral_information(f_min, f_max, 0.15, bw, 1e-3,
                                             spacing)
Exemple #2
0
def propagation(input_power, con_in, con_out,dest):
    equipment = load_equipment(eqpt_library_name)
    network = load_network(network_file_name,equipment)
    build_network(network, equipment, 0, 20)

    # parametrize the network elements with the con losses and adapt gain
    # (assumes all spans are identical)
    for e in network.nodes():
        if isinstance(e, Fiber):
            loss = e.loss_coef * e.length
            e.con_in = con_in
            e.con_out = con_out
        if isinstance(e, Edfa):
            e.operational.gain_target = loss + con_in + con_out

    transceivers = {n.uid: n for n in network.nodes() if isinstance(n, Transceiver)}

    p = input_power
    p = db2lin(p) * 1e-3
    spacing = 50e9 # THz
    si = create_input_spectral_information(191.3e12, 191.3e12+79*spacing, 0.15, 32e9, p, spacing)
    source = next(transceivers[uid] for uid in transceivers if uid == 'trx A')
    sink = next(transceivers[uid] for uid in transceivers if uid == dest)
    path = dijkstra_path(network, source, sink)
    for el in path:
        si = el(si)
        print(el) # remove this line when sweeping across several powers
    edfa_sample = next(el for el in path if isinstance(el, Edfa))
    nf = mean(edfa_sample.nf)

    print(f'pw: {input_power} conn in: {con_in} con out: {con_out}',
          f'[email protected]: {round(mean(sink.osnr_ase_01nm),2)}',
          f'SNR@bandwitdth: {round(mean(sink.snr),2)}')
    return sink , nf
Exemple #3
0
def test_raman_fiber():
    """ Test the accuracy of propagating the RamanFiber.
    """
    # spectral information generation
    power = 1e-3
    eqpt_params = load_json(TEST_DIR / 'data' / 'eqpt_config.json')
    spectral_info_params = eqpt_params['SI'][0]
    spectral_info_params.pop('power_dbm')
    spectral_info_params.pop('power_range_db')
    spectral_info_params.pop('tx_osnr')
    spectral_info_params.pop('sys_margins')
    spectral_info_input = create_input_spectral_information(power=power, **spectral_info_params)

    sim_params = SimParams(**load_json(TEST_DIR / 'data' / 'sim_params.json'))
    Simulation.set_params(sim_params)
    fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'raman_fiber_config.json'))

    # propagation
    spectral_info_out = fiber(spectral_info_input)

    p_signal = [carrier.power.signal for carrier in spectral_info_out.carriers]
    p_ase = [carrier.power.ase for carrier in spectral_info_out.carriers]
    p_nli = [carrier.power.nli for carrier in spectral_info_out.carriers]

    expected_results = read_csv(TEST_DIR / 'data' / 'expected_results_science_utils.csv')
    assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
    assert_allclose(p_ase, expected_results['ase'], rtol=1e-3)
    assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
Exemple #4
0
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)
    path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
    return path
Exemple #5
0
def propagation(input_power, network, sim_path, initial_slot, num_slots, eqpt):
    """ Calculate and output SNR based on inputs
        input_power: Power in decibels
        network: Network created from GNPy topology
        sim_path: list of nodes service will travel through
        num_slots: number of slots in service
        eqpt: equipment library for GNPy """

    # Values to create Spectral Information object
    spacing = 12.5e9
    min_freq = 195942783006536 + initial_slot * spacing
    max_freq = min_freq + (num_slots - 1) * spacing
    p = input_power
    p = db2lin(p) * 1e-3
    si = create_input_spectral_information(min_freq, max_freq, 0.15, 32e9, p,
                                           spacing)

    p_total_db = input_power + lin2db(
        automatic_nch(min_freq, max_freq, spacing))
    build_network(network, eqpt, input_power, p_total_db)

    # Store network elements
    transceivers = {
        n.uid: n
        for n in network.nodes() if isinstance(n, Transceiver)
    }
    fibers = {n.uid: n for n in network.nodes() if isinstance(n, Fiber)}
    edfas = {n.uid: n for n in network.nodes() if isinstance(n, Edfa)}

    # Recreate path in the GNPy network using node list from simulator
    path = []

    for index, node in enumerate(sim_path):
        # add transceiver to path
        path.append(transceivers[node])
        # add fiber connecting transceivers to path, unless source transceiver is last in path
        if index + 1 < len(sim_path):
            fiber_str = f"Fiber ({node} \u2192 {sim_path[index+1]})"
            for uid in fibers:
                # add all fibers to path even if they are split up
                if uid[0:len(fiber_str)] == fiber_str:
                    path.append(fibers[uid])
                    # add amplifier to path, if necessary
                    edfa = f"Edfa0_{uid}"
                    fiber_neighbors = [
                        n.uid for n in neighbors(network, fibers[uid])
                    ]
                    if edfa in edfas and edfa in fiber_neighbors:
                        path.append(edfas[edfa])

    # Calculate effects of physical layer impairments
    for el in path:
        si = el(si)

    destination_node = path[-1]

    return destination_node.snr
Exemple #6
0
def propagate_and_optimize_mode(path, req, equipment):
    #update roadm loss in case of power sweep (power mode only)
    set_roadm_loss(path, equipment, lin2db(req.power * 1e3))
    # if mode is unknown : loops on the modes starting from the highest baudrate fiting in the
    # step 1: create an ordered list of modes based on baudrate
    baudrate_to_explore = list(
        set([
            m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode
            if float(m['min_spacing']) <= req.spacing
        ]))
    # TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000
    baudrate_to_explore = sorted(baudrate_to_explore, reverse=True)
    if baudrate_to_explore:
        # at least 1 baudrate can be tested wrt spacing
        for b in baudrate_to_explore:
            modes_to_explore = [
                m for m in equipment['Transceiver'][req.tsp].mode
                if m['baud_rate'] == b
            ]
            modes_to_explore = sorted(modes_to_explore,
                                      key=lambda x: x['bit_rate'],
                                      reverse=True)
            # print(modes_to_explore)
            # step2 : computes propagation for each baudrate: stop and select the first that passes
            found_a_feasible_mode = False
            # TODO : the case of roll of is not included: for now use SI one
            # TODO : if the loop in mode optimization does not have a feasible path, then bugs
            si = create_input_spectral_information(
                req.f_min, req.f_max, equipment['SI']['default'].roll_off, b,
                req.power, req.spacing)
            for el in path:
                si = el(si)
            for m in modes_to_explore:
                if path[-1].snr is not None:
                    path[-1].update_snr(
                        m['tx_osnr'],
                        equipment['Roadms']['default'].add_drop_osnr)
                    if round(min(path[-1].snr + lin2db(b / (12.5e9))),
                             2) > m['OSNR']:
                        found_a_feasible_mode = True
                        return path, m
                else:
                    return [], None
        # only get to this point if no baudrate/mode satisfies OSNR requirement

        # returns the last propagated path and mode
        msg = f'\tWarning! Request {req.request_id}: no mode satisfies path SNR requirement.\n'
        print(msg)
        logger.info(msg)
        return [], None
    else:
        #  no baudrate satisfying spacing
        msg = f'\tWarning! Request {req.request_id}: no baudrate satisfies spacing requirement.\n'
        print(msg)
        logger.info(msg)
        return [], None
Exemple #7
0
def propagate2(path, req, equipment):
    si = create_input_spectral_information(
        req.f_min, req.f_max, req.roll_off, req.baud_rate,
        req.power, req.spacing)
    infos = {}
    for el in path:
        before_si = si
        after_si  = si = el(si)
        infos[el] = before_si, after_si
    path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
    return infos
Exemple #8
0
def propagate(path, req, equipment, show=False):
    #update roadm loss in case of power sweep (power mode only)
    set_roadm_loss(path, equipment, lin2db(req.power * 1e3))
    si = create_input_spectral_information(req.frequency['min'], req.roll_off,
                                           req.baud_rate, req.power,
                                           req.spacing, req.nb_channel)
    for el in path:
        si = el(si)
        if show:
            print(el)
    return path
Exemple #9
0
def propagate(path, req, equipment, show=False):
    #update roadm loss in case of power sweep (power mode only)
    set_roadm_loss(path, equipment, lin2db(req.power * 1e3))
    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)
        if show:
            print(el)
    path[-1].update_snr(req.tx_osnr,
                        equipment['Roadms']['default'].add_drop_osnr)
    return path
Exemple #10
0
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 i, el in enumerate(path):
        if isinstance(el, Roadm):
            next_el = path[i + 1]
            si = el(si, degree=next_el.uid)
        else:
            si = el(si)
        print(el)
    path[-1].update_snr(req.tx_osnr,
                        equipment['Roadm']['default'].add_drop_osnr)
    return path
Exemple #11
0
def propagate2(path, req, equipment):
    si = create_input_spectral_information(req.f_min, req.f_max, req.roll_off,
                                           req.baud_rate, req.power,
                                           req.spacing)
    infos = {}
    for i, el in enumerate(path):
        before_si = si
        if isinstance(el, Roadm):
            next_el = path[i + 1]
            after_si = si = el(si, degree=next_el.uid)
        else:
            after_si = si = el(si)
        infos[el] = before_si, after_si
    path[-1].update_snr(req.tx_osnr,
                        equipment['Roadm']['default'].add_drop_osnr)
    return infos
Exemple #12
0
import gnpy.core.info as gn
import matplotlib.pyplot as plt
import Mylib as ml
import json as js

# Exercise 3
# Create and plot a spectral information representing a comb of 120 WDM channels.
# Each channel has a -3 dB bandwidth of 32 Gbaud, a roll-off of 0.2 and a
# power equal to 0 dBm. This comb is centered around 193 THz and the spacing
# is 45 GHz.

data = {"f center": 194.5e12, "roll off": 0.2, "baud rate": 32e9, "power": 1e-3, "spacing": 45e9}

# write json data into a file
with open("Parameters3.json", "w") as write_file:
    js.dump(data, write_file, indent=4)

with open("Parameters3.json", "r") as read_file:
    data = js.load(read_file)

f_min = data["f center"]-(data["spacing"]*60)
f_max = data["f center"]+(data["spacing"]*60)

si = gn.create_input_spectral_information(f_min, f_max, data["roll off"], data["baud rate"], data["power"], data["spacing"])

ml.plot_spectrum(si)
plt.show()
Exemple #13
0
def propagate_and_optimize_mode(path, req, equipment):
    # if mode is unknown : loops on the modes starting from the highest baudrate fiting in the
    # step 1: create an ordered list of modes based on baudrate
    baudrate_to_explore = list(
        set([
            this_mode['baud_rate']
            for this_mode in equipment['Transceiver'][req.tsp].mode
            if float(this_mode['min_spacing']) <= req.spacing
        ]))
    # TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000
    baudrate_to_explore = sorted(baudrate_to_explore, reverse=True)
    if baudrate_to_explore:
        # at least 1 baudrate can be tested wrt spacing
        for this_br in baudrate_to_explore:
            modes_to_explore = [
                this_mode
                for this_mode in equipment['Transceiver'][req.tsp].mode
                if this_mode['baud_rate'] == this_br
                and float(this_mode['min_spacing']) <= req.spacing
            ]
            modes_to_explore = sorted(modes_to_explore,
                                      key=lambda x: x['bit_rate'],
                                      reverse=True)
            # print(modes_to_explore)
            # step2: computes propagation for each baudrate: stop and select the first that passes
            found_a_feasible_mode = False
            # TODO: the case of roll of is not included: for now use SI one
            # TODO: if the loop in mode optimization does not have a feasible path, then bugs
            spc_info = create_input_spectral_information(
                req.f_min, req.f_max, equipment['SI']['default'].roll_off,
                this_br, req.power, req.spacing)
            for i, el in enumerate(path):
                if isinstance(el, Roadm):
                    next_el = path[i + 1]
                    spc_info = el(spc_info, degree=next_el.uid)
                else:
                    spc_info = el(spc_info)
            for this_mode in modes_to_explore:
                if path[-1].snr is not None:
                    path[-1].update_snr(
                        this_mode['tx_osnr'],
                        equipment['Roadm']['default'].add_drop_osnr)
                    if round(min(path[-1].snr + lin2db(this_br / (12.5e9))),
                             2) > this_mode['OSNR']:
                        found_a_feasible_mode = True
                        return path, this_mode
                    else:
                        last_explored_mode = this_mode
                else:
                    req.blocking_reason = 'NO_COMPUTED_SNR'
                    return path, None

        # only get to this point if no baudrate/mode satisfies OSNR requirement

        # returns the last propagated path and mode
        msg = f'\tWarning! Request {req.request_id}: no mode satisfies path SNR requirement.\n'
        print(msg)
        LOGGER.info(msg)
        req.blocking_reason = 'NO_FEASIBLE_MODE'
        return path, last_explored_mode
    else:
        # no baudrate satisfying spacing
        msg = f'\tWarning! Request {req.request_id}: no baudrate satisfies spacing requirement.\n'
        print(msg)
        LOGGER.info(msg)
        req.blocking_reason = 'NO_FEASIBLE_BAUDRATE_WITH_SPACING'
        return [], None
Exemple #14
0
import gnpy.core.info as gn
import matplotlib.pyplot as plt
import Mylib as ml

# 1. Create a json file with the following parameters (in fundamental units, Hz,
# Baud, W):

data = {
    "f min": 191.5e12,
    "f max": 194.5e12,
    "roll off": 0.2,
    "baud rate": 32e9,
    "power": 1e-3,
    "spacing": 50e9
}

# write json data into a file
with open("Parameters.json", "w") as write_file:
    js.dump(data, write_file, indent=4)

# read json data from a file
with open("Parameters.json", "r") as read_file:
    data = js.load(read_file)

# Create spetral information
si = gn.create_input_spectral_information(data['f min'], data['f max'],
                                          data['roll off'], data['baud rate'],
                                          data['power'], data['spacing'])

ml.plot_spectrum(si)
plt.show()
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)
Exemple #16
0
def si(nch_and_spacing, bw):
    """parametrize a channel comb with nb_channel, spacing and signal bw"""
    nb_channel, spacing = nch_and_spacing
    return create_input_spectral_information(191.3e12, 0.15, bw, 1e-3, spacing,
                                             nb_channel)
#print(Edfa)

# 5. instantiate a noiseless WDM comb according to the parameters described
# in eqpt.json file

# read json data from a file
with open("eqp2.json", "r") as read_file:
    data = js.load(read_file)

# From the json data, extract only the values needed for the spectral info (SI)
si_data = data['SI'][0]

# Compute the WDM for the interested Spectral info
si = gn.create_input_spectral_information(
    si_data['f_min'], si_data['f_max'], si_data['roll_off'],
    si_data['baud_rate'], 10**(si_data['power_dbm'] / 10) / 1000,
    si_data['spacing'])

# 6. propagate the WDM comb through the EDFA.
# Hint: As Edfa has the method call (self, spectral info), it can be used
# as function. So, the command edfa(spectral information) will return the
# spectral information propagated through the EDFA.

ml.plot_signal(si)

new_si = EDFA(si)

# 7. plot the signal and ASE noise power before and after the propagation.

ml.plot_signal_ASE(new_si)
#print(new_si)
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)