Fix sudden_net_zero amp_B and integral (#310, QAE-808)
Issue
The pre-existing test_sudden_net_zero
passes obviously. This is it for reference:
where the waveform is
However, it has two flaws that emerge whenever t_pulse/t_phi/t_integral_correction are not integer multiples of the sample rate.
Inexact 0 integral
This will make the test fail: times = np.arange(0, 40e-9, 0.9e-9)
.
The problem can be traced to these lines in sudden_net_zero
:
sampling_rate = t[1] - t[0]
num_corr_samples = t_integral_correction / sampling_rate
corr_amp = -np.sum(waveform_amps) / num_corr_samples
The intention there is to spread the non-zero integral on an integer number of points in an exact manner.
However, num_corr_samples
is not an integer in general.
Silent amp_B
In this case the test does not fail but amp_B
won't be used without raising any flag.
For example, setting t_pulse=20.1e-9
gives the waveform
but also times = np.arange(0, 40e-9, 0.9e-9)
leads to this behaviour before making the test fail for the other reason:
Even only the second amp_B can be made to be silent using t_phi=2.1e-9
:
The problem is related to the use of np.heaviside(t0, amp_at_t0)
.
Amp_B is used only if a point in the time array matches exactly t0
, but in general this doesn't happen (in particular, in a realistic scenario t_pulse will be a real number and not a multiple of the sample rate).
Asymmetry of pulse
Additionally, I've noticed that the second half may contain one sample less or more than the first depending on the ratios of sample rate and t_pulse/t_phi. This is physically not acceptable since it leads to a significant asymmetry of the beamsplitters and will cause leakage.
Pulse may be chopped without flags
Currently if for example times = np.arange(0, 40e-9, 1e-9)
and t_pulse+t_phi+t_correction=50e-9
, the last 10e-9 get chopped off and the user won't notice in general.
Explanation of changes
I have performed a severe rewriting of the waveform. Now everything is based on the sample rate. The various pieces of the waveform are constructed one after the other as exact number of samples and then concatenated. If max(t) is too little compared to the total pulse duration, I've added an assert that will let the user know that.
Furthermore, I have put non-simple numbers in the test and I've added two assert clauses to check that amp_B is used in both sides of the pulse
Motivation of changes
The severe rewriting is due to the fact that the use of np.heaviside in the previous construction did not allow for ensuring the use of amp_B nor the simmetry and I did not see a simple workaround.
Closes #310 (closed)
Merge checklist
See also merge request guidelines
-
Merge request has been reviewed (in-depth by a knowledgeable contributor), and is approved by a project maintainer. -
New code is covered by unit tests (or N/A). -
New code is documented and docstrings use numpydoc format (or N/A). -
New functionality: considered making private instead of extending public API (or N/A). -
Public API changed: added @deprecated
(or N/A). -
Tested on hardware (or N/A). -
CHANGELOG.md
andAUTHORS.md
have been updated (or N/A). -
Windows tests in CI pipeline pass (manually triggered by maintainers before merging).
For reference, the issues workflow is described in the contribution guidelines.