예제 #1
0
    def __call__(self, domain: Domain) -> Tuple[List[int], List[Field]]:

        output_ports: List[int] = []
        output_fields: List[Field] = []
        field = Field(domain, cst.OPTI, self.field_name)
        # Check offset -------------------------------------------------
        for i in range(len(self.offset_nu)):
            if (abs(self.offset_nu[i]) > domain.nu_window):
                self.offset_nu[i] = 0.0
                util.warning_terminal(
                    "The offset of channel {} in component "
                    "{} is bigger than half the frequency window, offset will "
                    "be ignored.".format(str(i), self.name))
        # Field initialization -----------------------------------------
        if (self.energy):
            peak_power: List[float] = []
            time_window = domain.time_window * 1e-12  # ps -> s
            for i in range(len(self.energy)):
                peak_power.append(self.energy[i] / time_window)
        else:
            peak_power = self.peak_power
        rep_freq = np.nan
        for i in range(self.channels):  # Nbr of channels
            res = np.zeros(domain.time.shape, dtype=cst.NPFT)
            phi = (self.init_phi[i] -
                   Domain.nu_to_omega(self.offset_nu[i]) * domain.time)
            res += math.sqrt(peak_power[i]) * np.exp(1j * phi)
            field.add_channel(res,
                              Domain.lambda_to_omega(self.center_lambda[i]),
                              rep_freq)

        output_fields.append(field)
        output_ports.append(0)

        return output_ports, output_fields
예제 #2
0
    def __call__(self, domain: Domain) -> Tuple[List[int], List[Field]]:

        output_ports: List[int] = []
        output_fields: List[Field] = []
        field = Field(domain, cst.OPTI)
        # Bit rate initialization --------------------------------------
        nbr_pulses = []
        for i in range(self.channels):
            if (self.bit_rate[i]):
                nbr_temp = math.floor(domain.time_window * self.bit_rate[i])
                if (nbr_temp):
                    nbr_pulses.append(nbr_temp)
                else:
                    util.warning_terminal(
                        "In component {}: the time window "
                        "is too thin for the bit rate specified, bit rate "
                        "will be ignored".format(self.name))
                    nbr_pulses.append(1)
            else:
                nbr_pulses.append(1)

        rel_pos = []
        for i in range(self.channels):
            pos_step = 1 / nbr_pulses[i]
            if (nbr_pulses[i] % 2):  # Odd
                dist_from_center = nbr_pulses[i] // 2 * pos_step
            else:
                dist_from_center = (nbr_pulses[i] // 2 -
                                    1) * pos_step + pos_step / 2
            rel_pos.append(
                np.linspace(self.position[i] - dist_from_center,
                            self.position[i] + dist_from_center,
                            num=nbr_pulses[i]))
        # Check offset -------------------------------------------------
        for i in range(len(self.offset_nu)):
            if (abs(self.offset_nu[i]) > domain.nu_window):
                self.offset_nu[i] = 0.0
                util.warning_terminal(
                    "The offset of channel {} in component "
                    "{} is bigger than half the frequency window, offset will "
                    "be ignored.".format(str(i), self.name))
        # Field initialization -----------------------------------------
        for i in range(self.channels):  # Nbr of channels
            res = np.zeros(domain.time.shape, dtype=cst.NPFT)
            for j in range(len(rel_pos[i])):
                norm_time = domain.get_shift_time(
                    rel_pos[i][j]) / self.width[i]
                var_time = np.power(norm_time, 2)
                phi = (self.init_phi[i] -
                       Domain.nu_to_omega(self.offset_nu[i]) * domain.time -
                       0.5 * self.chirp[i] * var_time)
                res += (math.sqrt(self.peak_power[i]) / np.cosh(norm_time) *
                        np.exp(1j * phi))
            field.append(res, Domain.lambda_to_omega(self.center_lambda[i]))

        output_fields.append(field)
        output_ports.append(0)

        return output_ports, output_fields
예제 #3
0
    def fct(op, right_op, field_channel, type, center_omega, rep_freq, samples,
            *operands):
        res = []
        for operand in operands:
            new_field = Field(Domain(samples_per_bit=samples), type)
            for i, channel in enumerate(field_channel):
                new_field.add_channel(channel, center_omega[i], rep_freq[i])
            if (right_op):  # Right operand operator
                res.append(op(operand, new_field))
            else:  # Left operand operator
                res.append(op(new_field, operand))

        return res
    def term(self,
             waves: np.ndarray,
             id: int,
             corr_wave: Optional[np.ndarray] = None) -> np.ndarray:
        """The operator of the emission effect."""

        power = FFT.fftshift(Field.spectral_power(waves[id]))
        power_sum = np.sum(power)
        power = (power / power_sum) if (power_sum) else (power * 0.0)

        power *= Field.average_power(waves[id], self.dtime, self.rep_freq[id])

        return np.real(np.sum(self.op(waves, id, corr_wave) * power))
예제 #5
0
def test_same_omega(operator_fixture, op, right_op):
    """Should not fail if the center omega are the same and in the same
    order."""
    length = 12
    field = Field(Domain(samples_per_bit=length), type_op_test)
    center_omegas = [1030., 1025., 1020.]
    rep_freqs = [1., 2., 3.]
    channels = [np.ones(length) * (i + 1) for i in range(len(center_omegas))]
    for i in range(len(center_omegas)):
        field.add_channel(channels[i], center_omegas[i], rep_freqs[i])
    operands = [field]
    res = operator_fixture(op, right_op, channels, type_op_test, center_omegas,
                           rep_freqs, length, *operands)
    def has_converged(self, waves: np.ndarray, noises: np.ndarray) -> bool:
        """Compare the previous and current iterate and return True if
        the difference is below the specified threshold.

        Parameters
        ----------
        waves :
            The current values of the wave envelopes.
        noises :
            The current values of the noise powers.

        Returns
        -------
        :
            Boolean specifying the result of the comparison.

        """
        crt_energy: float = 0.
        crt_energy += float(np.sum(Field.energy(waves, self._dtime)))
        crt_energy += float(np.sum(noises * self._noise_domega))
        if (not self._crt_iter):
            self._prev_energy = crt_energy
            self.residual = math.inf

            return False
        else:
            eps: float = 1e-30
            self.residual = abs(
                (self._prev_energy - crt_energy) / (self._prev_energy + eps))
            self._prev_energy = crt_energy

            return self._residual < self._tolerance
예제 #7
0
def test_no_common_omegas(operator_fixture, op, right_op):
    """Should not perform math operators if the center omegas are
    different."""
    length = 12
    field = Field(Domain(samples_per_bit=length), type_op_test)
    center_omegas = [1030., 1025., 1020.]
    rep_freqs = [1., 2., 3.]
    channels = [np.ones(length) * (i + 1) for i in range(len(center_omegas))]
    for i in range(len(center_omegas)):
        field.add_channel(channels[i], center_omegas[i], rep_freqs[i])
    operands = [field]
    center_omegas = [1029., 1021.]
    channels = [np.ones(length) * (i + 1) for i in range(len(center_omegas))]
    rep_freqs = [2., 3.]
    res = operator_fixture(op, right_op, channels, type_op_test, center_omegas,
                           rep_freqs, length, *operands)
    field_res = res[0]
    if (len(field_res) == len(field)):
        assert np.array_equal(field_res[:], field[:])
    else:
        assert np.array_equal(field_res[:], np.asarray(channels))
예제 #8
0
def test_copy_field(reset_channels, reset_noise, reset_delays):
    """Should fail if no valid copy is returned.
    """
    uni_length = 12
    domain = Domain(samples_per_bit=uni_length, noise_samples=uni_length)
    type = 1
    center_omega = 1550.
    rep_freq = 1e3
    delay = 10.
    field = Field(domain, type)
    field.noise = np.ones(uni_length)
    field.add_channel(np.arange(uni_length), center_omega, rep_freq, delay)
    new_field = field.get_copy('', reset_channels, reset_noise, reset_delays)
    equal_channels = np.array_equal(new_field.channels, field.channels)
    if (not reset_channels):
        assert equal_channels
    else:
        assert not equal_channels
    equal_noise = np.array_equal(new_field.noise, field.noise)
    if (not reset_noise):
        assert equal_noise
    else:
        assert not equal_noise
    equal_delays = np.array_equal(new_field.delays, field.delays)
    if (not reset_delays):
        assert equal_delays
    else:
        assert not equal_delays
예제 #9
0
    def __call__(self, domain: Domain) -> Tuple[List[int], List[Field]]:

        output_ports: List[int] = []
        output_fields: List[Field] = []
        field: Field = Field(domain, cst.OPTI, self.field_name)
        # Bit rate initialization --------------------------------------
        rel_pos: List[np.ndarray]
        rel_pos = util.pulse_positions_in_time_window(self.channels,
                                                      self.rep_freq,
                                                      domain.time_window,
                                                      self.position)
        # Check offset -------------------------------------------------
        for i in range(len(self.offset_nu)):
            if (abs(self.offset_nu[i]) > domain.nu_window):
                self.offset_nu[i] = 0.0
                util.warning_terminal(
                    "The offset of channel {} in component "
                    "{} is bigger than half the frequency window, offset will "
                    "be ignored.".format(str(i), self.name))
        # Field initialization -----------------------------------------
        width: float
        for i in range(self.channels):  # Nbr of channels
            if (self.fwhm is None):
                width = self.width[i]
            else:
                width = self.fwhm_to_width(self.fwhm[i])
            res: np.ndarray = np.zeros(domain.time.shape, dtype=cst.NPFT)
            for j in range(len(rel_pos[i])):
                norm_time = domain.get_shift_time(rel_pos[i][j]) / width
                var_time = np.power(norm_time, 2)
                phi = (self.init_phi[i] -
                       Domain.nu_to_omega(self.offset_nu[i]) * domain.time -
                       0.5 * self.chirp[i] * var_time)
                res += (math.sqrt(self.peak_power[i]) / np.cosh(norm_time) *
                        np.exp(1j * phi))
            field.add_channel(res,
                              Domain.lambda_to_omega(self.center_lambda[i]),
                              self.rep_freq[i])
            if (self.noise is not None):
                field.noise = self.noise
        output_fields.append(field)
        output_ports.append(0)

        return output_ports, output_fields
예제 #10
0
    def transfer_function(nu: np.ndarray, center_nu: float, nu_bw: float,
                          nu_offset: float = 0.):
        """The transfer function of the flat top window.

        Parameters
        ----------
        nu :
            The frequency components. :math:`[ps^{-1}]`
        center_nu :
            The center frequency. :math:`[ps^{-1}]`
        nu_bw :
            The spectral bandwith. :math:`[ps^{-1}]`
        nu_offset :
            The offset frequency. :math:`[ps^{-1}]`

        """
        window = FlatTopFilter.amplitude_transfer_function(nu, center_nu,
                                                           nu_bw, nu_offset)

        return Field.temporal_power(window)
예제 #11
0
    def transfer_function(time: np.ndarray, v_pi: List[float],
                          v_bias: List[float],
                          v_mod: List[Union[float, Callable]]) -> np.ndarray:

        v_pi = util.make_list(v_pi, 2)
        v_bias = util.make_list(v_bias, 2)
        v_mod = util.make_list(v_mod, 2)
        v_mod_: List[Callable] = []
        for v in v_mod:
            if (callable(v)):
                v_mod_.append(v)
            else:
                v_mod_.append(lambda t: v)
        print(v_pi, v_bias, v_mod_)
        phase_shift = [
            lambda t: cst.PI * (v_bias[0] + v_mod_[0](t)) / v_pi[0],
            lambda t: cst.PI * (v_bias[1] + v_mod_[1](t)) / v_pi[1]
        ]
        tf = np.cos((phase_shift[0](time) - phase_shift[1](time)) / 2.)

        return Field.temporal_power(tf)
예제 #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 = self.window(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 *= Field.temporal_power(self.window(
                                    domain.noise_nu, self.center_nu,
                                    self.nu_bw, self.nu_offset))
            output_fields.append(field)

        return self.output_ports(ports), output_fields
예제 #13
0
    def get_criterion(self, waves_f, waves_b):
        criterion = np.sum(Field.temporal_power(waves_f))
        criterion += np.sum(Field.temporal_power(waves_b))

        return criterion
예제 #14
0
        return res

    return fct


# ----------------------------------------------------------------------
# Tests ----------------------------------------------------------------
# ----------------------------------------------------------------------

scale = 2
length = 12
type_op_test = 1
center_omega_op_test = [1550.]
rep_freq_op_test = [1e3]
field_ = Field(Domain(samples_per_bit=length), type_op_test)
field_.add_channel(scale * np.ones(length), center_omega_op_test[0],
                   rep_freq_op_test[0])
operand_args = [
    int(scale),
    float(scale),
    complex(scale), scale * np.ones(length), field_
]


@pytest.mark.field_op
@pytest.mark.parametrize("op, field_channel, op_res, operands", [
    (operator.__iadd__, [np.arange(1, length + 1)],
     np.array([np.arange(1, length + 1) +
               (scale * np.ones(length))]), operand_args),
    (operator.__isub__, [np.arange(1, length + 1)],
예제 #15
0
    def _get_power_p(self, waves: Array[cst.NPFT]) -> Array[float]:

        waves_p = self._in_eq_waves(waves, 1)

        return Field.spectral_power(waves_p, False)
예제 #16
0
        def __call__(self, domain):

            return ([4], [Field(Domain(), 1)])
    def _calc_power_for_ratio(self, array: np.ndarray):

        return np.sum(Field.temporal_power(array), axis=1).reshape((-1, 1))
예제 #18
0
                               RS=False,
                               XPM=False,
                               ASYM=True,
                               COUP=True,
                               approx_type=1,
                               nlse_method='ssfm_super_sym',
                               steps=steps,
                               ode_method=method,
                               save=True,
                               wait=False,
                               NOISE=True)
        lt.add_link(pulse[0], coupler[0])
        lt.run(pulse)
        lt.reset()
        # Plot parameters and get waves
        x_datas.append(coupler[2][0].time)
        y_datas.append(Field.temporal_power(coupler[2][0].channels))
        plot_groups.append(0)

    line_labels.extend(ode_methods)
    plot_titles.extend(["ODE solvers test with n={}".format(str(steps))])
    # -------------------- Plotting results ------------------------
    plot.plot2d(x_datas,
                y_datas,
                plot_groups=plot_groups,
                plot_titles=plot_titles,
                x_labels=['t'],
                y_labels=['P_t'],
                line_labels=line_labels,
                line_opacities=[0.1])