Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_Interp_2D_C.H
Go to the documentation of this file.
1#ifndef AMREX_INTERP_2D_C_H_
2#define AMREX_INTERP_2D_C_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_Array.H>
6#include <AMReX_Geometry.H>
7
8namespace amrex {
9
11pcinterp_interp (Box const& bx,
12 Array4<Real> const& fine, const int fcomp, const int ncomp,
13 Array4<Real const> const& crse, const int ccomp,
14 IntVect const& ratio) noexcept
15{
16 const auto lo = amrex::lbound(bx);
17 const auto hi = amrex::ubound(bx);
18
19 for (int n = 0; n < ncomp; ++n) {
20 for (int j = lo.y; j <= hi.y; ++j) {
21 const int jc = amrex::coarsen(j,ratio[1]);
23 for (int i = lo.x; i <= hi.x; ++i) {
24 const int ic = amrex::coarsen(i,ratio[0]);
25 fine(i,j,0,n+fcomp) = crse(ic,jc,0,n+ccomp);
26 }
27 }
28 }
29}
30
32namespace interp_detail {
33 constexpr int ix = 0;
34 constexpr int iy = 1;
35 constexpr int ixy = 2;
36}
38
39template<typename T>
41nodebilin_slopes (Box const& bx, Array4<T> const& slope, Array4<T const> const& u,
42 const int icomp, const int ncomp, IntVect const& ratio) noexcept
43{
44 using namespace interp_detail;
45
46 const auto lo = amrex::lbound(bx);
47 const auto hi = amrex::ubound(bx);
48
49 const Real rx = Real(1.)/Real(ratio[0]);
50 const Real ry = Real(1.)/Real(ratio[1]);
51
52 for (int n = 0; n < ncomp; ++n) {
53 for (int j = lo.y; j <= hi.y; ++j) {
55 for (int i = lo.x; i <= hi.x; ++i) {
56 T dx0 = u(i+1,j,0,n+icomp) - u(i,j,0,n+icomp);
57 T d0x = u(i,j+1,0,n+icomp) - u(i,j,0,n+icomp);
58 T dx1 = u(i+1,j+1,0,n+icomp) - u(i,j+1,0,n+icomp);
59
60 slope(i,j,0,n+ncomp*ix ) = rx*dx0;
61 slope(i,j,0,n+ncomp*iy ) = ry*d0x;
62 slope(i,j,0,n+ncomp*ixy) = rx*ry*(dx1 - dx0);
63 }
64 }
65 }
66}
67
68template<typename T>
70nodebilin_interp (Box const& bx, Array4<T> const& fine, const int fcomp, const int ncomp,
71 Array4<T const> const& slope, Array4<T const> const& crse,
72 const int ccomp, IntVect const& ratio) noexcept
73{
74 using namespace interp_detail;
75
76 const auto lo = amrex::lbound(bx);
77 const auto hi = amrex::ubound(bx);
78 const auto chi = amrex::ubound(slope);
79
80 for (int n = 0; n < ncomp; ++n) {
81 for (int j = lo.y; j <= hi.y; ++j) {
82 const int jc = amrex::min(amrex::coarsen(j,ratio[1]),chi.y);
83 const Real fy = j - jc*ratio[1];
85 for (int i = lo.x; i <= hi.x; ++i) {
86 const int ic = amrex::min(amrex::coarsen(i,ratio[0]),chi.x);
87 const Real fx = i - ic*ratio[0];
88 fine(i,j,0,n+fcomp) = crse(ic,jc,0,n+ccomp)
89 + fx*slope(ic,jc,0,n+ncomp*ix)
90 + fy*slope(ic,jc,0,n+ncomp*iy)
91 + fx*fy*slope(ic,jc,0,n+ncomp*ixy);
92 }
93 }
94 }
95}
96
97template<typename T>
99facediv_face_interp (int ci, int cj, int /*ck*/,
100 int nc, int nf, int idir,
101 Array4<T const> const& crse,
102 Array4<T> const& fine,
103 Array4<int const> const& mask,
104 IntVect const& ratio) noexcept
105{
106 if (mask) {
107 if (!mask(ci, cj, 0, nc))
108 { return; }
109 }
110
111 const int fi = ci*ratio[0];
112 const int fj = cj*ratio[1];
113
114 switch (idir) {
115 case 0:
116 {
117 const Real neg = crse(ci, cj-1, 0, nc);
118 const Real cen = crse(ci, cj , 0, nc);
119 const Real pos = crse(ci, cj+1, 0, nc);
120
121 fine(fi, fj , 0, nf) = Real(0.125)*(8*cen + neg - pos);
122 fine(fi, fj+1, 0, nf) = Real(0.125)*(8*cen + pos - neg);
123
124 break;
125 }
126 case 1:
127 {
128 const Real neg = crse(ci-1, cj, 0, nc);
129 const Real cen = crse(ci , cj, 0, nc);
130 const Real pos = crse(ci+1, cj, 0, nc);
131
132 fine(fi , fj, 0, nf) = Real(0.125)*(8*cen + neg - pos);
133 fine(fi+1, fj, 0, nf) = Real(0.125)*(8*cen + pos - neg);
134
135 break;
136 }
137 default : { break; }
138 }
139}
140
141template<typename T>
143facediv_int (int ci, int cj, int /*ck*/, int nf,
144 GpuArray<Array4<T>, AMREX_SPACEDIM> const& fine,
145 IntVect const& ratio,
146 GpuArray<Real, AMREX_SPACEDIM> const& cellSize) noexcept
147{
148 const int fi = ci*ratio[0];
149 const int fj = cj*ratio[1];
150
151 // References to fine exterior values.
152 const Real umm = fine[0](fi, fj, 0, nf);
153 const Real ump = fine[0](fi, fj+1, 0, nf);
154 const Real upm = fine[0](fi+2, fj, 0, nf);
155 const Real upp = fine[0](fi+2, fj+1, 0, nf);
156
157 const Real vmm = fine[1](fi, fj, 0, nf);
158 const Real vmp = fine[1](fi+1, fj, 0, nf);
159 const Real vpm = fine[1](fi, fj+2, 0, nf);
160 const Real vpp = fine[1](fi+1, fj+2, 0, nf);
161
162 const Real dxdy = cellSize[0]/cellSize[1];
163 const Real x_corr = Real(0.25)*dxdy * (vpp+vmm-vmp-vpm);
164 const Real y_corr = Real(0.25)/dxdy * (upp+umm-ump-upm);
165
166 // Calc fine faces on interior of coarse cells.
167 fine[0](fi+1,fj ,0,nf) = Real(0.5)*(umm+upm) + x_corr;
168 fine[0](fi+1,fj+1,0,nf) = Real(0.5)*(ump+upp) + x_corr;
169 fine[1](fi, fj+1,0,nf) = Real(0.5)*(vmm+vpm) + y_corr;
170 fine[1](fi+1,fj+1,0,nf) = Real(0.5)*(vmp+vpp) + y_corr;
171
172}
173
174template<typename T>
176face_linear_interp_x (int i, int j, int /*k*/, int n, Array4<T> const& fine,
177 Array4<T const> const& crse, IntVect const& ratio) noexcept
178{
179 const int ii = amrex::coarsen(i,ratio[0]);
180 const int jj = amrex::coarsen(j,ratio[1]);
181 if (i-ii*ratio[0] == 0) {
182 fine(i,j,0,n) = crse(ii,jj,0,n);
183 } else {
184 Real const w = static_cast<Real>(i-ii*ratio[0]) * (Real(1.)/Real(ratio[0]));
185 fine(i,j,0,n) = (Real(1.)-w) * crse(ii,jj,0,n) + w * crse(ii+1,jj,0,n);
186 }
187}
188
189template<typename T>
191face_linear_interp_y (int i, int j, int /*k*/, int n, Array4<T> const& fine,
192 Array4<T const> const& crse, IntVect const& ratio) noexcept
193{
194 const int ii = amrex::coarsen(i,ratio[0]);
195 const int jj = amrex::coarsen(j,ratio[1]);
196 if (j-jj*ratio[1] == 0) {
197 fine(i,j,0,n) = crse(ii,jj,0,n);
198 } else {
199 Real const w = static_cast<Real>(j-jj*ratio[1]) * (Real(1.)/Real(ratio[1]));
200 fine(i,j,0,n) = (Real(1.)-w) * crse(ii,jj,0,n) + w * crse(ii,jj+1,0,n);
201 }
202}
203
204template <typename T>
206void ccprotect_2d (int ic, int jc, int /*kc*/, int nvar,
207 Box const& fine_bx,
208 IntVect const& ratio,
209 GeometryData cs_geomdata,
210 GeometryData fn_geomdata,
211 Array4<T> const& fine,
212 Array4<T const> const& fine_state) noexcept
213{
214 // Calculate bounds for interpolation
215 Dim3 fnbxlo = lbound(fine_bx);
216 Dim3 fnbxhi = ubound(fine_bx);
217 int ilo = amrex::max(ratio[0]*ic, fnbxlo.x);
218 int ihi = amrex::min(ratio[0]*ic+(ratio[0]-1), fnbxhi.x);
219 int jlo = amrex::max(ratio[1]*jc, fnbxlo.y);
220 int jhi = amrex::min(ratio[1]*jc+(ratio[1]-1), fnbxhi.y);
221
222 /*
223 * Check if interpolation needs to be redone for derived components (n > 0)
224 */
225 for (int n = 1; n < nvar-1; ++n) {
226
227 bool redo_me = false;
228 for (int j = jlo; j <= jhi; ++j) {
229 for (int i = ilo; i <= ihi; ++i) {
230 if ((fine_state(i,j,0,n) + fine(i,j,0,n)) < 0.0) {
231 redo_me = true;
232 }
233 }
234 }
235
236 /*
237 * If all the fine values are non-negative after the original
238 * interpolated correction, then we do nothing here.
239 *
240 * If any of the fine values are negative after the original
241 * interpolated correction, then we do our best.
242 */
243 if (redo_me) {
244
245 /*
246 * Calculate coarse cell volumes.
247 */
248 Real cvol;
249 // Calculate coarse cell volume
250 const Real* cs_dx = cs_geomdata.CellSize();
251 if (cs_geomdata.coord == CoordSys::cartesian) {
252 // Cartesian
253 cvol = cs_dx[0] * cs_dx[1];
254 } else {
255 // RZ
256 const Real* cs_problo = cs_geomdata.ProbLo();
257 Real rp = cs_problo[0] + (ic+0.5_rt)*cs_dx[0];
258 Real rm = cs_problo[0] + (ic-0.5_rt)*cs_dx[0];
259 cvol = (rp*rp - rm*rm) * cs_dx[1];
260 }
261
262 /*
263 * First, calculate the following quantities:
264 *
265 * crseTot = volume-weighted sum of all interpolated values
266 * of the correction, which is equivalent to
267 * the total volume-weighted coarse correction
268 *
269 * SumN = volume-weighted sum of all negative values of fine_state
270 *
271 * SumP = volume-weighted sum of all positive values of fine_state
272 */
273 Real crseTot = 0.0;
274 Real SumN = 0.0;
275 Real SumP = 0.0;
276 for (int j = jlo; j <= jhi; ++j) {
277 for (int i = ilo; i <= ihi; ++i) {
278
279 Real fvol;
280 // Calculate fine cell volume
281 const Real* fn_dx = fn_geomdata.CellSize();
282 if (fn_geomdata.coord == CoordSys::cartesian) {
283 // Cartesian
284 fvol = fn_dx[0] * fn_dx[1];
285 } else {
286 // RZ
287 const Real* fn_problo = fn_geomdata.ProbLo();
288 Real rp = fn_problo[0] + (i+0.5_rt)*fn_dx[0];
289 Real rm = fn_problo[0] + (i-0.5_rt)*fn_dx[0];
290 fvol = (rp*rp - rm*rm) * fn_dx[1];
291 }
292
293 // Calculate sums
294 crseTot += fvol * fine(i,j,0,n);
295 if (fine_state(i,j,0,n) <= 0.0) {
296 SumN += fvol * fine_state(i,j,0,n);
297 } else {
298 SumP += fvol * fine_state(i,j,0,n);
299 }
300 }
301 }
302
303 if ( (crseTot > 0) && (crseTot > std::abs(SumN)) ) {
304
305 /*
306 * Special case 1:
307 *
308 * Coarse correction > 0, and fine_state has some cells
309 * with negative values which will be filled before
310 * adding to the other cells.
311 *
312 * Use the correction to bring negative cells to zero,
313 * then distribute the remaining positive proportionally.
314 */
315 for (int j = jlo; j <= jhi; ++j) {
316 for (int i = ilo; i <= ihi; ++i) {
317
318 // Fill in negative values first.
319 if (fine_state(i,j,0,n) < 0.0) {
320 fine(i,j,0,n) = -fine_state(i,j,0,n);
321 }
322
323 // Then, add the remaining positive proportionally.
324 if (SumP > 0.0) {
325 if (fine_state(i,j,0,n) > 0.0) {
326 Real alpha = (crseTot - std::abs(SumN)) / SumP;
327 fine(i,j,0,n) = alpha * fine_state(i,j,0,n);
328 }
329 } else { /* (SumP < 0) */
330 Real posVal = (crseTot - std::abs(SumN)) / cvol;
331 fine(i,j,0,n) += posVal;
332 }
333
334 }
335 }
336
337 } else if ( (crseTot > 0) && (crseTot < std::abs(SumN)) ) {
338
339 /*
340 * Special case 2:
341 *
342 * Coarse correction > 0, and correction can not make
343 * them all positive.
344 *
345 * Add correction only to the negative cells
346 * in proportion to their magnitude, and
347 * don't add any correction to the states already positive.
348 */
349 for (int j = jlo; j <= jhi; ++j) {
350 for (int i = ilo; i <= ihi; ++i) {
351
352 Real alpha = crseTot / std::abs(SumN);
353 if (fine_state(i,j,0,n) < 0.0) {
354 // Add correction to negative cells proportionally.
355 fine(i,j,0,n) = alpha * std::abs(fine_state(i,j,0,n));
356 } else {
357 // Don't touch the positive states.
358 fine(i,j,0,n) = 0.0;
359 }
360
361 }
362 }
363
364 } else if ( (crseTot < 0) && (std::abs(crseTot) > SumP) ) {
365
366 /*
367 * Special case 3:
368 *
369 * Coarse correction < 0, and fine_state DOES NOT have
370 * enough positive states to absorb it.
371 *
372 * Here we distribute the remaining negative amount
373 * in such a way as to make them all as close to the
374 * same negative value as possible.
375 */
376 for (int j = jlo; j <= jhi; ++j) {
377 for (int i = ilo; i <= ihi; ++i) {
378
379 // We want to make them all as close to the same negative value.
380 Real negVal = (SumP + SumN + crseTot) / cvol;
381 fine(i,j,0,n) = negVal - fine_state(i,j,0,n);
382
383 }
384 }
385
386 } else if ( (crseTot < 0) && (std::abs(crseTot) < SumP) &&
387 ((SumP+SumN+crseTot) > 0.0) ) {
388
389 /*
390 * Special case 4:
391 *
392 * Coarse correction < 0, and fine_state has enough
393 * positive states to absorb all the negative
394 * correction *and* to redistribute to make
395 * negative cells positive.
396 */
397 for (int j = jlo; j <= jhi; ++j) {
398 for (int i = ilo; i <= ihi; ++i) {
399
400 if (fine_state(i,j,0,n) < 0.0) {
401 // Absorb the negative correction
402 fine(i,j,0,n) = -fine_state(i,j,0,n);
403 } else {
404 // Redistribute the rest to make negative cells positive
405 Real alpha = (crseTot + SumN) / SumP;
406 fine(i,j,0,n) = alpha * fine_state(i,j,0,n);
407 }
408
409 }
410 }
411
412 } else if ( (crseTot < 0) && (std::abs(crseTot) < SumP) &&
413 ((SumP+SumN+crseTot) < 0.0) ) {
414 /*
415 * Special case 5:
416 *
417 * Coarse correction < 0, and fine_state has enough
418 * positive states to absorb all the negative
419 * correction, but not enough to fix the states
420 * already negative.
421 *
422 * Here we take a constant percentage away from each
423 * positive cell and don't touch the negatives.
424 */
425 for (int j = jlo; j <= jhi; ++j) {
426 for (int i = ilo; i <= ihi; ++i) {
427
428 if (fine_state(i,j,0,n) > 0.0) {
429 // Don't touch the negatives
430 fine(i,j,0,n) = -fine_state(i,j,0,n);
431 } else {
432 // Take a constant percentage away from each positive cell
433 Real alpha = (crseTot + SumP) / SumN;
434 fine(i,j,0,n) = alpha * fine_state(i,j,0,n);
435 }
436
437 }
438 }
439
440 } // special cases
441 } // redo_me
442 } // n
443
444 // Set sync for density (n=0) to sum of spec sync (1:nvar)
445 for (int j = jlo; j <= jhi; ++j) {
446 for (int i = ilo; i <= ihi; ++i) {
447 fine(i,j,0,0) = 0.0;
448 for (int n = 1; n < nvar-1; ++n) {
449 fine(i,j,0,0) += fine(i,j,0,n);
450 }
451 }
452 }
453
454}
455
457void ccquartic_interp (int i, int j, int /*k*/, int n,
458 Array4<Real const> const& crse,
459 Array4<Real> const& fine) noexcept
460{
461 // Note: there are asserts in CellConservativeQuartic::interp()
462 // to check whether ratio is all equal to 2.
463
464 constexpr Array1D<Real, -2, 2> cL = { -0.01171875_rt, 0.0859375_rt, 0.5_rt, -0.0859375_rt, 0.01171875_rt };
465
466 int ic = amrex::coarsen(i,2);
467 int jc = amrex::coarsen(j,2);
468 int irx = i - 2*ic; // = abs(i % 2)
469 int jry = j - 2*jc; // = abs(j % 2);
470
471 Array1D<Real, -2, 2> ctmp;
472 for (int ii = -2; ii <= 2; ++ii) {
473 ctmp(ii) = 2.0_rt * ( cL(-2)*crse(ic+ii,jc-2,0,n)
474 + cL(-1)*crse(ic+ii,jc-1,0,n)
475 + cL( 0)*crse(ic+ii,jc, 0,n)
476 + cL( 1)*crse(ic+ii,jc+1,0,n)
477 + cL( 2)*crse(ic+ii,jc+2,0,n) );
478 if (jry) {
479 ctmp(ii) = 2.0_rt * crse(ic+ii,jc,0,n) - ctmp(ii);
480 }
481 } // ii
482
483 Real ftmp = 2.0_rt * ( cL(-2)*ctmp(-2)
484 + cL(-1)*ctmp(-1)
485 + cL( 0)*ctmp( 0)
486 + cL( 1)*ctmp( 1)
487 + cL( 2)*ctmp( 2) );
488 if (irx) {
489 ftmp = 2.0_rt * ctmp(0) - ftmp;
490 }
491
492 fine(i,j,0,n) = ftmp;
493
494}
495
496} // namespace amrex
497
498#endif
#define AMREX_PRAGMA_SIMD
Definition AMReX_Extension.H:80
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
int idir
Definition AMReX_HypreMLABecLap.cpp:1093
Array4< Real > fine
Definition AMReX_InterpFaceRegister.cpp:90
Array4< int const > mask
Definition AMReX_InterpFaceRegister.cpp:93
Array4< Real > slope
Definition AMReX_InterpFaceRegister.cpp:91
Array4< Real const > crse
Definition AMReX_InterpFaceRegister.cpp:92
@ cartesian
Definition AMReX_CoordSys.H:27
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:79
__host__ __device__ BoxND< dim > coarsen(const BoxND< dim > &b, int ref_ratio) noexcept
Coarsen BoxND by given (positive) coarsening ratio.
Definition AMReX_Box.H:1409
Definition AMReX_Amr.cpp:49
__host__ __device__ Dim3 ubound(Array4< T > const &a) noexcept
Definition AMReX_Array4.H:319
__host__ __device__ void facediv_face_interp(int, int, int, int, int, int, Array4< T const > const &, Array4< T > const &, Array4< const int > const &, IntVect const &) noexcept
Definition AMReX_Interp_1D_C.H:75
__host__ __device__ void pcinterp_interp(Box const &bx, Array4< Real > const &fine, const int fcomp, const int ncomp, Array4< Real const > const &crse, const int ccomp, IntVect const &ratio) noexcept
Definition AMReX_Interp_1D_C.H:14
__host__ __device__ void ccprotect_2d(int ic, int jc, int, int nvar, Box const &fine_bx, IntVect const &ratio, GeometryData cs_geomdata, GeometryData fn_geomdata, Array4< T > const &fine, Array4< T const > const &fine_state) noexcept
Definition AMReX_Interp_2D_C.H:206
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:27
__host__ __device__ void nodebilin_slopes(Box const &bx, Array4< T > const &slope, Array4< T const > const &u, const int icomp, const int ncomp, IntVect const &ratio) noexcept
Definition AMReX_Interp_1D_C.H:33
__host__ __device__ constexpr const T & min(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:21
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:30
__host__ __device__ void face_linear_interp_x(int i, int, int, int n, Array4< T > const &fine, Array4< T const > const &crse, IntVect const &ratio) noexcept
Definition AMReX_Interp_1D_C.H:97
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:35
__host__ __device__ void nodebilin_interp(Box const &bx, Array4< T > const &fine, const int fcomp, const int ncomp, Array4< T const > const &slope, Array4< T const > const &crse, const int ccomp, IntVect const &ratio) noexcept
Definition AMReX_Interp_1D_C.H:52
__host__ __device__ void facediv_int(int, int, int, int, GpuArray< Array4< T >, 3 > const &, IntVect const &, GpuArray< Real, 3 > const &) noexcept
Definition AMReX_Interp_1D_C.H:87
__host__ __device__ void ccquartic_interp(int i, int, int, int n, Array4< Real const > const &crse, Array4< Real > const &fine) noexcept
Definition AMReX_Interp_1D_C.H:110
__host__ __device__ void face_linear_interp_y(int i, int j, int, int n, Array4< T > const &fine, Array4< T const > const &crse, IntVect const &ratio) noexcept
Definition AMReX_Interp_2D_C.H:191
__host__ __device__ Dim3 lbound(Array4< T > const &a) noexcept
Definition AMReX_Array4.H:312
Definition AMReX_Array4.H:61
Definition AMReX_Dim3.H:12
int x
Definition AMReX_Dim3.H:12
int y
Definition AMReX_Dim3.H:12
Definition AMReX_Geometry.H:25