Exemple #1
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;
}
Exemple #2
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;
     }
}