MultiFab_C_to_F::MultiFab_C_to_F (const Geometry& geom, const DistributionMapping& dmap, const BoxArray& ba) { BL_ASSERT(count == 0); count++; int nb = ba.size(); int dm = BL_SPACEDIM; std::vector<int> lo(nb*dm); std::vector<int> hi(nb*dm); for ( int i = 0; i < nb; ++i ) { const Box& bx = BoxLib::enclosedCells(ba[i]); for ( int j = 0; j < dm; ++j ) { lo[j + i*dm] = bx.smallEnd(j); hi[j + i*dm] = bx.bigEnd(j); } } const Box& domain = geom.Domain(); int pm[dm]; for ( int i = 0; i < dm; ++i ) { pm[i] = geom.isPeriodic(i)? 1 : 0; } const Array<int>& pmap = dmap.ProcessorMap(); build_layout_from_c(nb, dm, &lo[0], &hi[0], domain.loVect(), domain.hiVect(), pm, pmap.dataPtr()); }
void advance (MultiFab& old_phi, MultiFab& new_phi, PArray<MultiFab>& flux, Real time, Real dt, const Geometry& geom, PhysBCFunct& physbcf, BCRec& bcr) { // Fill the ghost cells of each grid from the other grids // includes periodic domain boundaries old_phi.FillBoundary(geom.periodicity()); // Fill physical boundaries physbcf.FillBoundary(old_phi, time); int Ncomp = old_phi.nComp(); int ng_p = old_phi.nGrow(); int ng_f = flux[0].nGrow(); const Real* dx = geom.CellSize(); // // Note that this simple example is not optimized. // The following two MFIter loops could be merged // and we do not have to use flux MultiFab. // // Compute fluxes one grid at a time for ( MFIter mfi(old_phi); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); compute_flux(old_phi[mfi].dataPtr(), &ng_p, flux[0][mfi].dataPtr(), flux[1][mfi].dataPtr(), #if (BL_SPACEDIM == 3) flux[2][mfi].dataPtr(), #endif &ng_f, bx.loVect(), bx.hiVect(), (geom.Domain()).loVect(), (geom.Domain()).hiVect(), bcr.vect(), &dx[0]); } // Advance the solution one grid at a time for ( MFIter mfi(old_phi); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); update_phi(old_phi[mfi].dataPtr(), new_phi[mfi].dataPtr(), &ng_p, flux[0][mfi].dataPtr(), flux[1][mfi].dataPtr(), #if (BL_SPACEDIM == 3) flux[2][mfi].dataPtr(), #endif &ng_f, bx.loVect(), bx.hiVect(), &dx[0] , &dt); } }
void MGRadBndry::setBndryConds(const BCRec& bc, const Geometry& geom, IntVect& ratio) { // NOTE: ALL BCLOC VALUES ARE NOW DEFINED AS A LENGTH IN PHYSICAL DIMENSIONS // *RELATIVE* TO THE FACE, NOT IN ABSOLUTE PHYSICAL SPACE const BoxArray& grids = boxes(); int ngrds = grids.size(); const Real* dx = geom.CellSize(); const Box& domain = geom.Domain(); for (OrientationIter fi; fi; ++fi) { Orientation face(fi()); Array<Real> &bloc = bcloc[face]; Array<RadBoundCond> &bctag = bcond[face]; int dir = face.coordDir(); Real delta = dx[dir]*ratio[dir]; int p_bc = (face.isLow() ? bc.lo(dir) : bc.hi(dir)); for (int i = 0; i < ngrds; i++) { const Box& grd = grids[i]; if (domain[face] == grd[face] && !geom.isPeriodic(dir)) { /* // All physical bc values are located on face if (p_bc == EXT_DIR) { bctag[i] = LO_DIRICHLET; bloc[i] = 0.; } else if (p_bc == EXTRAP || p_bc == HOEXTRAP || p_bc == REFLECT_EVEN) { bctag[i] = LO_NEUMANN; bloc[i] = 0.; } else if (p_bc == REFLECT_ODD) { bctag[i] = LO_REFLECT_ODD; bloc[i] = 0.; } */ if (p_bc == LO_DIRICHLET || p_bc == LO_NEUMANN || p_bc == LO_REFLECT_ODD) { bctag[i] = p_bc; bloc[i] = 0.; } else if (p_bc == LO_MARSHAK || p_bc == LO_SANCHEZ_POMRANING) { bctag[i] = p_bc; //gives asymmetric, second-order version of Marshak b.c. // (worked for bbmg, works with nonsymmetric hypre solvers): bloc[i] = 0.; //gives symmetric version of Marshak b.c. //(hypre symmetric solvers ignore bloc and do this automatically): //bloc[i] = -0.5 * dx[dir]; } else { cerr << "MGRadBndry---Not a recognized boundary condition" << endl; exit(1); } } else { // internal bndry bctag[i] = LO_DIRICHLET; bloc[i] = 0.5*delta; } } } }
void writePlotFile (const std::string& dir, const MultiFab& mf, const Geometry& geom) { // // Only let 64 CPUs be writing at any one time. // VisMF::SetNOutFiles(64); // // Only the I/O processor makes the directory if it doesn't already exist. // if (ParallelDescriptor::IOProcessor()) if (!BoxLib::UtilCreateDirectory(dir, 0755)) BoxLib::CreateDirectoryFailed(dir); // // Force other processors to wait till directory is built. // ParallelDescriptor::Barrier(); std::string HeaderFileName = dir + "/Header"; VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size); std::ofstream HeaderFile; HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size()); if (ParallelDescriptor::IOProcessor()) { // // Only the IOProcessor() writes to the header file. // HeaderFile.open(HeaderFileName.c_str(), std::ios::out|std::ios::trunc|std::ios::binary); if (!HeaderFile.good()) BoxLib::FileOpenFailed(HeaderFileName); HeaderFile << "NavierStokes-V1.1\n"; HeaderFile << mf.nComp() << '\n'; for (int ivar = 1; ivar <= mf.nComp(); ivar++) { HeaderFile << "Variable " << ivar << "\n"; } HeaderFile << BL_SPACEDIM << '\n'; HeaderFile << 0 << '\n'; HeaderFile << 0 << '\n'; for (int i = 0; i < BL_SPACEDIM; i++) HeaderFile << geom.ProbLo(i) << ' '; HeaderFile << '\n'; for (int i = 0; i < BL_SPACEDIM; i++) HeaderFile << geom.ProbHi(i) << ' '; HeaderFile << '\n'; HeaderFile << '\n'; HeaderFile << geom.Domain() << ' '; HeaderFile << '\n'; HeaderFile << 0 << ' '; HeaderFile << '\n'; for (int k = 0; k < BL_SPACEDIM; k++) HeaderFile << geom.CellSize()[k] << ' '; HeaderFile << '\n'; HeaderFile << geom.Coord() << '\n'; HeaderFile << "0\n"; } // Build the directory to hold the MultiFab at this level. // The name is relative to the directory containing the Header file. // static const std::string BaseName = "/Cell"; std::string Level = BoxLib::Concatenate("Level_", 0, 1); // // Now for the full pathname of that directory. // std::string FullPath = dir; if (!FullPath.empty() && FullPath[FullPath.length()-1] != '/') FullPath += '/'; FullPath += Level; // // Only the I/O processor makes the directory if it doesn't already exist. // if (ParallelDescriptor::IOProcessor()) if (!BoxLib::UtilCreateDirectory(FullPath, 0755)) BoxLib::CreateDirectoryFailed(FullPath); // // Force other processors to wait till directory is built. // ParallelDescriptor::Barrier(); if (ParallelDescriptor::IOProcessor()) { HeaderFile << 0 << ' ' << mf.boxArray().size() << ' ' << 0 << '\n'; HeaderFile << 0 << '\n'; for (int i = 0; i < mf.boxArray().size(); ++i) { RealBox loc = RealBox(mf.boxArray()[i],geom.CellSize(),geom.ProbLo()); for (int n = 0; n < BL_SPACEDIM; n++) HeaderFile << loc.lo(n) << ' ' << loc.hi(n) << '\n'; } std::string PathNameInHeader = Level; PathNameInHeader += BaseName; HeaderFile << PathNameInHeader << '\n'; } // // Use the Full pathname when naming the MultiFab. // std::string TheFullPath = FullPath; TheFullPath += BaseName; VisMF::Write(mf,TheFullPath); }
void AuxBoundaryData::initialize (const BoxArray& ba, int n_grow, int n_comp, const Geometry& geom) { BL_ASSERT(!m_initialized); const bool verbose = false; const int NProcs = ParallelDescriptor::NProcs(); const Real strt_time = ParallelDescriptor::second(); m_ngrow = n_grow; BoxList gcells = BoxLib::GetBndryCells(ba,n_grow); // // Remove any intersections with periodically shifted valid region. // if (geom.isAnyPeriodic()) { Box dmn = geom.Domain(); for (int d = 0; d < BL_SPACEDIM; d++) if (!geom.isPeriodic(d)) dmn.grow(d,n_grow); for (BoxList::iterator it = gcells.begin(); it != gcells.end(); ) { const Box& isect = *it & dmn; if (isect.ok()) { *it++ = isect; } else { gcells.remove(it++); } } } gcells.simplify(); if (gcells.size() < NProcs) { gcells.maxSize(BL_SPACEDIM == 3 ? 64 : 128); } BoxArray nba(gcells); gcells.clear(); if (nba.size() > 0) { m_fabs.define(nba, n_comp, 0, Fab_allocate); } else { m_empty = true; } if (verbose) { const int IOProc = ParallelDescriptor::IOProcessorNumber(); Real run_time = ParallelDescriptor::second() - strt_time; const int sz = nba.size(); #ifdef BL_LAZY Lazy::QueueReduction( [=] () mutable { #endif ParallelDescriptor::ReduceRealMax(run_time,IOProc); if (ParallelDescriptor::IOProcessor()) std::cout << "AuxBoundaryData::initialize() size = " << sz << ", time = " << run_time << '\n'; #ifdef BL_LAZY }); #endif } m_initialized = true; }
bool ParticleBase::CrseToFine (const BoxArray& cfba, const Array<IntVect>& cells, Array<IntVect>& cfshifts, const Geometry& gm, Array<int>& which, Array<IntVect>& pshifts) { // // We're in AssignDensity(). We want to know whether or not updating // with a particle, will we cross a crse->fine boundary of the level // with coarsened fine BoxArray "cfba". "cells" are as calculated from // CIC_Cells_Fracs(). // const int M = cells.size(); which.resize(M); cfshifts.resize(M); for (int i = 0; i < M; i++) which[i] = 0; bool result = false; for (int i = 0; i < M; i++) { if (cfba.contains(cells[i])) { result = true; which[i] = 1; cfshifts[i] = IntVect::TheZeroVector(); } else if (!gm.Domain().contains(cells[i])) { BL_ASSERT(gm.isAnyPeriodic()); // // Can the cell be shifted into cfba? // const Box bx(cells[i],cells[i]); gm.periodicShift(bx, gm.Domain(), pshifts); if (!pshifts.empty()) { BL_ASSERT(pshifts.size() == 1); const Box& dbx = bx - pshifts[0]; BL_ASSERT(dbx.ok()); if (cfba.contains(dbx)) { // // Note that pshifts[0] is from the coarse perspective. // We'll later need to multiply it by ref ratio to use // at the fine level. // result = true; which[i] = 1; cfshifts[i] = pshifts[0]; } } } } return result; }
static BoxArray GetBndryCells (const BoxArray& ba, int ngrow, const Geometry& geom) { // // First get list of all ghost cells. // BoxList gcells, bcells; for (int i = 0; i < ba.size(); ++i) gcells.join(BoxLib::boxDiff(BoxLib::grow(ba[i],ngrow),ba[i])); // // Now strip out intersections with original BoxArray. // for (BoxList::const_iterator it = gcells.begin(); it != gcells.end(); ++it) { std::vector< std::pair<int,Box> > isects = ba.intersections(*it); if (isects.empty()) bcells.push_back(*it); else { // // Collect all the intersection pieces. // BoxList pieces; for (int i = 0; i < isects.size(); i++) pieces.push_back(isects[i].second); BoxList leftover = BoxLib::complementIn(*it,pieces); bcells.catenate(leftover); } } // // Now strip out overlaps. // gcells.clear(); gcells = BoxLib::removeOverlap(bcells); bcells.clear(); if (geom.isAnyPeriodic()) { Array<IntVect> pshifts(27); const Box& domain = geom.Domain(); for (BoxList::const_iterator it = gcells.begin(); it != gcells.end(); ++it) { if (!domain.contains(*it)) { // // Add in periodic ghost cells shifted to valid region. // geom.periodicShift(domain, *it, pshifts); for (int i = 0; i < pshifts.size(); i++) { const Box& shftbox = *it + pshifts[i]; const Box& ovlp = domain & shftbox; BoxList bl = BoxLib::complementIn(ovlp,BoxList(ba)); bcells.catenate(bl); } } } gcells.catenate(bcells); } return BoxArray(gcells); }