def test_output_combiner_no_combine(nbr_channels, ratios): """Should fail if the output temporal power division does not correpsond to the dividing ratios. """ # Environment creation gssns = [] nbr_arms = len(ratios) base_power = 10.0 for i in range(nbr_arms): gssns.append( Gaussian(channels=nbr_channels, save=True, peak_power=[(i + 1) * base_power for i in range(nbr_channels)])) combiner = IdealCombiner(arms=nbr_arms, ratios=ratios, save=True, combine=False) lt = Layout() for i in range(nbr_arms): lt.add_link(gssns[i][0], combiner[i]) lt.run_all() # Testing init_fields = [] for i in range(0, nbr_arms): init_fields.extend(gssns[i][0].fields) output_fields = combiner[nbr_arms].fields assert len(output_fields) == nbr_arms assert len(output_fields) == len(init_fields) for i in range(len(output_fields)): for j in range(len(output_fields[i])): # Taking into account rounding errors power_1 = ratios[i] * temporal_power(init_fields[i][j]) power_2 = temporal_power(output_fields[i][j]) assert_array_almost_equal(power_1, power_2, 10)
def test_constraint_coprop(): r"""Should fail if the copropagating fields are not waiting for each others. Notes ----- Test case:: [0] _________ [1] __________\ [2] ___________\__ Combiner ___ Dummy Comp __ check output [3] ___________/ ... [n-1] _________/ """ lt = Layout() nbr_sig = 5 combiner = IdealCombiner(arms=nbr_sig, combine=False) for i in range(nbr_sig): lt.add_link(Gaussian()[0], combiner[i]) dummy_comp = IdealAmplifier(save=True) lt.add_link(combiner[nbr_sig], dummy_comp[0]) lt.run_all() assert (len(dummy_comp[1]) == nbr_sig)
def extinction(self, extinction: Optional[float]) -> None: self._extinction = extinction if (extinction is None): gamma_er = 1.0 else: extinction_ = 10**(0.1 * extinction) # db -> non db gamma_er = (math.sqrt(extinction_) - 1) / (math.sqrt(extinction_) + 1) # N.B. name='nocount' to avoid inc. default name counter self._combiner = IdealCombiner(name='nocount', arms=2, combine=True, ratios=[0.5, 0.5 * gamma_er])
def test_combine_output_diff_omega_and_rep_freq(nbr_channels, ratios): """Should fail if the different omega and repetition frequencies are added to each other. """ # Environment creation back_up_flag_omega = cfg.get_field_op_matching_omega() back_up_flag_rep_freq = cfg.get_field_op_matching_rep_freq() cfg.set_field_op_matching_omega(True) cfg.set_field_op_matching_rep_freq(True) gssns = [] nbr_arms = len(ratios) base_power = 10.0 for i in range(nbr_arms): gssns.append( Gaussian(channels=nbr_channels, save=True, peak_power=[(j + 1) * base_power for j in range(nbr_channels)], center_lambda=[(1500. + j) * (i + 1) for j in range(nbr_channels)], rep_freq=[(1e-2 + (j * 1e-4)) * (i + 1) for j in range(nbr_channels)])) combiner = IdealCombiner(arms=nbr_arms, ratios=ratios, save=True, combine=True) lt = Layout() for i in range(nbr_arms): lt.add_link(gssns[i][0], combiner[i]) lt.run_all() lt.reset() # Testing init_fields = [] for i in range(0, nbr_arms): init_fields.extend(gssns[i][0].fields) output_fields = combiner[nbr_arms].fields assert len(output_fields) == 1 assert len(output_fields[0]) == (nbr_channels * nbr_arms) # Reset cfg.set_field_op_matching_omega(back_up_flag_omega) cfg.set_field_op_matching_rep_freq(back_up_flag_rep_freq)
def test_constraint_waiting(): r"""Should fail if the component is not waiting for other fields. Notes ----- Test case:: [0] _________ [1] __________\ [2] ___________\__ Combiner __ check output [3] ___________/ ... [n-1] _________/ """ lt = Layout() nbr_sig = 5 combiner = IdealCombiner(arms=nbr_sig, combine=False, save=True) for i in range(nbr_sig): lt.add_link(Gaussian()[0], combiner[i]) lt.run_all() assert (len(combiner[nbr_sig]) == nbr_sig)
def __init__(self, name: str = default_name, phase_shift: Union[List[float], List[Callable]] = [0.0, 0.0], loss: float = 0.0, ext_ratio: float = 0.0, v_pi: Optional[List[float]] = None, v_bias: Optional[List[float]] = None, v_mod: Optional[List[Callable]] = None, save: bool = False, max_nbr_pass: Optional[List[int]] = None) -> None: r""" Parameters ---------- name : The name of the component. phase_shift : The phase difference induced between the two arms of the MZ. Can be a list of callable with time variable. :math:`[ps]` (will be ignored if (v_pi and v_bias) or (v_pi and v_mod) are provided) loss : The loss induced by the MZ. :math:`[dB]` ext_ratio : The extinction ratio. v_pi : The half-wave voltage. :math:`[V]` v_bias : The bias voltage. :math:`[V]` v_mod : The modulation voltage :math:`[V]`. Must be a callable with time variable. :math:`[ps]` save : If True, the last wave to enter/exit a port will be saved. max_nbr_pass : No fields will be propagated if the number of fields which passed through a specific port exceed the specified maximum number of pass for this port. """ # Parent constructor ------------------------------------------- ports_type = [cst.ANY_ALL, cst.ANY_ALL] super().__init__(name, default_name, ports_type, save, max_nbr_pass=max_nbr_pass) # Attr types check --------------------------------------------- util.check_attr_type(phase_shift, 'phase_shift', float, Callable, list) util.check_attr_type(loss, 'loss', float) util.check_attr_type(ext_ratio, 'ext_ratio', float) util.check_attr_type(v_pi, 'v_pi', None, float, list) util.check_attr_type(v_bias, 'v_bias', None, float, list) util.check_attr_type(v_mod, 'v_mod', None, Callable, list) # Attr --------------------------------------------------------- if (v_pi is not None and (v_bias is not None or v_mod is not None)): pi_ = util.make_list(v_pi, 2) bias_ = util.make_list(v_bias, 2) if v_bias is not None\ else [0.0, 0.0] mod_ = util.make_list(v_mod, 2) if v_mod is not None\ else [lambda t: 0.0, lambda t: 0.0] phase_shift_ = [ lambda t: cst.PI * (bias_[0] + mod_[0](t)) / pi_[0], lambda t: cst.PI * (bias_[1] + mod_[1](t)) / pi_[1] ] else: phase_shift_ = util.make_list(phase_shift, 2, 0.0) # N.B. name='nocount' to avoid inc. default name counter self._divider = IdealDivider(name='nocount', arms=2, divide=True, ratios=[0.5, 0.5]) self._combiner = IdealCombiner(name='nocount', arms=2, combine=True, ratios=[0.5, 0.5]) self._phasemod_1 = IdealPhaseMod(name='nocount', phase_shift=phase_shift_[0]) self._phasemod_2 = IdealPhaseMod(name='nocount', phase_shift=phase_shift_[1]) self._amp = IdealAmplifier(name='nocount', gain=-loss) # Policy ------------------------------------------------------- self.add_port_policy(([0], [1], True))