Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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])
Beispiel #4
0
    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)
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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))
Beispiel #8
0
 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
Beispiel #9
0
    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
Beispiel #10
0
    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
Beispiel #11
0
    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)))
Beispiel #12
0
    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
Beispiel #13
0
    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