Two-Level: Sech Pulse 2π — Self-Induced Transparency
Define the Problem
First we need to define a sech pulse with the area we want. We’ll fix the width of the pulse and the area to find the right amplitude.
The full-width at half maximum (FWHM) \(t_s\) of the sech pulse is related to the FWHM of a Gaussian by a factor of \(1/2.6339157938\). (See §3.2.2 of my PhD thesis).
[1]:
import numpy as np
SECH_FWHM_CONV = 1.0 / 2.6339157938
t_width = 1.0 * SECH_FWHM_CONV # [τ]
print("t_width", t_width)
t_width 0.3796628587572578
[2]:
mb_solve_json = """
{
"atom": {
"fields": [
{
"coupled_levels": [[0, 1]],
"rabi_freq_t_args": {
"n_pi": 2.0,
"centre": 0.0,
"width": %f
},
"rabi_freq_t_func": "sech"
}
],
"num_states": 2
},
"t_min": -2.0,
"t_max": 10.0,
"t_steps": 120,
"z_min": -0.5,
"z_max": 1.5,
"z_steps": 100,
"interaction_strengths": [
10.0
],
"savefile": "mbs-two-sech-2pi"
}
""" % (t_width)
[3]:
from maxwellbloch import mb_solve
mb_solve_00 = mb_solve.MBSolve().from_json_str(mb_solve_json)
We’ll just check that the pulse area is what we want.
[4]:
print(
"The input pulse area is {0}".format(
np.trapezoid(mb_solve_00.Omegas_zt[0, 0, :].real, mb_solve_00.tlist) / np.pi
)
)
The input pulse area is 1.993398883240025
Solve the Problem
[5]:
%time Omegas_zt, states_zt = mb_solve_00.mbsolve(recalc=True)
z-step 10/100 (10%)
z-step 20/100 (20%)
z-step 30/100 (30%)
/home/docs/checkouts/readthedocs.org/user_builds/maxwellbloch/envs/v0.10.0/lib/python3.11/site-packages/qutip/solver/solver_base.py:598: FutureWarning: e_ops will be keyword only from qutip 5.3 for all solver
warnings.warn(
z-step 40/100 (40%)
z-step 50/100 (50%)
z-step 60/100 (60%)
z-step 70/100 (70%)
z-step 80/100 (80%)
z-step 90/100 (90%)
Saving MBSolve to mbs-two-sech-2pi.qu
CPU times: user 677 ms, sys: 7.78 ms, total: 684 ms
Wall time: 677 ms
Plot Output
[6]:
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import seaborn as sns
sns.set_style("darkgrid")
fig = plt.figure(1, figsize=(16, 6))
ax = fig.add_subplot(111)
cmap_range = np.linspace(0.0, 1.0, 11)
cf = ax.contourf(
mb_solve_00.tlist,
mb_solve_00.zlist,
np.abs(mb_solve_00.Omegas_zt[0] / (2 * np.pi)),
cmap_range,
cmap=plt.cm.Blues,
)
ax.set_title(r"Rabi Frequency ($\Gamma / 2\pi $)")
ax.set_xlabel(r"Time ($1/\Gamma$)")
ax.set_ylabel("Distance ($L$)")
for y in [0.0, 1.0]:
ax.axhline(y, c="grey", lw=1.0, ls="dotted")
plt.colorbar(cf);
[7]:
fig, ax = plt.subplots(figsize=(16, 4))
ax.plot(mb_solve_00.zlist, mb_solve_00.fields_area()[0] / np.pi, clip_on=False)
ax.set_ylim([0.0, 8.0])
ax.set_xlabel("Distance ($L$)")
ax.set_ylabel(r"Pulse Area ($\pi$)");
Analysis
The \(2 \pi\) sech pulse passes through, slowed but with shape unaltered. This is self-induced transparency.
Movie
[8]:
# C = 0.1 # speed of light
# Y_MIN = 0.0 # Y-axis min
# Y_MAX = 4.0 # y-axis max
# ZOOM = 2 # level of linear interpolation
# FPS = 30 # frames per second
# ATOMS_ALPHA = 0.2 # Atom indicator transparency
[9]:
# FNAME = "images/mb-solve-two-sech-2pi"
# FNAME_JSON = FNAME + '.json'
# with open(FNAME_JSON, "w") as f:
# f.write(mb_solve_json)
[10]:
# !make-mp4-fixed-frame.py -f $FNAME_JSON -c $C --fps $FPS --y-min $Y_MIN --y-max $Y_MAX \
# --zoom $ZOOM --atoms-alpha $ATOMS_ALPHA #--peak-line --c-line
[11]:
# FNAME_MP4 = FNAME + '.mp4'
# !make-gif-ffmpeg.sh -f $FNAME_MP4 --in-fps $FPS
[12]:
# from IPython.display import Image
# Image(url=FNAME_MP4 +'.gif', format='gif')