def gaussian_beam(fwhm=10): """Display a Gaussian beam at the given fwhm. Parameters ---------- fwhm : float Full width at half maximum (for intensity not amplitude) (µm). """ w = fwhm / np.sqrt(2 * np.log(2)) bpm = Bpm(1, 1, 1, 1, 1, 1, 1) bpm.x = np.linspace(-1.5*fwhm, 1.5*fwhm, 500) x = bpm.x plt.figure("Beam") plt.title("Width definition of a gaussian beam with FWHM=%s µm" % fwhm) plt.xlabel("x (µm)") plt.plot(x, bpm.gauss_light(fwhm, 0), label='field') plt.plot(x, (bpm.gauss_light(fwhm, 0))**2, label='intensity') plt.plot(x, [1/2]*x.size, '-.', label='1/2') plt.plot([fwhm/2]*x.size, np.linspace(0, 1, x.size), '--', label='fwhm/2') plt.plot(x, [np.exp(-1)]*x.size, '-.', label='1/e') plt.plot(x, [np.exp(-2)]*x.size, '-.', label='1/$e^2$') plt.plot([w]*x.size, np.linspace(0, 1, x.size), '--', label='$w_0$=%.2f' % w) plt.legend() plt.show()
def test_kerr(): """More test than example. Show different approximations for the BPM implementation of the Kerr effect.""" no = 1 lo = 1.5 length_z = 50 dist_z = 0.1 nbr_z_disp = 1 dist_x = 0.01 length_x = 400 bpm = Bpm(no, lo, length_z, dist_z, nbr_z_disp, length_x, dist_x) [length_z, nbr_z, nbr_z_disp, length_x, nbr_x, x] = bpm.create_x_z() dn = np.zeros((nbr_z, nbr_x)) fwhm = 6 field = bpm.gauss_light(fwhm) irrad = 260e13 # if too high, see big difference between method theta_ext = 0 [progress_pow] = bpm.init_field(field, theta_ext, irrad) # Need to overwrite those variables due to changes theta = asin(sin(radians(theta_ext)) / no) # angle in the guide nu_max = 1 / (2 * dist_x) # max frequency due to sampling # Spacial frequencies over x (1/µm) nu = np.linspace(-nu_max, nu_max*(1 - 2/nbr_x), nbr_x) intermed = no * cos(theta) / lo fr = -2 * pi * nu**2 / (intermed + np.sqrt( intermed**2 - nu**2 + 0j)) bpm.phase_mat = fftshift(np.exp(1j * dist_z * fr)) bpm.phase_mat_demi = fftshift(np.exp(1j * dist_z / 2 * fr)) bpm.nl_mat = bpm.ko * bpm.dist_z * dn # End overwrite kerr_loop = 10 chi3 = 10 * 1E-20 nbr_step = nbr_z-1 print("\n dz/2+lens+dz/2") field = bpm.field for i in range(nbr_step): # Linear propagation over dz/2 field = ifft(bpm.phase_mat_demi * fft(field)) # Influence of the index modulation on the field field = field * np.exp(1j * bpm.nl_mat[nbr_step, :]) # No changes if # no initial guide (exp=1) # Linear propagation over dz/2 field = ifft(bpm.phase_mat_demi * fft(field)) cur_pow = bpm.epnc * abs2(field) field_ref = field cur_ref = cur_pow print("\n dz+kerr") field = bpm.field for i in range(nbr_step): # Linear propagation over dz field = ifft(bpm.phase_mat * fft(field)) # Influence of the index modulation on the field field_x = field * np.exp(1j * bpm.nl_mat[nbr_step, :]) cur_pow = bpm.epnc * abs2(field_x) for k in range(1): # insensitive to correction loop prev_pow = cur_pow # influence of the beam intensity on the index modulation dn_temp = dn[nbr_step, :] + (3*chi3)/(8*no)*(prev_pow/bpm.epnc) nl_mat = bpm.ko * bpm.dist_z * dn_temp # influence of the index modulation on the field field_x = field * np.exp(1j*nl_mat) # No changes for the pow cur_pow = bpm.epnc * abs2(field_x) try: bpm.variance(prev_pow, cur_pow) except ValueError as error: print(error) field = field_x field_1 = field cur_1 = cur_pow dn_1 = dn_temp print("\n dz/2+kerr+dz/2") field = bpm.field for i in range(nbr_step): # Linear propagation over dz/2 field = ifft(bpm.phase_mat_demi * fft(field)) # Influence of the index modulation on the field field_x = field * np.exp(1j * bpm.nl_mat[nbr_step, :]) # Linear propagation over dz/2 field_x = ifft(bpm.phase_mat_demi * fft(field_x)) cur_pow = bpm.epnc * abs2(field_x) for k in range(kerr_loop): prev_pow = cur_pow # influence of the beam intensity on the index modulation dn_temp = dn[nbr_step, :] + (3*chi3)/(8*no)*(prev_pow/bpm.epnc) nl_mat = bpm.ko * bpm.dist_z * dn_temp # influence of the index modulation on the field field_x = field * np.exp(1j * nl_mat) # Linear propagation over dz/2 field_x = ifft(bpm.phase_mat_demi * fft(field_x)) cur_pow = bpm.epnc * abs2(field_x) try: bpm.variance(prev_pow, cur_pow) except ValueError as error: print(error) field = field_x field_2 = field cur_2 = cur_pow dn_2 = dn_temp print("\n kerr+dz") field = bpm.field for i in range(nbr_step): # Influence of the index modulation on the field field_x = field * np.exp(1j * bpm.nl_mat[nbr_step, :]) # Linear propagation over dz field_x = ifft(bpm.phase_mat * fft(field_x)) cur_pow = bpm.epnc * abs2(field_x) for k in range(kerr_loop): prev_pow = cur_pow # influence of the beam intensity on the index modulation dn_temp = dn[nbr_step, :] + (3*chi3)/(8*no)*(prev_pow/bpm.epnc) nl_mat = bpm.ko * bpm.dist_z * dn_temp # influence of the index modulation on the field field_x = field * np.exp(1j * nl_mat) # Linear propagation over dz field_x = ifft(bpm.phase_mat * fft(field_x)) cur_pow = bpm.epnc * abs2(field_x) try: bpm.variance(prev_pow, cur_pow) except ValueError as error: print(error) field = field_x field_3 = field cur_3 = cur_pow dn_3 = dn_temp plt.figure(num="Impact order kerr") ax1 = plt.subplot(211) ax2 = plt.subplot(212) ax1.set_title("phase: comparison") ax2.set_title("power: comparison") ax1.set_xlim(-15, 15) ax2.set_xlim(-15, 15) ax1.plot(x, np.angle(field_ref), label="no kerr") ax1.plot(x, np.angle(field_1), label="dz+kerr") ax1.plot(x, np.angle(field_2), label="dz/2+kerr+dz/2") ax1.plot(x, np.angle(field_3), label="kerr+dz") ax2.plot(x, cur_ref, label="no kerr") ax2.plot(x, cur_1, label="dz+kerr") ax2.plot(x, cur_2, label="dz/2+kerr+dz/2") ax2.plot(x, cur_3, label="kerr+dz") ax1.legend(loc="upper right") ax2.legend(loc="upper right") plt.show() dn_ref = dn[nbr_step, :] plt.figure(num="Impact on dn order kerr") ax1 = plt.subplot(111) ax1.set_title("dn: comparison") ax1.set_xlim(-15, 15) ax1.plot(x, dn_ref, label="no kerr") ax1.plot(x, dn_1, label="dz+kerr") ax1.plot(x, dn_2, label="dz/2+kerr+dz/2") ax1.plot(x, dn_3, label="kerr+dz") ax1.legend(loc="upper right") plt.show()
def stability(): """Show the possible BPM approximations for implementing a refractive index variation""" width = 6 no = 2.14 wavelength = 1.55 delta_no = 0.0014 length_z = 200 dist_z = 1 nbr_z_disp = 1 dist_x = 0.2 length_x = 1000 bpm = Bpm(no, wavelength, length_z, dist_z, nbr_z_disp, length_x, dist_x) [length_z, nbr_z, nbr_z_disp, length_x, nbr_x, x] = bpm.create_x_z() shape = bpm.squared_guide(width) nbr_p = 1 p = 0 [peaks, dn] = bpm.create_guides(shape, delta_no, nbr_p, p) fwhm = 6 lo = 1.5 field = bpm.gauss_light(fwhm) irrad = 1 theta_ext = 0 [progress_pow] = bpm.init_field(field, theta_ext, irrad) nbr_step = nbr_z-1 # Need to overwrite those variables due to changes theta = asin(sin(radians(theta_ext)) / no) # angle in the guide nu_max = 1 / (2 * dist_x) # max frequency due to sampling # Spacial frequencies over x (1/µm) nu = np.linspace(-nu_max, nu_max * (1 - 2/nbr_x), nbr_x) intermed = no * cos(theta) / lo fr = -2 * pi * nu**2 / (intermed + np.sqrt( intermed**2 - nu**2 + 0j)) bpm.phase_mat = fftshift(np.exp(1j * dist_z * fr)) bpm.phase_mat_demi = fftshift(np.exp(1j * dist_z / 2 * fr)) bpm.nl_mat = bpm.ko * bpm.dist_z * dn # End overwrite field = bpm.field for i in range(nbr_step): field = ifft(bpm.phase_mat * fft(field)) field *= np.exp(1j * bpm.nl_mat[nbr_step, :]) test1 = field field = bpm.field for i in range(nbr_step): field = ifft(bpm.phase_mat_demi * fft(field)) field *= np.exp(1j * bpm.nl_mat[nbr_step, :]) field = ifft(bpm.phase_mat_demi * fft(field)) test2 = field field = bpm.field for i in range(nbr_step): field *= np.exp(1j * bpm.nl_mat[nbr_step, :]) field = ifft(bpm.phase_mat * fft(field)) test3 = field plt.figure("Power") plt.title("Power: Impact of the chosen algorithm on the free propagation") plt.xlim(-20, 20) # plt.ylim(-1, 350) plt.plot(x, abs2(test1), label='dz+lens') plt.plot(x, abs2(test2), label='dz/2+lens+dz/2') plt.plot(x, abs2(test3), label='lens+dz') plt.legend() plt.show() plt.figure("Phase") plt.title("Phase: Impact of the chosen algorithm on the free propagation") plt.xlim(-30, 30) plt.plot(x, np.angle(test1), label='dz+lens') plt.plot(x, np.angle(test2), label='dz/2+lens+dz/2') plt.plot(x, np.angle(test3), label='lens+dz') plt.legend() plt.show()
def benchmark_kerr(): """Kerr benchmark by looking at the critical power at which a beam become a soliton. Several test were done with this function and for now, it seems that the critical power find by the simulations is about 85% of the theorical value. Meaning a 15% error. Further tests are needed to understand the observed differences.""" width = 0 no = 1 wavelength = 4 delta_no = 0.000 length_z = 1000 dist_z = 0.5 nbr_z_disp = 200 dist_x = 0.05 length_x = 500 nbr_p = 1 p = 20 fwhm = 12 theta_ext = 0 n2 = 2.44e-20 alpha = 1.8962 # gaussian beam # See Self-focusing on wiki P_c = alpha*(wavelength*1e-6)**2/(4*pi*no*n2) print("critical power = %.2e W" % P_c) # irrad = 5e3*1e13 # power = irrad * (fwhm*1e-6)**2 * pi / (4*np.log(2)) # print("power", power) # See Gaussian_beam on wiki on beam power w = fwhm*1e-6 / sqrt(2*log(2)) irrad_cri = 2*P_c/(pi*w**2) print("Critical irradiance %.2e W/m^2" % irrad_cri) bpm = Bpm(no, wavelength, length_z, dist_z, nbr_z_disp, length_x, dist_x) [length_z, nbr_z, nbr_z_disp, length_x, nbr_x, x] = bpm.create_x_z() shape = bpm.gauss_guide(width, 4) sweep = (1, 0.2*irrad_cri, 0.5*irrad_cri, 0.7*irrad_cri, 0.75*irrad_cri, 0.8*irrad_cri, 0.85*irrad_cri, # 0.85 seem correct 0.9*irrad_cri, irrad_cri ) for i, irrad in enumerate(sweep): power = irrad/2 * (pi*w**2) print(i+1, "/", len(sweep), "\tpower= %.2e W" % power, sep="") [peaks, dn] = bpm.create_guides(shape, delta_no, nbr_p, p) field = bpm.gauss_light(fwhm) [progress_pow] = bpm.init_field(field, theta_ext, irrad) [progress_pow] = bpm.main_compute(dn, n2=n2, kerr_loop=2, disp_progress=False) x_pos = int(length_x/2/dist_x) z_disp = np.linspace(0, length_z/1000, nbr_z_disp+1) plt.figure("Benchmark kerr") plt.title(r"Central irradition for a theorical $P_c$ = %.2e W" % P_c) plt.xlabel("z (µm)") plt.ylabel(r"I (a.u)") # plt.ylim(-0.05, 2) plt.plot(z_disp*1e3, progress_pow[:, x_pos]/progress_pow[0, x_pos], label="Power=%.2e" % power) plt.legend() plt.show() # plt.savefig("kerr_irrad.png", bbox="tight", dpi=250) # x_beg = np.array([None]*nbr_z) # x_end = np.array([None]*nbr_z) # P = np.zeros(nbr_z_disp+1) # x_beg, x_end = bpm.guide_position(peaks, 0, p) # P = bpm.power_guide(x_beg, x_end) # plt.figure("Benchmark kerr2") # plt.title("Power for a theorical critical power = %.2e" % P_c) # plt.xlabel("z (µm)") # plt.ylabel(r"Power (a.u)") # plt.ylim(-0.05, 2) # plt.plot(z_disp, P, label="Power=%.2e" % power) # plt.legend() # plt.show() # xv, zv = np.meshgrid(x, z_disp) # plt.figure("check borders") # plt.title("check if beam don't reach the borders") # plt.pcolormesh(xv, zv, progress_pow, cmap='gray') # plt.show() plt.figure("Benchmark beam profil") plt.title("Beam profil at z=%.0f µm" % length_z) plt.xlabel("x (µm)") plt.ylabel(r"I/$I_0$") plt.xlim(-30, 30) plt.plot(x, progress_pow[-1]/np.max(progress_pow[0]), label="Power=%.2e" % power) plt.legend() plt.show()
def free_propag(dist_x=0.1, length_x=1000, length_z=10000, no=1, lo=1): """Show the free propagation of a beam and compare Beampy results with the theorical values. Parameters ---------- dist_x : float Step over x (µm). length_x : float Size of the compute window over x (µm). length_z : float Size of the compute window over z (µm). no : float Refractive index of the cladding lo : float Wavelength of the beam in vaccum (µm). """ dist_z = length_z nbr_z_disp = 1 bpm = Bpm(no, lo, length_z, dist_z, nbr_z_disp, length_x, dist_x) [length_z, nbr_z, nbr_z_disp, length_x, nbr_x, x] = bpm.create_x_z() dn = np.zeros((nbr_z, nbr_x)) fwhm = 20 field = bpm.gauss_light(fwhm) irrad = 1E13 theta_ext = 0 [progress_pow] = bpm.init_field(field, theta_ext, irrad) [progress_pow] = bpm.main_compute(dn) intensity = progress_pow[-1] index = np.where(intensity >= (np.max(intensity)/2))[0][0] fwhm_final = abs(2 * x[index]) w0_final = fwhm_final / np.sqrt(2 * np.log(2)) print("Beampy: width w = %f µm" % w0_final) w0 = fwhm / np.sqrt(2 * np.log(2)) z0 = np.pi * no * w0**2 / lo w = w0 * np.sqrt(1 + (length_z / z0)**2) print("Theory: width w = %f µm" % w) diff = abs(w - w0_final)/w*100 print("Relative difference: %f" % diff, "%") if diff > 1: print("Check the dist_x or length_x parameters") irrad_theo = irrad*w0/w # in 2D: irrad*(w0/w)**2 print("Beampy: irradiance I =", np.max(intensity)) print("Theory: irradiance I =", irrad_theo) diff = abs(np.max(intensity) - irrad_theo)/irrad_theo*100 print("Relative difference: %f" % diff, "%") if diff > 1: print("Check the dist_x or length_x parameters") fwhm_theo = w * np.sqrt(2 * np.log(2)) profil_theo = bpm.gauss_light(fwhm_theo) intensity_theo = irrad_theo * abs2(profil_theo) plt.figure() plt.title("Beam profil after %.0f mm of free propagation" % (length_z/1e3)) plt.xlabel("x (µm)") plt.ylabel(r"irradiance (W.m$^{-2}$)") plt.plot(x, intensity_theo, "-", label="Theory") plt.plot(x, intensity, "--", label="Beampy") plt.legend() plt.show()