def flux_vs_psi(divergence=numpy.linspace(-50, 50, 1000), electronEnergy=2.0, r_m=7.6136, photon_energy=0.1, i_a=0.5): codata_mee = 1e-6 * codata.m_e * codata.c**2 / codata.e cte = (3.0e0 / 4 / numpy.pi) * codata.h * codata.c * numpy.power( 1e3 / codata_mee, 3) / codata.e ec_ev = cte * numpy.power(electronEnergy, 3) / r_m f_1 = sync_ang(1,divergence,polarization=0, \ e_gev=electronEnergy,i_a=i_a,hdiv_mrad=1.0,r_m=r_m,energy=photon_energy,ec_ev=ec_ev) return f_1
def generate(self): if self.figure_canvas is not None: self.mainArea.layout().removeWidget(self.figure_canvas) # # Calculating the critical energy in eV following Green pag.3. # gamma = self.ELECTRON_ENERGY * 1e3 / codata_mee # the electron energy is given in GeV. critical_wavelength = 4.0 * np.pi * self.MAGNETIC_RADIUS / 3.0 / np.power( gamma, 3) # wavelength in m. ec_ev = m2ev / critical_wavelength # critical energy in eV. # # Constructing the angle and energy grids. # if self.ENERGY_POINTS == 1: # monochromatic bunch. ENERGY_MIN = ENERGY_MAX = self.ENERGY else: ENERGY_MIN = self.ENERGY_MIN ENERGY_MAX = self.ENERGY_MAX energies = np.linspace(start=ENERGY_MIN, stop=ENERGY_MAX, num=self.ENERGY_POINTS) if self.ANGLE_DEVIATION_POINTS == 1: # unidirectional bunch. ANGLE_DEVIATION_MIN = ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION * 1e-6 # urad --> rad else: ANGLE_DEVIATION_MIN = self.ANGLE_DEVIATION_MIN * 1e-6 # urad --> rad ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION_MAX * 1e-6 # urad --> rad deviations = np.linspace(start=ANGLE_DEVIATION_MIN, stop=ANGLE_DEVIATION_MAX, num=self.ANGLE_DEVIATION_POINTS) sync_ang_deviations = np.multiply( deviations, 1e3) # sync_ang takes as an input angles in mrad, not urad. photon_bunch = PolarizedPhotonBunch([]) for energy in energies: photon_bunch_to_add = stokes_calculator(energy, sync_ang_deviations, self.ELECTRON_ENERGY, self.ELECTRON_CURRENT, self.HORIZONTAL_DIVERGENCE, float(ec_ev)) photon_bunch.addBunch(photon_bunch_to_add) # # Dump data to file if requested. # if self.DUMP_TO_FILE: print("BendingMagnet: Writing data in {file}...\n".format( file=self.FILE_NAME)) with open(self.FILE_NAME, "w") as file: try: file.write("#S 1 photon bunch\n" "#N 9\n" "#L Energy [eV] Vx Vy Vz S0 S1 S2 S3\n") file.write(photon_bunch.toString()) file.close() print("File written to disk: %s" % self.FILE_NAME) except: raise Exception( "BendingMagnet: The data could not be dumped onto the specified file!\n" ) # # Plotting the emission profiles according to user input if requested. # if self.VIEW_EMISSION_PROFILE == 1: self.fig.clf() # clear the current Figure. self.figure_canvas.draw() elif self.VIEW_EMISSION_PROFILE == 0: self.fig.clf() # clear the current Figure. ax = self.fig.add_subplot(111) toptitle = "Bending Magnet angular emission" xtitle = "Psi[mrad]" ytitle = "Power density[Watts/mrad]" if self.ENERGY_POINTS == 1: flux = sync_ang(1, sync_ang_deviations, polarization=0, e_gev=self.ELECTRON_ENERGY, i_a=self.ELECTRON_CURRENT, hdiv_mrad=1.0, energy=self.ENERGY, ec_ev=ec_ev) ax.plot(sync_ang_deviations, flux, 'g', label="E={} keV".format(self.ENERGY * 1e-3)) else: flux_Emin = sync_ang( 1, sync_ang_deviations, polarization=0, # energy = lower limit. e_gev=self.ELECTRON_ENERGY, i_a=self.ELECTRON_CURRENT, hdiv_mrad=1.0, energy=self.ENERGY_MIN, ec_ev=ec_ev) flux_Emax = sync_ang( 1, sync_ang_deviations, polarization=0, # energy = upper limit. e_gev=self.ELECTRON_ENERGY, i_a=self.ELECTRON_CURRENT, hdiv_mrad=1.0, energy=self.ENERGY_MAX, ec_ev=ec_ev) ax.plot(sync_ang_deviations, flux_Emin, 'r', label="E min={} keV".format(self.ENERGY_MIN * 1e-3)) ax.plot(sync_ang_deviations, flux_Emax, 'b', label="E max={} keV".format(self.ENERGY_MAX * 1e-3)) ax.set_title(toptitle) ax.set_xlabel(xtitle) ax.set_ylabel(ytitle) ax.set_xlim(sync_ang_deviations.min(), sync_ang_deviations.max()) ax.legend(bbox_to_anchor=(1.1, 1.05)) self.figure_canvas.draw() print("BendingMagnet: Photon bunch generated.\n") self.send("photon bunch", photon_bunch)
def xoppy_calc_bm(MACHINE_NAME="ESRF bending magnet",RB_CHOICE=0,MACHINE_R_M=25.0,BFIELD_T=0.8,\ BEAM_ENERGY_GEV=6.04,CURRENT_A=0.1,HOR_DIV_MRAD=1.0,VER_DIV=0,\ PHOT_ENERGY_MIN=100.0,PHOT_ENERGY_MAX=100000.0,NPOINTS=500,LOG_CHOICE=1,\ PSI_MRAD_PLOT=1.0,PSI_MIN=-1.0,PSI_MAX=1.0,PSI_NPOINTS=500,TYPE_CALC=0,FILE_DUMP=0): print("Inside xoppy_calc_bm. ") # electron energy in GeV gamma = BEAM_ENERGY_GEV*1e3 / srfunc.codata_mee r_m = MACHINE_R_M # magnetic radius in m if RB_CHOICE == 1: r_m = srfunc.codata_me * srfunc.codata_c / srfunc.codata_ec / BFIELD_T * numpy.sqrt(gamma * gamma - 1) # calculate critical energy in eV ec_m = 4.0*numpy.pi*r_m/3.0/numpy.power(gamma,3) # wavelength in m ec_ev = srfunc.m2ev / ec_m fm = None a = None energy_ev = None if TYPE_CALC == 0: if LOG_CHOICE == 0: energy_ev = numpy.linspace(PHOT_ENERGY_MIN,PHOT_ENERGY_MAX,NPOINTS) # photon energy grid else: energy_ev = numpy.logspace(numpy.log10(PHOT_ENERGY_MIN),numpy.log10(PHOT_ENERGY_MAX),NPOINTS) # photon energy grid a5 = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=0, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a5par = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=1, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a5per = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=2, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) if VER_DIV == 0: coltitles=['Photon Energy [eV]','Photon Wavelength [A]','E/Ec','Flux_spol/Flux_total','Flux_ppol/Flux_total','Flux[Phot/sec/0.1%bw]','Power[Watts/eV]'] title='integrated in Psi,' if VER_DIV == 1: coltitles=['Photon Energy [eV]','Photon Wavelength [A]','E/Ec','Flux_spol/Flux_total','Flux_ppol/Flux_total','Flux[Phot/sec/0.1%bw/mrad(Psi)]','Power[Watts/eV/mrad(Psi)]'] title='at Psi=0,' if VER_DIV == 2: coltitles=['Photon Energy [eV]','Photon Wavelength [A]','E/Ec','Flux_spol/Flux_total','Flux_ppol/Flux_total','Flux[Phot/sec/0.1%bw]','Power[Watts/eV]'] title='in Psi=[%e,%e]'%(PSI_MIN,PSI_MAX) if VER_DIV == 3: coltitles=['Photon Energy [eV]','Photon Wavelength [A]','E/Ec','Flux_spol/Flux_total','Flux_ppol/Flux_total','Flux[Phot/sec/0.1%bw/mrad(Psi)]','Power[Watts/eV/mrad(Psi)]'] title='at Psi=%e mrad'%(PSI_MIN) a6=numpy.zeros((7,len(energy_ev))) a1 = energy_ev a6[0,:] = (a1) a6[1,:] = srfunc.m2ev * 1e10 / (a1) a6[2,:] = (a1)/ec_ev # E/Ec a6[3,:] = numpy.array(a5par)/numpy.array(a5) a6[4,:] = numpy.array(a5per)/numpy.array(a5) a6[5,:] = numpy.array(a5) a6[6,:] = numpy.array(a5)*1e3 * srfunc.codata_ec if TYPE_CALC == 1: # angular distributions over over all energies angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT,NPOINTS) # angle grid a6 = numpy.zeros((6,NPOINTS)) a6[0,:] = angle_mrad # angle in mrad a6[1,:] = angle_mrad*gamma/1e3 # Psi[rad]*Gamma a6[2,:] = srfunc.sync_f(angle_mrad * gamma / 1e3) a6[3,:] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=1) a6[4,:] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=2) a6[5,:] = srfunc.sync_ang(0, angle_mrad, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, e_gev=BEAM_ENERGY_GEV, r_m=r_m) coltitles=['Psi[mrad]','Psi[rad]*Gamma','F','F s-pol','F p-pol','Power[Watts/mrad(Psi)]'] if TYPE_CALC == 2: # angular distributions at a single energy angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT,NPOINTS) # angle grid a6 = numpy.zeros((7,NPOINTS)) a6[0,:] = angle_mrad # angle in mrad a6[1,:] = angle_mrad*gamma/1e3 # Psi[rad]*Gamma a6[2,:] = srfunc.sync_f(angle_mrad * gamma / 1e3) a6[3,:] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=1) a6[4,:] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=2) tmp = srfunc.sync_ang(1, angle_mrad, energy=PHOT_ENERGY_MIN, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, e_gev=BEAM_ENERGY_GEV, ec_ev=ec_ev) tmp.shape = -1 a6[5,:] = tmp a6[6,:] = a6[5,:] * srfunc.codata_ec * 1e3 coltitles=['Psi[mrad]','Psi[rad]*Gamma','F','F s-pol','F p-pol','Flux[Ph/sec/0.1%bw/mrad(Psi)]','Power[Watts/eV/mrad(Psi)]'] if TYPE_CALC == 3: # angular,energy distributions flux angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT,NPOINTS) # angle grid if LOG_CHOICE == 0: energy_ev = numpy.linspace(PHOT_ENERGY_MIN,PHOT_ENERGY_MAX,NPOINTS) # photon energy grid else: energy_ev = numpy.logspace(numpy.log10(PHOT_ENERGY_MIN),numpy.log10(PHOT_ENERGY_MAX),NPOINTS) # photon energy grid # fm[angle,energy] fm = srfunc.sync_ene(4, energy_ev, ec_ev=ec_ev, e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, \ hdiv_mrad=HOR_DIV_MRAD, psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a = numpy.linspace(PSI_MIN,PSI_MAX,PSI_NPOINTS) a6 = numpy.zeros((4,len(a)*len(energy_ev))) ij = -1 for i in range(len(a)): for j in range(len(energy_ev)): ij += 1 a6[0,ij] = a[i] a6[1,ij] = energy_ev[j] a6[2,ij] = fm[i,j] * srfunc.codata_ec * 1e3 a6[3,ij] = fm[i,j] coltitles=['Psi [mrad]','Photon Energy [eV]','Power [Watts/eV/mrad(Psi)]','Flux [Ph/sec/0.1%bw/mrad(Psi)]'] # write spec file ncol = len(coltitles) npoints = len(a6[0,:]) if FILE_DUMP == 1: outFile = "bm.spec" f = open(outFile,"w") f.write("#F "+outFile+"\n") f.write("\n") f.write("#S 1 bm results\n") f.write("#N %d\n"%(ncol)) f.write("#L") for i in range(ncol): f.write(" "+coltitles[i]) f.write("\n") for i in range(npoints): f.write((" %e "*ncol+"\n")%(tuple(a6[:,i].tolist()))) f.close() print("File written to disk: " + outFile) return a6.T, fm, a, energy_ev
def xoppy_calc_wiggler_radiation( ELECTRONENERGY=3.0, ELECTRONCURRENT=0.1, PERIODID=0.120, NPERIODS=37.0, KV=22.416, DISTANCE=30.0, HSLITPOINTS=500, VSLITPOINTS=500, PHOTONENERGYMIN=100.0, PHOTONENERGYMAX=100100.0, PHOTONENERGYPOINTS=101, NTRAJPOINTS=1001, FIELD=0, FILE="/Users/srio/Oasys/Bsin.txt", POLARIZATION=0, # 0=total, 1=parallel (s), 2=perpendicular (p) SHIFT_X_FLAG=0, SHIFT_X_VALUE=0.0, SHIFT_BETAX_FLAG=0, SHIFT_BETAX_VALUE=0.0, CONVOLUTION=1, PASSEPARTOUT=3.0, h5_file="wiggler_radiation.h5", h5_entry_name="XOPPY_RADIATION", h5_initialize=True, h5_parameters=None, do_plot=False, ): # calculate wiggler trajectory if FIELD == 0: (traj, pars) = srfunc.wiggler_trajectory( b_from=0, inData="", nPer=int(NPERIODS), #37, nTrajPoints=NTRAJPOINTS, ener_gev=ELECTRONENERGY, per=PERIODID, kValue=KV, trajFile="", shift_x_flag=SHIFT_X_FLAG, shift_x_value=SHIFT_X_VALUE, shift_betax_flag=SHIFT_BETAX_FLAG, shift_betax_value=SHIFT_BETAX_VALUE) if FIELD == 1: # magnetic field from B(s) map (traj, pars) = srfunc.wiggler_trajectory(b_from=1, nPer=1, nTrajPoints=NTRAJPOINTS, ener_gev=ELECTRONENERGY, inData=FILE, trajFile="", shift_x_flag=SHIFT_X_FLAG, shift_x_value=SHIFT_X_VALUE, shift_betax_flag=SHIFT_BETAX_FLAG, shift_betax_value=SHIFT_BETAX_FLAG) if FIELD == 2: raise ("Not implemented") energy, flux, power = srfunc.wiggler_spectrum( traj, enerMin=PHOTONENERGYMIN, enerMax=PHOTONENERGYMAX, nPoints=PHOTONENERGYPOINTS, electronCurrent=ELECTRONCURRENT, outFile="", elliptical=False, polarization=POLARIZATION) try: cumulated_power = power.cumsum() * numpy.abs(energy[0] - energy[1]) except: cumulated_power = 0.0 print("\nPower from integral of spectrum (sum rule): %8.3f W" % (cumulated_power[-1])) try: cumulated_power = cumtrapz(power, energy, initial=0) except: cumulated_power = 0.0 print("Power from integral of spectrum (trapezoid rule): %8.3f W" % (cumulated_power[-1])) codata_mee = 1e-6 * codata.m_e * codata.c**2 / codata.e # electron mass in meV gamma = ELECTRONENERGY * 1e3 / codata_mee Y = traj[1, :].copy() divX = traj[3, :].copy() By = traj[7, :].copy() # rho = (1e9 / codata.c) * ELECTRONENERGY / By # Ec0 = 3 * codata.h * codata.c * gamma**3 / (4 * numpy.pi * rho) / codata.e # Ec = 665.0 * ELECTRONENERGY**2 * numpy.abs(By) # Ecmax = 665.0 * ELECTRONENERGY** 2 * (numpy.abs(By)).max() coeff = 3 / ( 4 * numpy.pi) * codata.h * codata.c**2 / codata_mee**3 / codata.e # ~665.0 Ec = coeff * ELECTRONENERGY**2 * numpy.abs(By) Ecmax = coeff * ELECTRONENERGY**2 * (numpy.abs(By)).max() # approx formula for divergence (first formula in pag 43 of Tanaka's paper) sigmaBp = 0.597 / gamma * numpy.sqrt(Ecmax / PHOTONENERGYMIN) # we use vertical interval 6*sigmaBp and horizontal interval = vertical + trajectory interval divXX = numpy.linspace(divX.min() - PASSEPARTOUT * sigmaBp, divX.max() + PASSEPARTOUT * sigmaBp, HSLITPOINTS) divZZ = numpy.linspace(-PASSEPARTOUT * sigmaBp, PASSEPARTOUT * sigmaBp, VSLITPOINTS) e = numpy.linspace(PHOTONENERGYMIN, PHOTONENERGYMAX, PHOTONENERGYPOINTS) p = numpy.zeros((PHOTONENERGYPOINTS, HSLITPOINTS, VSLITPOINTS)) for i in range(e.size): Ephoton = e[i] # vertical divergence intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION) Ecmean = (Ec * intensity).sum() / intensity.sum() fluxDivZZ = srfunc.sync_ang(1, divZZ * 1e3, polarization=POLARIZATION, e_gev=ELECTRONENERGY, i_a=ELECTRONCURRENT, hdiv_mrad=1.0, energy=Ephoton, ec_ev=Ecmean) if do_plot: from srxraylib.plot.gol import plot plot(divZZ, fluxDivZZ, title="min intensity %f" % fluxDivZZ.min(), xtitle="divZ", ytitle="fluxDivZZ", show=1) # horizontal divergence after Tanaka if False: e_over_ec = Ephoton / Ecmax uudlim = 1.0 / gamma uud = numpy.linspace(-uudlim * 0.99, uudlim * 0.99, divX.size) uu = e_over_ec / numpy.sqrt(1 - gamma**2 * uud**2) plot(uud, 2 * numpy.pi / numpy.sqrt(3) * srfunc.sync_g1(uu)) # horizontal divergence # intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION) intensity_interpolated = interpolate_multivalued_function( divX, intensity, divXX, Y, ) if CONVOLUTION: # do always convolution! intensity_interpolated.shape = -1 divXX_window = divXX[-1] - divXX[0] divXXCC = numpy.linspace(-0.5 * divXX_window, 0.5 * divXX_window, divXX.size) fluxDivZZCC = srfunc.sync_ang(1, divXXCC * 1e3, polarization=POLARIZATION, e_gev=ELECTRONENERGY, i_a=ELECTRONCURRENT, hdiv_mrad=1.0, energy=Ephoton, ec_ev=Ecmax) fluxDivZZCC.shape = -1 intensity_convolved = numpy.convolve( intensity_interpolated / intensity_interpolated.max(), fluxDivZZCC / fluxDivZZCC.max(), mode='same') else: intensity_convolved = intensity_interpolated if i == 0: print( "\n\n============ sizes vs photon energy =======================" ) print( "Photon energy/eV FWHM X'/urad FWHM Y'/urad FWHM X/mm FWHM Z/mm " ) print("%16.3f %12.3f %12.3f %9.2f %9.2f" % (Ephoton, 1e6 * get_fwhm(intensity_convolved, divXX)[0], 1e6 * get_fwhm(fluxDivZZ, divZZ)[0], 1e3 * get_fwhm(intensity_convolved, divXX)[0] * DISTANCE, 1e3 * get_fwhm(fluxDivZZ, divZZ)[0] * DISTANCE)) if do_plot: plot(divX, intensity / intensity.max(), divXX, intensity_interpolated / intensity_interpolated.max(), divXX, intensity_convolved / intensity_convolved.max(), divXX, fluxDivZZCC / fluxDivZZCC.max(), title="min intensity %f, Ephoton=%6.2f" % (intensity.min(), Ephoton), xtitle="divX", ytitle="intensity", legend=["orig", "interpolated", "convolved", "kernel"], show=1) # combine H * V INTENSITY = numpy.outer( intensity_convolved / intensity_convolved.max(), fluxDivZZ / fluxDivZZ.max()) p[i, :, :] = INTENSITY if do_plot: from srxraylib.plot.gol import plot_image, plot_surface, plot_show plot_image(INTENSITY, divXX, divZZ, aspect='auto', title="E=%6.2f" % Ephoton, show=1) # to create oasys icon... # plot_surface(INTENSITY, divXX, divZZ, title="", show=0) # import matplotlib.pylab as plt # plt.xticks([]) # plt.yticks([]) # plt.axis('off') # plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off', # labeltop='off', labelright='off', labelbottom='off') # # plot_show() # h = divXX * DISTANCE * 1e3 # in mm for the h5 file v = divZZ * DISTANCE * 1e3 # in mm for the h5 file print("\nWindow size: %f mm [H] x %f mm [V]" % (h[-1] - h[0], v[-1] - v[0])) print("Window size: %g rad [H] x %g rad [V]" % (divXX[-1] - divXX[0], divZZ[-1] - divZZ[0])) # normalization and total flux for i in range(e.size): INTENSITY = p[i, :, :] # norm = INTENSITY.sum() * (h[1] - h[0]) * (v[1] - v[0]) norm = trapezoidal_rule_2d_1darrays(INTENSITY, h, v) p[i, :, :] = INTENSITY / norm * flux[i] # fit fit_ok = False try: power = p.sum(axis=0) * (e[1] - e[0]) * codata.e * 1e3 print( "\n\n============= Fitting power density to a 2D Gaussian. ==============\n" ) print( "Please use these results with care: check if the original data looks like a Gaussian." ) fit_parameters = fit_gaussian2d(power, h, v) print(info_params(fit_parameters)) H, V = numpy.meshgrid(h, v) data_fitted = twoD_Gaussian((H, V), *fit_parameters) print(" Total power (sum rule) in the fitted data [W]: ", data_fitted.sum() * (h[1] - h[0]) * (v[1] - v[0])) # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT") print("====================================================\n") fit_ok = True except: pass # output file if h5_file != "": try: if h5_initialize: h5w = H5SimpleWriter.initialize_file( h5_file, creator="xoppy_wigglers.py") else: h5w = H5SimpleWriter(h5_file, None) h5w.create_entry(h5_entry_name, nx_default=None) h5w.add_stack(e, h, v, p, stack_name="Radiation", entry_name=h5_entry_name, title_0="Photon energy [eV]", title_1="X gap [mm]", title_2="Y gap [mm]") h5w.create_entry("parameters", root_entry=h5_entry_name, nx_default=None) if h5_parameters is not None: for key in h5_parameters.keys(): h5w.add_key(key, h5_parameters[key], entry_name=h5_entry_name + "/parameters") h5w.create_entry("trajectory", root_entry=h5_entry_name, nx_default="transversal trajectory") h5w.add_key("traj", traj, entry_name=h5_entry_name + "/trajectory") h5w.add_dataset(traj[1, :], traj[0, :], dataset_name="transversal trajectory", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="X [m]") h5w.add_dataset(traj[1, :], traj[3, :], dataset_name="transversal velocity", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="Vx/c") h5w.add_dataset(traj[1, :], traj[7, :], dataset_name="Magnetic field", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="Bz [T]") if fit_ok: h5w.add_image(power, h, v, image_name="PowerDensity", entry_name=h5_entry_name, title_x="X [mm]", title_y="Y [mm]") h5w.add_image(data_fitted.reshape(h.size, v.size), h, v, image_name="PowerDensityFit", entry_name=h5_entry_name, title_x="X [mm]", title_y="Y [mm]") h5w.add_key("fit_info", info_params(fit_parameters), entry_name=h5_entry_name + "/PowerDensityFit") print("File written to disk: %s" % h5_file) except: print("ERROR initializing h5 file") return e, h, v, p, traj
def xoppy_calc_bm(MACHINE_NAME="ESRF bending magnet",RB_CHOICE=0,MACHINE_R_M=25.0,BFIELD_T=0.8,\ BEAM_ENERGY_GEV=6.04,CURRENT_A=0.1,HOR_DIV_MRAD=1.0,VER_DIV=0,\ PHOT_ENERGY_MIN=100.0,PHOT_ENERGY_MAX=100000.0,NPOINTS=500,LOG_CHOICE=1,\ PSI_MRAD_PLOT=1.0,PSI_MIN=-1.0,PSI_MAX=1.0,PSI_NPOINTS=500,TYPE_CALC=0,FILE_DUMP=0): # electron energy in GeV gamma = BEAM_ENERGY_GEV * 1e3 / srfunc.codata_mee r_m = MACHINE_R_M # magnetic radius in m if RB_CHOICE == 1: r_m = srfunc.codata_me * srfunc.codata_c / srfunc.codata_ec / BFIELD_T * numpy.sqrt( gamma * gamma - 1) # calculate critical energy in eV ec_m = 4.0 * numpy.pi * r_m / 3.0 / numpy.power(gamma, 3) # wavelength in m ec_ev = srfunc.m2ev / ec_m fm = None a = None energy_ev = None if TYPE_CALC == 0: if LOG_CHOICE == 0: energy_ev = numpy.linspace(PHOT_ENERGY_MIN, PHOT_ENERGY_MAX, NPOINTS) # photon energy grid else: energy_ev = numpy.logspace(numpy.log10(PHOT_ENERGY_MIN), numpy.log10(PHOT_ENERGY_MAX), NPOINTS) # photon energy grid a5 = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=0, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a5par = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=1, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a5per = srfunc.sync_ene(VER_DIV, energy_ev, ec_ev=ec_ev, polarization=2, \ e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, \ psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) if VER_DIV == 0: coltitles = [ 'Photon Energy [eV]', 'Photon Wavelength [A]', 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux[Phot/sec/0.1%bw]', 'Power[Watts/eV]' ] title = 'integrated in Psi,' if VER_DIV == 1: coltitles = [ 'Photon Energy [eV]', 'Photon Wavelength [A]', 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux[Phot/sec/0.1%bw/mrad(Psi)]', 'Power[Watts/eV/mrad(Psi)]' ] title = 'at Psi=0,' if VER_DIV == 2: coltitles = [ 'Photon Energy [eV]', 'Photon Wavelength [A]', 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux[Phot/sec/0.1%bw]', 'Power[Watts/eV]' ] title = 'in Psi=[%e,%e]' % (PSI_MIN, PSI_MAX) if VER_DIV == 3: coltitles = [ 'Photon Energy [eV]', 'Photon Wavelength [A]', 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux[Phot/sec/0.1%bw/mrad(Psi)]', 'Power[Watts/eV/mrad(Psi)]' ] title = 'at Psi=%e mrad' % (PSI_MIN) a6 = numpy.zeros((7, len(energy_ev))) a1 = energy_ev a6[0, :] = (a1) a6[1, :] = srfunc.m2ev * 1e10 / (a1) a6[2, :] = (a1) / ec_ev # E/Ec a6[3, :] = numpy.array(a5par) / numpy.array(a5) a6[4, :] = numpy.array(a5per) / numpy.array(a5) a6[5, :] = numpy.array(a5) a6[6, :] = numpy.array(a5) * 1e3 * srfunc.codata_ec if TYPE_CALC == 1: # angular distributions over over all energies angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT, NPOINTS) # angle grid a6 = numpy.zeros((6, NPOINTS)) a6[0, :] = angle_mrad # angle in mrad a6[1, :] = angle_mrad * gamma / 1e3 # Psi[rad]*Gamma a6[2, :] = srfunc.sync_f(angle_mrad * gamma / 1e3) a6[3, :] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=1) a6[4, :] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=2) a6[5, :] = srfunc.sync_ang(0, angle_mrad, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, e_gev=BEAM_ENERGY_GEV, r_m=r_m) coltitles = [ 'Psi[mrad]', 'Psi[rad]*Gamma', 'F', 'F s-pol', 'F p-pol', 'Power[Watts/mrad(Psi)]' ] if TYPE_CALC == 2: # angular distributions at a single energy angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT, NPOINTS) # angle grid a6 = numpy.zeros((7, NPOINTS)) a6[0, :] = angle_mrad # angle in mrad a6[1, :] = angle_mrad * gamma / 1e3 # Psi[rad]*Gamma a6[2, :] = srfunc.sync_f(angle_mrad * gamma / 1e3) a6[3, :] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=1) a6[4, :] = srfunc.sync_f(angle_mrad * gamma / 1e3, polarization=2) tmp = srfunc.sync_ang(1, angle_mrad, energy=PHOT_ENERGY_MIN, i_a=CURRENT_A, hdiv_mrad=HOR_DIV_MRAD, e_gev=BEAM_ENERGY_GEV, ec_ev=ec_ev) tmp.shape = -1 a6[5, :] = tmp a6[6, :] = a6[5, :] * srfunc.codata_ec * 1e3 coltitles = [ 'Psi[mrad]', 'Psi[rad]*Gamma', 'F', 'F s-pol', 'F p-pol', 'Flux[Ph/sec/0.1%bw/mrad(Psi)]', 'Power[Watts/eV/mrad(Psi)]' ] if TYPE_CALC == 3: # angular,energy distributions flux angle_mrad = numpy.linspace(-PSI_MRAD_PLOT, +PSI_MRAD_PLOT, NPOINTS) # angle grid if LOG_CHOICE == 0: energy_ev = numpy.linspace(PHOT_ENERGY_MIN, PHOT_ENERGY_MAX, NPOINTS) # photon energy grid else: energy_ev = numpy.logspace(numpy.log10(PHOT_ENERGY_MIN), numpy.log10(PHOT_ENERGY_MAX), NPOINTS) # photon energy grid # fm[angle,energy] fm = srfunc.sync_ene(4, energy_ev, ec_ev=ec_ev, e_gev=BEAM_ENERGY_GEV, i_a=CURRENT_A, \ hdiv_mrad=HOR_DIV_MRAD, psi_min=PSI_MIN, psi_max=PSI_MAX, psi_npoints=PSI_NPOINTS) a = numpy.linspace(PSI_MIN, PSI_MAX, PSI_NPOINTS) a6 = numpy.zeros((4, len(a) * len(energy_ev))) ij = -1 for i in range(len(a)): for j in range(len(energy_ev)): ij += 1 a6[0, ij] = a[i] a6[1, ij] = energy_ev[j] a6[2, ij] = fm[i, j] * srfunc.codata_ec * 1e3 a6[3, ij] = fm[i, j] coltitles = [ 'Psi [mrad]', 'Photon Energy [eV]', 'Power [Watts/eV/mrad(Psi)]', 'Flux [Ph/sec/0.1%bw/mrad(Psi)]' ] # write spec file ncol = len(coltitles) npoints = len(a6[0, :]) if FILE_DUMP: outFile = "bm.spec" f = open(outFile, "w") f.write("#F " + outFile + "\n") f.write("\n") f.write("#S 1 bm results\n") f.write("#N %d\n" % (ncol)) f.write("#L") for i in range(ncol): f.write(" " + coltitles[i]) f.write("\n") for i in range(npoints): f.write((" %e " * ncol + "\n") % (tuple(a6[:, i].tolist()))) f.close() print("File written to disk: " + outFile) if TYPE_CALC == 0: if LOG_CHOICE == 0: print("\nPower from integral of spectrum: %15.3f W" % (a5.sum() * 1e3 * srfunc.codata_ec * (energy_ev[1] - energy_ev[0]))) return a6.T, fm, a, energy_ev
def __calculate_rays(self, F_COHER=0, NRAYS=5000, SEED=123456, EPSI_DX=0.0, EPSI_DZ=0.0, psi_interval_in_units_one_over_gamma=None, psi_interval_number_of_points=1001, verbose=False): """ compute the rays in SHADOW matrix (shape (npoints,18) ) :param F_COHER: set this flag for coherent beam :param user_unit_to_m: default 1.0 (m) :return: rays, a numpy.array((npoits,18)) """ if SEED != 0: numpy.random.seed(SEED) rays = numpy.zeros((NRAYS,18)) #RAD_MIN= numpy.abs(self.get_magnetic_structure().radius()) #RAD_MAX= numpy.abs(self.get_magnetic_structure().radius()) # r_aladdin = bending magnet radius in units of length used for source size, CCW rings negative. r_aladdin = self.get_magnetic_structure().radius() if r_aladdin < 0: POL_ANGLE = -90.0 * numpy.pi / 2 else: POL_ANGLE = 90.0 * numpy.pi / 2 HDIV1 = 0.5 * self.get_magnetic_structure().horizontal_divergence() HDIV2 = HDIV1 gamma = self.get_electron_beam().gamma() critical_energy = self.get_magnetic_structure().get_critical_energy(self.get_electron_beam().energy()) if psi_interval_in_units_one_over_gamma is None: c = numpy.array([-0.3600382, 0.11188709]) # see file fit_psi_interval.py x = numpy.log10(self.get_magnetic_structure()._EMIN / critical_energy) y_fit = c[1] + c[0] * x psi_interval_in_units_one_over_gamma = 10 ** y_fit # this is the semi interval psi_interval_in_units_one_over_gamma *= 4 # doubled interval if psi_interval_in_units_one_over_gamma < 2: psi_interval_in_units_one_over_gamma = 2 if verbose: print(">>> psi_interval_in_units_one_over_gamma: ",psi_interval_in_units_one_over_gamma) angle_array_mrad = numpy.linspace(-0.5*psi_interval_in_units_one_over_gamma * 1e3 / gamma, 0.5*psi_interval_in_units_one_over_gamma * 1e3 / gamma, psi_interval_number_of_points) if self.get_magnetic_structure().is_monochromatic(): if verbose: print(">>> calculate_rays: is monochromatic") print(">>> calculate_rays: sync_ang (s) E=%f GeV, I=%f A, D=%f mrad, R=%f m, PhE=%f eV, Ec=%f eV, PhE/Ec=%f "% ( \ self.get_electron_beam().energy(), self.get_electron_beam().current(), (HDIV1 + HDIV2) * 1e3, self.get_magnetic_structure().radius(), # not needed anyway self.get_magnetic_structure()._EMIN, critical_energy, self.get_magnetic_structure()._EMIN/critical_energy, )) angular_distribution_s = sync_ang(1,#Flux at a given photon energy angle_array_mrad, polarization=1,#1 Parallel (l2=1, l3=0, in Sokolov&Ternov notation) e_gev=self.get_electron_beam().energy(), i_a=self.get_electron_beam().current(), hdiv_mrad=(HDIV1+HDIV2)*1e3, r_m=self.get_magnetic_structure().radius(),#not needed anyway energy=self.get_magnetic_structure()._EMIN, ec_ev=critical_energy) if verbose: print(">>> calculate_rays: sync_ang (p)") angular_distribution_p = sync_ang(1,#Flux at a given photon energy angle_array_mrad, polarization=2,#1 Parallel (l2=1, l3=0, in Sokolov&Ternov notation) e_gev=self.get_electron_beam().energy(), i_a=self.get_electron_beam().current(), hdiv_mrad=(HDIV1+HDIV2)*1e3, r_m=self.get_magnetic_structure().radius(),#not needed anyway energy=self.get_magnetic_structure()._EMIN, ec_ev=critical_energy) angular_distribution_s = angular_distribution_s.flatten() angular_distribution_p = angular_distribution_p.flatten() if verbose: from srxraylib.plot.gol import plot plot(angle_array_mrad,angular_distribution_s, angle_array_mrad,angular_distribution_p,xtitle="angle / mrad",legend=["s","p"]) sampler_angle = Sampler1D(angular_distribution_s+angular_distribution_p,angle_array_mrad*1e-3) if verbose: print(">>> calculate_rays: get_n_sampled_points (angle)") sampled_angle = sampler_angle.get_n_sampled_points(NRAYS) if verbose: print(">>> calculate_rays: DONE get_n_sampled_points (angle) %d points"%(sampled_angle.size)) pol_deg_interpolator = interp1d(angle_array_mrad*1e-3, angular_distribution_s/(angular_distribution_s+angular_distribution_p)) sampled_polarization = pol_deg_interpolator(sampled_angle) sampled_photon_energy = numpy.zeros_like(sampled_angle) + self.get_magnetic_structure()._EMIN else: # polychromatic photon_energy_array = numpy.linspace(self.get_magnetic_structure()._EMIN, self.get_magnetic_structure()._EMAX, self.get_magnetic_structure()._NG_E) if verbose: print(">>> sync_ene: calculating energy distribution") fm_s = sync_ene(4,photon_energy_array, ec_ev=self.get_magnetic_structure().get_critical_energy(self.get_electron_beam().energy()), e_gev=self.get_electron_beam().energy(), i_a=self.get_electron_beam().current(), hdiv_mrad=1, psi_min=angle_array_mrad.min(), psi_max=angle_array_mrad.max(), psi_npoints=angle_array_mrad.size, polarization=1) fm_p = sync_ene(4,photon_energy_array, ec_ev=self.get_magnetic_structure().get_critical_energy(self.get_electron_beam().energy()), e_gev=self.get_electron_beam().energy(), i_a=self.get_electron_beam().current(), hdiv_mrad=1, psi_min=angle_array_mrad.min(), psi_max=angle_array_mrad.max(), psi_npoints=angle_array_mrad.size, polarization=2) fm = fm_s + fm_p if verbose: print(">>> DONE sync_ene: calculating energy distribution",photon_energy_array.shape,fm.shape) from srxraylib.plot.gol import plot,plot_image plot(photon_energy_array,fm[fm.shape[0]//2,:],xtitle="Energy / eV",ytitle="Flux at zero elevation") plot(angle_array_mrad, fm[:,0], xtitle="Angle / mrad", ytitle="Flux at Emin="%(photon_energy_array[0])) print(">>>>>>>",fm.shape,angle_array_mrad.shape,photon_energy_array.shape) plot_image(fm,angle_array_mrad,photon_energy_array,aspect='auto',show=0,title="flux",xtitle="Psi / mrad",ytitle="Energy / eV") plot_image(fm_s/fm,angle_array_mrad,photon_energy_array,aspect='auto',title="polarization",xtitle="Psi / mrad",ytitle="Energy / eV") fm1 = numpy.zeros_like(fm) for i in range(fm.shape[0]): fm1[i,:] = fm[i,:] / (photon_energy_array*0.001) # in photons/ev # plot_image(fm,angle_array_mrad,photon_energy_array,aspect='auto',show=0) # plot_image(fm_s/fm,angle_array_mrad,photon_energy_array,aspect='auto',title="polarization") sampler2 = Sampler2D(fm1,angle_array_mrad*1e-3,photon_energy_array) sampled_angle,sampled_photon_energy = sampler2.get_n_sampled_points(NRAYS) Angle_array_mrad = numpy.outer(angle_array_mrad,numpy.ones_like(photon_energy_array)) Photon_energy_array = numpy.outer(numpy.ones_like(angle_array_mrad),photon_energy_array) Pi = numpy.array([Angle_array_mrad.flatten()*1e-3, Photon_energy_array.flatten()]).transpose() P = numpy.array([sampled_angle, sampled_photon_energy]).transpose() sampled_polarization = interpolate.griddata(Pi, (fm_s/fm).flatten(), P, method = "cubic") for itik in range(NRAYS): # ! Synchrontron depth ANGLE = numpy.random.random() * (HDIV1 + HDIV2) - HDIV2 EPSI_PATH = numpy.abs(r_aladdin) * ANGLE if self.get_magnetic_structure()._FLAG_EMITTANCE: sigma_x, sigma_xp, sigma_z, sigma_zp = self.get_electron_beam().get_sigmas_all() # ! calculation of the electrom beam moments at the current position # ! (sX,sZ) = (epsi_wx,epsi_ez): # ! <x2> = sX^2 + sigmaX^2 # ! <x x'> = sX sigmaXp^2 # ! <x'2> = sigmaXp^2 (same for Z) epsi_wX = EPSI_DX + EPSI_PATH # sigma_x * sigma_xp # ! C # ! C Compute the actual distance (EPSI_W*) from the orbital focus # ! C # EPSI_WX = EPSI_DX + EPSI_PATH # EPSI_WZ = EPSI_DZ + EPSI_PATH rSigmaX = numpy.sqrt( (epsi_wX**2) * (sigma_xp**2) + sigma_x**2 ) rSigmaXp = sigma_xp if rSigmaX * rSigmaXp != 0.0: rhoX = epsi_wX * sigma_xp**2 / (rSigmaX * rSigmaXp) else: rhoX = 0.0 mean = [0, 0] cov = [[rSigmaX**2, rhoX*rSigmaX*rSigmaXp], [rhoX*rSigmaX*rSigmaXp, rSigmaXp**2]] # diagonal covariance sampled_x, sampled_xp = numpy.random.multivariate_normal(mean, cov, 1).T # plot_scatter(sampled_x,sampled_xp,title="X") XXX = sampled_x E_BEAM1 = sampled_xp epsi_wZ = EPSI_DZ + EPSI_PATH # sigma_z * sigma_zp rSigmaZ = numpy.sqrt( (epsi_wZ**2) * (sigma_zp**2) + sigma_z**2 ) rSigmaZp = sigma_zp if rSigmaZ * rSigmaZp != 0.0: rhoZ = epsi_wZ * sigma_zp**2 / (rSigmaZ * rSigmaZp) else: rhoZ = 0.0 mean = [0, 0] cov = [[rSigmaZ**2, rhoZ*rSigmaZ*rSigmaZp], [rhoZ*rSigmaZ*rSigmaZp, rSigmaZp**2]] # diagonal covariance sampled_z, sampled_zp = numpy.random.multivariate_normal(mean, cov, 1).T # plot_scatter(sampled_z,sampled_zp,title="Z") ZZZ = sampled_z E_BEAM3 = sampled_zp # print(">>>>>>>>>",sampled_x,sampled_z) else: sigma_x, sigma_xp, sigma_z, sigma_zp = (0.0, 0.0, 0.0, 0.0) rhoX = 0.0 XXX = 0.0 E_BEAM1 = 0.0 ZZZ = 0.0 E_BEAM3 = 0.0 # ! C # ! C Synchrotron depth distribution # ! C # 440 CONTINUE # ! CC R_ALADDIN NEGATIVE FOR COUNTER-CLOCKWISE SOURCE # IF (R_ALADDIN.LT.0) THEN # YYY = (ABS(R_ALADDIN) + XXX) * SIN(ANGLE) # ELSE # YYY = ( R_ALADDIN - XXX) * SIN(ANGLE) # END IF # XXX = COS(ANGLE) * XXX + R_ALADDIN * (1.0D0 - COS(ANGLE)) # Synchrotron depth distribution # R_ALADDIN NEGATIVE FOR COUNTER-CLOCKWISE SOURCE if r_aladdin < 0: YYY = numpy.abs(r_aladdin + XXX) * numpy.sin(ANGLE) else: YYY = numpy.abs(r_aladdin - XXX) * numpy.sin(ANGLE) XXX = numpy.cos(ANGLE) * XXX + r_aladdin * (1.0 - numpy.cos(ANGLE)) rays[itik,0] = XXX rays[itik,1] = YYY rays[itik,2] = ZZZ # ! C # ! C Synchrotron source # ! C Note. The angle of emission IN PLANE is the same as the one used # ! C before. This will give rise to a source curved along the orbit. # ! C The elevation angle is instead characteristic of the SR distribution. # ! C The electron beam emittance is included at this stage. Note that if # ! C EPSI = 0, we'll have E_BEAM = 0.0, with no changes. # ! C # ANGLEX = ANGLE + E_BEAM(1) # DIREC(1) = TAN(ANGLEX) # IF (R_ALADDIN.LT.0.0D0) DIREC(1) = - DIREC(1) # DIREC(2) = 1.0D0 # ARG_ANG = GRID(6,ITIK) ANGLEX = ANGLE + E_BEAM1 DIREC1 = numpy.tan(ANGLEX) if r_aladdin < 0: DIREC1 *= -1.0 DIREC2 = 1.0 ARG_ANG = numpy.random.random() # ! C # ! C In the case of SR, we take into account the fact that the electron # ! C trajectory is not orthogonal to the field. This will give a correction # ! C to the photon energy. We can write it as a correction to the # ! C magnetic field strength; this will linearly shift the critical energy # ! C and, with it, the energy of the emitted photon. # ! C # E_TEMP(3) = TAN(E_BEAM(3))/COS(E_BEAM(1)) # E_TEMP(2) = 1.0D0 # E_TEMP(1) = TAN(E_BEAM(1)) # CALL NORM (E_TEMP,E_TEMP) # CORREC = SQRT(1.0D0-E_TEMP(3)**2) # 4400 CONTINUE E_TEMP3 = numpy.tan(E_BEAM3) / numpy.cos(E_BEAM1) E_TEMP2 = 1.0 E_TEMP1 = numpy.tan(E_BEAM1) E_TEMP_MOD = numpy.sqrt(E_TEMP1**2 + E_TEMP2**2 + E_TEMP3**2) E_TEMP3 /= E_TEMP_MOD E_TEMP2 /= E_TEMP_MOD E_TEMP1 /= E_TEMP_MOD # IF (FDISTR.EQ.6) THEN ! exect synchtotron # CALL ALADDIN1 (ARG_ANG,ANGLEV,F_POL,IER) # Q_WAVE = TWOPI*PHOTON(1)/TOCM*CORREC # POL_DEG = ARG_ANG # ELSE IF (FDISTR.EQ.4) THEN ! synchrotron # print*,"R_MAGNET, DIREC",R_MAGNET,DIREC # ARG_ENER = WRAN (ISTAR1) # RAD_MIN = ABS(R_MAGNET) # # i1 = 1 # arg_ener = 0.5 # arg_ang = 0.5 # CALL WHITE (RAD_MIN,CORREC,ARG_ENER,ARG_ANG,Q_WAVE,ANGLEV,POL_DEG,i1) # # print*,"RAD_MIN,CORREC,ARG_ENER,ARG_ANG,Q_WAVE,ANGLEV,POL_DEG",RAD_MIN,CORREC,ARG_ENER,ARG_ANG,Q_WAVE,ANGLEV,POL_DEG # !Q_WAVE = TWOPI*PHOTON(1)/TOCM*CORREC # print*,"ENER,ANGLEV: ",Q_WAVE*TOCM/TWOPI,ANGLEV # END IF # interpolate for the photon energy,vertical angle,and the degree of polarization. wavelength = codata.h * codata.c / codata.e / sampled_photon_energy[itik] Q_WAVE = 2 * numpy.pi / (wavelength*1e2) ANGLEV = sampled_angle[itik] POL_DEG = sampled_polarization[itik] # IF (ANGLEV.LT.0.0) I_CHANGE = -1 # ANGLEV = ANGLEV + E_BEAM(3) if ANGLEV < 0: I_CHANGE = -1 ANGLEV += E_BEAM3 # ------ NOT LONGER DONE ------ # ! C # ! C Test if the ray is within the specified limits # ! C # IF (FGRID.EQ.0.OR.FGRID.EQ.2) THEN # IF (ANGLEV.GT.VDIV1.OR.ANGLEV.LT.-VDIV2) THEN # ARG_ANG = WRAN(ISTAR1) # ! C # ! C If it is outside the range, then generate another ray. # ! C # GO TO 4400 # END IF # END IF # DIREC(3) = TAN(ANGLEV)/COS(ANGLEX) # CALL NORM (DIREC,DIREC) DIREC3 = numpy.tan(ANGLEV) / numpy.cos(ANGLEX) DIREC_MOD = numpy.sqrt(DIREC1**2 + DIREC2**2 + DIREC3**2) DIREC3 /= DIREC_MOD DIREC2 /= DIREC_MOD DIREC1 /= DIREC_MOD # print(">>>>DIREC,FGRID,R_ALADDIN: ",itik,DIREC1,DIREC2,DIREC3) rays[itik,3] = DIREC1 rays[itik,4] = DIREC2 rays[itik,5] = DIREC3 # # electric field vectors (cols 7-9, 16-18) and phases (cols 14-15) # # ! C # ! C --------------------------------------------------------------------- # ! C POLARIZATION # ! C # ! C Generates the polarization of the ray. This is defined on the # ! C source plane, so that A_VEC is along the X-axis and AP_VEC is along Z-axis. # ! C Then care must be taken so that A will be perpendicular to the ray # ! C direction. # ! C # ! C # A_VEC(1) = 1.0D0 # A_VEC(2) = 0.0D0 # A_VEC(3) = 0.0D0 DIREC = rays[:,3:6].copy() A_VEC = numpy.zeros_like(DIREC) A_VEC[:,0] = 1.0 # ! C # ! C Rotate A_VEC so that it will be perpendicular to DIREC and with the # ! C right components on the plane. # ! C # CALL CROSS (A_VEC,DIREC,A_TEMP) A_TEMP = self.__cross(A_VEC, DIREC) # CALL CROSS (DIREC,A_TEMP,A_VEC) A_VEC = self.__cross(DIREC, A_TEMP) # CALL NORM (A_VEC,A_VEC) A_VEC = self.__norm(A_VEC) # CALL CROSS (A_VEC,DIREC,AP_VEC) AP_VEC = self.__cross(A_VEC, DIREC) # CALL NORM (AP_VEC,AP_VEC) AP_VEC = self.__norm(AP_VEC) # # obtain polarization for each ray (interpolation) # POL_DEG = sampled_polarization DENOM = numpy.sqrt(1.0 - 2.0 * POL_DEG + 2.0 * POL_DEG**2) AX = POL_DEG/DENOM for i in range(3): A_VEC[:,i] *= AX AZ = (1.0-POL_DEG)/DENOM for i in range(3): AP_VEC[:,i] *= AZ rays[:,6:9] = A_VEC rays[:,15:18] = AP_VEC # # ! C # ! C Now the phases of A_VEC and AP_VEC. # ! C # POL_ANGLE = 0.5 * numpy.pi # TO BE CHECKED if F_COHER == 1: PHASEX = 0.0 else: PHASEX = numpy.random.random(NRAYS) * 2 * numpy.pi # PHASEZ = PHASEX + POL_ANGLE * numpy.sign(ANGLEV) rays[:,13] = 0.0 # PHASEX rays[:,14] = 0.0 # PHASEZ # set flag (col 10) rays[:,9] = 1.0 # # photon energy (col 11) # # A2EV = 2.0*numpy.pi/(codata.h*codata.c/codata.e*1e2) # sampled_photon_energy = sampled_photon_energy wavelength = codata.h * codata.c / codata.e /sampled_photon_energy Q_WAVE = 2 * numpy.pi / (wavelength*1e2) rays[:,10] = Q_WAVE # sampled_photon_energy * A2EV # col 12 (ray index) rays[:,11] = 1 + numpy.arange(NRAYS) # col 13 (optical path) rays[:,11] = 0.0 POL_ANGLE = 0.5 * numpy.pi if F_COHER == 1: PHASEX = 0.0 else: PHASEX = numpy.random.random(NRAYS) * 2 * numpy.pi PHASEZ = PHASEX + POL_ANGLE * numpy.sign(ANGLEV) rays[:,13] = PHASEX rays[:,14] = PHASEZ return rays