mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-30 17:47:50 +00:00 
			
		
		
		
	introcude NLI solver
This commit is contained in:
		| @@ -340,3 +340,108 @@ class RamanSolver: | |||||||
|                 dpdz[f_ind][z_ind] = dpdz_element |                 dpdz[f_ind][z_ind] = dpdz_element | ||||||
|  |  | ||||||
|         return np.vstack(dpdz) |         return np.vstack(dpdz) | ||||||
|  |  | ||||||
|  | class NliSolver: | ||||||
|  |     """ This class implements the NLI models. | ||||||
|  |         Model and method can be specified in `self.nli_params.method`. | ||||||
|  |         List of implemented methods: | ||||||
|  |         'gn_model_analytic': brute force triple integral solution | ||||||
|  |         'GGN_spectrally_separated_xpm_spm': XPM plus SPM | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def __init__(self, nli_params=None, fiber_params=None): | ||||||
|  |         """ Initialize the fiber object with its physical parameters | ||||||
|  |         """ | ||||||
|  |         self.fiber_params = fiber_params | ||||||
|  |         self.nli_params = nli_params | ||||||
|  |         self.srs_profile = None | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def fiber_params(self): | ||||||
|  |         return self.___fiber_params | ||||||
|  |  | ||||||
|  |     @fiber_params.setter | ||||||
|  |     def fiber_params(self, fiber_params): | ||||||
|  |         self.___fiber_params = fiber_params | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def srs_profile(self): | ||||||
|  |         return self.__srs_profile | ||||||
|  |  | ||||||
|  |     @srs_profile.setter | ||||||
|  |     def srs_profile(self, srs_profile): | ||||||
|  |         self.__srs_profile = srs_profile | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def nli_params(self): | ||||||
|  |         return self.__nli_params | ||||||
|  |  | ||||||
|  |     @nli_params.setter | ||||||
|  |     def nli_params(self, nli_params): | ||||||
|  |         """ | ||||||
|  |         :param model_params: namedtuple containing the parameters used to compute the NLI. | ||||||
|  |         """ | ||||||
|  |         self.__nli_params = nli_params | ||||||
|  |  | ||||||
|  |     def alpha0(self, f_eval=193.5e12): | ||||||
|  |         if not hasattr(self.fiber_params.loss_coef, 'alpha_power'): | ||||||
|  |             alpha0 = self.fiber_params.loss_coef | ||||||
|  |         else: | ||||||
|  |             alpha_interp = interp1d(self.fiber_params.loss_coef['frequency'], | ||||||
|  |                                     self.fiber_params.loss_coef['alpha_power']) | ||||||
|  |             alpha0 = alpha_interp(f_eval) | ||||||
|  |         return alpha0 | ||||||
|  |  | ||||||
|  |     def compute_nli(self, carrier, *carriers): | ||||||
|  |         """ Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier` | ||||||
|  |         at the end of the fiber span. | ||||||
|  |         """ | ||||||
|  |         if 'gn_model_analytic' == self.nli_params.nli_method_name.lower(): | ||||||
|  |             carrier_nli = self._gn_analytic(carrier, *carriers) | ||||||
|  |         else: | ||||||
|  |             raise ValueError(f'Method {self.nli_params.method_nli} not implemented.') | ||||||
|  |  | ||||||
|  |         return carrier_nli | ||||||
|  |  | ||||||
|  |     # Methods for computing spectrally separated GN | ||||||
|  |     def _gn_analytic(self, carrier, *carriers): | ||||||
|  |         """ Computes the nonlinear interference power on a single carrier. | ||||||
|  |         The method uses eq. 120 from arXiv:1209.0394. | ||||||
|  |         :param carrier: the signal under analysis | ||||||
|  |         :param carriers: the full WDM comb | ||||||
|  |         :return: carrier_nli: the amount of nonlinear interference in W on the under analysis | ||||||
|  |         """ | ||||||
|  |         alpha = self.alpha0() / 2 | ||||||
|  |         beta2 = self.fiber_params.beta2 | ||||||
|  |         gamma = self.fiber_params.gamma | ||||||
|  |         length = self.fiber_params.length | ||||||
|  |         effective_length = (1 - np.exp(-2 * alpha * length)) / (2 * alpha) | ||||||
|  |         asymptotic_length = 1 / (2 * alpha) | ||||||
|  |  | ||||||
|  |         g_nli = 0 | ||||||
|  |         for interfering_carrier in carriers: | ||||||
|  |             g_interfearing = interfering_carrier.power.signal / interfering_carrier.baud_rate | ||||||
|  |             g_signal = carrier.power.signal / carrier.baud_rate | ||||||
|  |             g_nli += g_interfearing**2 * g_signal * self._psi(carrier, interfering_carrier) | ||||||
|  |         g_nli *= (16.0 / 27.0) * (gamma * effective_length)**2 /\ | ||||||
|  |                  (2 * np.pi * abs(beta2) * asymptotic_length) | ||||||
|  |         carrier_nli = carrier.baud_rate * g_nli | ||||||
|  |         return carrier_nli | ||||||
|  |  | ||||||
|  |     def _psi(self, carrier, interfering_carrier): | ||||||
|  |         """ Calculates eq. 123 from arXiv:1209.0394. | ||||||
|  |         """ | ||||||
|  |         alpha = self.alpha0() / 2 | ||||||
|  |         beta2 = self.fiber_params.beta2 | ||||||
|  |         asymptotic_length = 1 / (2 * alpha) | ||||||
|  |  | ||||||
|  |         if carrier.channel_number == interfering_carrier.channel_number:  # SPM | ||||||
|  |             psi = np.arcsinh(0.5 * np.pi**2 * asymptotic_length | ||||||
|  |                               * abs(beta2) * carrier.baud_rate**2) | ||||||
|  |         else:  # XPM | ||||||
|  |             delta_f = carrier.frequency - interfering_carrier.frequency | ||||||
|  |             psi = np.arcsinh(np.pi**2 * asymptotic_length * abs(beta2) * | ||||||
|  |                              carrier.baud_rate * (delta_f + 0.5 * interfering_carrier.baud_rate)) | ||||||
|  |             psi -= np.arcsinh(np.pi**2 * asymptotic_length * abs(beta2) * | ||||||
|  |                               carrier.baud_rate * (delta_f - 0.5 * interfering_carrier.baud_rate)) | ||||||
|  |         return psi | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Alessio Ferrari
					Alessio Ferrari