WarpX
WarpX_PEC.H
Go to the documentation of this file.
1 #ifndef WARPX_PEC_KERNELS_H_
2 #define WARPX_PEC_KERNELS_H_
3 
4 #include "WarpX.H"
6 
7 #include <AMReX_Array.H>
8 #include <AMReX_Array4.H>
9 #include <AMReX_Config.H>
10 #include <AMReX_Extension.H>
11 #include <AMReX_GpuQualifiers.H>
12 #include <AMReX_IntVect.H>
13 #include <AMReX_REAL.H>
14 
15 #include <AMReX_BaseFwd.H>
16 
17 #include <array>
18 #include <memory>
19 
20 namespace PEC {
21 using namespace amrex;
32  bool is_boundary_PEC (amrex::GpuArray<int, 3> const& fboundary, int dir) {
33  return ( fboundary[dir] == FieldBoundaryType::PEC);
34  }
35 
103  void SetEfieldOnPEC (const int icomp, const amrex::IntVect & dom_lo,
104  const amrex::IntVect &dom_hi,
105  const amrex::IntVect &ijk_vec, const int n,
106  amrex::Array4<amrex::Real> const& Efield,
107  const amrex::IntVect& is_nodal,
108  amrex::GpuArray<int, 3> const& fbndry_lo,
109  amrex::GpuArray<int, 3> const& fbndry_hi )
110  {
111  // Tangential Efield componentes in guard cells set equal and opposite to cells
112  // in the mirror locations across the PEC boundary, whereas normal E-field
113  // components are set equal to values in the mirror locations across the PEC
114  // boundary. Here we just initialize it.
115  amrex::IntVect ijk_mirror = ijk_vec;
116  bool OnPECBoundary = false;
117  bool GuardCell = false;
118  amrex::Real sign = 1._rt;
119  // Loop over all the dimensions
120  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
121  // Loop over sides, iside = 0 (lo), iside = 1 (hi)
122  // Loop over sides, iside = 0 (lo), iside = 1 (hi)
123  for (int iside = 0; iside < 2; ++iside) {
124  const bool isPECBoundary = ( (iside == 0)
125  ? is_boundary_PEC(fbndry_lo, idim)
126  : is_boundary_PEC(fbndry_hi, idim) );
127 #if (defined WARPX_DIM_XZ) || (defined WARPX_DIM_RZ)
128  // For 2D : for icomp==1, (Ey in XZ, Etheta in RZ),
129  // icomp=1 is tangential to both x and z boundaries
130  // The logic below ensures that the flags are set right for 2D
131  const bool is_tangent_to_PEC = ( (icomp == AMREX_SPACEDIM*idim)
132  ? false : true );
133 #elif (defined WARPX_DIM_1D_Z)
134  // For 1D : icomp=0 and icomp=1 (Ex and Ey are tangential to the z boundary)
135  // The logic below ensures that the flags are set right for 1D
136  const bool is_tangent_to_PEC = ( ( icomp == idim+2) ? false : true );
137 #else
138  const bool is_tangent_to_PEC = ( ( icomp == idim) ? false : true );
139 #endif
140  if (isPECBoundary == true) {
141  // guard cell outside the domain by "ig" number cells, in direction, idim
142  const int ig = ( (iside == 0)
143  ? (dom_lo[idim] - ijk_vec[idim])
144  : (ijk_vec[idim] - (dom_hi[idim] + is_nodal[idim]) ) );
145  if (ig == 0) {
146  if (is_tangent_to_PEC == true and is_nodal[idim] == 1) {
147  OnPECBoundary = true;
148  }
149  } else if (ig > 0) {
150  // Find mirror location across PEC boundary
151  ijk_mirror[idim] = ( ( iside == 0)
152  ? (dom_lo[idim] + ig)
153  : (dom_hi[idim] + is_nodal[idim] - ig));
154  GuardCell = true;
155  // tangential components are inverted across PEC boundary
156  if (is_tangent_to_PEC == true) sign *= -1._rt;
157  }
158  } // is PEC boundary
159  } // loop over iside
160  } // loop over dimensions
161  if (OnPECBoundary == true) {
162  // if ijk_vec is on a PEC boundary in any direction, set Etangential to 0.
163  Efield(ijk_vec,n) = 0._rt;
164  } else if (GuardCell == true) {
165  Efield(ijk_vec,n) = sign * Efield(ijk_mirror,n);
166  }
167  }
168 
232  void SetBfieldOnPEC (const int icomp, const amrex::IntVect & dom_lo,
233  const amrex::IntVect & dom_hi,
234  const amrex::IntVect & ijk_vec, const int n,
235  amrex::Array4<amrex::Real> const& Bfield,
236  const amrex::IntVect & is_nodal,
237  amrex::GpuArray<int, 3> const& fbndry_lo,
238  amrex::GpuArray<int, 3> const& fbndry_hi )
239  {
240  amrex::IntVect ijk_mirror = ijk_vec;
241  bool OnPECBoundary = false;
242  bool GuardCell = false;
243  amrex::Real sign = 1._rt;
244  // Loop over all dimensions
245  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
246  // Loop over sides, iside = 0 (lo), iside = 1 (hi)
247  for (int iside = 0; iside < 2; ++iside) {
248  const bool isPECBoundary = ( (iside == 0 )
249  ? is_boundary_PEC(fbndry_lo, idim)
250  : is_boundary_PEC(fbndry_hi, idim) );
251  if (isPECBoundary == true) {
252 #if (defined WARPX_DIM_XZ) || (defined WARPX_DIM_RZ)
253  // For 2D : for icomp==1, (By in XZ, Btheta in RZ),
254  // icomp=1 is not normal to x or z boundary
255  // The logic below ensures that the flags are set right for 2D
256  const bool is_normal_to_PEC = ( (icomp == AMREX_SPACEDIM*idim)
257  ? true : false );
258 #elif (defined WARPX_DIM_1D_Z)
259  // For 1D : icomp=0 and icomp=1 (Bx and By are not normal to the z boundary)
260  // The logic below ensures that the flags are set right for 1D
261  const bool is_normal_to_PEC = ( ( icomp == idim+2) ? true : false );
262 #else
263  const bool is_normal_to_PEC = ( ( icomp == idim) ? true : false );
264 #endif
265  // guard cell outside the domain by "ig" number cells, in direction, idim
266  const int ig = ( (iside == 0)
267  ? (dom_lo[idim] - ijk_vec[idim])
268  : (ijk_vec[idim] - (dom_hi[idim] + is_nodal[idim]) ) );
269  if (ig == 0) {
270  // Only normal component is set to 0
271  if (is_normal_to_PEC == true and is_nodal[idim]==1) {
272  OnPECBoundary = true;
273  }
274  } else if ( ig > 0) {
275  // Mirror location inside the domain by "ig" number of cells
276  // across PEC boundary in direction, idim, and side, iside
277  ijk_mirror[idim] = ( (iside == 0)
278  ? (dom_lo[idim] + ig)
279  : (dom_hi[idim] + is_nodal[idim] - ig));
280  GuardCell = true;
281  // Sign of the normal component in guard cell is inverted
282  if (is_normal_to_PEC == true) sign *= -1._rt;
283  }
284  } // if PEC Boundary
285  } // loop over sides
286  } // loop of dimensions
287 
288  if (OnPECBoundary == true) {
289  // if ijk_vec is on a PEC boundary in any direction, set Bnormal to 0.
290  Bfield(ijk_vec,n) = 0._rt;
291  } else if (GuardCell == true) {
292  // Bnormal and Btangential is set opposite and equal to the value
293  // in the mirror location, respectively.
294  Bfield(ijk_vec,n) = sign * Bfield(ijk_mirror,n);
295  }
296  }
297 
299  bool isAnyBoundaryPEC();
311  void ApplyPECtoEfield ( std::array<amrex::MultiFab*, 3> Efield,
312  const int lev, PatchType patch_type,
313  const bool split_pml_field = false);
323  void ApplyPECtoBfield ( std::array<amrex::MultiFab*, 3> Bfield,
324  const int lev, PatchType patch_type);
325 }
326 
327 #endif // WarpX_PEC_KERNELS_H_
perfect electric conductor (PEC) with E_tangential=0
Definition: WarpXAlgorithmSelection.H:134
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void SetBfieldOnPEC(const int icomp, const amrex::IntVect &dom_lo, const amrex::IntVect &dom_hi, const amrex::IntVect &ijk_vec, const int n, amrex::Array4< amrex::Real > const &Bfield, const amrex::IntVect &is_nodal, amrex::GpuArray< int, 3 > const &fbndry_lo, amrex::GpuArray< int, 3 > const &fbndry_hi)
Sets the magnetic field value normal to the PEC boundary to zero. The tangential (and normal) field v...
Definition: WarpX_PEC.H:232
bool isAnyBoundaryPEC()
Definition: WarpX_PEC.cpp:18
#define AMREX_FORCE_INLINE
#define AMREX_GPU_DEVICE
int n
Definition: run_libensemble_on_warpx.py:67
void ApplyPECtoBfield(std::array< amrex::MultiFab *, 3 > Bfield, const int lev, PatchType patch_type)
Sets the normal component of the magnetic field at the PEC boundary to zero. The guard cell values ar...
Definition: WarpX_PEC.cpp:124
Definition: WarpX_PEC.H:20
PatchType
Definition: WarpX.H:71
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void SetEfieldOnPEC(const int icomp, const amrex::IntVect &dom_lo, const amrex::IntVect &dom_hi, const amrex::IntVect &ijk_vec, const int n, amrex::Array4< amrex::Real > const &Efield, const amrex::IntVect &is_nodal, amrex::GpuArray< int, 3 > const &fbndry_lo, amrex::GpuArray< int, 3 > const &fbndry_hi)
Sets the electric field value tangential to the PEC boundary to zero. The tangential Efield component...
Definition: WarpX_PEC.H:103
void ApplyPECtoEfield(std::array< amrex::MultiFab *, 3 > Efield, const int lev, PatchType patch_type, const bool split_pml_field=false)
Sets the tangential electric field at the PEC boundary to zero. The guard cell values are set equal a...
Definition: WarpX_PEC.cpp:27
AMREX_GPU_DEVICE AMREX_FORCE_INLINE bool is_boundary_PEC(amrex::GpuArray< int, 3 > const &fboundary, int dir)
Determines if the field boundary condition stored in fboundary is PEC in direction, dir, is PEC.
Definition: WarpX_PEC.H:32