Real BaseFab<Real>::sum (const Box& bx, int comp, int ncomp) const { BL_ASSERT(domain.contains(bx)); BL_ASSERT(comp >= 0 && comp + ncomp <= nvar); const int* _box_lo = bx.loVect(); const int* _box_hi = bx.hiVect(); const int* _datalo = loVect(); const int* _datahi = hiVect(); const Real* _data = dataPtr(comp); Real sm = 0; FORT_FASTSUM(_data, ARLIM(_datalo), ARLIM(_datahi), _box_lo, _box_hi, &ncomp, &sm); return sm; }
void MultiGrid::interpolate (MultiFab& f, const MultiFab& c) { BL_PROFILE("MultiGrid::interpolate()"); // // Use fortran function to interpolate up (prolong) c to f // Note: returns f=f+P(c) , i.e. ADDS interp'd c to f. // // OMP over boxes #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(c); mfi.isValid(); ++mfi) { const int k = mfi.index(); const Box& bx = c.boxArray()[k]; const int nc = f.nComp(); const FArrayBox& cfab = c[mfi]; FArrayBox& ffab = f[mfi]; FORT_INTERP(ffab.dataPtr(), ARLIM(ffab.loVect()), ARLIM(ffab.hiVect()), cfab.dataPtr(), ARLIM(cfab.loVect()), ARLIM(cfab.hiVect()), bx.loVect(), bx.hiVect(), &nc); } }
BaseFab<Real>& BaseFab<Real>::invert (Real val, const Box& bx, int comp, int ncomp) { BL_ASSERT(domain.contains(bx)); BL_ASSERT(comp >= 0 && comp + ncomp <= nvar); const int* _box_lo = bx.loVect(); const int* _box_hi = bx.hiVect(); const int* _datalo = loVect(); const int* _datahi = hiVect(); const Real* _data = dataPtr(comp); FORT_FASTINVERT(_data, ARLIM(_datalo), ARLIM(_datahi), _box_lo, _box_hi, &val, &ncomp); return *this; }
void BaseFab<Real>::copyFromMem (const Box& dstbox, int dstcomp, int numcomp, const Real* src) { BL_ASSERT(box().contains(dstbox)); BL_ASSERT(dstcomp >= 0 && dstcomp+numcomp <= nComp()); if (dstbox.ok()) { Real* data = dataPtr(dstcomp); const int* _box_lo = dstbox.loVect(); const int* _box_hi = dstbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); FORT_FASTCOPYFROMMEM(_box_lo, _box_hi, data, ARLIM(_th_plo), ARLIM(_th_phi), &numcomp, src); } }
void BaseFab<Real>::performSetVal (Real val, const Box& bx, int comp, int ncomp) { BL_ASSERT(domain.contains(bx)); BL_ASSERT(comp >= 0 && comp + ncomp <= nvar); Real* data = dataPtr(comp); if (bx == domain) { for (long i = 0, N = ncomp*numpts; i < N; i++) { *data++ = val; } } else { const int* _box_lo = bx.loVect(); const int* _box_hi = bx.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); FORT_FASTSETVAL(&val, _box_lo, _box_hi, data, ARLIM(_th_plo), ARLIM(_th_phi), &ncomp); } }
void MultiGrid::average (MultiFab& c, const MultiFab& f) { BL_PROFILE("MultiGrid::average()"); // // Use Fortran function to average down (restrict) f to c. // const bool tiling = true; #ifdef _OPENMP #pragma omp parallel #endif for (MFIter cmfi(c,tiling); cmfi.isValid(); ++cmfi) { BL_ASSERT(c.boxArray().get(cmfi.index()) == cmfi.validbox()); const int nc = c.nComp(); const Box& bx = cmfi.tilebox(); FArrayBox& cfab = c[cmfi]; const FArrayBox& ffab = f[cmfi]; FORT_AVERAGE(cfab.dataPtr(), ARLIM(cfab.loVect()), ARLIM(cfab.hiVect()), ffab.dataPtr(), ARLIM(ffab.loVect()), ARLIM(ffab.hiVect()), bx.loVect(), bx.hiVect(), &nc); } }
void BaseFab<Real>::copyToMem (const Box& srcbox, int srccomp, int numcomp, Real* dst) const { BL_ASSERT(box().contains(srcbox)); BL_ASSERT(srccomp >= 0 && srccomp+numcomp <= nComp()); if (srcbox.ok()) { const Real* data = dataPtr(srccomp); const int* _box_lo = srcbox.loVect(); const int* _box_hi = srcbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); FORT_FASTCOPYTOMEM(_box_lo, _box_hi, data, ARLIM(_th_plo), ARLIM(_th_phi), &numcomp, dst); } }
void setup_rhs(MultiFab& rhs, const Geometry& geom, Real a, Real b) { BL_PROFILE("setup_rhs"); Real sigma = 1.0; Real w = 1.0; int ibnd = static_cast<int>(bc_type); // We test the sum of the RHS to check solvability Real sum_rhs = 0.; for ( MFIter mfi(rhs); mfi.isValid(); ++mfi ) { const int* rlo = rhs[mfi].loVect(); const int* rhi = rhs[mfi].hiVect(); const Box& bx = mfi.validbox(); FORT_SET_RHS(rhs[mfi].dataPtr(),ARLIM(rlo),ARLIM(rhi), bx.loVect(),bx.hiVect(),dx, a, b, sigma, w, ibnd); sum_rhs += rhs[mfi].sum(0,1); } for (int n=0; n < BL_SPACEDIM; n++) { sum_rhs *= dx[n]; } ParallelDescriptor::ReduceRealSum(sum_rhs, ParallelDescriptor::IOProcessorNumber()); if (ParallelDescriptor::IOProcessor()) { std::cout << "Sum of RHS : " << sum_rhs << std::endl; } }
void setup_coeffs4(BoxArray& bs, MultiFab& alpha, MultiFab& beta, const Geometry& geom) { ParmParse pp; Real sigma, w; pp.get("sigma", sigma); pp.get("w", w); for ( MFIter mfi(alpha); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); const int* alo = alpha[mfi].loVect(); const int* ahi = alpha[mfi].hiVect(); const Box& abx = alpha[mfi].box(); FORT_SET_ALPHA(alpha[mfi].dataPtr(),ARLIM(alo),ARLIM(ahi), abx.loVect(),abx.hiVect(),dx); const int* clo = beta[mfi].loVect(); const int* chi = beta[mfi].hiVect(); FORT_SET_CC_COEF(beta[mfi].dataPtr(),ARLIM(clo),ARLIM(chi), bx.loVect(),bx.hiVect(),dx, sigma, w); } if (plot_beta == 1) { writePlotFile("BETA4", beta, geom); } }
void setup_coeffs(BoxArray& bs, MultiFab& alpha, PArray<MultiFab>& beta, const Geometry& geom, MultiFab& cc_coef) { BL_PROFILE("setup_coeffs()"); ParmParse pp; Real sigma, w; pp.get("sigma", sigma); pp.get("w", w); for ( MFIter mfi(alpha); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); const int* alo = alpha[mfi].loVect(); const int* ahi = alpha[mfi].hiVect(); FORT_SET_ALPHA(alpha[mfi].dataPtr(),ARLIM(alo),ARLIM(ahi), bx.loVect(),bx.hiVect(),dx); const int* clo = cc_coef[mfi].loVect(); const int* chi = cc_coef[mfi].hiVect(); FORT_SET_CC_COEF(cc_coef[mfi].dataPtr(),ARLIM(clo),ARLIM(chi), bx.loVect(),bx.hiVect(),dx, sigma, w); } BoxLib::average_cellcenter_to_face(beta, cc_coef, geom); if (plot_beta == 1) { writePlotFile("BETA", cc_coef, geom); } }
BaseFab<Real>& BaseFab<Real>::saxpy (Real a, const BaseFab<Real>& src, const Box& srcbox, const Box& destbox, int srccomp, int destcomp, int numcomp) { const int* destboxlo = destbox.loVect(); const int* destboxhi = destbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); const int* _x_lo = srcbox.loVect(); const int* _x_plo = src.loVect(); const int* _x_phi = src.hiVect(); Real* _th_p = dataPtr(destcomp); const Real* _x_p = src.dataPtr(srccomp); FORT_FASTSAXPY(_th_p, ARLIM(_th_plo), ARLIM(_th_phi), D_DECL(destboxlo[0],destboxlo[1],destboxlo[2]), D_DECL(destboxhi[0],destboxhi[1],destboxhi[2]), &a, _x_p, ARLIM(_x_plo), ARLIM(_x_phi), D_DECL(_x_lo[0],_x_lo[1],_x_lo[2]), &numcomp); return *this; }
void compute_analyticSolution(MultiFab& anaSoln, const Array<Real>& offset) { BL_PROFILE("compute_analyticSolution()"); int ibnd = static_cast<int>(bc_type); for (MFIter mfi(anaSoln); mfi.isValid(); ++mfi) { const int* alo = anaSoln[mfi].loVect(); const int* ahi = anaSoln[mfi].hiVect(); const Box& bx = mfi.validbox(); FORT_COMP_ASOL(anaSoln[mfi].dataPtr(), ARLIM(alo), ARLIM(ahi), bx.loVect(),bx.hiVect(),dx, ibnd, offset.dataPtr()); } }
void BaseFab<Real>::performCopy (const BaseFab<Real>& src, const Box& srcbox, int srccomp, const Box& destbox, int destcomp, int numcomp) { BL_ASSERT(destbox.ok()); BL_ASSERT(src.box().contains(srcbox)); BL_ASSERT(box().contains(destbox)); BL_ASSERT(destbox.sameSize(srcbox)); BL_ASSERT(srccomp >= 0 && srccomp+numcomp <= src.nComp()); BL_ASSERT(destcomp >= 0 && destcomp+numcomp <= nComp()); if (destbox == domain && srcbox == src.box()) { Real* data_dst = dataPtr(destcomp); const Real* data_src = src.dataPtr(srccomp); for (long i = 0, N = numcomp*numpts; i < N; i++) { *data_dst++ = *data_src++; } } else { const int* destboxlo = destbox.loVect(); const int* destboxhi = destbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); const int* _x_lo = srcbox.loVect(); const int* _x_plo = src.loVect(); const int* _x_phi = src.hiVect(); Real* _th_p = dataPtr(destcomp); const Real* _x_p = src.dataPtr(srccomp); FORT_FASTCOPY(_th_p, ARLIM(_th_plo), ARLIM(_th_phi), D_DECL(destboxlo[0],destboxlo[1],destboxlo[2]), D_DECL(destboxhi[0],destboxhi[1],destboxhi[2]), _x_p, ARLIM(_x_plo), ARLIM(_x_phi), D_DECL(_x_lo[0],_x_lo[1],_x_lo[2]), &numcomp); } }
Real BaseFab<Real>::norm (const Box& bx, int p, int comp, int ncomp) const { BL_ASSERT(domain.contains(bx)); BL_ASSERT(comp >= 0 && comp + ncomp <= nvar); const int* _box_lo = bx.loVect(); const int* _box_hi = bx.hiVect(); const int* _datalo = loVect(); const int* _datahi = hiVect(); const Real* _data = dataPtr(comp); Real nrm = 0; if (p == 0) { FORT_FASTZERONORM(_data, ARLIM(_datalo), ARLIM(_datahi), _box_lo, _box_hi, &ncomp, &nrm); } else if (p == 1) { FORT_FASTONENORM(_data, ARLIM(_datalo), ARLIM(_datahi), _box_lo, _box_hi, &ncomp, &nrm); } else { BoxLib::Error("BaseFab<Real>::norm(): only p == 0 or p == 1 are supported"); } return nrm; }
void ABec4::cc2ca(const MultiFab& cc, MultiFab& ca, int sComp, int dComp, int nComp) { #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(ca,true); mfi.isValid(); ++mfi) { const FArrayBox& ccf = cc[mfi]; FArrayBox& caf = ca[mfi]; const Box& box = mfi.growntilebox(); BL_ASSERT(ccf.box().contains(BoxLib::grow(box,1))); FORT_CC2CA(box.loVect(), box.hiVect(), ccf.dataPtr(sComp), ARLIM(ccf.box().loVect()), ARLIM(ccf.box().hiVect()), caf.dataPtr(dComp), ARLIM(caf.box().loVect()), ARLIM(caf.box().hiVect()), &nComp); } }
void StateDescriptor::BndryFunc::operator () (Real* data,const int* lo,const int* hi, const int* dom_lo, const int* dom_hi, const Real* dx, const Real* grd_lo, const Real* time, const int* bc, int ng) const { BL_ASSERT(m_gfunc != 0); bool thread_safe = bf_thread_safety(lo, hi, dom_lo, dom_hi, bc, ng); if (thread_safe) { m_gfunc(data,ARLIM(lo),ARLIM(hi),dom_lo,dom_hi,dx,grd_lo,time,bc); } else { #ifdef _OPENMP #pragma omp critical (bndryfunc) #endif m_gfunc(data,ARLIM(lo),ARLIM(hi),dom_lo,dom_hi,dx,grd_lo,time,bc); } }
void MCMultiGrid::average (MultiFab& c, const MultiFab& f) { // // Use Fortran function to average down (restrict) f to c. // for (MFIter cmfi(c); cmfi.isValid(); ++cmfi) { const Box& bx = cmfi.validbox(); int nc = c.nComp(); FArrayBox& cfab = c[cmfi]; const FArrayBox& ffab = f[cmfi]; FORT_AVERAGE( cfab.dataPtr(),ARLIM(cfab.loVect()),ARLIM(cfab.hiVect()), ffab.dataPtr(),ARLIM(ffab.loVect()),ARLIM(ffab.hiVect()), bx.loVect(), bx.hiVect(), &nc); } }
void ABec4::lo_cc2ec(const MultiFab& cc, MultiFab& ec, int sComp, int dComp, int nComp, int dir, bool do_harm) { #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(ec,true); mfi.isValid(); ++mfi) { const FArrayBox& ccf = cc[mfi]; FArrayBox& ecf = ec[mfi]; const Box& box = mfi.growntilebox(); BL_ASSERT(ccf.box().contains(Box(box).enclosedCells().grow(dir,1))); int iharm = (int)do_harm; FORT_LO_CC2EC(box.loVect(), box.hiVect(), ccf.dataPtr(sComp), ARLIM(ccf.box().loVect()), ARLIM(ccf.box().hiVect()), ecf.dataPtr(dComp), ARLIM(ecf.box().loVect()), ARLIM(ecf.box().hiVect()), &nComp,&dir,&iharm); } }
void MCMultiGrid::interpolate (MultiFab& f, const MultiFab& c) { // // Use fortran function to interpolate up (prolong) c to f // Note: returns f=f+P(c) , i.e. ADDS interp'd c to f // for (MFIter fmfi(f); fmfi.isValid(); ++fmfi) { const Box& bx = c.boxArray()[fmfi.index()]; int nc = f.nComp(); const FArrayBox& cfab = c[fmfi]; FArrayBox& ffab = f[fmfi]; FORT_INTERP( ffab.dataPtr(),ARLIM(ffab.loVect()),ARLIM(ffab.hiVect()), cfab.dataPtr(),ARLIM(cfab.loVect()),ARLIM(cfab.hiVect()), bx.loVect(), bx.hiVect(), &nc); } }
void setup_rhs(MultiFab& rhs, const Geometry& geom) { BL_PROFILE("setup_rhs()"); ParmParse pp; Real a, b, sigma, w; pp.get("a", a); pp.get("b", b); pp.get("sigma", sigma); pp.get("w", w); int ibnd = static_cast<int>(bc_type); // We test the sum of the RHS to check solvability Real sum_rhs = 0.; for ( MFIter mfi(rhs); mfi.isValid(); ++mfi ) { const int* rlo = rhs[mfi].loVect(); const int* rhi = rhs[mfi].hiVect(); const Box& bx = rhs[mfi].box(); FORT_SET_RHS(rhs[mfi].dataPtr(),ARLIM(rlo),ARLIM(rhi), bx.loVect(),bx.hiVect(),dx, a, b, sigma, w, ibnd); sum_rhs += rhs[mfi].sum(0,1); } for (int n=0; n < BL_SPACEDIM; n++) { sum_rhs *= dx[n]; } ParallelDescriptor::ReduceRealSum(sum_rhs, ParallelDescriptor::IOProcessorNumber()); if (ParallelDescriptor::IOProcessor()) { std::cout << "Sum of RHS : " << sum_rhs << std::endl; } if (plot_rhs == 1) { writePlotFile("RHS", rhs, geom); } }
void MCLinOp::residual (MultiFab& residL, const MultiFab& rhsL, MultiFab& solnL, int level, MCBC_Mode bc_mode) { apply(residL, solnL, level, bc_mode); for (MFIter solnLmfi(solnL); solnLmfi.isValid(); ++solnLmfi) { int nc = residL.nComp(); const Box& vbox = solnLmfi.validbox(); FArrayBox& resfab = residL[solnLmfi]; const FArrayBox& rhsfab = rhsL[solnLmfi]; FORT_RESIDL( resfab.dataPtr(), ARLIM(resfab.loVect()), ARLIM(resfab.hiVect()), rhsfab.dataPtr(), ARLIM(rhsfab.loVect()), ARLIM(rhsfab.hiVect()), resfab.dataPtr(), ARLIM(resfab.loVect()), ARLIM(resfab.hiVect()), vbox.loVect(), vbox.hiVect(), &nc); } }
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); }
BaseFab<Real>& BaseFab<Real>::protected_divide (const BaseFab<Real>& src, const Box& srcbox, const Box& destbox, int srccomp, int destcomp, int numcomp) { BL_ASSERT(destbox.ok()); BL_ASSERT(src.box().contains(srcbox)); BL_ASSERT(box().contains(destbox)); BL_ASSERT(destbox.sameSize(srcbox)); BL_ASSERT(srccomp >= 0 && srccomp+numcomp <= src.nComp()); BL_ASSERT(destcomp >= 0 && destcomp+numcomp <= nComp()); const int* destboxlo = destbox.loVect(); const int* destboxhi = destbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); const int* _x_lo = srcbox.loVect(); const int* _x_plo = src.loVect(); const int* _x_phi = src.hiVect(); Real* _th_p = dataPtr(destcomp); const Real* _x_p = src.dataPtr(srccomp); FORT_FASTPROTDIVIDE(_th_p, ARLIM(_th_plo), ARLIM(_th_phi), D_DECL(destboxlo[0],destboxlo[1],destboxlo[2]), D_DECL(destboxhi[0],destboxhi[1],destboxhi[2]), _x_p, ARLIM(_x_plo), ARLIM(_x_phi), D_DECL(_x_lo[0],_x_lo[1],_x_lo[2]), &numcomp); return *this; }
void setup_coeffs(BoxArray& bs, MultiFab& alpha, MultiFab beta[], const Geometry& geom) { BL_PROFILE("setup_coeffs"); Real sigma = 1.0; Real w = 1.0; MultiFab cc_coef(bs,Ncomp,1); // cell-centered beta for ( MFIter mfi(alpha); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); const int* alo = alpha[mfi].loVect(); const int* ahi = alpha[mfi].hiVect(); FORT_SET_ALPHA(alpha[mfi].dataPtr(),ARLIM(alo),ARLIM(ahi), bx.loVect(),bx.hiVect(),dx); const int* clo = cc_coef[mfi].loVect(); const int* chi = cc_coef[mfi].hiVect(); FORT_SET_CC_COEF(cc_coef[mfi].dataPtr(),ARLIM(clo),ARLIM(chi), bx.loVect(),bx.hiVect(),dx, sigma, w); } // convert cell-centered beta to edges for ( int n=0; n<BL_SPACEDIM; ++n ) { for ( MFIter mfi(beta[n]); mfi.isValid(); ++mfi ) { int i = mfi.index(); Box bx(bs[i]); const int* clo = cc_coef[mfi].loVect(); const int* chi = cc_coef[mfi].hiVect(); const int* edgelo = beta[n][mfi].loVect(); const int* edgehi = beta[n][mfi].hiVect(); FORT_COEF_TO_EDGES(&n,beta[n][mfi].dataPtr(),ARLIM(edgelo),ARLIM(edgehi), cc_coef[mfi].dataPtr(),ARLIM(clo),ARLIM(chi), bx.loVect(),bx.hiVect()); } } }
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); }
void LinOp::residual (MultiFab& residL, const MultiFab& rhsL, MultiFab& solnL, int level, LinOp::BC_Mode bc_mode, bool local) { BL_PROFILE("LinOp::residual()"); apply(residL, solnL, level, bc_mode, local); const bool tiling = true; #ifdef _OPENMP #pragma omp parallel #endif for (MFIter solnLmfi(solnL,tiling); solnLmfi.isValid(); ++solnLmfi) { const int nc = residL.nComp(); // // Only single-component solves supported (verified) by this class. // BL_ASSERT(nc == 1); const Box& tbx = solnLmfi.tilebox(); BL_ASSERT(gbox[level][solnLmfi.index()] == solnLmfi.validbox()); FArrayBox& residfab = residL[solnLmfi]; const FArrayBox& rhsfab = rhsL[solnLmfi]; FORT_RESIDL( residfab.dataPtr(), ARLIM(residfab.loVect()), ARLIM(residfab.hiVect()), rhsfab.dataPtr(), ARLIM(rhsfab.loVect()), ARLIM(rhsfab.hiVect()), residfab.dataPtr(), ARLIM(residfab.loVect()), ARLIM(residfab.hiVect()), tbx.loVect(), tbx.hiVect(), &nc); } }
void MCLinOp::makeCoefficients (MultiFab& cs, const MultiFab& fn, int level) { const int nc = fn.nComp(); // // Determine index type of incoming MultiFab. // const IndexType iType(fn.boxArray().ixType()); const IndexType cType(D_DECL(IndexType::CELL, IndexType::CELL, IndexType::CELL)); const IndexType xType(D_DECL(IndexType::NODE, IndexType::CELL, IndexType::CELL)); const IndexType yType(D_DECL(IndexType::CELL, IndexType::NODE, IndexType::CELL)); #if (BL_SPACEDIM == 3) const IndexType zType(D_DECL(IndexType::CELL, IndexType::CELL, IndexType::NODE)); #endif int cdir; if (iType == cType) { cdir = -1; } else if (iType == xType) { cdir = 0; } else if (iType == yType) { cdir = 1; } #if (BL_SPACEDIM == 3) else if (iType == zType) { cdir = 2; } #endif else BoxLib::Abort("MCLinOp::makeCoeffients(): Bad index type"); BoxArray d(gbox[level]); if (cdir >= 0) d.surroundingNodes(cdir); int nGrow=0; cs.define(d, nc, nGrow, Fab_allocate); cs.setVal(0.0); const BoxArray& grids = gbox[level]; for (MFIter csmfi(cs); csmfi.isValid(); ++csmfi) { const Box& grd = grids[csmfi.index()]; FArrayBox& csfab = cs[csmfi]; const FArrayBox& fnfab = fn[csmfi]; switch(cdir) { case -1: FORT_AVERAGECC( csfab.dataPtr(), ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()), fnfab.dataPtr(), ARLIM(fnfab.loVect()), ARLIM(fnfab.hiVect()), grd.loVect(), grd.hiVect(), &nc); break; case 0: case 1: case 2: if ( harmavg ) { FORT_HARMONIC_AVERAGEEC( csfab.dataPtr(), ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()), fnfab.dataPtr(), ARLIM(fnfab.loVect()), ARLIM(fnfab.hiVect()), grd.loVect(), grd.hiVect(), &nc, &cdir); } else { FORT_AVERAGEEC( csfab.dataPtr(), ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()), fnfab.dataPtr(), ARLIM(fnfab.loVect()), ARLIM(fnfab.hiVect()), grd.loVect(), grd.hiVect(), &nc, &cdir); } break; default: BoxLib::Error("MCLinOp::makeCoeffients(): bad coefficient coarsening direction!"); } } }
void MCLinOp::applyBC (MultiFab& inout, int level, MCBC_Mode bc_mode) { // // The inout MultiFab must have at least MCLinOp_grow ghost cells // for applyBC() // BL_ASSERT(inout.nGrow() >= MCLinOp_grow); // // The inout MultiFab must have at least Periodic_BC_grow cells for the // algorithms taking care of periodic boundary conditions. // BL_ASSERT(inout.nGrow() >= MCLinOp_grow); // // No coarsened boundary values, cannot apply inhomog at lev>0. // BL_ASSERT(!(level>0 && bc_mode == MCInhomogeneous_BC)); int flagden = 1; // fill in the bndry data and undrrelxr int flagbc = 1; // with values if (bc_mode == MCHomogeneous_BC) flagbc = 0; // nodata if homog int nc = inout.nComp(); BL_ASSERT(nc == numcomp ); inout.setBndry(-1.e30); inout.FillBoundary(); prepareForLevel(level); geomarray[level].FillPeriodicBoundary(inout,0,nc); // // Fill boundary cells. // #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(inout); mfi.isValid(); ++mfi) { const int gn = mfi.index(); BL_ASSERT(gbox[level][gn] == inout.box(gn)); const BndryData::RealTuple& bdl = bgb.bndryLocs(gn); const Array< Array<BoundCond> >& bdc = bgb.bndryConds(gn); const MaskTuple& msk = maskvals[level][gn]; for (OrientationIter oitr; oitr; ++oitr) { const Orientation face = oitr(); FabSet& f = (*undrrelxr[level])[face]; FabSet& td = (*tangderiv[level])[face]; int cdr(face); const FabSet& fs = bgb.bndryValues(face); Real bcl = bdl[face]; const Array<BoundCond>& bc = bdc[face]; const int *bct = (const int*) bc.dataPtr(); const FArrayBox& fsfab = fs[gn]; const Real* bcvalptr = fsfab.dataPtr(); // // Way external derivs stored. // const Real* exttdptr = fsfab.dataPtr(numcomp); const int* fslo = fsfab.loVect(); const int* fshi = fsfab.hiVect(); FArrayBox& inoutfab = inout[gn]; FArrayBox& denfab = f[gn]; FArrayBox& tdfab = td[gn]; #if BL_SPACEDIM==2 int cdir = face.coordDir(), perpdir = -1; if (cdir == 0) perpdir = 1; else if (cdir == 1) perpdir = 0; else BoxLib::Abort("MCLinOp::applyBC(): bad logic"); const Mask& m = *msk[face]; const Mask& mphi = *msk[Orientation(perpdir,Orientation::high)]; const Mask& mplo = *msk[Orientation(perpdir,Orientation::low)]; FORT_APPLYBC( &flagden, &flagbc, &maxorder, inoutfab.dataPtr(), ARLIM(inoutfab.loVect()), ARLIM(inoutfab.hiVect()), &cdr, bct, &bcl, bcvalptr, ARLIM(fslo), ARLIM(fshi), m.dataPtr(), ARLIM(m.loVect()), ARLIM(m.hiVect()), mphi.dataPtr(), ARLIM(mphi.loVect()), ARLIM(mphi.hiVect()), mplo.dataPtr(), ARLIM(mplo.loVect()), ARLIM(mplo.hiVect()), denfab.dataPtr(), ARLIM(denfab.loVect()), ARLIM(denfab.hiVect()), exttdptr, ARLIM(fslo), ARLIM(fshi), tdfab.dataPtr(),ARLIM(tdfab.loVect()),ARLIM(tdfab.hiVect()), inout.box(gn).loVect(), inout.box(gn).hiVect(), &nc, h[level]); #elif BL_SPACEDIM==3 const Mask& mn = *msk[Orientation(1,Orientation::high)]; const Mask& me = *msk[Orientation(0,Orientation::high)]; const Mask& mw = *msk[Orientation(0,Orientation::low)]; const Mask& ms = *msk[Orientation(1,Orientation::low)]; const Mask& mt = *msk[Orientation(2,Orientation::high)]; const Mask& mb = *msk[Orientation(2,Orientation::low)]; FORT_APPLYBC( &flagden, &flagbc, &maxorder, inoutfab.dataPtr(), ARLIM(inoutfab.loVect()), ARLIM(inoutfab.hiVect()), &cdr, bct, &bcl, bcvalptr, ARLIM(fslo), ARLIM(fshi), mn.dataPtr(),ARLIM(mn.loVect()),ARLIM(mn.hiVect()), me.dataPtr(),ARLIM(me.loVect()),ARLIM(me.hiVect()), mw.dataPtr(),ARLIM(mw.loVect()),ARLIM(mw.hiVect()), ms.dataPtr(),ARLIM(ms.loVect()),ARLIM(ms.hiVect()), mt.dataPtr(),ARLIM(mt.loVect()),ARLIM(mt.hiVect()), mb.dataPtr(),ARLIM(mb.loVect()),ARLIM(mb.hiVect()), denfab.dataPtr(), ARLIM(denfab.loVect()), ARLIM(denfab.hiVect()), exttdptr, ARLIM(fslo), ARLIM(fshi), tdfab.dataPtr(),ARLIM(tdfab.loVect()),ARLIM(tdfab.hiVect()), inout.box(gn).loVect(), inout.box(gn).hiVect(), &nc, h[level]); #endif } } #if 0 // This "probably" works, but is not strictly needed just because of the way Bill // coded up the tangential derivative stuff. It's handy code though, so I want to // keep it around/ // Clean up corners: // The problem here is that APPLYBC fills only grow cells normal to the boundary. // As a result, any corner cell on the boundary (either coarse-fine or fine-fine) // is not filled. For coarse-fine, the operator adjusts itself, sliding away from // the box edge to avoid referencing that corner point. On the physical boundary // though, the corner point is needed. Particularly if a fine-fine boundary intersects // the physical boundary, since we want the stencil to be independent of the box // blocking. FillBoundary operations wont fix the problem because the "good" // data we need is living in the grow region of adjacent fabs. So, here we play // the usual games to treat the newly filled grow cells as "valid" data. // Note that we only need to do something where the grids touch the physical boundary. const Geometry& geomlev = geomarray[level]; const BoxArray& grids = inout.boxArray(); const Box& domain = geomlev.Domain(); int nGrow = 1; int src_comp = 0; int num_comp = BL_SPACEDIM; // Lets do a quick check to see if we need to do anything at all here BoxArray BIGba = BoxArray(grids).grow(nGrow); if (! (domain.contains(BIGba.minimalBox())) ) { BoxArray boundary_pieces; Array<int> proc_idxs; Array<Array<int> > old_to_new(grids.size()); const DistributionMapping& dmap=inout.DistributionMap(); for (int d=0; d<BL_SPACEDIM; ++d) { if (! (geomlev.isPeriodic(d)) ) { BoxArray gba = BoxArray(grids).grow(d,nGrow); for (int i=0; i<gba.size(); ++i) { BoxArray new_pieces = BoxLib::boxComplement(gba[i],domain); int size_new = new_pieces.size(); if (size_new>0) { int size_old = boundary_pieces.size(); boundary_pieces.resize(size_old+size_new); proc_idxs.resize(boundary_pieces.size()); for (int j=0; j<size_new; ++j) { boundary_pieces.set(size_old+j,new_pieces[j]); proc_idxs[size_old+j] = dmap[i]; old_to_new[i].push_back(size_old+j); } } } } } proc_idxs.push_back(ParallelDescriptor::MyProc()); MultiFab boundary_data(boundary_pieces,num_comp,nGrow, DistributionMapping(proc_idxs)); for (MFIter mfi(inout); mfi.isValid(); ++mfi) { const FArrayBox& src_fab = inout[mfi]; for (int j=0; j<old_to_new[mfi.index()].size(); ++j) { int new_box_idx = old_to_new[mfi.index()][j]; boundary_data[new_box_idx].copy(src_fab,src_comp,0,num_comp); } } boundary_data.FillBoundary(); // Use a hacked Geometry object to handle the periodic intersections for us. // Here, the "domain" is the plane of cells on non-periodic boundary faces. // and there may be cells over the periodic boundary in the remaining directions. // We do a Geometry::PFB on each non-periodic face to sync these up. if (geomlev.isAnyPeriodic()) { Array<int> is_per(BL_SPACEDIM,0); for (int d=0; d<BL_SPACEDIM; ++d) { is_per[d] = geomlev.isPeriodic(d); } for (int d=0; d<BL_SPACEDIM; ++d) { if (! is_per[d]) { Box tmpLo = BoxLib::adjCellLo(geomlev.Domain(),d,1); Geometry tmpGeomLo(tmpLo,&(geomlev.ProbDomain()),(int)geomlev.Coord(),is_per.dataPtr()); tmpGeomLo.FillPeriodicBoundary(boundary_data); Box tmpHi = BoxLib::adjCellHi(geomlev.Domain(),d,1); Geometry tmpGeomHi(tmpHi,&(geomlev.ProbDomain()),(int)geomlev.Coord(),is_per.dataPtr()); tmpGeomHi.FillPeriodicBoundary(boundary_data); } } } for (MFIter mfi(inout); mfi.isValid(); ++mfi) { int idx = mfi.index(); FArrayBox& dst_fab = inout[mfi]; for (int j=0; j<old_to_new[idx].size(); ++j) { int new_box_idx = old_to_new[mfi.index()][j]; const FArrayBox& src_fab = boundary_data[new_box_idx]; const Box& src_box = src_fab.box(); BoxArray pieces_outside_domain = BoxLib::boxComplement(src_box,domain); for (int k=0; k<pieces_outside_domain.size(); ++k) { const Box& outside = pieces_outside_domain[k] & dst_fab.box(); if (outside.ok()) { dst_fab.copy(src_fab,outside,0,outside,src_comp,num_comp); } } } } } #endif }
void LinOp::makeCoefficients (MultiFab& cs, const MultiFab& fn, int level) { BL_PROFILE("LinOp::makeCoefficients()"); int nc = 1; // // Determine index type of incoming MultiFab. // const IndexType iType(fn.boxArray().ixType()); const IndexType cType(D_DECL(IndexType::CELL, IndexType::CELL, IndexType::CELL)); const IndexType xType(D_DECL(IndexType::NODE, IndexType::CELL, IndexType::CELL)); const IndexType yType(D_DECL(IndexType::CELL, IndexType::NODE, IndexType::CELL)); #if (BL_SPACEDIM == 3) const IndexType zType(D_DECL(IndexType::CELL, IndexType::CELL, IndexType::NODE)); #endif int cdir; if (iType == cType) { cdir = -1; } else if (iType == xType) { cdir = 0; } else if (iType == yType) { cdir = 1; #if (BL_SPACEDIM == 3) } else if (iType == zType) { cdir = 2; #endif } else { BoxLib::Error("LinOp::makeCoeffients: Bad index type"); } BoxArray d(gbox[level]); if (cdir >= 0) d.surroundingNodes(cdir); // // Only single-component solves supported (verified) by this class. // const int nComp=1; const int nGrow=0; cs.define(d, nComp, nGrow, Fab_allocate); const bool tiling = true; switch (cdir) { case -1: #ifdef _OPENMP #pragma omp parallel #endif for (MFIter csmfi(cs,tiling); csmfi.isValid(); ++csmfi) { const Box& tbx = csmfi.tilebox(); FArrayBox& csfab = cs[csmfi]; const FArrayBox& fnfab = fn[csmfi]; FORT_AVERAGECC(csfab.dataPtr(), ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()),fnfab.dataPtr(), ARLIM(fnfab.loVect()),ARLIM(fnfab.hiVect()), tbx.loVect(),tbx.hiVect(), &nc); } break; case 0: case 1: case 2: if (harmavg) { #ifdef _OPENMP #pragma omp parallel #endif for (MFIter csmfi(cs,tiling); csmfi.isValid(); ++csmfi) { const Box& tbx = csmfi.tilebox(); FArrayBox& csfab = cs[csmfi]; const FArrayBox& fnfab = fn[csmfi]; FORT_HARMONIC_AVERAGEEC(csfab.dataPtr(), ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()), fnfab.dataPtr(), ARLIM(fnfab.loVect()), ARLIM(fnfab.hiVect()), tbx.loVect(),tbx.hiVect(), &nc,&cdir); } } else { #ifdef _OPENMP #pragma omp parallel #endif for (MFIter csmfi(cs,tiling); csmfi.isValid(); ++csmfi) { const Box& tbx = csmfi.tilebox(); FArrayBox& csfab = cs[csmfi]; const FArrayBox& fnfab = fn[csmfi]; FORT_AVERAGEEC(csfab.dataPtr(),ARLIM(csfab.loVect()), ARLIM(csfab.hiVect()),fnfab.dataPtr(), ARLIM(fnfab.loVect()),ARLIM(fnfab.hiVect()), tbx.loVect(),tbx.hiVect(), &nc, &cdir); } } break; default: BoxLib::Error("LinOp:: bad coefficient coarsening direction!"); } }
void LinOp::applyBC (MultiFab& inout, int src_comp, int num_comp, int level, LinOp::BC_Mode bc_mode, bool local, int bndry_comp) { BL_PROFILE("LinOp::applyBC()"); // // The inout MultiFab needs at least LinOp_grow ghost cells for applyBC. // BL_ASSERT(inout.nGrow() >= LinOp_grow); // // No coarsened boundary values, cannot apply inhomog at lev>0. // BL_ASSERT(level < numLevels()); BL_ASSERT(!(level > 0 && bc_mode == Inhomogeneous_BC)); int flagden = 1; // Fill in undrrelxr. int flagbc = 1; // Fill boundary data. if (bc_mode == LinOp::Homogeneous_BC) // // No data if homogeneous. // flagbc = 0; const bool cross = true; inout.FillBoundary(src_comp,num_comp,local,cross); prepareForLevel(level); // // Do periodic fixup. // BL_ASSERT(level<geomarray.size()); geomarray[level].FillPeriodicBoundary(inout,src_comp,num_comp,false,local); // // Fill boundary cells. // // OMP over boxes #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(inout); mfi.isValid(); ++mfi) { const int gn = mfi.index(); BL_ASSERT(gbox[level][gn] == inout.box(gn)); BL_ASSERT(level<maskvals.size() && maskvals[level].local_index(gn)>=0); BL_ASSERT(level<lmaskvals.size() && lmaskvals[level].local_index(gn)>=0); BL_ASSERT(level<undrrelxr.size()); const MaskTuple& ma = maskvals[level][gn]; const MaskTuple& lma = lmaskvals[level][gn]; const BndryData::RealTuple& bdl = bgb->bndryLocs(gn); const Array< Array<BoundCond> >& bdc = bgb->bndryConds(gn); for (OrientationIter oitr; oitr; ++oitr) { const Orientation o = oitr(); FabSet& f = (*undrrelxr[level])[o]; int cdr = o; const FabSet& fs = bgb->bndryValues(o); const Mask& m = local ? (*lma[o]) : (*ma[o]); Real bcl = bdl[o]; BL_ASSERT(bdc[o].size()>bndry_comp); int bct = bdc[o][bndry_comp]; const Box& vbx = inout.box(gn); FArrayBox& iofab = inout[mfi]; BL_ASSERT(f.size()>gn); BL_ASSERT(fs.size()>gn); FArrayBox& ffab = f[mfi]; const FArrayBox& fsfab = fs[mfi]; FORT_APPLYBC(&flagden, &flagbc, &maxorder, iofab.dataPtr(src_comp), ARLIM(iofab.loVect()), ARLIM(iofab.hiVect()), &cdr, &bct, &bcl, fsfab.dataPtr(bndry_comp), ARLIM(fsfab.loVect()), ARLIM(fsfab.hiVect()), m.dataPtr(), ARLIM(m.loVect()), ARLIM(m.hiVect()), ffab.dataPtr(), ARLIM(ffab.loVect()), ARLIM(ffab.hiVect()), vbx.loVect(), vbx.hiVect(), &num_comp, h[level]); } } }