Skip to content

Instantly share code, notes, and snippets.

@DanHickstein
Created September 24, 2019 15:57
Show Gist options
  • Save DanHickstein/896213d8521e950b0fd4be5d77c735b0 to your computer and use it in GitHub Desktop.
Save DanHickstein/896213d8521e950b0fd4be5d77c735b0 to your computer and use it in GitHub Desktop.
import numpy as np
import matplotlib.pyplot as plt
from pynlo.interactions.FourWaveMixing import SSFM
from pynlo.media.fibers import fiber
from pynlo.light.DerivedPulses import SechPulse
########## Parameters:
Pulse1 = .200 # pulse duration (ps)
Pulse2 = .200
Pulse3 = .200
pulseWL1 = 1035.0 # pulse central wavelength (nm)\
pulseWL2 = pulseWL1/2.0
pulseWL3 = pulseWL1/0.74
EPP1 = 0.100e-6 # Pulse energy (J)
EPP2 = 0.100e-6
EPP3 = 0.010e-6
Length = 10.00 # mm
GDD1 = 0*0.040 # Group delay dispersion (ps^2)
GDD2 = 0*0.040
GDD3 = 0*0.020
TOD = 0.0 # Third order dispersion (ps^3), currently the same for all pulses
Window = 6.0 # simulation window (ps)
Steps = 20 # simulation steps - note that the integrator typically takes many more steps than this
Points = 2**16 # simulation points
error = 0.001 # the error desired for the integration. 0.001 is usually good. larger allows for faster calculations
Alpha = 0.0 # attentuation coefficient (dB/cm, pretty sure)
Aeff = 2*np.pi*10e-6**2 # effective area in m^2
n2_per_torr = 1.1e-22/760 # nonlinearity in m^2/(W torr)
Gamma_per_torr = 2*np.pi*n2_per_torr/(pulseWL1*1e-9 * Aeff)
Raman = False # enable Raman? (calculates fused silica Raman response)
Steep = True # enable self-steepening?
fund_THz = 3e8/(pulseWL1*1e-9) * 1e-12
loss_lo = fund_THz * 5.5
loss_hi = fund_THz * 6.5
loss = 0 # Alpha in the special attentuation region, in dB/cm
max_pressure = 1350 # pressure in mBar
#######################
fibWL = pulseWL1 # Center WL (nm)
alpha = np.log((10**(Alpha * 0.1))) * 100 # convert from dB/cm to 1/m
loss = np.log((10**(loss * 0.1))) * 100
def dB(num):
return 10 * np.log10(np.abs(num)**2)
def pressure_at_z(z):
# code can be added here to change pressure as a function of position
return max_pressure
def myDispersion(z):
# pressure = pressure_at_z(z*1e3/Length)
pressure = pressure_at_z(z*1e3/Length)
waves = np.linspace(0.05, 1.2, 1000)
RIs = 0*waves + 1 # just set the index to 1 everywhere
return waves*1e3, RIs
def myGamma(z):
pressure = pressure_at_z(z*1e3/Length)
pressure_torr = pressure*760.0/1000.0
return pressure_torr * Gamma_per_torr
fig = plt.figure(figsize=(8,8))
ax0 = plt.subplot2grid((3,2), (0, 0), rowspan=1)
ax1 = plt.subplot2grid((3,2), (0, 1), rowspan=1)
ax2 = plt.subplot2grid((3,2), (1, 0), rowspan=2, sharex=ax0)
ax3 = plt.subplot2grid((3,2), (1, 1), rowspan=2, sharex=ax1)
axs = (ax0, ax1, ax2, ax3)
fig.suptitle('Pulse 1: %.0f nm, %.0f fs, %.0f nJ \nPulse 2: %.0f nm, %.0f fs, %.0f nJ\nPulse 3: %.0f nm, %.0f fs, %.0f nJ'%(pulseWL1, Pulse1*1e3, EPP1*1e9, pulseWL2, Pulse2*1e3, EPP2*1e9, pulseWL3, Pulse3*1e3, EPP3*1e9))
# set up the pulse parameters
pulse1 = SechPulse(1, Pulse1/1.76, pulseWL1, time_window_ps=Window, NPTS=Points, frep_MHz=100, power_is_avg=False)
pulse2 = SechPulse(1, Pulse2/1.76, pulseWL2, time_window_ps=Window, NPTS=Points, frep_MHz=100, power_is_avg=False)
pulse3 = SechPulse(1, Pulse3/1.76, pulseWL3, time_window_ps=Window, NPTS=Points, frep_MHz=100, power_is_avg=False)
pulse1.set_epp(EPP1)
pulse2.set_epp(EPP2)
pulse3.set_epp(EPP3)
pulse1.chirp_pulse_W(GDD1)
pulse2.chirp_pulse_W(GDD2)
pulse3.chirp_pulse_W(GDD3)
# pulse2.rotate_spectrum_to_new_center_wl(pulseWL2)
pulse1.set_AW(pulse1.AW + pulse2.interpolate_to_new_center_wl(pulseWL1).AW + pulse3.interpolate_to_new_center_wl(pulseWL1).AW)
fiber1 = fiber.FiberInstance()
fiber1.generate_fiber(Length * 1e-3, center_wl_nm=fibWL, betas=(0,0,0),
gamma_W_m=0, gain=-alpha)
fiber1.set_dispersion_function(myDispersion, dispersion_format='n')
fiber1.set_gamma_function(myGamma)
F = pulse1.F_THz # Frequency grid of pulse (THz)
# include loss:
gain = -alpha * np.zeros(F.size)
# gain[((F>loss_lo)&(F<loss_hi))] = -loss
gain[((np.abs(F)>loss_lo)&(np.abs(F)<loss_hi))] = -loss
fiber1.set_gain(gain)
# Propagation
evol = SSFM.SSFM(local_error=error, USE_SIMPLE_RAMAN=True,
disable_Raman=np.logical_not(Raman),
disable_self_steepening=np.logical_not(Steep))
y, AW, AT, pulse_out = evol.propagate(pulse_in=pulse1, fiber=fiber1, n_steps=Steps, reload_fiber_each_step=True)
########## That's it! Physics complete. Just plotting commands from here! ################
def dB(num):
return 10 * np.log10(np.abs(num)**2)
zW = dB( np.transpose(AW)[:, (F > 0)] )
zT = dB( np.transpose(AT) )
y_mm = y * 1e3 # convert distance to mm
ax0.plot(pulse_out.F_THz, dB(pulse_out.AW), color = 'r')
ax1.plot(pulse_out.T_ps, dB(pulse_out.AT), color = 'r')
ax0.plot(pulse1.F_THz, dB(pulse1.AW), color = 'b')
ax1.plot(pulse1.T_ps, dB(pulse1.AT), color = 'b')
print 'timestep:', pulse1.T_ps[1]-pulse1.T_ps[0]
extent = (np.min(F[F > 0]), np.max(F[F > 0]), 0, Length)
ax2.imshow(zW, extent=extent,
vmin=np.max(zW) - 200.0, vmax=np.max(zW),
aspect='auto', origin='lower')
extent = (np.min(pulse1.T_ps), np.max(pulse1.T_ps), np.min(y_mm), Length)
ax3.imshow(zT, extent=extent,
vmin=np.max(zT) - 100.0, vmax=np.max(zT),
aspect='auto', origin='lower')
ax0.set_ylabel('Intensity (dB)')
ax0.set_ylim( - 250, 100)
ax1.set_ylim( - 200, 100)
ax2.set_ylabel('Propagation distance (mm)')
ax2.set_xlabel('Frequency (THz)')
ax2.set_xlim(0,4000)
ax3.set_xlabel('Time (ps)')
for ax in axs:
ax.grid(alpha=0.1)
plt.subplots_adjust(left=0.10, bottom=0.07, right=0.98, top=0.89, wspace=0.26, hspace=0.20)
plt.savefig('Three-pulses.png', dpi=200)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment