diff --git a/gnpy/core/elements.py b/gnpy/core/elements.py index 3fc13fdc3..7ae32b07e 100644 --- a/gnpy/core/elements.py +++ b/gnpy/core/elements.py @@ -242,7 +242,6 @@ def __init__(self, *args, params=None, **kwargs): # on the path, since it depends on the equalization definition on the degree. self.ref_pch_out_dbm = None self.loss = 0 # auto-design interest - # Optical power of carriers are equalized by the ROADM, so that the experienced loss is not the same for # different carriers. The ref_effective_loss records the loss for a reference carrier. self.ref_effective_loss = None @@ -707,11 +706,16 @@ def __init__(self, *args, params=None, **kwargs): def to_json(self): return dict(super().to_json, operational=self.operational) + def __str__(self): + return super().__str__() + f'\n reference gain (dB): {round(self.estimated_gain, 2)}' \ + + f'\n actual gain (dB): {round(self.actual_raman_gain, 2)}' + def propagate(self, spectral_info: SpectralInformation): """Modifies the spectral information computing the attenuation, the non-linear interference generation, the CD and PMD accumulation. """ # apply the attenuation due to the input connector loss + pin = watt2dbm(sum(spectral_info.signal)) attenuation_in_db = self.params.con_in + self.params.att_in spectral_info.apply_attenuation_db(attenuation_in_db) @@ -741,6 +745,8 @@ def propagate(self, spectral_info: SpectralInformation): spectral_info.apply_attenuation_db(attenuation_out_db) self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase) self.propagated_labels = spectral_info.label + pout = watt2dbm(sum(spectral_info.signal)) + self.actual_raman_gain = self.loss + pout - pin class Edfa(_Node): diff --git a/gnpy/core/network.py b/gnpy/core/network.py index ecfefd36c..3017d672f 100644 --- a/gnpy/core/network.py +++ b/gnpy/core/network.py @@ -19,6 +19,7 @@ from gnpy.core.info import ReferenceCarrier, create_input_spectral_information from gnpy.tools import json_io from gnpy.core.parameters import SimParams +from gnpy.core.science_utils import RamanSolver logger = getLogger(__name__) @@ -141,7 +142,6 @@ def target_power(network, node, equipment): # get_fiber_dp POWER_SLOPE = 0.3 dp_range = list(equipment['Span']['default'].delta_power_range_db) node_loss = span_loss(network, node, equipment) - try: dp = round2float((node_loss - SPAN_LOSS_REF) * POWER_SLOPE, dp_range[2]) dp = max(dp_range[0], dp) @@ -187,63 +187,73 @@ def next_node_generator(network, node): yield from next_node_generator(network, next_node) -def estimate_raman_gain(node, equipment): +def estimate_raman_gain(node, equipment, power_dbm): """If node is RamanFiber, then estimate the possible Raman gain if any - for this purpose propagate a fake signal in a copy. - to be accurate the nb of channel should be the same as in SI, but this increases computation time + for this purpose computes stimulated_raman_scattering loss_profile. This may be time consuming. """ - f_min = equipment['SI']['default'].f_min - f_max = equipment['SI']['default'].f_max - roll_off = equipment['SI']['default'].roll_off - baud_rate = equipment['SI']['default'].baud_rate - power_dbm = equipment['SI']['default'].power_dbm - power = dbm2watt(equipment['SI']['default'].power_dbm) - spacing = equipment['SI']['default'].spacing - tx_osnr = equipment['SI']['default'].tx_osnr - - sim_params = { - "raman_params": { - "flag": True, - "result_spatial_resolution": 10e3, - "solver_spatial_resolution": 50 - }, - "nli_params": { - "method": "ggn_spectrally_separated", - "dispersion_tolerance": 1, - "phase_shift_tolerance": 0.1, - "computed_channels": [1, 18, 37, 56, 75] - } - } if isinstance(node, elements.RamanFiber): + if hasattr(node, "estimated_gain"): + return node.estimated_gain + f_min = equipment['SI']['default'].f_min + f_max = equipment['SI']['default'].f_max + roll_off = equipment['SI']['default'].roll_off + baud_rate = equipment['SI']['default'].baud_rate + power = dbm2watt(power_dbm) + spacing = equipment['SI']['default'].spacing + tx_osnr = equipment['SI']['default'].tx_osnr + + # reduce the nb of channels to speed up + spacing = spacing * 3 + power = power * 3 + + sim_params = { + "raman_params": { + "flag": True, + "result_spatial_resolution": 50e3, + "solver_spatial_resolution": 100 + } + } + # in order to take into account gain generated in RamanFiber, propagate in the RamanFiber with - # SI reference channel. - spectral_info_input = create_input_spectral_information(f_min=f_min, f_max=f_max, roll_off=roll_off, - baud_rate=baud_rate, power=power, spacing=spacing, - tx_osnr=tx_osnr) - n_copy = deepcopy(node) - # need to set ref_pch_in_dbm in order to correctly run propagate of the element, because this - # setting has not yet been done by autodesign - n_copy.ref_pch_in_dbm = power_dbm + if hasattr(node, "estimated_gain"): + # do not compute twice to save on time + return node.estimated_gain + spectral_info = create_input_spectral_information(f_min=f_min, f_max=f_max, roll_off=roll_off, + baud_rate=baud_rate, power=power, spacing=spacing, + tx_osnr=tx_osnr) + pin = watt2dbm(sum(spectral_info.signal)) + attenuation_in_db = node.params.con_in + node.params.att_in + spectral_info.apply_attenuation_db(attenuation_in_db) + save_sim_params = {"raman_params": SimParams._shared_dict['raman_params'].to_json(), + "nli_params": SimParams._shared_dict['nli_params'].to_json()} SimParams.set_params(sim_params) - pin = watt2dbm(sum(spectral_info_input.signal)) - spectral_info_out = n_copy(spectral_info_input) - pout = watt2dbm(sum(spectral_info_out.signal)) - estimated_gain = pout - pin + node.loss + stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, node) + attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1] + spectral_info.apply_attenuation_lin(attenuation_fiber) + attenuation_out_db = node.params.con_out + spectral_info.apply_attenuation_db(attenuation_out_db) + pout = watt2dbm(sum(spectral_info.signal)) + estimated_loss = pin - pout + estimated_gain = node.loss - estimated_loss + node.estimated_gain = estimated_gain + SimParams.set_params(save_sim_params) return round(estimated_gain, 2) else: return 0.0 -def span_loss(network, node, equipment): - """Total loss of a span (Fiber and Fused nodes) which contains the given node""" +def span_loss(network, node, equipment, input_power=None): + """Total loss of a span (Fiber and Fused nodes) which contains the given node + Do not recompute, if it was already computed: records it in design_span_loss""" + if hasattr(node, "design_span_loss"): + return node.design_span_loss loss = node.loss if node.passive else 0 loss += sum(n.loss for n in prev_node_generator(network, node)) loss += sum(n.loss for n in next_node_generator(network, node)) # add the possible Raman gain - gain = estimate_raman_gain(node, equipment) - gain += sum(estimate_raman_gain(n, equipment) for n in prev_node_generator(network, node)) - gain += sum(estimate_raman_gain(n, equipment) for n in next_node_generator(network, node)) - + gain = estimate_raman_gain(node, equipment, input_power) + gain += sum(estimate_raman_gain(n, equipment, input_power) for n in prev_node_generator(network, node)) + gain += sum(estimate_raman_gain(n, equipment, input_power) for n in next_node_generator(network, node)) return loss - gain @@ -399,7 +409,8 @@ 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 - + elif isinstance(node, elements.RamanFiber): + _ = span_loss(network, node, equipment, input_power=pref_ch_db + dp) prev_dp = dp prev_voa = voa prev_node = node @@ -701,7 +712,11 @@ def add_fiber_padding(network, fibers, padding, equipment): next_node = get_next_node(fiber, network) if isinstance(next_node, elements.Fused): continue + # do not pad if this is a Raman Fiber + if isinstance(fiber, elements.RamanFiber): + continue this_span_loss = span_loss(network, fiber, equipment) + fiber.design_span_loss = this_span_loss if this_span_loss < padding: # add a padding att_in at the input of the 1st fiber: # address the case when several fibers are spliced together @@ -710,6 +725,7 @@ def add_fiber_padding(network, fibers, padding, equipment): # just after a roadm: need to check that first_fiber is really a fiber if isinstance(first_fiber, elements.Fiber): first_fiber.params.att_in = first_fiber.params.att_in + padding - this_span_loss + fiber.design_span_loss += first_fiber.params.att_in def add_missing_elements_in_network(network, equipment): diff --git a/gnpy/core/parameters.py b/gnpy/core/parameters.py index e23accc19..28e915db2 100644 --- a/gnpy/core/parameters.py +++ b/gnpy/core/parameters.py @@ -46,6 +46,11 @@ def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_re self.result_spatial_resolution = result_spatial_resolution # [m] self.solver_spatial_resolution = solver_spatial_resolution # [m] + def to_json(self): + return {"flag": self.flag, + "result_spatial_resolution": self.result_spatial_resolution, + "solver_spatial_resolution": self.solver_spatial_resolution} + class NLIParams(Parameters): def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1, @@ -62,6 +67,12 @@ def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shi self.phase_shift_tolerance = phase_shift_tolerance self.computed_channels = computed_channels + def to_json(self): + return {"method": self.method, + "dispersion_tolerance": self.dispersion_tolerance, + "phase_shift_tolerance": self.phase_shift_tolerance, + "computed_channels": self.computed_channels} + class SimParams(Parameters): _shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()} diff --git a/tests/invocation/transmission_main_example__raman b/tests/invocation/transmission_main_example__raman index 0dc242d35..5249b5ee0 100644 --- a/tests/invocation/transmission_main_example__raman +++ b/tests/invocation/transmission_main_example__raman @@ -25,112 +25,114 @@ RamanFiber Span1 (conn loss out includes EOL margin defined in eqpt_config.json) reference pch out (dBm): -7.20 actual pch out (dBm): -7.47 + reference gain (dB): 9.74 + actual gain (dB): 9.8 Fused Fused1 loss (dB): 0.00 Edfa Edfa1 type_variety: std_low_gain - effective gain(dB): 5.20 + effective gain(dB): 5.26 (before att_in and before output VOA) - noise figure (dB): 13.80 + noise figure (dB): 13.74 (including att_in) - pad att_in (dB): 2.80 + pad att_in (dB): 2.74 Power In (dBm): 11.61 - Power Out (dBm): 16.81 + Power Out (dBm): 16.87 Delta_P (dB): -2.00 target pch (dBm): -2.00 - actual pch out (dBm): -2.26 + actual pch out (dBm): -2.21 output VOA (dB): 0.00 Transceiver Site_B - GSNR (0.1nm, dB): 31.42 - GSNR (signal bw, dB): 27.34 - OSNR ASE (0.1nm, dB): 34.21 - OSNR ASE (signal bw, dB): 30.13 + GSNR (0.1nm, dB): 31.44 + GSNR (signal bw, dB): 27.35 + OSNR ASE (0.1nm, dB): 34.24 + OSNR ASE (signal bw, dB): 30.16 CD (ps/nm): 1336.00 PMD (ps): 0.36 PDL (dB): 0.00 Latency (ms): 0.39 Transmission result for input power = 0.00 dBm: - Final GSNR (0.1 nm): 31.42 dB + Final GSNR (0.1 nm): 31.44 dB The GSNR per channel at the end of the line is: Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB) - 1 191.35000 0.22 31.64 31.55 28.58 - 2 191.40000 0.18 31.62 31.46 28.53 - 3 191.45000 0.15 31.60 31.37 28.47 - 4 191.50000 0.11 31.58 31.28 28.42 - 5 191.55000 0.05 31.54 31.20 28.36 - 6 191.60000 -0.01 31.51 31.11 28.30 - 7 191.65000 -0.07 31.48 31.03 28.24 - 8 191.70000 -0.12 31.45 30.95 28.18 - 9 191.75000 -0.18 31.42 30.87 28.13 - 10 191.80000 -0.25 31.38 30.79 28.07 - 11 191.85000 -0.31 31.35 30.72 28.01 - 12 191.90000 -0.38 31.31 30.64 27.95 - 13 191.95000 -0.44 31.27 30.57 27.90 - 14 192.00000 -0.51 31.24 30.50 27.84 - 15 192.05000 -0.58 31.20 30.42 27.78 - 16 192.10000 -0.64 31.16 30.35 27.73 - 17 192.15000 -0.71 31.12 30.29 27.67 - 18 192.20000 -0.78 31.08 30.22 27.62 - 19 192.25000 -0.85 31.04 30.22 27.60 - 20 192.30000 -0.93 31.00 30.22 27.58 - 21 192.35000 -1.00 30.96 30.23 27.57 - 22 192.40000 -1.08 30.91 30.23 27.55 - 23 192.45000 -1.16 30.87 30.23 27.53 - 24 192.50000 -1.23 30.82 30.24 27.51 - 25 192.55000 -1.30 30.78 30.24 27.49 - 26 192.60000 -1.37 30.74 30.24 27.47 - 27 192.65000 -1.44 30.70 30.25 27.46 - 28 192.70000 -1.52 30.65 30.25 27.44 - 29 192.75000 -1.59 30.61 30.25 27.42 - 30 192.80000 -1.66 30.57 30.26 27.40 - 31 192.85000 -1.73 30.52 30.26 27.38 - 32 192.90000 -1.80 30.48 30.26 27.36 - 33 192.95000 -1.87 30.43 30.27 27.34 - 34 193.00000 -1.94 30.39 30.27 27.32 - 35 193.05000 -2.01 30.35 30.27 27.30 - 36 193.10000 -2.08 30.30 30.28 27.28 - 37 193.15000 -2.15 30.26 30.28 27.26 - 38 193.20000 -2.22 30.22 30.29 27.24 - 39 193.25000 -2.29 30.17 30.31 27.23 - 40 193.30000 -2.36 30.13 30.32 27.21 - 41 193.35000 -2.43 30.08 30.33 27.19 - 42 193.40000 -2.50 30.04 30.35 27.18 - 43 193.45000 -2.56 29.99 30.36 27.16 - 44 193.50000 -2.63 29.95 30.37 27.14 - 45 193.55000 -2.71 29.90 30.39 27.12 - 46 193.60000 -2.78 29.85 30.40 27.11 - 47 193.65000 -2.85 29.80 30.41 27.09 - 48 193.70000 -2.93 29.75 30.43 27.07 - 49 193.75000 -3.00 29.70 30.44 27.05 - 50 193.80000 -3.07 29.65 30.45 27.02 - 51 193.85000 -3.15 29.60 30.47 27.00 - 52 193.90000 -3.22 29.55 30.48 26.98 - 53 193.95000 -3.29 29.50 30.50 26.96 - 54 194.00000 -3.37 29.45 30.51 26.94 - 55 194.05000 -3.44 29.40 30.52 26.92 - 56 194.10000 -3.52 29.35 30.54 26.89 - 57 194.15000 -3.59 29.30 30.59 26.89 - 58 194.20000 -3.66 29.25 30.64 26.88 - 59 194.25000 -3.74 29.19 30.70 26.87 - 60 194.30000 -3.81 29.14 30.75 26.86 - 61 194.35000 -3.89 29.09 30.81 26.86 - 62 194.40000 -3.96 29.04 30.87 26.85 - 63 194.45000 -4.04 28.98 30.93 26.84 - 64 194.50000 -4.11 28.93 30.98 26.83 - 65 194.55000 -4.18 28.88 31.04 26.82 - 66 194.60000 -4.25 28.83 31.10 26.81 - 67 194.65000 -4.31 28.78 31.17 26.80 - 68 194.70000 -4.38 28.74 31.23 26.79 - 69 194.75000 -4.45 28.69 31.29 26.79 - 70 194.80000 -4.51 28.64 31.35 26.78 - 71 194.85000 -4.58 28.59 31.42 26.77 - 72 194.90000 -4.65 28.54 31.48 26.76 - 73 194.95000 -4.71 28.49 31.55 26.74 - 74 195.00000 -4.78 28.44 31.62 26.73 - 75 195.05000 -4.85 28.39 31.69 26.72 - 76 195.10000 -4.91 28.34 31.69 26.69 + 1 191.35000 0.27 31.66 31.55 28.60 + 2 191.40000 0.24 31.64 31.46 28.54 + 3 191.45000 0.20 31.62 31.37 28.48 + 4 191.50000 0.17 31.60 31.28 28.43 + 5 191.55000 0.11 31.57 31.20 28.37 + 6 191.60000 0.05 31.54 31.11 28.31 + 7 191.65000 -0.01 31.51 31.03 28.25 + 8 191.70000 -0.07 31.47 30.95 28.20 + 9 191.75000 -0.13 31.44 30.87 28.14 + 10 191.80000 -0.19 31.41 30.79 28.08 + 11 191.85000 -0.26 31.37 30.72 28.02 + 12 191.90000 -0.32 31.34 30.64 27.97 + 13 191.95000 -0.39 31.30 30.57 27.91 + 14 192.00000 -0.45 31.26 30.50 27.85 + 15 192.05000 -0.52 31.23 30.42 27.80 + 16 192.10000 -0.59 31.19 30.35 27.74 + 17 192.15000 -0.66 31.15 30.29 27.69 + 18 192.20000 -0.72 31.11 30.22 27.63 + 19 192.25000 -0.79 31.07 30.22 27.62 + 20 192.30000 -0.87 31.03 30.22 27.60 + 21 192.35000 -0.95 30.99 30.23 27.58 + 22 192.40000 -1.02 30.94 30.23 27.56 + 23 192.45000 -1.10 30.90 30.23 27.54 + 24 192.50000 -1.18 30.85 30.24 27.52 + 25 192.55000 -1.25 30.81 30.24 27.51 + 26 192.60000 -1.32 30.77 30.24 27.49 + 27 192.65000 -1.39 30.73 30.25 27.47 + 28 192.70000 -1.46 30.68 30.25 27.45 + 29 192.75000 -1.53 30.64 30.25 27.43 + 30 192.80000 -1.60 30.60 30.26 27.41 + 31 192.85000 -1.67 30.55 30.26 27.39 + 32 192.90000 -1.74 30.51 30.26 27.37 + 33 192.95000 -1.81 30.47 30.27 27.35 + 34 193.00000 -1.89 30.42 30.27 27.33 + 35 193.05000 -1.95 30.38 30.27 27.32 + 36 193.10000 -2.02 30.34 30.28 27.30 + 37 193.15000 -2.09 30.29 30.28 27.28 + 38 193.20000 -2.16 30.25 30.29 27.26 + 39 193.25000 -2.23 30.20 30.31 27.24 + 40 193.30000 -2.30 30.16 30.32 27.23 + 41 193.35000 -2.37 30.11 30.33 27.21 + 42 193.40000 -2.44 30.07 30.35 27.20 + 43 193.45000 -2.51 30.02 30.36 27.18 + 44 193.50000 -2.58 29.98 30.37 27.16 + 45 193.55000 -2.65 29.93 30.39 27.14 + 46 193.60000 -2.72 29.88 30.40 27.12 + 47 193.65000 -2.80 29.83 30.41 27.10 + 48 193.70000 -2.87 29.79 30.43 27.08 + 49 193.75000 -2.94 29.74 30.44 27.06 + 50 193.80000 -3.02 29.69 30.45 27.04 + 51 193.85000 -3.09 29.64 30.47 27.02 + 52 193.90000 -3.16 29.59 30.48 27.00 + 53 193.95000 -3.24 29.54 30.50 26.98 + 54 194.00000 -3.31 29.49 30.51 26.96 + 55 194.05000 -3.38 29.44 30.52 26.94 + 56 194.10000 -3.46 29.39 30.54 26.91 + 57 194.15000 -3.53 29.33 30.59 26.91 + 58 194.20000 -3.61 29.28 30.64 26.90 + 59 194.25000 -3.68 29.23 30.70 26.89 + 60 194.30000 -3.76 29.18 30.75 26.89 + 61 194.35000 -3.83 29.13 30.81 26.88 + 62 194.40000 -3.91 29.07 30.87 26.87 + 63 194.45000 -3.98 29.02 30.93 26.86 + 64 194.50000 -4.05 28.97 30.98 26.85 + 65 194.55000 -4.12 28.92 31.04 26.84 + 66 194.60000 -4.19 28.87 31.10 26.84 + 67 194.65000 -4.26 28.82 31.17 26.83 + 68 194.70000 -4.32 28.77 31.23 26.82 + 69 194.75000 -4.39 28.72 31.29 26.81 + 70 194.80000 -4.46 28.68 31.35 26.80 + 71 194.85000 -4.52 28.63 31.42 26.79 + 72 194.90000 -4.59 28.58 31.48 26.78 + 73 194.95000 -4.66 28.53 31.55 26.77 + 74 195.00000 -4.72 28.48 31.62 26.76 + 75 195.05000 -4.79 28.43 31.69 26.75 + 76 195.10000 -4.86 28.38 31.69 26.71 (No source node specified: picked Site_A)