mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-30 17:47:50 +00:00 
			
		
		
		
	Add ref_carrier to Pref and remove req_power from ReferenceCarrier
ref_carrier is added in Pref conveys the reference channel type information ie the channel that was used for design (would it be auto-design or for a given design). Other attributes (like slot_width or roll-off) may be added here for future equalization types. Pref object already records the req_power, so let's remove it from ReferenceCarrier and only use ref_carrier to record info that will be useful for PSD equalization ie baud_rate. This reference baud_rate is required to compute reference target power based on spectral density values during propagation. It is thus required because of on-the-fly evaluation of loss for p_span_i and for printing loss and target power of ROADM during propagation. Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com> Change-Id: Ic7441afa12ca5273ff99dea0268e439276107257
This commit is contained in:
		| @@ -42,10 +42,11 @@ class Channel(namedtuple('Channel', | |||||||
|     """ |     """ | ||||||
|  |  | ||||||
|  |  | ||||||
| class Pref(namedtuple('Pref', 'p_span0, p_spani')): | class Pref(namedtuple('Pref', 'p_span0, p_spani, ref_carrier')): | ||||||
|     """noiseless reference power in dBm: |     """noiseless reference power in dBm: | ||||||
|     p_span0: inital target carrier power for a reference channel defined by user |     p_span0: inital target carrier power for a reference channel defined by user | ||||||
|     p_spani: carrier power after element i for a reference channel defined by user |     p_spani: carrier power after element i for a reference channel defined by user | ||||||
|  |     ref_carrier records the baud rate of the reference channel | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -236,7 +237,7 @@ class SpectralInformation(object): | |||||||
|                                        delta_pdb_per_channel=append(self.delta_pdb_per_channel, |                                        delta_pdb_per_channel=append(self.delta_pdb_per_channel, | ||||||
|                                                                     other.delta_pdb_per_channel), |                                                                     other.delta_pdb_per_channel), | ||||||
|                                        tx_osnr=append(self.tx_osnr, other.tx_osnr), |                                        tx_osnr=append(self.tx_osnr, other.tx_osnr), | ||||||
|                                        ref_power=Pref(self.pref.p_span0, self.pref.p_spani)) |                                        ref_power=Pref(self.pref.p_span0, self.pref.p_spani, self.pref.ref_carrier)) | ||||||
|         except SpectrumError: |         except SpectrumError: | ||||||
|             raise SpectrumError('Spectra cannot be summed: channels overlapping.') |             raise SpectrumError('Spectra cannot be summed: channels overlapping.') | ||||||
|  |  | ||||||
| @@ -295,7 +296,7 @@ def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, in | |||||||
|             raise |             raise | ||||||
|  |  | ||||||
|  |  | ||||||
| def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing, tx_osnr): | def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing, tx_osnr, ref_carrier=None): | ||||||
|     """ Creates a fixed slot width spectral information with flat power. |     """ Creates a fixed slot width spectral information with flat power. | ||||||
|     all arguments are scalar values""" |     all arguments are scalar values""" | ||||||
|     number_of_channels = automatic_nch(f_min, f_max, spacing) |     number_of_channels = automatic_nch(f_min, f_max, spacing) | ||||||
| @@ -305,21 +306,24 @@ def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, | |||||||
|     delta_pdb_per_channel = zeros(number_of_channels) |     delta_pdb_per_channel = zeros(number_of_channels) | ||||||
|     return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate, |     return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate, | ||||||
|                                                  roll_off=roll_off, delta_pdb_per_channel=delta_pdb_per_channel, |                                                  roll_off=roll_off, delta_pdb_per_channel=delta_pdb_per_channel, | ||||||
|                                                  tx_osnr=tx_osnr, ref_power=Pref(p_span0=p_span0, p_spani=p_spani)) |                                                  tx_osnr=tx_osnr, | ||||||
|  |                                                  ref_power=Pref(p_span0=p_span0, p_spani=p_spani, | ||||||
|  |                                                                 ref_carrier=ref_carrier)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def carriers_to_spectral_information(initial_spectrum: dict[Union[int, float], Carrier], | def carriers_to_spectral_information(initial_spectrum: dict[Union[int, float], Carrier], power: float, | ||||||
|                                      ref_carrier: ReferenceCarrier) -> SpectralInformation: |                                      ref_carrier: ReferenceCarrier) -> SpectralInformation: | ||||||
|     """Initial spectrum is a dict with key = carrier frequency, and value a Carrier object. |     """Initial spectrum is a dict with key = carrier frequency, and value a Carrier object. | ||||||
|     :param initial_spectrum: indexed by frequency in Hz, with power offset (delta_pdb), baudrate, slot width, |     :param initial_spectrum: indexed by frequency in Hz, with power offset (delta_pdb), baudrate, slot width, | ||||||
|     tx_osnr and roll off. |     tx_osnr and roll off. | ||||||
|     :param ref_carrier: reference carrier (baudrate and power) used for the reference channel |     :param power: power of the request | ||||||
|  |     :param ref_carrier: reference carrier (baudrate) used for the reference channel | ||||||
|     """ |     """ | ||||||
|     frequency = list(initial_spectrum.keys()) |     frequency = list(initial_spectrum.keys()) | ||||||
|     signal = [ref_carrier.req_power * db2lin(c.delta_pdb) for c in initial_spectrum.values()] |     signal = [power * db2lin(c.delta_pdb) for c in initial_spectrum.values()] | ||||||
|     roll_off = [c.roll_off for c in initial_spectrum.values()] |     roll_off = [c.roll_off for c in initial_spectrum.values()] | ||||||
|     baud_rate = [c.baud_rate for c in initial_spectrum.values()] |     baud_rate = [c.baud_rate for c in initial_spectrum.values()] | ||||||
|     delta_pdb_per_channel = array([c.delta_pdb for c in initial_spectrum.values()]) |     delta_pdb_per_channel = [c.delta_pdb for c in initial_spectrum.values()] | ||||||
|     slot_width = [c.slot_width for c in initial_spectrum.values()] |     slot_width = [c.slot_width for c in initial_spectrum.values()] | ||||||
|     tx_osnr = [c.tx_osnr for c in initial_spectrum.values()] |     tx_osnr = [c.tx_osnr for c in initial_spectrum.values()] | ||||||
|     p_span0 = watt2dbm(ref_carrier.req_power) |     p_span0 = watt2dbm(ref_carrier.req_power) | ||||||
| @@ -327,7 +331,8 @@ def carriers_to_spectral_information(initial_spectrum: dict[Union[int, float], C | |||||||
|     return create_arbitrary_spectral_information(frequency=frequency, signal=signal, baud_rate=baud_rate, |     return create_arbitrary_spectral_information(frequency=frequency, signal=signal, baud_rate=baud_rate, | ||||||
|                                                  slot_width=slot_width, roll_off=roll_off, |                                                  slot_width=slot_width, roll_off=roll_off, | ||||||
|                                                  delta_pdb_per_channel=delta_pdb_per_channel, tx_osnr=tx_osnr, |                                                  delta_pdb_per_channel=delta_pdb_per_channel, tx_osnr=tx_osnr, | ||||||
|                                                  ref_power=Pref(p_span0=p_span0, p_spani=p_spani)) |                                                  ref_power=Pref(p_span0=p_span0, p_spani=p_spani, | ||||||
|  |                                                                 ref_carrier=ref_carrier)) | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass | @dataclass | ||||||
| @@ -345,13 +350,15 @@ class Carrier: | |||||||
|  |  | ||||||
| @dataclass | @dataclass | ||||||
| class ReferenceCarrier: | class ReferenceCarrier: | ||||||
|     """Reference channel is used during autodesign to determine target power |     """Reference channel type is used to determine target power out of ROADM for the reference channel when | ||||||
|     based on power spectral density values during propagation in ROADMs for equalization purpose. |     constant power spectral density (PSD) equalization is set. Reference channel is the type that has been defined | ||||||
|     It is also required to correctly compute the loss experienced by p_span_i in Roadm element. |     in SI block and used for the initial design of the network. | ||||||
|  |     Computing the power out of ROADM for the reference channel is required to correctly compute the loss | ||||||
|  |     experienced by p_span_i in Roadm element. | ||||||
|  |  | ||||||
|     In typical scenarios, users would pick a 32 GBaud channel at 0dBm, which will |     Baud rate is required to find the target power in constant PSD: power = PSD_target * baud_rate. | ||||||
|     neatly lead to the same power spectral density for a 64 GBaud channel at 3 dBm. |     For example, if target PSD is 3.125e4mW/GHz and reference carrier type a 32 GBaud channel then  | ||||||
|  |     output power should be -20 dBm and for a 64 GBaud channel power target would need 3 dB more: -17 dBm. | ||||||
|     Other attributes (like slot_width or roll-off) may be added there for future equalization purpose. |     Other attributes (like slot_width or roll-off) may be added there for future equalization purpose. | ||||||
|     """ |     """ | ||||||
|     baud_rate: float |     baud_rate: float | ||||||
|     req_power: float |  | ||||||
|   | |||||||
| @@ -340,12 +340,12 @@ def compute_constrained_path(network, req): | |||||||
|     return total_path |     return total_path | ||||||
|  |  | ||||||
|  |  | ||||||
| def ref_carrier(req_power, equipment): | def ref_carrier(equipment): | ||||||
|     """Create a reference carier based SI information with the specified request's power: |     """Create a reference carier based SI information with the specified request's power: | ||||||
|     req_power records the power in W that the user has defined for a given request |     req_power records the power in W that the user has defined for a given request | ||||||
|     (which might be different from the one used for the design). |     (which might be different from the one used for the design). | ||||||
|     """ |     """ | ||||||
|     return ReferenceCarrier(baud_rate=equipment['SI']['default'].baud_rate, req_power=req_power) |     return ReferenceCarrier(baud_rate=equipment['SI']['default'].baud_rate) | ||||||
|  |  | ||||||
|  |  | ||||||
| def propagate(path, req, equipment): | def propagate(path, req, equipment): | ||||||
| @@ -353,11 +353,11 @@ def propagate(path, req, equipment): | |||||||
|     """ |     """ | ||||||
|     if req.initial_spectrum is not None: |     if req.initial_spectrum is not None: | ||||||
|         si = carriers_to_spectral_information(initial_spectrum=req.initial_spectrum, |         si = carriers_to_spectral_information(initial_spectrum=req.initial_spectrum, | ||||||
|                                               ref_carrier=ref_carrier(req.power, equipment)) |                                               power=req.power, ref_carrier=ref_carrier(equipment)) | ||||||
|     else: |     else: | ||||||
|         si = create_input_spectral_information( |         si = create_input_spectral_information( | ||||||
|             f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate, |             f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate, | ||||||
|             power=req.power, spacing=req.spacing, tx_osnr=req.tx_osnr) |             power=req.power, spacing=req.spacing, tx_osnr=req.tx_osnr, ref_carrier=ref_carrier(equipment)) | ||||||
|     for i, el in enumerate(path): |     for i, el in enumerate(path): | ||||||
|         if isinstance(el, Roadm): |         if isinstance(el, Roadm): | ||||||
|             si = el(si, degree=path[i+1].uid) |             si = el(si, degree=path[i+1].uid) | ||||||
| @@ -396,12 +396,11 @@ def propagate_and_optimize_mode(path, req, equipment): | |||||||
|                 # this case is not yet handled: spectrum can not be defined for the path-request-run function |                 # this case is not yet handled: spectrum can not be defined for the path-request-run function | ||||||
|                 # and this function is only called in this case. so coming here should not be considered yet. |                 # and this function is only called in this case. so coming here should not be considered yet. | ||||||
|                 msg = f'Request: {req.request_id} contains a unexpected initial_spectrum.' |                 msg = f'Request: {req.request_id} contains a unexpected initial_spectrum.' | ||||||
|                 LOGGER.critical(msg) |  | ||||||
|                 raise ServiceError(msg) |                 raise ServiceError(msg) | ||||||
|             spc_info = create_input_spectral_information(f_min=req.f_min, f_max=req.f_max, |             spc_info = create_input_spectral_information(f_min=req.f_min, f_max=req.f_max, | ||||||
|                                                          roll_off=equipment['SI']['default'].roll_off, |                                                          roll_off=equipment['SI']['default'].roll_off, | ||||||
|                                                          baud_rate=this_br, power=req.power, spacing=req.spacing, |                                                          baud_rate=this_br, power=req.power, spacing=req.spacing, | ||||||
|                                                          tx_osnr=req.tx_osnr) |                                                          tx_osnr=req.tx_osnr, ref_carrier=ref_carrier(equipment)) | ||||||
|             for i, el in enumerate(path): |             for i, el in enumerate(path): | ||||||
|                 if isinstance(el, Roadm): |                 if isinstance(el, Roadm): | ||||||
|                     spc_info = el(spc_info, degree=path[i+1].uid) |                     spc_info = el(spc_info, degree=path[i+1].uid) | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ def test_create_arbitrary_spectral_information(): | |||||||
|                                                baud_rate=32e9, signal=[1, 1, 1], |                                                baud_rate=32e9, signal=[1, 1, 1], | ||||||
|                                                delta_pdb_per_channel=[1, 1, 1], |                                                delta_pdb_per_channel=[1, 1, 1], | ||||||
|                                                tx_osnr=40.0, |                                                tx_osnr=40.0, | ||||||
|                                                ref_power=Pref(1, 1)) |                                                ref_power=Pref(1, 1, None)) | ||||||
|     assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9])) |     assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9])) | ||||||
|     assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9])) |     assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9])) | ||||||
|     assert_array_equal(si.signal, ones(3)) |     assert_array_equal(si.signal, ones(3)) | ||||||
| @@ -35,7 +35,8 @@ def test_create_arbitrary_spectral_information(): | |||||||
|                                                slot_width=array([50e9, 50e9, 50e9]), |                                                slot_width=array([50e9, 50e9, 50e9]), | ||||||
|                                                baud_rate=32e9, signal=array([1, 2, 3]), |                                                baud_rate=32e9, signal=array([1, 2, 3]), | ||||||
|                                                tx_osnr=40.0, |                                                tx_osnr=40.0, | ||||||
|                                                ref_power=Pref(1, 1)) |                                                ref_power=Pref(1, 1, None)) | ||||||
|  |  | ||||||
|     assert_array_equal(si.signal, array([3, 2, 1])) |     assert_array_equal(si.signal, array([3, 2, 1])) | ||||||
|  |  | ||||||
|     with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, ' |     with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, ' | ||||||
| @@ -43,17 +44,16 @@ def test_create_arbitrary_spectral_information(): | |||||||
|         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, |         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, | ||||||
|                                               baud_rate=[64e9, 32e9, 64e9], slot_width=50e9, |                                               baud_rate=[64e9, 32e9, 64e9], slot_width=50e9, | ||||||
|                                               tx_osnr=40.0, |                                               tx_osnr=40.0, | ||||||
|                                               ref_power=Pref(1, 1)) |                                               ref_power=Pref(1, 1, None)) | ||||||
|     with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' |     with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' | ||||||
|                                             r'distances between channels: \[\(1, 2\), \(3, 4\)\].'): |                                             r'distances between channels: \[\(1, 2\), \(3, 4\)\].'): | ||||||
|         create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1, |         create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1, | ||||||
|                                               tx_osnr=40.0, baud_rate=32e9, slot_width=50e9, ref_power=Pref(1, 1)) |                                               tx_osnr=40.0, baud_rate=32e9, slot_width=50e9, ref_power=Pref(1, 1, None)) | ||||||
|     with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' |     with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' | ||||||
|                                             r'distances between channels: \[\(1, 2\), \(2, 3\)\].'): |                                             r'distances between channels: \[\(1, 2\), \(2, 3\)\].'): | ||||||
|         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9, |         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9, | ||||||
|                                               tx_osnr=40.0, roll_off=0.1, ref_power=Pref(1, 1)) |                                               tx_osnr=40.0, roll_off=0.1, ref_power=Pref(1, 1, None)) | ||||||
|  |  | ||||||
|     with pytest.raises(SpectrumError, |     with pytest.raises(SpectrumError, | ||||||
|                        match='Dimension mismatch in input fields.'): |                        match='Dimension mismatch in input fields.'): | ||||||
|         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9, |         create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9, | ||||||
|                                               tx_osnr=40.0, ref_power=Pref(1, 1)) |                                               tx_osnr=40.0, ref_power=Pref(1, 1, None)) | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ def test_fiber(): | |||||||
|     baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9]) |     baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9]) | ||||||
|     signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4]) |     signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4]) | ||||||
|     delta_pdb_per_channel = [0, 0, 0, 0, 0] |     delta_pdb_per_channel = [0, 0, 0, 0, 0] | ||||||
|     pref = Pref(p_span0=0, p_spani=0) |     pref = Pref(p_span0=0, p_spani=0, ref_carrier=None) | ||||||
|     spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width, |     spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width, | ||||||
|                                                                 signal=signal, baud_rate=baud_rate, roll_off=0.15, |                                                                 signal=signal, baud_rate=baud_rate, roll_off=0.15, | ||||||
|                                                                 delta_pdb_per_channel=delta_pdb_per_channel, |                                                                 delta_pdb_per_channel=delta_pdb_per_channel, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 EstherLerouzic
					EstherLerouzic