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
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
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))
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
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))
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
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
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)
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)
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
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
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)],
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)
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))
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])