Skip to content

Commit d5ea2c0

Browse files
authored
Cut gaussian beam (#868)
* add option to cut gaussian * cut gaussian distrubution at injection * add test for cut gaussian beam * increase tolerance * doc: mention that cutting the gaussian results in a lower total charge * more explicit * beware the const-able
1 parent 6768fae commit d5ea2c0

File tree

7 files changed

+56
-21
lines changed

7 files changed

+56
-21
lines changed

Docs/source/running_cpp/parameters.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ Particle initialization
276276
``<species_name>.npart`` (number of particles in the beam),
277277
``<species_name>.x/y/z_m`` (average position in `x/y/z`),
278278
``<species_name>.x/y/z_rms`` (standard deviation in `x/y/z`),
279+
``<species_name>.x/y/z_rms`` (standard deviation in `x/y/z`),
280+
``<species_name>.x/y/z_cut`` (optional, particles with ``abs(x-x_m) > x_cut*x_rms`` are not injected, same for y and z. ``<species_name>.q_tot`` is the charge of the un-cut beam, so that cutting the distribution is likely to result in a lower total charge),
279281
and optional argument ``<species_name>.do_symmetrize`` (whether to
280282
symmetrize the beam in the x and y directions).
281283

Examples/Tests/initial_distribution/analysis_distribution.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from read_raw_data import read_reduced_diags_histogram
2020

2121
# print tolerance
22-
tolerance = 0.007
22+
tolerance = 0.01
2323
print('Tolerance:', tolerance)
2424

2525
#===============================
@@ -96,17 +96,34 @@
9696

9797
# parameters of theory
9898
x_rms = 0.25
99+
z_cut = 2.
99100
q_tot = -1.0e-20
100101
q_e = -1.602176634e-19
101102
npart = q_tot/q_e
102-
db = 0.04
103+
db = bin_value[1]-bin_value[0]
103104

104105
# compute the analytical solution
105-
f = npart*db * np.exp(-0.5*(bin_value/x_rms)**2)/(x_rms*np.sqrt(2.0*scc.pi))
106-
f_peak = np.amax(f)
106+
f_xy = npart*db * np.exp(-0.5*(bin_value/x_rms)**2)/(x_rms*np.sqrt(2.0*scc.pi)) * scs.erf(z_cut/np.sqrt(2.))
107+
f_z = npart*db * np.exp(-0.5*(bin_value/x_rms)**2)/(x_rms*np.sqrt(2.0*scc.pi))
108+
f_z[ np.absolute(bin_value) > z_cut * x_rms ] = 0.
109+
f_peak = np.amax(f_z)
107110

108111
# compute error
109-
f4_error = np.sum(np.abs(f-h4x)+np.abs(f-h4y)+np.abs(f-h4z))/bin_value.size / f_peak
112+
f4_error = np.sum(np.abs(f_xy-h4x)+np.abs(f_xy-h4y)+np.abs(f_z-h4z))/bin_value.size / f_peak
113+
114+
do_plot = False
115+
if do_plot:
116+
import matplotlib.pyplot as plt
117+
plt.figure()
118+
plt.subplot(121)
119+
plt.plot(bin_value, f_xy, '+-', label='ref')
120+
plt.plot(bin_value, h4x, '+--', label='sim')
121+
plt.legend()
122+
plt.subplot(122)
123+
plt.plot(bin_value, f_z, '+-', label='ref')
124+
plt.plot(bin_value, h4z, '+--', label='sim')
125+
plt.legend()
126+
plt.savefig('toto.pdf', bbox_inches='tight')
110127

111128
print('Gaussian position distribution difference:', f4_error)
112129

Examples/Tests/initial_distribution/inputs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ beam.injection_style = "gaussian_beam"
6060
beam.x_rms = 0.25
6161
beam.y_rms = 0.25
6262
beam.z_rms = 0.25
63+
beam.z_cut = 2.
6364
beam.x_m = 0.0
6465
beam.y_m = 0.0
6566
beam.z_m = 0.0

Source/Initialization/PlasmaInjector.H

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ public:
6464
amrex::Real x_rms;
6565
amrex::Real y_rms;
6666
amrex::Real z_rms;
67+
amrex::Real x_cut = std::numeric_limits<amrex::Real>::max();
68+
amrex::Real y_cut = std::numeric_limits<amrex::Real>::max();
69+
amrex::Real z_cut = std::numeric_limits<amrex::Real>::max();
6770
amrex::Real q_tot;
6871
long npart;
6972
int do_symmetrize = 0;

Source/Initialization/PlasmaInjector.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ PlasmaInjector::PlasmaInjector (int ispecies, const std::string& name)
176176
pp.get("x_rms", x_rms);
177177
pp.get("y_rms", y_rms);
178178
pp.get("z_rms", z_rms);
179+
pp.query("x_cut", x_cut);
180+
pp.query("y_cut", y_cut);
181+
pp.query("z_cut", z_cut);
179182
pp.get("q_tot", q_tot);
180183
pp.get("npart", npart);
181184
pp.query("do_symmetrize", do_symmetrize);

Source/Particles/PhysicalParticleContainer.H

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,10 @@ public:
199199

200200
void MapParticletoBoostedFrame(amrex::Real& x, amrex::Real& y, amrex::Real& z, std::array<amrex::Real, 3>& u);
201201

202-
void AddGaussianBeam(amrex::Real x_m, amrex::Real y_m, amrex::Real z_m,
203-
amrex::Real x_rms, amrex::Real y_rms, amrex::Real z_rms,
204-
amrex::Real q_tot, long npart, int do_symmetrize);
202+
void AddGaussianBeam(const amrex::Real x_m, const amrex::Real y_m, const amrex::Real z_m,
203+
const amrex::Real x_rms, const amrex::Real y_rms, const amrex::Real z_rms,
204+
const amrex::Real x_cut, const amrex::Real y_cut, const amrex::Real z_cut,
205+
const amrex::Real q_tot, long npart, const int do_symmetrize);
205206

206207
/** Load a particle beam from an external file
207208
*

Source/Particles/PhysicalParticleContainer.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,12 @@ void PhysicalParticleContainer::MapParticletoBoostedFrame(Real& x, Real& y, Real
228228
}
229229

230230
void
231-
PhysicalParticleContainer::AddGaussianBeam(Real x_m, Real y_m, Real z_m,
232-
Real x_rms, Real y_rms, Real z_rms,
233-
Real q_tot, long npart,
234-
int do_symmetrize) {
231+
PhysicalParticleContainer::AddGaussianBeam (
232+
const Real x_m, const Real y_m, const Real z_m,
233+
const Real x_rms, const Real y_rms, const Real z_rms,
234+
const Real x_cut, const Real y_cut, const Real z_cut,
235+
const Real q_tot, long npart,
236+
const int do_symmetrize) {
235237

236238
std::mt19937_64 mt(0451);
237239
std::normal_distribution<double> distx(x_m, x_rms);
@@ -256,17 +258,20 @@ PhysicalParticleContainer::AddGaussianBeam(Real x_m, Real y_m, Real z_m,
256258
}
257259
for (long i = 0; i < npart; ++i) {
258260
#if (defined WARPX_DIM_3D) || (WARPX_DIM_RZ)
259-
Real weight = q_tot/npart/charge;
260-
Real x = distx(mt);
261-
Real y = disty(mt);
262-
Real z = distz(mt);
261+
const Real weight = q_tot/(npart*charge);
262+
const Real x = distx(mt);
263+
const Real y = disty(mt);
264+
const Real z = distz(mt);
263265
#elif (defined WARPX_DIM_XZ)
264-
Real weight = q_tot/npart/charge/y_rms;
265-
Real x = distx(mt);
266-
Real y = 0.;
267-
Real z = distz(mt);
266+
const Real weight = q_tot/(npart*charge*y_rms);
267+
const Real x = distx(mt);
268+
constexpr Real y = 0.;
269+
const Real z = distz(mt);
268270
#endif
269-
if (plasma_injector->insideBounds(x, y, z)) {
271+
if (plasma_injector->insideBounds(x, y, z) &&
272+
std::abs( x - x_m ) < x_cut * x_rms &&
273+
std::abs( y - y_m ) < y_cut * y_rms &&
274+
std::abs( z - z_m ) < z_cut * z_rms ) {
270275
XDim3 u = plasma_injector->getMomentum(x, y, z);
271276
u.x *= PhysConst::c;
272277
u.y *= PhysConst::c;
@@ -388,6 +393,9 @@ PhysicalParticleContainer::AddParticles (int lev)
388393
plasma_injector->x_rms,
389394
plasma_injector->y_rms,
390395
plasma_injector->z_rms,
396+
plasma_injector->x_cut,
397+
plasma_injector->y_cut,
398+
plasma_injector->z_cut,
391399
plasma_injector->q_tot,
392400
plasma_injector->npart,
393401
plasma_injector->do_symmetrize);

0 commit comments

Comments
 (0)