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]
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_
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]
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]
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
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
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)
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
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([])