Exemplo n.º 1
0
 virtual void linearIn(EBCellFAB& arg,  void* buf, const Box& R,
                       const Interval& comps) const
 {
   EBCellFAB tmp;
   tmp.clone(arg);
   tmp.linearIn(buf, R, comps);
   arg.plus(tmp, R, comps.begin(), comps.begin(), comps.size());
 }
Exemplo n.º 2
0
void
EBMGAverage::averageFAB(EBCellFAB&       a_coar,
                        const Box&       a_boxCoar,
                        const EBCellFAB& a_refCoar,
                        const DataIndex& a_datInd,
                        const Interval&  a_variables) const
{
  CH_TIMERS("EBMGAverage::average");
  CH_TIMER("regular_average", t1);
  CH_TIMER("irregular_average", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_boxCoar;

  //do all cells as if they were regular
  Box refBox(IntVect::Zero, IntVect::Zero);
  refBox.refine(m_refRat);
  int numFinePerCoar = refBox.numPts();

  BaseFab<Real>& coarRegFAB =             a_coar.getSingleValuedFAB();
  const BaseFab<Real>& refCoarRegFAB = a_refCoar.getSingleValuedFAB();

  //set to zero because the fortran is a bit simpleminded
  //and does stuff additively
  a_coar.setVal(0.);
  CH_START(t1);
  for (int comp = a_variables.begin();  comp <= a_variables.end(); comp++)
    {
      FORT_REGAVERAGE(CHF_FRA1(coarRegFAB,comp),
                      CHF_CONST_FRA1(refCoarRegFAB,comp),
                      CHF_BOX(coarBox),
                      CHF_BOX(refBox),
                      CHF_CONST_INT(numFinePerCoar),
                      CHF_CONST_INT(m_refRat));
    }
  CH_STOP(t1);

  //this is really volume-weighted averaging even though it does
  //not look that way.

  //so (in the traditional sense) we want to preserve
  //rhoc * volc = sum(rhof * volf)
  //this translates to
  //volfrac_C * rhoC = (1/numFinePerCoar)(sum(volFrac_F * rhoF))
  //but the data input to this routine is all kappa weigthed so
  //the volumefractions have already been multiplied
  //which means
  // rhoC = (1/numFinePerCoar)(sum(rhoF))
  //which is what this does

  CH_START(t2);
  for (int comp = a_variables.begin();  comp <= a_variables.end(); comp++)
    {
      m_averageEBStencil[a_datInd]->apply(a_coar, a_refCoar, false, comp);
    }
  CH_STOP(t2);

}
Exemplo n.º 3
0
 void op(EBCellFAB& dest,
         const Box& RegionFrom,
         const Interval& Cdest,
         const Box& RegionTo,
         const EBCellFAB& src,
         const Interval& Csrc) const
 {
   dest.plus(src, RegionFrom, Csrc.begin(), Cdest.begin(), Cdest.size());
 }
Exemplo n.º 4
0
void
MappedLevelFluxRegister::incrementCoarse(const FArrayBox& a_coarseFlux,
                                   Real a_scale,
                                   const DataIndex& a_coarseDataIndex,
                                   const Interval& a_srcInterval,
                                   const Interval& a_dstInterval,
                                   int a_dir,
                                   Side::LoHiSide a_sd)
{
    CH_assert(isDefined());
    if (!(m_isDefined & FluxRegCoarseDefined)) return;
    CH_TIME("MappedLevelFluxRegister::incrementCoarse");

    const Vector<Box>& intersect =
        m_coarseLocations[a_dir + a_sd * CH_SPACEDIM][a_coarseDataIndex];

    FArrayBox& coarse = m_coarFlux[a_coarseDataIndex];

    // We cast away the constness in a_coarseFlux for the scope of this function. This
    // should be acceptable, since at the end of the day there is no change to it. -JNJ
    FArrayBox& coarseFlux = const_cast<FArrayBox&>(a_coarseFlux); // Muhahaha.
    coarseFlux.shiftHalf(a_dir, sign(a_sd));
    Real scale = -sign(a_sd) * a_scale;
    int s = a_srcInterval.begin();
    int d = a_dstInterval.begin();
    int size = a_srcInterval.size();

    for (int b = 0; b < intersect.size(); ++b) {
        const Box& box = intersect[b];
        Vector<Real> regbefore(coarse.nComp());
        Vector<Real> regafter(coarse.nComp());
        if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) {
            for (int ivar = 0; ivar < coarse.nComp(); ivar++) {
                regbefore[ivar] = coarse(ivdebnoeb, ivar);
            }
        }

        coarse.plus(coarseFlux, box, box, scale, s, d, size);

        if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) {
            for (int ivar = 0; ivar < coarse.nComp(); ivar++) {
                regafter[ivar] = coarse(ivdebnoeb, ivar);
            }

            pout() << "levelfluxreg::incrementCoar: scale = " << scale << ", ";
            for (int ivar = 0; ivar < coarse.nComp(); ivar++) {
                pout() << " input flux = " << coarseFlux(ivdebnoeb, ivar) << ", ";
                pout() << " reg before = " <<             regbefore[ivar] << ", ";
                pout() << " reg after  = " <<                regafter[ivar] << ", ";
            }
            pout() << endl;

        }
    }

    coarseFlux.shiftHalf(a_dir, - sign(a_sd));
}
Exemplo n.º 5
0
void
EBCoarsen::coarsenIrreg(EBCellFAB&       a_coar,
                        const EBCellFAB& a_fine,
                        const DataIndex& a_dit,
                        const Interval&  a_variables)
{
  const BaseIVFAB<VoFStencil>& stenBaseIVFAB = m_coarsenStencil[a_dit];
  VoFIterator& vofit = m_vofIt[a_dit];
  for (vofit.reset(); vofit.ok(); ++vofit)
    {
      const VolIndex&    vofCoar   = vofit();
      const VoFStencil&  stencil   = stenBaseIVFAB(vofCoar,0);

      for (int icomp=a_variables.begin();icomp ==a_variables.end();icomp++)
        {
          //coarsen irreg fine vofs to coarse
          //  compute the coarsening by using fine data
          Real phi = 0.0;
          for (int i = 0; i < stencil.size(); ++i )
            {
              const Real&      weight = stencil.weight(i);
              const VolIndex& vofFine = stencil.vof(i);
              const Real&        phiF = a_fine(vofFine,icomp);
              phi += weight * phiF;
            }

          //set the coarse value
          a_coar(vofCoar,icomp) = phi;
        }
    }
}
Exemplo n.º 6
0
// ---------------------------------------------------------
// 28 March 2003:
// This is called by other functions, and should not be called directly.
Real
integral(const BoxLayoutData<NodeFArrayBox>& a_layout,
         const Real a_dx,
         const Interval& a_interval,
         bool a_verbose)
{
  Real integralTotal = 0.;

  for (DataIterator it = a_layout.dataIterator(); it.ok(); ++it)
    {
      const NodeFArrayBox& thisNfab = a_layout[it()];
      const Box& thisBox(a_layout.box(it())); // CELL-centered
      Real thisNfabIntegral =
        integral(thisNfab, a_dx, thisBox,
                 a_interval.begin(), a_interval.size());
      integralTotal += thisNfabIntegral;
    }
# ifdef CH_MPI
  Real recv;
  // add up
  int result = MPI_Allreduce(&integralTotal, &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 integral");
    }
  integralTotal = recv;
# endif
  return integralTotal;
}
Exemplo n.º 7
0
// ---------------------------------------------------------
// 27 March 2003:
// This is called by other functions, and should not be called directly.
Real
maxnorm(const BoxLayoutData<NodeFArrayBox>& a_layout,
        const Interval& a_interval,
        bool a_verbose)
{
  Real normTotal = 0.;
  // a_p == 0:  max norm
  for (DataIterator it = a_layout.dataIterator(); it.ok(); ++it)
    {
      const Box& thisBox(a_layout.box(it())); // CELL-centered
      const NodeFArrayBox& thisNfab = a_layout[it()];
      Real thisNfabNorm =
        maxnorm(thisNfab, thisBox, a_interval.begin(), a_interval.size());
      if (a_verbose)
        cout << "maxnorm(" << thisBox << ") = " << thisNfabNorm << endl;
      normTotal = Max(normTotal, thisNfabNorm);
    }
# ifdef CH_MPI
  Real recv;
  int result = MPI_Allreduce(&normTotal, &recv, 1, MPI_CH_REAL,
                             MPI_MAX, Chombo_MPI::comm);
  if (result != MPI_SUCCESS)
    { //bark!!!
      MayDay::Error("sorry, but I had a communication error on maxnorm");
    }
  normTotal = recv;
# endif
  return normTotal;
}
Exemplo n.º 8
0
void
LevelFluxRegisterEdge::incrementFine(
                                     FArrayBox& a_fineFlux,
                                     Real a_scale,
                                     const DataIndex& a_fineDataIndex,
                                     const Interval& a_srcInterval,
                                     const Interval& a_dstInterval)
{
  CH_assert(isDefined());
  CH_assert(!a_fineFlux.box().isEmpty());
  CH_assert(a_srcInterval.size() == a_dstInterval.size());
  CH_assert(a_srcInterval.begin() >= 0);
  CH_assert(a_srcInterval.end() < a_fineFlux.nComp());
  CH_assert(a_dstInterval.begin() >= 0);
  CH_assert(a_dstInterval.end() < m_nComp);

  int edgeDir = -1;
  for (int sideDir = 0; sideDir<SpaceDim; sideDir++)
    {
      if (a_fineFlux.box().type(sideDir) == IndexType::CELL)
        {
          edgeDir = sideDir;
        }
    }
  CH_assert(edgeDir >= 0);
  CH_assert(edgeDir < SpaceDim);

  for (int faceDir=0; faceDir<SpaceDim; faceDir++)
    {
      if (faceDir != edgeDir)
        {

          SideIterator sit;
          for (sit.begin(); sit.ok(); ++sit)
            {
              incrementFine(a_fineFlux,
                            a_scale,
                            a_fineDataIndex,
                            a_srcInterval,
                            a_dstInterval,
                            faceDir,
                            sit());
            }
        }
    }
}
Exemplo n.º 9
0
// ---------------------------------------------------------
// 7 Dec 2005
Real
maxnorm(const BoxLayoutData<NodeFArrayBox>& a_layout,
        const LevelData<NodeFArrayBox>& a_mask,
        const ProblemDomain& a_domain,
        const Interval& a_interval,
        bool a_verbose)
{
  Real normTotal = 0.;
  // a_p == 0:  max norm
  int ncomp = a_interval.size();
  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 =
        maxnorm(dataMasked, thisBox, a_interval.begin(), a_interval.size());
      if (a_verbose)
        cout << "maxnorm(" << thisBox << ") = " << thisNfabNorm << endl;
       normTotal = Max(normTotal, thisNfabNorm);
    }
# ifdef CH_MPI
  Real recv;
  // add up (a_p is not 0)
  int result = MPI_Allreduce(&normTotal, &recv, 1, MPI_CH_REAL,
                             MPI_MAX, Chombo_MPI::comm);
  if (result != MPI_SUCCESS)
    { //bark!!!
      MayDay::Error("sorry, but I had a communication error on norm");
    }
  normTotal = recv;
# endif
  return normTotal;
}
Exemplo n.º 10
0
void
LevelFluxRegisterEdge::incrementCoarse(FArrayBox& a_coarseFlux,
                                       Real a_scale,
                                       const DataIndex& a_coarseDataIndex,
                                       const Interval& a_srcInterval,
                                       const Interval& a_dstInterval)
{
  CH_assert(isDefined());
  CH_assert(!a_coarseFlux.box().isEmpty());

  CH_assert(a_srcInterval.size() == a_dstInterval.size());
  CH_assert(a_srcInterval.begin() >= 0);
  CH_assert(a_srcInterval.end() < a_coarseFlux.nComp());
  CH_assert(a_dstInterval.begin() >= 0);
  CH_assert(a_dstInterval.end() < m_nComp);

  // get edge-centering of coarseFlux
  const Box& edgeBox = a_coarseFlux.box();
  int edgeDir = -1;
  for (int dir=0; dir<SpaceDim; dir++)
    {
      if (edgeBox.type(dir) == IndexType::CELL)
        {
          if (edgeDir == -1)
            {
              edgeDir = dir;
            }
          else
            {
              // already found a cell-centered direction (should only be
              // one for edge-centering)
              MayDay::Error("LevelFluxRegisterEdge::incrementCoarse -- e-field not edge-centered");
            }
        }
    } // end loop over directions
  CH_assert(edgeDir != -1);

  FArrayBox& thisCrseReg = m_regCoarse[a_coarseDataIndex][edgeDir];

  thisCrseReg.plus(a_coarseFlux, -a_scale, a_srcInterval.begin(),
                   a_dstInterval.begin(), a_srcInterval.size());

}
Exemplo n.º 11
0
// ---------------------------------------------------------
// 27 March 2003:
// This is called by other functions, and should not be called directly.
Real
norm(const BoxLayoutData<NodeFArrayBox>& a_layout,
     const Real a_dx,
     const int a_p,
     const Interval& a_interval,
     bool a_verbose)
{
  if (a_p == 0)
    return maxnorm(a_layout, a_interval, a_verbose);

  Real normTotal = 0.;

  for (DataIterator it = a_layout.dataIterator(); it.ok(); ++it)
    {
      const NodeFArrayBox& thisNfab = a_layout[it()];
      const Box& thisBox(a_layout.box(it())); // CELL-centered
      Real thisNfabNorm = norm(thisNfab, a_dx, thisBox, 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;
}
Exemplo n.º 12
0
void
EBFineToCoarRedist::
redistribute(LevelData<EBCellFAB>& a_coarSolution,
             const Interval& a_variables)
{
  CH_TIME("EBFineToCoarRedist::redistribute");
  Real nrefD = 1.0;
  for (int idir = 0; idir < SpaceDim; idir++)
    nrefD *= m_refRat;
  //copy the buffer to the coarse layout
  m_regsFine.copyTo(a_variables, m_regsRefCoar, a_variables);
  //redistribute the refined coarse registers to the coarse solution
  int ibox = 0;
  for (DataIterator dit = m_gridsCoar.dataIterator(); dit.ok(); ++dit)
    {
      const BaseIVFAB<Real>& regRefCoar = m_regsRefCoar[dit()];
      const IntVectSet& ivsRefCoar = m_setsRefCoar[dit()];
      const EBISBox& ebisBoxRefCoar = m_ebislRefCoar[dit()];
      const EBISBox& ebisBoxCoar = m_ebislCoar[dit()];
      const BaseIVFAB<VoFStencil>& stenFAB = m_stenRefCoar[dit()];

      EBCellFAB& solFAB = a_coarSolution[dit()];

      for (VoFIterator vofit(ivsRefCoar, ebisBoxRefCoar.getEBGraph());
          vofit.ok(); ++vofit)
        {
          const VolIndex& srcVoFFine = vofit();
          const VoFStencil& vofsten = stenFAB(srcVoFFine, 0);
          for (int isten = 0; isten < vofsten.size(); isten++)
            {
              const Real& weight = vofsten.weight(isten);
              const VolIndex& dstVoFFine = vofsten.vof(isten);
              VolIndex dstVoFCoar =
                m_ebislRefCoar.coarsen(dstVoFFine,m_refRat, dit());
              //by construction...
              CH_assert(m_gridsCoar.get(dit()).contains(dstVoFCoar.gridIndex()));
              Real dstVolFracFine = ebisBoxRefCoar.volFrac(dstVoFFine);
              Real dstVolFracCoar = ebisBoxCoar.volFrac(dstVoFCoar);
              Real denom = dstVolFracCoar*nrefD;
              for (int ivar = a_variables.begin();
                  ivar <= a_variables.end();  ivar++)
                {
                  Real dmFine = regRefCoar(srcVoFFine, ivar);
                  //ucoar+= massfine/volcoar, ie.
                  //ucoar+= (wcoar*dmCoar*volFracfine/volfraccoar)=massfine/volcoar
                  Real dUCoar = dmFine*weight*dstVolFracFine/denom;
                  solFAB(dstVoFCoar, ivar) += dUCoar;
                }
            }
        }
      ibox++;
    }
}
Exemplo n.º 13
0
void
EBCoarToFineRedist::
redistribute(LevelData<EBCellFAB>& a_fineSolution,
             const Interval& a_variables)
{
  CH_TIME("EBCoarToFineRedist::redistribute");
  //copy the buffer to the fine layout
  m_regsCoar.copyTo(a_variables, m_regsCedFine, a_variables);
  //redistribute the coarsened fine registers to the fine solution
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      const BaseIVFAB<Real>& regCoar = m_regsCedFine[dit()];
      const IntVectSet& ivsCoar = m_setsCedFine[dit()];
      const EBISBox& ebisBoxCoar = m_ebislCedFine[dit()];
      const BaseIVFAB<VoFStencil>& stenFAB = m_stenCedFine[dit()];

      EBCellFAB& solFAB = a_fineSolution[dit()];

      for (VoFIterator vofitCoar(ivsCoar, ebisBoxCoar.getEBGraph());
          vofitCoar.ok(); ++vofitCoar)
        {
          const VolIndex& srcVoFCoar = vofitCoar();
          const VoFStencil& vofsten = stenFAB(srcVoFCoar, 0);
          for (int isten = 0; isten < vofsten.size(); isten++)
            {
              const Real& weight = vofsten.weight(isten);
              const VolIndex& dstVoFCoar = vofsten.vof(isten);
              Vector<VolIndex> vofsFine =
                m_ebislCedFine.refine(dstVoFCoar,m_refRat, dit());

              for (int ivar = a_variables.begin();
                  ivar <= a_variables.end();  ivar++)
                {
                  Real dmCoar = regCoar(srcVoFCoar, ivar);
                  for (int ifine = 0; ifine < vofsFine.size(); ifine++)
                    {

                      const VolIndex& dstVoFFine = vofsFine[ifine];
                      //ufine += (wcoar*dmCoar) (piecewise constant density diff)
                      Real dUFine = dmCoar*weight;
                      solFAB(dstVoFFine, ivar) += dUFine;
                    }
                }
            }
        }
    }
}
Exemplo n.º 14
0
void
EBCoarseAverage::averageFAB(BaseIVFAB<Real>&       a_coar,
                            const BaseIVFAB<Real>& a_fine,
                            const DataIndex&       a_datInd,
                            const Interval&        a_variables) const
{
  CH_assert(isDefined());
  //recall that datInd is from the fine layout.
  const EBISBox& ebisBoxCoar = m_eblgCoFi.getEBISL()[a_datInd];
  const EBISBox& ebisBoxFine = m_eblgFine.getEBISL()[a_datInd];
  const IntVectSet& coarIrregIVS = a_coar.getIVS();
  const IntVectSet& fineIrregIVS = a_fine.getIVS();

  for (VoFIterator vofitCoar(coarIrregIVS, ebisBoxCoar.getEBGraph());
      vofitCoar.ok(); ++vofitCoar)
    {
      const VolIndex& coarVoF = vofitCoar();
      Vector<VolIndex> fineVoFs =
        m_eblgCoFi.getEBISL().refine(coarVoF, m_refRat, a_datInd);

      for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++)
        {
          int  numVoFs = 0;
          Real areaTot = 0;
          Real dataVal = 0;
          for (int ifine = 0; ifine < fineVoFs.size(); ifine++)
            {
              const VolIndex& fineVoF = fineVoFs[ifine];
              if (fineIrregIVS.contains(fineVoF.gridIndex()))
                {
                  Real bndryArea = ebisBoxFine.bndryArea(fineVoF);
                  if (bndryArea > 0)
                    {
                      areaTot += bndryArea;
                      numVoFs++;
                      dataVal += a_fine(fineVoF, ivar);
                    }
                }
            }
          if (numVoFs > 1)
            {
              dataVal /= Real(numVoFs);
            }
          a_coar(coarVoF, ivar) = dataVal;
        }
    }
}
Exemplo n.º 15
0
void BlockTab::findIntervals( void )
{
	vector< bool > visited( curBlockNum + 1, false );
	list< BasicBlock * > left;
	left.push_back( blockList[ 1 ] );        //entry node
	visited[ blockList[ 1 ] -> no ] = true;
	
	while ( !left.empty( ) ) { 
		Interval current;	
		current.Head( *left.begin( ) );
		bool added = true;
		while ( added == true ) {
		added = false;
		for ( list< BasicBlock * >::iterator i = left.begin( );
							i != left.end( ); ) {
//includes:check if first set includes the second set 

			if ( current.Head( ) == *i || 
				includes( current.begin( ), current.end( ), 
				( *i ) -> predecessors.begin( ), 
						(*i) -> predecessors.end())) {

				current.insert(*i);
				(*i) -> head = current.Head();
               			if ((*i) -> getTakenPtr() && 
					!visited[(*i) -> getTakenPtr() -> no]) {
					
				    visited[(*i) -> getTakenPtr() -> no] = true;
					left.push_back((*i) -> getTakenPtr());
					added = true;
				}
	       			if ((*i) -> getNTakenPtr() && 
					!visited[(*i)-> getNTakenPtr() -> no]) {
				   visited[(*i) -> getNTakenPtr() -> no] = true;
					left.push_back((*i) -> getNTakenPtr());
					added = true;
				}
				left.erase(i++); 
	       		}
			else
				i++;
		}
		}
		all.push_back(current);
	}
}
Exemplo n.º 16
0
void TimeInterpolatorRK4::interpolate(/// interpolated solution on this level coarsened
                                      LevelData<FArrayBox>&   a_U,
                                      /// time interpolation coefficient in range [0:1]
                                      const Real&             a_timeInterpCoeff,
                                      /// interval of a_U to fill in
                                      const Interval&         a_intvl)
{
  CH_assert(m_defined);
  CH_assert(m_gotFullTaylorPoly);
  CH_assert(a_U.nComp() == m_numStates);

  LevelData<FArrayBox> UComp;
  aliasLevelData(UComp, &a_U, a_intvl);

  // For i in 0:m_numCoeffs-1,
  // coeffFirst[i] is index of first component of m_taylorCoeffs
  // that corresponds to a coefficient of t^i.
  Vector<int> coeffFirst(m_numCoeffs);
  int intervalLength = a_intvl.size();
  for (int i = 0; i < m_numCoeffs; i++)
    {
      coeffFirst[i] = a_intvl.begin() + i * m_numStates;
    }

  DataIterator dit = UComp.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      FArrayBox& UFab = UComp[dit];
      const FArrayBox& taylorFab = m_taylorCoeffs[dit];

      // Evaluate a0 + a1*t + a2*t^2 + a3*t^3
      // as a0 + t * (a1 + t * (a2 + t * a3)).
      UFab.copy(taylorFab, coeffFirst[m_numCoeffs-1], 0, intervalLength);
      for (int ind = m_numCoeffs - 2; ind >=0; ind--)
        {
          UFab *= a_timeInterpCoeff;
          UFab.plus(taylorFab, coeffFirst[ind], 0, intervalLength);
        }
    }
  // dummy statement in order to get around gdb bug
  int dummy_unused = 0; dummy_unused = 0;
}
Exemplo n.º 17
0
void
EBMGInterp::pwcInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::interp");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_coarBox;

  for (int ivar = a_variables.begin();  ivar <= a_variables.end(); ivar++)
    {
      m_interpEBStencil[a_datInd]->cache(a_refCoar, ivar);

      //do all cells as if they were regular
      Box refBox(IntVect::Zero, IntVect::Zero);
      refBox.refine(m_refRat);

      const BaseFab<Real>& coarRegFAB =    a_coar.getSingleValuedFAB();
      BaseFab<Real>& refCoarRegFAB    = a_refCoar.getSingleValuedFAB();

      CH_START(t1);

      FORT_REGPROLONG(CHF_FRA1(refCoarRegFAB,ivar),
                      CHF_CONST_FRA1(coarRegFAB,ivar),
                      CHF_BOX(coarBox),
                      CHF_BOX(refBox),
                      CHF_CONST_INT(m_refRat));

      CH_STOP(t1);

      m_interpEBStencil[a_datInd]->uncache(a_refCoar, ivar);

      CH_START(t2);
      m_interpEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Exemplo n.º 18
0
void
EBCoarToFineRedist::increment(const BaseIVFAB<Real>& a_coarseMass,
                              const DataIndex& a_coarseDataIndex,
                              const Interval&  a_variables)
{
  BaseIVFAB<Real>& coarBuf =  m_regsCoar[a_coarseDataIndex];
  const EBISBox&   ebisBox = m_ebislCoar[a_coarseDataIndex];
  const IntVectSet& ivsLoc =  m_setsCoar[a_coarseDataIndex];
  CH_assert(a_coarseMass.getIVS().contains(ivsLoc));
  CH_assert(coarBuf.getIVS().contains(ivsLoc));
  for (VoFIterator vofit(ivsLoc, ebisBox.getEBGraph()); vofit.ok(); ++vofit)
    {
      const VolIndex& vof = vofit();
      for (int ivar = a_variables.begin();
          ivar <= a_variables.end();  ivar++)
        {
          coarBuf(vof, ivar) += a_coarseMass(vof, ivar);
        }
    }
}
Exemplo n.º 19
0
void
MappedLevelFluxRegister::incrementFine(const FArrayBox& a_fineFlux,
                                 Real a_scale,
                                 const DataIndex& a_fineDataIndex,
                                 const Interval& a_srcInterval,
                                 const Interval& a_dstInterval,
                                 int a_dir,
                                 Side::LoHiSide a_sd)
{
    CH_assert(isDefined());
    if (!(m_isDefined & FluxRegFineDefined)) return;
    CH_assert(a_srcInterval.size() == a_dstInterval.size());

    CH_TIME("MappedLevelFluxRegister::incrementFine");

    // We cast away the constness in a_coarseFlux for the scope of this function. This
    // should be acceptable, since at the end of the day there is no change to it. -JNJ
    FArrayBox& fineFlux = const_cast<FArrayBox&>(a_fineFlux); // Muhahaha.
    fineFlux.shiftHalf(a_dir, sign(a_sd));
    Real denom = 1.0;

    if (m_scaleFineFluxes) {
        denom = m_nRefine.product() / m_nRefine[a_dir];
    }

    Real scale = sign(a_sd) * a_scale / denom;

    FArrayBox& cFine = m_fineFlux[a_fineDataIndex];
    //  FArrayBox  cFineFortran(cFine.box(), cFine.nComp());
    //  cFineFortran.copy(cFine);

    Box clipBox = m_fineFlux.box(a_fineDataIndex);
    clipBox.refine(m_nRefine);
    Box fineBox;
    if (a_sd == Side::Lo) {
        fineBox = adjCellLo(clipBox, a_dir, 1);
        fineBox &= fineFlux.box();
    } else {
        fineBox = adjCellHi(clipBox, a_dir, 1);
        fineBox &= fineFlux.box();
    }
#if 0
    for (BoxIterator b(fineBox); b.ok(); ++b) {
        int s = a_srcInterval.begin();
        int d = a_dstInterval.begin();
        for (; s <= a_srcInterval.end(); ++s, ++d) {
            cFine(coarsen(b(), m_nRefine), d) += scale * fineFlux(b(), s);
        }
    }
#else
    // shifting to ensure fineBox is in the positive quadrant, so IntVect coarening
    // is just integer division.

    const Box& box = coarsen(fineBox, m_nRefine);
    Vector<Real> regbefore(cFine.nComp());
    Vector<Real>  regafter(cFine.nComp());
    if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) {
        for (int ivar = 0; ivar < cFine.nComp(); ivar++) {
            regbefore[ivar] = cFine(ivdebnoeb, ivar);
        }
    }


    const IntVect& iv = fineBox.smallEnd();
    IntVect civ = coarsen(iv, m_nRefine);
    int srcComp = a_srcInterval.begin();
    int destComp = a_dstInterval.begin();
    int ncomp = a_srcInterval.size();
    FORT_MAPPEDINCREMENTFINE(CHF_CONST_FRA_SHIFT(fineFlux, iv),
                             CHF_FRA_SHIFT(cFine, civ),
                             CHF_BOX_SHIFT(fineBox, iv),
                             CHF_CONST_INTVECT(m_nRefine),
                             CHF_CONST_REAL(scale),
                             CHF_CONST_INT(srcComp),
                             CHF_CONST_INT(destComp),
                             CHF_CONST_INT(ncomp));


    if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) {
        for (int ivar = 0; ivar < cFine.nComp(); ivar++) {
            regafter[ivar] = cFine(ivdebnoeb, ivar);
        }
    }

    if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) {

        pout() << "levelfluxreg::incrementFine: scale = " << scale << endl;
        Box refbox(ivdebnoeb, ivdebnoeb);
        refbox.refine(m_nRefine);
        refbox &= fineBox;
        if (!refbox.isEmpty()) {
            pout() << "fine fluxes = " << endl;
            for (BoxIterator  bit(refbox); bit.ok(); ++bit) {
                for (int ivar = 0; ivar < cFine.nComp(); ivar++) {
                    pout() << "iv = " << bit() << "(";
                    for (int ivar = 0; ivar < cFine.nComp(); ivar++) {
                        pout() << fineFlux(bit(), ivar);
                    }
                    pout() << ")" << endl;
                }
            }
        }

        for (int ivar = 0; ivar < cFine.nComp(); ivar++) {
            pout() << " reg before = " <<               regbefore[ivar] << ", ";
            pout() << " reg after  = " <<                regafter[ivar] << ", ";
        }
        pout() << endl;

    }


    //fineBox.shift(-shift);
    // now, check that cFineFortran and cFine are the same
    //fineBox.coarsen(m_nRefine);
    //    for (BoxIterator b(fineBox); b.ok(); ++b)
    //      {
    //        if (cFineFortran(b(),0) != cFine(b(),0))
    //          {
    //            MayDay::Error("Fortran doesn't match C++");
    //          }
    //      }
    // need to shift boxes back to where they were on entry.

    //  cFine.shift(-shift/m_nRefine);
#endif
    fineFlux.shiftHalf(a_dir, - sign(a_sd));
}
Exemplo n.º 20
0
void
EBCoarsen::coarsenFAB(EBCellFAB&       a_coar,
                      const EBCellFAB& a_fine,
                      const DataIndex& a_datInd,
                      const Interval&  a_variables)
{
  CH_assert(isDefined());
  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();

  //this is how much we need to grow a coarse box to get a fine box that
  // only has the fine iv's that are neighbors of the coarse iv
  const int fac = 1 - m_refRat/2;//NOTE: fac = 0 for refRat==2...
  Box refbox(IntVect::Zero,
             (m_refRat-1)*IntVect::Unit);
  refbox.grow(fac);

  Box coarBox = m_coarsenedFineGrids.get(a_datInd);

  Box fineBox = refine(coarBox, m_refRat);
  CH_assert(coarRegFAB.box().contains(coarBox));
  CH_assert(fineRegFAB.box().contains(fineBox));

  for (int ivar = a_variables.begin();
      ivar <= a_variables.end(); ivar++)
    {
      BaseFab<Real> laplFine(fineBox, 1);
      laplFine.setVal(0.);
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          Box loBox, hiBox, centerBox;
          int hasLo, hasHi;
          EBArith::loHiCenter(loBox, hasLo,
                              hiBox, hasHi,
                              centerBox, m_domainFine,
                              fineBox, idir, &((*m_cfivsPtr)[a_datInd]));

          FORT_H2LAPL1DADDITIVE(CHF_FRA1(laplFine, 0),
                                CHF_FRA1(fineRegFAB, ivar),
                                CHF_CONST_INT(idir),
                                CHF_BOX(loBox),
                                CHF_CONST_INT(hasLo),
                                CHF_BOX(hiBox),
                                CHF_CONST_INT(hasHi),
                                CHF_BOX(centerBox));
        }

      FORT_EBCOARSEN(CHF_FRA1(coarRegFAB,ivar),
                     CHF_CONST_FRA1(fineRegFAB,ivar),
                     CHF_CONST_FRA1(laplFine, 0),
                     CHF_BOX(coarBox),
                     CHF_CONST_INT(m_refRat),
                     CHF_BOX(refbox));
    }

  //overwrite irregular vofs and coarse vofs next to the cfivs if refRat<4,
  //  for these vofs we coarsen based on
  //  taylor expansions from fine vofs to the coarse cell center
  coarsenIrreg(a_coar,a_fine,a_datInd,a_variables);
}
int UniformGridLayoutData<Dim>::touchesAllocLocal(const OtherDomain &d, OutIter o, 
					          const ConstructTag &ctag) const 
{
  // If there are no internal guard cells, then this calculation is the
  // same as the normal touches calculation.
    
  if (!this->hasInternalGuards_m) return touches(d,o,ctag);
    
  int i, count = 0;

  // Make sure we have a valid touching domain.

  PAssert(this->initialized());
  PAssert(contains(this->domain_m, d));

  // Find the starting and ending grid positions, and store as an
  // Interval.

  Interval<Dim> box = Pooma::NoInit();
  for (i = 0; i < Dim; ++i) 
    {
      int a, b;
        
      // This part is unchanged from touches. What we're going to do
      // here is simply extend the range in each direction by one block
      // and then let the intersection calculation below sort out if
      // there is actually an intersection. Otherwise we'd have to do
      // comparisons on all blocks up here and then still do the
      // intersection on the remaining blocks below. On average, this
      // should be slightly faster I think.
        
      if (!this->hasExternalGuards_m)
	{
	  a = (d[i].min() - this->firsti_m[i]) / blocksizes_m[i];
	  b = (d[i].max() - this->firsti_m[i]) / blocksizes_m[i];
	}
      else
	{
	  // If we're in the lower guards, this will fall
	  // through to give zero.
            
	  a = b = 0;
	  int pos = d[i].min();
	  int last = this->innerdomain_m[i].last();
	  int del = pos - this->firsti_m[i];
            
	  if (del >= 0)
	    if (pos <= last)
	      a = del / blocksizes_m[i];
	    else
	      a = allDomain_m[i].last();
            
	  pos = d[i].max();
	  del = pos - this->firsti_m[i];
            
	  if (del >= 0)
	    if (pos <= last)
	      b = del / blocksizes_m[i];
	    else
	      b = allDomain_m[i].last();
	}
          
      // Now we check that we're not at the ends of the domain for the
      // brick of blocks, and extend the region accordingly.
        
      if (a > 0) --a;
      if (b < allDomain_m[i].last()) ++b;
        
      box[i] = Interval<1>(a, b);
    }

  // Figure the type of the domain resulting from the intersection.

  typedef typename 
    IntersectReturnType<Domain_t,OtherDomain>::Type_t OutDomain_t;
  OutDomain_t outDomain = Pooma::NoInit();

  // Generate the type of the node pushed on the output iterator.

  typedef Node<OutDomain_t,Domain_t> OutNode_t;

  // Iterate through the Interval grid positions.

  typename Interval<Dim>::const_iterator boxiter = box.begin();
    
  while (boxiter != box.end()) 
    {
      // Calculate the linear position of the current node.
        
      int indx = (*boxiter)[0].first();
      for (i = 1; i < Dim; ++i)
	indx += blockstride_m[i] * (*boxiter)[i].first();

      // Get that node, intersect the *allocated* domain with the 
      // requested one, and write the result out to the output iterator.
        
      PAssert(indx >= 0 && indx < this->local_m.size());
        
      outDomain = intersect(d, this->local_m[indx]->allocated());

      // We can no longer assert that outDomain is not empty since
      // we extended the search box without checking. Thus we now 
      // have an if tests around the output.
        
      if (!outDomain.empty())
	{
	  *o = touchesConstruct(outDomain,
				this->local_m[indx]->allocated(),
				this->local_m[indx]->affinity(),
				this->local_m[indx]->context(),
				this->local_m[indx]->globalID(),
				this->local_m[indx]->localID(),
				ctag);
	}

      // Increment output iterator, count, and grid iterator.

      ++o;
      ++count;
      ++boxiter;
    }

  // Return the number of non-empty domains we found.
      
  return count;
}
Exemplo n.º 22
0
void
LevelFluxRegisterEdge::incrementFine(
                                     FArrayBox& a_fineFlux,
                                     Real a_scale,
                                     const DataIndex& a_fineDataIndex,
                                     const Interval& a_srcInterval,
                                     const Interval& a_dstInterval,
                                     int a_dir,
                                     Side::LoHiSide a_sd)
{
  CH_assert(isDefined());
  CH_assert(!a_fineFlux.box().isEmpty());
  CH_assert(a_srcInterval.size() == a_dstInterval.size());
  CH_assert(a_srcInterval.begin() >= 0);
  CH_assert(a_srcInterval.end() < a_fineFlux.nComp());
  CH_assert(a_dstInterval.begin() >= 0);
  CH_assert(a_dstInterval.end() < m_nComp);

  CH_assert(a_dir >= 0);
  CH_assert(a_dir < SpaceDim);
  CH_assert((a_sd == Side::Lo)||(a_sd == Side::Hi));
  //
  //
  //denom is the number of fine faces per coarse face
  //this is intrinsically dimension-dependent
#if (CH_SPACEDIM == 2)
  Real denom = 1;
#elif (CH_SPACEDIM == 3)
  Real denom = m_nRefine;
#else
  // This code doesn't make any sense in 1D, and hasn't been implemented
  // for DIM > 3
  Real denom = -1.0;
  MayDay::Error("LevelFluxRegisterEdge -- bad SpaceDim");
#endif

  Real scale = a_scale/denom;

  // need which fluxbox face we're doing this for
  Box thisBox = a_fineFlux.box();
  int fluxComp = -1;
  for (int sideDir=0; sideDir<SpaceDim; sideDir++)
  {
    // we do nothing in the direction normal to face
    if (sideDir != a_dir)
    {
      if (thisBox.type(sideDir) == IndexType::CELL)
      {
        fluxComp = sideDir;
      }
    }
  }
  CH_assert (fluxComp >= 0);
  int regcomp = getRegComp(a_dir, fluxComp);

  FluxBox& thisReg = m_fabFine[index(a_dir, a_sd)][a_fineDataIndex];
  FArrayBox& reg = thisReg[regcomp];

  a_fineFlux.shiftHalf(a_dir, sign(a_sd));

  // this is a way of geting a face-centered domain
  // box which we can then use to intersect with things
  // to screen out cells outside the physical domain
  // (nothing is screened out in periodic case)
  Box shiftedValidDomain = m_domainCoarse.domainBox();
  shiftedValidDomain.grow(2);
  shiftedValidDomain &= m_domainCoarse;
  shiftedValidDomain.surroundingNodes(regcomp);

  BoxIterator regIt(reg.box() & shiftedValidDomain);
  for (regIt.begin(); regIt.ok(); ++regIt)
    {
      const IntVect& coarseIndex = regIt();
      // create a cell-centered box, then shift back to face-centered
      Box box(coarseIndex, coarseIndex);
      box.shiftHalf(regcomp,-1);
      // to avoid adding in edges which do not overlie coarse-grid
      // edges, will refine only in non-fluxComp directions to
      // determine box from which to grab fluxes.
      IntVect refineVect(m_nRefine*IntVect::Unit);
      //refineVect.setVal(fluxComp,1);
      box.refine(refineVect);
      if (a_sd == Side::Lo) box.growLo(a_dir,-(m_nRefine-1));
      else                 box.growHi(a_dir,-(m_nRefine-1));
      BoxIterator fluxIt(box);
      for (fluxIt.begin(); fluxIt.ok(); ++fluxIt)
        {
          int src = a_srcInterval.begin();
          int dest =  a_dstInterval.begin();
          for ( ; src <=a_srcInterval.end(); ++src,++dest)
            reg(coarseIndex, dest) += scale*a_fineFlux(fluxIt(), src);
        }
    }
  a_fineFlux.shiftHalf(a_dir, -sign(a_sd));
}
Exemplo n.º 23
0
void
EBFluxRegister::
incrementRedistRegister(EBCoarToCoarRedist& a_register,
                        const Interval&     a_variables,
                        const Real&         a_scale)
{
  if (m_hasEBCF)
    {
      LevelData<BaseIVFAB<Real> >& registerMass = a_register.m_regsCoar;
      LayoutData<IntVectSet>&      registerSets = a_register.m_setsCoar;
      //reflux into an empty LevelData<EBCellFAB>
      //Multiply this by (kappa)(1-kappa)
      //add result into register mass
      EBCellFactory ebcfCoar(m_eblgCoar.getEBISL());
      LevelData<EBCellFAB> increment(m_eblgCoar.getDBL(), m_nComp, m_saveCoar.ghostVect(), ebcfCoar);
      EBLevelDataOps::clone (increment, m_saveCoar);
      EBLevelDataOps::setVal(increment, 0.0);

      reflux(increment, a_variables, a_scale, true);

      for (DataIterator dit = m_eblgCoar.getDBL().dataIterator(); dit.ok(); ++dit)
        {
          for (int idir = 0; idir < SpaceDim; idir++)
            {
              for (SideIterator sit; sit.ok(); ++sit)
                {
                  int iindex = index(idir, sit());
                  Vector<IntVectSet> setsCoar = (m_setsCoar[iindex])[dit()];
                  for (int iset = 0; iset < setsCoar.size(); iset++)
                    {
                      const IntVectSet& setCoa  = registerSets[dit()];
                      const IntVectSet& setReg  = setsCoar[iset];
                      IntVectSet set = setCoa;
                      set &= setReg;
                      const EBISBox& ebisBox =m_eblgCoar.getEBISL()[dit()];
                      for (VoFIterator vofit(set, ebisBox.getEBGraph()); vofit.ok(); ++vofit)
                        {
                          const VolIndex& vof = vofit();

                          int ibleck = 0;
                          if ((vof.gridIndex() == ivdebugfr) && EBFastFR::s_verbose)
                            {
                              ibleck = 1;
                              pout()    << setprecision(10)
                                        << setiosflags(ios::showpoint)
                                        << setiosflags(ios::scientific);
                              pout() << "incrcotoco:" << endl;

                            }

                          for (int icomp = a_variables.begin(); icomp <= a_variables.end(); icomp++)
                            {
                              Real extraMass = increment[dit()](vofit(), icomp);
                              Real oldMass   =  registerMass[dit()](vofit(), icomp);
                              Real newMass   = oldMass + extraMass;
                              Real diff = extraMass;
                              if (ibleck == 1)
                                {
                                  pout() << "( " << oldMass << ", " << newMass << ", "  << diff << ")";
                                }

                              registerMass[dit()](vofit(), icomp) += extraMass;

                              //set increment to zero in case it gets
                              //hit twice (more than one direction or
                              //whatever
                              increment[dit()](vof, icomp) = 0;

                            } //loop over comps
                          if (ibleck == 1)
                            {
                              ibleck = 0;
                              pout() << endl;
                            }
                        }//loop over vofs in the set
                    }//loop over sets in this coarse box
                } //loop over sides
            } //loop over directions
        } //dataiterator loop
    } //You are using Bonetti's defense against me, uh?
} //I thought it fitting, considering the rocky terrain.
Exemplo n.º 24
0
void
EBFluxRegister::
incrementRedistRegister(EBCoarToFineRedist& a_register,
                        const Interval&     a_variables,
                        const Real&         a_scale)
{
  if (m_hasEBCF)
    {
      LevelData<BaseIVFAB<Real> >& registerMass = a_register.m_regsCoar;
      LayoutData<IntVectSet>&      registerSets = a_register.m_setsCoar;
      //reflux into an empty LevelData<EBCellFAB>
      //Multiply this by (kappa)(1-kappa)
      //add result into register mass
      EBCellFactory ebcfCoar(m_eblgCoar.getEBISL());
      LevelData<EBCellFAB> increment(m_eblgCoar.getDBL(), m_nComp, m_saveCoar.ghostVect(), ebcfCoar);
      EBLevelDataOps::clone(increment, m_saveCoar);
      EBLevelDataOps::setVal(increment, 0.0);
      reflux(increment, a_variables, a_scale, true);

      for (DataIterator dit = m_eblgCoar.getDBL().dataIterator(); dit.ok(); ++dit)
        {
          for (int idir = 0; idir < SpaceDim; idir++)
            {
              for (SideIterator sit; sit.ok(); ++sit)
                {
                  int iindex = index(idir, sit());
                  Vector<IntVectSet> setsCoar = (m_setsCoar[iindex])[dit()];
                  for (int iset = 0; iset < setsCoar.size(); iset++)
                    {
                      const IntVectSet& setCoa  = registerSets[dit()];
                      const IntVectSet& setReg  = setsCoar[iset];
                      IntVectSet set = setCoa;
                      set &= setReg;
                      const EBISBox& ebisBox =m_eblgCoar.getEBISL()[dit()];
                      for (VoFIterator vofit(set, ebisBox.getEBGraph()); vofit.ok(); ++vofit)
                        {
                          const VolIndex vof = vofit();
                          int ibleck = 0;
                          if ((vof.gridIndex() == ivdebugfr) && EBFastFR::s_verbose)
                            {
                              ibleck = 1;
                              pout()    << setprecision(10)
                                        << setiosflags(ios::showpoint)
                                        << setiosflags(ios::scientific);
                              pout() << "incrcotofi:" << endl;
                            }

                          for (int icomp = a_variables.begin(); icomp <= a_variables.end(); icomp++)
                            {
                              Real extraMass = increment[dit()](vofit(), icomp);

                              if ((ibleck == 1) && icomp == 0)
                                {
                                  //incrredist
                                  Real soluOld = registerMass[dit()](vof, icomp);
                                  Real soluNew = soluOld + extraMass;

                                  Real fluxDif = -extraMass;
                                  pout() << "(" << extraMass << ", " << soluOld << ", " << soluNew << ",  " << fluxDif << ")   " ;
                                }

                              registerMass[dit()](vof, icomp) += extraMass;

                              //set increment to zero in case it gets
                              //hit twice (more than one direction or
                              //whatever
                              increment[dit()](vof, icomp) = 0;

                            }
                          if (ibleck == 1)
                            {
                              pout() << endl;
                              ibleck = 0;
                            }

                        }
                    }
                }
            }
        }
    }
}
Exemplo n.º 25
0
void TimeInterpolatorRK4::intermediate(/// intermediate RK4 solution on this level coarsened
                                       LevelData<FArrayBox>&   a_U,
                                       /// time interpolation coefficient in range [0:1]
                                       const Real&             a_timeInterpCoeff,
                                       /// which RK4 stage:  0, 1, 2, 3
                                       const int&              a_stage,
                                       /// interval of a_U to fill in
                                       const Interval&         a_intvl) const
{
  CH_assert(m_defined);
  CH_assert(m_gotFullTaylorPoly);
  CH_assert(a_U.nComp() == m_numStates);
  CH_assert(a_stage >= 0);
  CH_assert(a_stage < 4);

  Real rinv = 1. / Real(m_refineCoarse);
  Vector<Real> intermCoeffs(4);
  // 0 is coefficient of m_taylorCoeffs[0] = Ucoarse(0)
  // 1 is coefficient of m_taylorCoeffs[1] =           K1
  // 2 is coefficient of m_taylorCoeffs[2] = 1/2 * (-3*K1 + 2*K2 + 2*K3 - K4)
  // 3 is coefficient of m_taylorCoeffs[3] = 2/3 * (   K1 -   K2 -   K3 + K4)
  Real diff12Coeffs;
  // coefficient of m_diff12               =              -   K2 +   K3
  switch (a_stage)
    {
    case 0:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = a_timeInterpCoeff;
      intermCoeffs[2] = a_timeInterpCoeff * a_timeInterpCoeff;
      intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff  * a_timeInterpCoeff;
      diff12Coeffs = 0.;
      break;
    case 1:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff;
      intermCoeffs[2] = a_timeInterpCoeff * (rinv + a_timeInterpCoeff);
      intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff);
      diff12Coeffs = 0.;
      break;
    case 2:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff;
      intermCoeffs[2] = 0.5*rinv*rinv + a_timeInterpCoeff * (rinv + a_timeInterpCoeff);
      intermCoeffs[3] = 0.375*rinv*rinv*rinv + a_timeInterpCoeff * (1.5*rinv*rinv + a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff));
      diff12Coeffs = -0.25 * rinv * rinv;
      break;
    case 3:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = rinv + a_timeInterpCoeff;
      intermCoeffs[2] = rinv*rinv + a_timeInterpCoeff * (2.*rinv + a_timeInterpCoeff);
      intermCoeffs[3] = 0.75*rinv*rinv*rinv + a_timeInterpCoeff * (3.*rinv*rinv + a_timeInterpCoeff * (3.*rinv + a_timeInterpCoeff));
      diff12Coeffs = 0.5 * rinv * rinv;
      break;
    default:
      MayDay::Error("TimeInterpolatorRK4::intermediate must have a_stage in range 0:3");
    }
  LevelData<FArrayBox> UComp;
  aliasLevelData(UComp, &a_U, a_intvl);

  // For i in 0:m_numCoeffs-1,
  // coeffFirst[i] is index of first component of m_taylorCoeffs
  // that corresponds to a coefficient of t^i.
  Vector<int> coeffFirst(m_numCoeffs);
  int intervalLength = a_intvl.size();
  for (int i = 0; i < m_numCoeffs; i++)
    {
      coeffFirst[i] = a_intvl.begin() + i * m_numStates;
    }

  DataIterator dit = UComp.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      FArrayBox& UFab = UComp[dit];
      const FArrayBox& taylorFab = m_taylorCoeffs[dit];

      // WAS:  Evaluate a0 + a1*t + a2*t^2 + a3*t^3
      // as a0 + t * (a1 + t * (a2 + t * a3)):
      // that is, set UFab to
      // a3, t*a3 + a2, t*(t*a3 + a2) + a1, t*(t*(t*a3 + a2) + a1) * a0.

      // NEW:  Evaluate a0*c0 + a1*c1 + a2*c2 + a3*c3,
      // where c0, c1, c2, c3 are scalars,
      // and c0 = intermCoeffs[0] = 1.
      UFab.copy(taylorFab, coeffFirst[0], 0, intervalLength);
      for (int ind = 1; ind < 4; ind++)
        {
          UFab.plus(taylorFab, intermCoeffs[ind],
                    coeffFirst[ind], 0, intervalLength);
        }
      const FArrayBox& diff12Fab = m_diff12[dit];
      UFab.plus(diff12Fab, diff12Coeffs, 0, 0, intervalLength);
    }
  // dummy statement in order to get around gdb bug
  int dummy_unused = 0; dummy_unused = 0;
}
//----------------------------------------------------------------------------
void
EBNormalizeByVolumeFraction::
operator()(LevelData<EBCellFAB>& a_Q,
           const Interval& a_compInterval) const
{
  CH_TIME("EBNormalizer::operator()");
   // Endpoints of the given interval.
   int begin = a_compInterval.begin(), end = a_compInterval.end(),
       length = a_compInterval.size();

   // Loop over the EBISBoxes within our grid. The EB data structures are
   // indexed in the same manner as the non-EB data structures, so we piggy-
   // back the former on the latter.
   a_Q.exchange();
   EBISLayout ebisLayout = m_levelGrid.getEBISL();
   DisjointBoxLayout layout = m_levelGrid.getDBL();
   for (DataIterator dit = layout.dataIterator(); dit.ok(); ++dit)
   {
      const EBISBox& box = ebisLayout[dit()];
      EBCellFAB& QFAB = a_Q[dit()];

      // Go over the irregular cells in this box.
      const IntVectSet& irregCells = box.getIrregIVS(layout[dit()]);

      // The average has to be computed from the uncorrected data from all
      // the neighbors, so we can't apply the corrections in place. For now,
      // we stash them in a map.
      map<VolIndex, vector<Real> > correctedValues;
      for (VoFIterator vit(irregCells, box.getEBGraph()); vit.ok(); ++vit)
        {
          Real kappajSum = 0.0;
          vector<Real> kappajQjSum(length, 0.0);

          // Get all of the indices of the VoFs within a monotone path
          // radius of 1.
          VolIndex vofi = vit();
          Vector<VolIndex> vofjs;
          EBArith::getAllVoFsInMonotonePath(vofjs, vofi, box, 1);

          // Accumulate the contributions from the neighboring cells.
          for (unsigned int j = 0; j < vofjs.size(); ++j)
            {
              VolIndex vofj = vofjs[j];

              Real kappaj = box.volFrac(vofj);
              for (int icomp = begin; icomp <= end; ++icomp)
                {
                  kappajQjSum[icomp] += QFAB(vofj, icomp);
                }

              // Add this volume fraction to the sum.
              kappajSum += kappaj;
            }

          if (kappajSum > 0.)
            {
              // Normalize the quantity and stow it.
              vector<Real> correctedValue(length);
              //         Real kappai = box.volFrac(vofi);  //unused dtg
              for (int icomp = begin; icomp <= end; ++icomp)
                {
                  // correctedValue[icomp - begin] =
                  //    QFAB(vofi, icomp) + (1.0 - kappai) * kappajQjSum[icomp] / kappajSum;
                  correctedValue[icomp - begin] = kappajQjSum[icomp] / kappajSum;
                }
              correctedValues[vofi] = correctedValue;
            }
        }

      // Apply the corrections.
      for (map<VolIndex, vector<Real> >::const_iterator
           cit = correctedValues.begin(); cit != correctedValues.end(); ++cit)
      {
         for (int icomp = begin; icomp <= end; ++icomp)
         {
            QFAB(cit->first, icomp) = cit->second[icomp-begin];
         }
      }
   }
}
Exemplo n.º 27
0
void
EBMGInterp::pwlInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::pwlinterpfab");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());


  //first interpolate piecewise constant.
  pwcInterpFAB(a_refCoar,
               a_coarBox,
               a_coar,
               a_datInd,
               a_variables);

  //then add in slope*distance.
  const Box& coarBox = a_coarBox;

  for (int ivar = a_variables.begin();  ivar <= a_variables.end(); ivar++)
    {
      //save stuff at irreg cells because fortran result will be garbage
      //and this is an incremental process
      m_linearEBStencil[a_datInd]->cache(a_refCoar, ivar);

      //do all cells as if they were regular
      Box refBox(IntVect::Zero, IntVect::Zero);
      refBox.refine(m_refRat);

      const BaseFab<Real>& coarRegFAB =    a_coar.getSingleValuedFAB();
      BaseFab<Real>& refCoarRegFAB    = a_refCoar.getSingleValuedFAB();

      CH_START(t1);

      Real dxf = 1.0/m_coarDomain.size(0);
      Real dxc = 2.0*dxf;

      //do every cell as regular
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          FORT_PROLONGADDSLOPE(CHF_FRA1(refCoarRegFAB,ivar),
                               CHF_CONST_FRA1(coarRegFAB,ivar),
                               CHF_BOX(coarBox),
                               CHF_BOX(refBox),
                               CHF_INT(idir),
                               CHF_REAL(dxf),
                               CHF_REAL(dxc),
                               CHF_CONST_INT(m_refRat));
        }
      CH_STOP(t1);

      //replace garbage fortran put in with original values (at irregular cells)
      m_linearEBStencil[a_datInd]->uncache(a_refCoar, ivar);

      CH_START(t2);
      //do what fortran should have done at irregular cells.
      m_linearEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
0
void TraceState(/// state at time t+dt/2 on edges in direction dir
                FArrayBox& a_stateHalf,
                /// cell-centered state at time t
                const FArrayBox& a_state,
                /// cell-centered velocity at time t
                const FArrayBox& a_cellVel,
                /// edge-centered advection velocity at time t+dt/2
                const FluxBox& a_advectionVel,
                /// cell-centered source
                const FArrayBox& a_source,
                /// Physical domain
                const ProblemDomain& a_dProblem,
                /// interior of grid patch
                const Box& a_gridBox,
                /// timeStep
                const Real a_dt,
                /// cell-spacing
                const Real a_dx,
                /// direction in which to perform tracing
                const int a_dir,
                /// which components to trace
                const Interval& a_srcComps,
                ///  where to put traced components in a_stateHalf,
                const Interval& a_destComps)

{

  int ncomp = a_srcComps.size();
  CH_assert (ncomp == a_destComps.size());
  int offset = a_destComps.begin() - a_srcComps.begin();
  Box edgeBox = a_gridBox;
  edgeBox.surroundingNodes(a_dir);

#ifdef SIMPLEUPWIND
  // simple cell-to-edge averaging may be causing us problems --
  // instead do simple upwinding

  for (int comp=a_srcComps.begin(); comp <= a_srcComps.end(); comp++)
  {
    int destcomp = comp+offset;
    FORT_UPWINDCELLTOEDGE(CHF_FRA1(a_stateHalf, destComp),
                          CHF_CONST_FRA1(a_state,comp),
                          CHF_CONST_FRA(a_advectionVel[a_dir]),
                          CHF_BOX(edgeBox),
                          CHF_CONST_INT(a_dir));
  }

#else


  // first compute slopes
  Box slopesBox = grow(a_gridBox,1);

  // these are debugging changes to sync with old code
#ifdef MATCH_OLDCODE
  FluxBox tempEdgeVel(slopesBox,1);
  tempEdgeVel.setVal(0.0);

  FArrayBox tempCellVel(slopesBox,SpaceDim);
  tempCellVel.setVal(0.0);


  CellToEdge(a_cellVel, tempEdgeVel);
  EdgeToCell(tempEdgeVel, tempCellVel);
  tempEdgeVel.clear(); // done with this, so reclaim memory
  EdgeToCell(a_advectionVel, tempCellVel);
#endif

  FArrayBox delS(slopesBox,1);
  FArrayBox sHat(slopesBox,1);
  FArrayBox sTilde(a_state.box(),1);

  for (int comp=a_srcComps.begin(); comp<=a_srcComps.end(); comp++)
  {
    int destComp = comp+offset;

#ifdef SET_BOGUS_VALUES
    delS.setVal(BOGUS_VALUE);
    sHat.setVal(BOGUS_VALUE);
    sTilde.setVal(BOGUS_VALUE);
#endif

    // compute van leer limited slopes in the normal direction
    // for now, always limit slopes, although might want to make
    // this a parameter
    int limitSlopes = 1;
    FORT_SLOPES(CHF_FRA1(delS,0),
                CHF_CONST_FRA1(a_state,comp),
                CHF_BOX(slopesBox),
                CHF_CONST_INT(a_dir),
                CHF_CONST_INT(limitSlopes));

    // this is a way to incorporate the minion correction --
    // stateTilde = state + (dt/2)*source
    sTilde.copy(a_source,comp,0,1);
    Real sourceFactor = a_dt/2.0;
    sTilde *= sourceFactor;
    sTilde.plus(a_state, comp,0,1);
    sHat.copy(sTilde,slopesBox);

    // now loop over directions, adding transverse components
    for (int localDir=0; localDir < SpaceDim; localDir++)
    {
      if (localDir != a_dir)
      {
        // add simple transverse components
        FORT_TRANSVERSE(CHF_FRA1(sHat,0),
                        CHF_CONST_FRA1(sTilde,0),
#ifdef MATCH_OLDCODE
                        CHF_CONST_FRA1(tempCellVel, localDir),
#else
                        CHF_CONST_FRA1(a_cellVel,localDir),
#endif
                        CHF_BOX(slopesBox),
                        CHF_CONST_REAL(a_dt),
                        CHF_CONST_REAL(a_dx),
                        CHF_CONST_INT(localDir));
                        //CHF_FRA1(temp,0));  // not used in function

      }
      else if (SpaceDim == 3)
      {
        // only add cross derivative transverse piece if we're in 3D
        // note that we need both components of velocity for this one
        FORT_TRANSVERSECROSS(CHF_FRA1(sHat,0),
                             CHF_CONST_FRA1(sTilde,0),
                             CHF_CONST_FRA(a_cellVel),
                             CHF_BOX(slopesBox),
                             CHF_CONST_REAL(a_dt),
                             CHF_CONST_REAL(a_dx),
                             CHF_CONST_INT(localDir));
      }
    } // end loop over directions

    // now compute left and right states and resolve the Reimann
    // problem to get single set of edge-centered values
    FORT_PREDICT(CHF_FRA1(a_stateHalf,destComp),
                 CHF_CONST_FRA1(sHat,0),
                 CHF_CONST_FRA1(delS,0),
                 CHF_CONST_FRA1(a_cellVel,a_dir),
                 CHF_CONST_FRA1(a_advectionVel[a_dir],0),
                 CHF_BOX(edgeBox),
                 CHF_CONST_REAL(a_dt),
                 CHF_CONST_REAL(a_dx),
                 CHF_CONST_INT(a_dir));
  } // end loop over components

#endif


}
Exemplo n.º 30
0
int main(int argc, char *argv[])
{
  Pooma::initialize(argc, argv);
  Pooma::Tester tester(argc, argv);

  // To declare a field, you first need to set up a layout. This requires
  // knowing the physical vertex-domain and the number of external guard
  // cell layers. Vertex domains contain enough points to hold all of the
  // rectilinear centerings that POOMA is likely to support for quite
  // awhile. Also, it means that the same layout can be used for all
  // fields, regardless of centering.
  
  Interval<2> physicalVertexDomain(14, 14);
  Loc<2> blocks(3, 3);
  GridLayout<2> layout1(physicalVertexDomain, blocks, GuardLayers<2>(1),
                        LayoutTag_t());
  GridLayout<2> layout0(physicalVertexDomain, blocks, GuardLayers<2>(0),
                        LayoutTag_t());

  Centering<2> cell = canonicalCentering<2>(CellType, Continuous, AllDim);
  Centering<2> vert = canonicalCentering<2>(VertexType, Continuous, AllDim);
  Centering<2> yedge = canonicalCentering<2>(EdgeType, Continuous, YDim);

  Vector<2> origin(0.0);
  Vector<2> spacings(1.0, 2.0);

  // First basic test verifies that we're assigning to the correct areas
  // on a brick.

  typedef
    Field<UniformRectilinearMesh<2>, double,
    MultiPatch<GridTag, BrickTag_t> > Field_t;
  Field_t b0(cell, layout1, origin, spacings);
  Field_t b1(vert, layout1, origin, spacings);
  Field_t b2(yedge, layout1, origin, spacings);
  Field_t b3(yedge, layout1, origin, spacings);
  Field_t bb0(cell, layout0, origin, spacings);
  Field_t bb1(vert, layout0, origin, spacings);
  Field_t bb2(yedge, layout0, origin, spacings);

  b0.all() = 0.0;
  b1.all() = 0.0;
  b2.all() = 0.0;

  b0 = 1.0;
  b1 = 1.0;
  b2 = 1.0;

  bb0.all() = 0.0;
  bb1.all() = 0.0;
  bb2.all() = 0.0;

  bb0 = 1.0;
  bb1 = 1.0;
  bb2 = 1.0;

  // SPMD code follows.
  // Note, SPMD code will work with the evaluator if you are careful
  // to perform assignment on all the relevant contexts.  The patchLocal
  // function creates a brick on the local context, so you can just perform
  // the assignment on that context.

  int i;

  for (i = 0; i < b0.numPatchesLocal(); ++i)
  {
    Patch<Field_t>::Type_t patch = b0.patchLocal(i);
    //    tester.out() << "context " << Pooma::context() << ":  assigning to patch " << i
    //              << " with domain " << patch.domain() << std::endl;
    patch += 1.5;
  }

  // This is safe to do since b1 and b2 are built with the same layout.
  for (i = 0; i < b1.numPatchesLocal(); ++i)
  {
    b1.patchLocal(i) += 1.5;
    b2.patchLocal(i) += 1.5;
  }

  for (i = 0; i < bb0.numPatchesLocal(); ++i)
  {
    Patch<Field_t>::Type_t patch = bb0.patchLocal(i);
    //    tester.out() << "context " << Pooma::context() << ":  assigning to patch on bb0 " << i
    //              << " with domain " << patch.domain() << std::endl;
    patch += 1.5;
  }

  // This is safe to do since bb1 and bb2 are built with the same layout.
  for (i = 0; i < bb1.numPatchesLocal(); ++i)
  {
    bb1.patchLocal(i) += 1.5;
    bb2.patchLocal(i) += 1.5;
  }

  tester.check("cell centered field is 2.5", all(b0 == 2.5));
  tester.check("vert centered field is 2.5", all(b1 == 2.5));
  tester.check("edge centered field is 2.5", all(b2 == 2.5));

  tester.out() << "b0.all():" << std::endl << b0.all() << std::endl;
  tester.out() << "b1.all():" << std::endl << b1.all() << std::endl;
  tester.out() << "b2.all():" << std::endl << b2.all() << std::endl;

  tester.check("didn't write into b0 boundary",
               sum(b0.all()) == 2.5 * b0.physicalDomain().size());
  tester.check("didn't write into b1 boundary",
               sum(b1.all()) == 2.5 * b1.physicalDomain().size());
  tester.check("didn't write into b2 boundary",
               sum(b2.all()) == 2.5 * b2.physicalDomain().size());

  tester.check("cell centered field is 2.5", all(bb0 == 2.5));
  tester.check("vert centered field is 2.5", all(bb1 == 2.5));
  tester.check("edge centered field is 2.5", all(bb2 == 2.5));

  tester.out() << "bb0:" << std::endl << bb0 << std::endl;
  tester.out() << "bb1:" << std::endl << bb1 << std::endl;
  tester.out() << "bb2:" << std::endl << bb2 << std::endl;

  typedef
    Field<UniformRectilinearMesh<2>, double,
    MultiPatch<GridTag, CompressibleBrickTag_t> > CField_t;
  CField_t c0(cell, layout1, origin, spacings);
  CField_t c1(vert, layout1, origin, spacings);
  CField_t c2(yedge, layout1, origin, spacings);
  CField_t cb0(cell, layout0, origin, spacings);
  CField_t cb1(vert, layout0, origin, spacings);
  CField_t cb2(yedge, layout0, origin, spacings);

  c0.all() = 0.0;
  c1.all() = 0.0;
  c2.all() = 0.0;

  c0 = 1.0;
  c1 = 1.0;
  c2 = 1.0;

  cb0.all() = 0.0;
  cb1.all() = 0.0;
  cb2.all() = 0.0;

  cb0 = 1.0;
  cb1 = 1.0;
  cb2 = 1.0;

  // SPMD code follows.
  // Note, SPMD code will work with the evaluator if you are careful
  // to perform assignment on all the relevant contexts.  The patchLocal
  // function creates a brick on the local context, so you can just perform
  // the assignment on that context.

  for (i = 0; i < c0.numPatchesLocal(); ++i)
  {
    Patch<CField_t>::Type_t patch = c0.patchLocal(i);
    tester.out() << "context " << Pooma::context() << ":  assigning to patch " << i
                 << " with domain " << patch.domain() << std::endl;
    patch += 1.5;
  }

  // This is safe to do since c1 and c2 are built with the same layout.
  for (i = 0; i < c1.numPatchesLocal(); ++i)
  {
    c1.patchLocal(i) += 1.5;
    c2.patchLocal(i) += 1.5;
  }

  for (i = 0; i < cb0.numPatchesLocal(); ++i)
  {
    Patch<CField_t>::Type_t patch = cb0.patchLocal(i);
    tester.out() << "context " << Pooma::context() << ":  assigning to patch on cb0 " << i
                 << " with domain " << patch.domain() << std::endl;
    patch += 1.5;
  }

  // This is safe to do since cb1 and cb2 are cuilt with the same layout.
  for (i = 0; i < cb1.numPatchesLocal(); ++i)
  {
    cb1.patchLocal(i) += 1.5;
    cb2.patchLocal(i) += 1.5;
  }

  tester.check("cell centered field is 2.5", all(c0 == 2.5));
  tester.check("vert centered field is 2.5", all(c1 == 2.5));
  tester.check("edge centered field is 2.5", all(c2 == 2.5));

  tester.out() << "c0.all():" << std::endl << c0.all() << std::endl;
  tester.out() << "c1.all():" << std::endl << c1.all() << std::endl;
  tester.out() << "c2.all():" << std::endl << c2.all() << std::endl;

  tester.check("didn't write into c0 boundary",
               sum(c0.all()) == 2.5 * c0.physicalDomain().size());
  tester.check("didn't write into c1 boundary",
               sum(c1.all()) == 2.5 * c1.physicalDomain().size());
  tester.check("didn't write into c2 boundary",
               sum(c2.all()) == 2.5 * c2.physicalDomain().size());

  tester.check("cell centered field is 2.5", all(cb0 == 2.5));
  tester.check("vert centered field is 2.5", all(cb1 == 2.5));
  tester.check("edge centered field is 2.5", all(cb2 == 2.5));

  tester.out() << "cb0:" << std::endl << cb0 << std::endl;
  tester.out() << "cb1:" << std::endl << cb1 << std::endl;
  tester.out() << "cb2:" << std::endl << cb2 << std::endl;

  //------------------------------------------------------------------
  // Scalar code example:
  //

  c0 = iota(c0.domain()).comp(0);
  c1 = iota(c1.domain()).comp(1);

  // Make sure all the data-parallel are done:

  Pooma::blockAndEvaluate();

  for (i = 0; i < c0.numPatchesLocal(); ++i)
  {
    Patch<CField_t>::Type_t local0 = c0.patchLocal(i);
    Patch<CField_t>::Type_t local1 = c1.patchLocal(i);
    Patch<CField_t>::Type_t local2 = c2.patchLocal(i);

    Interval<2> domain = local2.domain();  // physical domain of local y-edges

    // --------------------------------------------------------------
    // I believe the following is probably the most efficient approach
    // for sparse computations.  For data-parallel computations, the
    // evaluator will uncompress the patches and take brick views, which
    // provide the most efficient access.  If you are only performing
    // the computation on a small portion of cells, then the gains would
    // be outweighed by the act of copying the compressed value to all the
    // cells.
    //
    // The read function is used on the right hand side, because
    // operator() is forced to uncompress the patch just in case you want
    // to write to it.

    for(Interval<2>::iterator pos = domain.begin(); pos != domain.end(); ++pos)
    {
      Loc<2> edge = *pos;
      Loc<2> rightCell = edge;  // cell to right is same cell
      Loc<2> leftCell = edge - Loc<2>(1,0);
      Loc<2> topVert = edge + Loc<2>(0, 1);
      Loc<2> bottomVert = edge;

      local2(edge) =
        local0.read(rightCell) + local0.read(leftCell) +
        local1.read(topVert) + local1.read(bottomVert);
    }

    // This statement is optional, it tries to compress the patch after
    // we're done computing on it.  Since I used .read() for the local0 and 1
    // they remained in their original state. compress() can be expensive, so
    // it may not be worth trying unless space is really important.

    compress(local2);
  }

  tester.out() << "c0" << std::endl << c0 << std::endl;
  tester.out() << "c1" << std::endl << c1 << std::endl;
  tester.out() << "c2" << std::endl << c2 << std::endl;

  //------------------------------------------------------------------
  // Interfacing with a c-function:
  //
  // This example handles the corner cases, where the patches from a
  // cell centered field with no guard layers actually contain some
  // extra data.

  Pooma::blockAndEvaluate();

  for (i = 0; i < cb0.numPatchesLocal(); ++i)
  {
    Patch<CField_t>::Type_t local0 = cb0.patchLocal(i);
    Interval<2> physicalDomain = local0.physicalDomain();
    double *data;
    int size = physicalDomain.size();

    if (physicalDomain == local0.totalDomain())
    {
      uncompress(local0);
      data = &local0(physicalDomain.firsts());
      nonsense(data, size);
    }
    else
    {
      // In this case, the engine has extra storage even though the
      // field has the right domain. We copy it to a brick engine,
      // call the function and copy it back.  No uncompress is required,
      // since the assignment will copy the compressed value into the
      // brick.

      // arrayView is a work-around.  Array = Field doesn't work at
      // the moment.

      Array<2, double, Brick> brick(physicalDomain);
      Array<2, double, CompressibleBrick> arrayView(local0.engine());
      brick = arrayView(physicalDomain);
      Pooma::blockAndEvaluate();
      data = &brick(Loc<2>(0));
      nonsense(data, size);
      arrayView(physicalDomain) = brick;

      // Note that we don't need a blockAndEvaluate here, since an iterate has
      // been spawned to perform the copy.
    }

    // If you want to try compress(local0) here, you should do blockAndEvaluate
    // first in case the local0 = brick hasn't been executed yet.
  }
      
  tester.out() << "cb0.all()" << std::endl << cb0 << std::endl;

  b2 = positions(b2).comp(0);

  RefCountedBlockPtr<double> block = pack(b2);

  // The following functions give you access to the raw data from pack.
  // Note that the lifetime of the data is managed by the RefCountedBlockPtr,
  // so when "block" goes out of scope, the data goes away.  (i.e. Don't write
  // a function where you return block.beginPointer().)

  double *start = block.beginPointer();  // start of the data
  double *end = block.endPointer();      // one past the end
  int size = block.size();               // size of the data

  tester.out() << Pooma::context() << ":" << block.size() << std::endl;

  unpack(b3, block);

  tester.out() << "b2" << std::endl << b2 << std::endl;
  tester.out() << "b3" << std::endl << b3 << std::endl;

  tester.check("pack, unpack", all(b2 == b3));

  int ret = tester.results("LocalPatch");
  Pooma::finalize();
  return ret;
}