diff --git a/Docs/source/usage/parameters.rst b/Docs/source/usage/parameters.rst index 4a8c4be0b5f..a09e57f10a1 100644 --- a/Docs/source/usage/parameters.rst +++ b/Docs/source/usage/parameters.rst @@ -3435,6 +3435,40 @@ Reduced Diagnostics For 1D-Z, :math:`x`-related and :math:`y`-related quantities are not outputted. RZ geometry is not supported yet. +* ``DifferentialLuminosity`` + This type computes the differential luminosity between two species, defined as: + + .. math:: + + \frac{d\mathcal{L}}{d\mathcal{E}^*}(\mathcal{E}^*, t) = \int_0^t dt'\int d\boldsymbol{x}\,d\boldsymbol{p}_1 d\boldsymbol{p}_2\; + \sqrt{ |\boldsymbol{v}_1 - \boldsymbol{v}_2|^2 - |\boldsymbol{v}_1\times\boldsymbol{v}_2|^2/c^2} \\ f_1(\boldsymbol{x}, \boldsymbol{p}_1, t')f_2(\boldsymbol{x}, \boldsymbol{p}_2, t') \delta(\mathcal{E}^* - \mathcal{E}^*(\boldsymbol{p}_1, \boldsymbol{p}_2)) + + where :math:`\mathcal{E}^*(\boldsymbol{p}_1, \boldsymbol{p}_2) = \sqrt{m_1^2c^4 + m_2^2c^4 + 2(m_1 m_2 c^4 + \gamma_1 \gamma_2 - \boldsymbol{p}_1\cdot\boldsymbol{p}_2 c^2)}` is the energy in the center-of-mass frame, + and :math:`f_i` is the distribution function of species :math:`i`. Note that, if :math:`\sigma^*(\mathcal{E}^*)` + is the center-of-mass cross-section of a given collision process, then + :math:`\int d\mathcal{E}^* \frac{d\mathcal{L}}{d\mathcal{E}^*} (\mathcal{E}^*, t)\sigma^*(\mathcal{E}^*)` + gives the total number of collisions of that process (from the beginning of the simulation up until time :math:`t`). + + The differential luminosity is given in units of :math:`\text{m}^{-2}.\text{J}^{-1}`. For collider-relevant WarpX simulations + involving two crossing, high-energy beams of particles, the differential luminosity in :math:`\text{s}^{-1}.\text{m}^{-2}.\text{J}^{-1}` + can be obtained by multiplying the above differential luminosity by the expected repetition rate of the beams. + + In practice, the above expression of the differential luminosity is evaluated over discrete bins in energy :math:`\mathcal{E}^*`, + and by summing over macroparticles. + + * ``.species`` (`list of two strings`) + The names of the two species for which the differential luminosity is computed. + + * ``.bin_number`` (`int` > 0) + The number of bins in energy :math:`\mathcal{E}^*` + + * ``.bin_max`` (`float`, in Joules) + The minimum value of :math:`\mathcal{E}^*` for which the differential luminosity is computed. + + * ``.bin_min`` (`float`, in Joules) + The maximum value of :math:`\mathcal{E}^*` for which the differential luminosity is computed. + * ``.intervals`` (`string`) Using the `Intervals Parser`_ syntax, this string defines the timesteps at which reduced diagnostics are written to file. diff --git a/Examples/Tests/diff_lumi_diag/analysis.py b/Examples/Tests/diff_lumi_diag/analysis.py new file mode 100755 index 00000000000..59378950fa5 --- /dev/null +++ b/Examples/Tests/diff_lumi_diag/analysis.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# This test checks the differential luminosity of the beam-beam interaction +# in the case of two Gaussian beams crossing rigidly at the interaction point. +# The beams have a Gaussian distribution both in energy and in transverse positions. +# In that case, the differential luminosity can be calculated analytically. + +import os +import sys + +import numpy as np +from read_raw_data import read_reduced_diags_histogram +from scipy.constants import eV + +sys.path.insert(1, "../../../../warpx/Regression/Checksum/") +import checksumAPI + +# Extract the differential luminosity from the file +_, _, E_bin, bin_data = read_reduced_diags_histogram( + "./diags/reducedfiles/DifferentialLuminosity_beam1_beam2.txt" +) +dL_dE_sim = bin_data[-1] # Differential luminosity at the end of the simulation + +# Beam parameters +N = 1.2e10 +E_beam = 125e9 * eV +sigma_x = 500e-9 +sigma_y = 10e-9 + +# Compute the analytical differential luminosity for 2 Gaussian beams +sigma_E1 = 0.02 * E_beam +sigma_E2 = 0.03 * E_beam +sigma_E = np.sqrt( + sigma_E1**2 + sigma_E2**2 +) # Expected width of the differential luminosity +dL_dE_th = ( + N**2 + / (2 * (2 * np.pi) ** 1.5 * sigma_x * sigma_y * sigma_E) + * np.exp(-((E_bin - 2 * E_beam) ** 2) / (2 * sigma_E**2)) +) + +# Check that the simulation result and analytical result match +error = abs(dL_dE_sim - dL_dE_th).max() / abs(dL_dE_th).max() +tol = 1e-2 +print("Relative error: ", error) +print("Tolerance: ", tol) +assert error < tol + +# Get name of the test +fn = sys.argv[1] +test_name = os.path.split(os.getcwd())[1] + +# Run checksum regression test +checksumAPI.evaluate_checksum(test_name, fn, rtol=1e-2) diff --git a/Examples/Tests/diff_lumi_diag/inputs b/Examples/Tests/diff_lumi_diag/inputs new file mode 100644 index 00000000000..1424cfd7672 --- /dev/null +++ b/Examples/Tests/diff_lumi_diag/inputs @@ -0,0 +1,127 @@ +################################# +########## MY CONSTANTS ######### +################################# +my_constants.mc2 = m_e*clight*clight +my_constants.GeV = q_e*1.e9 + +# BEAMS +my_constants.beam_energy = 125.*GeV +my_constants.beam_gamma = beam_energy/(mc2) +my_constants.beam_charge = 1.2e10*q_e +my_constants.sigmax = 500e-9 +my_constants.sigmay = 10e-9 +my_constants.sigmaz = 300e-3 +my_constants.muz = -4*sigmaz +my_constants.nmacropart = 2e5 + +# BOX +my_constants.Lx = 8*sigmax +my_constants.Ly = 8*sigmay +my_constants.Lz = 16*sigmaz + +my_constants.nx = 64 +my_constants.ny = 64 +my_constants.nz = 128 + +# TIME +my_constants.T = 0.5*Lz/clight +my_constants.dt = sigmaz/clight/10. + +################################# +####### GENERAL PARAMETERS ###### +################################# +stop_time = T +amr.n_cell = nx ny nz +amr.max_grid_size = 128 +amr.blocking_factor = 2 +amr.max_level = 0 +geometry.dims = 3 +geometry.prob_lo = -0.5*Lx -0.5*Ly -0.5*Lz +geometry.prob_hi = 0.5*Lx 0.5*Ly 0.5*Lz + +################################# +######## BOUNDARY CONDITION ##### +################################# +boundary.field_lo = open open open +boundary.field_hi = open open open +boundary.particle_lo = Absorbing Absorbing Absorbing +boundary.particle_hi = Absorbing Absorbing Absorbing + +################################# +############ NUMERICS ########### +################################# +warpx.do_electrostatic = relativistic +warpx.const_dt = dt +warpx.grid_type = collocated +algo.particle_shape = 3 +algo.load_balance_intervals=100 +algo.particle_pusher = vay +warpx.poisson_solver = fft + +################################# +########### PARTICLES ########### +################################# +particles.species_names = beam1 beam2 + +beam1.species_type = electron +beam1.injection_style = gaussian_beam +beam1.x_rms = sigmax +beam1.y_rms = sigmay +beam1.z_rms = sigmaz +beam1.x_m = 0 +beam1.y_m = 0 +beam1.z_m = muz +beam1.npart = nmacropart +beam1.q_tot = -beam_charge +beam1.z_cut = 4 +beam1.momentum_distribution_type = gaussian +beam1.uz_m = beam_gamma +beam1.uy_m = 0.0 +beam1.ux_m = 0.0 +beam1.ux_th = 0 +beam1.uy_th = 0 +beam1.uz_th = 0.02*beam_gamma +beam1.do_not_deposit = 1 + +beam2.species_type = positron +beam2.injection_style = gaussian_beam +beam2.x_rms = sigmax +beam2.y_rms = sigmay +beam2.z_rms = sigmaz +beam2.x_m = 0 +beam2.y_m = 0 +beam2.z_m = -muz +beam2.npart = nmacropart +beam2.q_tot = beam_charge +beam2.z_cut = 4 +beam2.momentum_distribution_type = gaussian +beam2.uz_m = -beam_gamma +beam2.uy_m = 0.0 +beam2.ux_m = 0.0 +beam2.ux_th = 0 +beam2.uy_th = 0 +beam2.uz_th = 0.03*beam_gamma +beam2.do_not_deposit = 1 + +################################# +######### DIAGNOSTICS ########### +################################# +# FULL +diagnostics.diags_names = diag1 + +diag1.intervals = 1 +diag1.diag_type = Full +diag1.write_species = 1 +diag1.fields_to_plot = rho_beam1 rho_beam2 +diag1.dump_last_timestep = 1 +diag1.species = beam1 beam2 + +# REDUCED +warpx.reduced_diags_names = DifferentialLuminosity_beam1_beam2 + +DifferentialLuminosity_beam1_beam2.type = DifferentialLuminosity +DifferentialLuminosity_beam1_beam2.intervals = 5 +DifferentialLuminosity_beam1_beam2.species = beam1 beam2 +DifferentialLuminosity_beam1_beam2.bin_number = 128 +DifferentialLuminosity_beam1_beam2.bin_max = 2.1*beam_energy +DifferentialLuminosity_beam1_beam2.bin_min = 1.9*beam_energy diff --git a/Regression/Checksum/benchmarks_json/diff_lumi_diag.json b/Regression/Checksum/benchmarks_json/diff_lumi_diag.json new file mode 100644 index 00000000000..5764278a0c0 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/diff_lumi_diag.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "rho_beam1": 656097730.398061, + "rho_beam2": 656073566.2600528 + }, + "beam2": { + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 1.3357156607472946e-11, + "particle_position_x": 0.07980004798883583, + "particle_position_y": 0.0015964156825818534, + "particle_position_z": 240184.81987149065, + "particle_weight": 11997240000.0 + }, + "beam1": { + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 1.3357730733347833e-11, + "particle_position_x": 0.0796200211671279, + "particle_position_y": 0.001592794429510446, + "particle_position_z": 239913.37896451252, + "particle_weight": 11997780000.0 + } +} diff --git a/Regression/WarpX-tests.ini b/Regression/WarpX-tests.ini index f28e3a36151..3e6a896d1c3 100644 --- a/Regression/WarpX-tests.ini +++ b/Regression/WarpX-tests.ini @@ -3866,3 +3866,18 @@ numprocs = 2 useOMP = 1 numthreads = 1 analysisRoutine = Examples/Tests/openbc_poisson_solver/analysis.py + +[diff_lumi_diag] +buildDir = . +inputFile = Examples/Tests/diff_lumi_diag/inputs +runtime_params = warpx.abort_on_warning_threshold = medium +dim = 3 +addToCompileString = USE_OPENPMD=TRUE USE_FFT=TRUE +cmakeSetupOpts = -DWarpX_DIMS=3 -DWarpX_FFT=ON -DWarpX_OPENPMD=ON +restartTest = 0 +useMPI = 1 +numprocs = 2 +useOMP = 1 +numthreads = 1 +analysisRoutine = Examples/Tests/diff_lumi_diag/analysis.py +aux1File = Tools/PostProcessing/read_raw_data.py diff --git a/Source/Diagnostics/ReducedDiags/CMakeLists.txt b/Source/Diagnostics/ReducedDiags/CMakeLists.txt index e63764bc24f..4f0b05f6180 100644 --- a/Source/Diagnostics/ReducedDiags/CMakeLists.txt +++ b/Source/Diagnostics/ReducedDiags/CMakeLists.txt @@ -4,6 +4,7 @@ foreach(D IN LISTS WarpX_DIMS) PRIVATE BeamRelevant.cpp ColliderRelevant.cpp + DifferentialLuminosity.cpp FieldEnergy.cpp FieldProbe.cpp FieldProbeParticleContainer.cpp diff --git a/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.H b/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.H new file mode 100644 index 00000000000..13c1dca55f9 --- /dev/null +++ b/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.H @@ -0,0 +1,62 @@ +/* Copyright 2023 The WarpX Community + * + * This file is part of WarpX. + * + * Authors: Arianna Formenti + * License: BSD-3-Clause-LBNL + */ + +#ifndef WARPX_DIAGNOSTICS_REDUCEDDIAGS_DIFFERENTIALLUMINOSITY_H_ +#define WARPX_DIAGNOSTICS_REDUCEDDIAGS_DIFFERENTIALLUMINOSITY_H_ + +#include "ReducedDiags.H" +#include + +#include +#include +#include + +/** + * This class contains the differential luminosity diagnostics. + */ +class DifferentialLuminosity : public ReducedDiags +{ +public: + + /** + * constructor + * @param[in] rd_name reduced diags names + */ + DifferentialLuminosity(const std::string& rd_name); + + /// name of the two colliding species + std::vector m_beam_name; + + /// number of bins + int m_bin_num; + + /// max and min bin values + amrex::Real m_bin_max; + amrex::Real m_bin_min; + + /// bin size + amrex::Real m_bin_size; + + void ComputeDiags(int step) final; + +private: + /// auxiliary structure to store headers and indices of the reduced diagnostics + struct aux_header_index + { + std::string header; + int idx; + }; + + /// map to store header texts and indices of the reduced diagnostics + std::map m_headers_indices; + + // Array in which to accumulate the luminosity across timesteps + amrex::Gpu::DeviceVector< amrex::Real > d_data; +}; + +#endif // WARPX_DIAGNOSTICS_REDUCEDDIAGS_DIFFERENTIALLUMINOSITY_H_ diff --git a/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.cpp b/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.cpp new file mode 100644 index 00000000000..bace6cf73ce --- /dev/null +++ b/Source/Diagnostics/ReducedDiags/DifferentialLuminosity.cpp @@ -0,0 +1,272 @@ +/* Copyright 2023 The WarpX Community + * + * This file is part of WarpX. + * + * Authors: Arianna Formenti, Yinjian Zhao + * License: BSD-3-Clause-LBNL + */ +#include "DifferentialLuminosity.H" + +#include "Diagnostics/ReducedDiags/ReducedDiags.H" +#include "Particles/MultiParticleContainer.H" +#include "Particles/Pusher/GetAndSetPosition.H" +#include "Particles/SpeciesPhysicalProperties.H" +#include "Particles/WarpXParticleContainer.H" +#include "Utils/ParticleUtils.H" +#include "Utils/Parser/ParserUtils.H" +#include "Utils/WarpXConst.H" +#include "Utils/TextMsg.H" +#include "Utils/WarpXProfilerWrapper.H" +#include "WarpX.H" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using ParticleType = WarpXParticleContainer::ParticleType; +using ParticleTileType = WarpXParticleContainer::ParticleTileType; +using ParticleTileDataType = ParticleTileType::ParticleTileDataType; +using ParticleBins = amrex::DenseBins; +using index_type = ParticleBins::index_type; + +using namespace amrex; + +DifferentialLuminosity::DifferentialLuminosity (const std::string& rd_name) +: ReducedDiags{rd_name} +{ + // read colliding species names - must be 2 + const amrex::ParmParse pp_rd_name(m_rd_name); + pp_rd_name.getarr("species", m_beam_name); + + WARPX_ALWAYS_ASSERT_WITH_MESSAGE( + m_beam_name.size() == 2u, + "DifferentialLuminosity diagnostics must involve exactly two species"); + + // RZ coordinate is not supported +#if (defined WARPX_DIM_RZ) + WARPX_ABORT_WITH_MESSAGE( + "DifferentialLuminosity diagnostics do not work in RZ geometry."); +#endif + + // read bin parameters + int bin_num = 0; + amrex::Real bin_max = 0.0_rt, bin_min = 0.0_rt; + utils::parser::getWithParser(pp_rd_name, "bin_number", bin_num); + utils::parser::getWithParser(pp_rd_name, "bin_max", bin_max); + utils::parser::getWithParser(pp_rd_name, "bin_min", bin_min); + m_bin_num = bin_num; + m_bin_max = bin_max; + m_bin_min = bin_min; + m_bin_size = (bin_max - bin_min) / bin_num; + + // resize and zero-out data array + m_data.resize(m_bin_num,0.0_rt); + d_data.resize(m_bin_num,0.0_rt); + + if (amrex::ParallelDescriptor::IOProcessor()) + { + if ( m_write_header ) + { + // open file + std::ofstream ofs; + ofs.open(m_path + m_rd_name + "." + m_extension, + std::ofstream::out | std::ofstream::app); + // write header row + int off = 0; + ofs << "#"; + ofs << "[" << off++ << "]step()"; + ofs << m_sep; + ofs << "[" << off++ << "]time(s)"; + for (int i = 0; i < m_bin_num; ++i) + { + ofs << m_sep; + ofs << "[" << off++ << "]"; + const Real b = m_bin_min + m_bin_size*(Real(i)+0.5_rt); + ofs << "bin" << 1+i << "=" << b << "(J)"; + } + ofs << std::endl; + // close file + ofs.close(); + } + } +} + +void DifferentialLuminosity::ComputeDiags (int step) +{ +#if defined(WARPX_DIM_RZ) + amrex::ignore_unused(step); +#else + WARPX_PROFILE("DifferentialLuminosity::ComputeDiags"); + + // Since this diagnostic *accumulates* the luminosity in the + // array d_data, we add contributions at *each timestep*, but + // we only write the data to file at intervals specified by the user. + + const Real c2 = PhysConst::c*PhysConst::c; + + // get a reference to WarpX instance + auto& warpx = WarpX::GetInstance(); + const Real dt = warpx.getdt(0); + // get cell volume + Geometry const & geom = warpx.Geom(0); + const Real dV = AMREX_D_TERM(geom.CellSize(0), *geom.CellSize(1), *geom.CellSize(2)); + + // declare local variables + auto const num_bins = m_bin_num; + Real const bin_min = m_bin_min; + Real const bin_size = m_bin_size; + + // get MultiParticleContainer class object + const MultiParticleContainer& mypc = warpx.GetPartContainer(); + + auto& species_1 = mypc.GetParticleContainerFromName(m_beam_name[0]); + auto& species_2 = mypc.GetParticleContainerFromName(m_beam_name[1]); + + const ParticleReal m1 = species_1.getMass(); + const ParticleReal m2 = species_2.getMass(); + + amrex::Real* const AMREX_RESTRICT dptr_data = d_data.dataPtr(); + + // Enable tiling + amrex::MFItInfo info; + if (amrex::Gpu::notInLaunchRegion()) { info.EnableTiling(WarpXParticleContainer::tile_size); } + + int const nlevs = std::max(0, species_1.finestLevel()+1); // species_1 ? + for (int lev = 0; lev < nlevs; ++lev) { +#ifdef AMREX_USE_OMP +#pragma omp parallel if (amrex::Gpu::notInLaunchRegion()) +#endif + + for (amrex::MFIter mfi = species_1.MakeMFIter(lev, info); mfi.isValid(); ++mfi){ + + ParticleTileType& ptile_1 = species_1.ParticlesAt(lev, mfi); + ParticleTileType& ptile_2 = species_2.ParticlesAt(lev, mfi); + + ParticleBins bins_1 = ParticleUtils::findParticlesInEachCell( lev, mfi, ptile_1 ); + ParticleBins bins_2 = ParticleUtils::findParticlesInEachCell( lev, mfi, ptile_2 ); + + // Species + const auto soa_1 = ptile_1.getParticleTileData(); + index_type* AMREX_RESTRICT indices_1 = bins_1.permutationPtr(); + index_type const* AMREX_RESTRICT cell_offsets_1 = bins_1.offsetsPtr(); + + // Particle data in the tile/box + amrex::ParticleReal * const AMREX_RESTRICT w1 = soa_1.m_rdata[PIdx::w]; + amrex::ParticleReal * const AMREX_RESTRICT u1x = soa_1.m_rdata[PIdx::ux]; + amrex::ParticleReal * const AMREX_RESTRICT u1y = soa_1.m_rdata[PIdx::uy]; // v*gamma=p/m + amrex::ParticleReal * const AMREX_RESTRICT u1z = soa_1.m_rdata[PIdx::uz]; + + const auto soa_2 = ptile_2.getParticleTileData(); + index_type* AMREX_RESTRICT indices_2 = bins_2.permutationPtr(); + index_type const* AMREX_RESTRICT cell_offsets_2 = bins_2.offsetsPtr(); + + amrex::ParticleReal * const AMREX_RESTRICT w2 = soa_2.m_rdata[PIdx::w]; + amrex::ParticleReal * const AMREX_RESTRICT u2x = soa_2.m_rdata[PIdx::ux]; + amrex::ParticleReal * const AMREX_RESTRICT u2y = soa_2.m_rdata[PIdx::uy]; + amrex::ParticleReal * const AMREX_RESTRICT u2z = soa_2.m_rdata[PIdx::uz]; + + // Extract low-level data + auto const n_cells = static_cast(bins_1.numBins()); + + // Loop over cells + amrex::ParallelFor( n_cells, + [=] AMREX_GPU_DEVICE (int i_cell) noexcept + { + // The particles from species1 that are in the cell `i_cell` are + // given by the `indices_1[cell_start_1:cell_stop_1]` + index_type const cell_start_1 = cell_offsets_1[i_cell]; + index_type const cell_stop_1 = cell_offsets_1[i_cell+1]; + // Same for species 2 + index_type const cell_start_2 = cell_offsets_2[i_cell]; + index_type const cell_stop_2 = cell_offsets_2[i_cell+1]; + + for(index_type i_1=cell_start_1; i_1=num_bins ) { continue; } // discard if out-of-range + + Real const v1_minus_v2_x = u1x[j_1]/gamma1 - u2x[j_2]/gamma2; + Real const v1_minus_v2_y = u1y[j_1]/gamma1 - u2y[j_2]/gamma2; + Real const v1_minus_v2_z = u1z[j_1]/gamma1 - u2z[j_2]/gamma2; + Real const v1_minus_v2_square = v1_minus_v2_x*v1_minus_v2_x + v1_minus_v2_y*v1_minus_v2_y + v1_minus_v2_z*v1_minus_v2_z; + + Real const u1_cross_u2_x = u1y[j_1]*u2z[j_2] - u1z[j_1]*u2y[j_2]; + Real const u1_cross_u2_y = u1z[j_1]*u2x[j_2] - u1x[j_1]*u2z[j_2]; + Real const u1_cross_u2_z = u1x[j_1]*u2y[j_2] - u1y[j_1]*u2x[j_2]; + + Real const v1_cross_v2_square = (u1_cross_u2_x*u1_cross_u2_x + u1_cross_u2_y*u1_cross_u2_y + u1_cross_u2_z*u1_cross_u2_z) / (gamma1*gamma1*gamma2*gamma2); + + Real const radicand = v1_minus_v2_square - v1_cross_v2_square / c2; + + Real const dL_dEcom = std::sqrt( radicand ) * w1[j_1] * w2[j_2] / dV / bin_size * dt; // m^-2 J^-1 + + amrex::HostDevice::Atomic::Add(&dptr_data[bin], dL_dEcom); + + } // particles species 2 + } // particles species 1 + }); // cells + } // boxes + } // levels + + // Only write to file at intervals specified by the user. + // At these intervals, the data needs to ready on the CPU, + // so we copy it from the GPU to the CPU and reduce across MPI ranks. + if (m_intervals.contains(step+1)) { + // blocking copy from device to host + amrex::Gpu::copy(amrex::Gpu::deviceToHost, + d_data.begin(), d_data.end(), m_data.begin()); + + // reduced sum over mpi ranks + ParallelDescriptor::ReduceRealSum + (m_data.data(), static_cast(m_data.size()), ParallelDescriptor::IOProcessorNumber()); + } + +#endif // not RZ + +} diff --git a/Source/Diagnostics/ReducedDiags/Make.package b/Source/Diagnostics/ReducedDiags/Make.package index a1f08a24da3..e840931f8d3 100644 --- a/Source/Diagnostics/ReducedDiags/Make.package +++ b/Source/Diagnostics/ReducedDiags/Make.package @@ -8,6 +8,7 @@ CEXE_sources += FieldProbeParticleContainer.cpp CEXE_sources += FieldMomentum.cpp CEXE_sources += BeamRelevant.cpp CEXE_sources += ColliderRelevant.cpp +CEXE_sources += DifferentialLuminosity.cpp CEXE_sources += LoadBalanceCosts.cpp CEXE_sources += LoadBalanceEfficiency.cpp CEXE_sources += ParticleHistogram.cpp diff --git a/Source/Diagnostics/ReducedDiags/MultiReducedDiags.cpp b/Source/Diagnostics/ReducedDiags/MultiReducedDiags.cpp index 73e63aeb4d3..25ea87d9f54 100644 --- a/Source/Diagnostics/ReducedDiags/MultiReducedDiags.cpp +++ b/Source/Diagnostics/ReducedDiags/MultiReducedDiags.cpp @@ -9,6 +9,7 @@ #include "BeamRelevant.H" #include "ChargeOnEB.H" #include "ColliderRelevant.H" +#include "DifferentialLuminosity.H" #include "FieldEnergy.H" #include "FieldMaximum.H" #include "FieldProbe.H" @@ -61,6 +62,7 @@ MultiReducedDiags::MultiReducedDiags () {"RhoMaximum", [](CS s){return std::make_unique(s);}}, {"BeamRelevant", [](CS s){return std::make_unique(s);}}, {"ColliderRelevant", [](CS s){return std::make_unique(s);}}, + {"DifferentialLuminosity",[](CS s){return std::make_unique(s);}}, {"LoadBalanceCosts", [](CS s){return std::make_unique(s);}}, {"LoadBalanceEfficiency", [](CS s){return std::make_unique(s);}}, {"ParticleHistogram", [](CS s){return std::make_unique(s);}},