Skip to content

Commit d4d0e90

Browse files
Fix Bug in FaceLinear Interpolater (#3483)
The bug was introduced in #2539. The issue was when FaceLinear was used by functions other than FillPatchTwoLevels, the assumption of the fine box was a refined version of the coarse box could be wrong. The bug did not affect FillPatchFromTwoLevels. Co-authored-by: Ann Almgren <[email protected]>
1 parent 84bd015 commit d4d0e90

File tree

3 files changed

+112
-7
lines changed

3 files changed

+112
-7
lines changed

Src/AmrCore/AMReX_Interp_2D_C.H

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,36 @@ facediv_int (int ci, int cj, int /*ck*/, int nf,
164164

165165
}
166166

167+
template<typename T>
168+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void
169+
face_linear_interp_x (int i, int j, int /*k*/, int n, Array4<T> const& fine,
170+
Array4<T const> const& crse, IntVect const& ratio) noexcept
171+
{
172+
const int ii = amrex::coarsen(i,ratio[0]);
173+
const int jj = amrex::coarsen(j,ratio[1]);
174+
if (i-ii*ratio[0] == 0) {
175+
fine(i,j,0,n) = crse(ii,jj,0,n);
176+
} else {
177+
Real const w = static_cast<Real>(i-ii*ratio[0]) * (Real(1.)/Real(ratio[0]));
178+
fine(i,j,0,n) = (Real(1.)-w) * crse(ii,jj,0,n) + w * crse(ii+1,jj,0,n);
179+
}
180+
}
181+
182+
template<typename T>
183+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void
184+
face_linear_interp_y (int i, int j, int /*k*/, int n, Array4<T> const& fine,
185+
Array4<T const> const& crse, IntVect const& ratio) noexcept
186+
{
187+
const int ii = amrex::coarsen(i,ratio[0]);
188+
const int jj = amrex::coarsen(j,ratio[1]);
189+
if (j-jj*ratio[1] == 0) {
190+
fine(i,j,0,n) = crse(ii,jj,0,n);
191+
} else {
192+
Real const w = static_cast<Real>(j-jj*ratio[1]) * (Real(1.)/Real(ratio[1]));
193+
fine(i,j,0,n) = (Real(1.)-w) * crse(ii,jj,0,n) + w * crse(ii,jj+1,0,n);
194+
}
195+
}
196+
167197
template <typename T>
168198
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
169199
void ccprotect_2d (int ic, int jc, int /*kc*/, int nvar,

Src/AmrCore/AMReX_Interp_3D_C.H

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,54 @@ facediv_int (int ci, int cj, int ck, int nf,
332332
+ dz3/(8*dy*zspxs)*(v000+v021-v001-v020);
333333
}
334334

335+
template<typename T>
336+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void
337+
face_linear_interp_x (int i, int j, int k, int n, Array4<T> const& fine,
338+
Array4<T const> const& crse, IntVect const& ratio) noexcept
339+
{
340+
const int ii = amrex::coarsen(i,ratio[0]);
341+
const int jj = amrex::coarsen(j,ratio[1]);
342+
const int kk = amrex::coarsen(k,ratio[2]);
343+
if (i-ii*ratio[0] == 0) {
344+
fine(i,j,k,n) = crse(ii,jj,kk,n);
345+
} else {
346+
Real const w = static_cast<Real>(i-ii*ratio[0]) * (Real(1.)/Real(ratio[0]));
347+
fine(i,j,k,n) = (Real(1.)-w) * crse(ii,jj,kk,n) + w * crse(ii+1,jj,kk,n);
348+
}
349+
}
350+
351+
template<typename T>
352+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void
353+
face_linear_interp_y (int i, int j, int k, int n, Array4<T> const& fine,
354+
Array4<T const> const& crse, IntVect const& ratio) noexcept
355+
{
356+
const int ii = amrex::coarsen(i,ratio[0]);
357+
const int jj = amrex::coarsen(j,ratio[1]);
358+
const int kk = amrex::coarsen(k,ratio[2]);
359+
if (j-jj*ratio[1] == 0) {
360+
fine(i,j,k,n) = crse(ii,jj,kk,n);
361+
} else {
362+
Real const w = static_cast<Real>(j-jj*ratio[1]) * (Real(1.)/Real(ratio[1]));
363+
fine(i,j,k,n) = (Real(1.)-w) * crse(ii,jj,kk,n) + w * crse(ii,jj+1,kk,n);
364+
}
365+
}
366+
367+
template<typename T>
368+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void
369+
face_linear_interp_z (int i, int j, int k, int n, Array4<T> const& fine,
370+
Array4<T const> const& crse, IntVect const& ratio) noexcept
371+
{
372+
const int ii = amrex::coarsen(i,ratio[0]);
373+
const int jj = amrex::coarsen(j,ratio[1]);
374+
const int kk = amrex::coarsen(k,ratio[2]);
375+
if (k-kk*ratio[2] == 0) {
376+
fine(i,j,k,n) = crse(ii,jj,kk,n);
377+
} else {
378+
Real const w = static_cast<Real>(k-kk*ratio[2]) * (Real(1.)/Real(ratio[2]));
379+
fine(i,j,k,n) = (Real(1.)-w) * crse(ii,jj,kk,n) + w * crse(ii,jj,kk+1,n);
380+
}
381+
}
382+
335383
template <typename T>
336384
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
337385
void ccprotect_3d (int ic, int jc, int kc, int nvar,

Src/AmrCore/AMReX_Interpolater.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,10 @@ FaceLinear::interp (const FArrayBox& crse,
134134
int ncomp,
135135
const Box& fine_region,
136136
const IntVect& ratio,
137-
const Geometry& crse_geom ,
138-
const Geometry& fine_geom ,
139-
Vector<BCRec> const& bcr,
140-
int actual_comp,
137+
const Geometry& /* crse_geom */,
138+
const Geometry& /* fine_geom */,
139+
Vector<BCRec> const& /*bcr*/,
140+
int /* actual_comp*/,
141141
int /*actual_state*/,
142142
RunOn runon)
143143
{
@@ -146,9 +146,36 @@ FaceLinear::interp (const FArrayBox& crse,
146146
//
147147
BL_PROFILE("FaceLinear::interp()");
148148

149-
// pass unallocated IArrayBox for solve_mask, so all fine values get filled.
150-
interp_face(crse, crse_comp, fine, fine_comp, ncomp, fine_region,
151-
ratio, IArrayBox(), crse_geom, fine_geom, bcr, actual_comp, runon);
149+
AMREX_ASSERT(AMREX_D_TERM(fine_region.type(0),+fine_region.type(1),+fine_region.type(2)) == 1);
150+
151+
Array4<Real> const& fine_arr = fine.array(fine_comp);
152+
Array4<Real const> const& crse_arr = crse.const_array(crse_comp);
153+
154+
if (fine_region.type(0) == IndexType::NODE)
155+
{
156+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
157+
{
158+
face_linear_interp_x(i,j,k,n,fine_arr,crse_arr,ratio);
159+
});
160+
}
161+
#if (AMREX_SPACEDIM >= 2)
162+
else if (fine_region.type(1) == IndexType::NODE)
163+
{
164+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
165+
{
166+
face_linear_interp_y(i,j,k,n,fine_arr,crse_arr,ratio);
167+
});
168+
}
169+
#if (AMREX_SPACEDIM == 3)
170+
else
171+
{
172+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
173+
{
174+
face_linear_interp_z(i,j,k,n,fine_arr,crse_arr,ratio);
175+
});
176+
}
177+
#endif
178+
#endif
152179
}
153180

154181
void

0 commit comments

Comments
 (0)