예제 #1
0
    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) -> 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.

        """
        # Parent constructor -------------------------------------------
        ports_type = [cst.OPTI_ALL, cst.OPTI_ALL]
        super().__init__(name, default_name, ports_type, save)
        # 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))
예제 #2
0
class FiberAmplifier(AbstractPassComp):
    r"""A non ideal Fiber Amplifier.

    Attributes
    ----------
    name : str
        The name of the component.
    ports_type : list of int
        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 : bool
        If True, the last wave to enter/exit a port will be saved.
    N_0 : numpy.ndarray of float
        The population in the ground state.
    N_1 : numpy.ndarray of float
        The population in the metastable state.
    power_signal_forward : numpy.ndarray of float
        Power of the foward propagating signal for each channel.
    power_signal_backward : numpy.ndarray of float
        Power of the backward propagating signal for each channel.
    power_ase_forward : numpy.ndarray of float
        Power of the foward propagating ase for each channel.
    power_ase_backward : numpy.ndarray of float
        Power of the backward propagating ase for each channel.
    power_pump_forward : numpy.ndarray of float
        Power of the foward propagating pump for each channel.
    power_pump_backward : numpy.ndarray of float
        Power of the backward propagating pump for each channel.

    Notes
    -----
    Component diagram::

        [0] _____________________ [1]
            /                   \
           /                     \
        [2]                       [3]


    [0] and [1] : signal and [2] and [3] : pump

    """

    _nbr_instances: int = 0
    _nbr_instances_with_default_name: int = 0

    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,
                 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,
                 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}]`
        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.
        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.
        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, cst.OPTI_IN, cst.OPTI_IN]
        super().__init__(name,
                         default_name,
                         ports_type,
                         save,
                         wait=True,
                         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(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(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, 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 __call__(self, domain: Domain, ports: List[int],
                 fields: List[Field]) -> Tuple[List[int], List[Field]]:
        output_ports: List[int] = []
        output_fields: List[Field] = []
        pump_ports: List[int] = []
        pump_fields: List[Field] = []
        # Sort fields --------------------------------------------------
        i = 0
        while (i < len(ports)):
            if (ports[i] == 2 or ports[i] == 3):  # Port from pump
                pump_fields.append(fields.pop(i))
                pump_ports.append(ports.pop(i))
            i += 1
        ports.extend(pump_ports)
        # Set shooting method ------------------------------------------
        if (util.sum_elem_list(util.unique(ports)) == 3):
            self._stepper.start_shooting_backward()
            util.warning_terminal(
                "Counter propagating pulses in fiber "
                "amplifier not totally handled yet, might lead to unrealistic "
                "results.")
        else:
            self._stepper.start_shooting_forward()
        # Compute ------------------------------------------------------
        output_fields = self._stepper(domain, fields, pump_fields)
        if (self._stepper.save_all):
            self.storages.append(self._stepper.storage)
        # Record RE parameters -----------------------------------------
        re = self._stepper.equations[0]
        # If shooting method stops earlier than expected, those values
        # won't be accurate anymore. -> need a back up in RE2Fiber ?
        self.N_0 = re.N_0
        self.N_1 = re.N_1
        self.power_ase_forward = re.power_ase_forward
        self.power_ase_backward = re.power_ase_backward
        self.power_signal_forward = re.power_signal_forward
        self.power_signal_backward = re.power_signal_backward
        self.power_pump_forward = re.power_pump_forward
        self.power_pump_backward = re.power_pump_backward

        return self.output_ports(ports), output_fields
예제 #3
0
    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])
예제 #4
0
    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])