ARTEMIS
RawEFieldReduction.H
Go to the documentation of this file.
1 /* Copyright 2021 Revathi Jambunathan, Saurabh Sawant, Andrew Nonaka
2  *
3  * This file is part of WarpX.
4  *
5  * License: BSD-3-Clause-LBNL
6  */
7 
8 #ifndef WARPX_DIAGNOSTICS_REDUCEDDIAGS_RAWEFIELDREDUCTION_H_
9 #define WARPX_DIAGNOSTICS_REDUCEDDIAGS_RAWEFIELDREDUCTION_H_
10 
11 #include "ReducedDiags.H"
12 #include "WarpX.H"
13 
14 #include <AMReX_Array.H>
15 #include <AMReX_Box.H>
16 #include <AMReX_Config.H>
17 #include <AMReX_FArrayBox.H>
18 #include <AMReX_FabArray.H>
19 #include <AMReX_Geometry.H>
20 #include <AMReX_GpuControl.H>
21 #include <AMReX_GpuQualifiers.H>
22 #include <AMReX_IndexType.H>
23 #include <AMReX_MFIter.H>
24 #include <AMReX_MultiFab.H>
26 #include <AMReX_Parser.H>
27 #include <AMReX_REAL.H>
28 #include <AMReX_RealBox.H>
29 #include <AMReX_Reduce.H>
30 #include <AMReX_Tuple.H>
31 
32 #include <memory>
33 #include <string>
34 #include <type_traits>
35 #include <vector>
36 
38 {
39 public:
40 
45  RawEFieldReduction(std::string rd_name);
46 
53  virtual void ComputeDiags(int step) override final;
54 
55 private:
58  static constexpr int m_nvars = 3;
59  std::unique_ptr<amrex::Parser> m_parser;
60 
61  // Type of reduction (e.g. Maximum, Minimum or Sum)
63  // Type of integration (e.g. volume or surface)
65 #if (AMREX_SPACEDIM==1)
66  // The direction of the surface for surface integration. (e.g. X)
67  int m_surface_normal[1]={0};
68  // Multipliers for Ex surface integral; default value of 1.0
69  std::vector<amrex::Real> m_scaling_factor={1.0};
70 #elif (AMREX_SPACEDIM==2)
71  // The direction of the surface for surface integration. (e.g. X or Z)
72  int m_surface_normal[2]={0,0};
73  // Multipliers for Ex and Ez surface integrals; default values of 1.0
74  std::vector<amrex::Real> m_scaling_factor={1.0,1.0};
75 #else
76  // The direction of the surface for surface integration. (e.g. X, Y, or Z)
77  int m_surface_normal[3]={0,0,0};
78  // Multipliers for Ex, Ey, and Ez surface integrals; default values of 1.0
79  std::vector<amrex::Real> m_scaling_factor={1.0,1.0,1.0};
80 #endif
81 
82 public:
83 
91  template<typename ReduceOp>
93  {
94  using namespace amrex::literals;
95 
96  auto & warpx = WarpX::GetInstance();
97  const auto nLevel = 1;
98  auto reduction_function_parser = m_parser->compile<m_nvars>();
99  int integral_type = m_integral_type;
100  int* surface_normal = &m_surface_normal[0];
101 
102  for (int lev = 0; lev < nLevel; ++lev) {
103  const amrex::MultiFab &Ex = warpx.getEfield(lev,0);
104  const amrex::MultiFab &Ey = warpx.getEfield(lev,1);
105  const amrex::MultiFab &Ez = warpx.getEfield(lev,2);
106 
107  constexpr int index_Ex = 0;
108  constexpr int index_Ey = 1;
109  constexpr int index_Ez = 2;
110  amrex::IntVect Ex_nodalType = Ex.ixType().toIntVect();
111  amrex::IntVect Ey_nodalType = Ey.ixType().toIntVect();
112  amrex::IntVect Ez_nodalType = Ez.ixType().toIntVect();
113 
114  amrex::ReduceOps<ReduceOp> reduceEx_op;
115  amrex::ReduceOps<ReduceOp> reduceEy_op;
116  amrex::ReduceOps<ReduceOp> reduceEz_op;
117  amrex::ReduceData<amrex::Real> reduceEx_data(reduceEx_op);
118  amrex::ReduceData<amrex::Real> reduceEy_data(reduceEy_op);
119  amrex::ReduceData<amrex::Real> reduceEz_data(reduceEz_op);
120 
121  using ReduceTuple = typename decltype(reduceEx_data)::Type;
122 
123  amrex::Geometry const & geom = warpx.Geom(lev);
124  const amrex::RealBox& real_box = geom.ProbDomain();
125  const auto dx = geom.CellSizeArray();
126 
127 #ifdef AMREX_USE_OMP
128 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
129 #endif
130  for ( amrex::MFIter mfi(Ex, false); mfi.isValid(); ++mfi)
131  {
132  const amrex::Box& tx = mfi.tilebox(Ex_nodalType);
133  const amrex::Box& ty = mfi.tilebox(Ey_nodalType);
134  const amrex::Box& tz = mfi.tilebox(Ez_nodalType);
135 
136  const amrex::IntVect lx = tx.smallEnd();
137  const amrex::IntVect hx = tx.bigEnd();
138 
139  const amrex::IntVect ly = ty.smallEnd();
140  const amrex::IntVect hy = ty.bigEnd();
141 
142  const amrex::IntVect lz = tz.smallEnd();
143  const amrex::IntVect hz = tz.bigEnd();
144 
145  const auto& Ex_arr = Ex[mfi].array();
146  const auto& Ey_arr = Ey[mfi].array();
147  const auto& Ez_arr = Ez[mfi].array();
148 
149  reduceEx_op.eval(tx, reduceEx_data,
150  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
151  {
152  // Shift x, y, z position based on index type
153  amrex::Real fac_x = (1._rt - Ex_nodalType[0]) * dx[0] * 0.5_rt;
154  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
155 #if (AMREX_SPACEDIM==1)
156  amrex::Real y = 0._rt;
157  amrex::Real z = 0._rt;
158 #elif (AMREX_SPACEDIM==2)
159  amrex::Real y = 0._rt;
160  amrex::Real fac_z = (1._rt - Ex_nodalType[1]) * dx[1] * 0.5_rt;
161  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
162 #else
163  amrex::Real fac_y = (1._rt - Ex_nodalType[1]) * dx[1] * 0.5_rt;
164  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
165  amrex::Real fac_z = (1._rt - Ex_nodalType[2]) * dx[2] * 0.5_rt;
166  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
167 #endif
168  // we want to weight interior edges by 1
169  // edges that are on faces of the box by 0.5
170  // edges that are on the edges of the box by 0.25
171  amrex::Real weight = 1.0;
172  if (k == lx[2] || k == hx[2]) {
173  weight *= 0.5;
174  }
175  if (j == lx[1] || j == hx[1]) {
176  weight *= 0.5;
177  }
178  return weight*reduction_function_parser(x,y,z)*Ex_arr(i,j,k);
179  });
180  reduceEy_op.eval(ty, reduceEy_data,
181  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
182  {
183  // Shift x, y, z position based on index type
184  amrex::Real fac_x = (1._rt - Ey_nodalType[0]) * dx[0] * 0.5_rt;
185  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
186 #if (AMREX_SPACEDIM==1)
187  amrex::Real y = 0._rt;
188  amrex::Real z = 0._rt;
189 #elif (AMREX_SPACEDIM==2)
190  amrex::Real y = 0._rt;
191  amrex::Real fac_z = (1._rt - Ey_nodalType[1]) * dx[1] * 0.5_rt;
192  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
193 #else
194  amrex::Real fac_y = (1._rt - Ey_nodalType[1]) * dx[1] * 0.5_rt;
195  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
196  amrex::Real fac_z = (1._rt - Ey_nodalType[2]) * dx[2] * 0.5_rt;
197  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
198 #endif
199  // we want to weight interior edges by 1
200  // edges that are on faces of the box by 0.5
201  // edges that are on the edges of the box by 0.25
202  amrex::Real weight = 1.0;
203  if (i == ly[0] || i == hy[0]) {
204  weight *= 0.5;
205  }
206  if (k == ly[2] || k == hy[2]) {
207  weight *= 0.5;
208  }
209  return weight*reduction_function_parser(x,y,z)*Ey_arr(i,j,k);
210  });
211  reduceEz_op.eval(tz, reduceEz_data,
212  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
213  {
214  // Shift x, y, z position based on index type
215  amrex::Real fac_x = (1._rt - Ez_nodalType[0]) * dx[0] * 0.5_rt;
216  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
217 #if (AMREX_SPACEDIM==1)
218  amrex::Real y = 0._rt;
219  amrex::Real z = 0._rt;
220 #elif (AMREX_SPACEDIM==2)
221  amrex::Real y = 0._rt;
222  amrex::Real fac_z = (1._rt - Ez_nodalType[1]) * dx[1] * 0.5_rt;
223  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
224 #else
225  amrex::Real fac_y = (1._rt - Ez_nodalType[1]) * dx[1] * 0.5_rt;
226  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
227  amrex::Real fac_z = (1._rt - Ez_nodalType[2]) * dx[2] * 0.5_rt;
228  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
229 #endif
230  // we want to weight interior edges by 1
231  // edges that are on faces of the box by 0.5
232  // edges that are on the edges of the box by 0.25
233  amrex::Real weight = 1.0;
234  if (i == lz[0] || i == hz[0]) {
235  weight *= 0.5;
236  }
237  if (j == lz[1] || j == hz[1]) {
238  weight *= 0.5;
239  }
240  return weight*reduction_function_parser(x,y,z)*Ez_arr(i,j,k);
241  });
242  }
243 
244  amrex::Real reducedEx_value = amrex::get<0>(reduceEx_data.value());
245  amrex::Real reducedEy_value = amrex::get<0>(reduceEy_data.value());
246  amrex::Real reducedEz_value = amrex::get<0>(reduceEz_data.value());
247 
248  // MPI reduce
250  {
254  }
256  {
260  }
262  {
266 
267  // If reduction operation is an integral, multiply the value by the cell volume
268  // If reduction operation is a surface, multiply the value by the cell face area
269  if (integral_type == 0) {
270 
271 #if (AMREX_SPACEDIM==1)
272  reducedEx_value *= dx[0];
273  reducedEy_value *= dx[0];
274  reducedEz_value *= dx[0];
275 #elif (AMREX_SPACEDIM==2)
276  reducedEx_value *= dx[0]*dx[1];
277  reducedEy_value *= dx[0]*dx[1];
278  reducedEz_value *= dx[0]*dx[1];
279 #else
280  reducedEx_value *= dx[0]*dx[1]*dx[2];
281  reducedEy_value *= dx[0]*dx[1]*dx[2];
282  reducedEz_value *= dx[0]*dx[1]*dx[2];
283 #endif
284  } else {
285 #if (AMREX_SPACEDIM==1)
286  amrex::Real point = surface_normal[0]*1.0;
287  reducedEx_value *= m_scaling_factor[0]*point;
288  reducedEy_value *= point;
289  reducedEz_value *= point;
290 #elif (AMREX_SPACEDIM==2)
291  amrex::Real length = surface_normal[0]*dx[1] + surface_normal[1]*dx[0];
292  reducedEx_value *= m_scaling_factor[0]*length;
293  reducedEy_value *= length;
294  reducedEz_value *= m_scaling_factor[1]*length;
295 #else
296  amrex::Real area = surface_normal[0]*dx[1]*dx[2] + surface_normal[1]*dx[2]*dx[0] + surface_normal[2]*dx[0]*dx[1];
297  reducedEx_value *= m_scaling_factor[0]*area;
298  reducedEy_value *= m_scaling_factor[1]*area;
299  reducedEz_value *= m_scaling_factor[2]*area;
300 #endif
301  }
302  }
303  m_data[index_Ex] = reducedEx_value;
304  m_data[index_Ey] = reducedEy_value;
305  m_data[index_Ez] = reducedEz_value;
306 
307  }
308  }
309 
310 };
311 
312 #endif
#define AMREX_GPU_DEVICE
Definition: RawEFieldReduction.H:38
virtual void ComputeDiags(int step) override final
Definition: RawEFieldReduction.cpp:122
void ComputeRawEFieldReduction()
Definition: RawEFieldReduction.H:92
int m_integral_type
Definition: RawEFieldReduction.H:64
std::vector< amrex::Real > m_scaling_factor
Definition: RawEFieldReduction.H:79
RawEFieldReduction(std::string rd_name)
Definition: RawEFieldReduction.cpp:26
static constexpr int m_nvars
Definition: RawEFieldReduction.H:58
std::unique_ptr< amrex::Parser > m_parser
Definition: RawEFieldReduction.H:59
int m_reduction_type
Definition: RawEFieldReduction.H:62
int m_surface_normal[3]
Definition: RawEFieldReduction.H:77
Definition: ReducedDiags.H:24
std::vector< amrex::Real > m_data
output data
Definition: ReducedDiags.H:46
static WarpX & GetInstance()
Definition: WarpX.cpp:309
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & smallEnd() const &noexcept
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & bigEnd() const &noexcept
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 AMREX_FORCE_INLINE IntVectND< dim > toIntVect() 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
void ReduceRealMin(Vector< std::reference_wrapper< Real > > const &)
void ReduceRealSum(Vector< std::reference_wrapper< Real > > const &)
void ReduceRealMax(Vector< std::reference_wrapper< Real > > const &)
i
Definition: check_interp_points_and_weights.py:174
int dx
Definition: stencil.py:436
value
Definition: updateAMReX.py:141
Definition: NCIGodfreyTables.H:14