Utility Functions

This page provides the auxilliary functions we use to build a Poisson operator and run AMRSolver with the operator. The main function for this is given in mainamre.html . To start with, outputData takes the solution and the right-hand side and copies them both into one set of data with two variables. The data is then output into HDF5 format.



int outputData(const Vector* >& vectPhi,
               const Vector* >& vectRhs,
               const Vector& vectGrids,
               const Vector& vectDomain,
               const Vector& vectRatio,
               int numlevels,
               bool verbose)
{
  string phiName("phi");
  string rhsName("rhs");
  Vector vectName(2);
  vectName[0] = phiName;
  vectName[1] = rhsName;
  Box domain = vectDomain[0];
  Real dx = 1.;
  Real dt = 1.;
  Real time = 1.;
  Vector* > vectPhiAndRHS(numlevels, NULL);
  for(int ilev = 0; ilev < numlevels; ilev++)
    {
      vectPhiAndRHS[ilev] = new LevelData(vectGrids[ilev], 2);
      Interval phiInterval(0,0);
      Interval rhsInterval(1,1);
      vectPhi[ilev]->copyTo(vectPhi[ilev]->interval(), 
                            *vectPhiAndRHS[ilev],
                            phiInterval);
      vectRhs[ilev]->copyTo(vectRhs[ilev]->interval(), 
                            *vectPhiAndRHS[ilev],
                            rhsInterval);
    }
#ifdef HDF5
  string filename("poissonOut.hdf5");
  WriteAMRHierarchyHDF5(filename,                             
                        vectGrids, 
                        vectPhiAndRHS, 
                        vectName,                 
                        domain,                               
                        dx, dt, time,                                         
                        vectRatio,                           
                        numlevels);
#endif

  for(int ilev = 0; ilev < numlevels; ilev++)
    delete vectPhiAndRHS[ilev];

  return 0;
}

The function setRHS set the right-hand side on the hierarchy using parameters from the input file. It calls FORT_GETRHSPOIS which is a Chombo Fortran subroutine.

int setRHS(Vector* >& vectRhs,
           Vector&                  vectDx, 
           Vector&                  vectDomain, 
           int numlevels, bool verbose)
{
  Real rhono, rno;
  int iprob;
  iprob = 0;
  rhono = 0.75;
  rno = 0.5;
  for(int ilev = 0; ilev < numlevels; ilev++)
    {
      Real dxlev = vectDx[ilev];
      Box domlev =vectDomain[ilev];
      LevelData& rhsLD = *vectRhs[ilev];
      DataIterator dit =  rhsLD.dataIterator();
      for(dit.reset(); dit.ok(); ++dit)
        {
          FArrayBox& rhsFab = rhsLD[dit()];
          FORT_GETRHSPOIS(CHF_FRA(rhsFab),
                          CHF_BOX(rhsFab.box()),
                          CHF_BOX(domlev),
                          CHF_CONST_REAL(dxlev),
                          CHF_CONST_REAL(rhono),
                          CHF_CONST_REAL(rno),
                          CHF_CONST_INT(iprob));
        }
    }
  
  return 0;
}

The function setGrids sets the hierarchy of grids and domains using parameters from the input file. It does this by grabbing the parameters of the domain using ParmParse. After the domain is defined, a fixed set of tags is defined and using that we call MeshRefine to generate a set of boxes for each level. We then use LoadBalance to generate processor assignments for the boxes and using the boxes and procesor assignments, we generate the layouts.

int setGrids(Vector& vectGrids,
             Vector&               vectDomain, 
             Vector&              vectDx, 
             Vector&               vectRefRatio, 
             int& numlevels, bool verbose)
{
  int max_level;
  Real fillRat = 0.77;
  Vector ancells(SpaceDim);
  Vector  prob_loa(SpaceDim);
  Vector  prob_hia(SpaceDim);
  int maxboxsize = 32;

  ParmParse pp("main");
  pp.get("max_level", max_level);
  numlevels = max_level + 1;
  pp.query("fill_ratio", fillRat);
  pp.getarr("n_cell", ancells, 0, SpaceDim);
  pp.getarr("ref_ratio", vectRefRatio, 0, numlevels);
  pp.getarr("prob_lo",prob_loa,0,SpaceDim);
  pp.getarr("prob_hi",prob_hia,0,SpaceDim);
  pp.get("maxboxsize",maxboxsize);
  numlevels = max_level + 1;
  
  IntVect ivlo = IntVect::TheZeroVector();
  IntVect ivhi;
  for(int idir = 0; idir < SpaceDim; idir++)
    ivhi[idir] = ancells[idir] - 1;

  Box basedom = Box(ivlo, ivhi);

  vectGrids.resize(numlevels);
  vectDomain.resize(numlevels);
  vectDx.resize(numlevels);


  vectDx.resize(numlevels,0.0);
  vectDx[0] = (prob_hia[0]-prob_loa[0])/ancells[0];
  for(int ilev = 1; ilev < numlevels; ilev++)
    {
      assert(vectRefRatio[ilev-1] > 0);
      vectDx[ilev] = vectDx[ilev-1]/vectRefRatio[ilev-1];
    }

  vectDomain[0] = basedom;
  for(int ilev = 1;ilev < numlevels; ilev++)
    {
      vectDomain[ilev] = refine(vectDomain[ilev-1],vectRefRatio[ilev-1]);
    }
  
  int nc = ancells[0];
  int nmi = nc/2;//16
  int nqu = nc/4;//8
  int ntf = (nc*3)/4;  //24
  int nte = (nc*3)/8; //12
  int nfe = (nc*5)/8; //20
#if(CH_SPACEDIM ==2)
  Box boxf1(IntVect(0, nqu), IntVect(nmi-1,ntf-1));
  Box boxf2(IntVect(nmi,nte), IntVect(ntf-1,nfe-1));
  Box boxf3(IntVect(nqu,0  ), IntVect(nfe-1,nqu-1));
  Box boxf4(IntVect(nfe,nqu), IntVect(nc -1,nte-1));
#else
  Box boxf1(IntVect(0, nqu,nqu), IntVect(nmi-1,ntf-1,ntf-1));
  Box boxf2(IntVect(nmi,nte,nte), IntVect(ntf-1,nfe-1,nfe-1));
  Box boxf3(IntVect(nqu,0,0  ), IntVect(nfe-1,nqu-1,nqu-1));
  Box boxf4(IntVect(nfe,nqu,nqu), IntVect(nc -1,nte-1,nte-1));
#endif
  //comment out for kluge 
  /**/
  IntVectSet tags;
  tags |= boxf1;
  tags |= boxf2;
  tags |= boxf3;
  tags |= boxf4;
  Vector > vvboxNew(numlevels);
  Vector > vvboxOld(numlevels);
  for(int ilev = 0; ilev = 0)
    eekflag = meshRefine(vvboxNew, tags, baseLevel, topLevel, vectDomain, 
                         vvboxOld, vectRefRatio, fillRat, blockFactor,
                         buffersize, maxboxsize);
  else
    vvboxNew = vvboxOld;

  if(eekflag != 0)
    {
      cerr << "setGrids: meshRefine returned error code " << eekflag << endl;
      return(1);
    }

  Vector< Vector > procAssign;
  Real effRatio = 0.75;
  Vector< Vector > loads(numlevels);
  for(int ilev = 0; ilev 
The function setDomainBC sets domain boundary conditions using the input file.

int setDomainBC(DomainGhostBC& domghostbc, bool verbose)
{
  Vector ibclo;
  Vector ibchi;
  ParmParse pp("main");
  pp.getarr("bc_lo", ibclo, 0, SpaceDim);
  pp.getarr("bc_hi", ibchi, 0, SpaceDim);
  
  for(int idir = 0; idir < SpaceDim; idir++)
    {
      //lo bc
      {
        NeumannBC neumbc(idir, Side::Lo);
        DircheletBC dircbc(idir, Side::Lo);
        if(ibclo[idir] == 0) 
          {
            if(verbose&& procID()==0)
              cout << "dirchelet bcs in low direction for side " << idir << endl;
            domghostbc.setBoxGhostBC(dircbc);
          }
        else if(ibclo[idir] == 1)
          {
            if(verbose&& procID()==0)
              cout << "neumann bcs in low direction for side " << idir << endl;
            domghostbc.setBoxGhostBC(neumbc);
          }
        else
          {
            if(verbose)
              cerr << "setDomainBC:: bogus input bc_lo flag" << endl;
            return(1);
          }
      }
      //hi bc
      {
        NeumannBC neumbc(idir, Side::Hi);
        DircheletBC dircbc(idir, Side::Hi);
        if(ibchi[idir] == 0) 
          {
            if(verbose&& procID()==0)
              cout << "dirchelet bcs in high direction for side " << idir << endl;
            domghostbc.setBoxGhostBC(dircbc);
          }
        else if(ibchi[idir] == 1)
          {
            if(verbose&& procID()==0)
              cout << "neumann bcs in high direction for side " << idir << endl;
            domghostbc.setBoxGhostBC(neumbc);
          }
        else
          {
            if(verbose)
              cerr << "setDomainBC:: bogus input bc_hi flag" << endl;
            return(2);
          }
      }
    }
  return(0);
}