-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples of the lasy beam propagation including resampling of the bea…
…m while focusing it; focused beam is also propagated in fbpic, both beams are compared
- Loading branch information
1 parent
8415735
commit d01b6cb
Showing
3 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import numpy as np | ||
from scipy.constants import c, e, m_e, m_p, k | ||
# Import the relevant structures from fbpic | ||
from fbpic.main import Simulation | ||
from fbpic.lpa_utils.laser import add_laser, add_laser_pulse | ||
from fbpic.lpa_utils.laser.laser_profiles import FlattenedGaussianLaser, GaussianLaser | ||
from fbpic.openpmd_diag import FieldDiagnostic, ParticleDiagnostic, \ | ||
set_periodic_checkpoint, restart_from_checkpoint, BoostedFieldDiagnostic, BoostedParticleDiagnostic | ||
from fbpic.lpa_utils.boosted_frame import BoostConverter | ||
from fbpic.lpa_utils.laser import add_laser_pulse, FromLasyFileLaser | ||
|
||
import os | ||
from mpi4py.MPI import COMM_WORLD as comm | ||
|
||
|
||
# Whether to use the GPU | ||
use_cuda = True | ||
|
||
# The simulation box | ||
Nz = 6000 #4000 #3200 # Number of gridpoints along z | ||
zmax = 0.e-6 # Right end of the simulation box (meters) | ||
#equal to the size of LASY box for the laser to be centered | ||
zmin = -2*90.e-15*c # Left end of the simulation box (meters) | ||
Nr = 500 #405 #270 # Number of gridpoints along r | ||
rmax = 200.e-6 # Length of the box along r (meters) | ||
Nm = 2 # Number of modes used | ||
# Boost factor | ||
gamma_boost = 5. | ||
# Maximum simulation length | ||
Lmax = 5.e-3 #LASY propagation distance of a pulse | ||
# The simulation timestep | ||
dt = min( rmax/(2*gamma_boost*Nr), (zmax-zmin)/Nz/c ) # Timestep (seconds) | ||
|
||
n_order = 16 | ||
|
||
boost = BoostConverter(gamma_boost) | ||
|
||
|
||
|
||
# The moving window | ||
v_window = c | ||
|
||
# Velocity of the Galilean frame (for suppression of the NCI) | ||
v_comoving = -np.sqrt(gamma_boost**2-1.)/gamma_boost * c | ||
|
||
# The diagnostics | ||
diag_period = 500 # Period of the diagnostics in number of timesteps | ||
|
||
# Whether to write the fields in the lab frame | ||
Ntot_snapshot_lab = 40 | ||
dt_snapshot_lab = (Lmax) / v_window / (Ntot_snapshot_lab - 1) | ||
|
||
track_bunch = False # Whether to tag and track the particles of the bunch | ||
|
||
# The interaction length of the simulation (meters) | ||
L_interact = Lmax # the plasma length | ||
# Interaction time (seconds) (to calculate number of PIC iterations) | ||
T_interact = boost.interaction_time( L_interact, (zmax-zmin), v_window ) | ||
# (i.e. the time it takes for the moving window to slide across the plasma) | ||
|
||
#take the first file | ||
PathToTheLasyFile = './DiagLASYforFBPIC/laser00000001_00001.h5' | ||
laser_profile = FromLasyFileLaser(PathToTheLasyFile) | ||
|
||
|
||
# --------------------------- | ||
# Carrying out the simulation | ||
# --------------------------- | ||
|
||
if __name__ == '__main__': | ||
|
||
# Initialize the simulation object | ||
sim = Simulation( Nz, zmax, Nr, rmax, Nm, dt, | ||
zmin=zmin, boundaries={'z':'open', 'r':'open'}, initialize_ions=False, | ||
n_order=n_order, use_cuda=use_cuda, v_comoving=v_comoving, | ||
gamma_boost=gamma_boost, verbose_level=2, particle_shape='cubic', | ||
use_galilean=True) | ||
# By default the simulation initializes an electron species (sim.ptcl[0]) | ||
# Because we did not pass the arguments `n`, `p_nz`, `p_nr`, `p_nz`, | ||
# this electron species does not contain any macroparticles. | ||
# It is okay to just remove it from the list of species. | ||
sim.ptcl = [] | ||
|
||
|
||
add_laser_pulse( sim, laser_profile, gamma_boost=gamma_boost, | ||
method='antenna', z0_antenna=0.e-6, v_antenna=0.) | ||
# Convert parameter to boosted frame | ||
v_window, = boost.velocity( [ v_window ] ) | ||
# Configure the moving window | ||
sim.set_moving_window( v=v_window ) | ||
|
||
# Add a diagnostics | ||
write_dir = 'DiagsFBPIC' | ||
sim.diags = [ | ||
BoostedFieldDiagnostic( zmin, zmax, c, | ||
dt_snapshot_lab, Ntot_snapshot_lab, gamma_boost, | ||
period=diag_period, fldobject=sim.fld, comm=sim.comm, | ||
fieldtypes=["E", "B", "rho"], write_dir=write_dir) | ||
] | ||
|
||
N_step = int(T_interact/sim.dt) | ||
### Run the simulation | ||
sim.step( N_step ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# Lasy Imports | ||
from lasy.profiles.gaussian_profile import GaussianProfile | ||
from lasy.laser import Laser, Grid | ||
from lasy.utils.zernike import zernike | ||
|
||
# OpenPMD Viewer (add-on for plasma acceleration) | ||
from openpmd_viewer.addons.pic import LpaDiagnostics | ||
|
||
# Standard Imports | ||
from scipy.constants import c | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
import copy | ||
import os, shutil | ||
|
||
|
||
def add_parabola(laser, f0): | ||
dt = laser.grid.dx[-1] | ||
omega0 = laser.profile.omega0 | ||
Nt = laser.grid.field.shape[-1] | ||
omega = 2 * np.pi * np.fft.fftfreq(Nt, dt) + omega0 | ||
|
||
#on-axis parabola | ||
|
||
r = laser.grid.axes[0] | ||
#transform the field from temporal to frequency domain | ||
field_fft = np.fft.ifft(laser.grid.field, axis=-1, norm="backward") | ||
|
||
#multiply spectral image by a parabolic mirror phase | ||
field_fft *= mirror_parabolic(f0, omega/c, r).T | ||
|
||
#rewrite laser field | ||
laser.grid.field[:, :, :] = np.fft.fft(field_fft, axis=-1, norm="backward" | ||
) | ||
|
||
def mirror_parabolic(f0, kz, r): | ||
""" | ||
Generate array with spectra-radial phase | ||
representing the on-axis Parabolic Mirror | ||
f0: focal length of a parabolic mirror | ||
kz = omega/c | ||
r: radial axis | ||
""" | ||
|
||
s_ax = r**2/4/f0 | ||
|
||
val = np.exp( -2j * s_ax[None,:] * \ | ||
( kz * np.ones((*kz.shape, *r.shape)).T ).T) | ||
return val | ||
|
||
|
||
#laser parameters | ||
|
||
#laser wavelength (m) | ||
wavelength = 800*1.e-9 | ||
#polarization vector | ||
pol = (1, 0) | ||
#laser energy (J) | ||
laser_energy = 1 | ||
#laser waist (m) | ||
w0 = 20.e-3 | ||
#pulse duration (s) | ||
tau = 30e-15 | ||
#maximum intensity time | ||
t_peak = 0 | ||
|
||
pulseProfile = GaussianProfile(wavelength, pol, laser_energy, w0, tau, t_peak, z_foc=0.e-3) | ||
|
||
# Create initial grid for the pulse | ||
Nr = 3000 | ||
R_max = 60.e-3 | ||
|
||
dim = "rt" | ||
lo = (0e-6, -90e-15) | ||
hi = (R_max, 90e-15) | ||
|
||
npoints = (Nr, 500) | ||
|
||
laser = Laser(dim=dim, lo=lo, hi=hi, npoints=npoints, profile=pulseProfile) | ||
|
||
#add sperical abberations | ||
R = np.linspace(0, R_max, Nr) | ||
#(n, m) = (2, 0) | ||
jthree = 4 | ||
#(n, m) = (5, 0) | ||
jfive = 12 | ||
|
||
pupilRadius = 4 * w0 | ||
pupilCoord = (0, 0, pupilRadius) | ||
|
||
third = zernike(0, R, pupilCoord, jthree) | ||
fifth = zernike(0, R, pupilCoord, jfive) | ||
|
||
coeff1 = -0.1 #defocus | ||
coeff2 = 0.9 #primary spherical | ||
|
||
phase = coeff1*third + coeff2*fifth | ||
|
||
phase2D = np.repeat(phase[:, np.newaxis], npoints[1], axis=1) | ||
laser.grid.field = laser.grid.field * np.exp(1j * phase2D) | ||
|
||
#propagate to OAP | ||
laser.propagate(40) | ||
|
||
#add parabolic mirror | ||
add_parabola(laser, 2000.e-3) | ||
|
||
#define a new grid for a focused beam | ||
new_grid = Grid(dim, lo, (200.e-6, 90e-15), npoints, n_azimuthal_modes=laser.grid.n_azimuthal_modes) | ||
laser.propagate((1995.e-3), grid=new_grid, nr_boundary = 128, backend = 'NP') #resample the grid | ||
|
||
laser_fbpic = copy.deepcopy(laser) | ||
|
||
#propagate laser by a box size to align LASY and FBPIC | ||
#laser pulse in FBPIC is emitted first and then propagated | ||
#in FBPIC laser is emitted by antenna and consequently it is fully iniallized after a full box size | ||
#initiallised laser should be at the same position as in LASY after propagation over one box | ||
!rm -rf './DiagLASYforFBPIC' | ||
path = './DiagLASYforFBPIC' | ||
os.mkdir(path) | ||
os.chdir(path) | ||
|
||
laser_fbpic.propagate(2*90e-15*c) | ||
file_format ='h5' | ||
filename = "laser%08d"%1 | ||
laser_fbpic.write_to_file(0, 1995.e-3 , filename, file_format) | ||
|
||
os.chdir('../') | ||
|
||
|
||
#propagating in a small grid to a focal point, step after step | ||
propDist = 1995.e-3 | ||
|
||
N = 40 | ||
prop_dz = (5.e-3)/(N-1) | ||
|
||
!rm -rf './DiagsLASY' | ||
path = './DiagsLASY' | ||
os.mkdir(path) | ||
os.chdir(path) | ||
|
||
|
||
file_format ='h5' | ||
filename = "laser%08d"%0 | ||
laser.write_to_file(0, propDist, filename, file_format) #writing propagation from 0 to 1995e-3 | ||
|
||
#write a file for separate iteration | ||
for j in range(N-1): | ||
laser.propagate(prop_dz) | ||
propDist += prop_dz | ||
|
||
i = j+1 | ||
file_format ='h5' | ||
filename = "laser%08d"%i | ||
currentit = i | ||
laser.write_to_file(currentit, propDist, filename, file_format) | ||
|
||
os.chdir('../') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#Analyse LASYvsFBPIC | ||
#compares propagation of two laser beams | ||
|
||
# OpenPmd (for reading information from file) | ||
from openpmd_viewer.addons.pic import LpaDiagnostics | ||
#from openpmd_viewer.addons import LpaDiagnostics # OpenPMD Viewer (add-on for plasma acceleration) | ||
|
||
# Standard Imports | ||
from scipy.constants import c | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
import copy | ||
import mpl_style | ||
mpl_style.load_preset() | ||
|
||
|
||
#FBPIC | ||
#data corresponding to FBPIC laser | ||
path_fbpic = './DiagsFBPICtwo/hdf5' | ||
data_fbpic = LpaDiagnostics(path_fbpic, check_all_files=True, backend="h5py") | ||
|
||
|
||
#all of the values correspond to the intensity | ||
num_iteration = 40 | ||
|
||
laser_fbpic, info_fbpic = data_fbpic.get_laser_envelope(iteration = 1 ,pol = 'x',slice_across='z', plot=False) | ||
|
||
#create an array containing propagation of the laser waist (intensity) | ||
array2d_fbpic = np.zeros((laser_fbpic.shape[0], num_iteration)) | ||
|
||
for iteration in range(num_iteration): | ||
laser_fbpic, info_fbpic = data_fbpic.get_laser_envelope(iteration = iteration ,pol = 'x', slice_across='z', plot=False) | ||
array2d_fbpic[:, iteration] = np.abs(laser_fbpic)**2 | ||
|
||
#plt.imshow(array2d_fbpic[:,:], extent=[1995, 2000, 0, 200], aspect='auto') | ||
#plt.xlabel('$z$ (mm)') | ||
#plt.ylabel('$r$ (µm)') | ||
#plt.colorbar() | ||
#plt.savefig('FBPIC.pdf') | ||
|
||
|
||
|
||
#LASY | ||
#data corresponding to the LASY laser | ||
path = './DiagLASY' | ||
data_lasy = LpaDiagnostics(path, check_all_files=True, backend="h5py") | ||
|
||
#lasy field has a shape of (6000, 40), to compare it with fbpic we need to reduce it to (1000, 40), manually pick #out appropriate entries for lasy (to avoid duplication of entries) | ||
def rewrite_lasy(laser_field, info_lasy, info_fbpic): | ||
array_half_size = info_lasy.r.size//2 #size of the lasy array | ||
divide_factor = info_lasy.r.size // info_fbpic.r.size #match sizes of lasy and fbpic | ||
|
||
r_second_half = info_lasy.r[array_half_size:][::divide_factor] | ||
r_first_half = info_lasy.r[::-1][array_half_size:][::divide_factor][::-1] | ||
r_new = np.concatenate([r_first_half,r_second_half]) | ||
|
||
field_second_half = laser_field[array_half_size:][::divide_factor] | ||
field_first_half = laser_field[::-1][array_half_size:][::divide_factor][::-1] | ||
field_new = np.concatenate([field_first_half,field_second_half]) | ||
return(field_new) | ||
|
||
|
||
#create a lasy field array of appropriate size | ||
lasy_iterations = [] | ||
for iteration in range(0, num_iteration): | ||
laser_fbpic, info_fbpic = data_fbpic.get_laser_envelope(iteration = iteration ,pol = 'x', slice_across='z', plot=False) | ||
laser_field,laser_field_info = data_lasy.get_field(iteration = iteration ,field='laserEnvelope', slice_across='t', plot=False) | ||
#write a separate laser field for each iteration | ||
laser_lasy = rewrite_lasy(laser_field, laser_field_info, info_fbpic) | ||
lasy_iterations.append(laser_lasy) | ||
|
||
#propagation of the LASY laser waist | ||
array2d_lasy = np.zeros((lasy_iterations[0].shape[0], num_iteration)) | ||
|
||
for iteration in range(num_iteration): | ||
array2d_lasy[:, iteration] = np.abs(np.array(lasy_iterations)[iteration, :])**2 | ||
|
||
#plt.imshow(array2d_lasy[:,:], extent=[1995, 2000, 0, 200]) | ||
#plt.xlabel('$z$ (mm)') | ||
#plt.ylabel('$r$ (µm)') | ||
#plt.colorbar() | ||
#plt.savefig('LASY.pdf') | ||
|
||
|
||
#LASY vs FBPIC | ||
#0 iteration is irrelevant since in fbpic the laser is getting emmited by antenna | ||
plt.imshow(array2d_lasy[:,1:] - array2d_fbpic[:,1:], extent=[1995.000128, 2000, 0, 200]) | ||
plt.colorbar() | ||
plt.xlabel('$z$ (mm)') | ||
plt.ylabel('$r$ (µm)') | ||
plt.title("LASY minus FBPIC") | ||
plt.savefig('LASYvsFBPIC.pdf') | ||
|
||
#slice comparison | ||
laser_fbpic, info_fbpic = data_fbpic.get_laser_envelope(iteration = 25 ,pol = 'x',slice_across='z', plot=False) | ||
plt.plot(np.abs(laser_fbpic)**2, 'b', label='fbpic') | ||
plt.plot(np.abs(np.array(lasy_iterations)[25,:])**2, 'y', label='lasy') | ||
plt.legend(loc='best') | ||
|
||
#max intensities at each iteration | ||
plt.plot(array2d_lasy[:, 1:].max(axis=0), 'y', label='lasy') | ||
plt.plot(array2d_fbpic[:,1:].max(axis=0), 'b', label='fbpic') | ||
plt.xlabel('$z$ (mm)') | ||
plt.ylabel('intensity') | ||
plt.legend(loc='best') | ||
#0.000128 mm to 5mm |