Beispiel #1
0
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;
}
Beispiel #2
0
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();
}
Beispiel #5
0
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);,
Beispiel #6
0
/** 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);
    }
}
Beispiel #10
0
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);
    }
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
    }
}
Beispiel #13
0
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();
}
Beispiel #14
0
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();
    }
}
Beispiel #15
0
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();
    }
}
Beispiel #16
0
// ---------------------------------------------------------
// 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;
    }
}
Beispiel #18
0
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
}
Beispiel #21
0
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);
    }
  }
}
Beispiel #23
0
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));
    }
}
Beispiel #24
0
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);
        }
    }
}
Beispiel #25
0
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();
}