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 term_rk4ip(self, waves: np.ndarray, id: int, corr_wave: Optional[np.ndarray] = None) -> np.ndarray: factor = (1 + self._omega * self._S[id]) return factor * FFT.fft(corr_wave * waves[id])
def op_non_lin_rk4ip(self, waves: Array[cst.NPFT], id: int, corr_wave: Optional[Array[cst.NPFT]] = None ) -> Array[cst.NPFT]: C_nl = 1 + self._omega/self._center_omega[id] kerr = ((1.0-self._f_R) * self._effects_non_lin[0].op(waves, id, corr_wave)) raman = self._f_R * self._effects_non_lin[1].op(waves, id, corr_wave) return C_nl * FFT.fft(kerr + raman)
def spectral_power(A, normalize=False): r""" Parameters ---------- A : Pulse field envelope. normalize : If True, normalize the power array. Returns ------- : The spectral power density of the pulse. :math:`[a.u.]` Notes ----- .. math:: P^\lambda(\lambda) = |\mathcal{F}\{A(t)\}|^2 """ if (isinstance(A, List)): res: List[np.ndarray] = [] for i in range(len(A)): res.append(Field.spectral_power(A[i], normalize)) return res else: P: np.ndarray = np.zeros(A.shape) if (A.ndim > 1): # multidimensional for i in range(A.shape[0]): P[i] = np.real(Field.sq_mod(FFT.fft(A[i]))) if (normalize): P[i] /= np.amax(P[i]) P[i] = FFT.ifftshift(P[i]) else: P = np.real(Field.sq_mod(FFT.fft(A))) # np.real to remove 0j if (normalize): P /= np.amax(P) P = FFT.ifftshift(P) return np.real(P) # np.real to remove 0j
def spectral_phase(A, unwrap=False): r""" Parameters ---------- A : Pulse field envelope. unwrap : If True, unwrap the phase array (see numpy.unwrap). Returns ------- : The spectral phase of the pulse. Notes ----- .. math:: \phi(\lambda) = Arg\big(\mathcal{F}\{A(t)\}\big) """ if (isinstance(A, List)): res: List[np.ndarray] = [] for i in range(len(A)): res.append(Field.spectral_phase(A[i], unwrap)) return res else: phase: np.ndarray = np.zeros(A.shape) if (A.ndim > 1): for i in range(A.shape[0]): phase[i] = np.angle(FFT.fft(A[i])) if (unwrap): phase[i] = np.unwrap(phase[i]) phase[i] = FFT.ifftshift(phase[i]) else: phase = np.angle(FFT.fft(A)) if (unwrap): phase = np.unwrap(phase[i]) phase = FFT.ifftshift(phase) return phase
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 h_R(self) -> Array[float]: if (self._h_R is None): if (self._time is None): util.warning_terminal("Must specified time array to" "calculate the Raman response function") else: self._h_R = self.calc_h_R(self._time, self._tau_1, self._tau_2, self._tau_b, self._f_a, self._f_b, self._f_c) # Save fft of h_R bcs might be reused and not change self._fft_h_R = FFT.fft(self._h_R) return self._h_R
def spectral_power(A, normalize=False): if (isinstance(A, List)): res = [] for i in range(len(A)): res.append(Field.spectral_power(A[i], normalize)) return res else: P = np.zeros(A.shape) if (A.ndim > 1): # multidimensional for i in range(A.shape[0]): P[i] = np.real(Field.sq_mod(FFT.fft(A[i]))) if (normalize): P[i] /= np.amax(P[i]) P[i] = FFT.ifftshift(P[i]) else: P = np.real(Field.sq_mod(FFT.fft(A))) # np.real to remove 0j if (normalize): P /= np.amax(P) P = FFT.ifftshift(P) return np.real(P) # np.real to remove 0j
def spectral_power(A: Array, normalize: bool = False): if (A is not None): if (A.ndim > 1): # multidimensional P = np.zeros(A.shape) for i in range(A.shape[0]): P[i] = np.real(Field.sq_mod(FFT.fft(A[i]))) if (normalize): P[i] /= np.amax(P[i]) P[i] = FFT.ifftshift(P[i]) else: P = np.real(Field.sq_mod(FFT.fft(A))) # np.real to remove 0j if (normalize): P /= np.amax(P) P = FFT.ifftshift(P) return np.real(P) # np.real to remove 0j else: util.warning_terminal( "Can not get spectral power of a " "nonexistent field, request ignored, return null field") return None
def calc_raman_gain(omega_bw: float, h_R: Array[float], center_omega: float, n_0: float, f_R: float, n_2: float) -> Array[float]: r"""Calculate the Raman gain. Parameters ---------- omega_bw : The angular frequency bandwidth. :math:`[ps^{-1}]` h_R : The raman response function. :math:`[ps^{-1}]` center_omega : The center angular frequency. :math:`[ps^{-1}]` n_0 : The refractive index. f_R : The fractional contribution of the delayed Raman response. :math:`[]` n_2 : The non-linear index. :math:`[m^2\cdot W^{-1}]` Returns ------- : The Raman gain. Notes ----- .. math:: g_R(\Delta \omega) = \frac{\omega_0}{c n_0} f_R \chi^{(3)} \Im{\hat{h}_R(\Delta \omega)} where: .. math:: \chi^{(3)} = \frac{4\epsilon_0 c n^2}{3} n_2 :math:`\chi^{(3)}` is in :math:`[m^2 \cdot V^{-2}]`. """ n_2 *= 1e36 # m^2 W^{-1} = s^3 kg^-1 -> ps^3 kg^-1 chi_3 = 4 * cst.EPS_0 * cst.LIGHT_SPEED * n_0**2 * n_2 / 3 return (center_omega / cst.LIGHT_SPEED / n_0 * f_R * chi_3 * np.imag(FFT.fft(h_R)))
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 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