forked from ECP-WarpX/WarpX
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'development' of https://github.com/ECP-WarpX/WarpX into…
… HSdevmerge_240303
- Loading branch information
Showing
31 changed files
with
550 additions
and
98 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
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
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
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
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
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
41 changes: 41 additions & 0 deletions
41
Examples/Tests/embedded_boundary_diffraction/analysis_fields.py
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,41 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
This test checks the implementation of the embedded boundary in cylindrical geometry, | ||
by checking the diffraction of a laser by an embedded boundary here. | ||
We then check that the first minimum of the diffracted intensity pattern | ||
occurs along the angle given by the theoretical Airy pattern, i.e. | ||
theta_diffraction = 1.22 * lambda / d | ||
""" | ||
import os | ||
import sys | ||
|
||
import numpy as np | ||
from openpmd_viewer import OpenPMDTimeSeries | ||
from scipy.ndimage import gaussian_filter1d | ||
|
||
sys.path.insert(1, '../../../../warpx/Regression/Checksum/') | ||
import checksumAPI | ||
|
||
ts = OpenPMDTimeSeries('./EmbeddedBoundaryDiffraction_plt/') | ||
|
||
# Extract the intensity as a function of r and z | ||
Ex, info = ts.get_field('E', 'x', iteration=300) | ||
I = gaussian_filter1d(Ex**2, sigma=5, axis=0) # Extract intensity by averaging E^2 over wavelength | ||
irmax = np.argmax( I, axis=-1) | ||
|
||
# Find the radius of the first minimum, as a function of z | ||
def r_first_minimum(iz): | ||
ir = len(info.r)//2 | ||
while I[iz, ir+1] < I[iz, ir]: | ||
ir += 1 | ||
return info.r[ir] | ||
r = np.array([ r_first_minimum(iz) for iz in range(len(info.z)) ]) | ||
|
||
# Check that this corresponds to the prediction from the Airy pattern | ||
theta_diffraction = np.arcsin(1.22*0.1/0.4)/2 | ||
assert np.all( abs(r[50:] - theta_diffraction*info.z[50:]) < 0.03 ) | ||
|
||
# Open the right plot file | ||
filename = sys.argv[1] | ||
test_name = os.path.split(os.getcwd())[1] | ||
checksumAPI.evaluate_checksum(test_name, filename, output_format='openpmd') |
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,42 @@ | ||
# This script tests the diffraction of a laser by | ||
# a cylindrical object, represented by an embedded boundary here | ||
|
||
max_step = 300 | ||
amr.n_cell = 128 256 | ||
amr.max_grid_size = 256 | ||
amr.max_level = 0 | ||
|
||
geometry.dims = RZ | ||
geometry.prob_lo = 0. -0.2 | ||
geometry.prob_hi = 2 1.4 | ||
warpx.cfl = 0.99 | ||
algo.particle_shape = 1 | ||
|
||
boundary.field_lo = none absorbing_silver_mueller | ||
boundary.field_hi = pec absorbing_silver_mueller | ||
|
||
# Make the cylindrical object that the laser will diffract on | ||
my_constants.aperture_l = 0.01 | ||
my_constants.aperture_r = 0.2 | ||
warpx.eb_implicit_function = "if( (abs(z)<0.5*aperture_l) and (x<aperture_r), 1, -1 )" | ||
|
||
warpx.n_rz_azimuthal_modes = 2 | ||
|
||
# Laser | ||
lasers.names = laser1 | ||
laser1.profile = Gaussian | ||
laser1.position = 0. 0. -0.1 | ||
laser1.direction = 0. 0. 1. | ||
laser1.polarization = 1. 0. 0. | ||
laser1.profile_waist = 1. | ||
laser1.profile_duration = 100 | ||
laser1.profile_t_peak = 0 | ||
laser1.profile_focal_distance = 0 | ||
laser1.e_max = 1. | ||
laser1.wavelength = 0.1 | ||
|
||
diagnostics.diags_names = diag1 | ||
diag1.intervals = 100 | ||
diag1.diag_type = Full | ||
diag1.fields_to_plot = Er Et Ez Br Bt Bz | ||
diag1.format = openpmd |
169 changes: 169 additions & 0 deletions
169
Examples/Tests/particle_boundary_interaction/PICMI_inputs_rz.py
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,169 @@ | ||
#!/usr/bin/env python3 | ||
# @Eya Dammak supervised by @Remi Lehe, 2024 | ||
# --- Input file for particle-boundary interaction testing in RZ. | ||
# --- This input is a simple case of reflection | ||
# --- of one electron on the surface of a sphere. | ||
import numpy as np | ||
|
||
from pywarpx import callbacks, particle_containers, picmi | ||
|
||
########################## | ||
# numerics parameters | ||
########################## | ||
|
||
dt = 1.0e-11 | ||
|
||
# --- Nb time steps | ||
|
||
max_steps = 23 | ||
diagnostic_interval = 1 | ||
|
||
# --- grid | ||
|
||
nr = 64 | ||
nz= 64 | ||
|
||
rmin = 0.0 | ||
rmax = 2 | ||
zmin = -2 | ||
zmax = 2 | ||
|
||
########################## | ||
# numerics components | ||
########################## | ||
|
||
grid = picmi.CylindricalGrid( | ||
number_of_cells = [nr, nz], | ||
n_azimuthal_modes = 1, | ||
lower_bound = [rmin, zmin], | ||
upper_bound = [rmax, zmax], | ||
lower_boundary_conditions = ['none', 'dirichlet'], | ||
upper_boundary_conditions = ['dirichlet', 'dirichlet'], | ||
lower_boundary_conditions_particles = ['absorbing', 'reflecting'], | ||
upper_boundary_conditions_particles = ['absorbing', 'reflecting'] | ||
) | ||
|
||
|
||
solver = picmi.ElectrostaticSolver( | ||
grid=grid, method='Multigrid', | ||
warpx_absolute_tolerance=1e-7 | ||
) | ||
|
||
embedded_boundary = picmi.EmbeddedBoundary( | ||
implicit_function="-(x**2+y**2+z**2-radius**2)", | ||
radius = 0.2 | ||
) | ||
|
||
########################## | ||
# physics components | ||
########################## | ||
|
||
#one particle | ||
e_dist=picmi.ParticleListDistribution(x=0.0, y=0.0, z=-0.25, ux=0.5e10, uy=0.0, uz=1.0e10, weight=1) | ||
|
||
electrons = picmi.Species( | ||
particle_type='electron', name='electrons', initial_distribution=e_dist, warpx_save_particles_at_eb=1 | ||
) | ||
|
||
########################## | ||
# diagnostics | ||
########################## | ||
|
||
field_diag = picmi.FieldDiagnostic( | ||
name = 'diag1', | ||
grid = grid, | ||
period = diagnostic_interval, | ||
data_list = ['Er', 'Ez', 'phi', 'rho','rho_electrons'], | ||
warpx_format = 'openpmd', | ||
write_dir = '.', | ||
warpx_file_prefix = 'particle_boundary_interaction_plt' | ||
) | ||
|
||
part_diag = picmi.ParticleDiagnostic(name = 'diag1', | ||
period = diagnostic_interval, | ||
species = [electrons], | ||
warpx_format = 'openpmd', | ||
write_dir = '.', | ||
warpx_file_prefix = 'particle_boundary_interaction_plt' | ||
) | ||
|
||
########################## | ||
# simulation setup | ||
########################## | ||
|
||
sim = picmi.Simulation( | ||
solver=solver, | ||
time_step_size = dt, | ||
max_steps = max_steps, | ||
warpx_embedded_boundary=embedded_boundary, | ||
warpx_amrex_the_arena_is_managed=1, | ||
) | ||
|
||
sim.add_species( | ||
electrons, | ||
layout = picmi.GriddedLayout( | ||
n_macroparticle_per_cell=[10, 1, 1], grid=grid | ||
) | ||
) | ||
sim.add_diagnostic(part_diag) | ||
sim.add_diagnostic(field_diag) | ||
|
||
sim.initialize_inputs() | ||
sim.initialize_warpx() | ||
|
||
########################## | ||
# python particle data access | ||
########################## | ||
|
||
def concat( list_of_arrays ): | ||
if len(list_of_arrays) == 0: | ||
# Return a 1d array of size 0 | ||
return np.empty(0) | ||
else: | ||
return np.concatenate( list_of_arrays ) | ||
|
||
|
||
def mirror_reflection(): | ||
buffer = particle_containers.ParticleBoundaryBufferWrapper() #boundary buffer | ||
|
||
#STEP 1: extract the different parameters of the boundary buffer (normal, time, position) | ||
lev = 0 # level 0 (no mesh refinement here) | ||
delta_t = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'deltaTimeScraped', lev)) | ||
r = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'x', lev)) | ||
theta = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'theta', lev)) | ||
z = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'z', lev)) | ||
x= r*np.cos(theta) #from RZ coordinates to 3D coordinates | ||
y= r*np.sin(theta) | ||
ux = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'ux', lev)) | ||
uy = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'uy', lev)) | ||
uz = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'uz', lev)) | ||
w = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'w', lev)) | ||
nx = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'nx', lev)) | ||
ny = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'ny', lev)) | ||
nz = concat(buffer.get_particle_boundary_buffer("electrons", 'eb', 'nz', lev)) | ||
|
||
#STEP 2: use these parameters to inject particle from the same position in the plasma | ||
elect_pc = particle_containers.ParticleContainerWrapper('electrons') #general particle container | ||
|
||
####this part is specific to the case of simple reflection. | ||
un=ux*nx+uy*ny+uz*nz | ||
ux_reflect=-2*un*nx+ux #for a "mirror reflection" u(sym)=-2(u.n)n+u | ||
uy_reflect=-2*un*ny+uy | ||
uz_reflect=-2*un*nz+uz | ||
elect_pc.add_particles( | ||
x=x + (dt-delta_t)*ux_reflect, y=y + (dt-delta_t)*uy_reflect, z=z + (dt-delta_t)*uz_reflect, | ||
ux=ux_reflect, uy=uy_reflect, uz=uz_reflect, | ||
w=w | ||
) #adds the particle in the general particle container at the next step | ||
#### Can be modified depending on the model of interaction. | ||
|
||
buffer.clear_buffer() #reinitialise the boundary buffer | ||
|
||
callbacks.installafterstep(mirror_reflection) #mirror_reflection is called at the next step | ||
# using the new particle container modified at the last step | ||
|
||
########################## | ||
# simulation run | ||
########################## | ||
|
||
sim.step(max_steps) #the whole process is done "max_steps" times |
Oops, something went wrong.