// ---------------------------------------------------------
void
AMRNavierStokes::computeLapVel(LevelData<FArrayBox>& a_lapVel,
                               LevelData<FArrayBox>& a_vel,
                               const LevelData<FArrayBox>* a_crseVelPtr)
{
  // set BC's
  VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC());
  bool isHomogeneous = false;
  m_velocityAMRPoissonOp.applyOp(a_lapVel, a_vel, a_crseVelPtr,
                                 isHomogeneous, velBC);

  // may need to extend lapVel to cover ghost cells as well
  {
    BCHolder viscBC = m_physBCPtr->viscousFuncBC();
    const DisjointBoxLayout& grids = a_lapVel.getBoxes();
    DataIterator dit = a_lapVel.dataIterator();
    for (dit.reset(); dit.ok(); ++dit)
      {
        viscBC(a_lapVel[dit], grids[dit],
               m_problem_domain, m_dx,
               false); // not homogeneous
      }
  }

  // finally, do exchange
  a_lapVel.exchange(a_lapVel.interval());
}
Beispiel #2
0
// ---------------------------------------------------------
void levelDivergenceMAC(LevelData<FArrayBox>& a_div,
                        const LevelData<FluxBox>& a_uEdge,
                        const Real a_dx)
{

  // silly way to do this until i figure out a better
  // way to make this dimensionally-independent
  CH_assert (a_uEdge.nComp() >= a_div.nComp());


  DataIterator dit = a_div.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
  {
    a_div[dit()].setVal(0.0);

    const FluxBox& thisFluxBox = a_uEdge[dit()];
    Box cellBox(thisFluxBox.box());
    // just to be sure we don't accidentally trash memory...
    cellBox &= a_div[dit()].box();

    // now loop over coordinate directions and add to divergence
    for (int dir=0; dir<SpaceDim; dir++)
    {
      const FArrayBox& uEdgeDir = thisFluxBox[dir];

      FORT_DIVERGENCE(CHF_CONST_FRA(uEdgeDir),
                      CHF_FRA(a_div[dit()]),
                      CHF_BOX(cellBox),
                      CHF_CONST_REAL(a_dx),
                      CHF_INT(dir));
    }

  }

}
// ---------------------------------------------------------
void
AMRNavierStokes::computeLapScal(LevelData<FArrayBox>& a_lapScal,
                                LevelData<FArrayBox>& a_scal,
                                const BCHolder& a_physBC,
                                const LevelData<FArrayBox>* a_crseScalPtr)
{
  m_scalarsAMRPoissonOp.setBC(a_physBC);
  bool isHomogeneous = false;
  if (a_crseScalPtr != NULL)
    {
      m_scalarsAMRPoissonOp.AMROperatorNF(a_lapScal, a_scal, *a_crseScalPtr,
                                          isHomogeneous);
    }
  else
    {
      m_scalarsAMRPoissonOp.applyOpI(a_lapScal, a_scal,
                                     isHomogeneous);
    }

  BCHolder viscBC = m_physBCPtr->viscousFuncBC();

  DataIterator dit = a_lapScal.dataIterator();
  const DisjointBoxLayout& grids = a_lapScal.getBoxes();
  for (dit.reset(); dit.ok(); ++dit)
    {
      viscBC(a_lapScal[dit],
             grids[dit],
             m_problem_domain, m_dx,
             false); // not homogeneous
    }

  // finally, do exchange
  a_lapScal.exchange(a_lapScal.interval());
}
// -----------------------------------------------------------------------------
// Semi-implicitly handles the gravity forcing and projection.
// The old* inputs should be the values at t^n.
// The new* inputs should be the updated values from the TGA solver.
// -----------------------------------------------------------------------------
void AMRNavierStokes::doCCIGProjection (LevelData<FArrayBox>&       a_newVel,
                                        LevelData<FArrayBox>&       a_newB,
                                        const LevelData<FArrayBox>& a_oldVel,
                                        const LevelData<FArrayBox>& a_oldB,
                                        const LevelData<FluxBox>&   a_advVel,
                                        const Real                  a_oldTime,
                                        const Real                  a_dt,
                                        const bool                  a_doProj)
{
    CH_TIME("AMRNavierStokes::doCCIGProjection");

    const Real halfTime = a_oldTime + 0.5 * a_dt;
    const Real newTime  = a_oldTime + 1.0 * a_dt;
    const Real dummyTime = -1.0e300;
    const GeoSourceInterface& geoSource = *(m_levGeoPtr->getGeoSourcePtr());
    const RealVect& dx = m_levGeoPtr->getDx();
    const DisjointBoxLayout& grids = a_newVel.getBoxes();
    DataIterator dit = grids.dataIterator();


    // 1. Compute the background buoyancy, N, Dinv, etc...

    // Fill the FC background buoyancy field.
    LevelData<FluxBox> bbar(grids, 1, 2*IntVect::Unit);
    for (dit.reset(); dit.ok(); ++dit) {
        FluxBox& bbarFB = bbar[dit];

        D_TERM(m_physBCPtr->setBackgroundScalar(bbarFB[0], 0, *m_levGeoPtr, dit(), dummyTime);,
               m_physBCPtr->setBackgroundScalar(bbarFB[1], 0, *m_levGeoPtr, dit(), dummyTime);,
Beispiel #5
0
// ----------------------------------------------------------------
void EdgeToCell(const LevelData<FluxBox>& a_edgeData,
                LevelData<FArrayBox>& a_cellData)
{
  // this is just a wrapper around the single-grid version
  DataIterator dit = a_edgeData.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      EdgeToCell(a_edgeData[dit()], a_cellData[dit()]);
    }
}
Beispiel #6
0
// -------------------------------------------------------------
void
Mask::buildMasks(LevelData<BaseFab<int> >& a_masks,
                 const ProblemDomain& a_dProblem,
                 const BoxLayout& a_grids, const BoxLayout* a_fineGridsPtr,
                 int a_nRefFine)
{
  // simply iterate over boxes and call single-basefab function
  DataIterator dit = a_masks.dataIterator();

  for (dit.reset(); dit.ok(); ++dit)
    {
      buildMask(a_masks[dit()], a_dProblem, a_grids, a_fineGridsPtr,
                a_nRefFine);
    }
}
Beispiel #7
0
// ----------------------------------------------------------
// this function is shamelessly based on the ANAG CoarseAverage
// (cell-centered) version
void
CoarseAverageEdge::averageToCoarse(LevelData<FluxBox>& a_coarseData,
                                   const LevelData<FluxBox>& a_fineData)
{
  CH_assert(isDefined());

  DataIterator dit = a_fineData.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      FluxBox& coarsenedFine = m_coarsenedFineData[dit()];
      const FluxBox& fine = a_fineData[dit()];

      // coarsen from the entire fine grid onto the entire coarse grid
      averageGridData(coarsenedFine, fine);
    }

  m_coarsenedFineData.copyTo(m_coarsenedFineData.interval(),
                             a_coarseData, a_coarseData.interval());
}
Beispiel #8
0
// -----------------------------------------------------------------------------
// Adds coarse cell values directly to all overlying fine cells.
// -----------------------------------------------------------------------------
void ConstInterpPS::prolongIncrement (LevelData<FArrayBox>&       a_phiThisLevel,
                                      const LevelData<FArrayBox>& a_correctCoarse)
{
    CH_TIME("ConstInterpPS::prolongIncrement");

    // Gather grids, domains, refinement ratios...
    const DisjointBoxLayout& fineGrids = a_phiThisLevel.getBoxes();
    const DisjointBoxLayout& crseGrids = a_correctCoarse.getBoxes();
    CH_assert(fineGrids.compatible(crseGrids));

    const ProblemDomain& fineDomain = fineGrids.physDomain();
    const ProblemDomain& crseDomain = crseGrids.physDomain();

    const IntVect mgRefRatio = fineDomain.size() / crseDomain.size();
    CH_assert(mgRefRatio.product() > 1);

    DataIterator dit = fineGrids.dataIterator();
    for (dit.reset(); dit.ok(); ++dit) {
        // Create references for convenience
        FArrayBox& fineFAB = a_phiThisLevel[dit];
        const FArrayBox& crseFAB = a_correctCoarse[dit];
        const Box& fineValid = fineGrids[dit];

        // To make things easier, we will offset the
        // coarse and fine data boxes to zero.
        const IntVect& fiv = fineValid.smallEnd();
        const IntVect civ = coarsen(fiv, mgRefRatio);

        // Correct the fine data
        FORT_CONSTINTERPPS (
            CHF_FRA_SHIFT(fineFAB, fiv),
            CHF_CONST_FRA_SHIFT(crseFAB, civ),
            CHF_BOX_SHIFT(fineValid, fiv),
            CHF_CONST_INTVECT(mgRefRatio));
    }
}
// ---------------------------------------------------------------
// tag cells for regridding
void
AMRNavierStokes::tagCells(IntVectSet & a_tags)
{
  if (s_verbosity >= 3)
    {
      pout () << "AMRNavierStokes::tagCells " << m_level << endl;
    }

  IntVectSet local_tags;

  // create tags based on something or other
  // for now, don't do anything
  const DisjointBoxLayout& level_domain = newVel().getBoxes();

  if (s_tag_vorticity)
    {
      LevelData<FArrayBox> vorticity;
      LevelData<FArrayBox> mag_vorticity;
      if (SpaceDim == 2)
        {
          vorticity.define(level_domain,1);
        }
      else if (SpaceDim == 3)
        {
          vorticity.define(level_domain,SpaceDim);
          mag_vorticity.define(level_domain,1);
        }
      computeVorticity(vorticity);

      Interval vortInterval(0,0);
      if (SpaceDim == 3)
        {
          vortInterval = Interval(0,SpaceDim-1);
        }
      Real tagLevel = norm(vorticity, vortInterval, 0);
      // Real tagLevel = 1.0;
      //tagLevel *= s_vort_factor/m_dx;
      // actually tag where vort*dx > s_vort_factor*max(vort)
      tagLevel = s_vort_factor/m_dx;

      if (tagLevel > 0)
        {
          // now tag where vorticity magnitude is greater than or equal
          // to tagLevel
          DataIterator dit = vorticity.dataIterator();
          for (dit.reset(); dit.ok(); ++dit)
            {
              FArrayBox& vortFab = vorticity[dit];

              // this only needs to be done in 3d...
              if (SpaceDim==3)
                {
                  FArrayBox& magVortFab = mag_vorticity[dit];
                  FORT_MAGVECT(CHF_FRA1(magVortFab,0),
                               CHF_CONST_FRA(vortFab),
                               CHF_BOX(level_domain[dit]));
                }

              BoxIterator bit(vortFab.box());
              for (bit.begin(); bit.ok(); ++bit)
                {
                  const IntVect& iv = bit();
                  if (SpaceDim == 2)
                    {
                      if (abs(vortFab(iv)) >= tagLevel)
                        {
                          local_tags |= iv;
                        }
                    }
                  else if (SpaceDim == 3)
                    {
                      FArrayBox& magVortFab = mag_vorticity[dit];
                      if (abs(magVortFab(iv)) >= tagLevel)
                        {
                          local_tags |= iv;
                        }
                    } // end if DIM=3
                } // end loop over interior of box
            } // loop over grids
        } // if taglevel > 0
    } // if tagging on vorticity

  a_tags = local_tags;
}
Beispiel #10
0
// this function works on two solutions on equivalent grids.
// It subtracts the computed solution from the exact solution
// if a_doGhostCells == true, then does box-by-box comparison,
// including ghost cells (boxes must be the same for each).
// Otherwise, only does this for valid cells, but boxes don't
// need to be the same.
void computeSameSizeError(Vector<LevelData<FArrayBox>* >&       a_error,
                          const Vector<string>&                 a_errorVars,
                          const Vector<LevelData<FArrayBox>* >& a_computedSoln,
                          const Vector<string>&                 a_computedVars,
                          const Vector<DisjointBoxLayout>&      a_computedGrids,
                          const Real                            a_dx,
                          const Vector<int>&                    a_refRatio,
                          const Vector<LevelData<FArrayBox>* >& a_exactSoln,
                          const Vector<string>&                 a_exactVars,
                          Real                                  a_bogus_value,
                          bool                                  a_computeRelativeError,
                          bool                                  a_doGhostCells)

{
  int numLevels = a_computedSoln.size();

  CH_assert(a_exactSoln.size() == numLevels);
  CH_assert(a_error.size() == numLevels);
  CH_assert(a_refRatio.size() >= numLevels - 1);

  Real dxLevel = a_dx;

  // outer loop is over levels
  for (int level = 0; level < numLevels; level++)
  {
    LevelData<FArrayBox>& thisLevelError = *a_error[level];
    LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level];
    LevelData<FArrayBox>& thisLevelExact = *a_exactSoln[level];

    const DisjointBoxLayout levelGrids = thisLevelComputed.getBoxes();
    const DisjointBoxLayout exactGrids = thisLevelExact.getBoxes();

    DataIterator levelDit = levelGrids.dataIterator();
    for (levelDit.begin(); levelDit.ok(); ++levelDit)
    {
      // initialize error to a bogus value
      thisLevelError[levelDit()].setVal(a_bogus_value);
    }

    // loop over variables
    for (int nErr = 0; nErr < a_errorVars.size(); nErr++)
    {
      string thisErrVar = a_errorVars[nErr];
      bool done = false;

      // this is where things differ between the ghost-cell
      // and non-ghost-cell approach.
      if (a_doGhostCells)
      {
        // this is the older approach to things --
        // do everything grid-by-grid

        // first loop over exact variables
        for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++)
        {
          string thisExactVar = a_exactVars[exactComp];
          // check if this exact variable is "the one"
          if (thisExactVar == thisErrVar)
          {
            int computedComp = 0;

            // now loop over computed variables
            while (!done && (computedComp < a_computedVars.size()))
            {
              if (a_computedVars[computedComp] == thisErrVar)
              {
                // copy exact solution -> error
                // and then subtract computed solution
                DataIterator exactDit = thisLevelExact.dataIterator();
                for (levelDit.reset(); levelDit.ok(); ++levelDit)
                {
                  FArrayBox& thisComputed = thisLevelComputed[levelDit()];
                  FArrayBox& thisError = thisLevelError[levelDit()];
                  const Box& thisBox = levelGrids[levelDit()];

                  for (exactDit.begin(); exactDit.ok(); ++exactDit)
                  {
                    if (thisBox.contains(exactGrids[exactDit()]))
                    {
                      thisError.copy(thisLevelExact[exactDit()],
                                     exactComp, nErr, 1);
                    } // end if exact and computed boxes match
                  } // end loop over exact grids

                  if (a_computeRelativeError)
                  {
                    // do this a little strangely -- relative
                    // error is one - computed/exact.
                    thisError.divide(thisComputed, computedComp, nErr, 1);
                    thisError.invert(-1.0, nErr, 1);
                    thisError.plus(1.0, nErr, 1);
                  }
                  else
                  {
                    thisError.minus(thisComputed, computedComp, nErr, 1);
                  }
                } // end loop over grids

                done = true;
              } // if a_computedVar is a_errorVar

              computedComp += 1;
            } // end loop over a_computedVars

            if (!done)
            {
              pout() << "Variable " << thisErrVar  << " not found!!!" << endl;
              MayDay::Error();
            }
          } // end if this exactVar is correct
        }  // end loop over exact variables
      }
      else
        // non-ghost cell case; this is simpler:
      {
        // first loop over exact variables and copy into error
        for (int exactComp=0; exactComp<a_exactVars.size(); ++exactComp)
        {
          string thisExactVar = a_exactVars[exactComp];

          // check if this exact variable is "the one"
          if (thisExactVar == thisErrVar)
          {
            // copy exact solution -> error
            Interval exactInterval(exactComp, exactComp);
            Interval errInterval(nErr, nErr);
            thisLevelExact.copyTo(exactInterval,
                                  thisLevelError,
                                  errInterval);
            done = true;
          } // end if this exact var is the error var
        } // end loop over exact comps

        if (!done)
        {
          pout() << "Variable " << thisErrVar
                 << " not found in exact solution!!!" << endl;
          MayDay::Error();
        }

        done = false;
        int computedComp = 0;
        // now loop over computed variables and subtract computed solution
        while (!done && (computedComp < a_computedVars.size()))
        {
          if (a_computedVars[computedComp] == thisErrVar)
          {
            for (levelDit.reset(); levelDit.ok(); ++levelDit)
            {
              FArrayBox& thisComputed = thisLevelComputed[levelDit()];
              FArrayBox& thisError = thisLevelError[levelDit()];

              thisError.minus(thisComputed, computedComp, nErr, 1);
            } // end loop over computed/error grids

            done = true;
          } // if a_computedVar is a_errorVar

          computedComp += 1;
        } // end loop over a_computedVars

        if (!done)
        {
          pout() << "Variable " << thisErrVar  << " not found!!!" << endl;
          MayDay::Error();
        }
      } // end non-ghost-cell case
    } // end loop over errors

    // now need to set covered regions to 0
    if (level < numLevels - 1)
    {
      // will need to loop over all boxes in finer level, not just
      // those on this processor...
      const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout();
      LayoutIterator fineLit = finerGrids.layoutIterator();

      // outer loop over this level's grids, since there are fewer of them
      DataIterator levelDit = thisLevelError.dataIterator();
      for (levelDit.reset(); levelDit.ok(); ++levelDit)
      {
        const Box& coarseBox = levelGrids[levelDit()];
        FArrayBox& thisError = thisLevelError[levelDit()];
        int numError = thisError.nComp();

        for (fineLit.reset(); fineLit.ok(); ++fineLit)
        {
          Box fineBox(finerGrids[fineLit()]);
          // now coarsen box down to this level
          fineBox.coarsen(a_refRatio[level]);
          // if coarsened fine box intersects error's box, set
          // overlap to 0
          fineBox &= coarseBox;
          if (!fineBox.isEmpty())
          {
            thisError.setVal(0.0, fineBox, 0, numError);
          }
        } // end loop over finer-level grids
      } // end loop over this-level grids

      // this is a good place to update dx as well
      dxLevel = dxLevel / a_refRatio[level];
    } // end if there is a finer level

    // finally, if we're not doing ghost cells, do an exchange just
    // to "prettify" the output
    if (!a_doGhostCells)
    {
      thisLevelError.exchange(thisLevelError.interval());
    }
  } // end loop over levels
}
Beispiel #11
0
//
// VCAMRPoissonOp2::reflux()
//   There are currently the new version (first) and the old version (second)
//   in this file.  Brian asked to preserve the old version in this way for
//   now. - TJL (12/10/2007)
//
void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>&        a_phiFine,
                            const LevelData<FArrayBox>&        a_phi,
                            LevelData<FArrayBox>&              a_residual,
                            AMRLevelOp<LevelData<FArrayBox> >* a_finerOp)
{
  CH_TIMERS("VCAMRPoissonOp2::reflux");

  m_levfluxreg.setToZero();
  Interval interv(0,a_phi.nComp()-1);

  CH_TIMER("VCAMRPoissonOp2::reflux::incrementCoarse", t2);
  CH_START(t2);

  DataIterator dit = a_phi.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
  {
    const FArrayBox& coarfab   = a_phi[dit];
    const FluxBox&   coarBCoef = (*m_bCoef)[dit];
    const Box&       gridBox   = a_phi.getBoxes()[dit];

    if (m_levfluxreg.hasCF(dit()))
    {
      for (int idir = 0; idir < SpaceDim; idir++)
      {
        FArrayBox coarflux;
        Box faceBox = surroundingNodes(gridBox, idir);

        getFlux(coarflux, coarfab, coarBCoef, faceBox, idir);

        Real scale = 1.0;
        m_levfluxreg.incrementCoarse(coarflux, scale,dit(),
            interv, interv, idir);
      }
    }
  }

  CH_STOP(t2);

  // const cast:  OK because we're changing ghost cells only
  LevelData<FArrayBox>& phiFineRef = ( LevelData<FArrayBox>&)a_phiFine;

  VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp;
  QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser;

  quadCFI.coarseFineInterp(phiFineRef, a_phi);
  // I'm pretty sure this is not necessary. bvs -- flux calculations use
  // outer ghost cells, but not inner ones
  // phiFineRef.exchange(a_phiFine.interval());
  IntVect phiGhost = phiFineRef.ghostVect();
  int ncomps = a_phiFine.nComp();

  CH_TIMER("VCAMRPoissonOp2::reflux::incrementFine", t3);
  CH_START(t3);

  DataIterator ditf = a_phiFine.dataIterator();
  const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout();
  for (ditf.reset(); ditf.ok(); ++ditf)
    {
      const FArrayBox& phifFab   = a_phiFine[ditf];
      const FluxBox&   fineBCoef = (*(finerAMRPOp->m_bCoef))[ditf];
      const Box&       gridbox   = dblFine.get(ditf());

      for (int idir = 0; idir < SpaceDim; idir++)
        {
          //int normalGhost = phiGhost[idir];
          SideIterator sit;
          for (sit.begin(); sit.ok(); sit.next())
            {
              if (m_levfluxreg.hasCF(ditf(), sit()))
                {
                  Side::LoHiSide hiorlo = sit();
                  Box fluxBox = bdryBox(gridbox,idir,hiorlo,1);

                  FArrayBox fineflux(fluxBox,ncomps);
                  getFlux(fineflux, phifFab, fineBCoef, fluxBox, idir,
                          m_refToFiner);

                  Real scale = 1.0;
                  m_levfluxreg.incrementFine(fineflux, scale, ditf(),
                                             interv, interv, idir, hiorlo);
                }
            }
        }
    }

  CH_STOP(t3);

  Real scale = 1.0/m_dx;
  m_levfluxreg.reflux(a_residual, scale);
}
Beispiel #12
0
Real DotProduct(const BoxLayoutData<FArrayBox>& a_dataOne,
                const BoxLayoutData<FArrayBox>& a_dataTwo,
                const BoxLayout&                a_dblIn,
                const Interval&                 a_comps)
{
  Vector<Real> rhodot;
  rhodot.reserve(10);
  const int startcomp = a_comps.begin();
  const int endcomp = a_comps.end();
  //calculate the single-processor dot product
  DataIterator dit = a_dataOne.dataIterator();

  for (dit.reset(); dit.ok(); ++dit)
  {
    Box fabbox = a_dblIn.get(dit());
    const FArrayBox& onefab = a_dataOne[dit()];
    const FArrayBox& twofab = a_dataTwo[dit()];
    CH_assert(onefab.box().contains(fabbox));
    CH_assert(twofab.box().contains(fabbox));

    Real dotgrid = 0;
    FORT_DOTPRODUCT(CHF_REAL(dotgrid),
                    CHF_CONST_FRA(onefab),
                    CHF_CONST_FRA(twofab),
                    CHF_BOX(fabbox),
                    CHF_CONST_INT(startcomp),
                    CHF_CONST_INT(endcomp));

    rhodot.push_back(dotgrid);
  }

  // now for the multi-processor fandango

  //gather all the rhodots onto a vector and add them up
  int baseProc = 0;
  Vector<Vector<Real> >dotVec;
  gather(dotVec, rhodot, baseProc);

  Real rhodotTot = 0.0;
  if (procID() == baseProc)
  {
    CH_assert(dotVec.size() == numProc());

    rhodot.resize(a_dblIn.size());

    int index = 0;
    for (int p = 0; p < dotVec.size(); p++)
    {
      Vector<Real>& v = dotVec[p];
      for (int i = 0; i < v.size(); i++, index++)
      {
        rhodot[index] = v[i];
      }
    }

    rhodot.sort();

    for (int ivec = 0; ivec < rhodot.size(); ivec++)
    {
      rhodotTot += rhodot[ivec];
    }
  }

  //broadcast the sum to all processors.
  broadcast(rhodotTot, baseProc);

  //return the total
  return rhodotTot;
}
Beispiel #13
0
void EBPoissonOp::
applyOp(LevelData<EBCellFAB>&             a_opPhi,
        const LevelData<EBCellFAB>&       a_phi,
        bool                              a_homogeneousPhysBC,
        DataIterator& dit,
        bool a_do_exchange)
{
  CH_TIMERS("EBPoissonOp::applyOp");
  CH_TIMER("regular_apply", t1);
  CH_TIMER("irregular_apply", t2);
  CH_TIMER("eb_bcs_apply", t3);
  CH_TIMER("dom_bcs_apply", t4);
  CH_TIMER("alpha_apply", t5);
  CH_assert(a_opPhi.ghostVect() == m_ghostCellsRHS);
  CH_assert(a_phi.ghostVect() == m_ghostCellsPhi);


  CH_assert(a_phi.nComp() == a_opPhi.nComp());

  LevelData<EBCellFAB>& phi = const_cast<LevelData<EBCellFAB>&>(a_phi);
  if (a_do_exchange)
    {
      phi.exchange(phi.interval());
    }

  int nComps = a_phi.nComp();

  for (dit.reset(); dit.ok(); ++dit)
    {

      Box dblBox( m_eblg.getDBL().get(dit()) );
      const EBCellFAB& phifab = phi[dit()];
      Box curPhiBox = phifab.box();
      const BaseFab<Real>& curPhiFAB = phifab.getSingleValuedFAB();

      EBCellFAB& opphifab = a_opPhi[dit()];
      BaseFab<Real>& curOpPhiFAB = opphifab.getSingleValuedFAB();

      //       Interval interv(0, nComps-1);
      CH_START(t5);
      if (m_alpha == 0)
        {
          opphifab.setVal(0.0);
        }
      else
        {
          opphifab.copy(phifab);
          opphifab.mult(m_alpha);
        }
      CH_STOP(t5);

      Box loBox[SpaceDim],hiBox[SpaceDim];
      int hasLo[SpaceDim],hasHi[SpaceDim];
      CH_START(t1);
      applyOpRegularAllDirs( loBox, hiBox, hasLo, hasHi,
                             dblBox, curPhiBox, nComps,
                             curOpPhiFAB,
                             curPhiFAB,
                             a_homogeneousPhysBC,
                             dit(),
                             m_beta);

      CH_STOP(t1);

      CH_START(t2);
      //apply stencil
      m_opEBStencil[dit()]->apply(opphifab, phifab, false);
      CH_STOP(t2);
      //apply inhom boundary conditions
      CH_START(t3);
      if (!a_homogeneousPhysBC)
        {
          const Real factor = m_dxScale*m_beta;
          m_ebBC->applyEBFlux(opphifab, phifab, m_vofItIrreg[dit()], (*m_eblg.getCFIVS()),
                              dit(), m_origin, m_dx, factor,
                              a_homogeneousPhysBC, m_time);
        }
      CH_STOP(t3);

      CH_START(t4);
      int comp = 0;
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          for (m_vofItIrregDomLo[idir][dit()].reset(); m_vofItIrregDomLo[idir][dit()].ok();  ++m_vofItIrregDomLo[idir][dit()])
            {
              Real flux;
              const VolIndex& vof = m_vofItIrregDomLo[idir][dit()]();
              m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()],
                                      m_origin,m_dx,idir,Side::Lo, dit(), m_time,
                                      a_homogeneousPhysBC);

              opphifab(vof,comp) -= flux * m_beta*m_invDx[idir];
            }
          for (m_vofItIrregDomHi[idir][dit()].reset(); m_vofItIrregDomHi[idir][dit()].ok();  ++m_vofItIrregDomHi[idir][dit()])
            {
              Real flux;
              const VolIndex& vof = m_vofItIrregDomHi[idir][dit()]();
              m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()],
                                      m_origin,m_dx,idir,Side::Hi,dit(), m_time,
                                      a_homogeneousPhysBC);

              opphifab(vof,comp) += flux * m_beta*m_invDx[idir];
            }

        }
      CH_STOP(t4);
    }
}
// ---------------------------------------------------------
void
AMRNavierStokes::computeVorticity(LevelData<FArrayBox>& a_vorticity) const
{
  // this breaks the "const"-ness of the function,
  // but is necessary to ensure that boundary
  // conditions are properly set.
  LevelData<FArrayBox>& vel =
    *(const_cast<LevelData<FArrayBox>*>(m_vel_new_ptr));

  const DisjointBoxLayout& grids = vel.getBoxes();

  if (m_level > 0)
    {
      // do quadratic C/F BC's
      // for now, assume that BC's are with new velocity
      // (may need to be changed for fine-level regridding)
      LevelData<FArrayBox>& crseVel = crseNSPtr()->newVel();
      const DisjointBoxLayout& crseGrids = crseVel.getBoxes();
      int nRefCrse = crseNSPtr()->refRatio();

      QuadCFInterp interpolator(grids, &crseGrids, m_dx, nRefCrse,
                                SpaceDim, m_problem_domain);

      interpolator.coarseFineInterp(vel, crseVel);
    }

  Interval velComps(0,SpaceDim-1);
  vel.exchange(velComps);

  DataIterator dit = vel.dataIterator();

  // at the moment, do extrap at physical boundaries
  // (same effect as one-sided differencing)
  BCHolder vortVelBC = m_physBCPtr->extrapFuncBC(1);

  for (dit.reset(); dit.ok(); ++dit)
    {
      // apply physical BC's
      vortVelBC(vel[dit], grids[dit],
                m_problem_domain, m_dx,
                true); // homogeneous
      if (SpaceDim == 3)
        {
          for (int dir=0; dir<SpaceDim; dir++)
            {
              // and then compute vorticity
              FORT_COMPUTEVORT(CHF_FRA1(a_vorticity[dit],dir),
                               CHF_CONST_FRA(vel[dit]),
                               CHF_BOX(grids[dit]),
                               CHF_CONST_REAL(m_dx),
                               CHF_CONST_INT(dir));
            }
        }
      else if (SpaceDim == 2)
        {
          int dir = 2;
          FORT_COMPUTEVORT(CHF_FRA1(a_vorticity[dit],0),
                           CHF_CONST_FRA(vel[dit]),
                           CHF_BOX(grids[dit]),
                           CHF_CONST_REAL(m_dx),
                           CHF_CONST_INT(dir));
        } // end dimensionality choice
    } // end loop over grids
}
Beispiel #15
0
// -----------------------------------------------------------------------------
// Adds coarse cell values directly to all overlying fine cells,
// then removes the average from the fine result.
// -----------------------------------------------------------------------------
void ZeroAvgConstInterpPS::prolongIncrement (LevelData<FArrayBox>&       a_phiThisLevel,
                                             const LevelData<FArrayBox>& a_correctCoarse)
{
    CH_TIME("ZeroAvgConstInterpPS::prolongIncrement");

    // Gather grids, domains, refinement ratios...
    const DisjointBoxLayout& fineGrids = a_phiThisLevel.getBoxes();
    const DisjointBoxLayout& crseGrids = a_correctCoarse.getBoxes();
    CH_assert(fineGrids.compatible(crseGrids));

    const ProblemDomain& fineDomain = fineGrids.physDomain();
    const ProblemDomain& crseDomain = crseGrids.physDomain();

    const IntVect mgRefRatio = fineDomain.size() / crseDomain.size();
    CH_assert(mgRefRatio.product() > 1);

    // These will accumulate averaging data.
    Real localSum = 0.0;
    Real localVol = 0.0;
    CH_assert(!m_CCJinvPtr.isNull());
    CH_assert(m_dxProduct > 0.0);

    DataIterator dit = fineGrids.dataIterator();
    for (dit.reset(); dit.ok(); ++dit) {
        // Create references for convenience
        FArrayBox& fineFAB = a_phiThisLevel[dit];
        const FArrayBox& crseFAB = a_correctCoarse[dit];
        const Box& fineValid = fineGrids[dit];
        const FArrayBox& JinvFAB = (*m_CCJinvPtr)[dit];

        // To make things easier, we will offset the
        // coarse and fine data boxes to zero.
        const IntVect& fiv = fineValid.smallEnd();
        const IntVect civ = coarsen(fiv, mgRefRatio);

        // Correct the fine data
        FORT_CONSTINTERPWITHAVGPS (
            CHF_FRA_SHIFT(fineFAB, fiv),
            CHF_CONST_FRA_SHIFT(crseFAB, civ),
            CHF_BOX_SHIFT(fineValid, fiv),
            CHF_CONST_INTVECT(mgRefRatio),
            CHF_CONST_FRA1_SHIFT(JinvFAB,0,fiv),
            CHF_CONST_REAL(m_dxProduct),
            CHF_REAL(localVol),
            CHF_REAL(localSum));
    }

    // Compute global sum (this is where the MPI communication happens)
#ifdef CH_MPI
    Real globalSum = 0.0;
    int result = MPI_Allreduce(&localSum, &globalSum, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm);

    if (result != MPI_SUCCESS) {
        MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement");
    }

    Real globalVol = 0.0;
    result = MPI_Allreduce(&localVol, &globalVol, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm);

    if (result != MPI_SUCCESS) {
        MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement");
    }

#else
    Real globalSum = localSum;
    Real globalVol = localVol;
#endif

    // Remove the average from phi.
    Real avgPhi = globalSum / globalVol;
    for (dit.reset(); dit.ok(); ++dit) {
        a_phiThisLevel[dit] -= avgPhi;
    }
}
Beispiel #16
0
int fluxRegTest()
{
#ifdef CH_USE_HDF5
  writeLevel(NULL);
#endif
  int retflag = 0;

  int nref;
  Vector<Box> fineboxes;
  Vector<Box> coarboxes;
  Box domf, domc;

  //set coarse and fine grid boxes
  setDefaults(nref, coarboxes,  fineboxes, domc, domf);

  {
    // first do nonperiodic test

    Interval interv(0,0);

    //set up coarse and fine grids
    DisjointBoxLayout dblFineCell,dblCoarCell;
    Vector<int> procAssignCoar(coarboxes.size(), 0);
    Vector<int> procAssignFine(fineboxes.size(), 0);
    LoadBalance(procAssignCoar, coarboxes);
    LoadBalance(procAssignFine, fineboxes);

    dblCoarCell.define(coarboxes, procAssignCoar);
    dblFineCell.define(fineboxes, procAssignFine);

    dblCoarCell.close();
    dblFineCell.close();

    LevelData<FArrayBox> coarData(dblCoarCell, 1);
    LevelData<FArrayBox> fineData(dblFineCell, 1);

    DataIterator coarIt = coarData.dataIterator();
    DataIterator fineIt = fineData.dataIterator();

    LevelFluxRegister fluxReg(dblFineCell,
                              dblCoarCell,
                              domf, nref,
                              1);

    //set data and flux registers to zero
    for (coarIt.reset(); coarIt.ok(); ++coarIt)
      coarData[coarIt()].setVal(0.);

    fluxReg.setToZero();

    //increment and decrement
    //flux registers with equal size fluxes
    Real scale = 1.0;
    Real fluxVal = 4.77;
    for (coarIt.reset(); coarIt.ok(); ++coarIt)
      {
        const Box&  cellBoxCoar = dblCoarCell.get(coarIt());
        for (int idir = 0; idir < SpaceDim; idir++)
          {
            Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir);
            FArrayBox edgeFlux(edgeBoxCoar,1);
            edgeFlux.setVal(fluxVal);
            DataIndex dataIndGlo = coarIt();
            fluxReg.incrementCoarse(edgeFlux, scale,
                                    dataIndGlo, interv, interv, idir);
          }
      }

    for (fineIt.reset(); fineIt.ok(); ++fineIt)
      {
        const Box&  cellBoxFine = dblFineCell.get(fineIt());
        for (int idir = 0; idir < SpaceDim; idir++)
          {
            Box edgeBoxFine = surroundingNodes(cellBoxFine, idir);
            FArrayBox edgeFlux(edgeBoxFine,1);
            edgeFlux.setVal(fluxVal);
            SideIterator sit;
            DataIndex dataIndGlo = fineIt();
            for (sit.reset(); sit.ok(); ++sit)
              {
                fluxReg.incrementFine(edgeFlux, scale,
                                      dataIndGlo,  interv, interv, idir, sit());
              }
          }
      }

    //reflux what ought to be zero into zero and the result should be zero
    fluxReg.reflux(coarData, scale);

    DataIterator datIt = coarData.dataIterator();
    for (datIt.reset(); datIt.ok(); ++datIt)
      {
        const FArrayBox& data = coarData[datIt()];
        Real rmax = Abs(data.max());
        Real rmin = Abs(data.min());
        if ((rmax > 1.0e-10)||(rmin > 1.0e-10))
          {
            pout() << indent << pgmname
                 << ": fluxRegister failed the nonperiodic conservation test = " << endl;
            retflag = 1;
          }
      }
  }
  // end non-periodic test

  // now do the same thing all over again, this time with a periodic domain
  {
    ProblemDomain coarseDomain(domc);
    ProblemDomain fineDomain(domf);
    for (int dir=0; dir<SpaceDim; dir++)
      {
        coarseDomain.setPeriodic(dir, true);
        fineDomain.setPeriodic(dir, true);
      }

    Interval interv(0,0);

    //set up coarse and fine grids
    DisjointBoxLayout dblFineCell,dblCoarCell;
    Vector<int> procAssignCoar(coarboxes.size(), 0);
    Vector<int> procAssignFine(fineboxes.size(), 0);
    LoadBalance(procAssignCoar, coarboxes);
    LoadBalance(procAssignFine, fineboxes);

    dblCoarCell.define(coarboxes, procAssignCoar, coarseDomain);
    dblFineCell.define(fineboxes, procAssignFine, fineDomain);

    dblCoarCell.close();
    dblFineCell.close();

    LevelData<FArrayBox> coarData(dblCoarCell, 1);
    LevelData<FArrayBox> fineData(dblFineCell, 1);

    DataIterator coarIt = coarData.dataIterator();
    DataIterator fineIt = fineData.dataIterator();

    LevelFluxRegister fluxReg(dblFineCell,
                              dblCoarCell,
                              fineDomain, nref,
                              1);

    //set data and flux registers to zero
    for (coarIt.reset(); coarIt.ok(); ++coarIt)
      coarData[coarIt()].setVal(0.);

    fluxReg.setToZero();

    //increment and decrement
    //flux registers with equal size fluxes
    Real scale = 1.0;
    Real fluxVal = 4.77;
    for (coarIt.reset(); coarIt.ok(); ++coarIt)
      {
        const Box&  cellBoxCoar = dblCoarCell.get(coarIt());
        for (int idir = 0; idir < SpaceDim; idir++)
          {
            Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir);
            FArrayBox edgeFlux(edgeBoxCoar,1);
            edgeFlux.setVal(fluxVal);
            DataIndex dataIndGlo = coarIt();
            fluxReg.incrementCoarse(edgeFlux, scale,
                                    dataIndGlo, interv, interv, idir);
          }
      }

    for (fineIt.reset(); fineIt.ok(); ++fineIt)
      {
        const Box&  cellBoxFine = dblFineCell.get(fineIt());
        for (int idir = 0; idir < SpaceDim; idir++)
          {
            Box edgeBoxFine = surroundingNodes(cellBoxFine, idir);
            FArrayBox edgeFlux(edgeBoxFine,1);
            edgeFlux.setVal(fluxVal);
            SideIterator sit;
            DataIndex dataIndGlo = fineIt();
            for (sit.reset(); sit.ok(); ++sit)
              {
                fluxReg.incrementFine(edgeFlux, scale,
                                      dataIndGlo,  interv, interv, idir, sit());
              }
          }
      }

    //reflux what ought to be zero into zero and the result should be zero
    fluxReg.reflux(coarData, scale);

    DataIterator datIt = coarData.dataIterator();
    for (datIt.reset(); datIt.ok(); ++datIt)
      {
        const FArrayBox& data = coarData[datIt()];
        Real rmax = Abs(data.max());
        Real rmin = Abs(data.min());
        if ((rmax > 1.0e-10)||(rmin > 1.0e-10))
          {
            pout() << indent << pgmname
                 << ": fluxRegister failed the periodic conservation test " << endl;
            retflag += 2;
          }
      }
  } // end periodic test

  return retflag;
}
Beispiel #17
0
void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>&        a_phiFine,
                            const LevelData<FArrayBox>&        a_phi,
                            LevelData<FArrayBox>&              a_residual,
                            AMRLevelOp<LevelData<FArrayBox> >* a_finerOp)
{
  CH_TIME("VCAMRPoissonOp2::reflux");

  int ncomp = 1;
  ProblemDomain fineDomain = refine(m_domain, m_refToFiner);
  LevelFluxRegister levfluxreg(a_phiFine.disjointBoxLayout(),
                               a_phi.disjointBoxLayout(),
                               fineDomain,
                               m_refToFiner,
                               ncomp);

  levfluxreg.setToZero();
  Interval interv(0,a_phi.nComp()-1);

  DataIterator dit = a_phi.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      const FArrayBox& coarfab = a_phi[dit];
      const FluxBox& coarBCoef  = (*m_bCoef)[dit];
      const Box& gridBox = a_phi.getBoxes()[dit];

      for (int idir = 0; idir < SpaceDim; idir++)
        {
          FArrayBox coarflux;
          Box faceBox = surroundingNodes(gridBox, idir);
          getFlux(coarflux, coarfab, coarBCoef , faceBox, idir);

          Real scale = 1.0;
          levfluxreg.incrementCoarse(coarflux, scale,dit(),
                                     interv,interv,idir);
        }
    }
  LevelData<FArrayBox>& p = ( LevelData<FArrayBox>&)a_phiFine;

  // has to be its own object because the finer operator
  // owns an interpolator and we have no way of getting to it
  VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp;
  QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser;

  quadCFI.coarseFineInterp(p, a_phi);
  // p.exchange(a_phiFine.interval()); // BVS is pretty sure this is not necesary.
  IntVect phiGhost = p.ghostVect();

  DataIterator ditf = a_phiFine.dataIterator();
  const  DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout();
  for (ditf.reset(); ditf.ok(); ++ditf)
    {
      const FArrayBox& phifFab = a_phiFine[ditf];
      const FluxBox& fineBCoef  = (*(finerAMRPOp->m_bCoef))[ditf];
      const Box& gridbox = dblFine.get(ditf());
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          int normalGhost = phiGhost[idir];
          SideIterator sit;
          for (sit.begin(); sit.ok(); sit.next())
            {
              Side::LoHiSide hiorlo = sit();
              Box fabbox;
              Box facebox;

              // assumption here that the stencil required
              // to compute the flux in the normal direction
              // is 2* the number of ghost cells for phi
              // (which is a reasonable assumption, and probably
              // better than just assuming you need one cell on
              // either side of the interface
              // (dfm 8-4-06)
              if (sit() == Side::Lo)
                {
                  fabbox = adjCellLo(gridbox,idir, 2*normalGhost);
                  fabbox.shift(idir, 1);
                  facebox = bdryLo(gridbox, idir,1);
                }
              else
                {
                  fabbox = adjCellHi(gridbox,idir, 2*normalGhost);
                  fabbox.shift(idir, -1);
                  facebox = bdryHi(gridbox, idir, 1);
                }

              // just in case we need ghost cells in the transverse direction
              // (dfm 8-4-06)
              for (int otherDir=0; otherDir<SpaceDim; ++otherDir)
                {
                  if (otherDir != idir)
                    {
                      fabbox.grow(otherDir, phiGhost[otherDir]);
                    }
                }
              CH_assert(!fabbox.isEmpty());

              FArrayBox phifab(fabbox, a_phi.nComp());
              phifab.copy(phifFab);

              FArrayBox fineflux;
              getFlux(fineflux, phifab, fineBCoef, facebox, idir,
                      m_refToFiner);

              Real scale = 1.0;
              levfluxreg.incrementFine(fineflux, scale, ditf(),
                                       interv, interv, idir, hiorlo);
            }
        }
    }

  Real scale =  1.0/m_dx;
  levfluxreg.reflux(a_residual, scale);
}
Beispiel #18
0
int fluxRegTest()
{
  int nref = 2;
  int eekflag = 0;
  ParmParse pp;

  Box domainCoar, domainFine;
  eekflag = makeGeometry(domainFine);
  if (eekflag != 0)
    return eekflag;
  domainCoar = coarsen(domainFine, nref);

  DisjointBoxLayout dblFine,dblCoar;
  eekflag = makeLayouts(dblCoar, dblFine, domainCoar, domainFine);

  Interval interv(0,0);

  EBISLayout ebislFine, ebislCoar;
  int nghost = 3;
  makeEBISL(ebislFine, dblFine, domainFine, nghost);
  makeEBISL(ebislCoar, dblCoar, domainCoar, nghost);

  EBCellFactory factFine(ebislFine);
  EBCellFactory factCoar(ebislCoar);
  IntVect ivghost = IntVect::Unit;

  LevelData<EBCellFAB> fineData(dblFine, 1,ivghost, factFine);
  LevelData<EBCellFAB> coarData(dblCoar, 1,ivghost, factCoar);

  LevelData<EBCellFAB> extraDense(dblCoar, 1,ivghost, factCoar);

  //set data and flux registers to zero
  for (DataIterator coarIt = coarData.dataIterator();
      coarIt.ok(); ++coarIt)
      coarData[coarIt()].setVal(0.);
  for (DataIterator fineIt = fineData.dataIterator();
      fineIt.ok(); ++fineIt)
    fineData[fineIt()].setVal(0.);
  {
    //    pout() << "before constructor" << endl;
    EBFluxRegister fluxReg(dblFine,
                           dblCoar,
                           ebislFine,
                           ebislCoar,
                           domainCoar,
                           nref, 1, Chombo_EBIS::instance());
    //    pout() << "after constructor" << endl;
    fluxReg.setToZero();
    //    pout() << "after settozero" << endl;
    //loop through directions
    Real scale = 1.0;
    Real fluxVal = 4.77;
    for (int idir = 0; idir < SpaceDim; idir++)
      {

        //        pout() << "idir = " << idir <<  endl;
        //        MPI_Barrier(Chombo_MPI::comm);
        //increment and decrement
        //flux registers with equal size fluxes
        for (DataIterator coarIt = coarData.dataIterator();
            coarIt.ok(); ++coarIt)
          {
            const Box&  boxCoar = dblCoar.get(coarIt());
            const EBISBox& ebisBox = ebislCoar[coarIt()];
            IntVectSet ivsBC(boxCoar);
            EBFaceFAB edgeFluxReg(ebisBox, boxCoar, idir, 1);
            BaseIFFAB<Real> edgeFluxIrr(ivsBC, ebisBox.getEBGraph(), idir, 1);
            edgeFluxReg.setVal(fluxVal);
            edgeFluxIrr.setVal(fluxVal);
            fluxReg.incrementCoarseRegular(edgeFluxReg, scale,
                                           coarIt(), interv, idir);
            //        pout() << "after increment coar regular"<< endl;
            fluxReg.incrementCoarseIrregular(edgeFluxIrr, scale,
                                             coarIt(), interv, idir);

            //        pout() << "after increment coar irregular"<< endl;
          }
        //        pout() << "after increment coar"<< endl;
        //        MPI_Barrier(Chombo_MPI::comm);
        for (DataIterator fineIt = fineData.dataIterator();
            fineIt.ok(); ++fineIt)
          {
            const Box&  boxFine = dblFine.get(fineIt());
            const EBISBox& ebisBox = ebislFine[fineIt()];
            IntVectSet ivsBF(boxFine);
            EBFaceFAB edgeFluxReg(ebisBox, boxFine, idir, 1);
            BaseIFFAB<Real> edgeFluxIrr(ivsBF, ebisBox.getEBGraph(), idir, 1);
            edgeFluxReg.setVal(fluxVal);
            edgeFluxIrr.setVal(fluxVal);

            for (SideIterator sit; sit.ok(); ++sit)
              {
                fluxReg.incrementFineRegular(edgeFluxReg, scale,
                                             fineIt(),  interv, idir, sit());

                fluxReg.incrementFineIrregular(edgeFluxIrr, scale,
                                               fineIt(),  interv, idir, sit());

              }
          }
        //        pout() << "after increment fine"<< endl;
        //        MPI_Barrier(Chombo_MPI::comm);
      }

    //reflux what ought to be zero into zero and the result should be zero
    //except where the coarse-fine boundary gets crossed by the embedded
    //boundary.  That should get fixed by the extramass thing.
    fluxReg.reflux(coarData, interv, scale);
    //    pout() << "after reflux"<< endl;

    for (DataIterator coarIt = coarData.dataIterator();
        coarIt.ok(); ++coarIt)
      extraDense[coarIt()].setVal(0.);

    // now add extra density to soltuion
    //in the end the solution should return to zero
    fluxReg.incrementDensityArray(extraDense, interv, scale);
  }
  //  pout() << "after fluxreg destruction" << endl;
  //  pout() << "after incementDensityArray"<< endl;
  for (DataIterator coarIt = coarData.dataIterator();
      coarIt.ok(); ++coarIt)
    coarData[coarIt()] += extraDense[coarIt()];
  //  MPI_Barrier(Chombo_MPI::comm);
  //  pout() << "after  += operation "<< endl;
  DataIterator datIt = coarData.dataIterator();
  for (datIt.reset(); datIt.ok(); ++datIt)
    {
      const EBCellFAB& data = coarData[datIt()];
      IntVectSet ivsBox(dblCoar.get(datIt()));
      const EBISBox& ebisBox = ebislCoar[datIt()];
      Real rmax = 0.;
      Real rmin = 0.;
      for (VoFIterator vofit(ivsBox, ebisBox.getEBGraph());
          vofit.ok(); ++vofit)
        {
          const VolIndex& vof = vofit();
          rmax = Max(rmax, Abs(data(vof, 0)));
          rmin = Min(rmax, Abs(data(vof, 0)));

#ifdef CH_USE_FLOAT
          Real tolerance = 1.0e-6;
#else
          Real tolerance = 1.0e-10;
#endif
          if ((rmax > tolerance)||(rmin > tolerance))
            {
              pout() << "EBFluxRegister failed the test at  "
                     << " vof = " << vof << endl;
              pout() << "   rmax: "      << rmax      << ", or"
                     <<   " rmin: "      << rmin      << " >"
                     <<   " tolerance: " << tolerance << ")" << endl;
              eekflag = 42;
              return eekflag;
            }
        }
    }

  //  pout() << "about to return "<< endl;
  return eekflag;
}
Beispiel #19
0
int main(int argc, char* argv[])
{
#ifdef CH_MPI
  MPI_Init(&argc, &argv);
  // setChomboMPIErrorHandler();
  MPI_Barrier(Chombo_MPI::comm);  // Barrier #1
#endif

  // ------------------------------------------------
  // parse command line and input file
  // ------------------------------------------------
  // infile must be first
  if (argc < 2)
  {
    cerr << "  need inputs file" << endl;
    abort();
  }

  char* in_file = argv[1];
  ParmParse pp(argc-2, argv+2, NULL, in_file);

#ifdef CH_MPI
  MPI_Barrier(Chombo_MPI::comm);
#endif

  pout().setf(ios::scientific);
  pout().precision(4);

  // set defaults
  bool isSameSize = false;
  bool doGhostCells = false;
  bool doPlots = true;
  bool isTimeDep = false;
  bool verbose = false;
  bool computeRelativeError = false;
  bool removeMean = false;
  bool useUnitDomain = false;
  bool HOaverage = false;

  // this is the initial value for the error
  Real bogusValue = 0.0;

  string exactRoot, computedRoot, errorRoot;

  Vector<string> errorVars;

  int numCrseFinish, numCrseStart, crseStep, crseMult, intFieldSize;

  init(exactRoot, computedRoot, errorRoot, intFieldSize,
       numCrseStart, errorVars, numCrseFinish, crseStep,
       crseMult, doPlots, isTimeDep, isSameSize, bogusValue,
       computeRelativeError, removeMean, doGhostCells, useUnitDomain,
       HOaverage,verbose);


  int nStep, exactStep;

  if (!isTimeDep)
  {
    crseStep = 1;
    numCrseFinish = numCrseStart;
  }

  for (nStep = numCrseStart; nStep <= numCrseFinish; nStep += crseStep)
  {
    if (verbose)
    {
      pout() << "starting step " << nStep << endl;
    }

    exactStep = nStep*crseMult;

    ostrstream exactFile;
    ostrstream computedFile;
    ostrstream errorFile;

    exactFile.fill('0');
    computedFile.fill('0');
    errorFile.fill('0');

    if (isTimeDep)
    {
      constructPlotFileName(exactFile, exactRoot, intFieldSize, exactStep);
      constructPlotFileName(computedFile, computedRoot, intFieldSize, nStep);
      constructPlotFileName(errorFile, errorRoot, intFieldSize, nStep);

    }
    else
    {
      // if not time dependent, file roots are really filenames
      exactFile << exactRoot << ends;
      computedFile << computedRoot << ends;
      errorFile << errorRoot << ends;
    }

    pout() << "exact Filename = " << exactFile.str() << endl;
    pout() << "computed Filename = " << computedFile.str() << endl;
    if (doPlots)
    {
      pout() << "error Filename = " << errorFile.str() << endl;
    }

    // declare memory
    Vector<LevelData<FArrayBox>* > exactSoln;
    Vector<string> exactVars; // exact solution variable names
    Vector<DisjointBoxLayout> exactGrids;
    Box exactDomain;
    Real exactDx, exactDt, exactTime;
    Vector<int> exactRefRatio;
    int exactNumLevels;
    IntVect ghostVect = IntVect::Unit;
    string exactFileName(exactFile.str());

    // get exact solution
    if (verbose)
    {
      pout() << "read exact solution..." << endl;
    }

    ReadAMRHierarchyHDF5(exactFileName,
                         exactGrids,
                         exactSoln,
                         exactVars,
                         exactDomain,
                         exactDx,
                         exactDt,
                         exactTime,
                         exactRefRatio,
                         exactNumLevels);

    if (verbose)
    {
      pout () << "done reading exact soln" << endl;
    }

    // we assume that exact soln is single-grid if we're doing averaging
    if (!isSameSize)
    {
      CH_assert(exactNumLevels == 1);
    }

    Vector<LevelData<FArrayBox>* > computedSoln;
    Vector<string> computedVars; // computed soln variable names
    Vector<DisjointBoxLayout> computedGrids;
    Box computedDomain;
    Real computedDx, computedDt, computedTime;
    Vector<int> computedRefRatio;
    int computedNumLevels;
    string computedFileName(computedFile.str());

    //ghostVect = IntVect::Zero;
    // now read in computed solution
    if (verbose)
    {
      pout() << "read computed solution..." << endl;
    }

    ReadAMRHierarchyHDF5(computedFileName,
                         computedGrids,
                         computedSoln,
                         computedVars,
                         computedDomain,
                         computedDx,
                         computedDt,
                         computedTime,
                         computedRefRatio,
                         computedNumLevels);

    if (verbose)
    {
      pout() << "done reading computed solution" << endl;
    }

    // reality check
    if ((computedDomain != exactDomain) && isSameSize)
    {
      MayDay::Error("Incompatible exact and computed domains for sameSize comparison");
    }

    int numExact    = exactVars.size();
    int numComputed = computedVars.size();

    int numError = errorVars.size();
    // If no errorVars were specified
    if (numError == 0)
    {
      // Set errorVars to the intersection of exactVars and computedVars
      // This numVars^2 method should be changed to something more efficient
      for (int iExact = 0; iExact < numExact; iExact++)
      {
        for (int iComp = 0; iComp < numComputed; iComp++)
        {
          if (exactVars[iExact] == computedVars[iComp])
          {
            errorVars.push_back(exactVars[iExact]);
            break;
          }
        }
      }

      numError = errorVars.size();
    }
    else
    {
      // if errorVars were specified, then do a quick check that
      // they're present in both exactVars and computedVars
      for (int errVarNo = 0; errVarNo<errorVars.size(); ++errVarNo)
        {
          bool foundComputed = false;
          for (int i=0; i<numComputed; i++)
            {
              if (errorVars[errVarNo] == computedVars[i])
                {
                  foundComputed = true;
                }
            } // end loop over exact variables
          if (!foundComputed)
            {
              pout() << "errorVar " << errorVars[errVarNo]
                     << " not found in computed solution!"
                     << endl;
              MayDay::Error();
            }

          bool foundExact = false;
          for (int i=0; i<numExact; i++)
            {
              if (errorVars[errVarNo] == exactVars[i])
                {
                  foundExact = true;
                }
            } // end loop over exact variables
          if (!foundExact)
            {
              pout() << "errorVar " << errorVars[errVarNo]
                     << " not found in exact solution!"
                     << endl;
              MayDay::Error();
            }

        } // end loop over errorVars
    } // end if errorVars was specified in the inputs file


    Vector<string> errorNames;
    errorNames.resize(numError);

    constructErrorNames(errorNames, errorVars);

    Vector<LevelData<FArrayBox>* > error(computedNumLevels);

    // allocate error -- same domain as computed solution
    for (int level = 0; level < computedNumLevels; level++)
    {
      error[level] = new LevelData<FArrayBox>(computedGrids[level],
                                              numError, ghostVect);
    }

    if (!isSameSize)
    {
      if (verbose)
      {
        pout () << "compute AMR error..." << endl;
      }

      computeAMRError(error,
                      errorVars,
                      computedSoln,
                      computedVars,
                      computedGrids,
                      computedDx,
                      computedRefRatio,
                      exactSoln,
                      exactVars,
                      exactDx,
                      bogusValue,
                      HOaverage,
                      computeRelativeError);

      if (verbose)
      {
        pout() << "done computing AMR error" << endl;
      }
    }
    else
    {
      // first make sure refRatios are the same
      for (int lev = 0; lev < computedRefRatio.size() - 1; lev++)
      {
        CH_assert(computedRefRatio[lev] == exactRefRatio[lev]);
      }

      CH_assert(exactDx == computedDx);

      if (verbose)
      {
        pout () << "compute sameSize error..." << endl;
      }

      computeSameSizeError(error,
                           errorVars,
                           computedSoln,
                           computedVars,
                           computedGrids,
                           computedDx,
                           computedRefRatio,
                           exactSoln,
                           exactVars,
                           bogusValue,
                           computeRelativeError,
                           doGhostCells);

      if (verbose)
      {
        pout() << "done computing sameSize error" << endl;
      }
    }

    Vector<Real> mean(numError);

    // remove mean
    if (removeMean)
    {
      int lBase = 0;
      int numLevels = error.size();

      for (int err = 0; err < numError; err++)
      {
        Interval errComps(err, err);

        if (verbose)
        {
          pout() << "compute mean for component " << err << endl;
        }

        Real volume;
        mean[err] = computeSum(volume,
                               error,
                               computedRefRatio,
                               computedDx,
                               errComps,
                               lBase);

        mean[err] /= volume;

        if (verbose)
        {
          pout() << "comp = "   << err
                 << ", mean = " << mean
                 << ", vol = "  << volume
                 << endl;
        }

        for (int level = 0; level < numLevels; level++)
        {
          LevelData<FArrayBox>& thisLevelError = *error[level];

          const DisjointBoxLayout levelGrids = error[level]->getBoxes();

          DataIterator dit = levelGrids.dataIterator();
          for (dit.reset(); dit.ok(); ++dit)
          {
            const Box thisBox = levelGrids[dit()];
            FArrayBox& thisFabError = thisLevelError[dit()];

            thisFabError.plus(-mean[err],err);
          } // end loop over errors

          thisLevelError.exchange();
        } // end loop over levels
      } // end loop over errors
    }

    // now compute norms

    pout() << "error, step " << nStep << ": L1, L2, Max, sum" << endl;
    for (int err = 0; err < numError; err++)
    {
      Interval errComps(err, err);
      Real L0, L1, L2, sum;

      if (verbose)
      {
        pout() << "compute error for component " << err << endl;
      }

      int lBase = 0;
      int normType = 0;
      Real normDx = computedDx;
      if (useUnitDomain)
        {
          normDx = 1.0/computedDomain.size(0);
        }
      L0 = computeNorm(error,
                       computedRefRatio,
                       normDx,
                       errComps,
                       normType,
                       lBase);

      normType = 1;
      L1 = computeNorm(error,
                       computedRefRatio,
                       normDx,
                       errComps,
                       normType,
                       lBase);

      normType = 2;
      L2 = computeNorm(error,
                       computedRefRatio,
                       normDx,
                       errComps,
                       normType,
                       lBase);
      
      sum = computeSum(error,
                       computedRefRatio,
                       normDx,
                       errComps,
                       lBase);


      pout() << errorNames[err] << ": "
             << L1 << ", "
             << L2 << ", "
             << L0 << ", "
             << sum;

      if (removeMean)
      {
        pout() << " (" << mean[err] << ")";
      }

      pout() << endl;
    } // end loop over errors

    if (doPlots)
    {
      if (verbose)
      {
        pout() << "begin writing hdf5 file..." << endl;
      }

      WriteAMRHierarchyHDF5(errorFile.str(),
                            computedGrids,
                            error,
                            errorNames,
                            computedDomain,
                            computedDx,
                            computedDt,
                            computedTime,
                            computedRefRatio,
                            computedNumLevels);

      if (verbose)
      {
        pout() << "done writing hdf5 file" << endl;
      }
    }

    // clean up memory
    for (int level = 0; level < exactNumLevels; level++)
    {
      if (exactSoln[level] != NULL)
      {
        delete exactSoln[level];
        exactSoln[level] = NULL;
      }
    }

    for (int level = 0; level < computedNumLevels; level++)
    {
      if (computedSoln[level] != NULL)
      {
        delete computedSoln[level];
        computedSoln[level] = NULL;
      }

      if (error[level] != NULL)
      {
        delete error[level];
        error[level] = NULL;
      }
    }
  } // end loop over timesteps

#ifdef CH_MPI
  dumpmemoryatexit();
  MPI_Finalize();
#endif
} // end main
// ---------------------------------------------------------------
void
AMRNavierStokes::computeAdvectionVelocities(LevelData<FluxBox>& a_advVel)
{
  if (s_verbosity >= 3)
    {
      pout() << "AMRNavierStokes::computeAdvectionVelocities: "
             << m_level << endl;
    }

  bool isViscous = (s_nu > 0.0);

  const DisjointBoxLayout& levelGrids = newVel().getBoxes();

  /// need to build grown grids to get be able to do all of
  /// tracing properly
  IntVect advect_grow(D_DECL(ADVECT_GROW, ADVECT_GROW, ADVECT_GROW));

  LevelData<FArrayBox> old_vel(levelGrids, SpaceDim, advect_grow);
  LevelData<FArrayBox> viscousSource(levelGrids, SpaceDim, advect_grow);
  LevelData<FArrayBox>* crseVelPtr = NULL;

  if (s_set_bogus_values)
    {
      setValLevel(old_vel, s_bogus_value);
      setValLevel(viscousSource, s_bogus_value);
    }

  // m_time contains the time at which the new state is centered
  Real old_time = m_time - m_dt;
  fillVelocity(old_vel, old_time);

  // set physical boundary conditions here
  // set physical boundary conditions on velocity

  if (isViscous)
    {
      LevelData<FArrayBox> viscousVel(levelGrids, SpaceDim, advect_grow);
      DataIterator dit = viscousVel.dataIterator();
      // rather than resetting BC's on old_vel, and then setting them
      // back, just copy old_vel to a temporary holder, and set
      // BCs on that one.
      for (dit.begin(); dit.ok(); ++dit)
        {
          viscousVel[dit].copy(old_vel[dit]);
        }
      VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC());
      velBC.applyBCs(viscousVel, levelGrids,
                     m_problem_domain, m_dx,
                     false); // inhomogeneous

      // if crse level exists, fill coarse velocity BC
      if (m_level > 0)
        {
          const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes();
          crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim);
          crseNSPtr()->fillVelocity(*crseVelPtr, old_time);
        }

      computeLapVel(viscousSource, viscousVel, crseVelPtr);

      for (dit.reset(); dit.ok(); ++dit)
        {
          viscousSource[dit].mult(s_nu);
        }
    }
  else
    {
      setValLevel(viscousSource, 0.0);
    }

  // tracing will use inviscid BC's
  {
    VelBCHolder velBC(m_physBCPtr->tracingVelFuncBC());
    velBC.applyBCs(old_vel, levelGrids,
                   m_problem_domain, m_dx,
                   false); // inhomogeneous
  }

  // call utility function to do tracing
  traceAdvectionVel(a_advVel, old_vel, viscousSource,
                    m_patchGodVelocity, old_time, m_dt);

  EdgeVelBCHolder edgeVelBC(m_physBCPtr->advectionVelFuncBC(isViscous));
  edgeVelBC.applyBCs(a_advVel, levelGrids,
                     m_problem_domain, m_dx,
                     false); // inhomogeneous

  // noel  levelMacProject is big guy
  // now MAC project
  m_projection.levelMacProject(a_advVel, old_time, m_dt);

  // finally, add volume discrepancy correction
  if (m_projection.etaLambda() > 0 && s_applyFreestreamCorrection)
    {
      LevelData<FluxBox>& grad_e_Lambda = m_projection.grad_eLambda();

      DataIterator dit = levelGrids.dataIterator();
      for (dit.reset(); dit.ok(); ++dit)
        {
          FluxBox& thisGrad_eLambda = grad_e_Lambda[dit];
          FluxBox& thisAdvVel = a_advVel[dit];
          for (int dir=0; dir<SpaceDim; dir++)
            {
              thisAdvVel[dir] += thisGrad_eLambda[dir];
            }
        }
    }

  edgeVelBC.applyBCs(a_advVel, levelGrids,
                     m_problem_domain, m_dx,
                     false); // inhomogeneous

  // clean up storage
  if (crseVelPtr != NULL)
    {
      delete crseVelPtr;
      crseVelPtr = NULL;
    }
}
Beispiel #21
0
// this function averages down the fine solution to the valid
// regions of the computed solution, then subtracts ir from
// the computed solution.  (error is exact-computed)
void computeAMRError(Vector<LevelData<FArrayBox>* >&       a_error,
                     const Vector<string>&                 a_errorVars,
                     const Vector<LevelData<FArrayBox>* >& a_computedSoln,
                     const Vector<string>&                 a_computedVars,
                     const Vector<DisjointBoxLayout>&      a_computedGrids,
                     const Real                            a_computedDx,
                     const Vector<int>&                    a_computedRefRatio,
                     const Vector<LevelData<FArrayBox>* >& a_exactSoln,
                     const Vector<string>&                 a_exactVars,
                     const Real                            a_exactDx,
                     Real                                  a_bogus_value,
                     bool                                  a_HOaverage,
                     bool                                  a_computeRelativeError)
{
  int numLevels = a_computedSoln.size();

  CH_assert(a_exactSoln.size() == 1);
  CH_assert(a_error.size() == numLevels);
  CH_assert(a_exactDx <= a_computedDx);
  CH_assert(a_computedRefRatio.size() >= numLevels - 1);

  if (a_exactDx == a_computedDx)
  {
    cerr << "Exact dx and computed dx are equal." << endl;
  }

  // check whether input file selects "sum all variables"
  bool sumAll = false;
  ParmParse pp;
  pp.query("sumAll",sumAll);
  
  // const DisjointBoxLayout& exactGrids = a_exactSoln[0]->getBoxes();

  Real dxLevel = a_computedDx;

  // do a bit of sleight-of-hand in the case where there are no
  // ghost cells in the exact solution -- allocate a temporary which
  // _has_ ghost cells, and do a copyTo
  LevelData<FArrayBox>* exactSolnPtr = NULL;
  bool allocatedMemory = false;
  if (a_exactSoln[0]->ghostVect() == IntVect::Zero)
    {
      exactSolnPtr = new LevelData<FArrayBox>(a_exactSoln[0]->getBoxes(),
                                              a_exactSoln[0]->nComp(),
                                              IntVect::Unit);
      a_exactSoln[0]->copyTo(*exactSolnPtr);

      allocatedMemory = true;
     }
   else
     {
       // if there are ghost cells, we can use the exactSoln as-is
       exactSolnPtr = a_exactSoln[0];
     }
   LevelData<FArrayBox>& exactSolnRef = *exactSolnPtr;

   // first need to set boundary conditions on exactsoln
   // this is for the Laplacian which is needed in AverageHO
   DataIterator ditFine = exactSolnRef.dataIterator();
   DomainGhostBC exactBC;
   Interval exactComps(0, a_exactVars.size() - 1);
   for (int dir = 0; dir < SpaceDim; dir++)
   {
     SideIterator sit;
     for (sit.reset(); sit.ok(); ++sit)
     {
       // use HO extrapolation at physical boundaries
       HOExtrapBC thisBC(dir, sit(), exactComps);
       exactBC.setBoxGhostBC(thisBC);
     }
   }

   for (ditFine.begin(); ditFine.ok(); ++ditFine)
   {
     FArrayBox& thisFineSoln = exactSolnRef[ditFine()];
     const Box& fineBox = exactSolnRef.getBoxes()[ditFine()];
     exactBC.applyInhomogeneousBCs(thisFineSoln, fineBox, a_exactDx);
   }
   exactSolnRef.exchange(exactComps);

   // outer loop is over levels
   for (int level = 0; level < numLevels; level++)
   {
     LevelData<FArrayBox>& thisLevelError = *a_error[level];
     LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level];

     // compute refinement ratio between solution at this level
     // and exact solution
     Real nRefTemp = (dxLevel / a_exactDx);
     int nRefExact = (int) nRefTemp;

     // this is to do rounding properly if necessary
     if (nRefTemp - nRefExact > 0.5) nRefExact += 1;

     // make sure it's not zero
     if (nRefExact == 0) nRefExact =1;

     const DisjointBoxLayout levelGrids = a_error[level]->getBoxes();
     const DisjointBoxLayout fineGrids = a_exactSoln[0]->getBoxes();
     DisjointBoxLayout coarsenedFineGrids;

     // petermc, 14 Jan 2014: Replace this because fineGrids might
     // not be coarsenable by nRefExact.
     // coarsen(coarsenedFineGrids, fineGrids, nRefExact);
     int nCoarsenExact = nRefExact;
     while ( !fineGrids.coarsenable(nCoarsenExact) && (nCoarsenExact > 0) )
       {
         // Divide nCoarsenExact by 2 until fineGrids is coarsenable by it.
         nCoarsenExact /= 2;
       }
     if (nCoarsenExact == 0)
       {
         nCoarsenExact = 1;
       }
     coarsen(coarsenedFineGrids, fineGrids, nCoarsenExact);

     int numExact = a_exactVars.size();
     LevelData<FArrayBox> averagedExact(coarsenedFineGrids, numExact);

     Box fineRefBox(IntVect::Zero, (nCoarsenExact-1)*IntVect::Unit);

     // average fine solution down to coarsened-fine level
     // loop over grids and do HO averaging down
     //DataIterator crseExactDit = coarsenedFineGrids.dataIterator();
     for (ditFine.reset(); ditFine.ok(); ++ditFine)
       {
         const Box fineBox = exactSolnRef.getBoxes()[ditFine()];
         FArrayBox fineTemp(fineBox, 1);
         Box coarsenedFineBox(fineBox);
         coarsenedFineBox.coarsen(nCoarsenExact);
         if (a_exactDx < a_computedDx)
           {
             // loop over components
             for (int comp = 0; comp < numExact; comp++)
               {
                 Box coarseBox(coarsenedFineGrids.get(ditFine()));
                 coarseBox &= coarsenedFineBox;
                 
                 if (!coarseBox.isEmpty())
                   {
                     // for now, this is a quick and dirty way to avoid
                     // stepping out of bounds if there are no ghost cells.
                     // LapBox will be the box over which we are
                     // able to compute the Laplacian.
                     Box LapBox = exactSolnRef[ditFine()].box();
                     LapBox.grow(-1);
                     LapBox &= fineBox;
                     fineTemp.setVal(0.0);
                     int doHO = 0;
                     if (a_HOaverage)
                       { 
                         doHO = 1;
                       }
                     
                     // average by default
                     int doAverage = 1;
                     
                     if (sumAll || sumVar(a_exactVars[comp]))
                       {
                         doAverage = 0;
                       }
                     
                     // average or sum, based on booleans
                     FORT_AVERAGEHO(CHF_FRA1(averagedExact[ditFine], comp),
                                    CHF_CONST_FRA1(exactSolnRef[ditFine], comp),
                                    CHF_FRA1(fineTemp, 0),
                                    CHF_BOX(coarseBox),
                                    CHF_BOX(LapBox),
                                    CHF_CONST_INT(nCoarsenExact),
                                    CHF_BOX(fineRefBox),
                                    CHF_INT(doHO),
                                    CHF_INT(doAverage));
                   } // end if crseBox not empty
               } // end loop over comps
           }
         else
           {
             // if cell sizes are the same, then copy
             averagedExact[ditFine].copy(exactSolnRef[ditFine]);
           }
         
       } // end loop over exact solution boxes
     
     int nRefineComputed = nRefExact / nCoarsenExact;
     LevelData<FArrayBox>* thisLevelComputedRefinedPtr = &thisLevelComputed;
     LevelData<FArrayBox>* thisLevelErrorRefinedPtr = &thisLevelError;
     if (nRefineComputed > 1)
       {
         // Do piecewise constant interpolation (replication) by nRefineComputed
         // on thisLevelComputed.
         DisjointBoxLayout levelRefinedGrids;
         refine(levelRefinedGrids, levelGrids, nRefineComputed);
         int nCompComputed = thisLevelComputed.nComp();
         IntVect ghostVectComputed = nRefineComputed * thisLevelComputed.ghostVect();
         thisLevelComputedRefinedPtr =
           new LevelData<FArrayBox>(levelRefinedGrids, nCompComputed, ghostVectComputed);
         ProblemDomain levelDomain = levelRefinedGrids.physDomain();
         FineInterp interpolator(levelRefinedGrids, nCompComputed, nRefineComputed,
                                 levelDomain);
         interpolator.pwcinterpToFine(*thisLevelComputedRefinedPtr, thisLevelComputed);

         int nCompErr = thisLevelError.nComp();
         IntVect ghostVectErr = nRefineComputed * thisLevelError.ghostVect();
         thisLevelErrorRefinedPtr =
           new LevelData<FArrayBox>(levelRefinedGrids, nCompErr, ghostVectErr);
       }

     // initialize error to 0
     // also initialize error to a bogus value
     DataIterator levelDit = thisLevelError.dataIterator();
     for (levelDit.begin(); levelDit.ok(); ++levelDit)
       {
         (*thisLevelErrorRefinedPtr)[levelDit].setVal(a_bogus_value);
       }

     Box refComputedBox(IntVect::Zero, (nRefineComputed-1)*IntVect::Unit);
     // loop over variables
     for (int nErr = 0; nErr < a_errorVars.size(); nErr++)
       {
         string thisErrVar = a_errorVars[nErr];
         bool done = false;

         // first loop over exact variables
         for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++)
           {
             string thisExactVar = a_exactVars[exactComp];
             // check if this exact variable is "the one"
             if ((thisExactVar == thisErrVar) || nonAverageVar(thisErrVar))
               {
                 int computedComp = 0;
                 // now loop over computed variables
                 while (!done && (computedComp < a_computedVars.size()))
                   {
                     if (a_computedVars[computedComp] == thisErrVar)
                       {
                         if (!nonAverageVar(thisErrVar))
                           {
                             // copy averaged exact solution -> error
                             // and then subtract computed solution
                             Interval exactInterval(exactComp, exactComp);
                             Interval errorInterval(nErr, nErr);
                             averagedExact.copyTo(exactInterval, *thisLevelErrorRefinedPtr,
                                                  errorInterval);
                           }
                         
                         DataIterator levelDit = thisLevelError.dataIterator();
                         for (levelDit.reset(); levelDit.ok(); ++levelDit)
                           {
                             FArrayBox& thisComputedRefined = (*thisLevelComputedRefinedPtr)[levelDit];
                             FArrayBox& thisErrorRefined = (*thisLevelErrorRefinedPtr)[levelDit];
                             if (a_computeRelativeError)
                               {
                                 // do this a little strangely -- relative
                                 // error is one - computed/exact.
                                 thisErrorRefined.divide(thisComputedRefined, computedComp, nErr, 1);
                                 thisErrorRefined.invert(-1.0, nErr, 1);
                                 thisErrorRefined.plus(1.0, nErr, 1);
                               }
                             else
                               {
                                 thisErrorRefined.minus(thisComputedRefined, computedComp, nErr, 1);
                               }
                             if (nRefineComputed > 1)
                               {
                                 FArrayBox& thisError = thisLevelError[levelDit];
                                 Box coarseBox = thisError.box();
                                 // Average thisErrorRefined to thisError.
                                 int doHO = 0;
                                 if (a_HOaverage)
                                   { 
                                     doHO = 1;
                                   }
                                 CH_assert(doHO == 0);

                                 // for now, this is a quick and dirty way to avoid
                                 // stepping out of bounds if there are no ghost cells.
                                 // LapBox will be the box over which we are
                                 // able to compute the Laplacian.
                                 Box LapBox = thisErrorRefined.box();
                                 LapBox.grow(-1);
                                 // LapBox &= fineBox;
                                 FArrayBox fineTemp(thisErrorRefined.box(), 1);
                                 fineTemp.setVal(0.0);
                                 
                                 // average by default
                                 int doAverage = 1;
                                 // average or sum, based on booleans
                                 FORT_AVERAGEHO(CHF_FRA1(thisError, nErr),
                                                CHF_CONST_FRA1(thisErrorRefined, nErr),
                                                CHF_FRA1(fineTemp, 0),
                                                CHF_BOX(coarseBox),
                                                CHF_BOX(LapBox),
                                                CHF_CONST_INT(nRefineComputed),
                                                CHF_BOX(refComputedBox),
                                                CHF_INT(doHO),
                                                CHF_INT(doAverage));
                                 
                               }
                           } // end loop over coarse grids
                         
                         done = true;
                       } // if computedVar is a_errorVar
                     
                     computedComp += 1;
                   } // end loop over a_computedVars
                 
                 if (!done)
                   {
                     pout() << "Variable " << thisErrVar  << " not found!!!" << endl;
                     MayDay::Error();
                   }
               } // end if this exactVar is correct
           } // end loop over exact variables
       } // end loop over errors
     
     if (nRefineComputed > 1)
       {
         delete thisLevelComputedRefinedPtr;
         delete thisLevelErrorRefinedPtr;
       }
     
     // now need to set covered regions to 0
     if (level < numLevels - 1)
       {
         // will need to loop over all boxes in finer level, not just
         // those on this processor...
         const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout();
         LayoutIterator fineLit = finerGrids.layoutIterator();
         
         // outer loop over this level's grids, since there are fewer of them
         DataIterator levelDit = thisLevelError.dataIterator();
         for (levelDit.reset(); levelDit.ok(); ++levelDit)
           {
             const Box& coarseBox = levelGrids[levelDit()];
             FArrayBox& thisError = thisLevelError[levelDit()];
             int numError = thisError.nComp();
             
             for (fineLit.reset(); fineLit.ok(); ++fineLit)
               {
                 Box fineBox(finerGrids[fineLit()]);
                 // now coarsen box down to this level
                 fineBox.coarsen(a_computedRefRatio[level]);
                 // if coarsened fine box intersects error's box, set
                 // overlap to 0
                 fineBox &= coarseBox;
                 if (!fineBox.isEmpty())
                   {
                     thisError.setVal(0.0, fineBox, 0, numError);
                   }
               } // end loop over finer-level grids
           } // end loop over this-level grids
         
         // this is a good place to update dx as well
         dxLevel = dxLevel / a_computedRefRatio[level];
       } // end if there is a finer level
     
     thisLevelError.exchange();
   } // end loop over levels
   
   // clean up if we need to
   if (allocatedMemory)
     {
       delete exactSolnPtr;
       exactSolnPtr = NULL;
     }
}