WarpX
Loading...
Searching...
No Matches
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 "Fields.H"
13#include "WarpX.H"
14
16
17#include <AMReX_Array.H>
18#include <AMReX_Box.H>
19#include <AMReX_Config.H>
20#include <AMReX_FArrayBox.H>
21#include <AMReX_FabArray.H>
22#include <AMReX_Geometry.H>
23#include <AMReX_GpuControl.H>
24#include <AMReX_GpuQualifiers.H>
25#include <AMReX_IndexType.H>
26#include <AMReX_MFIter.H>
27#include <AMReX_MultiFab.H>
29#include <AMReX_Parser.H>
30#include <AMReX_REAL.H>
31#include <AMReX_RealBox.H>
32#include <AMReX_Reduce.H>
33#include <AMReX_Tuple.H>
34
35#include <memory>
36#include <string>
37#include <type_traits>
38#include <vector>
39
46{
47public:
48
53 FieldReduction(const std::string& rd_name);
54
61 void ComputeDiags(int step) final;
62
68
69private:
72 static constexpr int m_nvars = 12;
73 std::unique_ptr<amrex::Parser> m_parser;
74
75 // Type of reduction (e.g. Maximum, Minimum or Sum)
77
78public:
79
87 template<typename ReduceOp>
89 {
91 using namespace amrex::literals;
93
94 // get a reference to WarpX instance
95 auto & warpx = WarpX::GetInstance();
96
97 constexpr int lev = 0; // This reduced diag currently does not work with mesh refinement
98
99 amrex::Geometry const & geom = warpx.Geom(lev);
100 const amrex::RealBox& real_box = geom.ProbDomain();
101 const auto dx = geom.CellSizeArray();
102
103 // get MultiFab data
104 const amrex::MultiFab & Ex = *warpx.m_fields.get(FieldType::Efield_aux, Direction{0}, lev);
105 const amrex::MultiFab & Ey = *warpx.m_fields.get(FieldType::Efield_aux, Direction{1}, lev);
106 const amrex::MultiFab & Ez = *warpx.m_fields.get(FieldType::Efield_aux, Direction{2}, lev);
107 const amrex::MultiFab & Bx = *warpx.m_fields.get(FieldType::Bfield_aux, Direction{0}, lev);
108 const amrex::MultiFab & By = *warpx.m_fields.get(FieldType::Bfield_aux, Direction{1}, lev);
109 const amrex::MultiFab & Bz = *warpx.m_fields.get(FieldType::Bfield_aux, Direction{2}, lev);
110 const amrex::MultiFab & jx = *warpx.m_fields.get(FieldType::current_fp, Direction{0},lev);
111 const amrex::MultiFab & jy = *warpx.m_fields.get(FieldType::current_fp, Direction{1},lev);
112 const amrex::MultiFab & jz = *warpx.m_fields.get(FieldType::current_fp, Direction{2},lev);
113
114
115 // General preparation of interpolation and reduction operations
116 const amrex::GpuArray<int,3> cellCenteredtype{0,0,0};
117 const amrex::GpuArray<int,3> reduction_coarsening_ratio{1,1,1};
118 constexpr int reduction_comp = 0;
119
121 amrex::ReduceData<amrex::Real> reduce_data(reduce_op);
122 using ReduceTuple = typename decltype(reduce_data)::Type;
123
124 // Prepare interpolation of field components to cell center
125 // The arrays below store the index type (staggering) of each MultiFab, with the third
126 // component set to zero in the two-dimensional case.
127 auto Extype = amrex::GpuArray<int,3>{0,0,0};
128 auto Eytype = amrex::GpuArray<int,3>{0,0,0};
129 auto Eztype = amrex::GpuArray<int,3>{0,0,0};
130 auto Bxtype = amrex::GpuArray<int,3>{0,0,0};
131 auto Bytype = amrex::GpuArray<int,3>{0,0,0};
132 auto Bztype = amrex::GpuArray<int,3>{0,0,0};
133 auto jxtype = amrex::GpuArray<int,3>{0,0,0};
134 auto jytype = amrex::GpuArray<int,3>{0,0,0};
135 auto jztype = amrex::GpuArray<int,3>{0,0,0};
136 for (int i = 0; i < AMREX_SPACEDIM; ++i){
137 Extype[i] = Ex.ixType()[i];
138 Eytype[i] = Ey.ixType()[i];
139 Eztype[i] = Ez.ixType()[i];
140 Bxtype[i] = Bx.ixType()[i];
141 Bytype[i] = By.ixType()[i];
142 Bztype[i] = Bz.ixType()[i];
143 jxtype[i] = jx.ixType()[i];
144 jytype[i] = jy.ixType()[i];
145 jztype[i] = jz.ixType()[i];
146
147 }
148
149 // get parser
150 auto reduction_function_parser = m_parser->compile<m_nvars>();
151
152 // MFIter loop to interpolate fields to cell center and perform reduction
153#ifdef AMREX_USE_OMP
154#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
155#endif
156 for ( amrex::MFIter mfi(Ex, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
157 {
158 // Make the box cell centered in preparation for the interpolation (and to avoid
159 // including ghost cells in the calculation)
160 const amrex::Box& box = enclosedCells(mfi.nodaltilebox());
161 const auto& arrEx = Ex[mfi].array();
162 const auto& arrEy = Ey[mfi].array();
163 const auto& arrEz = Ez[mfi].array();
164 const auto& arrBx = Bx[mfi].array();
165 const auto& arrBy = By[mfi].array();
166 const auto& arrBz = Bz[mfi].array();
167 const auto& arrjx = jx[mfi].array();
168 const auto& arrjy = jy[mfi].array();
169 const auto& arrjz = jz[mfi].array();
170
171 reduce_op.eval(box, reduce_data,
172 [=] AMREX_GPU_DEVICE (int i, int j, int k) -> ReduceTuple
173 {
174 // 0.5 is here because position are computed on the cell centers
175
176#if defined(WARPX_DIM_1D_Z)
177 const amrex::Real x = 0._rt;
178 const amrex::Real y = 0._rt;
179 const amrex::Real z = (k + 0.5_rt)*dx[0] + real_box.lo(0);
180#elif defined(WARPX_DIM_RCYLINDER) || defined(WARPX_DIM_RSPHERE)
181 const amrex::Real x = (i + 0.5_rt)*dx[0] + real_box.lo(0);
182 const amrex::Real y = 0._rt;
183 const amrex::Real z = 0._rt;
184#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
185 const amrex::Real x = (i + 0.5_rt)*dx[0] + real_box.lo(0);
186 const amrex::Real y = 0._rt;
187 const amrex::Real z = (j + 0.5_rt)*dx[1] + real_box.lo(1);
188#else
189 const amrex::Real x = (i + 0.5_rt)*dx[0] + real_box.lo(0);
190 const amrex::Real y = (j + 0.5_rt)*dx[1] + real_box.lo(1);
191 const amrex::Real z = (k + 0.5_rt)*dx[2] + real_box.lo(2);
192#endif
193 const amrex::Real Ex_interp = ablastr::coarsen::sample::Interp(arrEx, Extype, cellCenteredtype,
194 reduction_coarsening_ratio, i, j, k, reduction_comp);
195 const amrex::Real Ey_interp = ablastr::coarsen::sample::Interp(arrEy, Eytype, cellCenteredtype,
196 reduction_coarsening_ratio, i, j, k, reduction_comp);
197 const amrex::Real Ez_interp = ablastr::coarsen::sample::Interp(arrEz, Eztype, cellCenteredtype,
198 reduction_coarsening_ratio, i, j, k, reduction_comp);
199 const amrex::Real Bx_interp = ablastr::coarsen::sample::Interp(arrBx, Bxtype, cellCenteredtype,
200 reduction_coarsening_ratio, i, j, k, reduction_comp);
201 const amrex::Real By_interp = ablastr::coarsen::sample::Interp(arrBy, Bytype, cellCenteredtype,
202 reduction_coarsening_ratio, i, j, k, reduction_comp);
203 const amrex::Real Bz_interp = ablastr::coarsen::sample::Interp(arrBz, Bztype, cellCenteredtype,
204 reduction_coarsening_ratio, i, j, k, reduction_comp);
205 const amrex::Real jx_interp = ablastr::coarsen::sample::Interp(arrjx, jxtype, cellCenteredtype,
206 reduction_coarsening_ratio, i, j, k, reduction_comp);
207 const amrex::Real jy_interp = ablastr::coarsen::sample::Interp(arrjy, jytype, cellCenteredtype,
208 reduction_coarsening_ratio, i, j, k, reduction_comp);
209 const amrex::Real jz_interp = ablastr::coarsen::sample::Interp(arrjz, jztype, cellCenteredtype,
210 reduction_coarsening_ratio, i, j, k, reduction_comp);
211
212 return reduction_function_parser(x, y, z, Ex_interp, Ey_interp, Ez_interp,
213 Bx_interp, By_interp, Bz_interp,
214 jx_interp, jy_interp, jz_interp);
215 });
216 }
217
218 amrex::Real reduce_value = amrex::get<0>(reduce_data.value());
219
220 // MPI reduce
221 if (std::is_same_v<ReduceOp, amrex::ReduceOpMax>)
222 {
224 }
225 if (std::is_same_v<ReduceOp, amrex::ReduceOpMin>)
226 {
228 }
229 if (std::is_same_v<ReduceOp, amrex::ReduceOpSum>)
230 {
232 // If reduction operation is a sum, multiply the value by the cell volume so that the
233 // result is the integral of the function over the simulation domain.
234 reduce_value *= AMREX_D_TERM(dx[0], *dx[1], *dx[2]);
235 }
236
237 // Fill output array
238 m_data[0] = reduce_value;
239
240 // m_data now contains an up-to-date value of the reduced field quantity
241 }
242
243};
244
245#endif // WARPX_DIAGNOSTICS_REDUCEDDIAGS_FIELDREDUCTION_H_
#define AMREX_GPU_DEVICE
#define AMREX_D_TERM(a, b, c)
ReductionType
Definition WarpXAlgorithmSelection.H:159
Definition MultiFabRegister.H:71
static constexpr int m_nvars
Definition FieldReduction.H:72
FieldReduction(const std::string &rd_name)
Definition FieldReduction.cpp:25
void BackwardCompatibility()
Definition FieldReduction.cpp:88
ReductionType m_reduction_type
Definition FieldReduction.H:76
void ComputeFieldReduction()
Definition FieldReduction.H:88
void ComputeDiags(int step) final
Definition FieldReduction.cpp:101
std::unique_ptr< amrex::Parser > m_parser
Definition FieldReduction.H:73
ReducedDiags(const std::string &rd_name)
Definition ReducedDiags.cpp:26
std::vector< amrex::Real > m_data
output data
Definition ReducedDiags.H:49
static WarpX & GetInstance()
Definition WarpX.cpp:298
Definition MultiFabRegister.H:71
GpuArray< Real, 3 > 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
__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)
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:49
void ReduceRealMin(Vector< std::reference_wrapper< Real > > const &)
void ReduceRealSum(Vector< std::reference_wrapper< Real > > const &)
void ReduceRealMax(Vector< std::reference_wrapper< Real > > const &)
__host__ __device__ constexpr GpuTupleElement< I, GpuTuple< Ts... > >::type & get(GpuTuple< Ts... > &tup) noexcept
BoxND< 3 > Box
bool TilingIfNotGPU() noexcept
FieldType
Definition Fields.H:94
Definition FieldBoundaries.cpp:18