aboutsummaryrefslogtreecommitdiff
path: root/Source/Diagnostics/ReducedDiags/BeamRelevant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Diagnostics/ReducedDiags/BeamRelevant.cpp')
-rw-r--r--Source/Diagnostics/ReducedDiags/BeamRelevant.cpp389
1 files changed, 389 insertions, 0 deletions
diff --git a/Source/Diagnostics/ReducedDiags/BeamRelevant.cpp b/Source/Diagnostics/ReducedDiags/BeamRelevant.cpp
new file mode 100644
index 000000000..b82d24645
--- /dev/null
+++ b/Source/Diagnostics/ReducedDiags/BeamRelevant.cpp
@@ -0,0 +1,389 @@
+/* Copyright 2019-2020 Yinjian Zhao
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+
+#include "BeamRelevant.H"
+#include "WarpX.H"
+#include "WarpXConst.H"
+#include "AMReX_REAL.H"
+#include "AMReX_ParticleReduce.H"
+#include <iostream>
+#include <cmath>
+#include <limits>
+
+using namespace amrex;
+
+// constructor
+BeamRelevant::BeamRelevant (std::string rd_name)
+: ReducedDiags{rd_name}
+{
+
+#if (defined WARPX_DIM_RZ)
+ // RZ coordinate is not working
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(false,
+ "BeamRelevant reduced diagnostics does not work for RZ coordinate.");
+#endif
+
+ // read beam name
+ ParmParse pp(rd_name);
+ pp.get("species",m_beam_name);
+
+ // resize data array
+#if (AMREX_SPACEDIM == 3)
+ // 0, 1, 2: mean x,y,z
+ // 3, 4, 5: mean px,py,pz
+ // 6: gamma
+ // 7, 8, 9: rms x,y,z
+ // 10,11,12: rms px,py,pz
+ // 13: rms gamma
+ // 14,15,16: emittance x,y,z
+ m_data.resize(17,0.0);
+#elif (AMREX_SPACEDIM == 2)
+ // 0, 1: mean x,z
+ // 2, 3, 4: mean px,py,pz
+ // 5: gamma
+ // 6, 7: rms x,z
+ // 8, 9,10: rms px,py,pz
+ // 11: rms gamma
+ // 12,13: emittance x,z
+ m_data.resize(14,0.0);
+#endif
+
+ if (ParallelDescriptor::IOProcessor())
+ {
+ if ( m_IsNotRestart )
+ {
+ // open file
+ std::ofstream ofs;
+ ofs.open(m_path + m_rd_name + "." + m_extension,
+ std::ofstream::out | std::ofstream::app);
+ // write header row
+#if (AMREX_SPACEDIM == 3)
+ ofs << "#";
+ ofs << "[1]step"; ofs << m_sep;
+ ofs << "[2]time(s)"; ofs << m_sep;
+ ofs << "[3]x_mean(m)"; ofs << m_sep;
+ ofs << "[4]y_mean(m)"; ofs << m_sep;
+ ofs << "[5]z_mean(m)"; ofs << m_sep;
+ ofs << "[6]px_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[7]py_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[8]pz_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[9]gamma_mean"; ofs << m_sep;
+ ofs << "[10]x_rms(m)"; ofs << m_sep;
+ ofs << "[11]y_rms(m)"; ofs << m_sep;
+ ofs << "[12]z_rms(m)"; ofs << m_sep;
+ ofs << "[13]px_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[14]py_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[15]pz_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[16]gamma_rms"; ofs << m_sep;
+ ofs << "[17]emittance_x(m)"; ofs << m_sep;
+ ofs << "[18]emittance_y(m)"; ofs << m_sep;
+ ofs << "[19]emittance_z(m)"; ofs << std::endl;
+#elif (AMREX_SPACEDIM == 2)
+ ofs << "#";
+ ofs << "[1]step"; ofs << m_sep;
+ ofs << "[2]time(s)"; ofs << m_sep;
+ ofs << "[3]x_mean(m)"; ofs << m_sep;
+ ofs << "[4]z_mean(m)"; ofs << m_sep;
+ ofs << "[5]px_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[6]py_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[7]pz_mean(kg m/s)"; ofs << m_sep;
+ ofs << "[8]gamma_mean"; ofs << m_sep;
+ ofs << "[9]x_rms(m)"; ofs << m_sep;
+ ofs << "[10]z_rms(m)"; ofs << m_sep;
+ ofs << "[11]px_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[12]py_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[13]pz_rms(kg m/s)"; ofs << m_sep;
+ ofs << "[14]gamma_rms"; ofs << m_sep;
+ ofs << "[15]emittance_x(m)"; ofs << m_sep;
+ ofs << "[16]emittance_z(m)"; ofs << std::endl;
+#endif
+ // close file
+ ofs.close();
+ }
+ }
+
+}
+// end constructor
+
+// function that compute beam relevant quantities
+void BeamRelevant::ComputeDiags (int step)
+{
+
+ // Judge if the diags should be done
+ if ( (step+1) % m_freq != 0 ) { return; }
+
+ // get MultiParticleContainer class object
+ auto & mypc = WarpX::GetInstance().GetPartContainer();
+
+ // get number of species
+ int const nSpecies = mypc.nSpecies();
+
+ // get species names (std::vector<std::string>)
+ auto const species_names = mypc.GetSpeciesNames();
+
+ // inverse of speed of light squared
+ Real constexpr inv_c2 = 1.0 / (PhysConst::c * PhysConst::c);
+
+ // If 2D-XZ, p.pos(1) is z, rather than p.pos(2).
+#if (AMREX_SPACEDIM == 3)
+ int const index_z = 2;
+#elif (AMREX_SPACEDIM == 2)
+ int const index_z = 1;
+#endif
+
+ // loop over species
+ for (int i_s = 0; i_s < nSpecies; ++i_s)
+ {
+
+ // only beam species does
+ if (species_names[i_s] != m_beam_name) { continue; }
+
+ // get WarpXParticleContainer class object
+ auto const & myspc = mypc.GetParticleContainer(i_s);
+
+ // get mass (Real)
+ Real const m = myspc.getMass();
+
+ using PType = typename WarpXParticleContainer::SuperParticleType;
+
+ // weight sum
+ Real w_sum = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.rdata(PIdx::w); });
+
+ // reduced sum over mpi ranks
+ ParallelDescriptor::ReduceRealSum(w_sum);
+
+ if (w_sum < std::numeric_limits<Real>::min() )
+ {
+ for (int i = 0; i < m_data.size(); ++i) { m_data[i] = 0.0; }
+ return;
+ }
+
+ // x mean
+ Real x_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.pos(0) * p.rdata(PIdx::w); });
+
+#if (AMREX_SPACEDIM == 3)
+ // y mean
+ Real y_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.pos(1) * p.rdata(PIdx::w); });
+#endif
+
+ // z mean
+ Real z_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.pos(index_z) * p.rdata(PIdx::w); });
+
+ // ux mean
+ Real ux_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.rdata(PIdx::ux) * p.rdata(PIdx::w); });
+
+ // uy mean
+ Real uy_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.rdata(PIdx::uy) * p.rdata(PIdx::w); });
+
+ // uz mean
+ Real uz_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ { return p.rdata(PIdx::uz) * p.rdata(PIdx::w); });
+
+ // gamma mean
+ Real gm_mean = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real ux = p.rdata(PIdx::ux);
+ Real uy = p.rdata(PIdx::uy);
+ Real uz = p.rdata(PIdx::uz);
+ Real us = ux*ux + uy*uy + uz*uz;
+ return std::sqrt(1.0 + us*inv_c2) * p.rdata(PIdx::w);
+ });
+
+ // reduced sum over mpi ranks
+ ParallelDescriptor::ReduceRealSum(x_mean); x_mean /= w_sum;
+#if (AMREX_SPACEDIM == 3)
+ ParallelDescriptor::ReduceRealSum(y_mean); y_mean /= w_sum;
+#endif
+ ParallelDescriptor::ReduceRealSum(z_mean); z_mean /= w_sum;
+ ParallelDescriptor::ReduceRealSum(ux_mean); ux_mean /= w_sum;
+ ParallelDescriptor::ReduceRealSum(uy_mean); uy_mean /= w_sum;
+ ParallelDescriptor::ReduceRealSum(uz_mean); uz_mean /= w_sum;
+ ParallelDescriptor::ReduceRealSum(gm_mean); gm_mean /= w_sum;
+
+ // x mean square
+ Real x_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(0)-x_mean) * (p.pos(0)-x_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+#if (AMREX_SPACEDIM == 3)
+ // y mean square
+ Real y_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(1)-y_mean) * (p.pos(1)-y_mean);
+ return a * p.rdata(PIdx::w);
+ });
+#endif
+
+ // z mean square
+ Real z_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(index_z)-z_mean) * (p.pos(index_z)-z_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // ux mean square
+ Real ux_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.rdata(PIdx::ux)-ux_mean) *
+ (p.rdata(PIdx::ux)-ux_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // uy mean square
+ Real uy_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.rdata(PIdx::uy)-uy_mean) *
+ (p.rdata(PIdx::uy)-uy_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // uz mean square
+ Real uz_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.rdata(PIdx::uz)-uz_mean) *
+ (p.rdata(PIdx::uz)-uz_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // gamma mean square
+ Real gm_ms = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const ux = p.rdata(PIdx::ux);
+ Real const uy = p.rdata(PIdx::uy);
+ Real const uz = p.rdata(PIdx::uz);
+ Real const us = ux*ux + uy*uy + uz*uz;
+ Real const gm = std::sqrt(1.0 + us*inv_c2);
+ Real const a = (gm - gm_mean) * (gm - gm_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // x times ux
+ Real xux = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(0)-x_mean) * (p.rdata(PIdx::ux)-ux_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+#if (AMREX_SPACEDIM == 3)
+ // y times uy
+ Real yuy = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(1)-y_mean) * (p.rdata(PIdx::uy)-uy_mean);
+ return a * p.rdata(PIdx::w);
+ });
+#endif
+
+ // z times uz
+ Real zuz = ReduceSum( myspc,
+ [=] AMREX_GPU_HOST_DEVICE (const PType& p) -> Real
+ {
+ Real const a = (p.pos(index_z)-z_mean) * (p.rdata(PIdx::uz)-uz_mean);
+ return a * p.rdata(PIdx::w);
+ });
+
+ // reduced sum over mpi ranks
+ ParallelDescriptor::ReduceRealSum
+ ( x_ms, ParallelDescriptor::IOProcessorNumber());
+ x_ms /= w_sum;
+#if (AMREX_SPACEDIM == 3)
+ ParallelDescriptor::ReduceRealSum
+ ( y_ms, ParallelDescriptor::IOProcessorNumber());
+ y_ms /= w_sum;
+#endif
+ ParallelDescriptor::ReduceRealSum
+ ( z_ms, ParallelDescriptor::IOProcessorNumber());
+ z_ms /= w_sum;
+ ParallelDescriptor::ReduceRealSum
+ (ux_ms, ParallelDescriptor::IOProcessorNumber());
+ ux_ms /= w_sum;
+ ParallelDescriptor::ReduceRealSum
+ (uy_ms, ParallelDescriptor::IOProcessorNumber());
+ uy_ms /= w_sum;
+ ParallelDescriptor::ReduceRealSum
+ (uz_ms, ParallelDescriptor::IOProcessorNumber());
+ uz_ms /= w_sum;
+ ParallelDescriptor::ReduceRealSum
+ (gm_ms, ParallelDescriptor::IOProcessorNumber());
+ gm_ms /= w_sum;
+ ParallelDescriptor::ReduceRealSum
+ ( xux, ParallelDescriptor::IOProcessorNumber());
+ xux /= w_sum;
+#if (AMREX_SPACEDIM == 3)
+ ParallelDescriptor::ReduceRealSum
+ ( yuy, ParallelDescriptor::IOProcessorNumber());
+ yuy /= w_sum;
+#endif
+ ParallelDescriptor::ReduceRealSum
+ ( zuz, ParallelDescriptor::IOProcessorNumber());
+ zuz /= w_sum;
+
+ // save data
+#if (AMREX_SPACEDIM == 3)
+ m_data[0] = x_mean;
+ m_data[1] = y_mean;
+ m_data[2] = z_mean;
+ m_data[3] = ux_mean * m;
+ m_data[4] = uy_mean * m;
+ m_data[5] = uz_mean * m;
+ m_data[6] = gm_mean;
+ m_data[7] = std::sqrt(x_ms);
+ m_data[8] = std::sqrt(y_ms);
+ m_data[9] = std::sqrt(z_ms);
+ m_data[10] = std::sqrt(ux_ms * m);
+ m_data[11] = std::sqrt(uy_ms * m);
+ m_data[12] = std::sqrt(uz_ms * m);
+ m_data[13] = std::sqrt(gm_ms);
+ m_data[14] = std::sqrt(std::abs(x_ms*ux_ms-xux*xux)) / PhysConst::c;
+ m_data[15] = std::sqrt(std::abs(y_ms*uy_ms-yuy*yuy)) / PhysConst::c;
+ m_data[16] = std::sqrt(std::abs(z_ms*uz_ms-zuz*zuz)) / PhysConst::c;
+#elif (AMREX_SPACEDIM == 2)
+ m_data[0] = x_mean;
+ m_data[1] = z_mean;
+ m_data[2] = ux_mean * m;
+ m_data[3] = uy_mean * m;
+ m_data[4] = uz_mean * m;
+ m_data[5] = gm_mean;
+ m_data[6] = std::sqrt(x_ms);
+ m_data[7] = std::sqrt(z_ms);
+ m_data[8] = std::sqrt(ux_ms * m);
+ m_data[9] = std::sqrt(uy_ms * m);
+ m_data[10] = std::sqrt(uz_ms * m);
+ m_data[11] = std::sqrt(gm_ms);
+ m_data[12] = std::sqrt(std::abs(x_ms*ux_ms-xux*xux)) / PhysConst::c;
+ m_data[13] = std::sqrt(std::abs(z_ms*uz_ms-zuz*zuz)) / PhysConst::c;
+#endif
+
+ }
+ // end loop over species
+
+}
+// end void BeamRelevant::ComputeDiags