284 using namespace amrex::literals;
297 constexpr int getpos_offset = 0;
298 for (
int i = 0; i < n_product_species; i++)
300 ParticleTileType& ptile_product = product_species_vector[i]->ParticlesAt(lev, mfi);
301 tile_products.push_back(&ptile_product);
305 products_mass.push_back(product_species_vector[i]->getMass());
307 auto *tile_products_data = tile_products.data();
310 amrex::Real * global_debye_length_data =
nullptr;
315 global_debye_length_data = global_debye_length_fab.
dataPtr();
320#if defined(WARPX_DIM_RZ)
324 int const nz = hi.y - lo.y + 1;
326#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER) || defined(WARPX_DIM_RSPHERE)
327 auto const dr = geom_lev.
CellSize(0);
331#if defined(WARPX_DIM_RZ)
333 int const ri = (i_cell - i_cell%nz)/nz;
335 amrex::ParticleReal
const rr = (ri + 0.5_prt)*dr;
336 return 2.0_prt*
static_cast<amrex::ParticleReal
>(
MathConst::pi)*rr;
337#elif defined(WARPX_DIM_RCYLINDER)
338 int const ri = i_cell;
340 amrex::ParticleReal
const rr = (ri + 0.5_prt)*dr;
341 return 2.0_prt*
static_cast<amrex::ParticleReal
>(
MathConst::pi)*rr;
342#elif defined(WARPX_DIM_RSPHERE)
344 int const ri = i_cell;
346 amrex::ParticleReal
const rr = (ri + 0.5_prt)*dr;
347 return 4.0_prt*
static_cast<amrex::ParticleReal
>(
MathConst::pi)*rr*rr;
361 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findParticlesInEachCell", prof_findParticlesInEachCell);
368 auto const n_cells =
static_cast<int>(bins_1.
numBins());
375 const amrex::ParticleReal q1 = species_1.
getCharge();
376 const amrex::ParticleReal m1 = species_1.
getMass();
382 const int n_cells_products = have_product_species ? n_cells: 0;
389 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::computeNumberOfPairs", prof_computeNumberOfPairs);
393 const auto n_part_in_cell = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
395 p_n_pairs_in_each_cell[i_cell] = (n_part_in_cell == 1)? 0: (n_part_in_cell+1)/2;
401 const index_type n_total_pairs = (n_cells_products == 0) ? 0:
403 p_n_pairs_in_each_cell, pair_offsets.data());
412 const auto n_part_in_cell = (i_cell < n_cells)? cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell]: 0;
414 p_n_ind_pairs_in_each_cell[i_cell] = n_part_in_cell/2;
439 pair_reaction_weight.
dataPtr();
441 int const n_product_data = (binary_collision_functor.m_need_product_data ? n_total_pairs : 0);
461 if (binary_collision_functor.m_computeSpeciesDensities) {
462 n1_vec.
resize(n_cells, 0.0_prt);
464 if (binary_collision_functor.m_computeSpeciesTemperatures) {
465 T1_vec.
resize(n_cells, 0.0_prt);
466 vx1_vec.
resize(n_cells, 0.0_prt);
467 vy1_vec.
resize(n_cells, 0.0_prt);
468 vz1_vec.
resize(n_cells, 0.0_prt);
469 vs1_vec.
resize(n_cells, 0.0_prt);
487 ww_weighted_sum_vec.
resize(n_cells, 0.0_prt);
488 KE_vec.
resize(n_cells, 0.0_prt);
489 px_vec.
resize(n_cells, 0.0_prt);
490 py_vec.
resize(n_cells, 0.0_prt);
491 pz_vec.
resize(n_cells, 0.0_prt);
511 std::vector<std::string>
const & real_names1 = species_1.
GetRealSoANames();
512 auto const pos1 = std::find(real_names1.begin(), real_names1.end(),
"ux_n");
513 if (pos1 != real_names1.end()) {
514 int const u1x_ni = std::distance(real_names1.begin(), pos1);
515 u1x_before_ptr = soa_1.m_runtime_rdata[u1x_ni];
516 u1y_before_ptr = soa_1.m_runtime_rdata[u1x_ni + 1];
517 u1z_before_ptr = soa_1.m_runtime_rdata[u1x_ni + 2];
522 u1x_before_ptr = u1x_before.
dataPtr();
523 u1y_before_ptr = u1y_before.
dataPtr();
524 u1z_before_ptr = u1z_before.
dataPtr();
531 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures", prof_findDensityTemperatures);
534 binary_collision_functor.m_computeSpeciesDensities ||
535 binary_collision_functor.m_computeSpeciesTemperatures) {
539 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::atomics", prof_findDensityTemperatures_atomics);
544 if (correct_energy_momentum) {
545 u1x_before_ptr[ip] = u1x[ip];
546 u1y_before_ptr[ip] = u1y[ip];
547 u1z_before_ptr[ip] = u1z[ip];
549 const int i_cell = bins_1_ptr[ip];
552 amrex::ParticleReal
const w1_scaled = std::pow(w1[ip], beta_weight_exponent);
562 if (binary_collision_functor.m_computeSpeciesDensities) {
564 w1[ip]/(dV*volume_factor(bins_1_ptr[ip])));
568 if (binary_collision_functor.m_computeSpeciesTemperatures) {
569 amrex::ParticleReal us = u1x[ip]*u1x[ip] + u1y[ip]*u1y[ip] + u1z[ip]*u1z[ip];
571 amrex::ParticleReal gm = std::sqrt( 1.0_prt + us*inv_c2);
585 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::finishTemperature", prof_findDensityTemperatures_finish);
590 index_type const cell_start_1 = cell_offsets_1[i_cell];
591 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
594 if ( cell_stop_1 - cell_start_1 <= 1 ) {
return; }
597 if (binary_collision_functor.m_computeSpeciesTemperatures) {
598 const amrex::ParticleReal invsum = 1._prt/T1_in_each_cell[i_cell];
599 auto vx1 = vx1_in_each_cell[i_cell] * invsum;
600 auto vy1 = vy1_in_each_cell[i_cell] * invsum;
601 auto vz1 = vz1_in_each_cell[i_cell] * invsum;
602 auto vs1 = vs1_in_each_cell[i_cell] * invsum;
604 T1_in_each_cell[i_cell] = m1/(3._prt)*(vs1 -(vx1*vx1+vy1*vy1+vz1*vz1));
611 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::shuffle", prof_findDensityTemperatures_shuffle);
617 index_type const cell_start_1 = cell_offsets_1[i_cell];
618 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
621 if ( cell_stop_1 - cell_start_1 <= 1 ) {
return; }
636 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::LoopOverCollisions", prof_loopOverCollisions);
644 const int i_cell =
amrex::bisect( p_coll_offsets, 0, n_cells, ui_coll );
648 index_type const cell_start_1 = cell_offsets_1[i_cell];
649 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
650 index_type const cell_half_1 = (cell_start_1+cell_stop_1)/2;
653 const index_type coll_idx = ui_coll - p_coll_offsets[i_cell];
656 index_type const cell_start_pair = have_product_species?
657 p_pair_offsets[i_cell] : 0;
660 amrex::ParticleReal n1 = 0.0;
661 amrex::ParticleReal T1 = 0.0;
662 if (binary_collision_functor.m_computeSpeciesDensities) {
663 n1 = n1_in_each_cell[i_cell];
665 if (binary_collision_functor.m_computeSpeciesTemperatures) {
666 T1 = T1_in_each_cell[i_cell];
669 amrex::Real global_lamdb = 0.;
671 global_lamdb = global_debye_length_data[i_cell];
677 binary_collision_functor(
678 cell_start_1, cell_half_1,
679 cell_half_1, cell_stop_1,
680 indices_1, indices_1,
681 soa_1, soa_1, get_position_1, get_position_1,
682 n1, n1, T1, T1, global_lamdb,
683 q1, q1, m1, m1, dt, dV*volume_factor(i_cell), coll_idx,
684 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
685 p_pair_reaction_weight, p_product_data, engine);
693 product_species_vector,
696 products_mass, p_mask, products_np,
697 copy_species1, copy_species2,
698 p_pair_indices_1, p_pair_indices_2,
699 p_pair_reaction_weight, p_product_data);
701 for (
int i = 0; i < n_product_species; i++)
703 setNewParticleIDs(*(tile_products_data[i]),
static_cast<int>(products_np[i]), num_added[i]);
711 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::correctEnergyMomentum", prof_correctEnergyMomentum);
716 const int i_cell = bins_1_ptr[i1];
720 amrex::ParticleReal
const px = w1[i1]*u1x[i1]*m1;
721 amrex::ParticleReal
const py = w1[i1]*u1y[i1]*m1;
722 amrex::ParticleReal
const pz = w1[i1]*u1z[i1]*m1;
733 const int i_cell = bins_1_ptr[i1];
735 amrex::ParticleReal
const ww_weighted_sum = ww_weighted_sum_in_each_cell[i_cell];
736 amrex::ParticleReal
const w_factor = std::pow(w1[i1], beta_weight_exponent - 1._prt)/m1;
737 u1x[i1] += w_factor*px_in_each_cell[i_cell]/ww_weighted_sum;
738 u1y[i1] += w_factor*py_in_each_cell[i_cell]/ww_weighted_sum;
739 u1z[i1] += w_factor*pz_in_each_cell[i_cell]/ww_weighted_sum;
748 amrex::Long* failed_corrections_ptr = failed_corrections.
data();
749 amrex::ParticleReal* remaining_energy_ptr = remaining_energy.data();
755 index_type const cell_start_1 = cell_offsets_1[i_cell];
756 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
757 amrex::ParticleReal deltaEp1 = -KE_in_each_cell[i_cell];
759 if (deltaEp1 != 0.) {
761 bool correction_failed =
763 cell_start_1, cell_stop_1, m1,
764 energy_fraction, energy_fraction_max, deltaEp1);
765 if (correction_failed) {
768 for (
index_type i1=cell_start_1; i1<cell_stop_1; ++i1) {
769 u1x[ indices_1[i1] ] = u1x_before_ptr[ indices_1[i1] ];
770 u1y[ indices_1[i1] ] = u1y_before_ptr[ indices_1[i1] ];
771 u1z[ indices_1[i1] ] = u1z_before_ptr[ indices_1[i1] ];
781 amrex::Long
const num_failed_corrections = *(failed_corrections.copyToHost());
782 amrex::ParticleReal
const total_remaining_energy = *(remaining_energy.copyToHost());
783 if (num_failed_corrections > 0) {
785 "The energy correction failed for " + std::to_string(num_failed_corrections) +
" cells " +
787 "The remaining energy is " + std::to_string(total_remaining_energy/
PhysConst::q_e) +
" eV. " +
788 "The collisions in those cells was cancelled.");
802 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findParticlesInEachCell", prof_findParticlesInEachCell);
810 auto const n_cells =
static_cast<int>(bins_1.
numBins());
817 const amrex::ParticleReal q1 = species_1.
getCharge();
818 const amrex::ParticleReal m1 = species_1.
getMass();
826 const amrex::ParticleReal q2 = species_2.
getCharge();
827 const amrex::ParticleReal m2 = species_2.
getMass();
833 const int n_cells_products = have_product_species ? n_cells: 0;
840 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::computeNumberOfPairs", prof_computeNumberOfPairs);
844 const auto n_part_in_cell_1 = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
845 const auto n_part_in_cell_2 = cell_offsets_2[i_cell+1] - cell_offsets_2[i_cell];
847 if (n_part_in_cell_1 == 0 || n_part_in_cell_2 == 0) {
848 p_n_pairs_in_each_cell[i_cell] = 0;
850 p_n_pairs_in_each_cell[i_cell] =
851 amrex::max(n_part_in_cell_1,n_part_in_cell_2);
858 const index_type n_total_pairs = (n_cells_products == 0) ? 0:
860 p_n_pairs_in_each_cell, pair_offsets.data());
869 if (i_cell < n_cells)
871 const auto n_part_in_cell_1 = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
872 const auto n_part_in_cell_2 = cell_offsets_2[i_cell+1] - cell_offsets_2[i_cell];
873 p_n_ind_pairs_in_each_cell[i_cell] =
amrex::min(n_part_in_cell_1, n_part_in_cell_2);
877 p_n_ind_pairs_in_each_cell[i_cell] = 0;
903 pair_reaction_weight.
dataPtr();
905 int const n_product_data = (binary_collision_functor.m_need_product_data ? n_total_pairs : 0);
930 if (binary_collision_functor.m_computeSpeciesDensities) {
931 n1_vec.
resize(n_cells, 0.0_prt);
932 n2_vec.
resize(n_cells, 0.0_prt);
934 if (binary_collision_functor.m_computeSpeciesTemperatures) {
935 T1_vec.
resize(n_cells, 0.0_prt);
936 T2_vec.
resize(n_cells, 0.0_prt);
937 vx1_vec.
resize(n_cells, 0.0_prt);
938 vx2_vec.
resize(n_cells, 0.0_prt);
939 vy1_vec.
resize(n_cells, 0.0_prt);
940 vy2_vec.
resize(n_cells, 0.0_prt);
941 vz1_vec.
resize(n_cells, 0.0_prt);
942 vz2_vec.
resize(n_cells, 0.0_prt);
943 vs1_vec.
resize(n_cells, 0.0_prt);
944 vs2_vec.
resize(n_cells, 0.0_prt);
968 ww_weighted_sum_vec.
resize(n_cells, 0.0_prt);
969 KE_vec.
resize(n_cells, 0.0_prt);
970 px_vec.
resize(n_cells, 0.0_prt);
971 py_vec.
resize(n_cells, 0.0_prt);
972 pz_vec.
resize(n_cells, 0.0_prt);
992 std::vector<std::string>
const & real_names1 = species_1.
GetRealSoANames();
993 auto const pos1 = std::find(real_names1.begin(), real_names1.end(),
"ux_n");
994 if (pos1 != real_names1.end()) {
995 int const u1x_ni = std::distance(real_names1.begin(), pos1);
996 u1x_before_ptr = soa_1.m_runtime_rdata[u1x_ni];
997 u1y_before_ptr = soa_1.m_runtime_rdata[u1x_ni + 1];
998 u1z_before_ptr = soa_1.m_runtime_rdata[u1x_ni + 2];
1003 u1x_before_ptr = u1x_before.
dataPtr();
1004 u1y_before_ptr = u1y_before.
dataPtr();
1005 u1z_before_ptr = u1z_before.
dataPtr();
1017 std::vector<std::string>
const & real_names2 = species_2.
GetRealSoANames();
1018 auto const pos2 = std::find(real_names2.begin(), real_names2.end(),
"ux_n");
1019 if (pos2 != real_names2.end()) {
1020 int const u2x_ni = std::distance(real_names2.begin(), pos2);
1021 u2x_before_ptr = soa_2.m_runtime_rdata[u2x_ni];
1022 u2y_before_ptr = soa_2.m_runtime_rdata[u2x_ni + 1];
1023 u2z_before_ptr = soa_2.m_runtime_rdata[u2x_ni + 2];
1028 u2x_before_ptr = u2x_before.
dataPtr();
1029 u2y_before_ptr = u2y_before.
dataPtr();
1030 u2z_before_ptr = u2z_before.
dataPtr();
1036 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures", prof_findDensityTemperatures);
1039 binary_collision_functor.m_computeSpeciesDensities ||
1040 binary_collision_functor.m_computeSpeciesTemperatures) {
1045 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::atomics", prof_findDensityTemperatures_atomics);
1049 if (correct_energy_momentum) {
1052 const int i_cell = bins_1_ptr[i1];
1055 u1x_before_ptr[i1] = u1x[i1];
1056 u1y_before_ptr[i1] = u1y[i1];
1057 u1z_before_ptr[i1] = u1z[i1];
1060 amrex::ParticleReal
const w1_scaled = std::pow(w1[i1], beta_weight_exponent);
1071 const int i_cell = bins_2_ptr[i2];
1074 u2x_before_ptr[i2] = u2x[i2];
1075 u2y_before_ptr[i2] = u2y[i2];
1076 u2z_before_ptr[i2] = u2z[i2];
1079 amrex::ParticleReal
const w2_scaled = std::pow(w2[i2], beta_weight_exponent);
1090 if (binary_collision_functor.m_computeSpeciesDensities) {
1093 w1[ip]/(dV*volume_factor(bins_1_ptr[ip])));
1097 w2[ip]/(dV*volume_factor(bins_2_ptr[ip])));
1102 if (binary_collision_functor.m_computeSpeciesTemperatures) {
1104 amrex::ParticleReal us = u1x[ip]*u1x[ip] + u1y[ip]*u1y[ip] + u1z[ip]*u1z[ip];
1106 amrex::ParticleReal gm = std::sqrt( 1.0_prt + us*inv_c2);
1114 amrex::ParticleReal us = u2x[ip]*u2x[ip] + u2y[ip]*u2y[ip] + u2z[ip]*u2z[ip];
1116 amrex::ParticleReal gm = std::sqrt( 1.0_prt + us*inv_c2);
1131 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::finishTemperature", prof_findDensityTemperatures_finish);
1134 int i_cell = i < n_cells ? i : i - n_cells;
1138 index_type const cell_start_1 = cell_offsets_1[i_cell];
1139 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
1142 index_type const cell_start_2 = cell_offsets_2[i_cell];
1143 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
1146 if ( cell_stop_1 - cell_start_1 < 1 ||
1147 cell_stop_2 - cell_start_2 < 1 ) {
return; }
1150 if (binary_collision_functor.m_computeSpeciesTemperatures) {
1152 const amrex::ParticleReal invsum1 = 1._prt/T1_in_each_cell[i_cell];
1153 auto vx1 = vx1_in_each_cell[i_cell] * invsum1;
1154 auto vy1 = vy1_in_each_cell[i_cell] * invsum1;
1155 auto vz1 = vz1_in_each_cell[i_cell] * invsum1;
1156 auto vs1 = vs1_in_each_cell[i_cell] * invsum1;
1158 T1_in_each_cell[i_cell] = m1/(3._prt)*(vs1 -(vx1*vx1+vy1*vy1+vz1*vz1));
1160 const amrex::ParticleReal invsum2 = 1._prt/T2_in_each_cell[i_cell];
1161 auto vx2 = vx2_in_each_cell[i_cell] * invsum2;
1162 auto vy2 = vy2_in_each_cell[i_cell] * invsum2;
1163 auto vz2 = vz2_in_each_cell[i_cell] * invsum2;
1164 auto vs2 = vs2_in_each_cell[i_cell] * invsum2;
1166 T2_in_each_cell[i_cell] = m2/(3._prt)*(vs2 -(vx2*vx2+vy2*vy2+vz2*vz2));
1174 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::findDensityTemperatures::shuffle", prof_findDensityTemperatures_shuffle);
1178 int i_cell = i < n_cells ? i : i - n_cells;
1182 index_type const cell_start_1 = cell_offsets_1[i_cell];
1183 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
1186 index_type const cell_start_2 = cell_offsets_2[i_cell];
1187 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
1190 if ( cell_stop_1 - cell_start_1 < 1 ||
1191 cell_stop_2 - cell_start_2 < 1 ) {
return; }
1210 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::LoopOverCollisions", prof_loopOverCollisions);
1218 const int i_cell =
amrex::bisect( p_coll_offsets, 0, n_cells, ui_coll );
1222 index_type const cell_start_1 = cell_offsets_1[i_cell];
1223 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
1225 index_type const cell_start_2 = cell_offsets_2[i_cell];
1226 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
1229 const index_type coll_idx = ui_coll - p_coll_offsets[i_cell];
1232 index_type const cell_start_pair = have_product_species?
1233 p_pair_offsets[i_cell]: 0;
1240 amrex::ParticleReal n1 = 0.0, n2 = 0.0;
1241 amrex::ParticleReal T1 = 0.0, T2 = 0.0;
1242 if (binary_collision_functor.m_computeSpeciesDensities) {
1243 n1 = n1_in_each_cell[i_cell];
1244 n2 = n2_in_each_cell[i_cell];
1246 if (binary_collision_functor.m_computeSpeciesTemperatures) {
1247 T1 = T1_in_each_cell[i_cell];
1248 T2 = T2_in_each_cell[i_cell];
1251 amrex::Real global_lamdb = 0.;
1253 global_lamdb = global_debye_length_data[i_cell];
1259 binary_collision_functor(
1260 cell_start_1, cell_stop_1, cell_start_2, cell_stop_2,
1261 indices_1, indices_2,
1262 soa_1, soa_2, get_position_1, get_position_2,
1263 n1, n2, T1, T2, global_lamdb,
1264 q1, q2, m1, m2, dt, dV*volume_factor(i_cell), coll_idx,
1265 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
1266 p_pair_reaction_weight, p_product_data, engine);
1275 product_species_vector,
1278 products_mass, p_mask, products_np,
1279 copy_species1, copy_species2,
1280 p_pair_indices_1, p_pair_indices_2,
1281 p_pair_reaction_weight, p_product_data);
1283 for (
int i = 0; i < n_product_species; i++)
1285 setNewParticleIDs(*(tile_products_data[i]),
static_cast<int>(products_np[i]), num_added[i]);
1293 WARPX_PROFILE_VAR(
"BinaryCollision::doCollisionsWithinTile::correctEnergyMomentum", prof_correctEnergyMomentum);
1300 const int i_cell = bins_1_ptr[i1];
1304 amrex::ParticleReal
const px = w1[i1]*u1x[i1]*m1;
1305 amrex::ParticleReal
const py = w1[i1]*u1y[i1]*m1;
1306 amrex::ParticleReal
const pz = w1[i1]*u1z[i1]*m1;
1314 const int i_cell = bins_2_ptr[i2];
1318 amrex::ParticleReal
const px = w2[i2]*u2x[i2]*m2;
1319 amrex::ParticleReal
const py = w2[i2]*u2y[i2]*m2;
1320 amrex::ParticleReal
const pz = w2[i2]*u2z[i2]*m2;
1333 const int i_cell = bins_1_ptr[i1];
1335 amrex::ParticleReal
const ww_weighted_sum = ww_weighted_sum_in_each_cell[i_cell];
1336 amrex::ParticleReal
const w_factor = std::pow(w1[i1], beta_weight_exponent - 1._prt)/m1;
1337 u1x[i1] += w_factor*px_in_each_cell[i_cell]/ww_weighted_sum;
1338 u1y[i1] += w_factor*py_in_each_cell[i_cell]/ww_weighted_sum;
1339 u1z[i1] += w_factor*pz_in_each_cell[i_cell]/ww_weighted_sum;
1344 const int i_cell = bins_2_ptr[i2];
1346 amrex::ParticleReal
const ww_weighted_sum = ww_weighted_sum_in_each_cell[i_cell];
1347 amrex::ParticleReal
const w_factor = std::pow(w2[i2], beta_weight_exponent - 1._prt)/m2;
1348 u2x[i2] += w_factor*px_in_each_cell[i_cell]/ww_weighted_sum;
1349 u2y[i2] += w_factor*py_in_each_cell[i_cell]/ww_weighted_sum;
1350 u2z[i2] += w_factor*pz_in_each_cell[i_cell]/ww_weighted_sum;
1357 amrex::Long* failed_corrections_ptr = failed_corrections.
data();
1358 amrex::ParticleReal* remaining_energy_ptr = remaining_energy.data();
1365 index_type const cell_start_1 = cell_offsets_1[i_cell];
1366 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
1368 index_type const cell_start_2 = cell_offsets_2[i_cell];
1369 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
1372 if ( cell_stop_1 - cell_start_1 < 1 ||
1373 cell_stop_2 - cell_start_2 < 1 ) {
return; }
1375 amrex::ParticleReal
const psq = px_in_each_cell[i_cell]*px_in_each_cell[i_cell] +
1376 py_in_each_cell[i_cell]*py_in_each_cell[i_cell] +
1377 pz_in_each_cell[i_cell]*pz_in_each_cell[i_cell];
1379 amrex::ParticleReal w1_sum = 0.0_prt;
1380 amrex::ParticleReal w2_sum = 0.0_prt;
1381 amrex::ParticleReal KE1_after = 0._prt;
1382 amrex::ParticleReal KE2_after = 0._prt;
1383 for (
index_type i1=cell_start_1; i1<cell_stop_1; ++i1) {
1384 w1_sum += w1[ indices_1[i1] ];
1386 u1y[ indices_1[i1] ],
1387 u1z[ indices_1[i1] ], m1);
1389 for (
index_type i2=cell_start_2; i2<cell_stop_2; ++i2) {
1390 w2_sum += w2[ indices_2[i2] ];
1392 u2y[ indices_2[i2] ],
1393 u2z[ indices_2[i2] ], m2);
1396 const amrex::ParticleReal KE_after = KE1_after + KE2_after;
1397 const amrex::ParticleReal deltaE = KE_after - KE_in_each_cell[i_cell];
1398 amrex::ParticleReal deltaEp1, deltaEp2;
1399 int const numCell1 = (cell_stop_1 - cell_start_1);
1400 int const numCell2 = (cell_stop_2 - cell_start_2);
1401 if (numCell1 == 1) {
1404 }
else if (numCell2 == 1) {
1408 const amrex::ParticleReal Etotdenom = w1_sum*KE1_after/numCell1 + w2_sum*KE2_after/numCell2;
1409 deltaEp1 = w1_sum*KE1_after/Etotdenom*deltaE/numCell1;
1410 deltaEp2 = w2_sum*KE2_after/Etotdenom*deltaE/numCell2;
1413 bool correction1_failed =
false;
1414 bool correction2_failed =
false;
1415 if (deltaEp1 != 0.) {
1417 correction1_failed =
1419 cell_start_1, cell_stop_1, m1,
1420 energy_fraction, energy_fraction_max, deltaEp1);
1423 if (deltaEp2 != 0.) {
1425 correction2_failed =
1427 cell_start_2, cell_stop_2, m2,
1428 energy_fraction, energy_fraction_max, deltaEp2);
1431 if (correction1_failed || correction2_failed) {
1434 for (
index_type i1=cell_start_1; i1<cell_stop_1; ++i1) {
1435 u1x[ indices_1[i1] ] = u1x_before_ptr[ indices_1[i1] ];
1436 u1y[ indices_1[i1] ] = u1y_before_ptr[ indices_1[i1] ];
1437 u1z[ indices_1[i1] ] = u1z_before_ptr[ indices_1[i1] ];
1439 for (
index_type i2=cell_start_2; i2<cell_stop_2; ++i2) {
1440 u2x[ indices_2[i2] ] = u2x_before_ptr[ indices_2[i2] ];
1441 u2y[ indices_2[i2] ] = u2y_before_ptr[ indices_2[i2] ];
1442 u2z[ indices_2[i2] ] = u2z_before_ptr[ indices_2[i2] ];
1452 amrex::Long
const num_failed_corrections = *(failed_corrections.copyToHost());
1453 amrex::ParticleReal
const total_remaining_energy = *(remaining_energy.copyToHost());
1454 if (num_failed_corrections > 0) {
1456 "The energy correction failed for " + std::to_string(num_failed_corrections) +
" cells " +
1458 "The remaining energy is " + std::to_string(total_remaining_energy/
PhysConst::q_e) +
" eV. " +
1459 "The collisions in those cells was cancelled.");