Hipace
FieldGather.H
Go to the documentation of this file.
1 /* Copyright 2020-2022
2  *
3  * This file is part of HiPACE++.
4  *
5  * Authors: AlexanderSinn, MaxThevenet, Severin Diederichs
6  * License: BSD-3-Clause-LBNL
7  */
8 /* Copyright 2019 Axel Huebl, David Grote, Maxence Thevenet
9  * Revathi Jambunathan, Weiqun Zhang
10  *
11  * This file is part of WarpX.
12  *
13  * License: BSD-3-Clause-LBNL
14  */
15 #ifndef FIELDGATHER_H_
16 #define FIELDGATHER_H_
17 
19 #include "utils/GPUUtil.H"
20 #include <AMReX.H>
21 
45 template <int depos_order_xy>
47 void doGatherShapeN (const amrex::Real xp,
48  const amrex::Real yp,
49  amrex::Real& ExmByp,
50  amrex::Real& EypBxp,
51  amrex::Real& Ezp,
52  amrex::Real& Bxp,
53  amrex::Real& Byp,
54  amrex::Real& Bzp,
55  Array3<amrex::Real const> const& slice_arr,
56  const int psi_comp,
57  const int ez_comp,
58  const int bx_comp,
59  const int by_comp,
60  const int bz_comp,
61  const amrex::Real dx_inv,
62  const amrex::Real dy_inv,
63  const amrex::Real x_pos_offset,
64  const amrex::Real y_pos_offset)
65 {
66  // x,y direction
67  const amrex::Real x = (xp-x_pos_offset)*dx_inv;
68  const amrex::Real y = (yp-y_pos_offset)*dy_inv;
69 
70  constexpr int derivative_type = 1;
71 
72  // Gather field on particle from field on grid
73 #ifdef AMREX_USE_GPU
74 #pragma unroll
75 #endif
76  for (int iy=0; iy<=depos_order_xy+derivative_type; iy++){
77 #ifdef AMREX_USE_GPU
78 #pragma unroll
79 #endif
80  for (int ix=0; ix<=depos_order_xy+derivative_type; ix++){
81 
82  // Compute shape factors
83  auto [shape_y, shape_dy, j] =
84  single_derivative_shape_factor<derivative_type, depos_order_xy>(y, iy);
85  auto [shape_x, shape_dx, i] =
86  single_derivative_shape_factor<derivative_type, depos_order_xy>(x, ix);
87 
88  ExmByp += (shape_dx* shape_y) * slice_arr(i, j, psi_comp) * dx_inv;
89  EypBxp += (shape_x * shape_dy)* slice_arr(i, j, psi_comp) * dy_inv;
90  Ezp += (shape_x * shape_y) * slice_arr(i, j, ez_comp);
91  Bxp += (shape_x * shape_y) * slice_arr(i, j, bx_comp);
92  Byp += (shape_x * shape_y) * slice_arr(i, j, by_comp);
93  Bzp += (shape_x * shape_y) * slice_arr(i, j, bz_comp);
94  }
95  }
96 }
97 
98 
99 
124 void doGatherShapeN (const amrex::ParticleReal xp,
125  const amrex::ParticleReal yp,
126  amrex::ParticleReal& ExmByp,
127  amrex::ParticleReal& EypBxp,
128  amrex::ParticleReal& Ezp,
129  amrex::ParticleReal& Bxp,
130  amrex::ParticleReal& Byp,
131  amrex::ParticleReal& Bzp,
132  Array3<amrex::Real const> const& slice_arr,
133  const int psi_comp,
134  const int ez_comp,
135  const int bx_comp,
136  const int by_comp,
137  const int bz_comp,
138  const amrex::Real dx_inv,
139  const amrex::Real dy_inv,
140  const amrex::Real x_pos_offset,
141  const amrex::Real y_pos_offset,
142  const int depos_order_xy)
143 {
144  if (depos_order_xy == 0) {
145  doGatherShapeN<0>(xp, yp, ExmByp, EypBxp, Ezp, Bxp, Byp, Bzp, slice_arr,
146  psi_comp, ez_comp, bx_comp, by_comp, bz_comp,
147  dx_inv, dy_inv, x_pos_offset, y_pos_offset);
148  } else if (depos_order_xy == 1) {
149  doGatherShapeN<1>(xp, yp, ExmByp, EypBxp, Ezp, Bxp, Byp, Bzp, slice_arr,
150  psi_comp, ez_comp, bx_comp, by_comp, bz_comp,
151  dx_inv, dy_inv, x_pos_offset, y_pos_offset);
152  } else if (depos_order_xy == 2) {
153  doGatherShapeN<2>(xp, yp, ExmByp, EypBxp, Ezp, Bxp, Byp, Bzp, slice_arr,
154  psi_comp, ez_comp, bx_comp, by_comp, bz_comp,
155  dx_inv, dy_inv, x_pos_offset, y_pos_offset);
156  } else if (depos_order_xy == 3) {
157  doGatherShapeN<3>(xp, yp, ExmByp, EypBxp, Ezp, Bxp, Byp, Bzp, slice_arr,
158  psi_comp, ez_comp, bx_comp, by_comp, bz_comp,
159  dx_inv, dy_inv, x_pos_offset, y_pos_offset);
160  }
161 }
162 
163 
164 
181 template <int depos_order_xy>
183 void doBxByGatherShapeN (const amrex::Real xp,
184  const amrex::Real yp,
185  amrex::Real& Bxp,
186  amrex::Real& Byp,
187  Array3<amrex::Real const> const& slice_arr,
188  const int bx_comp,
189  const int by_comp,
190  const amrex::Real dx_inv,
191  const amrex::Real dy_inv,
192  const amrex::Real x_pos_offset,
193  const amrex::Real y_pos_offset)
194 {
195  // x,y direction
196  const amrex::Real x = (xp-x_pos_offset)*dx_inv;
197  const amrex::Real y = (yp-y_pos_offset)*dy_inv;
198 
199  // --- Compute shape factors
200  // x direction
201  // j_cell leftmost cell in x that the particle touches. sx_cell shape factor along x
202  amrex::Real sx_cell[depos_order_xy + 1];
203  const int i_cell = compute_shape_factor<depos_order_xy>(sx_cell, x);
204 
205  // y direction
206  amrex::Real sy_cell[depos_order_xy + 1];
207  const int j_cell = compute_shape_factor<depos_order_xy>(sy_cell, y);
208 
209  // Gather field on particle from field on grid
210  for (int iy=0; iy<=depos_order_xy; iy++){
211  for (int ix=0; ix<=depos_order_xy; ix++){
212  Bxp += sx_cell[ix]*sy_cell[iy] * slice_arr(i_cell+ix, j_cell+iy, bx_comp);
213  Byp += sx_cell[ix]*sy_cell[iy] * slice_arr(i_cell+ix, j_cell+iy, by_comp);
214  }
215  }
216 }
217 
218 
219 
235 template <int depos_order_xy>
237 void doLaserGatherShapeN (const amrex::Real xp,
238  const amrex::Real yp,
239  amrex::Real& Aabssqp,
240  amrex::Real& AabssqDxp,
241  amrex::Real& AabssqDyp,
242  Array3<amrex::Real const> const& a_arr,
243  const amrex::Real dx_inv,
244  const amrex::Real dy_inv,
245  const amrex::Real x_pos_offset,
246  const amrex::Real y_pos_offset)
247 {
248  using namespace amrex::literals;
249 
250  // x,y direction
251  const amrex::Real x = (xp-x_pos_offset)*dx_inv;
252  const amrex::Real y = (yp-y_pos_offset)*dy_inv;
253 
254  // --- Compute shape factors
255  // x direction
256  // j_cell leftmost cell in x that the particle touches. sx_cell shape factor along x
257  amrex::Real sx_cell[depos_order_xy + 1];
258  const int i_cell = compute_shape_factor<depos_order_xy>(sx_cell, x);
259 
260  // y direction
261  amrex::Real sy_cell[depos_order_xy + 1];
262  const int j_cell = compute_shape_factor<depos_order_xy>(sy_cell, y);
263 
264  // Gather field Aabssq, AabssqDxp, and AabssqDxp on particle from field on grid a_arr
265  // the derivative is calculated on the fly
266  for (int iy=0; iy<=depos_order_xy; iy++){
267  for (int ix=0; ix<=depos_order_xy; ix++){
268  const amrex::Real x00y00 = abssq(
269  a_arr(i_cell+ix , j_cell+iy , 0),
270  a_arr(i_cell+ix , j_cell+iy , 1) );
271  const amrex::Real xp1y00 = abssq(
272  a_arr(i_cell+ix+1, j_cell+iy , 0),
273  a_arr(i_cell+ix+1, j_cell+iy , 1) );
274  const amrex::Real xm1y00 = abssq(
275  a_arr(i_cell+ix-1, j_cell+iy , 0),
276  a_arr(i_cell+ix-1, j_cell+iy , 1) );
277  const amrex::Real x00yp1 = abssq(
278  a_arr(i_cell+ix , j_cell+iy+1, 0),
279  a_arr(i_cell+ix , j_cell+iy+1, 1) );
280  const amrex::Real x00ym1 = abssq(
281  a_arr(i_cell+ix , j_cell+iy-1, 0),
282  a_arr(i_cell+ix , j_cell+iy-1, 1) );
283  Aabssqp += sx_cell[ix]*sy_cell[iy]*x00y00;
284  AabssqDxp += sx_cell[ix]*sy_cell[iy]*0.5_rt*dx_inv*(xp1y00-xm1y00);
285  AabssqDyp += sx_cell[ix]*sy_cell[iy]*0.5_rt*dy_inv*(x00yp1-x00ym1);
286  }
287  }
288 }
289 
290 
291 
305 template <int depos_order_xy>
307 void doLaserGatherShapeN (const amrex::Real xp,
308  const amrex::Real yp,
309  amrex::Real& Aabssqp,
310  Array3<amrex::Real const> const& a_arr,
311  const amrex::Real dx_inv,
312  const amrex::Real dy_inv,
313  const amrex::Real x_pos_offset,
314  const amrex::Real y_pos_offset)
315 {
316  // x,y direction
317  const amrex::Real x = (xp-x_pos_offset)*dx_inv;
318  const amrex::Real y = (yp-y_pos_offset)*dy_inv;
319 
320  // --- Compute shape factors
321  // x direction
322  // i_cell leftmost cell in x that the particle touches. sx_cell shape factor along x
323  amrex::Real sx_cell[depos_order_xy + 1];
324  const int i_cell = compute_shape_factor<depos_order_xy>(sx_cell, x);
325 
326  // y direction
327  amrex::Real sy_cell[depos_order_xy + 1];
328  const int j_cell = compute_shape_factor<depos_order_xy>(sy_cell, y);
329 
330  // Gather field Aabssq, on particle from field on grid a_arr
331  for (int iy=0; iy<=depos_order_xy; iy++){
332  for (int ix=0; ix<=depos_order_xy; ix++){
333  const amrex::Real x00y00 = abssq(
334  a_arr(i_cell+ix , j_cell+iy , 0),
335  a_arr(i_cell+ix , j_cell+iy , 1) );
336  Aabssqp += sx_cell[ix]*sy_cell[iy]*x00y00;
337  }
338  }
339 }
340 
342 void doGatherEz (const amrex::Real xp,
343  const amrex::Real yp,
344  amrex::Real& Ezp,
345  Array3<amrex::Real const> const& slice_arr,
346  const int ez_comp,
347  const amrex::Real dx_inv,
348  const amrex::Real dy_inv,
349  const amrex::Real x_pos_offset,
350  const amrex::Real y_pos_offset)
351 {
352  // x,y direction
353  const amrex::Real x = (xp - x_pos_offset) * dx_inv;
354  const amrex::Real y = (yp - y_pos_offset) * dy_inv;
355 
356  // Compute shape factors
357  auto [shape_y, j] = compute_single_shape_factor<false, 0>(y, 0);
358  auto [shape_x, i] = compute_single_shape_factor<false, 0>(x, 0);
359 
360  // Gather Ez on particle from field on grid
361  Ezp += (shape_x * shape_y) * slice_arr(i, j, ez_comp);
362 }
363 
364 #endif // FIELDGATHER_H_
#define AMREX_FORCE_INLINE
#define AMREX_GPU_HOST_DEVICE
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void doLaserGatherShapeN(const amrex::Real xp, const amrex::Real yp, amrex::Real &Aabssqp, amrex::Real &AabssqDxp, amrex::Real &AabssqDyp, Array3< amrex::Real const > const &a_arr, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real x_pos_offset, const amrex::Real y_pos_offset)
Laser field gather for a single particle.
Definition: FieldGather.H:237
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void doBxByGatherShapeN(const amrex::Real xp, const amrex::Real yp, amrex::Real &Bxp, amrex::Real &Byp, Array3< amrex::Real const > const &slice_arr, const int bx_comp, const int by_comp, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real x_pos_offset, const amrex::Real y_pos_offset)
Field gather for a single particle of just Bx and By.
Definition: FieldGather.H:183
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void doGatherEz(const amrex::Real xp, const amrex::Real yp, amrex::Real &Ezp, Array3< amrex::Real const > const &slice_arr, const int ez_comp, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real x_pos_offset, const amrex::Real y_pos_offset)
Definition: FieldGather.H:342
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void doGatherShapeN(const amrex::Real xp, const amrex::Real yp, amrex::Real &ExmByp, amrex::Real &EypBxp, amrex::Real &Ezp, amrex::Real &Bxp, amrex::Real &Byp, amrex::Real &Bzp, Array3< amrex::Real const > const &slice_arr, const int psi_comp, const int ez_comp, const int bx_comp, const int by_comp, const int bz_comp, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real x_pos_offset, const amrex::Real y_pos_offset)
Field gather for a single particle.
Definition: FieldGather.H:47
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real abssq(amrex::Real r, amrex::Real i)
Definition: GPUUtil.H:187
int i
Definition: MakeOpenBoundary.py:152
j
Definition: MakeOpenBoundary.py:128
Definition: GPUUtil.H:98