@@ -55,41 +55,33 @@ namespace amrex
5555 const Geometry& geom,
5656 int ncomp = 1 ,
5757 bool use_harmonic_averaging = false );
58- /* ********* End average-to-different-IndexType methods **********/
5958
6059 /* ********* Begin average-down methods **********/
6160 /* *
62- * \brief Geometric weighed average of fine FabArray onto coarse FabArray of same IndexType .
61+ * \brief Volume- weighed average of fine cell-based MultiFab onto coarse cell-based MultiFab .
6362 *
64- * Works for any IndexType shared by both \p crse and \p fine . This routine DOES NOT assume that
65- * the \p crse BoxArray is a coarsened version of the \p fine BoxArray .
63+ * Both MultiFabs are assumed to be cell-centered . This routine DOES NOT assume that
64+ * the BoxArray of \p S_crse is a coarsened version of the BoxArray of \p S_fine .
6665 */
67- template <typename MF, std::enable_if_t <IsFabArray_v<MF>,int > = 0 >
68- void average_down (const MF& S_fine, MF& S_crse,
69- const Geometry& fgeom, const Geometry& cgeom,
70- int scomp, int ncomp, const IntVect& ratio,
71- const IntVect& ngcrse = IntVect(0 ));
72- // ! Geometric weighed average of fine FabArray onto coarse FabArray of same IndexType.
73- template <typename MF, std::enable_if_t <IsFabArray_v<MF>,int > = 0 >
74- void average_down (const MF& S_fine, MF& S_crse,
75- const Geometry& fgeom, const Geometry& cgeom,
76- int scomp, int ncomp, int rr,
77- const IntVect& ngcrse = IntVect(0 ));
66+ void average_down_cells (const MultiFab& S_fine, MultiFab& S_crse,
67+ const Geometry& fgeom, const Geometry& cgeom,
68+ int scomp, int ncomp, const IntVect& ratio);
69+ void average_down_cells (const MultiFab& S_fine, MultiFab& S_crse,
70+ const Geometry& fgeom, const Geometry& cgeom,
71+ int scomp, int ncomp, int rr);
72+
7873 /* *
79- * \brief Average fine FabArray onto coarse FabArray of same IndexType without geometric weighting.
74+ * \brief Average fine cell-based FabArray onto coarse cell-based FabArray without volume weighting.
8075 *
81- * Works for any IndexType shared by both \p crse and \p fine . This routine DOES NOT assume that
76+ * Work for both cell-centered and nodal MultiFabs . This routine DOES NOT assume that
8277 * the \p crse BoxArray is a coarsened version of the \p fine BoxArray.
8378 */
84- template <typename MF, std::enable_if_t <IsFabArray_v<MF>,int > = 0 >
85- void average_down (const MF& S_fine, MF& S_crse,
86- int scomp, int ncomp, const IntVect& ratio,
87- const IntVect& ngcrse = IntVect(0 ));
88- // ! Average fine FabArray onto coarse FabArray of same IndexType without geometric weighting.
89- template <typename MF, std::enable_if_t <IsFabArray_v<MF>,int > = 0 >
90- void average_down (const MF& S_fine, MF& S_crse,
91- int scomp, int ncomp, int rr,
92- const IntVect& ngcrse = IntVect(0 ));
79+ template <typename FAB>
80+ void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
81+ int scomp, int ncomp, const IntVect& ratio);
82+ template <typename FAB>
83+ void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
84+ int scomp, int ncomp, int rr);
9385
9486 // ! Average fine face-based MultiFab onto crse face-based MultiFab.
9587 template <typename MF, std::enable_if_t <IsFabArray<MF>::value,int > = 0 >
@@ -164,34 +156,39 @@ namespace amrex
164156 bool mfiter_is_definitely_safe=false );
165157
166158 /* *
167- * \brief Volume- weighed average of fine cell-based MultiFab onto coarse cell-based MultiFab .
159+ * \brief Geometric weighed average of fine FabArray onto coarse FabArray of same IndexType .
168160 *
169- * Both MultiFabs are assumed to be cell-centered . This routine DOES NOT assume that
170- * the BoxArray of \p S_crse is a coarsened version of the BoxArray of \p S_fine .
161+ * Works for any IndexType shared by both \p crse and \p fine . This routine DOES NOT assume that
162+ * the \p crse BoxArray is a coarsened version of the \p fine BoxArray .
171163 */
172- void average_down_cells (const MultiFab& S_fine, MultiFab& S_crse,
173- const Geometry& fgeom, const Geometry& cgeom,
174- int scomp, int ncomp, const IntVect& ratio);
175- void average_down_cells (const MultiFab& S_fine, MultiFab& S_crse,
176- const Geometry& fgeom, const Geometry& cgeom,
177- int scomp, int ncomp, int rr);
178-
164+ void average_down (const MultiFab& S_fine, MultiFab& S_crse,
165+ const Geometry& fgeom, const Geometry& cgeom,
166+ int scomp, int ncomp, const IntVect& ratio,
167+ const IntVect& ngcrse = IntVect(0 ));
168+ // ! Geometric weighed average of fine FabArray onto coarse FabArray of same IndexType.
169+ void average_down (const MultiFab& S_fine, MultiFab& S_crse,
170+ const Geometry& fgeom, const Geometry& cgeom,
171+ int scomp, int ncomp, int rr,
172+ const IntVect& ngcrse = IntVect(0 ));
179173 /* *
180- * \brief Average fine cell-based FabArray onto coarse cell-based FabArray without volume weighting.
174+ * \brief Average fine FabArray onto coarse FabArray of same IndexType without geometric weighting.
181175 *
182- * Work for both cell-centered and nodal MultiFabs . This routine DOES NOT assume that
176+ * Works for any IndexType shared by both \p crse and \p fine . This routine DOES NOT assume that
183177 * the \p crse BoxArray is a coarsened version of the \p fine BoxArray.
184178 */
185179 template <typename FAB>
186- void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
187- int scomp, int ncomp, const IntVect& ratio);
180+ void average_down (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
181+ int scomp, int ncomp, const IntVect& ratio,
182+ const IntVect& ngcrse = IntVect(0 ));
183+ // ! Average fine FabArray onto coarse FabArray of same IndexType without geometric weighting.
188184 template <typename FAB>
189- void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
190- int scomp, int ncomp, int rr);
191- /* End average-down methods */
185+ void average_down (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
186+ int scomp, int ncomp, int rr,
187+ const IntVect& ngcrse = IntVect(0 ));
188+ /* ********* End average-down methods **********/
192189
193- // ! Add a coarsened version of the data contained in the \p S_fine MultiFab to
194- // ! \p S_crse, including ghost cells.
190+ // ! Add a coarsened version of the data contained in the S_fine MultiFab to
191+ // ! S_crse, including ghost cells.
195192 void sum_fine_to_coarse (const MultiFab& S_Fine, MultiFab& S_crse,
196193 int scomp, int ncomp,
197194 const IntVect& ratio,
@@ -499,128 +496,6 @@ makeFineMask (const FabArray<FAB>& cmf, const FabArray<FAB>& fmf,
499496}
500497
501498/* ********* Begin average-down methods **********/
502- template <typename MF, std::enable_if_t <IsFabArray<MF>::value,int > FOO>
503- void average_down (const MF& S_fine, MF& S_crse,
504- int scomp, int ncomp, const IntVect& ratio,
505- const IntVect& ngcrse)
506- {
507- BL_PROFILE (" amrex::average_down" );
508- AMREX_ASSERT (S_crse.nComp () == S_fine.nComp ());
509- AMREX_ASSERT (S_crse.ixType () == S_fine.ixType ());
510-
511- // Coarsen() the fine stuff on processors owning the fine data.
512- BoxArray crse_S_fine_BA = S_fine.boxArray ();
513- if (ngcrse != IntVect{0 }) {
514- crse_S_fine_BA.grow (ngcrse);
515- }
516- crse_S_fine_BA.coarsen (ratio);
517-
518- if (crse_S_fine_BA == S_crse.boxArray () && S_fine.DistributionMap () == S_crse.DistributionMap ())
519- {
520- average_down_matching (S_crse, S_fine, scomp, scomp, ncomp, ratio, ngcrse);
521- }
522- else
523- {
524- MF crse_S_fine (crse_S_fine_BA, S_fine.DistributionMap (),
525- ncomp, ngcrse, MFInfo (), DefaultFabFactory<FAB>());
526- average_down_matching (S_fine, crse_S_fine, 0 , scomp, ncomp, ratio, ngcrse);
527- S_crse.ParallelCopy (crse_S_fine,0 ,scomp,ncomp);
528- }
529- }
530-
531- template <typename MF, std::enable_if_t <IsFabArray<MF>::value,int > FOO>
532- void average_down (const MF& S_fine, MF& S_crse,
533- int scomp, int ncomp, int rr,
534- const IntVect& ngcrse)
535- {
536- average_down (S_fine,S_crse,scomp,ncomp,rr*IntVect::TheUnitVector (),ngcrse);
537- }
538-
539- template <typename MF, std::enable_if_t <IsFabArray<MF>::value,int > FOO>
540- void average_down_matching (const MF& S_fine, MF& S_crse,
541- int fcomp, int ccomp, int ncomp, const IntVect& ratio,
542- const IntVect& ngcrse)
543- {
544- using VT = typename MF::value_type;
545- IndexType ixType = S_fine.ixType ();
546-
547- Dim3 ratioDim3, range;
548- range_for_average_down_matching (ratioDim3, range, ratio, ixType);
549-
550- const VT denom = VT (range.x * range.y * range.z );
551-
552- #ifdef AMREX_USE_GPU
553- if (Gpu::inLaunchRegion () && S_crse.isFusingCandidate ()) {
554- auto const & crsema = S_crse.arrays ();
555- auto const & finema = S_fine.const_arrays ();
556- ParallelFor (S_crse, ngcrse, ncomp,
557- [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
558- {
559- amrex_avgdown (i,j,k,n,crsema[box_no],finema[box_no],ccomp,fcomp,ratioDim3,range,denom);
560- });
561- if (!Gpu::inNoSyncRegion ()) {
562- Gpu::streamSynchronize ();
563- }
564- } else
565- #endif
566- {
567- #ifdef AMREX_USE_OMP
568- #pragma omp parallel if (Gpu::notInLaunchRegion())
569- #endif
570- for (MFIter mfi (S_crse,TilingIfNotGPU ()); mfi.isValid (); ++mfi)
571- {
572- // NOTE: The tilebox is defined at the coarse level.
573- const Box& bx = mfi.growntilebox (ngcrse);
574- Array4<VT> const & crsearr = S_crse.array (mfi);
575- Array4<VT const > const & finearr = S_fine.const_array (mfi);
576- AMREX_HOST_DEVICE_PARALLEL_FOR_4D (bx, ncomp, i, j, k, n,
577- {
578- amrex_avgdown (i,j,k,n,crsearr,finearr,ccomp,fcomp,ratioDim3,range,denom);
579- });
580- }
581- }
582- }
583-
584- void range_for_average_down_matching (Dim3& ratioDim3, Dim3& range, const IntVect& ratio, const IndexType ixType)
585- {
586- ratioDim3 = Dim3{0 ,0 ,0 };
587- range = Dim3{1 ,1 ,1 };
588-
589- ratioDim3.x = ratio[0 ];
590- if (ixType.cellCentered (0 )) {
591- range.x = ratio[0 ];
592- }
593- #if AMREX_SPACEDIM >= 2
594- ratioDim3.y = ratio[1 ];
595- if (ixType.cellCentered (1 )) {
596- range.y = ratio[1 ];
597- }
598- #endif
599- #if AMREX_SPACEDIM >= 3
600- ratioDim3.z = ratio[2 ];
601- if (ixType.cellCentered (2 )) {
602- range.z = ratio[2 ];
603- }
604- #endif
605- }
606-
607- template <typename T>
608- AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
609- void amrex_avgdown (int i, int j, int k, int n,
610- const Array4<T> &crse, const Array4<const T> &fine, int ccomp, int fcomp,
611- const Dim3 &ratio, const Dim3 &range, const T &denom) noexcept
612- {
613- T c = T (0.0 );
614- for ( int kk = k*ratio.z ; kk < k*ratio.z + range.z ; ++kk) {
615- for ( int jj = j*ratio.y ; jj < j*ratio.y + range.y ; ++jj) {
616- for (int ii = i*ratio.x ; ii < i*ratio.x + range.x ; ++ii) {
617- c += fine (ii,jj,kk,n+fcomp);
618- }
619- }
620- }
621- crse (i,j,k,n+ccomp) = c / denom;
622- }
623-
624499template <typename FAB>
625500void average_down_nodal (const FabArray<FAB>& fine, FabArray<FAB>& crse,
626501 const IntVect& ratio, int ngcrse, bool mfiter_is_definitely_safe)
@@ -666,7 +541,7 @@ void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse, int
666541
667542template <typename FAB>
668543void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
669- int scomp, int ncomp, const IntVect& ratio)
544+ int scomp, int ncomp, const IntVect& ratio)
670545{
671546 BL_PROFILE (" amrex::average_down_cells" );
672547 AMREX_ASSERT (S_crse.nComp () == S_fine.nComp ());
@@ -790,6 +665,125 @@ void average_down_cells (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
790665 }
791666}
792667
668+ template <typename FAB>
669+ void average_down (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
670+ int scomp, int ncomp, int rr,
671+ const IntVect& ngcrse)
672+ {
673+ average_down (S_fine,S_crse,scomp,ncomp,rr*IntVect::TheUnitVector (),ngcrse);
674+ }
675+
676+ template <typename FAB>
677+ void average_down (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
678+ int scomp, int ncomp, const IntVect& ratio,
679+ const IntVect& ngcrse)
680+ {
681+ BL_PROFILE (" amrex::average_down" );
682+ AMREX_ASSERT (S_crse.nComp () == S_fine.nComp ());
683+ AMREX_ASSERT (S_crse.ixType () == S_fine.ixType ());
684+
685+ // Coarsen() the fine stuff on processors owning the fine data.
686+ BoxArray crse_S_fine_BA = S_fine.boxArray ();
687+ if (ngcrse != IntVect{0 }) {
688+ crse_S_fine_BA.grow (ngcrse);
689+ }
690+ crse_S_fine_BA.coarsen (ratio);
691+
692+ if (crse_S_fine_BA == S_crse.boxArray () && S_fine.DistributionMap () == S_crse.DistributionMap ())
693+ {
694+ average_down_matching (S_crse, S_fine, scomp, scomp, ncomp, ratio, ngcrse);
695+ }
696+ else
697+ {
698+ FabArray<FAB> crse_S_fine (crse_S_fine_BA, S_fine.DistributionMap (),
699+ ncomp, ngcrse, MFInfo (), DefaultFabFactory<FAB>());
700+ average_down_matching (S_fine, crse_S_fine, 0 , scomp, ncomp, ratio, ngcrse);
701+ S_crse.ParallelCopy (crse_S_fine,0 ,scomp,ncomp);
702+ }
703+ }
704+
705+ template <typename FAB>
706+ void average_down_matching (const FabArray<FAB>& S_fine, FabArray<FAB>& S_crse,
707+ int fcomp, int ccomp, int ncomp, const IntVect& ratio,
708+ const IntVect& ngcrse)
709+ {
710+ using VT = typename MF::value_type;
711+ IndexType ixType = S_fine.ixType ();
712+
713+ Dim3 ratioDim3, range;
714+ range_for_average_down_matching (ratioDim3, range, ratio, ixType);
715+
716+ const VT denom = VT (range.x * range.y * range.z );
717+
718+ #ifdef AMREX_USE_GPU
719+ if (Gpu::inLaunchRegion () && S_crse.isFusingCandidate ()) {
720+ auto const & crsema = S_crse.arrays ();
721+ auto const & finema = S_fine.const_arrays ();
722+ ParallelFor (S_crse, ngcrse, ncomp,
723+ [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
724+ {
725+ amrex_avgdown (i,j,k,n,crsema[box_no],finema[box_no],ccomp,fcomp,ratioDim3,range,denom);
726+ });
727+ if (!Gpu::inNoSyncRegion ()) {
728+ Gpu::streamSynchronize ();
729+ }
730+ } else
731+ #endif
732+ {
733+ #ifdef AMREX_USE_OMP
734+ #pragma omp parallel if (Gpu::notInLaunchRegion())
735+ #endif
736+ for (MFIter mfi (S_crse,TilingIfNotGPU ()); mfi.isValid (); ++mfi)
737+ {
738+ // NOTE: The tilebox is defined at the coarse level.
739+ const Box& bx = mfi.growntilebox (ngcrse);
740+ Array4<VT> const & crsearr = S_crse.array (mfi);
741+ Array4<VT const > const & finearr = S_fine.const_array (mfi);
742+ AMREX_HOST_DEVICE_PARALLEL_FOR_4D (bx, ncomp, i, j, k, n,
743+ {
744+ amrex_avgdown (i,j,k,n,crsearr,finearr,ccomp,fcomp,ratioDim3,range,denom);
745+ });
746+ }
747+ }
748+ }
749+
750+ void range_for_average_down_matching (Dim3& ratioDim3, Dim3& range,
751+ const IntVect& ratio, const IndexType ixType)
752+ {
753+ ratioDim3 = Dim3{0 ,0 ,0 };
754+ range = Dim3{1 ,1 ,1 };
755+
756+ AMREX_D_TERM (
757+ ratioDim3.x = ratio[0 ];
758+ if (ixType.cellCentered (0 )) {
759+ range.x = ratio[0 ];
760+ },
761+ ratioDim3.y = ratio[1 ];
762+ if (ixType.cellCentered (1 )) {
763+ range.y = ratio[1 ];
764+ },
765+ ratioDim3.z = ratio[2 ];
766+ if (ixType.cellCentered (2 )) {
767+ range.z = ratio[2 ];
768+ });
769+ }
770+
771+ template <typename T>
772+ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
773+ void amrex_avgdown (int i, int j, int k, int n,
774+ const Array4<T> &crse, const Array4<const T> &fine, int ccomp, int fcomp,
775+ const Dim3 &ratio, const Dim3 &range, const T &denom) noexcept
776+ {
777+ T c = T (0.0 );
778+ for ( int kk = k*ratio.z ; kk < k*ratio.z + range.z ; ++kk) {
779+ for ( int jj = j*ratio.y ; jj < j*ratio.y + range.y ; ++jj) {
780+ for (int ii = i*ratio.x ; ii < i*ratio.x + range.x ; ++ii) {
781+ c += fine (ii,jj,kk,n+fcomp);
782+ }
783+ }
784+ }
785+ crse (i,j,k,n+ccomp) = c/denom;
786+ }
793787
794788
795789
0 commit comments