NewPoissonOp* NewPoissonOpFactory::MGnewOp(const ProblemDomain& a_FineindexSpace, int a_depth, bool a_homoOnly) { CH_assert(a_depth >= 0 ); CH_assert(m_bc != NULL); NewPoissonOp* newOp = new NewPoissonOp(); RealVect dx = m_dx; ProblemDomain domain = a_FineindexSpace; for (int i=0; i<a_depth; i++) { Box d = domain.domainBox(); d.coarsen(8); d.refine(8); if (domain.domainBox() == d) { dx*=2; domain.coarsen(2); } else { return NULL; } } newOp->define(dx, domain, m_bc); return newOp; }
void CompGridVTOBC::operator()( FArrayBox& a_state, const Box& a_valid, const ProblemDomain& a_domain, Real a_dx, bool a_homogeneous) { const Box& domainBox = a_domain.domainBox(); for (int idir = 0; idir < SpaceDim; idir++) { if (!a_domain.isPeriodic(idir)) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); if (a_valid.sideEnd(side)[idir] == domainBox.sideEnd(side)[idir]) { // Dirichlet BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); // include corner cells if possible by growing toRegion in transverse direction toRegion.grow(1); toRegion.grow(idir, -1); toRegion &= a_state.box(); for (BoxIterator bit(toRegion); bit.ok(); ++bit) { IntVect ivTo = bit(); IntVect ivClose = ivTo - isign*BASISV(idir); for (int ighost=0;ighost<m_nGhosts[0];ighost++,ivTo += isign*BASISV(idir)) { //for (int icomp = 0; icomp < a_state.nComp(); icomp++) a_state(ivTo, icomp) = 0.0; IntVect ivFrom = ivClose; // hardwire to linear BCs for now for (int icomp = 0; icomp < a_state.nComp() ; icomp++) { if (m_bcDiri[idir][side][icomp]) { a_state(ivTo, icomp) = (-1.0)*a_state(ivFrom, icomp); } else { a_state(ivTo, icomp) = (1.0)*a_state(ivFrom, icomp); } } } } // end loop over cells } // if ends match } // end loop over sides } // if not periodic in this direction } // end loop over directions }
void mtac::LiveVariableAnalysisProblem::meet(ProblemDomain& out, const ProblemDomain& in){ if(out.top()){ out = in; return; } else if(in.top()){ //out does not change return; } for(auto& value : in.values()){ out.values().insert(value); } }
// Define new AMR level void AMRLevelPluto::define(AMRLevel* a_coarserLevelPtr, const ProblemDomain& a_problemDomain, int a_level, int a_refRatio) { if (s_verbosity >= 3) { pout() << "AMRLevelPluto::define " << a_level << endl; } // Call inherited define AMRLevel::define(a_coarserLevelPtr, a_problemDomain, a_level, a_refRatio); // Get setup information from the next coarser level if (a_coarserLevelPtr != NULL) { AMRLevelPluto* amrGodPtr = dynamic_cast<AMRLevelPluto*>(a_coarserLevelPtr); if (amrGodPtr != NULL) { m_cfl = amrGodPtr->m_cfl; m_domainLength = amrGodPtr->m_domainLength; m_refineThresh = amrGodPtr->m_refineThresh; m_tagBufferSize = amrGodPtr->m_tagBufferSize; } else { MayDay::Error("AMRLevelPluto::define: a_coarserLevelPtr is not castable to AMRLevelPluto*"); } } // Compute the grid spacing m_dx = m_domainLength / (a_problemDomain.domainBox().bigEnd(0)-a_problemDomain.domainBox().smallEnd(0)+1.); // Nominally, one layer of ghost cells is maintained permanently and // individual computations may create local data with more m_numGhost = 1; CH_assert(m_patchPluto != NULL); CH_assert(isDefined()); m_patchPluto->define(m_problem_domain,m_dx,m_level,m_numGhost); // Get additional information from the patch integrator m_numStates = m_patchPluto->numConserved(); m_ConsStateNames = m_patchPluto->ConsStateNames(); m_PrimStateNames = m_patchPluto->PrimStateNames(); }
void DenseIntVectSet::nestingRegion(int radius, const ProblemDomain& a_domain) { CH_assert(radius >= 0); if (radius == 0) return; DenseIntVectSet tmp; Box region = a_domain.domainBox(); if (!a_domain.isPeriodic()) { tmp = *this; } else { D_TERM6(if (a_domain.isPeriodic(0)) region.grow(0, radius);, if (a_domain.isPeriodic(1)) region.grow(1, radius);, if (a_domain.isPeriodic(2)) region.grow(2, radius);,
/** Initializes the DisjointBoxLayouts, each step. */ void EBRestart::makeHierarchy(Vector<DisjointBoxLayout>& a_dbl, const ProblemDomain& a_baseDomain, const IntVectSet& a_baseTags, const Vector<int>& a_refRatios, const InputParams& a_inputs) { a_dbl.resize(a_inputs.nlevs); Real fillRatio = 0.85; BRMeshRefine regridder(a_baseDomain, a_refRatios, fillRatio, a_inputs.blocking_factor, a_inputs.buffer_size, a_inputs.max_size); Vector<Vector<Box> > oldGrids(a_inputs.nlevs,1), newGrids(a_inputs.nlevs); oldGrids[0][0]=a_baseDomain.domainBox(); for ( int l=1; l<a_inputs.nlevs; ++l ) { oldGrids[l][0]=coarsen(oldGrids[l-1][0], a_refRatios[l-1]); // FIXME: is a_refRatios[l-1] correct?? } regridder.regrid(newGrids, a_baseTags, 0, 1, oldGrids); // 0 is baselevel, 1 is toplevel. Vector<int> procs; for (int l=0; l<a_inputs.nlevs; l++) { newGrids[l].sort(); LoadBalance(procs, newGrids[l]); a_dbl[l] = DisjointBoxLayout(newGrids[l], procs); } }
void mtac::LiveVariableAnalysisProblem::transfer(mtac::basic_block_p/* basic_block*/, mtac::Quadruple& quadruple, ProblemDomain& in){ if(in.top()){ ProblemDomain::Values values; in.int_values = values; } if(quadruple.op != mtac::Operator::NOP){ if(mtac::erase_result(quadruple.op)){ in.values().erase(quadruple.result); } else { in.values().insert(quadruple.result); } if_init<std::shared_ptr<Variable>>(quadruple.arg1, [&in](std::shared_ptr<Variable>& var){in.values().insert(var);}); if_init<std::shared_ptr<Variable>>(quadruple.arg2, [&in](std::shared_ptr<Variable>& var){in.values().insert(var);}); } }
ProblemDomain mtac::LiveVariableAnalysisProblem::meet(ProblemDomain& out, ProblemDomain& in){ if(out.top()){ return in; } else if(in.top()){ return out; } typename ProblemDomain::Values values; ProblemDomain result(values); for(auto& value : in.values()){ result.values().insert(value); } for(auto& value : out.values()){ result.values().insert(value); } return result; }
void mtac::LiveVariableAnalysisProblem::transfer(mtac::basic_block_p B, ProblemDomain& x){ auto& x_values = x.values(); //Compute x - def(B) for(auto& v : def[B]){ x_values.erase(v); } //Compute use(B) U (x - def(B)) for(auto& v : use[B]){ x_values.insert(v); } }
void mtac::global_cse::meet(ProblemDomain& in, const ProblemDomain& out){ eddic_assert(!in.top() || !out.top(), "At least one lattice should not be a top element"); if(in.top()){ in = out; } else if(out.top()){ //in does not change } else { auto& first = in.values(); auto& second = out.values(); std::set<expression> intersection; std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), std::inserter(intersection, intersection.begin())); in.values() = std::move(intersection); } }
int VCAMRPoissonOp2Factory::refToFiner(const ProblemDomain& a_domain) const { int retval = -1; bool found = false; for (int ilev = 0; ilev < m_domains.size(); ilev++) { if (m_domains[ilev].domainBox() == a_domain.domainBox()) { retval = m_refRatios[ilev]; found = true; } } if (!found) { MayDay::Abort("Domain not found in AMR hierarchy"); } return retval; }
void mtac::global_cse::transfer(mtac::basic_block_p basic_block, ProblemDomain& out){ auto& out_values = out.values(); auto it = out_values.begin(); //Compute AEin - Kill(i) while(it != out_values.end()){ if(Kill[basic_block].find(*it) != Kill[basic_block].end()){ it = out_values.erase(it); continue; } ++it; } //Compute Eval(i) U (AEin - Kill(i)) for(auto& expression : Eval[basic_block]){ out_values.insert(expression); } }
void CFStencil::buildPeriodicVector(Vector<Box>& a_periodicVector, const ProblemDomain& a_fineDomain, const DisjointBoxLayout& a_fineBoxes) { Box periodicTestBox(a_fineDomain.domainBox()); if (a_fineDomain.isPeriodic()) { for (int idir=0; idir<SpaceDim; idir++) { if (a_fineDomain.isPeriodic(idir)) { periodicTestBox.grow(idir,-1); } } } a_periodicVector.clear(); a_periodicVector.reserve(a_fineBoxes.size()); LayoutIterator lit = a_fineBoxes.layoutIterator(); for (lit.reset(); lit.ok(); ++lit) { const Box& box = a_fineBoxes[lit()]; a_periodicVector.push_back(box); // if periodic, also need to add periodic images // only do this IF we're periodic and box // adjacent to the domain box boundary somewhere if (a_fineDomain.isPeriodic() && !periodicTestBox.contains(box)) { ShiftIterator shiftIt = a_fineDomain.shiftIterator(); IntVect shiftMult(a_fineDomain.domainBox().size()); Box shiftedBox(box); for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect = shiftMult*shiftIt(); shiftedBox.shift(shiftVect); a_periodicVector.push_back(shiftedBox); shiftedBox.shift(-shiftVect); } // end loop over periodic shift directions } // end if periodic } a_periodicVector.sort(); }
void CFStencil::define( const ProblemDomain& a_fineDomain, const Box& a_grid, const Vector<Box>& a_periodicVector, int a_refRatio, int a_direction, Side::LoHiSide a_hiorlo) { m_isDefined = true; CH_assert(a_refRatio >= 1); CH_assert(a_direction >= 0); CH_assert(a_direction < SpaceDim); CH_assert((a_hiorlo == Side::Lo) || (a_hiorlo == Side::Hi)); CH_assert(!a_fineDomain.isEmpty()); //set internal vars. most of these are kept around //just to keep the class from having an identity crisis. m_direction = a_direction; m_hiorlo = a_hiorlo; Box finebox = a_grid; //compute intvectset of all points on fine grid that //need to be interpolated //shift direction int hilo = sign(a_hiorlo); //create fine stencil Box edgebox; CH_assert((hilo ==1) || (hilo == -1)); if (hilo == -1) { edgebox = adjCellLo(finebox,m_direction,1); } else { edgebox = adjCellHi(finebox,m_direction,1); } edgebox = a_fineDomain & edgebox; if (edgebox.isEmpty()) return; int w1 = edgebox.smallEnd()[0]; int w2 = edgebox.bigEnd()[0]; m_fineIVS.define(edgebox); // moving window loop in i-direction (bvs) for (int i=0; i<a_periodicVector.size(); ++i) { const Box& b = a_periodicVector[i]; if (b.bigEnd()[0] >= w1) { m_fineIVS -= b; if (b.smallEnd()[0] > w2) { i=a_periodicVector.size(); } } } //ivs where all coarse slopes are defined //== coarsened fine ivs m_coarIVS.define(m_fineIVS); m_coarIVS.coarsen(a_refRatio); // this is a trick to get around the lack of a IntVectSet intersection // operator which works with a ProblemDomain ProblemDomain coardom= coarsen(a_fineDomain, a_refRatio); Box domainIntersectBox = m_coarIVS.minBox(); domainIntersectBox = coardom & domainIntersectBox; m_coarIVS &= domainIntersectBox; m_packedBox = m_fineIVS.minBox(); if (m_fineIVS.numPts() == m_packedBox.numPts()) { m_isPacked = true; } else { m_isPacked = false; m_packedBox = Box(); } }
void CFStencil::define( const ProblemDomain& a_fineDomain, const Box& a_grid, const DisjointBoxLayout& a_fineBoxes, const DisjointBoxLayout& a_coarBoxes, int a_refRatio, int a_direction, Side::LoHiSide a_hiorlo) { m_isDefined = true; CH_assert(a_refRatio >= 1); CH_assert(a_direction >= 0); CH_assert(a_direction < SpaceDim); CH_assert((a_hiorlo == Side::Lo) || (a_hiorlo == Side::Hi)); CH_assert(!a_fineDomain.isEmpty()); //set internal vars. most of these are kept around //just to keep the class from having an identity crisis. m_direction = a_direction; m_hiorlo = a_hiorlo; Box finebox = a_grid; //compute intvectset of all points on fine grid that //need to be interpolated //shift direction int hilo = sign(a_hiorlo); //create fine stencil Box edgebox; CH_assert((hilo ==1) || (hilo == -1)); if (hilo == -1) { edgebox = adjCellLo(finebox,m_direction,1); } else { edgebox = adjCellHi(finebox,m_direction,1); } edgebox = a_fineDomain & edgebox; if (!edgebox.isEmpty()) { Box periodicTestBox(a_fineDomain.domainBox()); if (a_fineDomain.isPeriodic()) { for (int idir=0; idir<SpaceDim; idir++) { if (a_fineDomain.isPeriodic(idir)) { periodicTestBox.grow(idir,-1); } } } m_fineIVS.define(edgebox); LayoutIterator lit = a_fineBoxes.layoutIterator(); for (lit.reset(); lit.ok(); ++lit) { m_fineIVS -= a_fineBoxes[lit()]; // if periodic, also need to subtract periodic images // only do this IF we're periodic _and_ both boxes // adjoin the domain box boundary somewhere if (a_fineDomain.isPeriodic() && !periodicTestBox.contains(edgebox) && !periodicTestBox.contains(a_fineBoxes[lit()])) { ShiftIterator shiftIt = a_fineDomain.shiftIterator(); IntVect shiftMult(a_fineDomain.domainBox().size()); Box shiftedBox(a_fineBoxes[lit()]); for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect = shiftMult*shiftIt(); shiftedBox.shift(shiftVect); m_fineIVS -= shiftedBox; shiftedBox.shift(-shiftVect); } // end loop over periodic shift directions } // end if periodic } } //ivs where all coarse slopes are defined //== coarsened fine ivs m_coarIVS.define(m_fineIVS); m_coarIVS.coarsen(a_refRatio); // this is a trick to get around the lack of a IntVectSet intersection // operator which works with a ProblemDomain ProblemDomain coardom= coarsen(a_fineDomain, a_refRatio); Box domainIntersectBox = m_coarIVS.minBox(); domainIntersectBox = coardom & domainIntersectBox; m_coarIVS &= domainIntersectBox; m_packedBox = m_fineIVS.minBox(); if (m_fineIVS.numPts() == m_packedBox.numPts()) { m_isPacked = true; } else { m_isPacked = false; m_packedBox = Box(); } }
// --------------------------------------------------------- // 7 Dec 2005 Real norm(const BoxLayoutData<NodeFArrayBox>& a_layout, const LevelData<NodeFArrayBox>& a_mask, const ProblemDomain& a_domain, const Real a_dx, const int a_p, const Interval& a_interval, bool a_verbose) { if (a_p == 0) return maxnorm(a_layout, a_mask, a_domain, a_interval, a_verbose); Real normTotal = 0.; int ncomp = a_interval.size(); Box domBox = a_domain.domainBox(); for (DataIterator it = a_layout.dataIterator(); it.ok(); ++it) { const NodeFArrayBox& thisNfab = a_layout[it()]; const FArrayBox& dataFab = thisNfab.getFab(); const FArrayBox& maskFab = a_mask[it()].getFab(); const Box& thisBox(a_layout.box(it())); // CELL-centered NodeFArrayBox dataMasked(thisBox, ncomp); FArrayBox& dataMaskedFab = dataMasked.getFab(); dataMaskedFab.copy(dataFab); // dataMaskedFab *= maskFab; for (int comp = a_interval.begin(); comp <= a_interval.end(); comp++) { // Set dataMaskedFab[comp] *= maskFab[0]. dataMaskedFab.mult(maskFab, 0, comp); } Real thisNfabNorm = 0.; if (thisBox.intersects(domBox)) { Box thisBoxInDomain = thisBox & domBox; thisNfabNorm = norm(dataMasked, a_dx, thisBoxInDomain, a_p, a_interval.begin(), a_interval.size()); } if (a_verbose) cout << a_p << "norm(" << thisBox << ") = " << thisNfabNorm << endl; if (a_p == 1) { normTotal += thisNfabNorm; } else if (a_p == 2) { normTotal += thisNfabNorm * thisNfabNorm; } else { normTotal += pow(thisNfabNorm, Real(a_p)); } } # ifdef CH_MPI Real recv; // add up (a_p is not 0) int result = MPI_Allreduce(&normTotal, &recv, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); if (result != MPI_SUCCESS) { //bark!!! MayDay::Error("sorry, but I had a communication error on norm"); } normTotal = recv; # endif // now do sqrt, etc if (a_p == 2) normTotal = sqrt(normTotal); else if ((a_p != 0) && (a_p != 1)) normTotal = pow(normTotal, (Real)1.0/Real(a_p)); return normTotal; }
void EBCompositeMACProjector:: correctTangentialVelocity(EBFaceFAB& a_velocity, const EBFaceFAB& a_gradient, const Box& a_grid, const EBISBox& a_ebisBox, const IntVectSet& a_cfivs) { CH_TIME("EBCompositeMACProjector::correctTangentialVelocity"); int velDir = a_velocity.direction(); int gradDir = a_gradient.direction(); //veldir is the face on which the velocity lives //graddir is the direction of the component //and the face on which the mac gradient lives CH_assert(velDir != gradDir); CH_assert(a_velocity.nComp() == 1); CH_assert(a_gradient.nComp() == 1); //updating in place in fortran so we have to save a acopy EBFaceFAB velSave(a_ebisBox, a_velocity.getCellRegion(), velDir, 1); velSave.copy(a_velocity); //interior box is the box where all of the stencil can be reached //without going out of the domain ProblemDomain domainBox = a_ebisBox.getDomain(); Box interiorBox = a_grid; interiorBox.grow(1); interiorBox &= domainBox; interiorBox.grow(-1); Box interiorFaceBox = surroundingNodes(interiorBox, velDir); if (!interiorBox.isEmpty()) { BaseFab<Real>& regVel = a_velocity.getSingleValuedFAB(); const BaseFab<Real>& regGrad = a_gradient.getSingleValuedFAB(); FORT_REGCORRECTTANVEL(CHF_FRA1(regVel,0), CHF_CONST_FRA1(regGrad,0), CHF_BOX(interiorFaceBox), CHF_INT(velDir), CHF_INT(gradDir)); } //do only irregular and boundary cells pointwise IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid); IntVectSet ivsGrid(a_grid); ivsGrid -= interiorBox; ivsGrid |= ivsIrreg; FaceIterator faceit(ivsGrid, a_ebisBox.getEBGraph(), velDir, FaceStop::SurroundingWithBoundary); for (faceit.reset(); faceit.ok(); ++faceit) { //average neighboring grads in grad dir direction int numGrads = 0; Real gradAve = 0.0; const FaceIndex& velFace = faceit(); for (SideIterator sitVel; sitVel.ok(); ++sitVel) { const VolIndex& vofSide = velFace.getVoF(sitVel()); const IntVect& ivSide = vofSide.gridIndex(); //do not include stuff over coarse-fine interface and inside the domain //cfivs includes cells just outside domain if (!a_cfivs.contains(ivSide) && domainBox.contains(ivSide)) { for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(vofSide, gradDir, sitGrad()); for (int iface = 0; iface < gradFaces.size(); iface++) { if (!gradFaces[iface].isBoundary()) { numGrads++; gradAve += a_gradient(gradFaces[iface], 0); } } }//end loop over gradient sides }//end cfivs check else { // inside coarse/fine interface or at domain boundary. extrapolate from neighboring vofs to get the gradient const Side::LoHiSide inSide = flip(sitVel()); const VolIndex& inSideVof = velFace.getVoF(inSide); const IntVect& inSideIV = inSideVof.gridIndex(); IntVect inSideFarIV = inSideIV; inSideFarIV[velDir] += sign(inSide); if (domainBox.contains(inSideIV) && domainBox.contains(inSideFarIV)) { Vector<VolIndex> farVofs = a_ebisBox.getVoFs(inSideFarIV); if (farVofs.size() == 1) { const VolIndex& inSideFarVof = farVofs[0]; for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { //get the grad for the face adjoining inSideVof on the sitGrad side, in the gradDir direction Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(inSideVof , gradDir, sitGrad()); Vector<FaceIndex> gradFarFaces = a_ebisBox.getFaces(inSideFarVof, gradDir, sitGrad()); if ( (gradFaces.size() == 1) && (gradFarFaces.size() == 1) ) { // if ( (!gradFaces[0].isBoundary()) && (!gradFarFaces[0].isBoundary()) ) // { const Real& inSideGrad = a_gradient(gradFaces[0], 0); const Real& inSideFarGrad = a_gradient(gradFarFaces[0], 0); Real extrapGrad = 2.0*inSideGrad - inSideFarGrad; gradAve += extrapGrad; numGrads++; // } } } } } }//end cfivs check }//end loop over sides of velocity face if (numGrads > 1) { gradAve /= Real(numGrads); } //remember that the fortran updated the velocity in place so //we have to use the saved velocity a_velocity(velFace, 0) = velSave(velFace, 0) - gradAve; } }
void EBCoarseAverage::define(const DisjointBoxLayout& a_dblFine, const DisjointBoxLayout& a_dblCoar, const EBISLayout& a_ebislFine, const EBISLayout& a_ebislCoar, const ProblemDomain& a_domainCoar, const int& a_nref, const int& a_nvar, const EBIndexSpace* ebisPtr) { CH_TIME("EBCoarseAverage::define"); CH_assert(ebisPtr->isDefined()); ProblemDomain domainFine = a_domainCoar; domainFine.refine(a_nref); EBLevelGrid eblgFine; EBLevelGrid eblgCoar = EBLevelGrid(a_dblCoar, a_ebislCoar, a_domainCoar); EBLevelGrid eblgCoFi; //check to see if the input layout is coarsenable. //if so, proceed with ordinary drill //otherwise, see if the layout covers the domain. //if it does, we can use domainsplit if (a_dblFine.coarsenable(a_nref)) { eblgFine = EBLevelGrid(a_dblFine, a_ebislFine, domainFine); m_useFineBuffer = false; } else { Box fineDomBox = refine(a_domainCoar.domainBox(), a_nref); int numPtsDom = fineDomBox.numPts(); //no need for gathers here because the meta data is global int numPtsLayout = 0; for (LayoutIterator lit = a_dblFine.layoutIterator(); lit.ok(); ++lit) { numPtsLayout += a_dblFine.get(lit()).numPts(); } bool coveringDomain = (numPtsDom == numPtsLayout); if (coveringDomain) { m_useFineBuffer = true; int maxBoxSize = 4*a_nref; Vector<Box> boxes; Vector<int> procs; domainSplit(fineDomBox, boxes, maxBoxSize); mortonOrdering(boxes); LoadBalance(procs, boxes); DisjointBoxLayout dblBufFine(boxes, procs); eblgFine = EBLevelGrid(dblBufFine, domainFine, 2, eblgCoar.getEBIS()); } else { pout() << "EBCoarseAverage::input layout is not coarsenable and does not cover the domain--bailing out" << endl; MayDay::Error(); } } coarsen(eblgCoFi, eblgFine, a_nref); define(eblgFine, eblgCoar, eblgCoFi, a_nref, a_nvar); }
void MappedLevelFluxRegister::define(const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, const IntVect& a_nRefine, int a_nComp, bool a_scaleFineFluxes) { CH_TIME("MappedLevelFluxRegister::define"); m_isDefined = FluxRegDefined; // Basically, define was called m_nRefine = a_nRefine; m_scaleFineFluxes = a_scaleFineFluxes; DisjointBoxLayout coarsenedFine; coarsen(coarsenedFine, a_dbl, a_nRefine); #ifndef DISABLE_TEMPORARY_FLUX_REGISTER_OPTIMIZATION // This doesn't work for multi-block calculations, which are // not properly nested. -JNJ //begin temporary optimization. bvs int numPts = 0; for (LayoutIterator lit = a_dblCoarse.layoutIterator(); lit.ok(); ++lit) { numPts += a_dblCoarse[lit].numPts(); } for (LayoutIterator lit = coarsenedFine.layoutIterator(); lit.ok(); ++lit) { numPts -= coarsenedFine[lit].numPts(); } if (numPts == 0) { m_coarFlux.clear(); // OK, fine region completely covers coarse region. no registers. return; } #endif //end temporary optimization. bvs m_coarFlux.define( a_dblCoarse, a_nComp); m_isDefined |= FluxRegCoarseDefined; m_domain = a_dProblem; ProblemDomain coarsenedDomain; coarsen(coarsenedDomain, a_dProblem, a_nRefine); m_fineFlux.define( coarsenedFine, a_nComp, IntVect::Unit); m_isDefined |= FluxRegFineDefined; m_reverseCopier.ghostDefine(coarsenedFine, a_dblCoarse, coarsenedDomain, IntVect::Unit); for (int i = 0; i < CH_SPACEDIM; i++) { m_coarseLocations[i].define(a_dblCoarse); m_coarseLocations[i + CH_SPACEDIM].define(a_dblCoarse); } DataIterator dC = a_dblCoarse.dataIterator(); LayoutIterator dF = coarsenedFine.layoutIterator(); for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); if (fBox.bigEnd(0) + 1 < cBox.smallEnd(0)) { //can skip this box since they cannot intersect, due to sorting } else if (fBox.smallEnd(0) - 1 > cBox.bigEnd(0)) { //skip to end, since all the rest of boxes will not intersect either dF.end(); } else { for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& lo = m_coarseLocations[i][dC]; Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; Box loBox = adjCellLo(fBox, i, 1); Box hiBox = adjCellHi(fBox, i, 1); if (cBox.intersectsNotEmpty(loBox)) lo.push_back(loBox & cBox); if (cBox.intersectsNotEmpty(hiBox)) hi.push_back(hiBox & cBox); } } } } Box domainBox = coarsenedDomain.domainBox(); if (a_dProblem.isPeriodic()) { Vector<Box> periodicBoxes[2 * CH_SPACEDIM]; for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); for (int i = 0; i < CH_SPACEDIM; i++) { if (a_dProblem.isPeriodic(i)) { if (fBox.smallEnd(i) == domainBox.smallEnd(i)) periodicBoxes[i].push_back(adjCellLo(fBox, i, 1)); if (fBox.bigEnd(i) == domainBox.bigEnd(i)) periodicBoxes[i + CH_SPACEDIM].push_back(adjCellHi(fBox, i, 1)); } } } for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; int size = domainBox.size(i); for (int j = 0; j < loV.size(); j++) loV[j].shift(i, size); for (int j = 0; j < hiV.size(); j++) hiV[j].shift(i, -size); } for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (int i = 0; i < CH_SPACEDIM; i++) if (a_dProblem.isPeriodic(i)) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; if (cBox.smallEnd(i) == domainBox.smallEnd(i) ) { Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; for (int j = 0; j < hiV.size(); j++) { if (cBox.intersectsNotEmpty(hiV[j])) hi.push_back(cBox & hiV[j]); } } if (cBox.bigEnd(i) == domainBox.bigEnd(i) ) { Vector<Box>& lo = m_coarseLocations[i][dC]; for (int j = 0; j < loV.size(); j++) { if (cBox.intersectsNotEmpty(loV[j])) lo.push_back(cBox & loV[j]); } } } } } }
void ConstBCFunction::operator()(FArrayBox& a_state, const Box& a_valid, const ProblemDomain& a_domain, Real a_dx, bool a_homogeneous) { const Box& domainBox = a_domain.domainBox(); for (int idir = 0; idir < SpaceDim; idir++) { if (!a_domain.isPeriodic(idir)) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); if (a_valid.sideEnd(side)[idir] == domainBox.sideEnd(side)[idir]) { int bcType; Real bcValue; if (side == Side::Lo) { bcType = m_loSideType [idir]; bcValue = m_loSideValue[idir]; } else { bcType = m_hiSideType [idir]; bcValue = m_hiSideValue[idir]; } if (bcType == 0) { // Neumann BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); toRegion &= a_state.box(); Box fromRegion = toRegion; fromRegion.shift(idir, -isign); a_state.copy(a_state, fromRegion, 0, toRegion, 0, a_state.nComp()); if (!a_homogeneous) { for (BoxIterator bit(toRegion); bit.ok(); ++bit) { const IntVect& ivTo = bit(); // IntVect ivClose = ivTo - isign*BASISV(idir); for (int icomp = 0; icomp < a_state.nComp(); icomp++) { a_state(ivTo, icomp) += Real(isign)*a_dx*bcValue; } } } } else if (bcType == 1) { // Dirichlet BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); toRegion &= a_state.box(); for (BoxIterator bit(toRegion); bit.ok(); ++bit) { const IntVect& ivTo = bit(); IntVect ivClose = ivTo - isign*BASISV(idir); // IntVect ivFar = ivTo - 2*isign*BASISV(idir); Real inhomogVal = 0.0; if (!a_homogeneous) { inhomogVal = bcValue; } for (int icomp = 0; icomp < a_state.nComp(); icomp++) { Real nearVal = a_state(ivClose, icomp); // Real farVal = a_state(ivFar, icomp); Real ghostVal = linearInterp(inhomogVal, nearVal); a_state(ivTo, icomp) = ghostVal; } } } else { MayDay::Abort("ConstBCFunction::operator() - unknown BC type"); } } // if ends match } // end loop over sides } // if not periodic in this direction } // end loop over directions }
void ReductionCopier::define(const BoxLayout& a_level, const BoxLayout& a_dest, const ProblemDomain& a_domain, const IntVect& a_ghost, const Vector<int>& a_transverseDir, bool a_exchange) { #ifdef MULTIDIM_TIMER CH_TIME("ReductionCopier::define") #endif m_isDefined = true; m_transverseDir = a_transverseDir; CH_assert(a_level.isClosed()); CH_assert(a_dest.isClosed()); // CH_assert(a_level.checkPeriodic(a_domain)); clear(); buffersAllocated = false; //bool self = a_dest == a_level; const BoxLayout& level= a_level; const BoxLayout& dest = a_dest; // note that while much of the implementation for the // periodic case remains in this function (as copied, more // or less, from the original Copier), at least at the moment // periodic support is "turned off" for the ReductionCopier // because it's not entirely clear it will do the right thing // for this case. I've left the vast majority of the // periodic implementation in place, however, in case we // change our minds... (DFM 3/10/09) // set up vector of dataIndexes to keep track of which // "to" boxes are not completely contained within the primary // domain. these boxes are then candidates for filling by // periodic images of the "from" data. Vector<DataIndex> periodicallyFilledToVect; // in order to cull which "from" data may be needed to // fill the "to" data, keep track of the radius around the // primary domain in which all these cells lie. // do this by incrementally growing the domain box and // keeping track of what this radius is. // just to make things simpler, start off with a radius of one Box grownDomainCheckBox = a_domain.domainBox(); grownDomainCheckBox.grow(1); int periodicCheckRadius = 1; // since valid regions of the "from" DBL may also be outside // the primary domain, need to keep track of whether any of these // need to be checked separately. Vector<DataIndex> periodicFromVect; // use same domain trick here as well Box grownFromDomainCheckBox = a_domain.domainBox(); int periodicFromCheckRadius = 1; Box domainBox(a_domain.domainBox()); // grab index extents of domain in transverse direction Vector<int> transverseLo(m_transverseDir.size()); Vector<int> transverseHi(m_transverseDir.size()); for (int n=0; n<m_transverseDir.size(); n++) { // grab index extents of domain in transverse direction transverseLo[n] = domainBox.smallEnd(m_transverseDir[n]); transverseHi[n] = domainBox.bigEnd(m_transverseDir[n]); } bool isPeriodic = false; // I think the right thing here is that the ReductionCopier // completely ignores periodicity //if (!domainBox.isEmpty()) //isPeriodic = a_domain.isPeriodic(); // (dfm -- 9/13/05) as currently written, the Copier won't correctly // handle periodic cases where the number of ghost cells is greater // than the width of the domain. We _should_ do multiple wraparounds, // but we don't. So, put in this assertion. We can revisit this if it // becomes an issue if (isPeriodic) { for (int dir=0; dir<SpaceDim; dir++) { if (a_domain.isPeriodic(dir)) { CH_assert (a_ghost[dir] <= domainBox.size(dir)); } } } unsigned int myprocID = procID(); // The following 4 for loops are the result of a performance optimization. // When increasing the size of the problem, we found that the code was // looping over every destination box for every source box which was N1*N2 // loop iterations (essentially an N-squared approach). // The following code attempts to simply reduce N1 and N2 by first separating // the boxes (or LayoutIndexes to boxes) that reside on the current processor. // Then the loop to determine which boxes of the first list intersect with // which boxes of the second list can be done in N1' * N2' iterations, // where N1' is the reduced N1 and N2' is the reduced N2. // We have to break up the assigning of MotionItems into two separate // loops and be careful about the local copies. These 4 loops are // significantly faster than the original for loop -- _especially_ // for large problems. (ndk) #ifdef CH_MPI // don't need to do this in serial // make a vector of boxes (or LayoutIndexes to boxes) from destination layout // that are known to reside on this processor. vector<DataIndex> vectorDestDI; vector<DataIndex> vectorDestOnProcDI; for (LayoutIterator to(a_dest.layoutIterator()); to.ok(); ++to) { vectorDestDI.push_back(DataIndex(to())); if (myprocID == dest.procID(to())) { vectorDestOnProcDI.push_back(DataIndex(to())); } } // make a vector of boxes (or LayoutIndexes to boxes) from "level"/src layout // that are known to reside on this processor. vector<DataIndex> vectorLevelDI; vector<DataIndex> vectorLevelOnProcDI; for (LayoutIterator from(a_level.layoutIterator()); from.ok(); ++from) { vectorLevelDI.push_back(DataIndex(from())); if (myprocID == level.procID(from())) { vectorLevelOnProcDI.push_back(DataIndex(from())); } } #else // in serial, it's not very interesting as it's all of them. vector<DataIndex> vectorDestOnProcDI; vector<DataIndex> vectorLevelDI; for (LayoutIterator to(a_dest.layoutIterator()); to.ok(); ++to) { vectorDestOnProcDI.push_back(DataIndex(to())); } for (LayoutIterator from(a_level.layoutIterator()); from.ok(); ++from) { vectorLevelDI.push_back(DataIndex(from())); } #endif // loop over all dest/to DI's on my processor for (vector<DataIndex>::iterator vdi=vectorDestOnProcDI.begin(); vdi != vectorDestOnProcDI.end(); ++vdi) { // at this point, i know myprocID == toProcID const DataIndex todi(*vdi); Box ghost(dest[todi]); // don't do anything if ghost is entirely outside domain // may need to revisit this in the periodic case if (a_domain.intersects(ghost)) { // this is somewhat different from the "normal" Copier. We only want // to look at ghost cells if they're outside the domain. // note that we don't want to do this for domain ghost cells in the // transverse (spreading) directions. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius if (!isTransverseDir && a_ghost[dir] != 0) { if (ghost.bigEnd(dir) == domainBox.bigEnd(dir)) { ghost.growHi(dir, a_ghost[dir]); } if (ghost.smallEnd(dir) == domainBox.smallEnd(dir)) { ghost.growLo(dir, a_ghost[dir]); } } } Box destBox(ghost); // for this Copier, we want to grow the "dest" region to cover the // entire domain in the transverse direction. In that way, we // will be able to catch all of the source data regions which // project onto the dest boxes // do this for all transverse directions for (int n=0; n<m_transverseDir.size(); n++) { ghost.setSmall(m_transverseDir[n], transverseLo[n]); ghost.setBig(m_transverseDir[n], transverseHi[n]); } // then for each level/from DI, see if they intersect for (vector<DataIndex>::iterator vli = vectorLevelDI.begin(); vli != vectorLevelDI.end(); ++vli) { const DataIndex fromdi(*vli); const unsigned int fromProcID = level.procID(fromdi); Box fromBox(level[fromdi]); // also grow the fromBox if it's near the domain boundary and // if there are ghost cells specified. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius // and if it's not a transverseDir if (!isTransverseDir && a_ghost[dir] != 0) { if (fromBox.bigEnd(dir) == domainBox.bigEnd(dir)) { fromBox.growHi(dir, a_ghost[dir]); } if (fromBox.smallEnd(dir) == domainBox.smallEnd(dir)) { fromBox.growLo(dir, a_ghost[dir]); } } } if (fromBox.bigEnd(0) < ghost.smallEnd(0)) { //can skip rest cuz we haven't gotten to something interesting continue; } if (ghost.intersectsNotEmpty(fromBox)) { Box box(ghost); // ?? box&=fromBox; // ?? // to get correct toBox, stretch box in the transverse direction // then intersect with the destBox to get the appropriate part // of the destbox Box toBox(box); // do this for all transverse directions for (int n=0; n<m_transverseDir.size(); n++) { toBox.setSmall(m_transverseDir[n], transverseLo[n]); toBox.setBig(m_transverseDir[n], transverseHi[n]); } toBox &= destBox; MotionItem* item = new (s_motionItemPool.getPtr()) MotionItem(fromdi, todi, box, toBox); if (item == NULL) { MayDay::Error("Out of Memory in copier::define"); } if (fromProcID == myprocID) { // local move if (a_exchange && fromdi == todi) s_motionItemPool.returnPtr(item); else m_localMotionPlan.push_back(item); } else { item->procID = fromProcID; m_toMotionPlan.push_back(item); } } if (fromBox.smallEnd(0) > ghost.bigEnd(0)) { //can break out of loop, since we know that the smallEnd // of all the remaining boxes are lexigraphically beyond this ghosted box. break; } } } // end if ghost intersects domain } // Don't need to worry about this in serial as we already // took care of the local copy motion items just above. skip this. #ifdef CH_MPI // loop over all dest/to DI's for (vector<DataIndex>::iterator vdi=vectorDestDI.begin(); vdi != vectorDestDI.end(); ++vdi) { const DataIndex todi(*vdi); Box ghost(dest[todi]); // don't do anything if ghost is outside domain if (a_domain.intersects(ghost) ) { // this is somewhat different from the "normal" Copier. We only want // to look at ghost cells if they're outside the domain. // note that we don't want to do this for domain ghost cells in the // transverse (spreading) directions. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius if (!isTransverseDir && a_ghost[dir] != 0) { if (ghost.bigEnd(dir) == domainBox.bigEnd(dir)) { ghost.growHi(dir, a_ghost[dir]); } if (ghost.smallEnd(dir) == domainBox.smallEnd(dir)) { ghost.growLo(dir, a_ghost[dir]); } } } Box destBox(ghost); // for this Copier, we want to grow the "dest" region to cover the // entire domain in the transverse direction. In that way, we // will be able to catch all of the source data regions which // project onto the dest boxes // do this for all transverse directions for (int n=0; n<m_transverseDir.size(); n++) { ghost.setSmall(m_transverseDir[n], transverseLo[n]); ghost.setBig(m_transverseDir[n], transverseHi[n]); } const unsigned int toProcID = dest.procID(todi); // then for each level/from DI on this processor, see if they intersect for (vector<DataIndex>::iterator vli = vectorLevelOnProcDI.begin(); vli != vectorLevelOnProcDI.end(); ++vli) { // at this point, i know myprocID == fromProcID const DataIndex fromdi(*vli); Box fromBox(level[fromdi]); // also grow the fromBox if it's near the domain boundary and // if there are ghost cells specified. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius // and if it's not a transverseDir if (!isTransverseDir && a_ghost[dir] != 0) { if (fromBox.bigEnd(dir) == domainBox.bigEnd(dir)) { fromBox.growHi(dir, a_ghost[dir]); } if (fromBox.smallEnd(dir) == domainBox.smallEnd(dir)) { fromBox.growLo(dir, a_ghost[dir]); } } } if (fromBox.bigEnd(0) < ghost.smallEnd(0)) { //can skip rest cuz we haven't gotten to something interesting continue; } if (ghost.intersectsNotEmpty(fromBox)) { Box box(ghost); // ?? box&=fromBox; // ?? // to get correct toBox, stretch box in the transverse direction // then intersect with the destBox to get the appropriate part // of the destbox // do this for each transverse direction Box toBox(box); for (int n=0; n<m_transverseDir.size(); n++) { toBox.setSmall(m_transverseDir[n], transverseLo[n]); toBox.setBig(m_transverseDir[n], transverseHi[n]); } toBox &= destBox; if (toProcID == myprocID) { // local move // don't push back here! or you will get two. // we already did it above... //m_localMotionPlan.push_back(item); } else { MotionItem* item = new (s_motionItemPool.getPtr()) MotionItem(fromdi, todi, box, toBox); if (item == NULL) { MayDay::Error("Out of Memory in copier::define"); } item->procID = toProcID; m_fromMotionPlan.push_back(item); } } if (fromBox.smallEnd(0) > ghost.bigEnd(0)) { //can break out of loop, since we know that the smallEnd // of all the remaining boxes are lexigraphically beyond this ghosted box. break; } } } // end if ghost intersects domain } #endif // put periodic intersection checking in here for "to" boxes if (isPeriodic) { for (LayoutIterator to(a_dest.layoutIterator()); to.ok(); ++to) { Box ghost(dest[to()]); // don't do anything if ghost doesn't intersect domain if (a_domain.intersects(ghost) ) { // this is somewhat different from the "normal" Copier. We only want // to look at ghost cells if they're outside the domain. // note that we don't want to do this for domain ghost cells in the // transverse (spreading) directions. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius if (!isTransverseDir && a_ghost[dir] != 0) { if (ghost.bigEnd(dir) == domainBox.bigEnd(dir)) { ghost.growHi(dir, a_ghost[dir]); } if (ghost.smallEnd(dir) == domainBox.smallEnd(dir)) { ghost.growLo(dir, a_ghost[dir]); } } } Box destBox(ghost); // for this Copier, we want to grow the "dest" region to cover the // entire domain in the transverse direction. In that way, we // will be able to catch all of the source data regions which // project onto the dest boxes // do this for each transverse directions for (int n=0; n<m_transverseDir.size(); n++) { ghost.setSmall(m_transverseDir[n], transverseLo[n]); ghost.setBig(m_transverseDir[n], transverseHi[n]); } //unsigned int toProcID = dest.procID(to()); // unused variable // only do this if ghost box hangs over domain edge if (!domainBox.contains(ghost)) { // add the dataIndex for this box to the list // of boxes which we need to come back to periodicallyFilledToVect.push_back(DataIndex(to())); // now check to see if we need to grow the // periodic check radius if (!grownDomainCheckBox.contains(ghost)) { // grow the domainCheckBox until it contains ghost while (!grownDomainCheckBox.contains(ghost)) { grownDomainCheckBox.grow(1); periodicCheckRadius++; } } // end if we need to grow radius around domain } //end if ghost box is not contained in domain } // end if original ghost box didn't intersect domain }// end if periodic } // Here ends the so-called N-squared optimizations. the rest is unchanged. (ndk) // now do periodic checking, if necessary if (isPeriodic) { // the only "from" boxes we will need to check // will be those within periodicCheckRadius of the // domain boundary. so, create a box to screen out // those which we will need to check. Box shrunkDomainBox = a_domain.domainBox(); shrunkDomainBox.grow(-periodicCheckRadius); ShiftIterator shiftIt = a_domain.shiftIterator(); IntVect shiftMult(domainBox.size()); // now loop over "from" boxes for (LayoutIterator from(a_level.layoutIterator()); from.ok(); ++from) { // first check to see whether we need to look at this box const Box& fromBox = level[from()]; if (!shrunkDomainBox.contains(fromBox)) { unsigned int fromProcID = level.procID(from()); // check to see if fromBox is contained in domain, // if not, add it to the list of fromBoxes we need to // go back and check separately to see if it will // fill one of the "to" boxes if (!domainBox.contains(fromBox)) { periodicFromVect.push_back(DataIndex(from())); if (!grownFromDomainCheckBox.contains(fromBox)) { while (!grownFromDomainCheckBox.contains(fromBox)) { grownFromDomainCheckBox.grow(1); periodicFromCheckRadius++; } } // end if we need to grow domain check box } // end if fromBox is outside domain // now loop over those "to" boxes which were not contained // in the domain for (int toRef=0; toRef<periodicallyFilledToVect.size(); toRef++) { DataIndex toIndex = periodicallyFilledToVect[toRef]; unsigned int toProcID = dest.procID(toIndex); // don't worry about anything that doesn't involve this proc if (toProcID != myprocID && fromProcID != myprocID) { // do nothing } else { Box ghost(dest[toIndex]); // don't do anything if ghost doesn't intersect domain if (a_domain.intersects(ghost)) { // this is somewhat different from the "normal" Copier. // We only want // to look at ghost cells if they're outside the domain. // note that we don't want to do this for domain ghost // cells in the transverse (spreading) directions. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius if (!isTransverseDir && a_ghost[dir] != 0) { if (ghost.bigEnd(dir) == domainBox.bigEnd(dir)) { ghost.growHi(dir, a_ghost[dir]); } if (ghost.smallEnd(dir) == domainBox.smallEnd(dir)) { ghost.growLo(dir, a_ghost[dir]); } } } Box destBox(ghost); // for this Copier, we want to grow the "dest" // region to cover the entire domain in the transverse // direction. In that way, we will be able to catch all // of the source data regions which project onto the // dest boxes // do this for each transverse direction for (int n=0; n<m_transverseDir.size(); n++) { ghost.setSmall(m_transverseDir[n], transverseLo[n]); ghost.setBig(m_transverseDir[n], transverseHi[n]); } // now need to loop over shift vectors and look at images for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect(shiftIt()*shiftMult); ghost.shift(shiftVect); if (ghost.intersectsNotEmpty(fromBox)) // rarely happens { Box intersectBox(ghost); intersectBox &= fromBox; Box toBox(intersectBox); toBox.shift(-shiftVect); toBox &= destBox; MotionItem* item = new (s_motionItemPool.getPtr()) MotionItem(DataIndex(from()), DataIndex(toIndex), intersectBox, toBox); if (item == NULL) { MayDay::Error("Out of Memory in copier::define"); } if (toProcID == fromProcID) // local move m_localMotionPlan.push_back(item); else if (fromProcID == myprocID) { item->procID = toProcID; m_fromMotionPlan.push_back(item); } else { item->procID = fromProcID; m_toMotionPlan.push_back(item); } } // end if shifted box intersects ghost.shift(-shiftVect); } // end loop over shift vectors } // end if original "ghost" intersected domain } // end if either from box or to box are on this proc } // end loop over destination boxes } // end if source box is close to domain boundary } // end loop over destination boxes // now go back through the "from" boxes which were outside // the domain and see if they intersect any toBoxes if (periodicFromVect.size() != 0) { // the only "to" boxes we will need to check // will be those within periodicCheckRadius of the // domain boundary. so, create a box to screen out // those which we will need to check. shrunkDomainBox = a_domain.domainBox(); shrunkDomainBox.grow(-periodicFromCheckRadius); // now loop over the "to" boxes for (LayoutIterator to(a_dest.layoutIterator()); to.ok(); ++to) { // first check to see whether we need to look at this box Box ghost(dest[to()]); // don't do anything if "ghost" doesn't interesect domain if (a_domain.intersects(ghost)) { // this is somewhat different from the "normal" Copier. // We only want // to look at ghost cells if they're outside the domain. // note that we don't want to do this for domain ghost cells // in the transverse (spreading) directions. for (int dir=0; dir<SpaceDim; dir++) { bool isTransverseDir = false; for (int n=0; n<m_transverseDir.size(); n++) { if (dir == m_transverseDir[n]) isTransverseDir = true; } // only need to do this if we specify a ghost radius if (!isTransverseDir && a_ghost[dir] != 0) { if (ghost.bigEnd(dir) == domainBox.bigEnd(dir)) { ghost.growHi(dir, a_ghost[dir]); } if (ghost.smallEnd(dir) == domainBox.smallEnd(dir)) { ghost.growLo(dir, a_ghost[dir]); } } } Box destBox(ghost); // for this Copier, we want to grow the "dest" region to // cover the entire domain in the transverse direction. // In that way, we will be able to catch all of the source // data regions which project onto the dest boxes // do this for each transverse direction for (int n=0; n<m_transverseDir.size(); n++) { ghost.setSmall(m_transverseDir[n], transverseLo[n]); ghost.setBig(m_transverseDir[n], transverseHi[n]); } if (!shrunkDomainBox.contains(ghost)) { unsigned int toProcID = a_dest.procID(to()); // now loop over those "from" boxes which are not // contained by the domain for (int fromRef = 0; fromRef<periodicFromVect.size(); fromRef++) { DataIndex fromIndex = periodicFromVect[fromRef]; const Box& fromBox = level[fromIndex]; unsigned int fromProcID = level.procID(fromIndex); // don't worry about anything which doesn't involve // this proc if (toProcID != myprocID && fromProcID != myprocID) { // do nothing } else { // now need to loop over shift vectors and look at images for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect(shiftIt()*shiftMult); ghost.shift(shiftVect); if (ghost.intersectsNotEmpty(fromBox)) { Box intersectBox(ghost); intersectBox &= fromBox; Box toBox(intersectBox); toBox.shift(-shiftVect); toBox &= destBox; MotionItem* item = new (s_motionItemPool.getPtr()) MotionItem(DataIndex(fromIndex), DataIndex(to()), intersectBox, toBox); if (item == NULL) { MayDay::Error("Out of Memory in copier::define"); } if (toProcID == fromProcID) // local move m_localMotionPlan.push_back(item); else if (fromProcID == myprocID) { item->procID = toProcID; m_fromMotionPlan.push_back(item); } else { item->procID = fromProcID; m_toMotionPlan.push_back(item); } } // end if shifted box intersects ghost.shift(-shiftVect); } // end loop over shift vectors } // end if either from box or to box are on this proc } // end loop over "from" boxes } // end if destination box is close to domain boundary } // end if original "ghost" intersects domain } // end loop over destination boxes } // end if any of the "From" boxes were outside the domain } // end if we need to do anything for periodicity }
// new define void LevelFluxRegisterEdge::define( const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, int a_nRefine, int a_nComp) { m_isDefined = true; CH_assert(a_nRefine > 0); CH_assert(a_nComp > 0); CH_assert(!a_dProblem.isEmpty()); m_nComp = a_nComp; m_nRefine = a_nRefine; m_domainCoarse = coarsen(a_dProblem, a_nRefine); CH_assert (a_dblCoarse.checkPeriodic(m_domainCoarse)); // allocate copiers m_crseCopiers.resize(SpaceDim*2); SideIterator side; // create a Vector<Box> of the fine boxes which also includes periodic images, // since we don't really care about the processor layouts, etc Vector<Box> periodicFineBoxes; CFStencil::buildPeriodicVector(periodicFineBoxes, a_dProblem, a_dbl); // now coarsen these boxes... for (int i=0; i<periodicFineBoxes.size(); i++) { periodicFineBoxes[i].coarsen(m_nRefine); } for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { // step one, build fineBoxes, flux register boxes // indexed by the fine level but in the coarse index // space DisjointBoxLayout fineBoxes,tmp; // first create coarsened dbl, then compute flux register boxes // adjacent to coarsened fine boxes coarsen(tmp, a_dbl, m_nRefine); if (side() == Side::Lo) { adjCellLo(fineBoxes, tmp, idir,1); } else { adjCellHi(fineBoxes, tmp, idir,1); } // now define the FluxBoxes of fabFine on this DisjointBoxLayout m_fabFine[index(idir, side())].define(fineBoxes, a_nComp); LayoutData<Vector<Vector<IntVectSet> > >& ivsetsVect = m_refluxLocations[index(idir, side())]; ivsetsVect.define(a_dblCoarse); LayoutData<Vector<DataIndex> >& mapsV = m_coarToCoarMap[index(idir, side())]; mapsV.define(a_dblCoarse); DisjointBoxLayout coarseBoxes = a_dblCoarse; DataIterator dit = a_dblCoarse.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { unsigned int thisproc = a_dblCoarse.procID(dit()); if (thisproc == procID()) { ivsetsVect[DataIndex(dit())].resize(SpaceDim); } const Box& coarseBox = a_dblCoarse[dit()]; int count = 0; for (int i=0; i<periodicFineBoxes.size(); i++) { Box regBox; if (side() == Side::Lo) { regBox = adjCellLo(periodicFineBoxes[i], idir, 1); } else { regBox = adjCellHi(periodicFineBoxes[i], idir, 1); } // do this little dance in order to ensure that // we catch corner cells which might be in different // boxes. Box testBox(regBox); testBox.grow(1); testBox.grow(idir,-1); if (testBox.intersectsNotEmpty(coarseBox)) { testBox &= coarseBox; ++count; unsigned int proc = a_dblCoarse.procID(dit()); const DataIndex index = DataIndex(dit()); if (proc == procID()) { mapsV[DataIndex(dit())].push_back(index); // loop over face directions here for (int faceDir=0; faceDir<SpaceDim; faceDir++) { // do nothing in normal direction if (faceDir != idir) { // this should give us the face indices for the // faceDir-centered faces adjacent to the coarse-fine // interface which are contained in the current // coarse box Box intersectBox(regBox); Box coarseEdgeBox(coarseBox); coarseEdgeBox.surroundingNodes(faceDir); intersectBox.surroundingNodes(faceDir); intersectBox &= coarseEdgeBox; intersectBox.shiftHalf(faceDir,1); IntVectSet localIV(intersectBox); ivsetsVect[DataIndex(dit())][faceDir].push_back(localIV); } } } } } // end loop over boxes on coarse level } m_regCoarse.define(coarseBoxes, a_nComp, IntVect::Unit); // last thing to do is to define copiers m_crseCopiers[index(idir, side())].define(fineBoxes, coarseBoxes, IntVect::Unit); } } }
void oldLoHiCenter(Box& a_loBox, int& a_hasLo, Box& a_hiBox, int& a_hasHi, Box& a_centerBox, Box& a_entireBox, const Box& a_inBox, const ProblemDomain& a_domain, const int& a_dir) { // Make a copy of the input box which can be modified Box inBox = a_inBox; inBox &= a_domain; // The centered difference box is always one smaller in a_dir a_centerBox = inBox; a_centerBox.grow(a_dir,-1); // The union of all the output boxes start off equal to the center // difference portion on the input box (intersected with the domain) a_entireBox = a_centerBox; // See if this chops off the high side of the input box Box tmp = a_inBox; tmp.shift(a_dir,-1); tmp &= a_domain; tmp.shift(a_dir,1); // If so, set up the high, one-sided difference box, a_hiBox, and expand // the entire box to include it if (!a_domain.contains(tmp)) { a_hasHi = 1; tmp.shift(a_dir,-2); a_hiBox = adjCellHi(tmp,a_dir); a_entireBox.growHi(a_dir,1); } else { a_hasHi = 0; a_hiBox = Box(); } // See if this chops off the low side of the input box tmp = a_inBox; tmp.shift(a_dir,1); tmp &= a_domain; tmp.shift(a_dir,-1); // If so, set up the low, one-sided difference box, a_loBox, and expand // the entire box to include it if (!a_domain.contains(tmp)) { a_hasLo = 1; tmp.shift(a_dir,2); a_loBox = adjCellLo(tmp,a_dir); a_entireBox.growLo(a_dir,1); } else { a_hasLo = 0; a_loBox = Box(); } // Make some simple sanity checks CH_assert(a_entireBox.contains(a_centerBox)); if (a_hasLo == 1) { CH_assert(a_entireBox.contains(a_loBox)); } if (a_hasHi == 1) { CH_assert(a_entireBox.contains(a_hiBox)); } }
void SlabService::fillGraph(BaseFab<int>& a_regIrregCovered, Vector<IrregNode>& a_nodes, const Box& a_validRegion, const Box& a_ghostRegion, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_dx) const { Box grownCovBox = grow(m_coveredRegion, 1); grownCovBox &= a_ghostRegion; IntVectSet ivsIrreg(grownCovBox); ivsIrreg -= m_coveredRegion; ivsIrreg &= a_domain; //set regirregcoverred flags CH_assert(a_regIrregCovered.box().contains(a_ghostRegion)); //set every cell to regular a_regIrregCovered.setVal(1); for (BoxIterator bit(a_ghostRegion); bit.ok(); ++bit) { if (m_coveredRegion.contains(bit())) { //set covered cells to -1 a_regIrregCovered(bit(), 0) = -1; } else if (ivsIrreg.contains(bit())) { //set irreg cells to 0 a_regIrregCovered(bit(), 0) = 0; } } //now loop through irreg cells and make Nodes for them a_nodes.resize(0); for (IVSIterator ivsit(ivsIrreg); ivsit.ok(); ++ivsit) { const IntVect& iv = ivsit(); if (a_validRegion.contains(iv)) { IrregNode node; //first the obvious node.m_cell = iv; node.m_volFrac = 1.0; node.m_cellIndex = 0; node.m_volCentroid = RealVect::Zero; //any time the next cell over is in the covered //region, there is no face. If there is a cell //but it is outside the domain, the arc=-1 to signify //a boundary face. Otherwise, the arc is -2 if it //is to a regular cell and 0 if it is to an irregular cell for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int arcIndex = node.index(idir, sit()); Vector<int>& arcs = node.m_arc[arcIndex]; Vector<Real>& areaFracs= node.m_areaFrac[arcIndex]; Vector<RealVect>& faceCents= node.m_faceCentroid[arcIndex]; IntVect otherIV = iv + sign(sit())*BASISV(idir); if (m_coveredRegion.contains(otherIV)) { //do nothing, covered face. leave the vector empty } else { int otherCellIndex; if (ivsIrreg.contains(otherIV)) { //arc irregular cell inside the domain otherCellIndex = 0; } else if (!a_domain.contains(otherIV)) { //boundary face otherCellIndex = -1; } else { //arc to regular cell otherCellIndex = -2; } arcs.push_back(otherCellIndex); Real areaFrac = 1.0; RealVect faceCent = RealVect::Zero; areaFracs.push_back(areaFrac); faceCents.push_back(faceCent); } //end otherIV not covered } } //the boundary centroid and normal //depend on which side is covered for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int arcIndex = node.index(idir, sit()); Vector<int>& arcs = node.m_arc[arcIndex]; if (arcs.size() == 0) { int isign = sign(sit()); node.m_bndryCentroid[idir] = Real(isign)*0.5; } } } a_nodes.push_back(node); } } }
void EBMGInterp::fillGhostCellsPWC(LevelData<EBCellFAB>& a_data, const EBISLayout& a_ebisl, const ProblemDomain& a_dom) { for (int idir = 0; idir < SpaceDim; idir++) { if (m_ghost[idir] < 1) { MayDay::Error("EBMGInterp:I need a ghost cell for linear interpolation"); } } //extrapolate to every ghost cell const DisjointBoxLayout& dbl = a_data.disjointBoxLayout(); for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { const Box& grid = dbl.get(dit()); const EBGraph& ebgraph = a_ebisl[dit()].getEBGraph(); for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide flipSide = flip(sit()); Box ghostBox = adjCellBox(grid, idir, sit(), 1); for (BoxIterator boxit(ghostBox); boxit.ok(); ++boxit) { if (a_dom.contains(boxit())) { Vector<VolIndex> vofs = ebgraph.getVoFs(boxit()); for (int ivof = 0; ivof < vofs.size(); ivof++) { Real extrapVal = 0; Vector<FaceIndex> faces = ebgraph.getFaces(vofs[ivof], idir, flipSide); for (int ivar = 0; ivar < a_data.nComp(); ivar++) { for (int iface = 0; iface < faces.size(); iface++) { const VolIndex& flipVoF = faces[iface].getVoF(flipSide); extrapVal += a_data[dit()](flipVoF, ivar); } if (faces.size() > 1) extrapVal /= faces.size(); a_data[dit()](vofs[ivof], ivar) = extrapVal; } } } else { //just put in the single valued part of the data holder something sensible //if not inside domain int isign = sign(flipSide); BaseFab<Real>& bfdata = a_data[dit()].getSingleValuedFAB(); IntVect otherIV = boxit() + isign*BASISV(idir); for (int ivar = 0; ivar < a_data.nComp(); ivar++) { bfdata(boxit(), ivar) = bfdata(otherIV, ivar); } } } } } } //do exchange to overwrite ghost cells where there exists real data a_data.exchange(); }