diff --git a/gnpy/core/parameters.py b/gnpy/core/parameters.py new file mode 100644 index 00000000..120e0b27 --- /dev/null +++ b/gnpy/core/parameters.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +gnpy.core.parameters +================== + +This module contains all parameters to configure standard network elements. + +""" + +from logging import getLogger +from scipy.constants import c, pi +from numpy import squeeze, log10, exp + + +from gnpy.core.units import UNITS +from gnpy.core.utils import db2lin +from gnpy.core.exceptions import ParametersError + + +logger = getLogger(__name__) + + +class Parameters: + def asdict(self): + class_dict = self.__class__.__dict__ + instance_dict = self.__dict__ + new_dict = {} + for key in class_dict: + if isinstance(class_dict[key],property): + new_dict[key] = instance_dict['_' + key] + return new_dict + + +class PumpParams(Parameters): + def __init__(self, power, frequency, propagation_direction): + self._power = power + self._frequency = frequency + self._propagation_direction = propagation_direction + + @property + def power(self): + return self._power + + @property + def frequency(self): + return self._frequency + + @property + def propagation_direction(self): + return self._propagation_direction + + +class RamanParams(Parameters): + def __init__(self, **kwargs): + self._flag_raman = kwargs['flag_raman'] + self._space_resolution = kwargs['space_resolution'] if 'space_resolution' in kwargs else None + self._tolerance = kwargs['tolerance'] if 'tolerance' in kwargs else None + + @property + def flag_raman(self): + return self._flag_raman + + @property + def space_resolution(self): + return self._space_resolution + + @property + def tolerance(self): + return self._tolerance + + +class NLIParams(Parameters): + def __init__(self, **kwargs): + self._nli_method_name = kwargs['nli_method_name'] + self._wdm_grid_size = kwargs['wdm_grid_size'] + self._dispersion_tolerance = kwargs['dispersion_tolerance'] + self._phase_shift_tolerance = kwargs['phase_shift_tolerance'] + self._f_cut_resolution = None + self._f_pump_resolution = None + self._computed_channels = kwargs['computed_channels'] if 'computed_channels' in kwargs else None + + @property + def nli_method_name(self): + return self._nli_method_name + + @property + def wdm_grid_size(self): + return self._wdm_grid_size + + @property + def dispersion_tolerance(self): + return self._dispersion_tolerance + + @property + def phase_shift_tolerance(self): + return self._phase_shift_tolerance + + @property + def f_cut_resolution(self): + return self._f_cut_resolution + + @f_cut_resolution.setter + def f_cut_resolution(self, f_cut_resolution): + self._f_cut_resolution = f_cut_resolution + + @property + def f_pump_resolution(self): + return self._f_pump_resolution + + @f_pump_resolution.setter + def f_pump_resolution(self, f_pump_resolution): + self._f_pump_resolution = f_pump_resolution + + + @property + def computed_channels(self): + return self._computed_channels + + +class SimParams(Parameters): + def __init__(self, **kwargs): + if kwargs: + if 'nli_parameters' in kwargs: + self._nli_params = NLIParams(**kwargs['nli_parameters']) + else: + self._nli_params = None + if 'raman_parameters' in kwargs: + self._raman_params = RamanParams(**kwargs['raman_parameters']) + else: + self._raman_params = None + + @property + def nli_params(self): + return self._nli_params + + @property + def raman_params(self): + return self._raman_params + + +class FiberParams(Parameters): + def __init__(self, **kwargs): + try: + self._length_units_factor = UNITS[kwargs['length_units']] + self._length = kwargs['length'] * self._length_units_factor # m + self._length_units = 'm' + # fixed attenuator for padding + self._att_in = kwargs['att_in'] if 'att_in' in kwargs else 0 + # if not defined in the network json connector loss in/out + # the None value will be updated in network.py[build_network] + # with default values from eqpt_config.json[Spans] + self._con_in = kwargs['con_in'] if 'con_in' in kwargs else None + self._con_out = kwargs['con_out'] if 'con_out' in kwargs else None + self._gamma = kwargs['gamma'] # 1/W/m + self._dispersion = kwargs['dispersion'] # s/m/m + if 'ref_wavelength' in kwargs: + self._ref_wavelength = kwargs['ref_wavelength'] + self._ref_frequency = c / self._ref_wavelength + elif 'ref_frequency' in kwargs: + self._ref_frequency = kwargs['ref_frequency'] + self._ref_wavelength = c / self._ref_frequency + else: + self._ref_wavelength = 1550e-9 + self._ref_frequency = c / self._ref_wavelength + self._beta2 = (self._ref_wavelength ** 2) * abs(self._dispersion) / (2 * pi * c) # 1/(m * Hz^2) + self._beta3 = kwargs['beta3'] if 'beta3' in kwargs else 0 + if type(kwargs['loss_coef']) == dict: + self._loss_coef = squeeze(kwargs['loss_coef']['loss_coef_power']) * 1e-3 # lineic loss dB/m + self._f_loss_ref = squeeze(kwargs['loss_coef']['frequency']) # Hz + else: + self._loss_coef = kwargs['loss_coef'] * 1e-3 # lineic loss dB/m + self._f_loss_ref = 193.5e12 # Hz + self._lin_attenuation = db2lin(self._length * self._loss_coef) + self._lin_loss_exp = self._loss_coef / (10 * log10(exp(1))) # linear power exponent loss Neper/m + self._effective_length = (1 - exp(- self._lin_loss_exp * self._length)) / self._lin_loss_exp + self._asymptotic_length = 1 / self._lin_loss_exp + # raman parameters (not compulsory) + self._raman_efficiency = kwargs['raman_efficiency'] if 'raman_efficiency' in kwargs else None + self._pumps_loss_coef = kwargs['pumps_loss_coef'] if 'pumps_loss_coef' in kwargs else None + except KeyError as e: + raise ParametersError(f'Fiber configurations json must include {e}') + + @property + def length(self): + return self._length + + @length.setter + def length(self, length): + """length must be in m""" + self._length = length + + @property + def length_units(self): + return self._length_units + + @property + def length_units_factor(self): + return self._length_units_factor + + @property + def att_in(self): + return self._att_in + + @att_in.setter + def att_in(self, att_in): + self._att_in = att_in + + @property + def con_in(self): + return self._con_in + + @con_in.setter + def con_in(self, con_in): + self._con_in = con_in + + @property + def con_out(self): + return self._con_out + + @con_out.setter + def con_out(self, con_out): + self._con_out = con_out + + @property + def dispersion(self): + return self._dispersion + + @property + def gamma(self): + return self._gamma + + @property + def ref_wavelength(self): + return self._ref_wavelength + + @property + def ref_frequency(self): + return self._ref_frequency + + @property + def beta2(self): + return self._beta2 + + @property + def beta3(self): + return self._beta3 + + @property + def loss_coef(self): + return self._loss_coef + + @property + def f_loss_ref(self): + return self._f_loss_ref + + @property + def lin_loss_exp(self): + return self._lin_loss_exp + + @property + def lin_attenuation(self): + return self._lin_attenuation + + @property + def effective_length(self): + return self._effective_length + + @property + def asymptotic_length(self): + return self._asymptotic_length + + @property + def raman_efficiency(self): + return self._raman_efficiency + + @property + def pumps_loss_coef(self): + return self._pumps_loss_coef + + def asdict(self): + dictionary = super().asdict() + dictionary['loss_coef'] = self.loss_coef * 1e3 + return dictionary +