Example #1
0
    def __init__(self,
                 dopant: str = cst.DEF_FIBER_DOPANT,
                 medium: str = cst.DEF_FIBER_MEDIUM,
                 T: float = cst.TEMPERATURE,
                 sigma_e: Optional[Union[float, Callable]] = None) -> None:
        r"""
        Parameters
        ----------
        dopant :
            The doping medium.
        medium :
            The fiber medium.
        T :
            The absolute temperature. :math:`[K]`
        sigma_e :
            A callable which return the emission cross section.
            :math:`[nm^2]` If a callable, the parameters must be the
            angular frequencies. :math:`[ps^{-1}]` If none is provided,
            use fitting formulas.

        """
        self._dopant: str = util.check_attr_value(dopant.lower(), DOPANTS,
                                                  cst.DEF_FIBER_DOPANT)
        self._medium: str = util.check_attr_value(medium.lower(), MEDIA,
                                                  cst.DEF_FIBER_MEDIUM)
        self._T: float = T
        self._sigma_e: Optional[Union[float, Callable]] = sigma_e
        self._coefficients = DOPANT_FIT_COEFF[self._dopant]
        self._lambda_range = DOPANT_RANGE[self._dopant]
Example #2
0
    def __init__(
        self,
        dopant: str = cst.DEF_FIBER_DOPANT,
        medium: str = cst.DEF_FIBER_DOPANT,
        stark_energies: STARK_ENERGIES_TYPE = ([], [])
    ) -> None:
        """
        Parameters
        ----------
        dopant :
            The doping medium.
        medium :
            The fiber medium.
        stark_energies :
            The stark energies of the first level and the second level.
            The first element of the tuple is a list with all stark
            energies of the first level and the second element of the
            tuple is a list with all stark energies of the second level.
            :math:`[cm^{-1}]` (dopant and medium will be ignored if
            stark_energies are provided)

        """
        self._dopant: str = util.check_attr_value(dopant.lower(), DOPANT,
                                                  cst.DEF_FIBER_DOPANT)
        self._medium: str = util.check_attr_value(medium.lower(),
                                                  MEDIA[self._dopant],
                                                  cst.DEF_FIBER_MEDIUM)
        self._stark_energies: STARK_ENERGIES_TYPE = ([], [])
        if (stark_energies != ([], [])):
            self._stark_energies = stark_energies
        else:
            data = STARK.get(self._dopant)
            if (data is not None):
                stark = data.get(self._medium)
                if (stark is not None):
                    self._stark_energies = stark
                else:
                    util.warning_terminal(
                        "The specify medium {} for the "
                        "dopant {} for Mccumber relations is not valid.".
                        format(self._medium, self._dopant))
                    stark_ = data.get(cst.DEF_FIBER_MEDIUM)
                    if (stark_ is not None):  # Should be obvious (for typing)
                        self._stark_energies = stark_
            else:
                util.warning_terminal(
                    "The specify dopant medium {} for "
                    "Mccumber relations is not valid.".format(self._dopant))
                data_ = STARK.get(cst.DEF_FIBER_DOPANT)
                if (data_ is not None):  # Should be obvious (for typing)
                    stark_ = data_.get(cst.DEF_FIBER_MEDIUM)
                    if (stark_ is not None):  # Same, it is obvious
                        self._stark_energies = stark_
Example #3
0
    def __init__(self, medium: str, n_0: Union[float, Callable],
                 N: Union[float, Callable]) -> None:
        r"""
        Parameters
        ----------
        medium :
            The medium in which the wave propagates.
        n_0 :
            The raw refratvie index of the medium.  If a
            callable is provided, the variable must be angular
            frequency. :math:`[ps^{-1}]`
        N :
            The population of the metastable level. :math:`[nm^{-3}]`
            If a callable is provided, the variable must be angular
            frequency. :math:`[ps^{-1}]`

        """
        self._medium: str = util.check_attr_value(medium.lower(), MEDIA,
                                                  cst.DEF_FIBER_DOPANT)
        self._n_0: Union[float, Callable] = n_0
        self._N: Union[float, Callable] = N
        self._main_trans = main_trans_values[self._medium]
        self._gs = g_values[self._medium]
        self._esa = esa_values[self._medium]
        self._gsa = gsa_values[self._medium]
Example #4
0
    def __init__(
            self,
            medium: str = cst.DEF_FIBER_MEDIUM,
            factor: Optional[float] = None,
            coefficients: Optional[List[Tuple[float, float]]] = None) -> None:
        r"""The non linear index.

        Parameters
        ----------
        medium :
            The medium in which the wave propagates.
        factor :
            Number which will multiply the fitting formula.
        coefficients :
            Coefficients of the fitting formula. [(coeff, expo), ..]

        """
        self._medium: str = util.check_attr_value(medium.lower(), MEDIA,
                                                  cst.DEF_FIBER_MEDIUM)
        self._factor: float
        self._coefficients: List[Tuple[float, float]]
        if (factor is not None and coefficients is not None):
            self._factor = factor
            self._coefficients = coefficients
        else:
            self._factor = POLY_FACTOR[self._medium]
            self._coefficients = POLY_COEFF[self._medium]
Example #5
0
 def __init__(self,
              func: Callable,
              method: str = cst.DFT_ROOTMETHOD,
              error: float = 1e-6) -> None:
     self._func: Callable = func
     self._method: str = util.check_attr_value(method, METHODS,
                                               cst.DFT_ROOTMETHOD)
     self._error: float = error
Example #6
0
    def __init__(self,
                 medium: str = cst.DEF_FIBER_MEDIUM,
                 dopant: str = cst.FIBER_CORE_DOPANT,
                 dopant_concent: float = 0.0) -> None:
        r"""
        Parameters
        ----------
        medium :
            The medium in which the wave propagates.
        dopant :
            The dopant of the medium.
        dopant_concent :
            The concentration of the dopant. [mole%]

        """
        self._medium = util.check_attr_value(medium.lower(), MEDIA,
                                             cst.DEF_FIBER_MEDIUM)
        self._dopant = util.check_attr_value(dopant.lower(), DOPANTS,
                                             cst.FIBER_CORE_DOPANT)
        self._As: List[float] = COEFF_VALUES[self._medium][0]
        self._lambdas: List[float] = COEFF_VALUES[self._medium][1]
        self._dopant_slope: float = DOPANT_VALUES[self._dopant]
        self._dopant_concent: float = dopant_concent
Example #7
0
 def __init__(self,
              func: Callable,
              method: str = cst.DFT_GRADIENTMETHOD) -> None:
     self._func: Callable = func
     self._method: str = util.check_attr_value(method, METHODS,
                                               cst.DFT_GRADIENTMETHOD)
Example #8
0
    def __init__(self,
                 solvers: List[AbstractSolver],
                 noise_solvers: List[Optional[AbstractSolver]] = [None],
                 length: float = 1.0,
                 steps: List[int] = [100],
                 step_method: List[str] = [FIXED],
                 solver_order: str = FOLLOWING,
                 stepper_method: List[str] = [FORWARD],
                 solver_sequence: Optional[List[int]] = None,
                 boundary_cond: Optional[AbstractBoundaryConditions] = None,
                 conv_checker: Optional[AbstractConvergenceChecker] = None,
                 save_all: bool = False) -> None:
        r"""
        Parameters
        ----------
        solvers :
            The solvers used to solve the equations.
        nlse_solvers :
            The solvers used to solve the noise equations.
        length :
            The length over which the equation is considered.
            :math:`[km]`
        steps :
            The number of steps used for the computation.
        step_method :
            The method used to update the step size.
        solver_order :
            The order type in which the methods will be computed. (will
            be ignored if solver_sequence is provided)
        stepper_method :
            The method used to converge to solution.
        solver_sequence :
            The sequence in which the methods will be computed.
        boundary_cond : AbstractBoundaryConditions
            The boundaries conditions.
        conv_checker : AbstractConvergenceChecker
            The convergence checker.
        save_all :
            If True, will save all channels of all fields at each space
            step during the equation resolution. The number of step
            recorded depends on the :attr:`memory_storage` attribute
            of :class:`layout.Layout`.

        """
        # Attr types check ---------------------------------------------
        util.check_attr_type(length, 'length', int, float)
        util.check_attr_type(steps, 'steps', int, list)
        util.check_attr_type(step_method, 'step_method', str, list)
        util.check_attr_type(solver_order, 'solver_order', str)
        util.check_attr_type(stepper_method, 'stepper_method', str, list)
        util.check_attr_type(boundary_cond, 'boundary_cond',
                             AbstractBoundaryConditions, None)
        util.check_attr_type(conv_checker, 'conv_checker',
                             AbstractConvergenceChecker, None)
        util.check_attr_type(save_all, 'save_all', bool)
        # Attr ---------------------------------------------------------
        self._solvers: List[AbstractSolver] = util.make_list(solvers)
        self._nbr_solvers: int = len(self._solvers)
        self._noise_solvers: List[Optional[AbstractSolver]]
        self._noise_solvers = util.make_list(noise_solvers, self._nbr_solvers,
                                             None)
        self._eqs: List[SOLVER_CALLABLE_TYPE]
        self._eqs = [self._solvers[i].f for i in range(self._nbr_solvers)]
        self._steps: List[int] = util.make_list(steps, self._nbr_solvers)
        self._length: float = length
        # Stepper method
        stepper_method = util.make_list(stepper_method, self._nbr_solvers)
        self._stepper_method_str: List[str] = []
        self._stepper_method: List[STEPPER_METHOD_TYPE] = []
        for i in range(len(stepper_method)):
            self._stepper_method_str.append(
                util.check_attr_value(stepper_method[i].lower(),
                                      STEPPER_METHODS, FORWARD))
            self._stepper_method.append(
                getattr(
                    self,
                    "_{}_method".format(self._stepper_method_str[i].lower())))
        # Step method
        step_method = util.make_list(step_method, self._nbr_solvers)
        self._step_method_str: List[str] = []
        self._step_method: List[STEP_METHOD_TYPE] = []
        for i in range(len(step_method)):
            self._step_method_str.append(
                util.check_attr_value(step_method[i].lower(), STEP_METHODS,
                                      FIXED))
            self._step_method.append(
                getattr(self,
                        "_{}_step".format(self._step_method_str[i].lower())))
        # Solver order
        solver_order = util.check_attr_value(solver_order.lower(),
                                             SOLVER_ORDERS, FOLLOWING)
        if (solver_sequence is None):
            if (solver_order.lower() == ALTERNATING):
                solver_sequence = [0 for i in range(self._nbr_solvers)]
            if (solver_order.lower() == FOLLOWING):
                solver_sequence = [i for i in range(self._nbr_solvers)]
        else:
            solver_sequence = solver_sequence
        self._solver_seq_ids: List[List[int]] =\
            self._get_seq_ids(solver_sequence)
        self.save_all: bool = save_all
        self._avail_memory: float = 0.
        self._save_step: int = 0
        self._enough_space: bool = False
        self._storage: Storage = Storage()
        self._channels: np.ndarray = np.array([])
        self._noises: np.ndarray = np.array([])
        self._space: np.ndarray = np.array([])
        self._conv_checker: Optional[AbstractConvergenceChecker] = conv_checker
        self._boundary_cond: Optional[
            AbstractBoundaryConditions] = boundary_cond
Example #9
0
    def __init__(self, re_fiber: AbstractREFiber, gain_order: int,
                 en_sat: List[Optional[Union[float, Callable]]],
                 R_0: Union[float, Callable], R_L: Union[float, Callable],
                 temperature: float, GAIN_SAT: bool, NOISE: bool,
                 split_noise_option: str, UNI_OMEGA: List[bool],
                 STEP_UPDATE: bool) -> None:
        r"""
        Parameters
        ----------
        re_fiber : AbstractREFiber
            The rate equations describing the fiber laser dynamics.
        gain_order :
            The order of the gain coefficients to take into account.
        en_sat :
            The saturation energy. :math:`[J]`  If a callable
            is provided, variable must be angular frequency.
            :math:`[ps^{-1}]` (1<=len(en_sat)<=2 for signal and pump)
        R_0 :
            The reflectivity at the fiber start.  If a callable
            is provided, variable must be angular frequency.
            :math:`[ps^{-1}]`
        R_L :
            The reflectivity at the fiber end.  If a callable
            is provided, variable must be angular frequency.
            :math:`[ps^{-1}]`
        temperature :
            The temperature of the medium. :math:`[K]`
        GAIN_SAT :
            If True, trigger the gain saturation.
        NOISE :
            If True, trigger the noise calculation.
        split_noise_option :
            The way the spontaneous emission power is split among the
            fields.
        UNI_OMEGA :
            If True, consider only the center omega for computation.
            Otherwise, considered omega discretization.  The first
            element is related to the seed and the second to the pump.
        STEP_UPDATE :
            If True, update component parameters at each spatial
            space step by calling the _update_variables method.

        """
        # 4 equations, one for each port. (2 signals + 2 pumps)
        super().__init__(nbr_eqs=4, prop_dir=[True, False, True, False],
                         SHARE_WAVES=True, NOISE=NOISE,
                         STEP_UPDATE=STEP_UPDATE,
                         INTRA_COMP_DELAY=False, INTRA_PORT_DELAY=False,
                         INTER_PORT_DELAY=False)
        self._re = re_fiber
        self._UNI_OMEGA = UNI_OMEGA
        self._n_reso: List[ResonantIndex] = self._re.n_reso
        self._R_L: Union[float, Callable] = R_L
        self._R_0: Union[float, Callable] = R_0
        self._eff_area = self._re.eff_area
        self._overlap = self._re.overlap
        self._sigma_a = self._re.sigma_a
        self._sigma_e = self._re.sigma_e
        # Alias --------------------------------------------------------
        CLE = CallableLittExpr
        # Gain ---------------------------------------------------------
        start_taylor_gain = 1 if GAIN_SAT else 0
        self._gain_coeff: List[DopedFiberGain] = []
        self._absorp_coeff: List[DopedFiberGain] = []
        k: int = 0  # counter
        for i in range(self._nbr_eqs):
            k = i//2
            self._gain_coeff.append(DopedFiberGain(self._sigma_e[k],
                                                   self._overlap[k], 0.))
            self._absorp_coeff.append(DopedFiberGain(self._sigma_a[k],
                                                     self._overlap[k], 0.))
        self._gains: List[Gain] = []
        self._absorps: List[Attenuation] = []
        for i in range(self._nbr_eqs):
            k = i//2
            self._gains.append(Gain(self._gain_coeff[i], gain_order,
                                    start_taylor=start_taylor_gain,
                                    UNI_OMEGA=UNI_OMEGA[k]))
            self._add_lin_effect(self._gains[-1], i, i)
            self._absorps.append(Attenuation(self._absorp_coeff[i], gain_order,
                                             start_taylor=start_taylor_gain,
                                             UNI_OMEGA=UNI_OMEGA[k]))
            self._add_lin_effect(self._absorps[-1], i, i)
        # Gain saturation ----------------------------------------------
        en_sat = util.make_list(en_sat, 2)
        self._sat_gains: Optional[List[GainSaturation]] = None
        if (GAIN_SAT):
            self._sat_gains = []
            start_taylor_gain = 1
            en_sat_: Union[float, Callable]
            for i in range(self._nbr_eqs):
                k = i//2
                crt_en_sat = en_sat[k]
                if (crt_en_sat is None):
                    en_sat_ = EnergySaturation(self._eff_area[k],
                                               self._sigma_a[k],
                                               self._sigma_e[k],
                                               self._overlap[k])
                else:
                    en_sat_ = CLE([np.ones_like, crt_en_sat], ['*'])
                coeff = CLE([self._gain_coeff[i], self._absorp_coeff[i]],
                            ['-'])
                self._sat_gains.append(GainSaturation(coeff, en_sat_,
                                                      UNI_OMEGA=UNI_OMEGA[k]))
                self._add_lin_effect(self._sat_gains[-1], i, i)
        # Noise --------------------------------------------------------
        self._split_noise_option = util.check_attr_value(split_noise_option,
                                                         SPLIT_NOISE_OPTIONS,
                                                         SEED_SPLIT)
        # Reflection coeff ---------------------------------------------
        self._R_0_waves: np.ndarray = np.array([])
        self._R_L_waves: np.ndarray = np.array([])
        self._R_0_noises: np.ndarray = np.array([])
        self._R_L_noises: np.ndarray = np.array([])