Skip to content

Commit

Permalink
Setting laser particle positions to be time-centered for implicit sol…
Browse files Browse the repository at this point in the history
…vers (#5485)

The current deposition schemes expect the particle positions to be
time-centered when using the implicit solvers. This is not currently the
case for the laser particles. This PR fixes this issue.

It should be commented that there is really no need for the current
deposition schemes to expect the particle positions to be time centered
for the implicit solvers. This is somewhat of a legacy thing from
PICNIC. This can and should be changed in a future PR.

Here are results of Ey generated from the analysis script for the 1D CI
test using the semi-implicit method:

![plt_Ey](https://github.com/user-attachments/assets/6c925872-66e0-4d7c-85ac-94800d49c71d)

Here are results of Ey generated from the analysis script for the 2D CI
test using the semi-implicit method:

![plt_Ey](https://github.com/user-attachments/assets/32813bba-1074-4beb-85f8-da9289436c32)

Here are results generated from the analysis script for the 3D CI test
using the semi-implicit method:

![laser_analysis](https://github.com/user-attachments/assets/0e3a8505-a039-4e79-99d1-496ff23cd498)
  • Loading branch information
JustinRayAngus authored Nov 25, 2024
1 parent a1a677e commit be77c76
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 8 deletions.
20 changes: 20 additions & 0 deletions Examples/Tests/laser_injection/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,23 @@ add_warpx_test(
diags/diag1000020 # output
OFF # dependency
)

add_warpx_test(
test_1d_laser_injection_implicit # name
1 # dims
2 # nprocs
inputs_test_1d_laser_injection_implicit # inputs
analysis_1d.py # analysis
diags/diag1000240 # output
OFF # dependency
)

add_warpx_test(
test_2d_laser_injection_implicit # name
2 # dims
2 # nprocs
inputs_test_2d_laser_injection_implicit # inputs
analysis_2d.py # analysis
diags/diag1000240 # output
OFF # dependency
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Maximum number of time steps
max_step = 240

# number of grid points
amr.n_cell = 352

# Maximum allowable size of each subdomain in the problem domain;
# this is used to decompose the domain for parallel calculations.
amr.max_grid_size = 32

# Maximum level in hierarchy (for now must be 0, i.e., one level in total)
amr.max_level = 0

# Geometry
geometry.dims = 1
geometry.prob_lo = -15.e-6 # physical domain
geometry.prob_hi = 15.e-6

boundary.field_lo = pec
boundary.field_hi = pec

warpx.serialize_initial_conditions = 1

# Verbosity
warpx.verbose = 1

# Algorithms
algo.current_deposition = esirkepov
warpx.use_filter = 0

# implicit evolve scheme
algo.evolve_scheme = "semi_implicit_em"
#
implicit_evolve.nonlinear_solver = "newton"
newton.verbose = true
newton.max_iterations = 21
newton.relative_tolerance = 1.0e-8
newton.require_convergence = true
#
gmres.verbose_int = 2
gmres.max_iterations = 1000
gmres.relative_tolerance = 1.0e-4

# CFL
warpx.cfl = 0.9

# Order of particle shape factors
algo.particle_shape = 1

# Laser
lasers.names = laser1
laser1.profile = Gaussian
laser1.position = 0.e-6 0.e-6 0.e-6 # This point is on the laser plane
laser1.direction = 0. 0. 1. # The plane normal direction
laser1.polarization = 1. 1. 0. # The main polarization vector
laser1.e_max = 4.e12 # Maximum amplitude of the laser field (in V/m)
laser1.wavelength = 1.0e-6 # The wavelength of the laser (in meters)
laser1.profile_waist = 5.e-6 # The waist of the laser (in meters)
laser1.profile_duration = 10.e-15 # The duration of the laser (in seconds)
laser1.profile_t_peak = 24.e-15 # The time at which the laser reaches its peak (in seconds)
laser1.profile_focal_distance = 13.109e-6 # Focal distance from the antenna (in meters)
# With this focal distance the laser is at focus
# at the end of the simulation.

# Diagnostics
diagnostics.diags_names = diag1 openpmd
diag1.intervals = 20
diag1.diag_type = Full

openpmd.intervals = 20
openpmd.diag_type = Full
openpmd.format = openpmd

# Moving window
warpx.do_moving_window = 1
warpx.moving_window_dir = z
warpx.moving_window_v = 1.0 # in units of the speed of light
warpx.start_moving_window_step = 20
warpx.end_moving_window_step = 200
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Maximum number of time steps
max_step = 240

# number of grid points
amr.n_cell = 480 352

# Maximum allowable size of each subdomain in the problem domain;
# this is used to decompose the domain for parallel calculations.
amr.max_grid_size = 32

# Maximum level in hierarchy (for now must be 0, i.e., one level in total)
amr.max_level = 0

# Geometry
geometry.dims = 2
geometry.prob_lo = -20.e-6 -15.e-6 # physical domain
geometry.prob_hi = 20.e-6 15.e-6

boundary.field_lo = pec periodic
boundary.field_hi = pec periodic

warpx.serialize_initial_conditions = 1

# Verbosity
warpx.verbose = 1

# Algorithms
algo.current_deposition = esirkepov
warpx.use_filter = 0

# implicit evolve scheme
algo.evolve_scheme = "semi_implicit_em"
#
implicit_evolve.nonlinear_solver = "newton"
newton.verbose = true
newton.max_iterations = 21
newton.relative_tolerance = 1.0e-8
newton.require_convergence = true
#
gmres.verbose_int = 2
gmres.max_iterations = 1000
gmres.relative_tolerance = 1.0e-4

# CFL
warpx.cfl = 1.0

# Order of particle shape factors
algo.particle_shape = 1

# Laser
lasers.names = laser1
laser1.profile = Gaussian
laser1.position = 10.e-6 0.e-6 0.e-6 # This point is on the laser plane
laser1.direction = 2. 0. 1. # The plane normal direction
laser1.polarization = 1. 1. -2. # The main polarization vector
laser1.e_max = 4.e12 # Maximum amplitude of the laser field (in V/m)
laser1.wavelength = 1.0e-6 # The wavelength of the laser (in meters)
laser1.profile_waist = 5.e-6 # The waist of the laser (in meters)
laser1.profile_duration = 10.e-15 # The duration of the laser (in seconds)
laser1.profile_t_peak = 24.e-15 # The time at which the laser reaches its peak (in seconds)
laser1.profile_focal_distance = 13.109e-6 # Focal distance from the antenna (in meters)
# With this focal distance the laser is at focus
# at the end of the simulation.

# Diagnostics
diagnostics.diags_names = diag1
diag1.intervals = 240
diag1.diag_type = Full

# Moving window
warpx.do_moving_window = 1
warpx.moving_window_dir = x
warpx.moving_window_v = 1.0 # in units of the speed of light
warpx.start_moving_window_step = 20
warpx.end_moving_window_step = 200
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"lev=0": {
"Bx": 374596.7817425552,
"By": 374596.7817425552,
"Bz": 0.0,
"Ex": 111502789524279.0,
"Ey": 111502789524279.0,
"Ez": 0.0,
"jx": 73098054407.2772,
"jy": 73098054407.2772,
"jz": 0.0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"lev=0": {
"Bx": 19699314.38858362,
"By": 101297372.8536657,
"Bz": 39796093.072294116,
"Ex": 1.3881256464656438e+16,
"Ey": 1.322100107139857e+16,
"Ez": 2.6833518029118908e+16,
"jx": 3.669364941403736e+16,
"jy": 3.669364586262695e+16,
"jz": 7.338729883115621e+16
}
}
24 changes: 16 additions & 8 deletions Source/Particles/LaserParticleContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,11 +917,13 @@ LaserParticleContainer::update_laser_particle (WarpXParIter& pti,
puyp[i] = gamma * vy;
puzp[i] = gamma * vz;

// Push the the particle positions
// Push the particle positions

// When using the implicit solver, this function is called multiple times per timestep
// (within the linear and nonlinear solver). Thus, the position of the particles needs to be reset
// to the initial position (at the beginning of the timestep), before updating the particle position
// to the initial position (at the beginning of the timestep), before updating the particle position.
// Also, the current deposition schemes expect the particle positions to be time centered
// (cur_time + 0.5*dt) for PushType::Implicit.

ParticleReal x=0., y=0., z=0.;
if (push_type == PushType::Explicit) {
Expand All @@ -930,20 +932,26 @@ LaserParticleContainer::update_laser_particle (WarpXParIter& pti,

#if !defined(WARPX_DIM_1D_Z)
if (push_type == PushType::Implicit) {
x = x_n[i];
x = x_n[i] + vx * dt*0.5_prt;
}
else {
x += vx * dt;
}
x += vx * dt;
#endif
#if defined(WARPX_DIM_3D) || defined(WARPX_DIM_RZ)
if (push_type == PushType::Implicit) {
y = y_n[i];
y = y_n[i] + vy * dt*0.5_prt;
}
else {
y += vy * dt;
}
y += vy * dt;
#endif
if (push_type == PushType::Implicit) {
z = z_n[i];
z = z_n[i] + vz * dt*0.5_prt;
}
else {
z += vz * dt;
}
z += vz * dt;

SetPosition(i, x, y, z);
}
Expand Down

0 comments on commit be77c76

Please sign in to comment.