Skip to content

Commit 7cdcbef

Browse files
committed
WIP: electron impact ionization
1 parent 3504971 commit 7cdcbef

8 files changed

Lines changed: 69 additions & 65 deletions

File tree

docs/source/run/parameters.rst

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,20 +500,23 @@ When both are specified, the per-species value is used.
500500
the specific ionization energy of each state.
501501
Options are: ``electron``, ``positron``, ``H``, ``D``, ``T``, ``He``, ``Li``, ``Be``, ``B``, ….
502502

503-
* ``<plasma name>.can_ionize`` (`bool`) optional (default `0`)
504-
Whether this plasma can ionize. Can also be set to 1 by specifying ``<plasma name>.ionization_product``.
503+
* ``<plasma name>.can_field_ionize`` (`bool`) optional (default `0`)
504+
Whether this plasma can be ionized by fields, as for example from a driving particle beam.
505505

506-
* ``<plasma name>.can_laser_ionize`` (`bool`) optional (default `<plasma name>.can_ionize`)
506+
* ``<plasma name>.can_laser_ionize`` (`bool`) optional (default `0`)
507507
Whether this plasma can be ionized by a laser.
508508

509+
* ``<plasma name>.can_impact_ionize`` (`bool`) optional (default `0`)
510+
Whether this plasma can be ionized by impact ionization between plasma particles.
511+
509512
* ``<plasma name>.initial_ion_level`` (`int`) optional (default `-1`)
510513
The initial ionization state of the plasma. `0` for neutral gasses.
511514
If set, the plasma charge gets multiplied by this number. If the plasma species is not ionizable,
512515
the initial ionization level is set to 1.
513516

514517
* ``<plasma name>.ionization_product`` (`string`) optional (default "")
515518
Name of the plasma species that contains the new electrons that are produced
516-
when this plasma gets ionized. Only needed if this plasma is ionizable.
519+
when this plasma gets field or laser ionized. Only needed if this plasma is ionizable.
517520

518521
* ``<plasma name> or plasmas.neutralize_background`` (`bool`) optional (default `1`)
519522
Whether to add a neutralizing background of immobile particles of opposite charge.
@@ -1307,9 +1310,10 @@ WARNING: this module is in development.
13071310
HiPACE++ proposes an implementation of [Perez et al., Phys. Plasmas 19, 083104 (2012)], inherited from WarpX,
13081311
for collisions between plasma-plasma and beam-plasma.
13091312
As collisions depend on the physical density, in normalized units `hipace.background_density_SI` must be specified.
1313+
Please note that the impact ionization module is currently under development, and SI units are always required.
13101314

13111315
* ``hipace.collisions`` (list of `strings`) optional
1312-
List of names of binary Coulomb collisions.
1316+
List of names of binary elastic Coulomb collisions.
13131317
Each will represent collisions between 2 species.
13141318

13151319
* ``<collision name>.species`` (two `strings`) optional
@@ -1321,6 +1325,32 @@ As collisions depend on the physical density, in normalized units `hipace.backgr
13211325
Coulomb logarithm used for this collision.
13221326
If not specified, the Coulomb logarithm is determined from the temperature in each cell.
13231327

1328+
* ``hipace.impact_ionization`` (list of `strings`) optional
1329+
List of names of binary inelastic Coulomb collisions.
1330+
Each will represent collisions between 2 plasma species.
1331+
Three species must be specified: the projectile, the target (ion or neutral atom), and the product (electron).
1332+
Currently only impact ionization between electrons and another species, which might be ions or neutral atoms, is implemented.
1333+
Please note that the impact ionization module is currently under development, and SI units are always required.
1334+
1335+
* ``<impact_name>.type`` (string) optional
1336+
Type of impact ionization. Currently, only `electron_impact` is implemented.
1337+
1338+
* ``<impact name>.projectile`` (string) optional
1339+
The name of the projectile species for impact ionization.
1340+
The species must be defined according to `Plasma parameters`.
1341+
1342+
* ``<impact name>.target`` (string) optional
1343+
The name of the target species for impact ionization.
1344+
The species must be defined according to `Plasma parameters`.
1345+
1346+
* ``<impact name>.new_electron`` (string) optional
1347+
The name of the product species for impact ionization.
1348+
The species must be defined according to `Plasma parameters` and should be an electron species.
1349+
In electron impacts, initial and newly created electrons can be treated as on single species
1350+
simply by using the same name for the projectile and the new electrons.
1351+
However, to treat the new electrons as a separate species, a different name can be used.
1352+
In that case, the new electrons won't be contributing to further ionizations.
1353+
13241354
Radiation reaction
13251355
^^^^^^^^^^^^^^^^^^
13261356

src/Hipace.H

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,9 @@ private:
364364
std::vector<std::string> m_collision_names;
365365
/** Vector of binary collisions */
366366
amrex::Vector< CoulombCollision > m_all_collisions;
367-
amrex::Vector<std::string> m_collision_names2;
368-
amrex::Vector<Collision> m_all_collisions2;
367+
/** Impact ionization */
368+
amrex::Vector<std::string> m_impact_names;
369+
amrex::Vector<Collision> m_all_impacts;
369370

370371
void InitDiagnostics (const int step, const amrex::Real time, const bool is_last_step);
371372
void FillFieldDiagnostics (const int current_N_level, int islice);

src/Hipace.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,10 @@ Hipace::ReadParameters ()
261261
"be specified via 'hipace.background_density_SI'");
262262
}
263263

264-
queryWithParser(pph, "collisions2", m_collision_names2);
265-
for (int i = 0; i != m_collision_names2.size(); ++i) {
266-
m_all_collisions2.emplace_back(Collision());
267-
m_all_collisions2.back().ReadParameters(m_multi_plasma.m_names, m_collision_names2[i]);
264+
queryWithParser(pph, "impact_ionization", m_impact_names);
265+
for (int i = 0; i != m_impact_names.size(); ++i) {
266+
m_all_impacts.emplace_back(Collision());
267+
m_all_impacts.back().ReadParameters(m_multi_plasma.m_names, m_impact_names[i]);
268268
}
269269

270270
// external fields applied to the grid
@@ -850,8 +850,8 @@ Hipace::SolveOneSlice (int islice, int step, bool is_first_step, bool is_last_st
850850
// collisions for plasmas and beams
851851
doCoulombCollision();
852852

853-
for (auto& collision : m_all_collisions2) {
854-
collision.doCollision(0, m_slice_geom[0], m_multi_plasma);
853+
for (auto& impact : m_all_impacts) {
854+
impact.doCollision(0, m_slice_geom[0], m_multi_plasma);
855855
}
856856

857857
// get minimum beam uz after push

src/particles/collisions/Collision.H

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
*/
1414
class Collision
1515
{
16-
std::string m_inout_species1_name = "";
17-
std::string m_inout_species2_name = "";
18-
std::string m_out_species3_name = "";
16+
std::string m_projectile_name = "";
17+
std::string m_target_name = "";
18+
std::string m_new_electron_name = "";
1919
std::string m_collision_type = "";
2020
std::string m_physical_element ="";
2121
bool m_has_collision_product = false;

src/particles/collisions/Collision.cpp

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ Collision::ReadParameters(
6868
// The user is asked to always input the target type as the second specie
6969
m_has_collision_product = m_collision_type == "electron_impact" || m_collision_type == "ion_impact";
7070

71-
getWithParser(pp, "species1", m_inout_species1_name);
72-
getWithParser(pp, "species2", m_inout_species2_name);
71+
getWithParser(pp, "projectile", m_projectile_name);
72+
getWithParser(pp, "target", m_target_name);
7373

7474
if (m_has_collision_product) {
75-
getWithParser(pp, "species3", m_out_species3_name);
75+
getWithParser(pp, "new_electron", m_new_electron_name);
7676
}
7777

7878
if (m_collision_type == "electron_impact") {
@@ -90,7 +90,7 @@ Collision::ReadParameters(
9090

9191
}
9292
// Plasma physical element name
93-
amrex::ParmParse pp_s2(m_inout_species2_name);
93+
amrex::ParmParse pp_s2(m_target_name);
9494
getWithParser(pp_s2, "element", m_physical_element);
9595
}
9696

@@ -120,9 +120,9 @@ Collision::doCollisionA (
120120
const amrex::Real* p_binding_energies = m_binding_energies.data();
121121
const amrex::Real* p_ionization_energies = m_ionization_energies.data();
122122

123-
auto& species1 = multi_plasma.GetPlasma(m_inout_species1_name);
124-
auto& species2 = multi_plasma.GetPlasma(m_inout_species2_name);
125-
auto& species3 = multi_plasma.GetPlasma(m_out_species3_name);
123+
auto& species1 = multi_plasma.GetPlasma(m_projectile_name);
124+
auto& species2 = multi_plasma.GetPlasma(m_target_name);
125+
auto& species3 = multi_plasma.GetPlasma(m_new_electron_name);
126126

127127
auto m1 = species1.GetMass();
128128
auto m2 = species2.GetMass();
@@ -134,7 +134,7 @@ Collision::doCollisionA (
134134
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
135135
ion_atomic_number == 1 ||
136136
ion_atomic_number == 18,
137-
"The current implementation of electron-impact ionization only supports Hydrogen and Argon. Please check the input file and the physical element specified for species2."
137+
"The current implementation of electron-impact ionization only supports Hydrogen and Argon. Please check the input file and the physical element specified for target."
138138
);
139139

140140
const amrex::Real inv_dV = geom.InvCellSize(0)*geom.InvCellSize(1)*geom.InvCellSize(2);
@@ -374,8 +374,8 @@ Collision::doCollisionImp (
374374
G const& ionization_function)
375375
{
376376
// assume the two species are different for now
377-
auto& species1 = multi_plasma.GetPlasma(m_inout_species1_name);
378-
auto& species2 = multi_plasma.GetPlasma(m_inout_species2_name);
377+
auto& species1 = multi_plasma.GetPlasma(m_projectile_name);
378+
auto& species2 = multi_plasma.GetPlasma(m_target_name);
379379

380380
for (PlasmaParticleIterator pti(species1); pti.isValid(); ++pti) {
381381
amrex::removeInvalidParticles(species1.ParticlesAt(0, pti));
@@ -442,34 +442,6 @@ Collision::doCollisionImp (
442442
auto p_flag1 = flag1.dataPtr();
443443
auto p_flag2 = flag2.dataPtr();
444444

445-
amrex::Gpu::DeviceVector<amrex::Real> cell_weight1(num_cells);
446-
amrex::Gpu::DeviceVector<amrex::Real> cell_weight2(num_cells);
447-
auto p_cell_weight1 = cell_weight1.dataPtr();
448-
auto p_cell_weight2 = cell_weight2.dataPtr();
449-
450-
amrex::ParallelFor(2*num_cells,
451-
[=] AMREX_GPU_DEVICE (int icell) {
452-
if (icell < num_cells) {
453-
auto start = offset1[icell];
454-
auto stop = offset1[icell+1];
455-
amrex::Real loc_cell_weight1 = 0;
456-
for (int idx1 = start; idx1 < stop; ++idx1) {
457-
loc_cell_weight1 += ptd1.rdata(PlasmaIdx::w)[perm1[idx1]];
458-
}
459-
p_cell_weight1[icell] = loc_cell_weight1;
460-
} else {
461-
icell -= num_cells;
462-
auto start = offset2[icell];
463-
auto stop = offset2[icell+1];
464-
amrex::Real loc_cell_weight2 = 0;
465-
for (int idx2 = start; idx2 < stop; ++idx2) {
466-
loc_cell_weight2 += ptd2.rdata(PlasmaIdx::w)[perm2[idx2]];
467-
}
468-
p_cell_weight2[icell] = loc_cell_weight2;
469-
}
470-
}
471-
);
472-
473445
// loop over independent pairs
474446
amrex::ParallelForRNG(total_ind_pairs,
475447
[=] AMREX_GPU_DEVICE (int ipair, amrex::RandomEngine const& engine){
@@ -485,9 +457,6 @@ Collision::doCollisionImp (
485457
const int N1 = offset1_stop - offset1_start;
486458
const int N2 = offset2_stop - offset2_start;
487459

488-
//const amrex::Real loc_cell_weight1 = p_cell_weight1[icell];
489-
//const amrex::Real loc_cell_weight2 = p_cell_weight2[icell];
490-
491460
int idx1 = icoll;
492461
int idx2 = icoll;
493462
while (idx1 < N1 && idx2 < N2) {
@@ -554,12 +523,12 @@ Collision::doCollisionImp (
554523
amrex::Scan::Type::exclusive, amrex::Scan::retSum
555524
);
556525

557-
auto& species3 = multi_plasma.GetPlasma(m_out_species3_name);
526+
auto& species3 = multi_plasma.GetPlasma(m_new_electron_name);
558527
auto& ptile3 = species3.ParticlesAt(0, pti);
559528
int old_size3 = ptile3.size();
560529
ptile3.resize(old_size3 + num_new_particles);
561530

562-
// get new ptd after resize in case species3 is the same as species1 or 2
531+
// get new ptd after resize in case species3 is the same as species1 or species2
563532
ptd1 = ptile1.getParticleTileData();
564533
ptd2 = ptile2.getParticleTileData();
565534
auto ptd3 = ptile3.getParticleTileData();

src/particles/plasma/MultiPlasma.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void
5454
MultiPlasma::InitIonization (amrex::Vector<amrex::Geometry> gm)
5555
{
5656
for (auto& plasma : m_all_plasmas) {
57-
if(plasma.m_can_ionize) {
57+
if(plasma.m_can_field_ionize || plasma.m_can_laser_ionize) {
5858
for (int i=0; i<m_names.size(); ++i) {
5959
if(m_names[i] == plasma.m_product_name) {
6060
plasma.m_product_pc = &m_all_plasmas[i];

src/particles/plasma/PlasmaParticleContainer.H

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ public:
279279
bool m_can_ionize = false; /**< whether this plasma can ionize from anything */
280280
bool m_can_field_ionize = false; /**< whether this plasma can ionize from the field */
281281
bool m_can_laser_ionize = false; /**< whether this plasma can ionize from a laser */
282+
bool m_can_impact_ionize = false; /**< whether this plasma can ionize from particle impact */
282283
int m_init_ion_lev = -1; /**< initial Ion level of each particle */
283284
int m_max_ion_lev = 0; /**< maximum ionization level */
284285
std::string m_product_name = ""; /**< name of Ionization product plasma */

src/particles/plasma/PlasmaParticleContainer.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,17 @@ PlasmaParticleContainer::ReadParameters ()
6565
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_mass != 0, "The plasma particle mass must be specified");
6666

6767
bool ion_lev_specified = queryWithParser(pp, "initial_ion_level", m_init_ion_lev);
68-
// m_can_field_ionize = pp.contains("ionization_product");
6968

70-
// queryWithParser(pp, "can_ionize", m_can_field_ionize);
71-
queryWithParser(pp, "can_ionize", m_can_ionize);
72-
m_can_laser_ionize = false;
69+
queryWithParser(pp, "can_field_ionize", m_can_field_ionize);
7370
queryWithParser(pp, "can_laser_ionize", m_can_laser_ionize);
71+
queryWithParser(pp, "can_impact_ionize", m_can_impact_ionize);
7472

75-
// m_can_ionize = m_can_field_ionize || m_can_laser_ionize; // !!!
73+
m_can_ionize = m_can_field_ionize || m_can_laser_ionize || m_can_impact_ionize;
74+
75+
DeprecatedInput(m_name, "can_ionize", "can_field_ionize");
76+
77+
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_can_field_ionize == pp.contains("ionization_product") || m_can_laser_ionize == pp.contains("ionization_product"),
78+
"When specifying ionization_product, can_*_ionize must be set to 1 via field or laser");
7679

7780
if(m_can_ionize) {
7881
m_neutralize_background = false; // change default

0 commit comments

Comments
 (0)