def __init__(self, bits: int = 1, bit_width: float = 100.0, samples_per_bit: int = 512, memory_storage: float = 1.0, noise_range: Tuple[float, float] = (900.0, 1600.0), noise_samples: int = 250) -> None: r""" Parameters ---------- bits : Number of bits to consider. bit_width : The width of one bit. :math:`[ps]` samples_per_bit : Number of samples per bit. memory_storage : Max memory available if recording all steps of computation. Will be used if the attribute :attr:`save_all` of :class:`AbstractComponent` is True. :math:`[Gb]` noise_range : The wavelength range in which the noise must be considered. :math:`[nm]` noise_samples : The number of samples in the noise wavelength range. """ # Attr types check --------------------------------------------- util.check_attr_type(bits, 'bits', int) util.check_attr_type(bit_width, 'bit_width', int, float) util.check_attr_type(samples_per_bit, 'samples_per_bit', int) util.check_attr_type(memory_storage, 'memory_storage', int, float) util.check_attr_type(noise_range, 'noise_range', tuple) util.check_attr_type(noise_samples, 'noise_samples', int) # Attr range check --------------------------------------------- util.check_attr_range(bits, 'bits', cst.MIN_BITS, cst.MAX_BITS) util.check_attr_range(samples_per_bit, 'samples_per_bit', cst.MIN_SAMPLES_PER_BIT, cst.MAX_SAMPLES_PER_BIT) util.check_attr_range(bit_width, 'bit_width', cst.MIN_BIT_WIDTH, cst.MAX_BIT_WIDTH) # Attr --------------------------------------------------------- self._memory_storage: float = memory_storage self._bits: int = bits self._samples_per_bit: int = samples_per_bit self._bit_width: float = bit_width self._samples: int = int(self._bits * self._samples_per_bit) # Time --------------------------------------------------------- self._time_window: float = self._bits * self._bit_width self._time, self._dtime = np.linspace(0.0, self._time_window, self._samples, False, True) # Angular Frequency -------------------------------------------- # log for omega compared to t self._omega_window = Domain.nu_to_omega(1.0 / self._dtime) self._omega, self._domega = np.linspace(-0.5 * self._omega_window, 0.5 * self._omega_window, self._samples, False, True) # Noise -------------------------------------------------------- omega_noise_lower = Domain.lambda_to_omega(noise_range[1]) omega_noise_upper = Domain.lambda_to_omega(noise_range[0]) self._noise_omega_window: float = omega_noise_upper - omega_noise_lower self._noise_samples: int = noise_samples self._noise_omega, self._noise_domega = np.linspace( omega_noise_lower, omega_noise_upper, noise_samples, False, True)
def __init__(self, name: str = default_name, length: float = 1.0, alpha: Optional[Union[List[float], Callable]] = None, alpha_order: int = 1, beta: Optional[Union[List[float], Callable]] = None, beta_order: int = 2, gamma: Optional[Union[float, Callable]] = None, gain_order: int = 1, sigma: float = cst.KERR_COEFF, eta: float = cst.XPM_COEFF, T_R: float = cst.RAMAN_COEFF, tau_1: float = cst.TAU_1, tau_2: float = cst.TAU_2, f_R: float = cst.F_R, nl_approx: bool = True, sigma_a: Optional[Union[List[float], Callable]] = None, sigma_e: Optional[Union[List[float], Callable]] = None, n_core: Optional[Union[float, List[float]]] = None, n_clad: Optional[Union[float, List[float]]] = None, NA: Optional[Union[float, List[float]]] = None, temperature: float = 293.15, tau_meta: float = cst.TAU_META, N_T: float = cst.N_T, core_radius: float = cst.CORE_RADIUS, clad_radius: float = cst.CLAD_RADIUS, area_doped: Optional[float] = None, eta_s: float = cst.ETA_SIGNAL, eta_p: float = cst.ETA_PUMP, R_0: float = cst.R_0, R_L: float = cst.R_L, signal_width: List[float] = [1.0], nl_index: Optional[Union[float, Callable]] = None, ATT: bool = True, DISP: bool = True, SPM: bool = True, XPM: bool = False, FWM: bool = False, SS: bool = False, RS: bool = False, GS: bool = True, approx_type: int = cst.DEFAULT_APPROX_TYPE, medium: str = cst.DEF_FIBER_MEDIUM, dopant: str = cst.DEF_FIBER_DOPANT, method: str = "rk4ip", steps: int = 100, solver_order: str = 'following', error: float = 0.01, propagate_pump: bool = False, save: bool = False, save_all: bool = False) -> None: r""" Parameters ---------- name : The name of the component. length : The length of the fiber. :math:`[km]` alpha : The derivatives of the attenuation coefficients. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` alpha_order : The order of alpha coefficients to take into account. (will be ignored if alpha values are provided - no file) beta : The derivatives of the propagation constant. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` beta_order : The order of beta coefficients to take into account. (will be ignored if beta values are provided - no file) gamma : The non linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` gain_order : The order of the gain coefficients to take into account. (from the Rate Equations resolution) eta : Positive term muiltiplying the XPM in other non linear terms of the NLSE. T_R : The raman coefficient. :math:`[]` tau_1 : The inverse of vibrational frequency of the fiber core molecules. :math:`[ps]` tau_2 : The damping time of vibrations. :math:`[ps]` f_R : The fractional contribution of the delayed Raman response. :math:`[]` nl_approx : If True, the approximation of the NLSE is used. sigma_a : The absorption cross sections of the signal and the pump (1<=len(sigma_a)<=2). :math:`[nm^2]` If a callable is provided, varibale must be wavelength. :math:`[nm]` sigma_e : The emission cross sections of the signal and the pump (1<=len(sigma_a)<=2). :math:`[nm^2]` If a callable is provided, varibale must be wavelength. :math:`[nm]` n_core : The refractive index of the core. If the medium is not recognised by Optcom, at least two elements should be provided out of those three: n_core, n_clad, NA. n_clad : The refractive index of the cladding. If the medium is not recognised by Optcom, at least two elements should be provided out of those three: n_core, n_clad, NA. NA : The numerical aperture. If the medium is not recognised by Optcom, at least two elements should be provided out of those three: n_core, n_clad, NA. temperature : The temperature of the medium. :math:`[K]` tau_meta : The metastable level lifetime. :math:`[\mu s]` N_T : The total doping concentration. :math:`[nm^{-3}]` core_radius : The radius of the core. :math:`[\mu m]` clad_radius : The radius of the cladding. :math:`[\mu m]` area_doped : The doped area. :math:`[\mu m^2]` If None, will be approximated to the core area. eta_s : The background signal loss. :math:`[km^{-1}]` eta_p : The background pump loss. :math:`[km^{-1}]` R_0 : The reflectivity at the fiber start. R_L : The reflectivity at the fiber end. signal_width : The width of each channel of the signal. :math:`[ps]` nl_index : The non linear index. Used to calculate the non linear parameter. :math:`[m^2\cdot W^{-1}]` ATT : If True, trigger the attenuation. DISP : If True, trigger the dispersion. SPM : If True, trigger the self-phase modulation. XPM : If True, trigger the cross-phase modulation. FWM : If True, trigger the Four-Wave mixing. SS : If True, trigger the self-steepening. RS : If True, trigger the Raman scattering. GS : If True, trigger the gain saturation. approx_type : The type of the NLSE approximation. medium : The main medium of the fiber amplifier. dopant : The doped medium of the fiber amplifier. method : The solver method type steps : The number of steps for the solver solver_order: The order in which to solve RE and NLSE. Can be either "following" or "alternating". error : The error for convergence criterion of stepper resolution. propagate_pump : If True, the pump is propagated forward in the layout. save : If True, the last wave to enter/exit a port will be saved. save_all : If True, save the wave at each spatial step in the component. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_ALL, cst.OPTI_ALL, cst.OPTI_IN, cst.OPTI_IN] super().__init__(name, default_name, ports_type, save, wait=True) # Attr types check --------------------------------------------- util.check_attr_type(length, 'length', float) util.check_attr_type(alpha, 'alpha', None, Callable, float, List) util.check_attr_type(alpha_order, 'alpha_order', int) util.check_attr_type(beta, 'beta', None, Callable, float, list) util.check_attr_type(beta_order, 'beta_order', int) util.check_attr_type(gamma, 'gamma', None, float, Callable) util.check_attr_type(gain_order, 'gain_order', int) util.check_attr_type(sigma, 'sigma', float) util.check_attr_type(eta, 'eta', float) util.check_attr_type(T_R, 'T_R', float) util.check_attr_type(tau_1, 'tau_1', float) util.check_attr_type(tau_2, 'tau_2', float) util.check_attr_type(f_R, 'f_R', float) util.check_attr_type(nl_approx, 'nl_approx', bool) util.check_attr_type(sigma_a, 'sigma_a', None, float, list, Callable) util.check_attr_type(sigma_e, 'sigma_e', None, float, list, Callable) util.check_attr_type(n_core, 'n_core', None, float, list) util.check_attr_type(n_clad, 'n_clad', None, float, list) util.check_attr_type(NA, 'NA', None, float, list) util.check_attr_type(temperature, 'temperature', float) util.check_attr_type(tau_meta, 'tau_meta', float) util.check_attr_type(N_T, 'N_T', float) util.check_attr_type(core_radius, 'core_radius', float) util.check_attr_type(clad_radius, 'clad_radius', float) util.check_attr_type(area_doped, 'area_doped', None, float) util.check_attr_type(eta_s, 'eta_s', float) util.check_attr_type(eta_p, 'eta_p', float) util.check_attr_type(R_0, 'R_0', float) util.check_attr_type(R_L, 'R_L', float) util.check_attr_type(signal_width, 'signal_width', list) util.check_attr_type(nl_index, 'nl_index', None, float, Callable) util.check_attr_type(ATT, 'ATT', bool) util.check_attr_type(DISP, 'DISP', bool) util.check_attr_type(SPM, 'SPM', bool) util.check_attr_type(XPM, 'XPM', bool) util.check_attr_type(FWM, 'FWM', bool) util.check_attr_type(SS, 'SS', bool) util.check_attr_type(RS, 'RS', bool) util.check_attr_type(GS, 'GS', bool) util.check_attr_type(approx_type, 'approx_type', int) util.check_attr_type(medium, 'medium', str) util.check_attr_type(dopant, 'dopant', str) util.check_attr_type(method, 'method', str) util.check_attr_type(steps, 'steps', int) util.check_attr_type(solver_order, 'solver_order', str) util.check_attr_type(error, 'error', float) util.check_attr_type(propagate_pump, 'propagate_pump', bool) # Attr --------------------------------------------------------- # Component equations ------------------------------------------ step_update: bool = False if (solver_order == 'following') else True re = RE2Fiber(sigma_a, sigma_e, n_core, n_clad, NA, temperature, tau_meta, N_T, core_radius, clad_radius, area_doped, eta_s, eta_p, R_0, R_L, signal_width, medium, dopant, step_update) if (nl_approx): nlse = AmpANLSE(re, alpha, alpha_order, beta, beta_order, gamma, gain_order, sigma, eta, T_R, R_0, R_L, nl_index, ATT, DISP, SPM, XPM, FWM, SS, RS, approx_type, GS, medium, dopant) else: if (SS): nlse = AmpGNLSE(re, alpha, alpha_order, beta, beta_order, gamma, gain_order, sigma, tau_1, tau_2, f_R, R_0, R_L, nl_index, ATT, DISP, SPM, XPM, FWM, GS, medium, dopant) else: nlse = AmpNLSE(re, alpha, alpha_order, beta, beta_order, gamma, gain_order, sigma, tau_1, tau_2, f_R, R_0, R_L, nl_index, ATT, DISP, SPM, XPM, FWM, GS, medium, dopant) # Component stepper -------------------------------------------- # Special case for gnlse and rk4ip method if (SS and not nl_approx and (method == "rk4ip") and cst.RK4IP_GNLSE): method = "rk4ip_gnlse" step_method = "fixed" # for now, only works with "fixed" eqs = [re, nlse] stepper_method: List[str] if (solver_order == 'following'): stepper_method = ['shooting', 'forward'] else: stepper_method = ['shooting', 'shooting'] # if method is empty '', will directly call the equation object self._stepper = Stepper(eqs, ['', method], length, [steps], [step_method], solver_order, stepper_method, error=error, save_all=save_all) self.N_0: Array[float] self.N_1: Array[float] self.power_ase_forward: Array[float] self.power_ase_backward: Array[float] self.power_signal_forward: Array[float] self.power_signal_backward: Array[float] self.power_pump_forward: Array[float] self.power_pump_backward: Array[float] # Policy ------------------------------------------------------- if (propagate_pump): self.add_port_policy( ([0, 2], [1, 1], False), ([0, 3], [1, 1], False), ([1, 2], [0, 0], False), ([1, 3], [0, 1], False)) else: self.add_port_policy( ([0, 2], [1, -1], False), ([0, 3], [1, -1], False), ([1, 2], [0, -1], False), ([1, 3], [0, -1], False)) self.add_wait_policy([0, 2], [0, 3], [1, 2], [1, 3])
def __init__(self, name: str = default_name, channels: int = 1, center_lambda: List[float] = [cst.DEF_LAMBDA], peak_power: List[float] = [1e-3], energy: List[float] = [], offset_nu: List[float] = [0.0], init_phi: List[float] = [0.0], field_name: str = '', save: bool = False, pre_call_code: str = '', post_call_code: str = '') -> None: r""" Parameters ---------- name : The name of the component. channels : The number of channels in the field. center_lambda : The center wavelength of the channels. :math:`[nm]` peak_power : Peak power of the pulses. :math:`[W]` energy : Total power of the pulses. :math:`[J]` (peak_power will be ignored if energy provided) offset_nu : The offset frequency. :math:`[THz]` init_phi : The initial phase of the pulses. field_name : The name of the field. save : If True, the last wave to enter/exit a port will be saved. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_OUT] super().__init__(name, default_name, ports_type, save, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(channels, 'channels', int) util.check_attr_type(center_lambda, 'center_lambda', float, list) util.check_attr_type(peak_power, 'peak_power', float, list) util.check_attr_type(energy, 'energy', None, float, list) util.check_attr_type(offset_nu, 'offset_nu', float, list) util.check_attr_type(init_phi, 'init_phi', float, list) util.check_attr_type(field_name, 'field_name', str) # Attr --------------------------------------------------------- self.channels: int = channels self.center_lambda: List[float] = util.make_list( center_lambda, channels) self.peak_power: List[float] = util.make_list(peak_power, channels) self._energy: List[float] = [] self.energy = energy self.offset_nu: List[float] = util.make_list(offset_nu, channels) self.init_phi: List[float] = util.make_list(init_phi, channels) self.field_name: str = field_name
def __init__(self, name: str = default_name, channels: int = 1, center_lambda: List[float] = [cst.DEF_LAMBDA], position: List[float] = [0.5], width: List[float] = [10.0], fwhm: Optional[List[float]] = None, peak_power: List[float] = [1e-3], rep_freq: List[float] = [0.0], offset_nu: List[float] = [0.0], chirp: List[float] = [0.0], init_phi: List[float] = [0.0], noise: Optional[np.ndarray] = None, field_name: str = '', save: bool = False, pre_call_code: str = '', post_call_code: str = '') -> None: r""" Parameters ---------- name : The name of the component. channels : The number of channels in the field. center_lambda : The center wavelength of the channels. :math:`[nm]` position : Relative position of the pulses in the time window. :math:`\in [0,1]` width : Half width of the pulse. :math:`[ps]` fwhm : Full band width at half maximum. :math:`[ps]` If fwhm is provided, the width will be ignored. If fwhm is not provided or set to None, will use the width. peak_power : Peak power of the pulses. :math:`[W]` rep_freq : The repetition frequency of the pulse in the time window. :math:`[THz]` offset_nu : The offset frequency. :math:`[THz]` chirp : The chirp parameter for chirped pulses. init_phi : The initial phase of the pulses. noise : The initial noise along the pulses. field_name : The name of the field. save : If True, the last wave to enter/exit a port will be saved. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_OUT] super().__init__(name, default_name, ports_type, save, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(channels, 'channels', int) util.check_attr_type(center_lambda, 'center_lambda', float, list) util.check_attr_type(position, 'position', float, list) util.check_attr_type(width, 'width', float, list) util.check_attr_type(fwhm, 'fwhm', float, list, None) util.check_attr_type(peak_power, 'peak_power', float, list) util.check_attr_type(rep_freq, 'rep_freq', float, list) util.check_attr_type(offset_nu, 'offset_nu', float, list) util.check_attr_type(chirp, 'chirp', float, list) util.check_attr_type(init_phi, 'init_phi', float, list) util.check_attr_type(noise, 'noise', None, np.ndarray) util.check_attr_type(field_name, 'field_name', str) # Attr --------------------------------------------------------- self.channels: int = channels self.center_lambda: List[float] = util.make_list( center_lambda, channels) self.position: List[float] = util.make_list(position, channels) self.width: List[float] = util.make_list(width, channels) self._fwhm: Optional[List[float]] self.fwhm = fwhm self.peak_power: List[float] = util.make_list(peak_power, channels) self.rep_freq: List[float] = util.make_list(rep_freq, channels) self.offset_nu: List[float] = util.make_list(offset_nu, channels) self.chirp: List[float] = util.make_list(chirp, channels) self.init_phi: List[float] = util.make_list(init_phi, channels) self.noise: Optional[np.ndarray] = noise self.field_name: str = field_name
def __init__(self, name: str = default_name, length: float = 1.0, alpha: Optional[Union[List[float], Callable]] = None, alpha_order: int = 0, beta: Optional[Union[List[float], Callable]] = None, beta_order: int = 2, gamma: Optional[Union[float, Callable]] = None, sigma: float = cst.XPM_COEFF, eta: float = cst.XNL_COEFF, T_R: float = cst.RAMAN_COEFF, h_R: Optional[Union[float, Callable]] = None, f_R: float = cst.F_R, core_radius: float = cst.CORE_RADIUS, clad_radius: float = cst.CLAD_RADIUS, n_core: Optional[Union[float, Callable]] = None, n_clad: Optional[Union[float, Callable]] = None, NA: Optional[Union[float, Callable]] = None, v_nbr: Optional[Union[float, Callable]] = None, eff_area: Optional[Union[float, Callable]] = None, nl_index: Optional[Union[float, Callable]] = None, nl_approx: bool = True, medium_core: str = cst.FIBER_MEDIUM_CORE, medium_clad: str = cst.FIBER_MEDIUM_CLAD, temperature: float = cst.TEMPERATURE, ATT: bool = True, DISP: bool = True, SPM: bool = True, XPM: bool = False, FWM: bool = False, SS: bool = False, RS: bool = False, XNL: bool = False, NOISE: bool = True, approx_type: int = cst.DEFAULT_APPROX_TYPE, noise_ode_method: str = 'rk4', UNI_OMEGA: bool = True, STEP_UPDATE: bool = False, INTRA_COMP_DELAY: bool = True, INTRA_PORT_DELAY: bool = True, INTER_PORT_DELAY: bool = False, nlse_method: str = "rk4ip", step_method: str = "fixed", steps: int = 100, save: bool = False, save_all: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: r""" Parameters ---------- name : The name of the component. length : The length of the fiber. :math:`[km]` alpha : The derivatives of the attenuation coefficients. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` alpha_order : The order of alpha coefficients to take into account. (will be ignored if alpha values are provided - no file) beta : The derivatives of the propagation constant. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` beta_order : The order of beta coefficients to take into account. (will be ignored if beta values are provided - no file) gamma : The non linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` sigma : Positive term multiplying the XPM terms of the NLSE. eta : Positive term multiplying the cross-non-linear terms of the NLSE. T_R : The raman coefficient. :math:`[]` h_R : The Raman response function values. If a callable is provided, variable must be time. :math:`[ps]` f_R : The fractional contribution of the delayed Raman response. :math:`[]` core_radius : The radius of the core. :math:`[\mu m]` clad_radius : The radius of the cladding. :math:`[\mu m]` n_core : The refractive index of the core. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` n_clad : The refractive index of the clading. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` NA : The numerical aperture. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` v_nbr : The V number. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` eff_area : The effective area. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` nl_index : The non-linear coefficient. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` nl_approx : If True, the approximation of the NLSE is used. medium_core : The medium of the fiber core. medium_clad : The medium of the fiber cladding. temperature : The temperature of the fiber. :math:`[K]` ATT : If True, trigger the attenuation. DISP : If True, trigger the dispersion. SPM : If True, trigger the self-phase modulation. XPM : If True, trigger the cross-phase modulation. FWM : If True, trigger the Four-Wave mixing. SS : bool If True, trigger the self-steepening. RS : If True, trigger the Raman scattering. XNL : If True, trigger cross-non linear effects. approx_type : The type of the NLSE approximation. NOISE : If True, trigger the noise calculation. noise_ode_method : The ode solver method type for noise propagation computation. UNI_OMEGA : If True, consider only the center omega for computation. Otherwise, considered omega discretization. STEP_UPDATE : If True, update fiber parameters at each spatial sub-step. INTRA_COMP_DELAY : If True, take into account the relative time difference, between all waves, that is acquired while propagating in the component. INTRA_PORT_DELAY : If True, take into account the initial relative time difference between channels of all fields but for each port. INTER_PORT_DELAY : If True, take into account the initial relative time difference between channels of all fields of all ports. nlse_method : The nlse solver method type. step_method : The method for spatial step size generation. steps : The number of steps for the solver save : If True, the last wave to enter/exit a port will be saved. save_all : If True, save the wave at each spatial step in the component. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_ALL, cst.OPTI_ALL] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(length, 'length', float) util.check_attr_type(alpha, 'alpha', None, Callable, float, List) util.check_attr_type(alpha_order, 'alpha_order', int) util.check_attr_type(beta, 'beta', None, Callable, float, list) util.check_attr_type(beta_order, 'beta_order', int) util.check_attr_type(gamma, 'gamma', None, float, Callable) util.check_attr_type(sigma, 'sigma', float) util.check_attr_type(eta, 'eta', float) util.check_attr_type(T_R, 'T_R', float) util.check_attr_type(h_R, 'h_R', None, float, callable) util.check_attr_type(f_R, 'f_R', float) util.check_attr_type(core_radius, 'core_radius', float) util.check_attr_type(clad_radius, 'clad_radius', float) util.check_attr_type(n_core, 'n_core', None, float, Callable) util.check_attr_type(n_clad, 'n_clad', None, float, Callable) util.check_attr_type(NA, 'NA', None, float, Callable) util.check_attr_type(v_nbr, 'v_nbr', None, float, Callable) util.check_attr_type(eff_area, 'eff_area', None, float, Callable) util.check_attr_type(nl_index, 'nl_index', None, float, Callable) util.check_attr_type(nl_approx, 'nl_approx', bool) util.check_attr_type(medium_core, 'medium_core', str) util.check_attr_type(medium_clad, 'medium_clad', str) util.check_attr_type(temperature, 'temperature', float) util.check_attr_type(ATT, 'ATT', bool) util.check_attr_type(DISP, 'DISP', bool) util.check_attr_type(SPM, 'SPM', bool) util.check_attr_type(XPM, 'XPM', bool) util.check_attr_type(FWM, 'FWM', bool) util.check_attr_type(SS, 'SS', bool) util.check_attr_type(RS, 'RS', bool) util.check_attr_type(XNL, 'XNL', bool) util.check_attr_type(NOISE, 'NOISE', bool) util.check_attr_type(approx_type, 'approx_type', int) util.check_attr_type(noise_ode_method, 'noise_ode_method', str) util.check_attr_type(UNI_OMEGA, 'UNI_OMEGA', bool) util.check_attr_type(STEP_UPDATE, 'STEP_UPDATE', bool) util.check_attr_type(INTRA_COMP_DELAY, 'INTRA_COMP_DELAY', bool) util.check_attr_type(INTRA_PORT_DELAY, 'INTRA_PORT_DELAY', bool) util.check_attr_type(INTER_PORT_DELAY, 'INTER_PORT_DELAY', bool) util.check_attr_type(nlse_method, 'nlse_method', str) util.check_attr_type(step_method, 'step_method', str) util.check_attr_type(steps, 'steps', int) # Attr --------------------------------------------------------- nlse: AbstractNLSE if (nl_approx or (not RS and not SS)): nlse = ANLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, eta, T_R, core_radius, clad_radius, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, SS, RS, XNL, NOISE, approx_type, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) else: if (SS): nlse = GNLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, eta, h_R, f_R, core_radius, clad_radius, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, XNL, NOISE, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) else: nlse = NLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, eta, h_R, f_R, core_radius, clad_radius, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, XNL, NOISE, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) solver: NLSESolver = NLSESolver(nlse, nlse_method) noise_solver: ODESolver = ODESolver(nlse.calc_noise, 'rk4') self._stepper: FieldStepper = FieldStepper([solver], [noise_solver], length, [steps], [step_method], save_all=save_all) # Policy ------------------------------------------------------- self.add_port_policy(([0], [1], True))
def __init__(self, name: str = default_name, channels: int = 1, center_lambda: List[float] = [cst.DEF_LAMBDA], position: List[float] = [0.5], width: List[float] = [10.0], peak_power: List[float] = [1e-3], bit_rate: List[float] = [0.0], offset_nu: List[float] = [0.0], order: List[int] = [1], chirp: List[float] = [0.0], init_phi: List[float] = [0.0], save: bool = False) -> None: r""" Parameters ---------- name : The name of the component. channels : The number of channels in the field. center_lambda : The center wavelength of the channels. :math:`[nm]` position : Relative position of the pulses in the time window. :math:`\in [0,1]` width : Half width of the pulse. :math:`[ps]` peak_power : Peak power of the pulses. :math:`[W]` bit_rate : Bit rate (repetition rate) of the pulse in the time window. :math:`[THz]` offset_nu : The offset frequency. :math:`[THz]` order : The order of the super gaussian pulse. chirp : The chirp parameter for chirped pulses. init_phi : The initial phase of the pulses. save : If True, the last wave to enter/exit a port will be saved. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_OUT] super().__init__(name, default_name, ports_type, save) # Attr types check --------------------------------------------- util.check_attr_type(channels, 'channels', int) util.check_attr_type(center_lambda, 'center_lambda', float, list) util.check_attr_type(position, 'position', float, list) util.check_attr_type(width, 'width', float, list) util.check_attr_type(peak_power, 'peak_power', float, list) util.check_attr_type(bit_rate, 'bit_rate', float, list) util.check_attr_type(offset_nu, 'offset_nu', float, list) util.check_attr_type(order, 'order', int, list) util.check_attr_type(chirp, 'chirp', float, list) util.check_attr_type(init_phi, 'init_phi', float, list) # Attr --------------------------------------------------------- self.channels: int = channels self.center_lambda: List[float] = util.make_list( center_lambda, channels) self.position: List[float] = util.make_list(position, channels) self.width: List[float] = util.make_list(width, channels) self.peak_power: List[float] = util.make_list(peak_power, channels) self.bit_rate: List[float] = util.make_list(bit_rate, channels) self.offset_nu: List[float] = util.make_list(offset_nu, channels) self.order: List[int] = util.make_list(order, channels) self.chirp: List[float] = util.make_list(chirp, channels) self.init_phi: List[float] = util.make_list(init_phi, channels)
def __init__(self, name: str = default_name, phase_shift: Union[List[float], List[Callable]] = [0.0, 0.0], loss: float = 0.0, ext_ratio: float = 0.0, v_pi: Optional[List[float]] = None, v_bias: Optional[List[float]] = None, v_mod: Optional[List[Callable]] = None, save: bool = False) -> None: r""" Parameters ---------- name : The name of the component. phase_shift : The phase difference induced between the two arms of the MZ. Can be a list of callable with time variable. :math:`[ps]` (will be ignored if (v_pi and v_bias) or (v_pi and v_mod) are provided) loss : The loss induced by the MZ. :math:`[dB]` ext_ratio : The extinction ratio. v_pi : The half-wave voltage. :math:`[V]` v_bias : The bias voltage. :math:`[V]` v_mod : The modulation voltage :math:`[V]`. Must be a callable with time variable. :math:`[ps]` save : If True, the last wave to enter/exit a port will be saved. """ # Parent constructor ------------------------------------------- ports_type = [cst.ANY_ALL, cst.ANY_ALL] super().__init__(name, default_name, ports_type, save) # Attr types check --------------------------------------------- util.check_attr_type(phase_shift, 'phase_shift', float, Callable, list) util.check_attr_type(loss, 'loss', float) util.check_attr_type(ext_ratio, 'ext_ratio', float) util.check_attr_type(v_pi, 'v_pi', None, float, list) util.check_attr_type(v_bias, 'v_bias', None, float, list) util.check_attr_type(v_mod, 'v_mod', None, Callable, list) # Attr --------------------------------------------------------- if (v_pi is not None and (v_bias is not None or v_mod is not None)): pi_ = util.make_list(v_pi, 2) bias_ = util.make_list(v_bias, 2) if v_bias is not None\ else [0.0, 0.0] mod_ = util.make_list(v_mod, 2) if v_mod is not None\ else [lambda t: 0.0, lambda t: 0.0] phase_shift_ = [lambda t: cst.PI * (bias_[0]+mod_[0](t)) / pi_[0], lambda t: cst.PI * (bias_[1]+mod_[1](t)) / pi_[1]] else: phase_shift_ = util.make_list(phase_shift, 2, 0.0) # N.B. name='nocount' to avoid inc. default name counter self._divider = IdealDivider(name='nocount', arms=2, divide=True, ratios=[0.5, 0.5]) self._combiner = IdealCombiner(name='nocount', arms=2, combine=True, ratios=[0.5, 0.5]) self._phasemod_1 = IdealPhaseMod(name='nocount', phase_shift=phase_shift_[0]) self._phasemod_2 = IdealPhaseMod(name='nocount', phase_shift=phase_shift_[1]) self._amp = IdealAmplifier(name='nocount', gain=-loss) # Policy ------------------------------------------------------- self.add_port_policy(([0],[1], True))
def N_T(self, N_T) -> None: util.check_attr_type(N_T, 'N_T', float) self._N_T = N_T
def __init__(self, name: str = default_name, channels: int = 1, center_lambda: List[float] = [cst.DEF_LAMBDA], peak_power: List[float] = [1e-3], total_power: Optional[List[float]] = None, offset_nu: List[float] = [0.0], init_phi: List[float] = [0.0], save: bool = False) -> None: r""" Parameters ---------- name : The name of the component. channels : The number of channels in the field. center_lambda : The center wavelength of the channels. :math:`[nm]` peak_power : Peak power of the pulses. :math:`[W]` total_power : Total power of the pulses. :math:`[W]` (peak_power will be ignored if total_power provided) offset_nu : The offset frequency. :math:`[THz]` init_phi : The initial phase of the pulses. save : If True, the last wave to enter/exit a port will be saved. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_OUT] super().__init__(name, default_name, ports_type, save) # Attr types check --------------------------------------------- util.check_attr_type(channels, 'channels', int) util.check_attr_type(center_lambda, 'center_lambda', float, list) util.check_attr_type(peak_power, 'peak_power', float, list) util.check_attr_type(total_power, 'total_power', None, float, list) util.check_attr_type(offset_nu, 'offset_nu', float, list) util.check_attr_type(init_phi, 'init_phi', float, list) # Attr --------------------------------------------------------- self.channels: int = channels self.center_lambda: List[float] = util.make_list( center_lambda, channels) self.peak_power: List[float] = util.make_list(peak_power, channels) self.total_power: List[float] = [] if (total_power is not None): self.total_power = util.make_list(total_power, channels) self.offset_nu: List[float] = util.make_list(offset_nu, channels) self.init_phi: List[float] = util.make_list(init_phi, channels)
def __init__(self, name: str, default_name: str, ports_type: List[int], save: bool, wait: bool = False, max_nbr_pass: Optional[List[int]] = None) -> None: """ Parameters ---------- name : The name of the component. default_name : The default name of the component. ports_type : Type of each port of the component, give also the number of ports in the component. For types, see :mod:`optcom/utils/constant_values/port_types`. save : If True, will save each field going through each port. The recorded fields can be accessed with the attribute :attr:`fields`. wait : If True, will wait for specified waiting port policy added with the function :func:`AbstractComponent.add_wait_policy`. max_nbr_pass : If not None, no fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. """ # Attr type check ---------------------------------------------- util.check_attr_type(name, 'name', str) util.check_attr_type(default_name, 'default_name', str) util.check_attr_type(ports_type, 'ports_type', list) util.check_attr_type(save, 'save', bool) util.check_attr_type(wait, 'wait', bool) util.check_attr_type(max_nbr_pass, 'max_nbr_pass', None, list) # Nbr of instances and default name management ----------------- self.inc_nbr_instances() self.name: str = name if (name == default_name): if (self._nbr_instances_with_default_name): self.name += ' ' + str(self._nbr_instances_with_default_name) self.inc_nbr_instances_with_default_name() # Others var --------------------------------------------------- self.ports_type: List[int] = ports_type self._nbr_ports: int = len(ports_type) self.save: bool = save # _ports = [(neighbor_comp_1, input_port_neighbor_1), ...] self._ports: List[Optional[Tuple[AbstractComponent, int]]] =\ [None for i in range(self._nbr_ports)] self._fields: List[Optional[Field]] =\ [None for i in range(self._nbr_ports)] self._times: 'AbstractComponent.Times' = self.Times(self._nbr_ports) self._port_policy: Dict[Tuple[int,...], Tuple[int,...]] = {} self._wait_policy: List[List[int]] = [] self._wait: bool = wait self._counter_pass: List[int] = [0 for i in range(self._nbr_ports)] self._max_nbr_pass: List[int] if (max_nbr_pass is None): # 999 bcs max default recursion depth with python self._max_nbr_pass = [999 for i in range(self._nbr_ports)] else: self._max_nbr_pass = util.make_list(max_nbr_pass, self._nbr_ports)
def __init__(self, name: str = default_name, length: float = 1.0, nbr_fibers: int = 2, alpha: OPTIONAL_LIST_CALL_FLOAT = None, alpha_order: int = 1, beta: OPTIONAL_LIST_CALL_FLOAT = None, beta_order: int = 2, gamma: Optional[Union[List[float], List[Callable]]] = None, kappa: Optional[List[List[List[float]]]] = None, sigma: List[float] = [cst.KERR_COEFF], sigma_cross: List[List[float]] = [[cst.KERR_COEFF_CROSS]], eta: float = cst.XPM_COEFF, T_R: float = cst.RAMAN_COEFF, tau_1: float = cst.TAU_1, tau_2: float = cst.TAU_2, f_R: float = cst.F_R, nl_approx: bool = True, NA: Union[List[float], List[Callable]] = [cst.NA], ATT: bool = True, DISP: bool = True, SPM: bool = True, XPM: bool = False, FWM: bool = False, SS: bool = False, RS: bool = False, ASYM: bool = True, COUP: bool = True, approx_type: int = cst.DEFAULT_APPROX_TYPE, medium: str = cst.DEF_FIBER_MEDIUM, c2c_spacing: List[List[float]] = [[cst.C2C_SPACING]], core_radius: List[float] = [cst.CORE_RADIUS], V: List[float] = [cst.V], n_0: List[float] = [cst.REF_INDEX], method: str = "rk4ip", steps: int = 100, save: bool = False, save_all: bool = False, wait: bool = False, max_nbr_pass: Optional[List[int]] = None) -> None: r""" Parameters ---------- name : The name of the component. length : The length of the coupler. :math:`[km]` nbr_fibers : The number of fibers in the coupler. alpha : The derivatives of the attenuation coefficients. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` alpha_order : The order of alpha coefficients to take into account. (will be ignored if alpha values are provided - no file) beta : The derivatives of the propagation constant. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` beta_order : The order of beta coefficients to take into account. (will be ignored if beta values are provided - no file) gamma : The non linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` kappa : The coupling coefficients. :math:`[km^{-1}]` sigma : Positive term multiplying the XPM term of the NLSE. sigma_cross : Positive term multiplying the XPM term of the NLSE inbetween the fibers. eta : Positive term muiltiplying the XPM in other non linear terms of the NLSE. T_R : The raman coefficient. :math:`[]` tau_1 : The inverse of vibrational frequency of the fiber core molecules. :math:`[ps]` tau_2 : The damping time of vibrations. :math:`[ps]` f_R : The fractional contribution of the delayed Raman response. :math:`[]` NA : The numerical aperture. nl_approx : If True, the approximation of the NLSE is used. ATT : If True, trigger the attenuation. DISP : If True, trigger the dispersion. SPM : If True, trigger the self-phase modulation. XPM : If True, trigger the cross-phase modulation. FWM : If True, trigger the Four-Wave mixing. SS : If True, trigger the self-steepening. RS : If True, trigger the Raman scattering. ASYM : If True, trigger the asymmetry effects between cores. COUP : If True, trigger the coupling effects between cores. approx_type : The type of the NLSE approximation. medium : The main medium of the fiber. c2c_spacing : The center to center distance between two cores. :math:`[\mu m]` core_radius : The core radius. :math:`[\mu m]` V : The fiber parameter. n_0 : The refractive index outside of the waveguides. method : The solver method type steps : The number of steps for the solver save : If True, the last wave to enter/exit a port will be saved. save_all : If True, save the wave at each spatial step in the component. wait : If True, wait for another pulse in the anolog port [0 <-> 1, and 2 <-> 3] to launch the simulation. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_ALL for i in range(4)] super().__init__(name, default_name, ports_type, save, wait=wait, max_nbr_pass=max_nbr_pass) # Attr types check --------------------------------------------- util.check_attr_type(length, 'length', float) util.check_attr_type(nbr_fibers, 'nbr_fibers', int) util.check_attr_type(alpha, 'alpha', None, Callable, float, List) util.check_attr_type(alpha_order, 'alpha_order', int) util.check_attr_type(beta, 'beta', None, Callable, float, list) util.check_attr_type(beta_order, 'beta_order', int) util.check_attr_type(gamma, 'gamma', None, float, list, Callable) util.check_attr_type(kappa, 'kappa', None, float, list) util.check_attr_type(sigma, 'sigma', float, list) util.check_attr_type(sigma_cross, 'sigma_cross', float, list) util.check_attr_type(eta, 'eta', float) util.check_attr_type(T_R, 'T_R', float) util.check_attr_type(tau_1, 'tau_1', float) util.check_attr_type(tau_2, 'tau_2', float) util.check_attr_type(f_R, 'f_R', float) util.check_attr_type(nl_approx, 'nl_approx', bool) util.check_attr_type(NA, 'NA', float, list, Callable) util.check_attr_type(ATT, 'ATT', bool) util.check_attr_type(DISP, 'DISP', bool) util.check_attr_type(SPM, 'SPM', bool) util.check_attr_type(XPM, 'XPM', bool) util.check_attr_type(FWM, 'FWM', bool) util.check_attr_type(SS, 'SS', bool) util.check_attr_type(RS, 'RS', bool) util.check_attr_type(ASYM, 'ASYM', bool) util.check_attr_type(COUP, 'COUP', bool) util.check_attr_type(approx_type, 'approx_type', int) util.check_attr_type(medium, 'medium', str) util.check_attr_type(c2c_spacing, 'c2c_spacing', float, list) util.check_attr_type(core_radius, 'core_radius', float, list) util.check_attr_type(V, 'V', float, list) util.check_attr_type(n_0, 'n_0', float, list) util.check_attr_type(method, 'method', str) util.check_attr_type(steps, 'steps', int) # Attr --------------------------------------------------------- if (nl_approx): cnlse = CANLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, eta, T_R, NA, ATT, DISP, SPM, XPM, FWM, SS, RS, ASYM, COUP, approx_type, medium, c2c_spacing, core_radius, V, n_0) else: if (SS): cnlse = CGNLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, tau_1, tau_2, f_R, NA, ATT, DISP, SPM, XPM, FWM, ASYM, COUP, medium, c2c_spacing, core_radius, V, n_0) else: cnlse = CNLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, tau_1, tau_2, f_R, NA, ATT, DISP, SPM, XPM, FWM, ASYM, COUP, medium, c2c_spacing, core_radius, V, n_0) method_2 = 'euler' # only euler for now step_method = 'fixed' # only fixed for now self._stepper = Stepper([cnlse, cnlse], [method, method_2], length, [steps, steps], [step_method], "alternating", save_all=save_all) # Policy ------------------------------------------------------- self.add_port_policy(([0, 1], [2, 3], True)) self.add_wait_policy([0, 1], [2, 3])
def __init__(self, name: str = default_name, arms: int = 2, divide: bool = True, ratios: List[float] = [], NOISE: bool = False, save: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: """ Parameters ---------- name : The name of the component. arms : The number of input arms. divide : If False, propagate a copy of entering fields to each output port. (ratios will be ignored) Otherwise, divide power depending on provided ratios. ratios : A list of ratios where each index is related to one arm. The length of the list should be equal to the number of arms, if not it will be pad to it. The ratio represents the fraction of the power that will be taken from the field arriving at the corresponding arm. If None is provided and divide is set to True, dispatch equally among arms. NOISE : If True, the noise is handled, otherwise is unchanged. save : If True, the last wave to enter/exit a port will be saved. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_IN] + [cst.OPTI_OUT for i in range(arms)] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Check types attr --------------------------------------------- util.check_attr_type(arms, 'arms', int) util.check_attr_type(divide, 'combine', bool) util.check_attr_type(ratios, 'ratios', list) util.check_attr_type(NOISE, 'NOISE', bool) # Attr --------------------------------------------------------- self.divide: bool = divide self.arms: int = arms self.ratios: List[float] if (not ratios): self.ratios = [1.0 / arms for i in range(arms)] else: self.ratios = util.make_list(ratios, arms) self.NOISE = NOISE
def __init__(self, name: str = default_name, length: float = 1.0, nbr_fibers: int = 2, alpha: TAYLOR_COEFF_TYPE_OPTIONAL = [None], alpha_order: int = 0, beta: TAYLOR_COEFF_TYPE_OPTIONAL = [None], beta_order: int = 2, gamma: FLOAT_COEFF_TYPE_OPTIONAL = [None], kappa: TAYLOR_COUP_COEFF_OPTIONAL = [[None]], sigma: List[float] = [cst.XPM_COEFF], sigma_cross: List[List[float]] = [[cst.XPM_COEFF_CROSS]], eta: List[float] = [cst.XNL_COEFF], eta_cross: List[List[float]] = [[cst.XNL_COEFF_CROSS]], T_R: List[float] = [cst.RAMAN_COEFF], h_R: FLOAT_COEFF_TYPE_OPTIONAL = [None], f_R: float = cst.F_R, core_radius: List[float] = [cst.CORE_RADIUS], clad_radius: float = cst.CLAD_RADIUS_COUP, c2c_spacing: List[List[float]] = [[cst.C2C_SPACING]], n_core: FLOAT_COEFF_TYPE_OPTIONAL = [None], n_clad: Optional[Union[float, Callable]] = None, NA: FLOAT_COEFF_TYPE_OPTIONAL = [None], v_nbr: FLOAT_COEFF_TYPE_OPTIONAL = [None], eff_area: FLOAT_COEFF_TYPE_OPTIONAL = [None], nl_index: FLOAT_COEFF_TYPE_OPTIONAL = [None], nl_approx: bool = True, medium_core: List[str] = [cst.FIBER_MEDIUM_CORE], medium_clad: str = cst.FIBER_MEDIUM_CLAD, temperature: float = cst.TEMPERATURE, ATT: bool = True, DISP: bool = True, SPM: bool = True, XPM: bool = False, FWM: bool = False, SS: bool = False, RS: bool = False, XNL: bool = False, ASYM: bool = True, COUP: bool = True, NOISE: bool = True, approx_type: int = cst.DEFAULT_APPROX_TYPE, noise_ode_method: str = 'rk4', UNI_OMEGA: bool = True, STEP_UPDATE: bool = False, INTRA_COMP_DELAY: bool = True, INTRA_PORT_DELAY: bool = True, INTER_PORT_DELAY: bool = False, nlse_method: str = "rk4ip", ode_method: str = "euler", step_method: str = "fixed", steps: int = 100, save: bool = False, save_all: bool = False, wait: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: r""" Parameters ---------- name : The name of the component. length : The length of the coupler. :math:`[km]` nbr_fibers : The number of fibers in the coupler. alpha : The derivatives of the attenuation coefficients. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` alpha_order : The order of alpha coefficients to take into account. (will be ignored if alpha values are provided - no file) beta : The derivatives of the propagation constant. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` beta_order : The order of beta coefficients to take into account. (will be ignored if beta values are provided - no file) gamma : The non linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` kappa : The coupling coefficients. :math:`[km^{-1}]` sigma : Positive term multiplying the XPM terms of the NLSE. sigma_cross : Positive term multiplying the XPM terms of the NLSE inbetween the fibers. eta : Positive term multiplying the cross-non-linear terms of the NLSE. eta_cross : Positive term multiplying the cross-non-linear terms of the NLSE inbetween the fibers. T_R : The raman coefficient. :math:`[]` h_R : The Raman response function values. If a callable is provided, variable must be time. :math:`[ps]` f_R : The fractional contribution of the delayed Raman response. :math:`[]` core_radius : The core radius. :math:`[\mu m]` clad_radius : The radius of the cladding. :math:`[\mu m]` c2c_spacing : The center to center distance between two cores. :math:`[\mu m]` n_core : The refractive index of the core. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` n_clad : The refractive index of the clading. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` NA : The numerical aperture. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` v_nbr : The V number. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` eff_area : The effective area. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` nl_index : The non-linear coefficient. If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` nl_approx : If True, the approximation of the NLSE is used. medium_core : The medium of the fiber core. medium_clad : The medium of the fiber cladding. temperature : The temperature of the fiber. :math:`[K]` ATT : If True, trigger the attenuation. DISP : If True, trigger the dispersion. SPM : If True, trigger the self-phase modulation. XPM : If True, trigger the cross-phase modulation. FWM : If True, trigger the Four-Wave mixing. SS : bool If True, trigger the self-steepening. RS : If True, trigger the Raman scattering. XNL : If True, trigger cross-non linear effects. ASYM : If True, trigger the asymmetry effects between cores. COUP : If True, trigger the coupling effects between cores. NOISE : If True, trigger the noise calculation. approx_type : The type of the NLSE approximation. noise_ode_method : The ode solver method type for noise propagation computation. UNI_OMEGA : If True, consider only the center omega for computation. Otherwise, considered omega discretization. STEP_UPDATE : If True, update fiber parameters at each spatial sub-step. INTRA_COMP_DELAY : If True, take into account the relative time difference, between all waves, that is acquired while propagating in the component. INTRA_PORT_DELAY : If True, take into account the initial relative time difference between channels of all fields but for each port. INTER_PORT_DELAY : If True, take into account the initial relative time difference between channels of all fields of all ports. nlse_method : The nlse solver method type. ode_method : The ode solver method type. step_method : The method for spatial step size generation. steps : The number of steps for the solver save : If True, the last wave to enter/exit a port will be saved. save_all : If True, save the wave at each spatial step in the component. wait : If True, wait for another pulse in the anolog port [0 <-> 1, and 2 <-> 3] to launch the simulation. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_ALL for i in range(4)] super().__init__(name, default_name, ports_type, save, wait=wait, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(length, 'length', float) util.check_attr_type(nbr_fibers, 'nbr_fibers', int) util.check_attr_type(alpha, 'alpha', None, Callable, float, List) util.check_attr_type(alpha_order, 'alpha_order', int) util.check_attr_type(beta, 'beta', None, Callable, float, list) util.check_attr_type(beta_order, 'beta_order', int) util.check_attr_type(gamma, 'gamma', None, float, list, Callable) util.check_attr_type(kappa, 'kappa', None, float, list) util.check_attr_type(sigma, 'sigma', float, list) util.check_attr_type(sigma_cross, 'sigma_cross', float, list) util.check_attr_type(eta, 'eta', float, list) util.check_attr_type(eta_cross, 'eta_cross', float, list) util.check_attr_type(T_R, 'T_R', float, list) util.check_attr_type(f_R, 'f_R', float) util.check_attr_type(core_radius, 'core_radius', float, list) util.check_attr_type(clad_radius, 'clad_radius', float) util.check_attr_type(c2c_spacing, 'c2c_spacing', float, list) util.check_attr_type(n_core, 'n_core', None, float, Callable, list) util.check_attr_type(n_clad, 'n_clad', None, float, Callable, list) util.check_attr_type(NA, 'NA', None, float, Callable, list) util.check_attr_type(v_nbr, 'v_nbr', None, float, Callable, list) util.check_attr_type(eff_area, 'eff_area', None, float, Callable, list) util.check_attr_type(nl_index, 'nl_index', None, float, Callable, list) util.check_attr_type(medium_core, 'medium_core', str, list) util.check_attr_type(medium_clad, 'medium_clad', str) util.check_attr_type(temperature, 'temperature', float) util.check_attr_type(nl_approx, 'nl_approx', bool) util.check_attr_type(ATT, 'ATT', bool) util.check_attr_type(DISP, 'DISP', bool) util.check_attr_type(SPM, 'SPM', bool) util.check_attr_type(XPM, 'XPM', bool) util.check_attr_type(FWM, 'FWM', bool) util.check_attr_type(SS, 'SS', bool) util.check_attr_type(RS, 'RS', bool) util.check_attr_type(XNL, 'XNL', bool) util.check_attr_type(ASYM, 'ASYM', bool) util.check_attr_type(COUP, 'COUP', bool) util.check_attr_type(NOISE, 'NOISE', bool) util.check_attr_type(approx_type, 'approx_type', int) util.check_attr_type(noise_ode_method, 'noise_ode_method', str) util.check_attr_type(UNI_OMEGA, 'UNI_OMEGA', bool) util.check_attr_type(STEP_UPDATE, 'STEP_UPDATE', bool) util.check_attr_type(INTRA_COMP_DELAY, 'INTRA_COMP_DELAY', bool) util.check_attr_type(INTRA_PORT_DELAY, 'INTRA_PORT_DELAY', bool) util.check_attr_type(INTER_PORT_DELAY, 'INTER_PORT_DELAY', bool) util.check_attr_type(nlse_method, 'nlse_method', str) util.check_attr_type(ode_method, 'ode_method', str) util.check_attr_type(step_method, 'step_method', str) util.check_attr_type(steps, 'steps', int) # Attr --------------------------------------------------------- self._NOISE = NOISE cnlse: AbstractCNLSE if (nl_approx or (not RS and not SS)): cnlse = CANLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, eta, eta_cross, T_R, core_radius, clad_radius, c2c_spacing, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, SS, RS, XNL, ASYM, COUP, NOISE, approx_type, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) else: if (SS): cnlse = CGNLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, eta, eta_cross, h_R, f_R, core_radius, clad_radius, c2c_spacing, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, XNL, ASYM, COUP, NOISE, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) else: cnlse = CNLSE(nbr_fibers, alpha, alpha_order, beta, beta_order, gamma, kappa, sigma, sigma_cross, eta, eta_cross, h_R, f_R, core_radius, clad_radius, c2c_spacing, n_core, n_clad, NA, v_nbr, eff_area, nl_index, medium_core, medium_clad, temperature, ATT, DISP, SPM, XPM, FWM, XNL, ASYM, COUP, NOISE, UNI_OMEGA, STEP_UPDATE, INTRA_COMP_DELAY, INTRA_PORT_DELAY, INTER_PORT_DELAY) solvers: List[AbstractSolver] solvers = [ NLSESolver(cnlse, nlse_method), ODESolver(cnlse, ode_method) ] noise_solvers: List[Optional[AbstractSolver]] noise_solvers = [ODESolver(cnlse.calc_noise), None] solver_order: str = "alternating" self._stepper = FieldStepper(solvers, noise_solvers, length, [steps, steps], [step_method], solver_order, save_all=save_all) # Policy ------------------------------------------------------- self.add_port_policy(([0, 1], [2, 3], True)) self.add_wait_policy([0, 1], [2, 3]) # temp self._get_kappa_for_noise = cnlse.get_kappa_for_noise
def __init__(self, name: str = default_name, phase_shift: Union[List[float], List[Callable]] = [0.0, 0.0], loss: float = 0.0, extinction: Optional[float] = None, v_pi: Optional[List[float]] = None, v_bias: Optional[List[float]] = None, v_mod: Optional[List[Callable]] = None, save: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: r""" Parameters ---------- name : The name of the component. phase_shift : The phase difference induced between the two arms of the MZ. Can be a list of callable with time variable. :math:`[ps]` (will be ignored if (v_pi and v_bias) or (v_pi and v_mod) are provided) loss : The loss induced by the MZ. :math:`[dB]` extinction : The extinction ratio. :math:`[dB]` v_pi : The half-wave voltage. :math:`[V]` v_bias : The bias voltage. :math:`[V]` v_mod : The modulation voltage :math:`[V]`. Must be a callable with time variable. :math:`[ps]` save : If True, the last wave to enter/exit a port will be saved. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.ANY_ALL, cst.ANY_ALL] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(phase_shift, 'phase_shift', float, Callable, list) util.check_attr_type(loss, 'loss', float) util.check_attr_type(extinction, 'extinction', None, float) util.check_attr_type(v_pi, 'v_pi', None, float, list) util.check_attr_type(v_bias, 'v_bias', None, float, list) util.check_attr_type(v_mod, 'v_mod', None, Callable, list) # Attr --------------------------------------------------------- self._v_pi: Optional[List[float]] self._v_pi = v_pi if v_pi is None else util.make_list(v_pi, 2) self._v_bias: Optional[List[float]] self._v_bias = v_bias if v_bias is None else util.make_list(v_bias, 2) self._v_mod: Optional[List[Callable]] self._v_mod = v_mod if v_mod is None else util.make_list(v_mod, 2) if (v_pi is not None and (v_bias is not None or v_mod is not None)): self._update_phase_shift() else: self.phase_shift = phase_shift self.loss = loss self._extinction: Optional[float] self.extinction = extinction self._divider = IdealDivider(name='nocount', arms=2, divide=True, ratios=[0.5, 0.5]) # Policy ------------------------------------------------------- self.add_port_policy(([0], [1], True))
def __init__(self, name: str = default_name, channels: int = 1, center_lambda: List[float] = [cst.DEF_LAMBDA], position: List[float] = [0.5], width: List[float] = [10.0], bit_rate: List[float] = [0.0], offset_nu: List[float] = [0.0], order: List[int] = [1], init_phi: List[float] = [0.0], beta_2: List[float] = [-18.0], gamma: List[float] = [1.0], save: bool = False) -> None: r""" Parameters ---------- name : The name of the component. channels : The number of channels in the field. center_lambda : The center wavelength of the channels. :math:`[nm]` position : Relative position of the pulses in the time window. :math:`\in [0,1]` width : Half width of the pulse. :math:`[ps]` bit_rate : Bit rate (repetition rate) of the pulse in the time window. :math:`[THz]` offset_nu : The offset frequency. :math:`[THz]` order : The order of the super soliton pulse. init_phi : The initial phase of the pulses. beta_2 : The GVD term of the dispersion. (must be negative) :math:`[ps^2\cdot km^{-1}]` gamma : The non-linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` save : If True, the last wave to enter/exit a port will be saved. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_OUT] super().__init__(name, default_name, ports_type, save) # Attr types check --------------------------------------------- util.check_attr_type(channels, 'channels', int) util.check_attr_type(center_lambda, 'center_lambda', float, list) util.check_attr_type(position, 'position', float, list) util.check_attr_type(width, 'width', float, list) util.check_attr_type(bit_rate, 'bit_rate', float, list) util.check_attr_type(offset_nu, 'offset_nu', float, list) util.check_attr_type(order, 'order', int, list) util.check_attr_type(init_phi, 'init_phi', float, list) util.check_attr_type(beta_2, 'beta_2', float, list) util.check_attr_type(gamma, 'gamma', float, list) # Attr --------------------------------------------------------- self.channels: int = channels self.center_lambda: List[float] = util.make_list( center_lambda, channels) self.position: List[float] = util.make_list(position, channels) self.width: List[float] = util.make_list(width, channels) self.bit_rate: List[float] = util.make_list(bit_rate, channels) self.offset_nu: List[float] = util.make_list(offset_nu, channels) self.order: List[int] = util.make_list(order, channels) self.init_phi: List[float] = util.make_list(init_phi, channels) self.beta_2: List[float] = util.make_list(beta_2, channels) self.gamma: List[float] = util.make_list(gamma, channels)
def __init__(self, name: str = default_name, arms: int = 2, combine: bool = False, ratios: List[float] = [], NOISE: bool = False, wait: bool = True, save: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: """ Parameters ---------- name : The name of the component. arms : The number of input arms. combine : If False, propagate all incoming fields in the last port. Otherwise, add common channels and append the others to create one single field. Both methods operate depending on ratios provided. ratios : A list of ratios where each index is related to one arm. The length of the list should be equal to the number of arms, if not it will be pad to it. The ratio represents the fraction of the power that will be taken from the field arriving at the corresponding arm. NOISE : If True, the noise is handled, otherwise is unchanged. save : If True, the last wave to enter/exit a port will be saved. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.ANY_IN for i in range(arms)] + [cst.ANY_OUT] super().__init__(name, default_name, ports_type, save, wait=wait, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Check types attr --------------------------------------------- util.check_attr_type(arms, 'arms', int) util.check_attr_type(combine, 'combine', bool) util.check_attr_type(ratios, 'ratios', list) util.check_attr_type(NOISE, 'NOISE', bool) # Attr --------------------------------------------------------- self.arms: int = arms self.ratios: List[float] = [] if (not ratios): self.ratios = [1.0 for i in range(self.arms)] else: self.ratios = ratios self._combine: bool self.combine = combine # also add a part of port policy self.NOISE = NOISE # Policy ------------------------------------------------------- self.add_wait_policy([i for i in range(arms)])
def __init__(self, name: str, default_name: str, ports_type: List[int], save: bool, wait: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: """ Parameters ---------- name : The name of the component. default_name : The default name of the component. ports_type : Type of each port of the component, give also the number of ports in the component. For types, see :mod:`optcom/utils/constant_values/port_types`. save : If True, will save each field going through each port. The recorded fields can be accessed with the attribute :attr:`fields`. wait : If True, will wait for specified waiting port policy added with the function :func:`AbstractComponent.add_wait_policy`. max_nbr_pass : If not None, no fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Attr type check ---------------------------------------------- util.check_attr_type(name, 'name', str) util.check_attr_type(default_name, 'default_name', str) util.check_attr_type(ports_type, 'ports_type', list) util.check_attr_type(save, 'save', bool) util.check_attr_type(wait, 'wait', bool) util.check_attr_type(max_nbr_pass, 'max_nbr_pass', None, list) util.check_attr_type(pre_call_code, 'pre_call_code', str) util.check_attr_type(post_call_code, 'post_call_code', str) # Nbr of instances and default name management ----------------- self.inc_nbr_instances() self.name: str = name if (name == default_name): if (self._nbr_instances_with_default_name): self.name += ' ' + str(self._nbr_instances_with_default_name) self.inc_nbr_instances_with_default_name() # Others var --------------------------------------------------- self._nbr_ports: int = len(ports_type) self.save: bool = save self._storages: List[Storage] = [] self._ports: List[Port] = [] max_nbr_pass_: List[Optional[int]] max_nbr_pass_ = util.make_list(max_nbr_pass, self._nbr_ports) for i in range(self._nbr_ports): max_nbr = max_nbr_pass_[i] if (max_nbr is not None): self._ports.append(Port(self, ports_type[i], max_nbr)) else: self._ports.append(Port(self, ports_type[i])) self._port_policy: Dict[Tuple[int, ...], Tuple[int, ...]] = {} self._wait_policy: List[List[int]] = [] self._wait: bool = wait self.pre_call_code: str = pre_call_code self.post_call_code: str = post_call_code self.call_counter: int = 0 self._ptr: int = 0 # for __iter__() method
def __init__(self, name: str = default_name, center_nu: float = cst.DEF_NU, nu_bw: float = 1.0, nu_offset: float = 0.0, order: int = 1, NOISE: bool = True, save: bool = False, max_nbr_pass: Optional[List[int]] = None, pre_call_code: str = '', post_call_code: str = '') -> None: """ Parameters ---------- name : The name of the component. center_nu : The center frequency. :math:`[ps^{-1}]` nu_bw : The spectral bandwidth. :math:`[ps^{-1}]` Correspond to the FWHM of the Gaussian window. nu_offset : The offset frequency. :math:`[ps^{-1}]` order : The order of the gaussian filter. NOISE : If True, the noise is handled, otherwise is unchanged. save : If True, the last wave to enter/exit a port will be saved. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. pre_call_code : A string containing code which will be executed prior to the call to the function :func:`__call__`. The two parameters `input_ports` and `input_fields` are available. post_call_code : A string containing code which will be executed posterior to the call to the function :func:`__call__`. The two parameters `output_ports` and `output_fields` are available. """ # Parent constructor ------------------------------------------- ports_type = [cst.ANY_ALL, cst.ANY_ALL] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass, pre_call_code=pre_call_code, post_call_code=post_call_code) # Attr types check --------------------------------------------- util.check_attr_type(center_nu, 'center_nu', float) util.check_attr_type(nu_bw, 'nu_bw', float) util.check_attr_type(nu_offset, 'nu_offset', float) util.check_attr_type(order, 'order', int) util.check_attr_type(NOISE, 'NOISE', bool) # Attr --------------------------------------------------------- self.center_nu = center_nu self.nu_bw = nu_bw self.nu_offset = nu_offset self.order = order self.NOISE = NOISE # Policy ------------------------------------------------------- self.add_port_policy(([0], [1], True))
def __init__(self, name: str = default_name, length: float = 1.0, alpha: Optional[Union[List[float], Callable]] = None, alpha_order: int = 1, beta: Optional[Union[List[float], Callable]] = None, beta_order: int = 2, gamma: Optional[Union[float, Callable]] = None, sigma: float = cst.KERR_COEFF, eta: float = cst.XPM_COEFF, T_R: float = cst.RAMAN_COEFF, tau_1: float = cst.TAU_1, tau_2: float = cst.TAU_2, f_R: float = cst.F_R, core_radius: float = cst.CORE_RADIUS, NA: Union[float, Callable] = cst.NA, nl_approx: bool = True, ATT: bool = True, DISP: bool = True, SPM: bool = True, XPM: bool = False, FWM: bool = False, SS: bool = False, RS: bool = False, approx_type: int = cst.DEFAULT_APPROX_TYPE, method: str = "rk4ip", steps: int = 100, medium: str = cst.DEF_FIBER_MEDIUM, save: bool = False, save_all: bool = False, max_nbr_pass: Optional[List[int]] = None) -> None: r""" Parameters ---------- name : The name of the component. length : The length of the fiber. :math:`[km]` alpha : The derivatives of the attenuation coefficients. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` alpha_order : The order of alpha coefficients to take into account. (will be ignored if alpha values are provided - no file) beta : The derivatives of the propagation constant. :math:`[km^{-1}, ps\cdot km^{-1}, ps^2\cdot km^{-1}, ps^3\cdot km^{-1}, \ldots]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` beta_order : The order of beta coefficients to take into account. (will be ignored if beta values are provided - no file) gamma : The non linear coefficient. :math:`[rad\cdot W^{-1}\cdot km^{-1}]` If a callable is provided, variable must be angular frequency. :math:`[ps^{-1}]` sigma : Positive term multiplying the XPM term of the NLSE eta : Positive term muiltiplying the XPM in other non linear terms of the NLSE T_R : The raman coefficient. :math:`[]` tau_1 : The inverse of vibrational frequency of the fiber core molecules. :math:`[ps]` tau_2 : The damping time of vibrations. :math:`[ps]` f_R : The fractional contribution of the delayed Raman response. :math:`[]` core_radius : The radius of the core. :math:`[\mu m]` NA : The numerical aperture. nl_approx : If True, the approximation of the NLSE is used. ATT : If True, trigger the attenuation. DISP : If True, trigger the dispersion. SPM : If True, trigger the self-phase modulation. XPM : If True, trigger the cross-phase modulation. FWM : If True, trigger the Four-Wave mixing. SS : bool If True, trigger the self-steepening. RS : If True, trigger the Raman scattering. approx_type : The type of the NLSE approximation. method : The solver method type steps : The number of steps for the solver medium : The main medium of the fiber. save : If True, the last wave to enter/exit a port will be saved. save_all : If True, save the wave at each spatial step in the component. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. """ # Parent constructor ------------------------------------------- ports_type = [cst.OPTI_ALL, cst.OPTI_ALL] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass) # Attr types check --------------------------------------------- util.check_attr_type(length, 'length', float) util.check_attr_type(alpha, 'alpha', None, Callable, float, List) util.check_attr_type(alpha_order, 'alpha_order', int) util.check_attr_type(beta, 'beta', None, Callable, float, list) util.check_attr_type(beta_order, 'beta_order', int) util.check_attr_type(gamma, 'gamma', None, float, Callable) util.check_attr_type(sigma, 'sigma', float) util.check_attr_type(eta, 'eta', float) util.check_attr_type(T_R, 'T_R', float) util.check_attr_type(tau_1, 'tau_1', float) util.check_attr_type(tau_2, 'tau_2', float) util.check_attr_type(f_R, 'f_R', float) util.check_attr_type(nl_approx, 'nl_approx', bool) util.check_attr_type(core_radius, 'core_radius', float) util.check_attr_type(NA, 'NA', float, Callable) util.check_attr_type(ATT, 'ATT', bool) util.check_attr_type(DISP, 'DISP', bool) util.check_attr_type(SPM, 'SPM', bool) util.check_attr_type(XPM, 'XPM', bool) util.check_attr_type(FWM, 'FWM', bool) util.check_attr_type(SS, 'SS', bool) util.check_attr_type(RS, 'RS', bool) util.check_attr_type(approx_type, 'approx_type', int) util.check_attr_type(method, 'method', str) util.check_attr_type(steps, 'steps', int) util.check_attr_type(medium, 'medium', str) # Attr --------------------------------------------------------- if (nl_approx): nlse = ANLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, eta, T_R, core_radius, NA, ATT, DISP, SPM, XPM, FWM, SS, RS, approx_type, medium) else: if (SS): nlse = GNLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, tau_1, tau_2, f_R, core_radius, NA, ATT, DISP, SPM, XPM, FWM, medium) else: nlse = NLSE(alpha, alpha_order, beta, beta_order, gamma, sigma, tau_1, tau_2, f_R, core_radius, NA, ATT, DISP, SPM, XPM, FWM, medium) # Special case for gnlse and rk4ip method if (SS and not nl_approx and (method == "rk4ip") and cst.RK4IP_GNLSE): method = "rk4ip_gnlse" step_method = "fixed" # to change later when implementing adaptative self._stepper = Stepper([nlse], [method], length, [steps], [step_method], save_all=save_all) # Policy ------------------------------------------------------- self.add_port_policy(([0], [1], True))