Skip to content

[WIP] Plasma Temperature Diagnostics #1228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Hipace.H
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ public:
inline static bool m_deposit_rho = false;
/** Whether to deposit rho for every individual plasma for diagnostics */
inline static bool m_deposit_rho_individual = false;
/** Whether to deposit temperature (plasma) for diagnostics */
inline static bool m_deposit_temp = false;
/** Whether to deposit temperature for every individual plasma for diagnostics */
inline static bool m_deposit_temp_individual = false;
/** Whether to interpolate the neutralizing background to MR levels 1 and 2 instead of depositing it */
inline static bool m_interpolate_neutralizing_background = false;
/** Whether to use tiling for particle operations */
Expand Down
13 changes: 13 additions & 0 deletions src/Hipace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ Hipace::Hipace () :
queryWithParser(pph, "deposit_rho", m_deposit_rho);
m_deposit_rho_individual = m_diags.needsRhoIndividual();
queryWithParser(pph, "deposit_rho_individual", m_deposit_rho_individual);
m_deposit_temp = m_diags.needsTemp();
queryWithParser(pph, "deposit_temp", m_deposit_temp);
m_deposit_temp_individual = m_diags.needsTempIndividual();
queryWithParser(pph, "deposit_temp_individual", m_deposit_temp_individual);
queryWithParser(pph, "interpolate_neutralizing_background",
m_interpolate_neutralizing_background);
bool do_mfi_sync = false;
Expand Down Expand Up @@ -619,6 +623,9 @@ Hipace::SolveOneSlice (int islice, int step)
m_multi_plasma.DepositCurrent(m_fields, WhichSlice::This, true, false,
m_deposit_rho || m_deposit_rho_individual, true, true, m_3D_geom, lev);

// deposit w, ux, uy, uz, ux2, uy2 and uz2 for all plasmas
m_multi_plasma.DepositTemperature(m_fields, WhichSlice::This, m_3D_geom, lev);

// deposit jz_beam and maybe rhomjz of the beam on This slice
m_multi_beam.DepositCurrentSlice(m_fields, m_3D_geom, lev, step,
false, true, m_do_beam_jz_minus_rho, WhichSlice::This, WhichBeamSlice::This);
Expand All @@ -627,6 +634,9 @@ Hipace::SolveOneSlice (int islice, int step)
m_multi_plasma.DepositCurrent(m_fields, WhichSlice::This, true, true,
m_deposit_rho || m_deposit_rho_individual, m_use_laser, true, m_3D_geom, lev);

// deposit w, ux, uy, uz, ux2, uy2 and uz2 for all plasmas
m_multi_plasma.DepositTemperature(m_fields, WhichSlice::This, m_3D_geom, lev);

// deposit jx jy jz and maybe rhomjz on This slice
m_multi_beam.DepositCurrentSlice(m_fields, m_3D_geom, lev, step,
m_do_beam_jx_jy_deposition, true, m_do_beam_jz_minus_rho,
Expand Down Expand Up @@ -996,6 +1006,9 @@ Hipace::PredictorCorrectorLoopToSolveBxBy (const int islice, const int current_N
m_multi_plasma.DepositCurrent(m_fields, WhichSlice::Next,
true, false, false, false, false, m_3D_geom, lev);

// deposit w, ux, uy, uz, ux2, uy2 and uz2 for all plasmas
m_multi_plasma.DepositTemperature(m_fields, WhichSlice::This, m_3D_geom, lev);

// beams deposit jx jy to the next slice
m_multi_beam.DepositCurrentSlice(m_fields, m_3D_geom, lev, step,
m_do_beam_jx_jy_deposition, false, false, WhichSlice::Next, WhichBeamSlice::Next);
Expand Down
8 changes: 8 additions & 0 deletions src/diagnostics/Diagnostic.H
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ public:
*/
bool needsRhoIndividual () const;

/** \brief determines if the temperature parameters are requested as a diagnostic
*/
bool needsTemp () const;

/** \brief determines if the temperature parameters for every individual plasma are requested as a diagnostic
*/
bool needsTempIndividual () const;

/** \brief calculate box which possibly was trimmed in case of slice IO
*
* \param[in] slice_dir slicing direction
Expand Down
33 changes: 33 additions & 0 deletions src/diagnostics/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,39 @@ Diagnostic::needsRhoIndividual () const {
return false;
}


bool
Diagnostic::needsTemp () const {
amrex::ParmParse ppd("diagnostic");
for (auto& fd : m_field_data) {
amrex::ParmParse pp(fd.m_diag_name);
amrex::Vector<std::string> comps{};
queryWithParserAlt(pp, "field_data", comps, ppd);
for (auto& c : comps) {
if (c == "ux") {
return true;
}
}
}
return false;
}

bool
Diagnostic::needsTempIndividual () const {
amrex::ParmParse ppd("diagnostic");
for (auto& fd : m_field_data) {
amrex::ParmParse pp(fd.m_diag_name);
amrex::Vector<std::string> comps{};
queryWithParserAlt(pp, "field_data", comps, ppd);
for (auto& c : comps) {
// we don't know the names of all the plasmas here so just look for "ux_..."
if (c.find("ux_") == 0) {
}
}
}
return false;
}

void
Diagnostic::Initialize (int nlev, bool use_laser) {
amrex::ParmParse ppd("diagnostic");
Expand Down
27 changes: 27 additions & 0 deletions src/fields/Fields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ Fields::AllocData (
Comps[isl].multi_emplace(N_Comps, "rho_" + plasma_name);
}
}
if (Hipace::m_deposit_temp) {
Comps[isl].multi_emplace(N_Comps, "w", "ux", "uy", "uz", "ux^2", "uy^2", "uz^2");
}
if (Hipace::m_deposit_temp_individual) {
for (auto& plasma_name : Hipace::GetInstance().m_multi_plasma.GetNames()) {
Comps[isl].multi_emplace(N_Comps, "w_" + plasma_name, "ux_" + plasma_name, "uy_" + plasma_name,
"uz_" + plasma_name, "ux^2_" + plasma_name, "uy^2_" + plasma_name, "uz^2_" + plasma_name);
}
}
if (Hipace::m_do_beam_jz_minus_rho) {
Comps[isl].multi_emplace(N_Comps, "rhomjz_beam");
}
Expand Down Expand Up @@ -144,6 +153,15 @@ Fields::AllocData (
Comps[isl].multi_emplace(N_Comps, "rho_" + plasma_name);
}
}
if (Hipace::m_deposit_temp) {
Comps[isl].multi_emplace(N_Comps, "w", "ux", "uy", "uz", "ux^2", "uy^2", "uz^2");
}
if (Hipace::m_deposit_temp_individual) {
for (auto& plasma_name : Hipace::GetInstance().m_multi_plasma.GetNames()) {
Comps[isl].multi_emplace(N_Comps, "w_" + plasma_name, "ux_" + plasma_name, "uy_" + plasma_name,
"uz_" + plasma_name, "ux^2_" + plasma_name, "uy^2_" + plasma_name, "uz^2_" + plasma_name);
}
}

isl = WhichSlice::Previous;
Comps[isl].multi_emplace(N_Comps, "Bx", "By", "jx", "jy");
Expand Down Expand Up @@ -583,6 +601,15 @@ Fields::InitializeSlices (int lev, int islice, const amrex::Vector<amrex::Geomet
setVal(0., lev, WhichSlice::This, "rho_" + plasma_name);
}
}
if (Hipace::m_deposit_temp) {
setVal(0., lev, WhichSlice::This, "w", "ux", "uy", "uz", "ux^2", "uy^2", "uz^2");
}
if (Hipace::m_deposit_temp_individual) {
for (auto& plasma_name : Hipace::GetInstance().m_multi_plasma.GetNames()) {
setVal(0., lev, WhichSlice::This, "w_" + plasma_name, "ux_" + plasma_name, "uy_" + plasma_name,
"uz_" + plasma_name, "ux^2_" + plasma_name, "uy^2_" + plasma_name, "uz^2_" + plasma_name);
}
}
}

void
Expand Down
1 change: 1 addition & 0 deletions src/particles/deposition/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
target_sources(HiPACE
PRIVATE
BeamDepositCurrent.cpp
TemperatureDeposition.cpp
PlasmaDepositCurrent.cpp
ExplicitDeposition.cpp
)
28 changes: 28 additions & 0 deletions src/particles/deposition/TemperatureDeposition.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* Copyright 2020-2021
*
* This file is part of HiPACE++.
*
* Authors: EyaDammak, AlexanderSinn, MaxThevenet
* License: BSD-3-Clause-LBNL
*/
#ifndef TEMPERATUREDEPOSITION_H_
#define TEMPERATUREDEPOSITION_H_

#include "particles/plasma/PlasmaParticleContainer.H"
#include "fields/Fields.H"
#include "utils/Constants.H"
#include "Hipace.H"

/** Depose current of particles in species plasma into the current 2D slice in fields
* \param[in] plasma species of which the current is deposited
* \param[in,out] fields the general field class, modified by this function
* \param[in] which_slice defines if this or the next slice is handled
* \param[in] gm Geometry of the simulation, to get the cell size etc.
* \param[in] lev MR level
*/
void
DepositTemperature (PlasmaParticleContainer& plasma, Fields & fields, const int which_slice,
amrex::Vector<amrex::Geometry> const& gm, int const lev);


#endif // TEMPERATUREDEPOSITION_H_
151 changes: 151 additions & 0 deletions src/particles/deposition/TemperatureDeposition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* Copyright 2025
*
* This file is part of HiPACE++.
*
* Authors: AlexanderSinn, EyaDammak, MaxThevenet
* License: BSD-3-Clause-LBNL
*/
#include "TemperatureDeposition.H"

#include "DepositionUtil.H"
#include "particles/particles_utils/ShapeFactors.H"
#include "particles/particles_utils/FieldGather.H"
#include "particles/plasma/PlasmaParticleContainer.H"
#include "fields/Fields.H"
#include "utils/Constants.H"
#include "Hipace.H"
#include "utils/HipaceProfilerWrapper.H"
#include "utils/Constants.H"
#include "utils/GPUUtil.H"


void
DepositTemperature (PlasmaParticleContainer& plasma, Fields & fields, const int which_slice,
amrex::Vector<amrex::Geometry> const& gm, int const lev)
{
if (!Hipace::m_deposit_temp) { // deposit temperature in input
return;
}
HIPACE_PROFILE("DepositCurrent_PlasmaParticleContainer()");
using namespace amrex::literals;

// only deposit ux individual on WhichSlice::This
const bool deposit_temp_individual = true;
const std::string ux_str = deposit_temp_individual ? "ux_" + plasma.GetName() : "ux";

// Loop over particle boxes
for (PlasmaParticleIterator pti(plasma); pti.isValid(); ++pti)
{
// Create the map with weight, momentum and squared momentum
amrex::FArrayBox& isl_fab = fields.getSlices(lev)[pti];
const int w = Comps[WhichSlice::This]["w_" + plasma.GetName()];
const int ux = Comps[WhichSlice::This]["ux_" + plasma.GetName()];
const int uy = Comps[WhichSlice::This]["uy_" + plasma.GetName()];
const int uz = Comps[WhichSlice::This]["uz_" + plasma.GetName()];
const int uxsq = Comps[WhichSlice::This]["ux^2_" + plasma.GetName()];
const int uysq = Comps[WhichSlice::This]["uy^2_" + plasma.GetName()];
const int uzsq = Comps[WhichSlice::This]["uz^2_" + plasma.GetName()];

// Offset for converting positions to indexes
const amrex::Real x_pos_offset = GetPosOffset(0, gm[lev], isl_fab.box());
const amrex::Real y_pos_offset = GetPosOffset(1, gm[lev], isl_fab.box());

// Extract box properties
const amrex::Real dx_inv = gm[lev].InvCellSize(0);
const amrex::Real dy_inv = gm[lev].InvCellSize(1);
const amrex::Real dz_inv = gm[lev].InvCellSize(2);
// in normalized units this is rescaling dx and dy for MR,
// while in SI units it's the factor for charge to charge density
const amrex::Real invvol = Hipace::m_normalized_units ?
gm[0].CellSize(0)*gm[0].CellSize(1)*dx_inv*dy_inv
: dx_inv*dy_inv*dz_inv;

const PhysConst pc = get_phys_const();
const amrex::Real clight = pc.c;
const amrex::Real clightinv = 1.0_rt/pc.c;
const amrex::Real clightinv2 = clightinv*clightinv;

// Loop over particles and deposit into jx_fab, jy_fab, jz_fab, and rho_fab

SharedMemoryDeposition<1, 1, false>(
int(pti.numParticles()),
// is_valid
// return whether the particle is valid and should deposit
[=] AMREX_GPU_DEVICE (int ip, auto ptd)
{
// only deposit plasma currents on or below their according MR level
return ptd.id(ip).is_valid() && (lev == 0 || ptd.cpu(ip) >= lev);
},
// get_cell
// return the lowest cell index that the particle deposits into
[=] AMREX_GPU_DEVICE (int ip, auto ptd) -> amrex::IntVectND<2>
{
const amrex::Real xp = ptd.pos(0, ip);
const amrex::Real yp = ptd.pos(1, ip);

const amrex::Real xmid = (xp - x_pos_offset) * dx_inv;
const amrex::Real ymid = (yp - y_pos_offset) * dy_inv;

auto [shape_x, i] =
compute_single_shape_factor<false, 0>(xmid, 0);

auto [shape_y, j] =
compute_single_shape_factor<false, 0>(ymid, 0);

return {i, j};
},
// deposit
[=] AMREX_GPU_DEVICE (int ip, auto ptd,
Array3<amrex::Real> arr,
auto cache_idx, auto depos_idx) noexcept
{
const amrex::Real xp = ptd.pos(0, ip);
const amrex::Real yp = ptd.pos(1, ip);

const amrex::Real ux = ptd.rdata(PlasmaIdx::ux)[ip];
const amrex::Real uy = ptd.rdata(PlasmaIdx::uy)[ip];
amrex::Real psi = ptd.rdata(PlasmaIdx::psi)[ip];
const amrex::Real uz = (1+ux*ux*clightinv2+uy*uy*clightinv2-psi*psi)/(2.*psi)*clight;
const amrex::Real w = ptd.rdata(PlasmaIdx::w)[ip];

const amrex::Real xmid = (xp - x_pos_offset) * dx_inv;
const amrex::Real ymid = (yp - y_pos_offset) * dy_inv;

// amrex::Real Aabssqp = 0._rt;
// if constexpr (use_laser) {
// doLaserGatherShapeN<0>(xp, yp, Aabssqp, arr, cache_idx[0],
// dx_inv, dy_inv, x_pos_offset, y_pos_offset);
// Aabssqp *= laser_norm_ion;
// }

// calculate gamma/psi for plasma particles
// const amrex::Real gamma_psi = 0.5_rt * (
// (1._rt + 0.5_rt * Aabssqp) * psi_inv * psi_inv
// + vx_c * vx_c * clightinv * clightinv
// + vy_c * vy_c * clightinv * clightinv
// + 1._rt
// );

// --- Compute shape factors
// x direction
auto [shape_x, i] =
compute_single_shape_factor<false, 0>(xmid, 0);

// y direction
auto [shape_y, j] =
compute_single_shape_factor<false, 0>(ymid, 0);

amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[0]), w);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[1]), w*ux);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[2]), w*uy);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[3]), w*uz);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[4]), w*ux*ux);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[5]), w*uy*uy);
amrex::Gpu::Atomic::Add(arr.ptr(i, j, depos_idx[6]), w*uz*uz);
},
isl_fab.array(),
isl_fab.box(), pti.GetParticleTile().getParticleTileData(),
amrex::GpuArray<int, 0>{},
amrex::GpuArray<int, 7>{w, ux, uy, uz, uxsq, uysq, uzsq});
}
}
11 changes: 11 additions & 0 deletions src/particles/plasma/MultiPlasma.H
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ public:
bool deposit_jz, bool deposit_rho, bool deposit_chi, bool deposit_rhomjz,
amrex::Vector<amrex::Geometry> const& gm, int const lev);

/** Loop over plasma species and depose their currents into the current 2D slice in fields
*
* \param[in,out] fields the general field class, modified by this function
* \param[in] which_slice defines if this or the next slice is handled
* \param[in] gm Geometry of the simulation, to get the cell size etc.
* \param[in] lev MR level
*/
void DepositTemperature (
Fields & fields, int which_slice,
amrex::Vector<amrex::Geometry> const& gm, int const lev);

/** Loop over plasma species and depose Sx and Sy into the current 2D slice in fields
*
* \param[in,out] fields the general field class, modified by this function
Expand Down
12 changes: 12 additions & 0 deletions src/particles/plasma/MultiPlasma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
#include "MultiPlasma.H"
#include "particles/deposition/PlasmaDepositCurrent.H"
#include "particles/deposition/TemperatureDeposition.H"
#include "particles/deposition/ExplicitDeposition.H"
#include "particles/pusher/PlasmaParticleAdvance.H"
#include "utils/HipaceProfilerWrapper.H"
Expand Down Expand Up @@ -85,6 +86,17 @@ MultiPlasma::DepositCurrent (
}
}

void
MultiPlasma::DepositTemperature (
Fields & fields, int which_slice,
amrex::Vector<amrex::Geometry> const& gm, int const lev)
{
for (int i=0; i<m_nplasmas; i++) {
::DepositTemperature(m_all_plasmas[i], fields, which_slice,
gm, lev);
}
}

void
MultiPlasma::ExplicitDeposition (Fields& fields, amrex::Vector<amrex::Geometry> const& gm,
int const lev)
Expand Down
Loading