WarpX
FieldReduction.H
Go to the documentation of this file.
1 /* Copyright 2021 Neil Zaim
2  *
3  * This file is part of WarpX.
4  *
5  * License: BSD-3-Clause-LBNL
6  */
7 
8 #ifndef WARPX_DIAGNOSTICS_REDUCEDDIAGS_FIELDREDUCTION_H_
9 #define WARPX_DIAGNOSTICS_REDUCEDDIAGS_FIELDREDUCTION_H_
10 
11 #include "ReducedDiags.H"
12 #include "Utils/CoarsenIO.H"
13 #include "WarpX.H"
14 
15 #include <AMReX_Array.H>
16 #include <AMReX_Box.H>
17 #include <AMReX_Config.H>
18 #include <AMReX_FArrayBox.H>
19 #include <AMReX_FabArray.H>
20 #include <AMReX_Geometry.H>
21 #include <AMReX_GpuControl.H>
22 #include <AMReX_GpuQualifiers.H>
23 #include <AMReX_IndexType.H>
24 #include <AMReX_MFIter.H>
25 #include <AMReX_MultiFab.H>
27 #include <AMReX_Parser.H>
28 #include <AMReX_REAL.H>
29 #include <AMReX_RealBox.H>
30 #include <AMReX_Reduce.H>
31 #include <AMReX_Tuple.H>
32 
33 #include <memory>
34 #include <string>
35 #include <type_traits>
36 #include <vector>
37 
38 
45 {
46 public:
47 
52  FieldReduction(std::string rd_name);
53 
60  virtual void ComputeDiags(int step) override final;
61 
62 private:
65  static constexpr int m_nvars = 9;
66  std::unique_ptr<amrex::Parser> m_parser;
67 
68  // Type of reduction (e.g. Maximum, Minimum or Sum)
70 
71 public:
72 
80  template<typename ReduceOp>
82  {
83  using namespace amrex::literals;
84 
85  // get a reference to WarpX instance
86  auto & warpx = WarpX::GetInstance();
87 
88  constexpr int lev = 0; // This reduced diag currently does not work with mesh refinement
89 
90  amrex::Geometry const & geom = warpx.Geom(lev);
91  const amrex::RealBox& real_box = geom.ProbDomain();
92  const auto dx = geom.CellSizeArray();
93 
94  // get MultiFab data
95  const amrex::MultiFab & Ex = warpx.getEfield(lev,0);
96  const amrex::MultiFab & Ey = warpx.getEfield(lev,1);
97  const amrex::MultiFab & Ez = warpx.getEfield(lev,2);
98  const amrex::MultiFab & Bx = warpx.getBfield(lev,0);
99  const amrex::MultiFab & By = warpx.getBfield(lev,1);
100  const amrex::MultiFab & Bz = warpx.getBfield(lev,2);
101 
102  // General preparation of interpolation and reduction operations
103  const amrex::GpuArray<int,3> cellCenteredtype{0,0,0};
104  const amrex::GpuArray<int,3> reduction_coarsening_ratio{1,1,1};
105  constexpr int reduction_comp = 0;
106 
107  amrex::ReduceOps<ReduceOp> reduce_op;
108  amrex::ReduceData<amrex::Real> reduce_data(reduce_op);
109  using ReduceTuple = typename decltype(reduce_data)::Type;
110 
111  // Prepare interpolation of field components to cell center
112  // The arrays below store the index type (staggering) of each MultiFab, with the third
113  // component set to zero in the two-dimensional case.
114  auto Extype = amrex::GpuArray<int,3>{0,0,0};
115  auto Eytype = amrex::GpuArray<int,3>{0,0,0};
116  auto Eztype = amrex::GpuArray<int,3>{0,0,0};
117  auto Bxtype = amrex::GpuArray<int,3>{0,0,0};
118  auto Bytype = amrex::GpuArray<int,3>{0,0,0};
119  auto Bztype = amrex::GpuArray<int,3>{0,0,0};
120  for (int i = 0; i < AMREX_SPACEDIM; ++i){
121  Extype[i] = Ex.ixType()[i];
122  Eytype[i] = Ey.ixType()[i];
123  Eztype[i] = Ez.ixType()[i];
124  Bxtype[i] = Bx.ixType()[i];
125  Bytype[i] = By.ixType()[i];
126  Bztype[i] = Bz.ixType()[i];
127  }
128 
129  // get parser
130  auto reduction_function_parser = m_parser->compile<m_nvars>();
131 
132  // MFIter loop to interpolate fields to cell center and perform reduction
133 #ifdef AMREX_USE_OMP
134 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
135 #endif
136  for ( amrex::MFIter mfi(Ex, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
137  {
138  // Make the box cell centered in preparation for the interpolation (and to avoid
139  // including ghost cells in the calculation)
140  const amrex::Box& box = enclosedCells(mfi.nodaltilebox());
141  const auto& arrEx = Ex[mfi].array();
142  const auto& arrEy = Ey[mfi].array();
143  const auto& arrEz = Ez[mfi].array();
144  const auto& arrBx = Bx[mfi].array();
145  const auto& arrBy = By[mfi].array();
146  const auto& arrBz = Bz[mfi].array();
147 
148  reduce_op.eval(box, reduce_data,
149  [=] AMREX_GPU_DEVICE (int i, int j, int k) -> ReduceTuple
150  {
151  // 0.5 is here because position are computed on the cell centers
152  const amrex::Real x = (i + 0.5_rt)*dx[0] + real_box.lo(0);
153 #if defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
154  const amrex::Real y = 0._rt;
155  const amrex::Real z = (j + 0.5_rt)*dx[1] + real_box.lo(1);
156 #else
157  const amrex::Real y = (j + 0.5_rt)*dx[1] + real_box.lo(1);
158  const amrex::Real z = (k + 0.5_rt)*dx[2] + real_box.lo(2);
159 #endif
160  const amrex::Real Ex_interp = CoarsenIO::Interp(arrEx, Extype, cellCenteredtype,
161  reduction_coarsening_ratio, i, j, k, reduction_comp);
162  const amrex::Real Ey_interp = CoarsenIO::Interp(arrEy, Eytype, cellCenteredtype,
163  reduction_coarsening_ratio, i, j, k, reduction_comp);
164  const amrex::Real Ez_interp = CoarsenIO::Interp(arrEz, Eztype, cellCenteredtype,
165  reduction_coarsening_ratio, i, j, k, reduction_comp);
166  const amrex::Real Bx_interp = CoarsenIO::Interp(arrBx, Bxtype, cellCenteredtype,
167  reduction_coarsening_ratio, i, j, k, reduction_comp);
168  const amrex::Real By_interp = CoarsenIO::Interp(arrBy, Bytype, cellCenteredtype,
169  reduction_coarsening_ratio, i, j, k, reduction_comp);
170  const amrex::Real Bz_interp = CoarsenIO::Interp(arrBz, Bztype, cellCenteredtype,
171  reduction_coarsening_ratio, i, j, k, reduction_comp);
172  return reduction_function_parser(x, y, z, Ex_interp, Ey_interp, Ez_interp,
173  Bx_interp, By_interp, Bz_interp);
174  });
175  }
176 
177  amrex::Real reduce_value = amrex::get<0>(reduce_data.value());
178 
179  // MPI reduce
181  {
183  }
185  {
187  }
189  {
191  // If reduction operation is a sum, multiply the value by the cell volume so that the
192  // result is the integral of the function over the simulation domain.
193 #if defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
194  reduce_value *= dx[0]*dx[1];
195 #else
196  reduce_value *= dx[0]*dx[1]*dx[2];
197 #endif
198  }
199 
200  // Fill output array
201  m_data[0] = reduce_value;
202 
203  // m_data now contains an up-to-date value of the reduced field quantity
204  }
205 
206 };
207 
208 #endif // WARPX_DIAGNOSTICS_REDUCEDDIAGS_FIELDREDUCTION_H_
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Box enclosedCells(const Box &b, int dir) noexcept
Array4< typename FabArray< FArrayBox >::value_type const > array(const MFIter &mfi) const noexcept
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
GpuArray< Real, AMREX_SPACEDIM > CellSizeArray() const noexcept
ParserExecutor< N > compile() const
std::vector< amrex::Real > m_data
output data
Definition: ReducedDiags.H:46
def x
Definition: read_lab_particles.py:26
Definition: ReducedDiags.H:23
int dx
Definition: compute_domain.py:35
static constexpr int m_nvars
Definition: FieldReduction.H:65
void ReduceRealMin(Vector< std::reference_wrapper< Real > > &&)
int m_reduction_type
Definition: FieldReduction.H:69
def z
Definition: read_lab_particles.py:27
Definition: FieldReduction.H:44
void ComputeFieldReduction()
Definition: FieldReduction.H:81
#define AMREX_GPU_DEVICE
i
Definition: check_interp_points_and_weights.py:173
void ReduceRealMax(Vector< std::reference_wrapper< Real > > &&)
FieldReduction(std::string rd_name)
Definition: FieldReduction.cpp:25
const RealBox & ProbDomain() const noexcept
static WarpX & GetInstance()
Definition: WarpX.cpp:215
AMREX_GPU_DEVICE AMREX_FORCE_INLINE Real Interp(Array4< Real const > const &arr_src, GpuArray< int, 3 > const &sf, GpuArray< int, 3 > const &sc, GpuArray< int, 3 > const &cr, const int i, const int j, const int k, const int comp)
Interpolates the floating point data contained in the source Array4 arr_src, extracted from a fine Mu...
Definition: CoarsenIO.H:38
virtual void ComputeDiags(int step) override final
Definition: FieldReduction.cpp:89
bool TilingIfNotGPU() noexcept
void ReduceRealSum(Vector< std::reference_wrapper< Real > > &&)
Definition: NCIGodfreyTables.H:13
const AMREX_GPU_HOST_DEVICE Real * lo() const &noexcept
value
Definition: updateAMReX.py:141
std::unique_ptr< amrex::Parser > m_parser
Definition: FieldReduction.H:66