Skip to content

Commit c59345a

Browse files
authored
Fix Bug in FaceConservativeLinear (#4630)
This fixes a bug when the fine box is not coarsenable in the face direction.
1 parent ae20296 commit c59345a

File tree

2 files changed

+111
-18
lines changed

2 files changed

+111
-18
lines changed

Src/AmrCore/AMReX_Interp_C.H

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,60 @@ face_linear_interp_z (int i, int j, int k, int n, amrex::Array4<amrex::Real> con
283283
}
284284
}
285285

286+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
287+
Real face_linear_interp_safe_x (int i, int j, int k, int n,
288+
amrex::Array4<amrex::Real> const& fine,
289+
IntVect const& ratio) noexcept
290+
{
291+
const int ci = amrex::coarsen(i,ratio[0]);
292+
293+
if (i-ci*ratio[0] != 0)
294+
{
295+
Real const w = static_cast<Real>(i-ci*ratio[0]) * (Real(1.)/Real(ratio[0]));
296+
int i1 = ci*ratio[0];
297+
int i2 = (ci+1)*ratio[0];
298+
return (Real(1.)-w) * fine(i1,j,k,n) + w * fine(i2,j,k,n);
299+
} else {
300+
return fine(i,j,k,n);
301+
}
302+
}
303+
304+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
305+
Real face_linear_interp_safe_y (int i, int j, int k, int n,
306+
amrex::Array4<amrex::Real> const& fine,
307+
IntVect const& ratio) noexcept
308+
{
309+
const int cj = amrex::coarsen(j,ratio[1]);
310+
311+
if (j-cj*ratio[1] != 0)
312+
{
313+
Real const w = static_cast<Real>(j-cj*ratio[1]) * (Real(1.)/Real(ratio[1]));
314+
int j1 = cj*ratio[1];
315+
int j2 = (cj+1)*ratio[1];
316+
return (Real(1.)-w) * fine(i,j1,k,n) + w * fine(i,j2,k,n);
317+
} else {
318+
return fine(i,j,k,n);
319+
}
320+
}
321+
322+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
323+
Real face_linear_interp_safe_z (int i, int j, int k, int n,
324+
amrex::Array4<amrex::Real> const& fine,
325+
IntVect const& ratio) noexcept
326+
{
327+
const int ck = amrex::coarsen(k,ratio[2]);
328+
329+
if (k-ck*ratio[2] != 0)
330+
{
331+
Real const w = static_cast<Real>(k-ck*ratio[2]) * (Real(1.)/Real(ratio[2]));
332+
int k1 = ck*ratio[2];
333+
int k2 = (ck+1)*ratio[2];
334+
return (Real(1.)-w) * fine(i,j,k1,n) + w * fine(i,j,k2,n);
335+
} else {
336+
return fine(i,j,k,n);
337+
}
338+
}
339+
286340
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
287341
void cell_quartic_interp_x (int i, int j, int k, int n, Array4<Real> const& fine,
288342
Array4<Real const> const& crse) noexcept

Src/AmrCore/AMReX_Interpolater.cpp

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,24 @@ FaceConservativeLinear::interp_face (const FArrayBox& crse,
516516
}
517517
}
518518

519+
bool is_safe = true;
520+
FArrayBox safe_fine;
521+
Array4<Real> safe_fine_arr = fine_arr;
522+
Box safe_fine_region = fine_region;
523+
int facedir = 0;
524+
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
525+
if (fine_region.type(idim) == IndexType::NODE) { facedir = idim; }
526+
}
527+
IntVect rrtmp(1);
528+
rrtmp[facedir] = ratio[facedir];
529+
if (! safe_fine_region.coarsenable(rrtmp)) {
530+
is_safe = false;
531+
safe_fine_region.coarsen(rrtmp);
532+
safe_fine_region.refine(rrtmp);
533+
safe_fine.resize(safe_fine_region, ncomp, The_Async_Arena());
534+
safe_fine_arr = safe_fine.array();
535+
}
536+
519537
//
520538
// Fill fine ghost faces with interpolation of coarse data that is conservative linear
521539
// in the tangential direction.
@@ -525,25 +543,25 @@ FaceConservativeLinear::interp_face (const FArrayBox& crse,
525543
//
526544
if (fine_region.type(0) == IndexType::NODE)
527545
{
528-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
546+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,safe_fine_region,ncomp,i,j,k,n,
529547
{
530-
face_cons_linear_face_interp(i,j,k,n,fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,0);
548+
face_cons_linear_face_interp(i,j,k,n,safe_fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,0);
531549
});
532550
}
533551
#if (AMREX_SPACEDIM >= 2)
534552
else if (fine_region.type(1) == IndexType::NODE)
535553
{
536-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
554+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,safe_fine_region,ncomp,i,j,k,n,
537555
{
538-
face_cons_linear_face_interp(i,j,k,n,fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,1);
556+
face_cons_linear_face_interp(i,j,k,n,safe_fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,1);
539557
});
540558
}
541559
#if (AMREX_SPACEDIM == 3)
542560
else
543561
{
544-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
562+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,safe_fine_region,ncomp,i,j,k,n,
545563
{
546-
face_cons_linear_face_interp(i,j,k,n,fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,2);
564+
face_cons_linear_face_interp(i,j,k,n,safe_fine_arr,crse_arr,mask_arr,ratio,per_grown_domain,2);
547565
});
548566
}
549567
#endif
@@ -556,26 +574,47 @@ FaceConservativeLinear::interp_face (const FArrayBox& crse,
556574
//
557575
if (fine_region.type(0) == IndexType::NODE)
558576
{
559-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
560-
{
561-
face_linear_interp_x(i,j,k,n,fine_arr,ratio);
562-
});
577+
if (is_safe) {
578+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
579+
{
580+
face_linear_interp_x(i,j,k,n,fine_arr,ratio);
581+
});
582+
} else {
583+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
584+
{
585+
fine_arr(i,j,k,n) = face_linear_interp_safe_x(i,j,k,n,safe_fine_arr,ratio);
586+
});
587+
}
563588
}
564589
#if (AMREX_SPACEDIM >= 2)
565590
else if (fine_region.type(1) == IndexType::NODE)
566591
{
567-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
568-
{
569-
face_linear_interp_y(i,j,k,n,fine_arr,ratio);
570-
});
592+
if (is_safe) {
593+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
594+
{
595+
face_linear_interp_y(i,j,k,n,fine_arr,ratio);
596+
});
597+
} else {
598+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
599+
{
600+
fine_arr(i,j,k,n) = face_linear_interp_safe_y(i,j,k,n,safe_fine_arr,ratio);
601+
});
602+
}
571603
}
572604
#if (AMREX_SPACEDIM == 3)
573605
else
574606
{
575-
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
576-
{
577-
face_linear_interp_z(i,j,k,n,fine_arr,ratio);
578-
});
607+
if (is_safe) {
608+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
609+
{
610+
face_linear_interp_z(i,j,k,n,fine_arr,ratio);
611+
});
612+
} else {
613+
AMREX_HOST_DEVICE_PARALLEL_FOR_4D_FLAG(runon,fine_region,ncomp,i,j,k,n,
614+
{
615+
fine_arr(i,j,k,n) = face_linear_interp_safe_z(i,j,k,n,safe_fine_arr,ratio);
616+
});
617+
}
579618
}
580619
#endif
581620
#endif

0 commit comments

Comments
 (0)