mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 18:18:00 +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: | ||||
|     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 | ||||
|     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, | ||||
|                                                                     other.delta_pdb_per_channel), | ||||
|                                        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: | ||||
|             raise SpectrumError('Spectra cannot be summed: channels overlapping.') | ||||
|  | ||||
| @@ -295,7 +296,7 @@ def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, in | ||||
|             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. | ||||
|     all arguments are scalar values""" | ||||
|     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) | ||||
|     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, | ||||
|                                                  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: | ||||
|     """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, | ||||
|     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()) | ||||
|     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()] | ||||
|     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()] | ||||
|     tx_osnr = [c.tx_osnr for c in initial_spectrum.values()] | ||||
|     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, | ||||
|                                                  slot_width=slot_width, 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)) | ||||
|                                                  ref_power=Pref(p_span0=p_span0, p_spani=p_spani, | ||||
|                                                                 ref_carrier=ref_carrier)) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| @@ -345,13 +350,15 @@ class Carrier: | ||||
|  | ||||
| @dataclass | ||||
| class ReferenceCarrier: | ||||
|     """Reference channel is used during autodesign to determine target power | ||||
|     based on power spectral density values during propagation in ROADMs for equalization purpose. | ||||
|     It is also required to correctly compute the loss experienced by p_span_i in Roadm element. | ||||
|     """Reference channel type is used to determine target power out of ROADM for the reference channel when | ||||
|     constant power spectral density (PSD) equalization is set. Reference channel is the type that has been defined | ||||
|     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 | ||||
|     neatly lead to the same power spectral density for a 64 GBaud channel at 3 dBm. | ||||
|     Baud rate is required to find the target power in constant PSD: power = PSD_target * baud_rate. | ||||
|     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. | ||||
|     """ | ||||
|     baud_rate: float | ||||
|     req_power: float | ||||
|   | ||||
| @@ -340,12 +340,12 @@ def compute_constrained_path(network, req): | ||||
|     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: | ||||
|     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). | ||||
|     """ | ||||
|     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): | ||||
| @@ -353,11 +353,11 @@ def propagate(path, req, equipment): | ||||
|     """ | ||||
|     if req.initial_spectrum is not None: | ||||
|         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: | ||||
|         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, | ||||
|             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): | ||||
|         if isinstance(el, Roadm): | ||||
|             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 | ||||
|                 # 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.' | ||||
|                 LOGGER.critical(msg) | ||||
|                 raise ServiceError(msg) | ||||
|             spc_info = create_input_spectral_information(f_min=req.f_min, f_max=req.f_max, | ||||
|                                                          roll_off=equipment['SI']['default'].roll_off, | ||||
|                                                          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): | ||||
|                 if isinstance(el, Roadm): | ||||
|                     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], | ||||
|                                                delta_pdb_per_channel=[1, 1, 1], | ||||
|                                                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.slot_width, array([37.5e9, 37.5e9, 37.5e9])) | ||||
|     assert_array_equal(si.signal, ones(3)) | ||||
| @@ -35,7 +35,8 @@ def test_create_arbitrary_spectral_information(): | ||||
|                                                slot_width=array([50e9, 50e9, 50e9]), | ||||
|                                                baud_rate=32e9, signal=array([1, 2, 3]), | ||||
|                                                tx_osnr=40.0, | ||||
|                                                ref_power=Pref(1, 1)) | ||||
|                                                ref_power=Pref(1, 1, None)) | ||||
|  | ||||
|     assert_array_equal(si.signal, array([3, 2, 1])) | ||||
|  | ||||
|     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, | ||||
|                                               baud_rate=[64e9, 32e9, 64e9], slot_width=50e9, | ||||
|                                               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 ' | ||||
|                                             r'distances between channels: \[\(1, 2\), \(3, 4\)\].'): | ||||
|         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 ' | ||||
|                                             r'distances between channels: \[\(1, 2\), \(2, 3\)\].'): | ||||
|         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, | ||||
|                        match='Dimension mismatch in input fields.'): | ||||
|         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]) | ||||
|     signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4]) | ||||
|     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, | ||||
|                                                                 signal=signal, baud_rate=baud_rate, roll_off=0.15, | ||||
|                                                                 delta_pdb_per_channel=delta_pdb_per_channel, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 EstherLerouzic
					EstherLerouzic