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