Block-Structured AMR Software Framework
AMReX_MLNodeTensorLap_2D_K.H
Go to the documentation of this file.
1 #ifndef AMREX_MLNODETENSORLAP_2D_K_H_
2 #define AMREX_MLNODETENSORLAP_2D_K_H_
3 #include <AMReX_Config.H>
4 
5 namespace amrex {
6 
7 namespace mlndts_detail {
8 
10  Real ts_interp_line_x (Array4<Real const> const& crse, int ic, int jc) noexcept
11  {
12  return (crse(ic,jc,0)+crse(ic+1,jc,0))*Real(0.5);
13  }
14 
16  Real ts_interp_line_y (Array4<Real const> const& crse, int ic, int jc) noexcept
17  {
18  return (crse(ic,jc,0)+crse(ic,jc+1,0))*Real(0.5);
19  }
20 
22  Real ts_interp_face_xy (Array4<Real const> const& crse, int ic, int jc) noexcept
23  {
24  return (ts_interp_line_y(crse,ic ,jc ) +
25  ts_interp_line_y(crse,ic+1,jc ) +
26  ts_interp_line_x(crse,ic ,jc ) +
27  ts_interp_line_x(crse,ic ,jc+1)) * Real(0.25);
28  }
29 }
30 
32 void mlndtslap_interpadd (int i, int j, int, Array4<Real> const& fine,
33  Array4<Real const> const& crse, Array4<int const> const& msk) noexcept
34 {
35  using namespace mlndts_detail;
36 
37  if (!msk(i,j,0)) {
38  int ic = amrex::coarsen(i,2);
39  int jc = amrex::coarsen(j,2);
40  bool i_is_odd = (ic*2 != i);
41  bool j_is_odd = (jc*2 != j);
42  if (i_is_odd && j_is_odd) {
43  // Node on a X-Y face
44  fine(i,j,0) += ts_interp_face_xy(crse,ic,jc);
45  } else if (i_is_odd) {
46  // Node on X line
47  fine(i,j,0) += ts_interp_line_x(crse,ic,jc);
48  } else if (j_is_odd) {
49  // Node on Y line
50  fine(i,j,0) += ts_interp_line_y(crse,ic,jc);
51  } else {
52  // Node coincident with coarse node
53  fine(i,j,0) += crse(ic,jc,0);
54  }
55  }
56 }
57 
59 void mlndtslap_semi_interpadd (int i, int j, int, Array4<Real> const& fine,
60  Array4<Real const> const& crse, Array4<int const> const& msk,
61  int semi_dir) noexcept
62 {
63  using namespace mlndts_detail;
64 
65  if (!msk(i,j,0)) {
66  if (semi_dir == 0) {
67  int jc = amrex::coarsen(j,2);
68  bool j_is_odd = (jc*2 != j);
69  if (j_is_odd) {
70  // Node on Y line
71  fine(i,j,0) += ts_interp_line_y(crse,i,jc);
72  } else {
73  // Node coincident with coarse node
74  fine(i,j,0) += crse(i,jc,0);
75  }
76  } else {
77  int ic = amrex::coarsen(i,2);
78  bool i_is_odd = (ic*2 != i);
79  if (i_is_odd) {
80  // Node on X line
81  fine(i,j,0) += ts_interp_line_x(crse,ic,j);
82  } else {
83  // Node coincident with coarse node
84  fine(i,j,0) += crse(ic,j,0);
85  }
86  }
87  }
88 }
89 
91 void mlndtslap_adotx (int i, int j, int k, Array4<Real> const& y, Array4<Real const> const& x,
92  Array4<int const> const& msk, GpuArray<Real,3> const& s) noexcept
93 {
94  if (msk(i,j,k)) {
95  y(i,j,k) = Real(0.0);
96  } else {
97  y(i,j,k) = s[0] * (x(i-1,j,0) + x(i+1,j,0))
98  + s[2] * (x(i,j-1,0) + x(i,j+1,0))
99  - Real(2.)*(s[0]+s[2]) * x(i,j,0)
100  + Real(0.5)*s[1] * (x(i-1,j-1,0) + x(i+1,j+1,0) - x(i-1,j+1,0) - x(i+1,j-1,0));
101  }
102 }
103 
105 void mlndtslap_gauss_seidel (int i, int j, int k, Array4<Real> const& sol,
106  Array4<Real const> const& rhs, Array4<int const> const& msk,
107  GpuArray<Real,3> const& s) noexcept
108 {
109  if (msk(i,j,k)) {
110  sol(i,j,k) = 0.0;
111  } else {
112  constexpr Real omega = Real(1.25);
113  Real s0 = Real(-2.)*(s[0]+s[2]);
114  Real Ax = s[0] * (sol(i-1,j,0) + sol(i+1,j,0))
115  + s[2] * (sol(i,j-1,0) + sol(i,j+1,0))
116  + s0 * sol(i,j,0)
117  + Real(0.5)*s[1] * (sol(i-1,j-1,0) + sol(i+1,j+1,0) - sol(i-1,j+1,0) - sol(i+1,j-1,0));
118  sol(i,j,k) += (rhs(i,j,k) - Ax) * (omega/s0);
119  }
120 }
121 
122 #if defined(AMREX_USE_HYPRE) && (AMREX_SPACEDIM > 1)
123 
124 template <typename HypreInt, typename AtomicInt>
125 void mlndtslap_fill_ijmatrix_cpu (Box const& ndbx,
126  Array4<AtomicInt const> const& gid,
127  Array4<int const> const& lid,
128  HypreInt* const ncols, HypreInt* const cols, Real* const mat, // NOLINT(readability-non-const-parameter)
129  GpuArray<Real,3> const& s) noexcept
130 {
131  constexpr auto gidmax = std::numeric_limits<AtomicInt>::max();
132  HypreInt nelems = 0;
133  amrex::LoopOnCpu(ndbx, [&] (int i, int j, int k) noexcept
134  {
135  if (lid(i,j,k) >= 0)
136  {
137  HypreInt nelems_old = nelems;
138 
139  cols[nelems] = gid(i,j,k);
140  mat[nelems] = Real(-2.)*(s[0]+s[2]);
141  ++nelems;
142 
143  if (gid(i-1,j-1,k) < gidmax) {
144  cols[nelems] = gid(i-1,j-1,k);
145  mat[nelems] = Real(0.5)*s[1];
146  ++nelems;
147  }
148 
149  if (gid(i,j-1,k) < gidmax) {
150  cols[nelems] = gid(i,j-1,k);
151  mat[nelems] = s[2];
152  ++nelems;
153  }
154 
155  if (gid(i+1,j-1,k) < gidmax) {
156  cols[nelems] = gid(i+1,j-1,k);
157  mat[nelems] = Real(-0.5)*s[1];
158  ++nelems;
159  }
160 
161  if (gid(i-1,j,k) < gidmax) {
162  cols[nelems] = gid(i-1,j,k);
163  mat[nelems] = s[0];
164  ++nelems;
165  }
166 
167  if (gid(i+1,j,k) < gidmax) {
168  cols[nelems] = gid(i+1,j,k);
169  mat[nelems] = s[0];
170  ++nelems;
171  }
172 
173  if (gid(i-1,j+1,k) < gidmax) {
174  cols[nelems] = gid(i-1,j+1,k);
175  mat[nelems] = Real(-0.5)*s[1];
176  ++nelems;
177  }
178 
179  if (gid(i,j+1,k) < gidmax) {
180  cols[nelems] = gid(i,j+1,k);
181  mat[nelems] = s[2];
182  ++nelems;
183  }
184 
185  if (gid(i+1,j+1,k) < gidmax) {
186  cols[nelems] = gid(i+1,j+1,k);
187  mat[nelems] = Real(0.5)*s[1];
188  ++nelems;
189  }
190 
191  ncols[lid(i,j,k)] = nelems - nelems_old;
192  }
193  });
194 }
195 
196 #ifdef AMREX_USE_GPU
197 template <typename HypreInt, typename AtomicInt>
199 void mlndtslap_fill_ijmatrix_gpu (const int ps, const int i, const int j, const int k,
200  const int offset, Box const& ndbx,
201  Array4<AtomicInt const> const& gid,
202  Array4<int const> const& lid,
203  HypreInt* const ncols, HypreInt* const cols, Real* const mat,
204  GpuArray<Real,3> const& s) noexcept
205 {
206  if (lid(i,j,k) >= 0)
207  {
208  constexpr auto gidmax = std::numeric_limits<AtomicInt>::max();
209 
210  if (offset == 0) {
211  cols[ps] = gid(i,j,k);
212  mat[ps] = Real(-2.)*(s[0]+s[2]);
213  int nc = 1;
214  if (gid(i-1,j-1,k) < gidmax) { ++nc; }
215  if (gid(i ,j-1,k) < gidmax) { ++nc; }
216  if (gid(i+1,j-1,k) < gidmax) { ++nc; }
217  if (gid(i-1,j ,k) < gidmax) { ++nc; }
218  if (gid(i+1,j ,k) < gidmax) { ++nc; }
219  if (gid(i-1,j+1,k) < gidmax) { ++nc; }
220  if (gid(i ,j+1,k) < gidmax) { ++nc; }
221  if (gid(i+1,j+1,k) < gidmax) { ++nc; }
222  ncols[lid(i,j,k)] = nc;
223  }
224  else if (offset == 1 && gid(i-1,j-1,k) < gidmax) {
225  cols[ps] = gid(i-1,j-1,k);
226  mat[ps] = Real(0.5)*s[1];
227  }
228  else if (offset == 2 && gid(i ,j-1,k) < gidmax) {
229  cols[ps] = gid(i ,j-1,k);
230  mat[ps] = s[2];
231  }
232  else if (offset == 3 && gid(i+1,j-1,k) < gidmax) {
233  cols[ps] = gid(i+1,j-1,k);
234  mat[ps] = Real(-0.5)*s[1];
235  }
236  else if (offset == 4 && gid(i-1,j ,k) < gidmax) {
237  cols[ps] = gid(i-1,j ,k);
238  mat[ps] = s[0];
239  }
240  else if (offset == 5 && gid(i+1,j ,k) < gidmax) {
241  cols[ps] = gid(i+1,j ,k);
242  mat[ps] = s[0];
243  }
244  else if (offset == 6 && gid(i-1,j+1,k) < gidmax) {
245  cols[ps] = gid(i-1,j+1,k);
246  mat[ps] = Real(-0.5)*s[1];
247  }
248  else if (offset == 7 && gid(i ,j+1,k) < gidmax) {
249  cols[ps] = gid(i ,j+1,k);
250  mat[ps] = s[2];
251  }
252  else if (offset == 8 && gid(i+1,j+1,k) < gidmax) {
253  cols[ps] = gid(i+1,j+1,k);
254  mat[ps] = Real(0.5)*s[1];
255  }
256  }
257 }
258 #endif
259 
260 #endif
261 
262 }
263 
264 #endif
#define AMREX_FORCE_INLINE
Definition: AMReX_Extension.H:119
#define AMREX_GPU_DEVICE
Definition: AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition: AMReX_GpuQualifiers.H:20
Array4< int const > offset
Definition: AMReX_HypreMLABecLap.cpp:1089
Array4< Real > fine
Definition: AMReX_InterpFaceRegister.cpp:90
Array4< Real const > crse
Definition: AMReX_InterpFaceRegister.cpp:92
@ max
Definition: AMReX_ParallelReduce.H:17
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real ts_interp_line_x(Array4< Real const > const &crse, int ic, int jc) noexcept
Definition: AMReX_MLNodeTensorLap_2D_K.H:10
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real ts_interp_line_y(Array4< Real const > const &crse, int ic, int jc) noexcept
Definition: AMReX_MLNodeTensorLap_2D_K.H:16
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real ts_interp_face_xy(Array4< Real const > const &crse, int ic, int jc) noexcept
Definition: AMReX_MLNodeTensorLap_2D_K.H:22
Definition: AMReX_Amr.cpp:49
AMREX_ATTRIBUTE_FLATTEN_FOR void LoopOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition: AMReX_Loop.H:355
BoxND< AMREX_SPACEDIM > Box
Definition: AMReX_BaseFwd.H:27
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlndtslap_adotx(int i, int j, int k, Array4< Real > const &y, Array4< Real const > const &x, Array4< int const > const &msk, GpuArray< Real, 3 > const &s) noexcept
Definition: AMReX_MLNodeTensorLap_2D_K.H:91
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlndtslap_gauss_seidel(int i, int j, int k, Array4< Real > const &sol, Array4< Real const > const &rhs, Array4< int const > const &msk, GpuArray< Real, 3 > const &s) noexcept
Definition: AMReX_MLNodeTensorLap_2D_K.H:105
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlndtslap_semi_interpadd(int, int, int, Array4< Real > const &, Array4< Real const > const &, Array4< int const > const &, int) noexcept
Definition: AMReX_MLNodeTensorLap_1D_K.H:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlndtslap_interpadd(int, int, int, Array4< Real > const &, Array4< Real const > const &, Array4< int const > const &) noexcept
Definition: AMReX_MLNodeTensorLap_1D_K.H:8
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > coarsen(const BoxND< dim > &b, int ref_ratio) noexcept
Coarsen BoxND by given (positive) refinement ratio. NOTE: if type(dir) = CELL centered: lo <- lo/rati...
Definition: AMReX_Box.H:1304
Definition: AMReX_Array4.H:61