MultiFab* Nyx::build_fine_mask() { BL_ASSERT(level > 0); // because we are building a mask for the coarser level if (fine_mask != 0) return fine_mask; BoxArray baf = parent->boxArray(level); baf.coarsen(crse_ratio); const BoxArray& bac = parent->boxArray(level-1); fine_mask = new MultiFab(bac,parent->DistributionMap(level-1), 1,0); fine_mask->setVal(1.0); #ifdef _OPENMP #pragma omp parallel #endif for (MFIter mfi(*fine_mask); mfi.isValid(); ++mfi) { FArrayBox& fab = (*fine_mask)[mfi]; std::vector< std::pair<int,Box> > isects = baf.intersections(fab.box()); for (int ii = 0; ii < isects.size(); ii++) { fab.setVal(0.0,isects[ii].second,0); } } return fine_mask; }
// // What's the slowest way I can think of to compute all the norms?? // Real MFNorm (const MultiFab& mfab, const int exponent, const int srcComp, const int numComp, const int numGrow) { BL_ASSERT (numGrow <= mfab.nGrow()); BoxArray boxes = mfab.boxArray(); boxes.grow(numGrow); // // Get a copy of the multifab // MultiFab mftmp(mfab.boxArray(), numComp, 0); MultiFab::Copy(mftmp,mfab,srcComp,0,numComp,numGrow); // // Calculate the Norms // Real myNorm = 0; if ( exponent == 0 ) { for ( MFIter mftmpmfi(mftmp); mftmpmfi.isValid(); ++mftmpmfi) { mftmp[mftmpmfi].abs(boxes[mftmpmfi.index()], 0, numComp); myNorm = std::max(myNorm, mftmp[mftmpmfi].norm(0, 0, numComp)); } ParallelDescriptor::ReduceRealMax(myNorm); } else if ( exponent == 1 ) { for ( MFIter mftmpmfi(mftmp); mftmpmfi.isValid(); ++mftmpmfi) { mftmp[mftmpmfi].abs(boxes[mftmpmfi.index()], 0, numComp); myNorm += mftmp[mftmpmfi].norm(1, 0, numComp); } ParallelDescriptor::ReduceRealSum(myNorm); } else if ( exponent == 2 ) { for ( MFIter mftmpmfi(mftmp); mftmpmfi.isValid(); ++mftmpmfi) { mftmp[mftmpmfi].abs(boxes[mftmpmfi.index()], 0, numComp); myNorm += pow(mftmp[mftmpmfi].norm(2, 0, numComp), 2); } ParallelDescriptor::ReduceRealSum(myNorm); myNorm = sqrt( myNorm ); } else { BoxLib::Error("Invalid exponent to norm function"); } return myNorm; }
BoxList::BoxList (const BoxArray &ba) : lbox(), btype() { if (ba.size() > 0) btype = ba[0].ixType(); for (int i = 0, N = ba.size(); i < N; ++i) push_back(ba[i]); }
int iMultiFab::norm0 (int comp, const BoxArray& ba, bool local) const { int nm0 = -std::numeric_limits<int>::max(); #ifdef _OPENMP #pragma omp parallel #endif { std::vector< std::pair<int,Box> > isects; int priv_nm0 = -std::numeric_limits<int>::max(); for (MFIter mfi(*this); mfi.isValid(); ++mfi) { ba.intersections(mfi.validbox(),isects); for (int i = 0, N = isects.size(); i < N; i++) { priv_nm0 = std::max(priv_nm0, get(mfi).norm(isects[i].second, 0, comp, 1)); } } #ifdef _OPENMP #pragma omp critical (imultifab_norm0_ba) #endif { nm0 = std::max(nm0, priv_nm0); } } if (!local) ParallelDescriptor::ReduceIntMax(nm0); return nm0; }
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()); }
MCMultiGrid::MCMultiGrid (MCLinOp &_lp) : initialsolution(0), Lp(_lp) { Initialize(); maxiter = def_maxiter; numiter = def_numiter; nu_0 = def_nu_0; nu_1 = def_nu_1; nu_2 = def_nu_2; nu_f = def_nu_f; usecg = def_usecg; verbose = def_verbose; rtol_b = def_rtol_b; atol_b = def_atol_b; nu_b = def_nu_b; numLevelsMAX = def_numLevelsMAX; numlevels = numLevels(); numcomps = _lp.numberComponents(); if ( ParallelDescriptor::IOProcessor() && (verbose > 2) ) { BoxArray tmp = Lp.boxArray(); std::cout << "MCMultiGrid: numlevels = " << numlevels << ": ngrid = " << tmp.size() << ", npts = ["; for ( int i = 0; i < numlevels; ++i ) { if ( i > 0 ) tmp.coarsen(2); std::cout << tmp.d_numPts() << " "; } std::cout << "]" << '\n'; std::cout << "MCMultiGrid: " << numlevels << " multigrid levels created for this solve" << '\n'; } if ( ParallelDescriptor::IOProcessor() && (verbose > 4) ) { std::cout << "Grids: " << '\n'; BoxArray tmp = Lp.boxArray(); for (int i = 0; i < numlevels; ++i) { Orientation face(0, Orientation::low); const DistributionMapping& map = Lp.bndryData().bndryValues(face).DistributionMap(); if (i > 0) tmp.coarsen(2); std::cout << " Level: " << i << '\n'; for (int k = 0; k < tmp.size(); k++) { const Box& b = tmp[k]; std::cout << " [" << k << "]: " << b << " "; for (int j = 0; j < BL_SPACEDIM; j++) std::cout << b.length(j) << ' '; std::cout << ":: " << map[k] << '\n'; } } } }
void BndryRegister::setBoxes (const BoxArray& _grids) { BL_ASSERT(grids.size() == 0); BL_ASSERT(_grids.size() > 0); BL_ASSERT(_grids[0].cellCentered()); grids.define(_grids); // // Check that bndry regions are not allocated. // for (int k = 0; k < 2*BL_SPACEDIM; k++) BL_ASSERT(bndry[k].size() == 0); }
bool ParticleBase::FineToCrse (const ParticleBase& p, int flev, const ParGDBBase* gdb, const Array<IntVect>& fcells, const BoxArray& fvalid, const BoxArray& compfvalid_grown, Array<IntVect>& ccells, Array<Real>& cfracs, Array<int>& which, Array<int>& cgrid, Array<IntVect>& pshifts, std::vector< std::pair<int,Box> >& isects) { BL_ASSERT(gdb != 0); BL_ASSERT(flev > 0); // // We're in AssignDensity(). We want to know whether or not updating // with a particle we'll cross a fine->crse boundary. Note that crossing // a periodic boundary, where the periodic shift lies in our valid region, // is not considered a Fine->Crse crossing. // const int M = fcells.size(); which.resize(M); cgrid.resize(M); ccells.resize(M); cfracs.resize(M); for (int i = 0; i < M; i++) { cgrid[i] = -1; which[i] = 0; } const Box& ibx = BoxLib::grow(gdb->ParticleBoxArray(flev)[p.m_grid],-1); BL_ASSERT(ibx.ok()); if (ibx.contains(p.m_cell)) // // We're strictly contained in our valid box. // We can't cross a fine->crse boundary. // return false; if (!compfvalid_grown.contains(p.m_cell)) // // We're strictly contained in our "valid" region. Note that the valid // region contains any periodically shifted ghost cells that intersect // valid region. // return false; // // Otherwise ... // const Geometry& cgm = gdb->Geom(flev-1); const IntVect& rr = gdb->refRatio(flev-1); const BoxArray& cba = gdb->ParticleBoxArray(flev-1); ParticleBase::CIC_Cells_Fracs(p, cgm.ProbLo(), cgm.CellSize(), cfracs, ccells); bool result = false; for (int i = 0; i < M; i++) { IntVect ccell_refined = ccells[i]*rr; // // We've got to protect against the case when we're at the low // end of the domain because coarsening & refining don't work right // when indices go negative. // for (int dm = 0; dm < BL_SPACEDIM; dm++) ccell_refined[dm] = std::max(ccell_refined[dm], -1); if (!fvalid.contains(ccell_refined)) { result = true; which[i] = 1; Box cbx(ccells[i],ccells[i]); if (!cgm.Domain().contains(ccells[i])) { // // We must be at a periodic boundary. // Find valid box into which we can be periodically shifted. // BL_ASSERT(cgm.isAnyPeriodic()); cgm.periodicShift(cbx, cgm.Domain(), pshifts); BL_ASSERT(pshifts.size() == 1); cbx -= pshifts[0]; ccells[i] -= pshifts[0]; BL_ASSERT(cbx.ok()); BL_ASSERT(cgm.Domain().contains(cbx)); } // // Which grid at the crse level do we need to update? // cba.intersections(cbx,isects,true); BL_ASSERT(!isects.empty()); cgrid[i] = isects[0].first; // The grid ID at crse level that we hit. } } return result; }
void BndryRegister::defineDoit (Orientation _face, IndexType _typ, int _in_rad, int _out_rad, int _extent_rad, BoxArray& fsBA) { BL_PROFILE("BndryRegister::defineDoit()"); BL_ASSERT(grids.size() > 0); const int coord_dir = _face.coordDir(); const int lo_side = _face.isLow(); // // Build the BoxArray on which to define the FabSet on this face. // const int N = grids.size(); fsBA.resize(N); #ifdef _OPENMP #pragma omp parallel for #endif for (int idx = 0; idx < N; ++idx) { Box b; // // First construct proper box for direction normal to face. // if (_out_rad > 0) { if (_typ.ixType(coord_dir) == IndexType::CELL) b = BoxLib::adjCell(grids[idx], _face, _out_rad); else b = BoxLib::bdryNode(grids[idx], _face, _out_rad); if (_in_rad > 0) b.grow(_face.flip(), _in_rad); } else { if (_in_rad > 0) { if (_typ.ixType(coord_dir) == IndexType::CELL) b = BoxLib::adjCell(grids[idx], _face, _in_rad); else b = BoxLib::bdryNode(grids[idx], _face, _in_rad); b.shift(coord_dir, lo_side ? _in_rad : -_in_rad); } else BoxLib::Error("BndryRegister::define(): strange values for in_rad, out_rad"); } // // Now alter box in all other index directions. // for (int dir = 0; dir < BL_SPACEDIM; dir++) { if (dir == coord_dir) continue; if (_typ.ixType(dir) == IndexType::NODE) b.surroundingNodes(dir); if (_extent_rad > 0) b.grow(dir,_extent_rad); } BL_ASSERT(b.ok()); fsBA.set(idx,b); } BL_ASSERT(fsBA.ok()); }
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 }
Real Adv::advance (Real time, Real dt, int iteration, int ncycle) { for (int k = 0; k < NUM_STATE_TYPE; k++) { state[k].allocOldData(); state[k].swapTimeLevels(dt); } MultiFab& S_new = get_new_data(State_Type); const Real prev_time = state[State_Type].prevTime(); const Real cur_time = state[State_Type].curTime(); const Real ctr_time = 0.5*(prev_time + cur_time); const Real* dx = geom.CellSize(); const Real* prob_lo = geom.ProbLo(); // // Get pointers to Flux registers, or set pointer to zero if not there. // FluxRegister *fine = 0; FluxRegister *current = 0; int finest_level = parent->finestLevel(); if (do_reflux && level < finest_level) { fine = &getFluxReg(level+1); fine->setVal(0.0); } if (do_reflux && level > 0) { current = &getFluxReg(level); } MultiFab fluxes[BL_SPACEDIM]; if (do_reflux) { for (int j = 0; j < BL_SPACEDIM; j++) { BoxArray ba = S_new.boxArray(); ba.surroundingNodes(j); fluxes[j].define(ba, NUM_STATE, 0, Fab_allocate); } } // State with ghost cells MultiFab Sborder(grids, NUM_STATE, NUM_GROW); FillPatch(*this, Sborder, NUM_GROW, time, State_Type, 0, NUM_STATE); #ifdef _OPENMP #pragma omp parallel #endif { FArrayBox flux[BL_SPACEDIM], uface[BL_SPACEDIM]; for (MFIter mfi(S_new, true); mfi.isValid(); ++mfi) { const Box& bx = mfi.tilebox(); const FArrayBox& statein = Sborder[mfi]; FArrayBox& stateout = S_new[mfi]; // Allocate fabs for fluxes and Godunov velocities. for (int i = 0; i < BL_SPACEDIM ; i++) { const Box& bxtmp = BoxLib::surroundingNodes(bx,i); flux[i].resize(bxtmp,NUM_STATE); uface[i].resize(BoxLib::grow(bxtmp,1),1); } get_face_velocity(level, ctr_time, D_DECL(BL_TO_FORTRAN(uface[0]), BL_TO_FORTRAN(uface[1]), BL_TO_FORTRAN(uface[2])), dx, prob_lo); advect(time, bx.loVect(), bx.hiVect(), BL_TO_FORTRAN_3D(statein), BL_TO_FORTRAN_3D(stateout), D_DECL(BL_TO_FORTRAN_3D(uface[0]), BL_TO_FORTRAN_3D(uface[1]), BL_TO_FORTRAN_3D(uface[2])), D_DECL(BL_TO_FORTRAN_3D(flux[0]), BL_TO_FORTRAN_3D(flux[1]), BL_TO_FORTRAN_3D(flux[2])), dx, dt); if (do_reflux) { for (int i = 0; i < BL_SPACEDIM ; i++) fluxes[i][mfi].copy(flux[i],mfi.nodaltilebox(i)); } } } if (do_reflux) { if (current) { for (int i = 0; i < BL_SPACEDIM ; i++) current->FineAdd(fluxes[i],i,0,0,NUM_STATE,1.); } if (fine) { for (int i = 0; i < BL_SPACEDIM ; i++) fine->CrseInit(fluxes[i],i,0,0,NUM_STATE,-1.); } } return dt; }
bool BoxList::contains (const BoxArray& ba) const { BoxArray tba(*this); return ba.contains(tba); }
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); }
int main (int argc, char* argv[]) { BoxLib::Initialize(argc,argv); if (argc < 2) print_usage(argc,argv); ParmParse pp; if (pp.contains("help")) print_usage(argc,argv); bool verbose = false; pp.query("verbose",verbose); if (verbose>1) AmrData::SetVerbose(true); std::string infile; pp.get("infile",infile); std::string outfile_DEF; std::string outType = "tec"; #ifdef USE_TEC_BIN_IO bool doBin = true; pp.query("doBin",doBin); outfile_DEF = infile+(doBin ? ".plt" : ".dat" ); #else bool doBin=false; outfile_DEF = infile+".dat"; #endif // bool connect_cc = true; pp.query("connect_cc",connect_cc); std::string outfile(outfile_DEF); pp.query("outfile",outfile); DataServices::SetBatchMode(); Amrvis::FileType fileType(Amrvis::NEWPLT); DataServices dataServices(infile, fileType); if (!dataServices.AmrDataOk()) DataServices::Dispatch(DataServices::ExitRequest, NULL); AmrData& amrData = dataServices.AmrDataRef(); const Array<std::string>& names = amrData.PlotVarNames(); Array<int> comps; if (int nc = pp.countval("comps")) { comps.resize(nc); pp.getarr("comps",comps,0,nc); } else { int sComp = 0; pp.query("sComp",sComp); int nComp = amrData.NComp(); pp.query("nComp",nComp); BL_ASSERT(sComp+nComp <= amrData.NComp()); comps.resize(nComp); for (int i=0; i<nComp; ++i) comps[i] = sComp + i; } Box subbox; if (int nx=pp.countval("box")) { Array<int> barr; pp.getarr("box",barr,0,nx); int d=BL_SPACEDIM; BL_ASSERT(barr.size()==2*d); subbox=Box(IntVect(D_DECL(barr[0],barr[1],barr[2])), IntVect(D_DECL(barr[d],barr[d+1],barr[d+2]))) & amrData.ProbDomain()[0]; } else { subbox = amrData.ProbDomain()[0]; } int finestLevel = amrData.FinestLevel(); pp.query("finestLevel",finestLevel); int Nlev = finestLevel + 1; Array<BoxArray> gridArray(Nlev); Array<Box> subboxArray(Nlev); int nGrowPer = 0; pp.query("nGrowPer",nGrowPer); PArray<Geometry> geom(Nlev); Array<Real> LO(BL_SPACEDIM,0); Array<Real> HI(BL_SPACEDIM,1); RealBox rb(LO.dataPtr(),HI.dataPtr()); int coordSys = 0; Array<int> isPer(BL_SPACEDIM,0); for (int lev=0; lev<Nlev; ++lev) { subboxArray[lev] = (lev==0 ? subbox : Box(subboxArray[lev-1]).refine(amrData.RefRatio()[lev-1])); geom.set(lev,new Geometry(amrData.ProbDomain()[lev],&rb,coordSys,const_cast<int*>(isPer.dataPtr()))); if (nGrowPer>0 && lev==0) { for (int i=0; i<BL_SPACEDIM; ++i) { if (geom[lev].isPeriodic(i)) { if (subboxArray[lev].smallEnd()[i] == amrData.ProbDomain()[lev].smallEnd()[i]) subboxArray[lev].growLo(i,nGrowPer); if (subboxArray[lev].bigEnd()[i] == amrData.ProbDomain()[lev].bigEnd()[i]) subboxArray[lev].growHi(i,nGrowPer); } } } gridArray[lev] = BoxLib::intersect(amrData.boxArray(lev), subboxArray[lev]); if (nGrowPer>0 && geom[lev].isAnyPeriodic() && gridArray[lev].size()>0) { //const Box& probDomain = amrData.ProbDomain()[lev]; const BoxArray& ba = amrData.boxArray(lev); BoxList bladd; Array<IntVect> shifts; for (int i=0; i<ba.size(); ++i) { geom[lev].periodicShift(subboxArray[lev],ba[i],shifts); for (int j=0; j<shifts.size(); ++j) { Box ovlp = Box(ba[i]).shift(shifts[j]) & subboxArray[lev]; if (ovlp.ok()) bladd.push_back(ovlp); } } bladd.simplify(); BoxList blnew(gridArray[lev]); blnew.join(bladd); gridArray[lev] = BoxArray(blnew); } if (!gridArray[lev].size()) { Nlev = lev; finestLevel = Nlev-1; gridArray.resize(Nlev); subboxArray.resize(Nlev); } } const int nGrow = 1; typedef BaseFab<Node> NodeFab; typedef FabArray<NodeFab> MultiNodeFab; PArray<MultiNodeFab> nodes(Nlev,PArrayManage); std::cerr << "Before nodes allocated" << endl; for (int lev=0; lev<Nlev; ++lev) nodes.set(lev,new MultiNodeFab(gridArray[lev],1,nGrow)); std::cerr << "After nodes allocated" << endl; int cnt = 0; typedef std::map<Node,int> NodeMap; NodeMap nodeMap; for (int lev=0; lev<Nlev; ++lev) { for (MFIter fai(nodes[lev]); fai.isValid(); ++fai) { NodeFab& ifab = nodes[lev][fai]; const Box& box = ifab.box() & subboxArray[lev]; for (IntVect iv=box.smallEnd(); iv<=box.bigEnd(); box.next(iv)) ifab(iv,0) = Node(iv,lev,fai.index(),Node::VALID); } if (lev != 0) { const int ref = amrData.RefRatio()[lev-1]; const Box& rangeBox = Box(IntVect::TheZeroVector(), (ref-1)*IntVect::TheUnitVector()); BoxArray bndryCells = GetBndryCells(nodes[lev].boxArray(),ref,geom[lev]); for (MFIter fai(nodes[lev]); fai.isValid(); ++fai) { const Box& box = BoxLib::grow(fai.validbox(),ref) & subboxArray[lev]; NodeFab& ifab = nodes[lev][fai]; std::vector< std::pair<int,Box> > isects = bndryCells.intersections(box); for (int i = 0; i < isects.size(); i++) { Box co = isects[i].second & fai.validbox(); if (co.ok()) std::cout << "BAD ISECTS: " << co << std::endl; const Box& dstBox = isects[i].second; const Box& srcBox = BoxLib::coarsen(dstBox,ref); NodeFab dst(dstBox,1); for (IntVect iv(srcBox.smallEnd()); iv<=srcBox.bigEnd(); srcBox.next(iv)) { const IntVect& baseIV = ref*iv; for (IntVect ivt(rangeBox.smallEnd());ivt<=rangeBox.bigEnd();rangeBox.next(ivt)) dst(baseIV + ivt,0) = Node(iv,lev-1,-1,Node::VALID); } const Box& ovlp = dstBox & ifab.box(); Box mo = ovlp & fai.validbox(); if (mo.ok()) { std::cout << "BAD OVERLAP: " << mo << std::endl; std::cout << " vb: " << fai.validbox() << std::endl; } if (ovlp.ok()) ifab.copy(dst,ovlp,0,ovlp,0,1); } } } // Block out cells covered by finer grid if (lev < finestLevel) { const BoxArray coarsenedFineBoxes = BoxArray(gridArray[lev+1]).coarsen(amrData.RefRatio()[lev]); for (MFIter fai(nodes[lev]); fai.isValid(); ++fai) { NodeFab& ifab = nodes[lev][fai]; const Box& box = ifab.box(); std::vector< std::pair<int,Box> > isects = coarsenedFineBoxes.intersections(box); for (int i = 0; i < isects.size(); i++) { const Box& ovlp = isects[i].second; for (IntVect iv=ovlp.smallEnd(); iv<=ovlp.bigEnd(); ovlp.next(iv)) ifab(iv,0) = Node(iv,lev,fai.index(),Node::COVERED); } } } // Add the unique nodes from this level to the list for (MFIter fai(nodes[lev]); fai.isValid(); ++fai) { NodeFab& ifab = nodes[lev][fai]; const Box& box = fai.validbox() & subboxArray[lev]; for (IntVect iv(box.smallEnd()); iv<=box.bigEnd(); box.next(iv)) { if (ifab(iv,0).type == Node::VALID) { if (ifab(iv,0).level != lev) std::cout << "bad level: " << ifab(iv,0) << std::endl; nodeMap[ifab(iv,0)] = cnt++; } } } } std::cerr << "After nodeMap built, size=" << nodeMap.size() << endl; typedef std::set<Element> EltSet; EltSet elements; for (int lev=0; lev<Nlev; ++lev) { for (MFIter fai(nodes[lev]); fai.isValid(); ++fai) { NodeFab& ifab = nodes[lev][fai]; Box box = ifab.box() & subboxArray[lev]; for (int dir=0; dir<BL_SPACEDIM; ++dir) box.growHi(dir,-1); for (IntVect iv(box.smallEnd()); iv<=box.bigEnd(); box.next(iv)) { #if (BL_SPACEDIM == 2) const Node& n1 = ifab(iv,0); const Node& n2 = ifab(IntVect(iv).shift(BoxLib::BASISV(0)),0); const Node& n3 = ifab(IntVect(iv).shift(IntVect::TheUnitVector()),0); const Node& n4 = ifab(IntVect(iv).shift(BoxLib::BASISV(1)),0); if (n1.type==Node::VALID && n2.type==Node::VALID && n3.type==Node::VALID && n4.type==Node::VALID ) elements.insert(Element(n1,n2,n3,n4)); #else const IntVect& ivu = IntVect(iv).shift(BoxLib::BASISV(2)); const Node& n1 = ifab(iv ,0); const Node& n2 = ifab(IntVect(iv ).shift(BoxLib::BASISV(0)),0); const Node& n3 = ifab(IntVect(iv ).shift(BoxLib::BASISV(0)).shift(BoxLib::BASISV(1)),0); const Node& n4 = ifab(IntVect(iv ).shift(BoxLib::BASISV(1)),0); const Node& n5 = ifab(ivu,0); const Node& n6 = ifab(IntVect(ivu).shift(BoxLib::BASISV(0)),0); const Node& n7 = ifab(IntVect(ivu).shift(BoxLib::BASISV(0)).shift(BoxLib::BASISV(1)),0); const Node& n8 = ifab(IntVect(ivu).shift(BoxLib::BASISV(1)),0); if (n1.type==Node::VALID && n2.type==Node::VALID && n3.type==Node::VALID && n4.type==Node::VALID && n5.type==Node::VALID && n6.type==Node::VALID && n7.type==Node::VALID && n8.type==Node::VALID ) elements.insert(Element(n1,n2,n3,n4,n5,n6,n7,n8)); #endif } } } int nElts = (connect_cc ? elements.size() : nodeMap.size()); std::cerr << "Before connData allocated " << elements.size() << " elements" << endl; Array<int> connData(MYLEN*nElts); std::cerr << "After connData allocated " << elements.size() << " elements" << endl; if (connect_cc) { cnt = 0; for (EltSet::const_iterator it = elements.begin(); it!=elements.end(); ++it) { for (int j=0; j<MYLEN; ++j) { const NodeMap::const_iterator noit = nodeMap.find(*((*it).n[j])); if (noit == nodeMap.end()) { std::cout << "Node not found in node map" << std::endl; std::cout << *((*it).n[j]) << std::endl; } else { connData[cnt++] = noit->second+1; } } } } else { cnt = 1; for (int i=0; i<nElts; ++i) { for (int j=0; j<MYLEN; ++j) { connData[i*MYLEN+j] = cnt++; } } } std::cerr << "Final elements built" << endl; // Invert the map std::vector<Node> nodeVect(nodeMap.size()); for (NodeMap::const_iterator it=nodeMap.begin(); it!=nodeMap.end(); ++it) { if (it->second>=nodeVect.size() || it->second<0) std::cout << "Bad id: " << it->second << " bad node: " << it->first << std::endl; BL_ASSERT(it->second>=0); BL_ASSERT(it->second<nodeVect.size()); nodeVect[it->second] = (*it).first; } std::cerr << "Final nodeVect built (" << nodeVect.size() << " nodes)" << endl; nodeMap.clear(); elements.clear(); nodes.clear(); std::cerr << "Temp nodes, elements cleared" << endl; PArray<MultiFab> fileData(Nlev); int ng = nGrowPer; for (int lev=0; lev<Nlev; ++lev) { if (lev!=0) ng *= amrData.RefRatio()[lev-1]; const BoxArray& ba = gridArray[lev]; fileData.set(lev,new MultiFab(ba,comps.size(),0)); fileData[lev].setVal(1.e30); std::cerr << "My data set alloc'd at lev=" << lev << endl; MultiFab pData, pDataNG; if (ng>0 && geom[lev].isAnyPeriodic()) { const Box& pd = amrData.ProbDomain()[lev]; //const BoxArray& vba = amrData.boxArray(lev); Box shrunkenDomain = pd; for (int i=0; i<BL_SPACEDIM; ++i) if (geom[lev].isPeriodic(i)) shrunkenDomain.grow(i,-ng); const BoxArray edgeVBoxes = BoxLib::boxComplement(pd,shrunkenDomain); pData.define(edgeVBoxes,1,ng,Fab_allocate); pDataNG.define(BoxArray(edgeVBoxes).grow(ng),1,0,Fab_allocate); } for (int i=0; i<comps.size(); ++i) { BoxArray tmpBA = BoxLib::intersect(fileData[lev].boxArray(),amrData.ProbDomain()[lev]); MultiFab tmpMF(tmpBA,1,0); tmpMF.setVal(2.e30); amrData.FillVar(tmpMF,lev,names[comps[i]],0); fileData[lev].copy(tmpMF,0,i,1); if (ng>0 && geom[lev].isAnyPeriodic()) { pData.setVal(3.e30); pDataNG.copy(tmpMF); for (MFIter mfi(pData); mfi.isValid(); ++mfi) pData[mfi].copy(pDataNG[mfi]); amrData.FillVar(pData,lev,names[comps[i]],0); geom[lev].FillPeriodicBoundary(pData); for (MFIter mfi(pData); mfi.isValid(); ++mfi) pDataNG[mfi].copy(pData[mfi]); fileData[lev].copy(pDataNG,0,i,1); } } if (fileData[lev].max(0) > 1.e29) { std::cerr << "Bad mf data" << std::endl; VisMF::Write(fileData[lev],"out.mfab"); BoxLib::Abort(); } } std::cerr << "File data loaded" << endl; int nNodesFINAL = (connect_cc ? nodeVect.size() : nElts*MYLEN ); int nCompsFINAL = BL_SPACEDIM+comps.size(); FABdata tmpData(nNodesFINAL,nCompsFINAL); int tmpDatLen = nCompsFINAL*nNodesFINAL; std::cerr << "Final node data allocated (size=" << tmpDatLen << ")" << endl; //const Array<Array<Real> >& dxLevel = amrData.DxLevel(); // Do not trust dx from file...compute our own Array<Array<Real> > dxLevel(Nlev); for (int i=0; i<Nlev; ++i) { dxLevel[i].resize(BL_SPACEDIM); for (int j=0; j<BL_SPACEDIM; ++j) dxLevel[i][j] = amrData.ProbSize()[j]/amrData.ProbDomain()[i].length(j); } const Array<Real>& plo = amrData.ProbLo(); // Handy structures for loading data in usual fab ordering (transpose of mef/flt ordering) #define BIN_POINT #undef BIN_POINT #ifdef BIN_POINT Real* data = tmpData.dataPtr(); #else /* BLOCK ordering */ Array<Real*> fdat(comps.size()+BL_SPACEDIM); for (int i=0; i<fdat.size(); ++i) fdat[i] = tmpData.dataPtr(i); #endif cnt = 0; int Nnodes = nodeVect.size(); int jGridPrev = 0; int levPrev = -1; for (int i=0; i<Nnodes; ++i) { const Node& node = nodeVect[i]; const Array<Real>& dx = dxLevel[node.level]; const IntVect& iv = node.iv; const BoxArray& grids = fileData[node.level].boxArray(); int jGrid = node.grid; if (jGrid<0) { bool found_it = false; // Try same grid as last time, otherwise search list if (node.level==levPrev && grids[jGridPrev].contains(iv)) { found_it = true; jGrid = jGridPrev; } for (int j=0; j<grids.size() && !found_it; ++j) { if (grids[j].contains(iv)) { found_it = true; jGrid = j; } } BL_ASSERT(found_it); } // Remember these for next time levPrev = node.level; jGridPrev = jGrid; Array<IntVect> ivt; if (connect_cc) { ivt.resize(1,iv); } else { ivt.resize(D_PICK(1,4,8),iv); ivt[1] += BoxLib::BASISV(0); ivt[2] = ivt[1] + BoxLib::BASISV(1); ivt[3] += BoxLib::BASISV(1); #if BLSPACEDIM==3 for (int n=0; n<4; ++n) { ivt[4+n] = iv[n] + BoxLib::BASISV(2); } #endif } for (int j=0; j<ivt.size(); ++j) { Real offset = (connect_cc ? 0.5 : 0); #ifdef BIN_POINT for (int dir=0; dir<BL_SPACEDIM; ++dir) data[cnt++] = plo[dir] + (ivt[j][dir] + offset) * dx[dir]; #else /* BLOCK ordering */ for (int dir=0; dir<BL_SPACEDIM; ++dir) fdat[dir][cnt] = plo[dir] + (ivt[j][dir] + offset) * dx[dir]; #endif /* BIN_POINT */ #ifdef BIN_POINT for (int n=0; n<comps.size(); ++n) { data[cnt++] = fileData[node.level][jGrid](iv,n); } #else /* BLOCK ordering */ for (int n=0; n<comps.size(); ++n) { fdat[n+BL_SPACEDIM][cnt] = fileData[node.level][jGrid](iv,n); } cnt++; #endif /* BIN_POINT */ } } //Collate(tmpData,connData,MYLEN); // // Write output // const int nState = BL_SPACEDIM + comps.size(); std::string vars = D_TERM("X"," Y"," Z"); for (int j=0; j<comps.size(); ++j) vars += " " + amrData.PlotVarNames()[comps[j]]; if (outType == "tec") { #ifdef BIN_POINT string block_or_point = "FEPOINT"; #else /* BLOCK ordering */ string block_or_point = "FEBLOCK"; #endif if (doBin) { #ifdef USE_TEC_BIN_IO INTEGER4 Debug = 0; INTEGER4 VIsDouble = 1; INTEGER4 EltID = D_PICK(0,1,3); TECINI((char*)"Pltfile data", (char*)vars.c_str(), (char*)outfile.c_str(), (char*)".", &Debug, &VIsDouble); INTEGER4 nPts = nNodesFINAL; TECZNE((char*)infile.c_str(), &nPts, &nElts, &EltID, (char*)block_or_point.c_str(), NULL); TECDAT(&tmpDatLen,tmpData.fab.dataPtr(),&VIsDouble); TECNOD(connData.dataPtr()); TECEND(); #else BoxLib::Abort("Need to recompile with USE_TEC_BIN_IO defined"); #endif } else { std::ofstream osf(outfile.c_str(),std::ios::out); osf << D_TERM("VARIABLES= \"X\"", " \"Y\"", " \"Z\""); for (int j=0; j<comps.size(); ++j) osf << " \"" << amrData.PlotVarNames()[comps[j]] << "\""; char buf[100]; sprintf(buf,"%g",amrData.Time()); osf << endl << "ZONE T=\"" << infile << " time = " << buf << "\", N=" << nNodesFINAL << ", E=" << nElts << ", F=" << "FEPOINT" << " ET=" //<< "\", N=" << nPts << ", E=" << nElts << ", F=" << block_or_point << " ET=" << D_PICK("POINT","QUADRILATERAL","BRICK") << endl; for (int i=0; i<nNodesFINAL; ++i) { for (int j=0; j<nState; ++j) osf << tmpData.dataPtr(j)[i] << " "; osf << endl; } for (int i=0; i<nElts; ++i) { for (int j=0; j<MYLEN; ++j) osf << connData[i*MYLEN+j] << " "; osf << endl; } osf << endl; osf.close(); } } else { std::ofstream ofs; std::ostream* os = (outfile=="-" ? (std::ostream*)(&std::cout) : (std::ostream*)(&ofs) ); if (outfile!="-") ofs.open(outfile.c_str(),std::ios::out|std::ios::trunc|std::ios::binary); (*os) << infile << " time = " << amrData.Time() << endl; (*os) << vars << endl; (*os) << nElts << " " << MYLEN << endl; tmpData.fab.writeOn(*os); (*os).write((char*)connData.dataPtr(),sizeof(int)*connData.size()); if (outfile!="-") ofs.close(); } BoxLib::Finalize(); return 0; }
void main_main () { // What time is it now? We'll use this to compute total run time. Real strt_time = ParallelDescriptor::second(); // AMREX_SPACEDIM: number of dimensions int n_cell, max_grid_size; Vector<int> bc_lo(AMREX_SPACEDIM,0); Vector<int> bc_hi(AMREX_SPACEDIM,0); // inputs parameters { // ParmParse is way of reading inputs from the inputs file ParmParse pp; // We need to get n_cell from the inputs file - this is the // number of cells on each side of a square (or cubic) domain. pp.get("n_cell", n_cell); // The domain is broken into boxes of size max_grid_size max_grid_size = 32; pp.query("max_grid_size", max_grid_size); } Vector<int> is_periodic(AMREX_SPACEDIM,0); for (int idim=0; idim < AMREX_SPACEDIM; ++idim) { is_periodic[idim] = 1; } // make BoxArray and Geometry BoxArray ba; Geometry geom; { IntVect dom_lo(AMREX_D_DECL( 0, 0, 0)); IntVect dom_hi(AMREX_D_DECL(n_cell-1, n_cell-1, n_cell-1)); Box domain(dom_lo, dom_hi); // Initialize the boxarray "ba" from the single box "bx" ba.define(domain); // Break up boxarray "ba" into chunks no larger than // "max_grid_size" along a direction ba.maxSize(max_grid_size); // This defines the physical box, [0, 1] in each direction. RealBox real_box({AMREX_D_DECL(0.0, 0.0, 0.0)}, {AMREX_D_DECL(1.0, 1.0, 1.0)}); // This defines a Geometry object geom.define(domain, &real_box, CoordSys::cartesian, is_periodic.data()); } // Nghost = number of ghost cells for each array int Nghost = 0; // do the runtime parameter initializations and microphysics inits if (ParallelDescriptor::IOProcessor()) { std::cout << "reading extern runtime parameters ..." << std::endl; } ParmParse ppa("amr"); std::string probin_file = "probin"; ppa.query("probin_file", probin_file); const int probin_file_length = probin_file.length(); Vector<int> probin_file_name(probin_file_length); for (int i = 0; i < probin_file_length; i++) probin_file_name[i] = probin_file[i]; init_unit_test(probin_file_name.dataPtr(), &probin_file_length); // Ncomp = number of components for each array int Ncomp = -1; init_variables(); get_ncomp(&Ncomp); int name_len = -1; get_name_len(&name_len); // get the variable names Vector<std::string> varnames; for (int i=0; i<Ncomp; i++) { char* cstring[name_len+1]; get_var_name(cstring, &i); std::string name(*cstring); varnames.push_back(name); } // time = starting time in the simulation Real time = 0.0; // How Boxes are distrubuted among MPI processes DistributionMapping dm(ba); // we allocate our main multifabs MultiFab state(ba, dm, Ncomp, Nghost); // Initialize the state and compute the different thermodynamics // by inverting the EOS for ( MFIter mfi(state); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); #pragma gpu do_eos(AMREX_INT_ANYD(bx.loVect()), AMREX_INT_ANYD(bx.hiVect()), BL_TO_FORTRAN_ANYD(state[mfi]), n_cell); } std::string name = "test_eos."; // get the name of the EOS int eos_len = -1; get_eos_len(&eos_len); char* eos_string[eos_len+1]; get_eos_name(eos_string); std::string eos(*eos_string); // Write a plotfile WriteSingleLevelPlotfile(name + eos, state, varnames, geom, time, 0); // Call the timer again and compute the maximum difference between // the start time and stop time over all processors Real stop_time = ParallelDescriptor::second() - strt_time; const int IOProc = ParallelDescriptor::IOProcessorNumber(); ParallelDescriptor::ReduceRealMax(stop_time, IOProc); // Tell the I/O Processor to write out the "run time" amrex::Print() << "Run time = " << stop_time << std::endl; }
int main (int argc, char* argv[]) { BoxLib::Initialize(argc,argv); std::cout << std::setprecision(10); if (argc < 2) { std::cerr << "usage: " << argv[0] << " inputsfile [options]" << '\n'; exit(-1); } ParmParse pp; int n; BoxArray bs; #if BL_SPACEDIM == 2 Box domain(IntVect(0,0),IntVect(11,11)); std::string boxfile("gr.2_small_a") ; #elif BL_SPACEDIM == 3 Box domain(IntVect(0,0,0),IntVect(11,11,11)); std::string boxfile("grids/gr.3_2x3x4") ; #endif pp.query("boxes", boxfile); std::ifstream ifs(boxfile.c_str(), std::ios::in); if (!ifs) { std::string msg = "problem opening grids file: "; msg += boxfile.c_str(); BoxLib::Abort(msg.c_str()); } ifs >> domain; if (ParallelDescriptor::IOProcessor()) std::cout << "domain: " << domain << std::endl; bs.readFrom(ifs); if (ParallelDescriptor::IOProcessor()) std::cout << "grids:\n" << bs << std::endl; Geometry geom(domain); const Real* H = geom.CellSize(); int ratio=2; pp.query("ratio", ratio); // allocate/init soln and rhs int Ncomp=BL_SPACEDIM; int Nghost=0; int Ngrids=bs.size(); MultiFab soln(bs, Ncomp, Nghost, Fab_allocate); soln.setVal(0.0); MultiFab out(bs, Ncomp, Nghost, Fab_allocate); MultiFab rhs(bs, Ncomp, Nghost, Fab_allocate); rhs.setVal(0.0); for(MFIter rhsmfi(rhs); rhsmfi.isValid(); ++rhsmfi) { FORT_FILLRHS(rhs[rhsmfi].dataPtr(), ARLIM(rhs[rhsmfi].loVect()),ARLIM(rhs[rhsmfi].hiVect()), H,&Ncomp); } // Create the boundary object MCViscBndry vbd(bs,geom); BCRec phys_bc; Array<int> lo_bc(BL_SPACEDIM), hi_bc(BL_SPACEDIM); pp.getarr("lo_bc",lo_bc,0,BL_SPACEDIM); pp.getarr("hi_bc",hi_bc,0,BL_SPACEDIM); for (int i = 0; i < BL_SPACEDIM; i++) { phys_bc.setLo(i,lo_bc[i]); phys_bc.setHi(i,hi_bc[i]); } // Create the BCRec's interpreted by ViscBndry objects #if BL_SPACEDIM==2 Array<BCRec> pbcarray(4); pbcarray[0] = BCRec(D_DECL(REFLECT_ODD,REFLECT_EVEN,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[1] = BCRec(D_DECL(REFLECT_EVEN,REFLECT_ODD,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[2] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[3] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); #elif BL_SPACEDIM==3 Array<BCRec> pbcarray(12); #if 1 pbcarray[0] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[1] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[2] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[3] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[4] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[5] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[6] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[7] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[8] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[9] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[10] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[11] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); #else for (int i = 0; i < 12; i++) pbcarray[i] = phys_bc; #endif #endif Nghost = 1; // need space for bc info MultiFab fine(bs,Ncomp,Nghost,Fab_allocate); for(MFIter finemfi(fine); finemfi.isValid(); ++finemfi) { FORT_FILLFINE(fine[finemfi].dataPtr(), ARLIM(fine[finemfi].loVect()),ARLIM(fine[finemfi].hiVect()), H,&Ncomp); } // Create "background coarse data" Box crse_bx = Box(domain).coarsen(ratio).grow(1); BoxArray cba(crse_bx); cba.maxSize(32); Real h_crse[BL_SPACEDIM]; for (n=0; n<BL_SPACEDIM; n++) h_crse[n] = H[n]*ratio; MultiFab crse_mf(cba, Ncomp, 0); // FArrayBox crse_fab(crse_bx,Ncomp); for (MFIter mfi(crse_mf); mfi.isValid(); ++mfi) { FORT_FILLCRSE(crse_mf[mfi].dataPtr(), ARLIM(crse_mf[mfi].loVect()),ARLIM(crse_mf[mfi].hiVect()), h_crse,&Ncomp); } // Create coarse boundary register, fill w/data from coarse FAB int bndry_InRad=0; int bndry_OutRad=1; int bndry_Extent=1; BoxArray cbs = BoxArray(bs).coarsen(ratio); BndryRegister cbr(cbs,bndry_InRad,bndry_OutRad,bndry_Extent,Ncomp); for (OrientationIter face; face; ++face) { Orientation f = face(); FabSet& bnd_fs(cbr[f]); bnd_fs.copyFrom(crse_mf, 0, 0, 0, Ncomp); } // Interpolate crse data to fine boundary, where applicable int cbr_Nstart=0; int fine_Nstart=0; int bndry_Nstart=0; vbd.setBndryValues(cbr,cbr_Nstart,fine,fine_Nstart, bndry_Nstart,Ncomp,ratio,pbcarray); Nghost = 1; // other variables don't need extra space DivVis lp(vbd,H); Real a = 0.0; Real b[BL_SPACEDIM]; b[0] = 1.0; b[1] = 1.0; #if BL_SPACEDIM>2 b[2] = 1.0; #endif MultiFab acoefs; int NcompA = (BL_SPACEDIM == 2 ? 2 : 1); acoefs.define(bs, NcompA, Nghost, Fab_allocate); acoefs.setVal(a); MultiFab bcoefs[BL_SPACEDIM]; for (n=0; n<BL_SPACEDIM; ++n) { BoxArray bsC(bs); bcoefs[n].define(bsC.surroundingNodes(n), 1, Nghost, Fab_allocate); #if 1 for(MFIter bmfi(bcoefs[n]); bmfi.isValid(); ++bmfi) { FORT_MAKEMU(bcoefs[n][bmfi].dataPtr(), ARLIM(bcoefs[n][bmfi].loVect()),ARLIM(bcoefs[n][bmfi].hiVect()),H,n); } #else bcoefs[n].setVal(b[n]); #endif } // -->> over dimension lp.setCoefficients(acoefs, bcoefs); #if 1 lp.maxOrder(4); #endif Nghost = 1; MultiFab tsoln(bs, Ncomp, Nghost, Fab_allocate); tsoln.setVal(0.0); #if 1 tsoln.copy(fine); #endif #if 0 // testing apply lp.apply(out,tsoln); Box subbox = out[0].box(); Real n1 = out[0].norm(subbox,1,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealSum(n1); if (ParallelDescriptor::IOProcessor()) { cout << "n1 output is "<<n1<<std::endl; } out.minus(rhs,0,BL_SPACEDIM,0); // special to single grid prob Real n2 = out[0].norm(subbox,1,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealSum(n2); if (ParallelDescriptor::IOProcessor()) { cout << "n2 difference is "<<n2<<std::endl; } #if 0 subbox.grow(-1); Real n3 = out[0].norm(subbox,0,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealMax(n3); if (ParallelDescriptor::IOProcessor()) { cout << "n3 difference is "<<n3<<std::endl; } #endif #endif const IntVect refRatio(D_DECL(2,2,2)); const Real bgVal = 1.0; #if 1 #ifndef NDEBUG // testing flux computation BoxArray xfluxbox(bs); xfluxbox.surroundingNodes(0); MultiFab xflux(xfluxbox,Ncomp,Nghost,Fab_allocate); xflux.setVal(1.e30); BoxArray yfluxbox(bs); yfluxbox.surroundingNodes(1); MultiFab yflux(yfluxbox,Ncomp,Nghost,Fab_allocate); yflux.setVal(1.e30); #if BL_SPACEDIM>2 BoxArray zfluxbox(bs); zfluxbox.surroundingNodes(2); MultiFab zflux(zfluxbox,Ncomp,Nghost,Fab_allocate); zflux.setVal(1.e30); #endif lp.compFlux(xflux, yflux, #if BL_SPACEDIM>2 zflux, #endif tsoln); // Write fluxes //writeMF(&xflux,"xflux.mfab"); //writeMF(&yflux,"yflux.mfab"); #if BL_SPACEDIM>2 //writeMF(&zflux,"zflux.mfab"); #endif #endif #endif Real tolerance = 1.0e-10; pp.query("tol", tolerance); Real tolerance_abs = 1.0e-10; pp.query("tol_abs", tolerance_abs); #if 0 cout << "Bndry Data object:" << std::endl; cout << lp.bndryData() << std::endl; #endif #if 0 bool use_mg_pre = false; MCCGSolver cg(lp,use_mg_pre); cg.solve(soln,rhs,tolerance,tolerance_abs); #else MCMultiGrid mg(lp); mg.solve(soln,rhs,tolerance,tolerance_abs); #endif #if 0 cout << "MCLinOp object:" << std::endl; cout << lp << std::endl; #endif VisMF::Write(soln,"soln"); #if 0 // apply operator to soln to see if really satisfies eqn tsoln.copy(soln); lp.apply(out,tsoln); soln.copy(out); // Output "apply" results on soln VisMF::Write(soln,"apply"); // Compute truncation for (MFIter smfi(soln); smfi.isValid(); ++smfi) { soln[smfi] -= fine[smfi]; } for( int icomp=0; icomp < BL_SPACEDIM ; icomp++ ) { Real solnMin = soln.min(icomp); Real solnMax = soln.max(icomp); ParallelDescriptor::ReduceRealMin(solnMin); ParallelDescriptor::ReduceRealMax(solnMax); if (ParallelDescriptor::IOProcessor()) { cout << icomp << " "<<solnMin << " " << solnMax <<std::endl; } } // Output truncation VisMF::Write(soln,"trunc"); #endif int dumpLp=0; pp.query("dumpLp",dumpLp); bool write_lp = (dumpLp == 1 ? true : false); if (write_lp) std::cout << lp << std::endl; // Output trunc ParallelDescriptor::EndParallel(); }
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; }
void main_main () { // What time is it now? We'll use this to compute total run time. Real strt_time = ParallelDescriptor::second(); std::cout << std::setprecision(15); int n_cell, max_grid_size, nsteps, plot_int, is_periodic[BL_SPACEDIM]; // Boundary conditions Array<int> lo_bc(BL_SPACEDIM), hi_bc(BL_SPACEDIM); // inputs parameters { // ParmParse is way of reading inputs from the inputs file ParmParse pp; // We need to get n_cell from the inputs file - this is the number of cells on each side of // a square (or cubic) domain. pp.get("n_cell",n_cell); // Default nsteps to 0, allow us to set it to something else in the inputs file pp.get("max_grid_size",max_grid_size); // Default plot_int to 1, allow us to set it to something else in the inputs file // If plot_int < 0 then no plot files will be written plot_int = 1; pp.query("plot_int",plot_int); // Default nsteps to 0, allow us to set it to something else in the inputs file nsteps = 0; pp.query("nsteps",nsteps); // Boundary conditions - default is periodic (INT_DIR) for (int i = 0; i < BL_SPACEDIM; ++i) { lo_bc[i] = hi_bc[i] = INT_DIR; // periodic boundaries are interior boundaries } pp.queryarr("lo_bc",lo_bc,0,BL_SPACEDIM); pp.queryarr("hi_bc",hi_bc,0,BL_SPACEDIM); } // make BoxArray and Geometry BoxArray ba; Geometry geom; { IntVect dom_lo(IntVect(D_DECL(0,0,0))); IntVect dom_hi(IntVect(D_DECL(n_cell-1, n_cell-1, n_cell-1))); Box domain(dom_lo, dom_hi); // Initialize the boxarray "ba" from the single box "bx" ba.define(domain); // Break up boxarray "ba" into chunks no larger than "max_grid_size" along a direction ba.maxSize(max_grid_size); // This defines the physical size of the box. Right now the box is [-1,1] in each direction. RealBox real_box; for (int n = 0; n < BL_SPACEDIM; n++) { real_box.setLo(n,-1.0); real_box.setHi(n, 1.0); } // This says we are using Cartesian coordinates int coord = 0; // This sets the boundary conditions to be doubly or triply periodic int is_periodic[BL_SPACEDIM]; for (int i = 0; i < BL_SPACEDIM; i++) { is_periodic[i] = 0; if (lo_bc[i] == 0 && hi_bc[i] == 0) { is_periodic[i] = 1; } } // This defines a Geometry object geom.define(domain,&real_box,coord,is_periodic); } // Boundary conditions PhysBCFunct physbcf; BCRec bcr(&lo_bc[0], &hi_bc[0]); physbcf.define(geom, bcr, BndryFunctBase(phifill)); // phifill is a fortran function // define dx[] const Real* dx = geom.CellSize(); // Nghost = number of ghost cells for each array int Nghost = 1; // Ncomp = number of components for each array int Ncomp = 1; // time = starting time in the simulation Real time = 0.0; // we allocate two phi multifabs; one will store the old state, the other the new // we swap the indices each time step to avoid copies of new into old PArray<MultiFab> phi(2, PArrayManage); phi.set(0, new MultiFab(ba, Ncomp, Nghost)); phi.set(1, new MultiFab(ba, Ncomp, Nghost)); // Initialize both to zero (just because) phi[0].setVal(0.0); phi[1].setVal(0.0); // Initialize phi[init_index] by calling a Fortran routine. // MFIter = MultiFab Iterator int init_index = 0; for ( MFIter mfi(phi[init_index]); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); init_phi(phi[init_index][mfi].dataPtr(), bx.loVect(), bx.hiVect(), &Nghost, geom.CellSize(), geom.ProbLo(), geom.ProbHi()); } // compute the time step Real dt = 0.9*dx[0]*dx[0] / (2.0*BL_SPACEDIM); // Write a plotfile of the initial data if plot_int > 0 (plot_int was defined in the inputs file) if (plot_int > 0) { int n = 0; const std::string& pltfile = BoxLib::Concatenate("plt",n,5); writePlotFile(pltfile, phi[init_index], geom, time); } // build the flux multifabs PArray<MultiFab> flux(BL_SPACEDIM, PArrayManage); for (int dir = 0; dir < BL_SPACEDIM; dir++) { // flux(dir) has one component, zero ghost cells, and is nodal in direction dir BoxArray edge_ba = ba; edge_ba.surroundingNodes(dir); flux.set(dir, new MultiFab(edge_ba, 1, 0)); } int old_index = init_index; for (int n = 1; n <= nsteps; n++, old_index = 1 - old_index) { int new_index = 1 - old_index; // new_phi = old_phi + dt * (something) advance(phi[old_index], phi[new_index], flux, time, dt, geom, physbcf, bcr); time = time + dt; // Tell the I/O Processor to write out which step we're doing if (ParallelDescriptor::IOProcessor()) std::cout << "Advanced step " << n << std::endl; // Write a plotfile of the current data (plot_int was defined in the inputs file) if (plot_int > 0 && n%plot_int == 0) { const std::string& pltfile = BoxLib::Concatenate("plt",n,5); writePlotFile(pltfile, phi[new_index], geom, time); } } // Call the timer again and compute the maximum difference between the start time and stop time // over all processors Real stop_time = ParallelDescriptor::second() - strt_time; const int IOProc = ParallelDescriptor::IOProcessorNumber(); ParallelDescriptor::ReduceRealMax(stop_time,IOProc); // Tell the I/O Processor to write out the "run time" if (ParallelDescriptor::IOProcessor()) { std::cout << "Run time = " << stop_time << std::endl; } }
int main (int argc, char* argv[]) { amrex::Initialize(argc,argv); if (argc < 2) print_usage(argc,argv); ParmParse pp; if (pp.contains("help")) print_usage(argc,argv); bool verbose = false; if (pp.contains("verbose")) { verbose = true; AmrData::SetVerbose(true); } std::string infile; pp.get("infile",infile); if (ParallelDescriptor::IOProcessor()) std::cout << "Reading " << infile << "..."; DataServices::SetBatchMode(); Amrvis::FileType fileType(Amrvis::NEWPLT); DataServices dataServices(infile, fileType); if( ! dataServices.AmrDataOk()) DataServices::Dispatch(DataServices::ExitRequest, NULL); if (ParallelDescriptor::IOProcessor()) std::cout << "Done reading plot file" << std::endl; AmrData& amrData = dataServices.AmrDataRef(); int finestLevel = amrData.FinestLevel(); pp.query("finestLevel",finestLevel); finestLevel=std::min(finestLevel,amrData.FinestLevel()); int Nlev = finestLevel + 1; if (ParallelDescriptor::IOProcessor()) std::cout << "... finest level " << finestLevel << std::endl; Vector<int> comps; if (int nc = pp.countval("comps")) { comps.resize(nc); pp.getarr("comps",comps,0,nc); } else { int sComp = 0; pp.query("sComp",sComp); int nComp = 1; pp.query("nComp",nComp); BL_ASSERT(sComp+nComp <= amrData.NComp()); comps.resize(nComp); std::cout << "NCOMP NOW " << nComp << std::endl; for (int i=0; i<nComp; ++i) comps[i] = sComp + i; } int nComp = comps.size(); const Vector<string>& plotVarNames=amrData.PlotVarNames(); Vector<string> inVarNames(nComp); Vector<int> destFillComps(nComp); for (int i=0; i<nComp; ++i) { inVarNames[i] = plotVarNames[comps[i]]; std::cout << "plotVarNames " << plotVarNames[comps[i]] << std::endl;; destFillComps[i] = i; } const int nGrow = 0; if (ParallelDescriptor::IOProcessor() && verbose>0) { cerr << "Will read the following states: "; for (int i=0; i<nComp; ++i) cerr << " " << amrData.StateNumber(inVarNames[i]) << " (" << inVarNames[i] << ")" ; cerr << '\n'; } const Box& probDomain = amrData.ProbDomain()[finestLevel]; int dir=BL_SPACEDIM-1; pp.query("dir",dir); const IntVect lo=probDomain.smallEnd(); IntVect hi=lo; hi[dir] = probDomain.bigEnd()[dir]; const Box resBox(lo,hi); FArrayBox resFab(resBox,nComp); resFab.setVal(0.); int accumFac = 1; for (int lev=finestLevel; lev>=0; --lev) { const BoxArray& ba = amrData.boxArray(lev); const DistributionMapping& dm = amrData.DistributionMap(lev); MultiFab mf(ba,dm,nComp,nGrow); if (ParallelDescriptor::IOProcessor() && verbose>0) cerr << "...filling data at level " << lev << endl; amrData.FillVar(mf,lev,inVarNames,destFillComps); // Zero covered regions if (lev < finestLevel) { const BoxArray baf = BoxArray(amrData.boxArray(lev+1)).coarsen(amrData.RefRatio()[lev]); for (MFIter mfi(mf); mfi.isValid(); ++mfi) { FArrayBox& myFab = mf[mfi]; std::vector< std::pair<int,Box> > isects = baf.intersections(ba[mfi.index()]); for (int ii = 0; ii < isects.size(); ii++) myFab.setVal(0,isects[ii].second,0,nComp); } } // Scale by "volume" (plane, 1 cell thick) of cells, normalized to volume of finest cells mf.mult(accumFac*accumFac,0,nComp); for (MFIter mfi(mf); mfi.isValid(); ++mfi) { const FArrayBox& fab = mf[mfi]; const Box& box = mfi.validbox(); IntVect ivlo = box.smallEnd(); IntVect ivhi = box.bigEnd(); ivhi[dir] = ivlo[dir]; for (int plane=box.smallEnd(dir); plane<=box.bigEnd(dir); ++plane) { ivlo[dir] = plane; ivhi[dir] = plane; Box subbox(ivlo,ivhi); Vector<Real> thisSum(nComp); for (int n=0; n<nComp; ++n) thisSum[n] = fab.sum(subbox,n,1); // Now, increment each sum affected by this coarse plane for (int r=0; r<accumFac; ++r) { const int finePlane = plane*accumFac + r; IntVect ivF=resBox.smallEnd(); ivF[dir] = finePlane; for (int n=0; n<nComp; ++n) resFab(ivF,n) += thisSum[n]; } } } if (lev>0) accumFac *= amrData.RefRatio()[lev-1]; } // Accumulate sums from all processors to IOProc ParallelDescriptor::ReduceRealSum(resFab.dataPtr(),nComp*resBox.numPts(),ParallelDescriptor::IOProcessorNumber()); if (ParallelDescriptor::IOProcessor()) { // Scale result by total "volume" (plane, 1 cell thick) of slab at each plane Real volume=1; for (int d=0; d<BL_SPACEDIM; ++d) if (d!=dir) volume*=probDomain.length(d); resFab.mult(1/volume); std::cout << "RESFAB " << resFab << std::endl; } amrex::Finalize(); return 0; }