def __init__(self, power, FWHM_ps, center_wavelength_nm, time_window_ps = 10., frep_MHz = 100., NPTS = 2**10, GDD = 0, TOD = 0, chirp2 = 0, chirp3 = 0, power_is_avg = False): """Generate sinc pulse A(t) = sqrt(peak_power[W]) * sin(t/T0)/(t/T0) centered at wavelength center_wavelength_nm (nm). The width is given by FWHM_ps, which is the full-width-at-half-maximum in picoseconds. T0 is equal th FWHM/3.7909885. time_window_ps sets temporal grid size. Optional GDD and TOD are in ps^2 and ps^3.""" Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) T0_ps = FWHM_ps/3.7909885 ### Generate pulse if not power_is_avg: # numpy.sinc is sin(pi*x)/(pi*x), so we divide by pi self.set_AT( np.sqrt(power) * np.sinc(self.T_ps/(T0_ps*np.pi)) ) else: self.set_AT( 1 / np.sinc(np.pi * self.T_ps/(T0_ps*np.pi)) ) self.set_AT(self.AT * np.sqrt( power / ( frep_MHz*1.0e6 * self.calc_epp()) )) self.chirp_pulse_W(GDD, TOD) self.chirp_pulse_T(chirp2, chirp3, T0_ps)
def __init__(self, avg_power, center_wavelength_nm, time_window_ps = 10.0, NPTS = 2**8,offset_from_center_THz = None): Pulse.__init__(self, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) if offset_from_center_THz is None: self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) # Set the time domain to be CW, which should give us a delta function in # frequency. Then normalize that delta function (in frequency space) to # the average power. Note that frep does not factor in here. self.set_AT(np.ones(self.NPTS,)) self.set_AW(self.AW * np.sqrt(avg_power) / sum(abs(self.AW)) ) else: dF = 1.0/time_window_ps n_offset = np.round( offset_from_center_THz/dF) center_THz = self._c_nmps/center_wavelength_nm -\ n_offset * dF center_nm = self._c_nmps / center_THz self.set_time_window_ps(time_window_ps) self.set_center_wavelength_nm(center_nm) aws = np.zeros((self.NPTS, )) aws[int(self.NPTS/2.0) + int(n_offset) ] = 1.0 *np.sqrt(avg_power) self.set_AW(aws)
def __init__(self, power, T0_ps, center_wavelength_nm, time_window_ps = 10., frep_MHz = 100., NPTS = 2**10, GDD = 0, TOD = 0, chirp2 = 0, chirp3 = 0, power_is_avg = False): """Generate a squared-hyperbolic secant "sech" pulse A(t) = sqrt(P0 [W]) * sech(t/T0 [ps]) centered at wavelength center_wavelength_nm (nm). time_window (ps) sets temporal grid size. Optional GDD and TOD are in ps^2 and ps^3. Note: The full-width-at-half-maximum (FWHM) is given by T0_ps * 1.76 """ Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) ### Generate pulse if not power_is_avg: # from https://www.rp-photonics.com/sech2_shaped_pulses.html self.set_AT( np.sqrt(power)/np.cosh(self.T_ps/T0_ps) ) else: self.set_AT( 1 / np.cosh(self.T_ps/T0_ps) ) self.set_AT(self.AT * np.sqrt( power / ( frep_MHz*1.0e6 * self.calc_epp()) )) self.chirp_pulse_W(GDD, TOD) self.chirp_pulse_T(chirp2, chirp3, T0_ps)
def __init__(self, power, T0_ps, center_wavelength_nm, time_window_ps = 10., frep_MHz = 100., NPTS = 2**10, GDD = 0, TOD = 0, chirp2 = 0, chirp3 = 0, power_is_avg = False): """Generate Gaussian pulse A(t) = sqrt(peak_power[W]) * exp( -(t/T0 [ps])^2 / 2 ) centered at wavelength center_wavelength_nm (nm). time_window (ps) sets temporal grid size. Optional GDD and TOD are in ps^2 and ps^3. Note: For this definition of a Gaussian pulse, T0_ps is the full-width-at-half-maximum (FWHM) of the pulse. """ Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) GDD = GDD TOD = TOD # from https://www.rp-photonics.com/gaussian_pulses.html self.set_AT( np.sqrt(power) * np.exp(-2.77*0.5*self.T_ps**2/(T0_ps**2)) ) # input field (W^0.5) if power_is_avg: self.set_AT(self.AT * np.sqrt( power / ( frep_MHz*1.0e6 * self.calc_epp()) )) self.chirp_pulse_W(GDD, TOD) self.chirp_pulse_T(chirp2, chirp3, T0_ps)
def __init__(self, center_wavelength_nm, time_window_ps = 10., NPTS = 2**8, frep_MHz = None): Pulse.__init__(self, n = NPTS, frep_MHz = frep_MHz) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) self.set_AW( 1e-30 * np.ones(self.NPTS) * np.exp(1j * 2 * np.pi * 1j * np.random.rand(self.NPTS)))
def __init__(self, time_window_ps, center_wavelength_nm, power,frep_MHz = 100., NPTS = 2**10, power_is_avg = False, fileloc = '', flip_phase = True): """Generate pulse from FROG data. Grid is centered at wavelength center_wavelength_nm (nm), but pulse properties are loaded from data file. If flip_phase is true, all phase is multiplied by -1 [useful for correcting direction of time ambiguity]. time_window (ps) sets temporal grid size. power sets the pulse energy: if power_is_epp is True then the number is pulse energy [J] if power_is_epp is False then the power is average power [W], and is multiplied by frep to calculate pulse energy""" Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) try: self.fileloc = fileloc # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_time_window_ps(time_window_ps) self.set_center_wavelength_nm(center_wavelength_nm) # reference wavelength (nm) # power -> EPP if power_is_avg: power = power / self.frep_mks # Read in retrieved FROG trace frog_data = np.genfromtxt(self.fileloc) wavelengths = frog_data[:,0]# (nm) intensity = frog_data[:,1]# (arb. units) phase = frog_data[:,2]# (radians) if flip_phase: phase = -1 * phase pulse_envelope = interp1d(wavelengths, intensity, kind='linear', bounds_error=False,fill_value=0) phase_envelope = interp1d(wavelengths, phase, kind='linear', bounds_error=False,fill_value=0) gridded_intensity = pulse_envelope(self.wl_nm) gridded_phase = phase_envelope(self.wl_nm) # Calculate time domain complex electric field A self.set_AW(gridded_intensity*np.exp(1j*gridded_phase)) # Calculate normalization factor to achieve requested # pulse energy e_scale = np.sqrt(power / self.calc_epp() ) self.set_AT(self.AT * e_scale ) except IOError: print ('File not found.' )
def __init__(self, time_window_ps, center_wavelength_nm, power,frep_MHz = 100., NPTS = 2**10, power_is_avg = False, fileloc = '', flip_phase = True): """Generate pulse from FROG data. Grid is centered at wavelength center_wavelength_nm (nm), but pulse properties are loaded from data file. If flip_phase is true, all phase is multiplied by -1 [useful for correcting direction of time ambiguity]. time_window (ps) sets temporal grid size. power sets the pulse energy: if power_is_epp is True then the number is pulse energy [J] if power_is_epp is False then the power is average power [W], and is multiplied by frep to calculate pulse energy""" Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) try: self.fileloc = fileloc # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_time_window_ps(time_window_ps) self.set_center_wavelength_nm(center_wavelength_nm) # reference wavelength (nm) # power -> EPP if power_is_avg: power = power / self.frep_mks # Read in retrieved FROG trace frog_data = np.genfromtxt(self.fileloc) wavelengths = frog_data[:,0]# (nm) intensity = frog_data[:,1]# (arb. units) phase = frog_data[:,2]# (radians) if flip_phase: phase = -1 * phase pulse_envelope = interp1d(wavelengths, intensity, kind='linear', bounds_error=False,fill_value=0) phase_envelope = interp1d(wavelengths, phase, kind='linear', bounds_error=False,fill_value=0) gridded_intensity = pulse_envelope(self.wl_nm) gridded_phase = phase_envelope(self.wl_nm) # Calculate time domain complex electric field A self.set_AW(gridded_intensity*np.exp(1j*gridded_phase)) # Calculate normalization factor to achieve requested # pulse energy e_scale = np.sqrt(power / self.calc_epp() ) self.set_AT(self.AT * e_scale ) except IOError: print 'File not found.'
def filter(self, pulse_in, band, fiber, output_power=None): self.band0 = band / (2 * np.sqrt(np.log(2))) pulse_out = Pulse() pulse_out.clone_pulse(pulse_in) self.setup_fftw(pulse_in, fiber, output_power, raman_plots=False) self.T_BP = np.exp(-(self.wl_nm - self.center_wavelength_nm)**2 / 2 / self.band0**2) pulse_out.set_AW(pulse_out.AW * self.T_BP) return pulse_out
def __init__(self, power, T0_ps, center_wavelength_nm, time_window_ps = 10., frep_MHz = 100., NPTS = 2**10, GDD = 0, TOD = 0, chirp2 = 0, chirp3 = 0, power_is_avg = False): """Generate Gaussian pulse A(t) = sqrt(peak_power[W]) * exp( -(t/T0 [ps])^2 / 2 ) centered at wavelength center_wavelength_nm (nm). time_window (ps) sets temporal grid size. Optional GDD and TOD are in ps^2 and ps^3.""" Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) GDD = GDD TOD = TOD self.set_AT( np.sqrt(power) * np.exp(-2.77*self.T_ps**2/(T0_ps**2)) ) # input field (W^0.5) if power_is_avg: self.set_AT(self.AT * np.sqrt( power / ( frep_MHz*1.0e6 * self.calc_epp()) )) self.chirp_pulse_W(GDD, TOD) self.chirp_pulse_T(chirp2, chirp3, T0_ps)
def __init__(self, power, T0_ps, center_wavelength_nm, time_window_ps = 10., frep_MHz = 100., NPTS = 2**10, GDD = 0, TOD = 0, chirp2 = 0, chirp3 = 0, power_is_avg = False): """Generate sech pulse A(t) = sqrt(P0 [W]) * sech(t/T0 [ps]) centered at wavelength center_wavelength_nm (nm). time_window (ps) sets temporal grid size. Optional GDD and TOD are in ps^2 and ps^3.""" Pulse.__init__(self, frep_MHz = frep_MHz, n = NPTS) # make sure we weren't passed mks units assert (center_wavelength_nm > 1.0) assert (time_window_ps > 1.0 ) self.set_center_wavelength_nm(center_wavelength_nm) self.set_time_window_ps(time_window_ps) ### Generate pulse if not power_is_avg: self.set_AT( np.sqrt(power)/np.cosh(self.T_ps/T0_ps) ) else: self.set_AT( 1 / np.cosh(self.T_ps/T0_ps) ) self.set_AT(self.AT * np.sqrt( power / ( frep_MHz*1.0e6 * self.calc_epp()) )) self.chirp_pulse_W(GDD, TOD) self.chirp_pulse_T(chirp2, chirp3, T0_ps)
def get_run(self, run_num=None, z_num=None): """ Return tuple of (pump, signal, idler) pulses for run # n at z index z_num . By default, returns last z step of last run.""" if run_num is None: run_num = self.run_ctr - 1 if run_num < 0 or run_num >= self.run_ctr: raise IndexError(str(run_num) + ' not a valid run index.') if z_num is None: z_num = -1 run = self.root_name + '/run' + str(run_num) # Read in and generate pump pulse pump_field = self.tables_file.get_node(run + '/pump')[:, z_num] pump_Twind = self.tables_file.get_node(run + '/pump_Twind')[0] pump_center = self.tables_file.get_node(run + '/pump_center_nm')[0] p = Pulse() p.set_NPTS(len(pump_field)) p.set_center_wavelength_nm(pump_center) p.set_time_window_ps(pump_Twind) p.set_AW(pump_field) p.set_frep_MHz(self.frep_Hz * 1.0e-6) # Read in and generate signal pulse sgnl_field = self.tables_file.get_node(run + '/sgnl')[:, z_num] sgnl_Twind = self.tables_file.get_node(run + '/sgnl_Twind')[0] sgnl_center = self.tables_file.get_node(run + '/sgnl_center_nm')[0] s = Pulse() s.set_NPTS(len(sgnl_field)) s.set_center_wavelength_nm(sgnl_center) s.set_time_window_ps(sgnl_Twind) s.set_AW(sgnl_field) s.set_frep_MHz(self.frep_Hz * 1.0e-6) # Read in and generate idler pulse idlr_field = self.tables_file.get_node(run + '/idlr')[:, z_num] idlr_Twind = self.tables_file.get_node(run + '/idlr_Twind')[0] idlr_center = self.tables_file.get_node(run + '/idlr_center_nm')[0] i = Pulse() i.set_NPTS(len(idlr_field)) i.set_center_wavelength_nm(idlr_center) i.set_time_window_ps(idlr_Twind) i.set_AW(idlr_field) i.set_frep_MHz(self.frep_Hz * 1.0e-6) return (p, s, i)
def get_run(self, run_num = None, z_num = None): """ Return tuple of (pump, signal, idler) pulses for run # n at z index z_num . By default, returns last z step of last run.""" if run_num is None: run_num = self.run_ctr - 1 if run_num < 0 or run_num >= self.run_ctr: raise IndexError(str(run_num)+' not a valid run index.') if z_num is None: z_num = -1 run = self.root_name+'/run'+str(run_num) # Read in and generate pump pulse pump_field = self.tables_file.get_node(run+'/pump')[:,z_num] pump_Twind = self.tables_file.get_node(run+'/pump_Twind')[0] pump_center = self.tables_file.get_node(run+'/pump_center_nm')[0] p = Pulse() p.set_NPTS(len(pump_field)) p.set_center_wavelength_nm(pump_center) p.set_time_window_ps(pump_Twind) p.set_AW(pump_field) p.set_frep_MHz(self.frep_Hz * 1.0e-6) # Read in and generate signal pulse sgnl_field = self.tables_file.get_node(run+'/sgnl')[:,z_num] sgnl_Twind = self.tables_file.get_node(run+'/sgnl_Twind')[0] sgnl_center = self.tables_file.get_node(run+'/sgnl_center_nm')[0] s = Pulse() s.set_NPTS(len(sgnl_field)) s.set_center_wavelength_nm(sgnl_center) s.set_time_window_ps(sgnl_Twind) s.set_AW(sgnl_field) s.set_frep_MHz(self.frep_Hz * 1.0e-6) # Read in and generate idler pulse idlr_field = self.tables_file.get_node(run+'/idlr')[:,z_num] idlr_Twind = self.tables_file.get_node(run+'/idlr_Twind')[0] idlr_center = self.tables_file.get_node(run+'/idlr_center_nm')[0] i = Pulse() i.set_NPTS(len(idlr_field)) i.set_center_wavelength_nm(idlr_center) i.set_time_window_ps(idlr_Twind) i.set_AW(idlr_field) i.set_frep_MHz(self.frep_Hz * 1.0e-6) return (p, s, i)
def propagate(self, pulse_in, fiber, n_steps, output_power=None, reload_fiber_each_step=False): """ This is the main user-facing function that allows a pulse to be propagated along a fiber (or other nonlinear medium). Parameters ---------- pulse_in : pulse object this is an instance of the :class:`pynlo.light.PulseBase.Pulse` class. fiber : fiber object this is an instance of the :class:`pynlo.media.fibers.fiber.FiberInstance` class. n_steps : int the number of steps requested in the integrator output. Note: the RK4IP integrator uses an adaptive step size. It should pick the correct step size automatically, so setting n_steps should not affect the accuracy, just the number of points that are returned by this funciton. output_power : This parameter is a mystery reload_fiber_each_step : boolean This flag determines if the fiber parameters should be reloaded every step. It is necessary if the fiber dispersion or gamma changes along the fiber length. :func:`pynlo.media.fibers.fiber.FiberInstance.set_dispersion_function` and :func:`pynlo.media.fibers.fiber.FiberInstance.set_dispersion_function` should be used to specify how the dispersion and gamma change with the fiber length Returns ------- z_positions : array of float an array of z-positions along the fiber (in meters) AW : 2D array of complex128 A 2D numpy array corresponding to the intensities in each *frequency* bin for each step in the z-direction of the fiber. AT : 2D array of complex128 A 2D numpy array corresponding to the intensities in each *time* bin for each step in the z-direction of the fiber. pulse_out : PulseBase object the pulse after it has propagated through the fiber. This object is suitable for propagation through the next fiber! """ n_steps = int(n_steps) # Copy parameters from pulse and fiber into class-wide variables z_positions = np.linspace(0, fiber.length, n_steps + 1) if n_steps == 1: delta_z = fiber.length else: delta_z = z_positions[1] - z_positions[0] AW = np.complex64(np.zeros((pulse_in.NPTS, n_steps))) AT = np.complex64(np.copy(AW)) #print ("Pulse energy before", fiber.fibertype,":", \ # 1e9 * pulse_in.calc_epp(), 'nJ' ) pulse_out = Pulse() pulse_out.clone_pulse(pulse_in) self.setup_fftw(pulse_in, fiber, output_power, raman_plots=False) self.load_fiber_parameters(pulse_in, fiber, output_power) for i in range(n_steps): #print ("Step:", i, "Distance remaining:", fiber.length * (1 - np.float(i)/n_steps) ) if reload_fiber_each_step: self.load_fiber_parameters(pulse_in, fiber, output_power, z=i * delta_z) self.integrate_over_dz(delta_z) AW[:, i] = self.conditional_ifftshift(self.FFT_t_2(self.A)) AT[:, i] = self.conditional_ifftshift(self.A) pulse_out.set_AT(self.conditional_ifftshift(self.A)) #print ("Pulse energy after:", \ # 1e9 * pulse_out.calc_epp(), 'nJ' ) pulse_out.set_AT(self.conditional_ifftshift(self.A)) #print ( "Pulse energy after", fiber.fibertype,":", \ # 1e9 * pulse_out.calc_epp(), 'nJ' ) # print "alpha out:",self.alpha self.cleanup() return z_positions, AW, AT, pulse_out
roundtrip = 20 for i in range(roundtrip): print('正在运行第%s次循环,共%s循环' % (i + 1, roundtrip)) Et_1.append(evol.propagate(Et_8[i], Fiber1, n_steps=Steps)[3]) # PulseTemp = Pulse() # PulseTemp.clone_pulse(Et) # PulseTemp.set_AT(Et_1[i]) Et_2.append(evol.filter(Et_1[i], band, Fiber1)) Et_3.append(evol.propagate(Et_2[i], Fiber2, n_steps=Steps)[3]) Et_4.append(evol.propagate(Et_3[i], FiberYsfLo, n_steps=Steps)[3]) Et_5.append(evol.propagate(Et_4[i], Fiber3, n_steps=Steps)[3]) # NALM #clock Eclock0 = Pulse() Eclock0.clone_pulse(Et_5[i]) Eclock0.set_AT(np.sqrt(CRatio) * Eclock0.AT) Eclock1 = evol.propagate(Eclock0, FiberSmf1, n_steps=Steps)[3] Eclock2 = evol.propagate(Eclock1, FiberYsfHi, n_steps=Steps)[3] Eclock3 = evol.propagate(Eclock2, FiberSmf2, n_steps=Steps)[3] #anclock Eanclock0 = Pulse() Eanclock0.clone_pulse(Et_5[i]) Eanclock0.set_AT(1j * np.sqrt(1 - CRatio) * Eanclock0.AT) Eanclock1 = evol.propagate(Eanclock0, FiberSmf2, n_steps=Steps)[3] Eanclock2 = evol.propagate(Eanclock1, FiberYsfHi, n_steps=Steps)[3] Eanclock3 = evol.propagate(Eanclock2, FiberSmf1, n_steps=Steps)[3] E6 = Pulse() E6.clone_pulse(Et_5[i])