void average_down (MultiFab& S_fine, MultiFab& S_crse, int scomp, int ncomp, const IntVect& ratio) { BL_ASSERT(S_crse.nComp() == S_fine.nComp()); // // Coarsen() the fine stuff on processors owning the fine data. // BoxArray crse_S_fine_BA = S_fine.boxArray(); crse_S_fine_BA.coarsen(ratio); MultiFab crse_S_fine(crse_S_fine_BA,ncomp,0); #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(crse_S_fine,true); mfi.isValid(); ++mfi) { // NOTE: The tilebox is defined at the coarse level. const Box& tbx = mfi.tilebox(); // NOTE: We copy from component scomp of the fine fab into component 0 of the crse fab // because the crse fab is a temporary which was made starting at comp 0, it is // not part of the actual crse multifab which came in. BL_FORT_PROC_CALL(BL_AVGDOWN,bl_avgdown) (tbx.loVect(), tbx.hiVect(), BL_TO_FORTRAN_N(S_fine[mfi],scomp), BL_TO_FORTRAN_N(crse_S_fine[mfi],0), ratio.getVect(),&ncomp); } S_crse.copy(crse_S_fine,0,scomp,ncomp); }
BoxList& BoxList::maxSize (const IntVect& chunk) { for (iterator bli = begin(), End = end(); bli != End; ++bli) { IntVect boxlen = bli->size(); const int* len = boxlen.getVect(); for (int i = 0; i < BL_SPACEDIM; i++) { if (len[i] > chunk[i]) { // // Reduce by powers of 2. // int ratio = 1; int bs = chunk[i]; int nlen = len[i]; while ((bs%2 == 0) && (nlen%2 == 0)) { ratio *= 2; bs /= 2; nlen /= 2; } // // Determine number and size of (coarsened) cuts. // const int numblk = nlen/bs + (nlen%bs ? 1 : 0); const int size = nlen/numblk; const int extra = nlen%numblk; // // Number of cuts = number of blocks - 1. // for (int k = 0; k < numblk-1; k++) { // // Compute size of this chunk, expand by power of 2. // const int ksize = (k < extra ? size+1 : size) * ratio; // // Chop from high end. // const int pos = bli->bigEnd(i) - ksize + 1; push_back(bli->chop(i,pos)); } } } // // b has been chopped down to size and pieces split off // have been added to the end of the list so that they // can be checked for splitting (in other directions) later. // } return *this; }
void average_down (MultiFab& S_fine, MultiFab& S_crse, const Geometry& fgeom, const Geometry& cgeom, int scomp, int ncomp, const IntVect& ratio) { if (S_fine.is_nodal() || S_crse.is_nodal()) { BoxLib::Error("Can't use BoxLib::average_down for nodal MultiFab!"); } #if (BL_SPACEDIM == 3) BoxLib::average_down(S_fine, S_crse, scomp, ncomp, ratio); return; #else BL_ASSERT(S_crse.nComp() == S_fine.nComp()); // // Coarsen() the fine stuff on processors owning the fine data. // const BoxArray& fine_BA = S_fine.boxArray(); BoxArray crse_S_fine_BA = fine_BA; crse_S_fine_BA.coarsen(ratio); MultiFab crse_S_fine(crse_S_fine_BA,ncomp,0); MultiFab fvolume; fgeom.GetVolume(fvolume, fine_BA, 0); #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(crse_S_fine,true); mfi.isValid(); ++mfi) { // NOTE: The tilebox is defined at the coarse level. const Box& tbx = mfi.tilebox(); // NOTE: We copy from component scomp of the fine fab into component 0 of the crse fab // because the crse fab is a temporary which was made starting at comp 0, it is // not part of the actual crse multifab which came in. BL_FORT_PROC_CALL(BL_AVGDOWN_WITH_VOL,bl_avgdown_with_vol) (tbx.loVect(), tbx.hiVect(), BL_TO_FORTRAN_N(S_fine[mfi],scomp), BL_TO_FORTRAN_N(crse_S_fine[mfi],0), BL_TO_FORTRAN(fvolume[mfi]), ratio.getVect(),&ncomp); } S_crse.copy(crse_S_fine,0,scomp,ncomp); #endif }
void CellBilinear::interp (const FArrayBox& crse, int crse_comp, FArrayBox& fine, int fine_comp, int ncomp, const Box& fine_region, const IntVect & ratio, const Geometry& /*crse_geom*/, const Geometry& /*fine_geom*/, Array<BCRec>& /*bcr*/, int actual_comp, int actual_state) { BL_PROFILE("CellBilinear::interp()"); #if (BL_SPACEDIM == 3) BoxLib::Error("interp: not implemented"); #endif // // Set up to call FORTRAN. // const int* clo = crse.box().loVect(); const int* chi = crse.box().hiVect(); const int* flo = fine.loVect(); const int* fhi = fine.hiVect(); const int* lo = fine_region.loVect(); const int* hi = fine_region.hiVect(); int num_slope = D_TERM(2,*2,*2)-1; int len0 = crse.box().length(0); int slp_len = num_slope*len0; Array<Real> slope(slp_len); int strp_len = len0*ratio[0]; Array<Real> strip(strp_len); int strip_lo = ratio[0] * clo[0]; int strip_hi = ratio[0] * chi[0]; const Real* cdat = crse.dataPtr(crse_comp); Real* fdat = fine.dataPtr(fine_comp); const int* ratioV = ratio.getVect(); FORT_CBINTERP (cdat,ARLIM(clo),ARLIM(chi),ARLIM(clo),ARLIM(chi), fdat,ARLIM(flo),ARLIM(fhi),ARLIM(lo),ARLIM(hi), D_DECL(&ratioV[0],&ratioV[1],&ratioV[2]),&ncomp, slope.dataPtr(),&num_slope,strip.dataPtr(),&strip_lo,&strip_hi, &actual_comp,&actual_state); }
void NodeBilinear::interp (const FArrayBox& crse, int crse_comp, FArrayBox& fine, int fine_comp, int ncomp, const Box& fine_region, const IntVect& ratio, const Geometry& /*crse_geom */, const Geometry& /*fine_geom */, Array<BCRec>& /*bcr*/, int actual_comp, int actual_state) { BL_PROFILE("NodeBilinear::interp()"); // // Set up to call FORTRAN. // const int* clo = crse.box().loVect(); const int* chi = crse.box().hiVect(); const int* flo = fine.loVect(); const int* fhi = fine.hiVect(); const int* lo = fine_region.loVect(); const int* hi = fine_region.hiVect(); int num_slope = D_TERM(2,*2,*2)-1; int len0 = crse.box().length(0); int slp_len = num_slope*len0; Array<Real> strip(slp_len); const Real* cdat = crse.dataPtr(crse_comp); Real* fdat = fine.dataPtr(fine_comp); const int* ratioV = ratio.getVect(); FORT_NBINTERP (cdat,ARLIM(clo),ARLIM(chi),ARLIM(clo),ARLIM(chi), fdat,ARLIM(flo),ARLIM(fhi),ARLIM(lo),ARLIM(hi), D_DECL(&ratioV[0],&ratioV[1],&ratioV[2]),&ncomp, strip.dataPtr(),&num_slope,&actual_comp,&actual_state); }
// Average fine face-based MultiFab onto crse fine-centered MultiFab. // This routine assumes that the crse BoxArray is a coarsened version of the fine BoxArray. void average_down_faces (PArray<MultiFab>& fine, PArray<MultiFab>& crse, IntVect& ratio) { BL_ASSERT(crse.size() == BL_SPACEDIM); BL_ASSERT(fine.size() == BL_SPACEDIM); BL_ASSERT(crse[0].nComp() == 1); BL_ASSERT(fine[0].nComp() == 1); #ifdef _OPENMP #pragma omp parallel #endif for (int n=0; n<BL_SPACEDIM; ++n) { for (MFIter mfi(crse[n],true); mfi.isValid(); ++mfi) { const Box& tbx = mfi.tilebox(); BL_FORT_PROC_CALL(BL_AVGDOWN_FACES,bl_avgdown_faces) (tbx.loVect(),tbx.hiVect(), BL_TO_FORTRAN(fine[n][mfi]), BL_TO_FORTRAN(crse[n][mfi]), ratio.getVect(),n); } } }
IntVect iMultiFab::maxIndex (int comp, int nghost) const { BL_ASSERT(nghost >= 0 && nghost <= n_grow); IntVect loc; int mx = -std::numeric_limits<int>::max(); #ifdef _OPENMP #pragma omp parallel #endif { IntVect priv_loc; int priv_mx = -std::numeric_limits<int>::max(); for (MFIter mfi(*this); mfi.isValid(); ++mfi) { const Box& box = BoxLib::grow(mfi.validbox(),nghost); const int lmx = get(mfi).max(box,comp); if (lmx > priv_mx) { priv_mx = lmx; priv_loc = get(mfi).maxIndex(box,comp); } } #ifdef _OPENMP #pragma omp critical (imultifab_maxindex) #endif { if (priv_mx > mx) { mx = priv_mx; loc = priv_loc; } } } const int NProcs = ParallelDescriptor::NProcs(); if (NProcs > 1) { Array<int> mxs(1); Array<int> locs(1); if (ParallelDescriptor::IOProcessor()) { mxs.resize(NProcs); locs.resize(NProcs*BL_SPACEDIM); } const int IOProc = ParallelDescriptor::IOProcessorNumber(); ParallelDescriptor::Gather(&mx, 1, mxs.dataPtr(), 1, IOProc); BL_ASSERT(sizeof(IntVect) == sizeof(int)*BL_SPACEDIM); ParallelDescriptor::Gather(loc.getVect(), BL_SPACEDIM, locs.dataPtr(), BL_SPACEDIM, IOProc); if (ParallelDescriptor::IOProcessor()) { mx = mxs[0]; loc = IntVect(D_DECL(locs[0],locs[1],locs[2])); for (int i = 1; i < NProcs; i++) { if (mxs[i] > mx) { mx = mxs[i]; const int j = BL_SPACEDIM * i; loc = IntVect(D_DECL(locs[j+0],locs[j+1],locs[j+2])); } } } ParallelDescriptor::Bcast(const_cast<int*>(loc.getVect()), BL_SPACEDIM, IOProc); } return loc; }