def rk4ip_gnlse(f: AbstractEquation, waves: Array[cst.NPFT], h: float, z: float) -> Array[cst.NPFT]: if (len(waves) == 1): h_h = 0.5 * h A = copy.deepcopy(waves[0]) exp_op_lin = f.exp_op_lin(waves, 0, h_h) #if (Solver.rk4ip_gnlse.first_rk4ip_gnlse_iter): A_lin = exp_op_lin * FFT.fft(A) # Solver.rk4ip_gnlse.first_rk4ip_gnlse_iter = False #else: # A_lin = exp_op_lin * Solver.rk4ip_gnlse.fft_A_next k_0 = h * exp_op_lin * f.op_non_lin_rk4ip(waves, 0) waves[0] = FFT.ifft(A_lin + k_0 / 2) k_1 = h * f.op_non_lin_rk4ip(waves, 0) waves[0] = FFT.ifft(A_lin + k_1 / 2) k_2 = h * f.op_non_lin_rk4ip(waves, 0) waves[0] = FFT.ifft(exp_op_lin * (A_lin + k_0 / 2)) k_3 = h * f.op_non_lin_rk4ip(waves, 0) #Solver.rk4ip_gnlse.fft_A_next = k_3/6 + (exp_op_lin # * (A_lin + k_0/6 + (k_1+k_2)/3)) waves[0] = FFT.ifft(k_3 / 6 + (exp_op_lin * (A_lin + k_0 / 6 + (k_1 + k_2) / 3))) return waves else: util.warning_terminal("rk4ip with more than two fields " "currently not supported") return waves
def __call__(self, domain: Domain, ports: List[int], fields: List[Field]) -> Tuple[List[int], List[Field]]: output_fields: List[Field] = [] gain_in_bw_lin = cmath.sqrt(util.db_to_linear(self.gain_in_bw)) gain_out_bw_lin = cmath.sqrt(util.db_to_linear(self.gain_out_bw)) for field in fields: # Pulse for i in range(len(field)): nu: np.ndarray = field.nu[i] - self.nu_offset nu_gains = np.where((nu > (self.center_nu + self.nu_bw)) | (nu < (self.center_nu - self.nu_bw)), gain_out_bw_lin, gain_in_bw_lin) nu_gains_shift = FFT.ifftshift(nu_gains) field[i] = FFT.ifft(nu_gains_shift * FFT.fft(field[i])) # Noise if (self.NOISE): gain_in_bw_lin_ = util.db_to_linear(self.gain_in_bw) gain_out_bw_lin_ = util.db_to_linear(self.gain_out_bw) nu_noise: np.ndarray = domain.noise_nu nu_gains_ = np.where((nu_noise > (self.center_nu + self.nu_bw)) | (nu_noise < (self.center_nu - self.nu_bw)), gain_out_bw_lin_, gain_in_bw_lin_) print(nu_gains_) field.noise *= nu_gains_ output_fields.append(field) return self.output_ports(ports), output_fields
def exp_term_lin( self, waves: Array[cst.NPFT], id: int, h: float, corr_wave: Optional[Array[cst.NPFT]] = None) -> Array[cst.NPFT]: if (corr_wave is None): corr_wave = waves[id] return FFT.ifft( self.exp_op_lin(waves, id, h, corr_wave) * FFT.fft(corr_wave))
def __call__(self, domain: Domain, ports: List[int], fields: List[Field] ) -> Tuple[List[int], List[Field]]: output_fields: List[Field] = [] for field in fields: # Channels for i in range(len(field)): window = np.zeros(field[i].shape, dtype=complex) window = FlatTopFilter.amplitude_transfer_function(field.nu[i], self.center_nu, self.nu_bw, self.nu_offset) window_shift = FFT.ifftshift(window) field[i] = FFT.ifft(window_shift * FFT.fft(field[i])) # Noise if (self.NOISE): field.noise *= FlatTopFilter.transfer_function(domain.noise_nu, self.center_nu, self.nu_bw, self.nu_offset) output_fields.append(field) return self.output_ports(ports), output_fields
def op_non_lin(self, waves: Array[cst.NPFT], id: int, corr_wave: Optional[Array[cst.NPFT]] = None ) -> Array[cst.NPFT]: r"""Represent the non linear effects of the approximated NLSE. Parameters ---------- waves : The wave packet propagating in the fiber. id : The ID of the considered wave in the wave packet. corr_wave : Correction wave, use for consistency. Returns ------- : The non linear term for the considered wave. Notes ----- .. math:: \hat{N} = \mathcal{F}^{-1}\bigg\{i \gamma \Big(1+\frac{\omega}{\omega_0}\Big) \mathcal{F}\Big\{ (1-f_R) |A|^2 + f_R \mathcal{F}^{-1}\big\{\mathcal{F}\{h_R\} \mathcal{F}\{|A|^2\}\big\}\Big\}\bigg\} """ res = FFT.ifft(self.op_non_lin_rk4ip(waves, id) * waves[id]) if (corr_wave is None): corr_wave = waves[id] res = np.zeros_like(res) res = np.divide(res, corr_wave, out=res, where=corr_wave!=0) return res
def rk4ip_gnlse(f: AbstractFieldEquation, waves: np.ndarray, z: float, h: float) -> np.ndarray: r"""Optimized Runge-Kutta interaction picture method. Parameters ---------- f : The function to compute. waves : The value of the unknown (waves) at the considered space step. z : The current value of the space variable. h : The step size. Returns ------- : The one step euler computation results. Notes ----- Implementation: .. math:: \begin{align} &A^L_j = \exp\Big(\frac{h}{2}\hat{\mathcal{D}}\Big) \mathcal{F}\{A_j(z)\} &\forall j=1,\ldots,K\\ &k_0 = h \exp\Big(\frac{h}{2}\hat{\mathcal{D}}\Big) \hat{\mathcal{N}}_0\big(A_1(z), \ldots, A_j(z), \ldots, A_K(z)\big)&\forall j=1,\ldots,K\\ &k_1 = h \hat{\mathcal{N}}_0\Big(\mathcal{F}^{-1} \Big\{A^L_{1} +\frac{k_{0,1}}{2},\ldots, A^L_{j}+\frac{k_{0,j}}{2},\ldots, A^L_{K} + \frac{k_{0,K}}{2}\Big\} \Big) &\forall j=1,\ldots,K\\ &k_2 = h \hat{\mathcal{N}}_0\Big(\mathcal{F}^{-1} \Big\{A^L_{1} +\frac{k_{1,1}}{2},\ldots, A^L_{j} +\frac{k_{1,j}}{2},\ldots, A^L_{K} + \frac{k_{1,K}}{2}\Big\} \Big) &\forall j=1,\ldots,K\\ &k_3 = h \hat{\mathcal{N}}_0\Big(\mathcal{F}^{-1} \Big\{\exp\Big(\frac{h}{2}\hat{\mathcal{D}}\Big) (A^L_1 + k_{2, 1}) \Big\},\ldots, \nonumber \\ & \qquad \qquad \quad \mathcal{F}^{-1}\Big\{\exp \Big(\frac{h}{2}\hat{\mathcal{D}}\Big)(A^L_j + k_{2,j}) \Big\}, \ldots,\nonumber\\ & \qquad \qquad \quad \mathcal{F}^{-1}\Big\{\exp\Big( \frac{h}{2}\hat{\mathcal{D}}\Big)(A^L_K + k_{2,K}) \Big\}\Big)&\forall j=1,\ldots,K\\ &A(z+h) = \mathcal{F}^{-1}\Big\{\frac{k_{3,j}}{6} +\exp\Big(\frac{h}{2}\hat{\mathcal{D}}\Big) \big(A^L_{j}+\frac{k_{0,j}}{6}+\frac{k_{1,j}}{3} +\frac{k_{2,j}}{3}\big)\Big\} &\forall j=1,\ldots,K \end{align} where :math:`K` is the number of channels. """ if (isinstance(f, GNLSE) or isinstance(f, AmpGNLSE)): h_h = 0.5 * h exp_op_lin = np.zeros_like(waves) A_L = np.zeros_like(waves) k_0 = np.zeros_like(waves) k_1 = np.zeros_like(waves) k_2 = np.zeros_like(waves) k_3 = np.zeros_like(waves) for i in range(len(waves)): exp_op_lin[i] = f.exp_op_lin(waves, i, h_h) for i in range(len(waves)): A_L[i] = exp_op_lin[i] * FFT.fft(waves[i]) for i in range(len(waves)): k_0[i] = h * exp_op_lin[i] * f.term_rk4ip_non_lin(waves, i, z) for i in range(len(waves)): waves[i] = FFT.ifft(A_L[i] + 0.5*k_0[i]) for i in range(len(waves)): k_1[i] = h * f.term_rk4ip_non_lin(waves, i, z) for i in range(len(waves)): waves[i] = FFT.ifft(A_L[i] + 0.5*k_1[i]) for i in range(len(waves)): k_2[i] = h * f.term_rk4ip_non_lin(waves, i, z) for i in range(len(waves)): waves[i] = FFT.ifft(exp_op_lin[i] * (A_L[i] + k_2[i])) for i in range(len(waves)): k_3[i] = h * f.term_rk4ip_non_lin(waves, i, z) for i in range(len(waves)): waves[i] = ((k_3[i]/6.0) + (exp_op_lin[i] * (A_L[i] + k_0[i]/6.0 + (k_1[i]+k_2[i])/3.0))) waves[i] = FFT.ifft(waves[i]) else: raise RK4IPGNLSEError("Only the the gnlse can be computed with " "the rk4ip_gnlse method.") return waves