ARTEMIS
RawBFieldReduction.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_RAWBFIELDREDUCTION_H_
9 #define WARPX_DIAGNOSTICS_REDUCEDDIAGS_RAWBFIELDREDUCTION_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  RawBFieldReduction(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 Bx 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 Bx and Bz surface integrals; default 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 Bx, By, and Bz surface integrals; default 1.0
79  std::vector<amrex::Real> m_scaling_factor={1.0,1.0,1.0};
80 #endif
81 public:
82 
90  template<typename ReduceOp>
92  {
93  using namespace amrex::literals;
94 
95  auto & warpx = WarpX::GetInstance();
96  const auto nLevel = 1;
97  auto reduction_function_parser = m_parser->compile<m_nvars>();
98  int integral_type = m_integral_type;
99  int* surface_normal = &m_surface_normal[0];
100 
101  for (int lev = 0; lev < nLevel; ++lev) {
102  const amrex::MultiFab &Bx = warpx.getBfield(lev,0);
103  const amrex::MultiFab &By = warpx.getBfield(lev,1);
104  const amrex::MultiFab &Bz = warpx.getBfield(lev,2);
105 
106  constexpr int index_Bx = 0;
107  constexpr int index_By = 1;
108  constexpr int index_Bz = 2;
109  amrex::IntVect Bx_nodalType = Bx.ixType().toIntVect();
110  amrex::IntVect By_nodalType = By.ixType().toIntVect();
111  amrex::IntVect Bz_nodalType = Bz.ixType().toIntVect();
112 
113  amrex::ReduceOps<ReduceOp> reduceBx_op;
114  amrex::ReduceOps<ReduceOp> reduceBy_op;
115  amrex::ReduceOps<ReduceOp> reduceBz_op;
116  amrex::ReduceData<amrex::Real> reduceBx_data(reduceBx_op);
117  amrex::ReduceData<amrex::Real> reduceBy_data(reduceBy_op);
118  amrex::ReduceData<amrex::Real> reduceBz_data(reduceBz_op);
119 
120  using ReduceTuple = typename decltype(reduceBx_data)::Type;
121 
122  amrex::Geometry const & geom = warpx.Geom(lev);
123  const amrex::RealBox& real_box = geom.ProbDomain();
124  const auto dx = geom.CellSizeArray();
125 
126 #ifdef AMREX_USE_OMP
127 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
128 #endif
129  for ( amrex::MFIter mfi(Bx, false); mfi.isValid(); ++mfi)
130  {
131  const amrex::Box& tx = mfi.tilebox(Bx_nodalType);
132  const amrex::Box& ty = mfi.tilebox(By_nodalType);
133  const amrex::Box& tz = mfi.tilebox(Bz_nodalType);
134 
135  const amrex::IntVect lx = tx.smallEnd();
136  const amrex::IntVect hx = tx.bigEnd();
137 
138  const amrex::IntVect ly = ty.smallEnd();
139  const amrex::IntVect hy = ty.bigEnd();
140 
141  const amrex::IntVect lz = tz.smallEnd();
142  const amrex::IntVect hz = tz.bigEnd();
143 
144  const auto& Bx_arr = Bx[mfi].array();
145  const auto& By_arr = By[mfi].array();
146  const auto& Bz_arr = Bz[mfi].array();
147 
148  reduceBx_op.eval(tx, reduceBx_data,
149  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
150  {
151  // Shift x, y, z position based on index type
152  amrex::Real fac_x = (1._rt - Bx_nodalType[0]) * dx[0] * 0.5_rt;
153  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
154 #if (AMREX_SPACEDIM==1)
155  amrex::Real y = 0._rt;
156  amrex::Real z = 0._rt;
157 #elif (AMREX_SPACEDIM==2)
158  amrex::Real y = 0._rt;
159  amrex::Real fac_z = (1._rt - Bx_nodalType[1]) * dx[1] * 0.5_rt;
160  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
161 #else
162  amrex::Real fac_y = (1._rt - Bx_nodalType[1]) * dx[1] * 0.5_rt;
163  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
164  amrex::Real fac_z = (1._rt - Bx_nodalType[2]) * dx[2] * 0.5_rt;
165  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
166 #endif
167  // We want to weight interior faces by 1
168  // and faces that are on the faces of the box by 0.5
169  // Faces for Bx computation can lie on xmin and xmax box faces.
170  amrex::Real weight = 1.0;
171  if (i == lx[0] || i == hx[0]) {
172  weight *= 0.5;
173  }
174  return weight*reduction_function_parser(x,y,z)*Bx_arr(i,j,k);
175  });
176  reduceBy_op.eval(ty, reduceBy_data,
177  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
178  {
179  // Shift x, y, z position based on index type
180  amrex::Real fac_x = (1._rt - By_nodalType[0]) * dx[0] * 0.5_rt;
181  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
182 #if (AMREX_SPACEDIM==1)
183  amrex::Real y = 0._rt;
184  amrex::Real z = 0._rt;
185 #elif (AMREX_SPACEDIM==2)
186  amrex::Real y = 0._rt;
187  amrex::Real fac_z = (1._rt - By_nodalType[1]) * dx[1] * 0.5_rt;
188  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
189 #else
190  amrex::Real fac_y = (1._rt - By_nodalType[1]) * dx[1] * 0.5_rt;
191  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
192  amrex::Real fac_z = (1._rt - By_nodalType[2]) * dx[2] * 0.5_rt;
193  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
194 #endif
195  // We want to weight interior faces by 1
196  // and faces that are on the faces of the box by 0.5
197  // Faces for By computation can lie on ymin and ymax box faces.
198  amrex::Real weight = 1.0;
199  if (j == ly[1] || j == hy[1]) {
200  weight *= 0.5;
201  }
202  return weight*reduction_function_parser(x,y,z)*By_arr(i,j,k);
203  });
204  reduceBz_op.eval(tz, reduceBz_data,
205  [=] AMREX_GPU_DEVICE (int i, int j, int k) ->ReduceTuple
206  {
207  // Shift x, y, z position based on index type
208  amrex::Real fac_x = (1._rt - Bz_nodalType[0]) * dx[0] * 0.5_rt;
209  amrex::Real x = i * dx[0] + real_box.lo(0) + fac_x;
210 #if (AMREX_SPACEDIM==1)
211  amrex::Real y = 0._rt;
212  amrex::Real z = 0._rt;
213 #elif (AMREX_SPACEDIM==2)
214  amrex::Real y = 0._rt;
215  amrex::Real fac_z = (1._rt - Bz_nodalType[1]) * dx[1] * 0.5_rt;
216  amrex::Real z = j * dx[1] + real_box.lo(1) + fac_z;
217 #else
218  amrex::Real fac_y = (1._rt - Bz_nodalType[1]) * dx[1] * 0.5_rt;
219  amrex::Real y = j * dx[1] + real_box.lo(1) + fac_y;
220  amrex::Real fac_z = (1._rt - Bz_nodalType[2]) * dx[2] * 0.5_rt;
221  amrex::Real z = k * dx[2] + real_box.lo(2) + fac_z;
222 #endif
223  // We want to weight interior faces by 1
224  // and faces that are on the faces of the box by 0.5
225  // Faces for Bz computation can lie on zmin and zmax box faces.
226  amrex::Real weight = 1.0;
227  if (k == lz[2] || k == hz[2]) {
228  weight *= 0.5;
229  }
230  return weight*reduction_function_parser(x,y,z)*Bz_arr(i,j,k);
231  });
232  }
233 
234  amrex::Real reducedBx_value = amrex::get<0>(reduceBx_data.value());
235  amrex::Real reducedBy_value = amrex::get<0>(reduceBy_data.value());
236  amrex::Real reducedBz_value = amrex::get<0>(reduceBz_data.value());
237 
238  // MPI reduce
240  {
244  }
246  {
250  }
252  {
256 
257  // If reduction operation is an integral, multiply the value by the cell volume
258  // If reduction operation is a surface, multiply the value by the cell face area
259  if (integral_type == 0) {
260 
261 #if (AMREX_SPACEDIM==1)
262  amrex::Real length = dx[0];
263  reducedBx_value *= length;
264  reducedBy_value *= length;
265  reducedBz_value *= length;
266 #elif (AMREX_SPACEDIM==2)
267  amrex::Real area = dx[0]*dx[1];
268  reducedBx_value *= area;
269  reducedBy_value *= area;
270  reducedBz_value *= area;
271 #else
272  amrex::Real volume = dx[0]*dx[1]*dx[2];
273  reducedBx_value *= volume;
274  reducedBy_value *= volume;
275  reducedBz_value *= volume;
276 #endif
277  } else {
278 #if (AMREX_SPACEDIM==1)
279  amrex::Real point = surface_normal[0]*1.0;
280  reducedBx_value *= m_scaling_factor[0]*point;
281  reducedBy_value *= point;
282  reducedBz_value *= point;
283 #elif (AMREX_SPACEDIM==2)
284  amrex::Real length = surface_normal[0]*dx[1] + surface_normal[1]*dx[0];
285  reducedBx_value *= m_scaling_factor[0]*length;
286  reducedBy_value *= length;
287  reducedBz_value *= m_scaling_factor[1]*length;
288 #else
289  amrex::Real area = surface_normal[0]*dx[1]*dx[2] + surface_normal[1]*dx[2]*dx[0] + surface_normal[2]*dx[0]*dx[1];
290  reducedBx_value *= m_scaling_factor[0]*area;
291  reducedBy_value *= m_scaling_factor[1]*area;
292  reducedBz_value *= m_scaling_factor[2]*area;
293 #endif
294  }
295  }
296  m_data[index_Bx] = reducedBx_value;
297  m_data[index_By] = reducedBy_value;
298  m_data[index_Bz] = reducedBz_value;
299 
300  }
301  }
302 
303 };
304 
305 #endif
#define AMREX_GPU_DEVICE
Definition: RawBFieldReduction.H:38
void ComputeRawBFieldReduction()
Definition: RawBFieldReduction.H:91
std::unique_ptr< amrex::Parser > m_parser
Definition: RawBFieldReduction.H:59
int m_surface_normal[3]
Definition: RawBFieldReduction.H:77
static constexpr int m_nvars
Definition: RawBFieldReduction.H:58
RawBFieldReduction(std::string rd_name)
Definition: RawBFieldReduction.cpp:26
int m_reduction_type
Definition: RawBFieldReduction.H:62
int m_integral_type
Definition: RawBFieldReduction.H:64
virtual void ComputeDiags(int step) override final
Definition: RawBFieldReduction.cpp:122
std::vector< amrex::Real > m_scaling_factor
Definition: RawBFieldReduction.H:79
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