trying to get bug fixes for DivergenceOp into weiqun/eb branch (AMReX-Codes/amrex#78)

getting some bug fixes over to development branch

diff --git a/Src/EBAMRElliptic/AMReX_AMREBMultiGrid.H b/Src/EBAMRElliptic/AMReX_AMREBMultiGrid.H
index cc806d29845..c2cc7c4b086 100644
--- a/Src/EBAMRElliptic/AMReX_AMREBMultiGrid.H
+++ b/Src/EBAMRElliptic/AMReX_AMREBMultiGrid.H
@@ -71,6 +71,22 @@ namespace amrex
                              AMRLevelOp<T>*  a_finerOp) = 0;

     ///
+    /**
+       a_residual = a_rhs - L^nf(a_phi, a_phiCoarse)
+       assume no finer AMR level
+    */
+    virtual void AMRResidualNF(T& a_residual, const T& a_phi, const T& a_phiCoarse,
+                               const T& a_rhs, bool a_homogeneousBC) = 0;
+
+    ///
+    /**
+       a_residual = a_rhs - L(a_phiFine, a_phi)
+       assume no coarser AMR level
+    */
+    virtual void AMRResidualNC(T& a_residual, const T& a_phiFine, const T& a_phi,
+                               const T& a_rhs, bool a_homogeneousBC,
+                               AMRLevelOp<T>* a_finerOp) = 0;
+    ///
     /**
        Apply the AMR operator, including coarse-fine matching
     */
@@ -165,7 +181,7 @@ namespace amrex
     virtual void define(const Box                    & a_coarseDomain,
                         AMRLevelOpFactory<T>         & a_factory,
                         shared_ptr<LinearSolver<T> > & a_bottomSolver,
-                        std::vector<int>             & a_refRat,
+                        const std::vector<int>       & a_refRat,
                         bool a_enableLevelSolves,
                         int a_numLevels);

@@ -322,9 +338,9 @@ namespace amrex
     std::vector<T*>  m_residual;
     std::vector<T*>  m_resC;

-    NoOpSolver<T>    m_nosolve;
+    shared_ptr<LinearSolver<T> >   m_nosolve;

-    LinearSolver<T>* m_bottomSolver;
+    shared_ptr<LinearSolver<T> > m_bottomSolver;

     std::vector<char> m_hasInitBeenCalled;

@@ -841,18 +857,6 @@ namespace amrex
         // clean const out
       }

-      // For solvers with accuracy higher than 2nd order
-      //  consistency between levels has to be explicitly enforced.
-      // Qinghai Zhang
-      if (m_op[0]->orderOfAccuracy()>2)
-      {
-        for (int ilev=l_max; ilev>l_base; ilev--)
-        {
-          m_op[ilev]->enforceCFConsistency(*a_phi[ilev-1], *a_phi[ilev]);
-        }
-      }
-      //------end enforcing consistency.
-
       //recompute residual
       rnorm = computeAMRResidual(uberResidual, a_phi, a_rhs, l_max, l_base, a_forceHomogeneous, true);
       iter++;
@@ -993,7 +997,7 @@ namespace amrex
         m_mg[ilev]->m_post = m_post;
         m_mg[ilev]->m_bottom = m_bottom;
       }
-      m_mg[ilev]->m_bottomSolver = &m_nosolve;
+      m_mg[ilev]->m_bottomSolver = m_nosolve;
     }

     m_mg[l_base]->setBottomSolver(m_bottomSolver);
@@ -1011,7 +1015,7 @@ namespace amrex
   void AMREBMultiGrid<T>::define(const Box& a_coarseDomain,
                                AMRLevelOpFactory<T>& a_factory,
                                shared_ptr<LinearSolver<T> > & a_bottomSolver,
-                               vector<int>      & a_refRat,
+                               const vector<int>      & a_refRat,
                                bool a_enableLevelSolves,
                                int a_maxAMRLevels)
   {
@@ -1022,7 +1026,7 @@ namespace amrex
     m_op.resize( a_maxAMRLevels, NULL);
     m_mg.resize( a_maxAMRLevels, NULL);
     m_hasInitBeenCalled.resize(a_maxAMRLevels, 'f');
-
+    m_nosolve  = shared_ptr<LinearSolver<T> >(static_cast<LinearSolver<T>*>(new NoOpSolver<T>));
     m_correction.resize( a_maxAMRLevels, NULL);
     m_residual.  resize( a_maxAMRLevels, NULL);
     m_resC.      resize( a_maxAMRLevels, NULL);
@@ -1043,7 +1047,7 @@ namespace amrex
       }
       if((i==0) || (refToCoarser > 2) || a_enableLevelSolves)
       {
-        m_mg[i]->define(a_factory, &m_nosolve, current, m_maxDepth, m_op[i]);
+        m_mg[i]->define(a_factory, m_nosolve, current, m_maxDepth);
       }

       // Only do this if it will be used (avoiding a reference to invalid
@@ -1065,7 +1069,7 @@ namespace amrex
     {
       for (int level = l_base; level <= l_max; level++)
       {
-        m_op[level]->assignLocal(*m_residual[level], *a_uberResidual[level]);
+        m_op[level]->assign(*m_residual[level], *a_uberResidual[level]);
         m_op[level]->setToZero(*m_correction[level]);
       }
     }
@@ -1099,11 +1103,10 @@ namespace amrex
                               true);

       // Compute the restriction of the residual to the coarser level resC.
-      m_op[ilev]->AMRRestrictS(*(m_resC[ilev]),
-                               *(m_residual[ilev]),
-                               *(m_correction[ilev]),
-                               *(m_correction[ilev-1]),
-                               *(a_uberCorrection[ilev]));
+      m_op[ilev]->AMRRestrict(*(m_resC[ilev]),
+                              *(m_residual[ilev]),
+                              *(m_correction[ilev]),
+                              *(m_correction[ilev-1]));

       // Overwrite residual on the valid region of the next coarser level
       //  with coarsened residual from this level
@@ -1119,8 +1122,7 @@ namespace amrex
       //================= Upsweep ======================
       //increment the correction with coarser version
       //m_op[ilev]->AMRProlong(*(m_correction[ilev]), *(m_correction[ilev-1]));
-      m_op[ilev]->AMRProlongS(*(m_correction[ilev]), *(m_correction[ilev-1]),
-                              *m_resC[ilev]);
+      m_op[ilev]->AMRProlong(*(m_correction[ilev]), *(m_correction[ilev-1]));
       //recompute residual
       m_op[ilev]->AMRUpdateResidual(*(m_residual[ilev]), *(m_correction[ilev]), *(m_correction[ilev-1]));

@@ -1132,7 +1134,7 @@ namespace amrex
       //correct the correction with the correction to the correction
       m_op[ilev]->incr(*(m_correction[ilev]), dCorr, 1.0);

-      m_op[ilev]->assignLocal(*(a_uberCorrection[ilev]), *(m_correction[ilev]));
+      m_op[ilev]->assign(*(a_uberCorrection[ilev]), *(m_correction[ilev]));
     }
   }

diff --git a/Src/EBAMRElliptic/AMReX_ConductivityBaseEBBC.H b/Src/EBAMRElliptic/AMReX_ConductivityBaseEBBC.H
index 3f572055f5c..a29ab9f11ab 100644
--- a/Src/EBAMRElliptic/AMReX_ConductivityBaseEBBC.H
+++ b/Src/EBAMRElliptic/AMReX_ConductivityBaseEBBC.H
@@ -152,7 +152,7 @@ namespace amrex
     ///
     /**
      */
-    virtual ConductivityBaseEBBC* new_object_ptr();
+    virtual ConductivityBaseEBBC* new_object_ptr() = 0;

     ///
     void
diff --git a/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.H b/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.H
index 191a6c87cdb..5137b25e6a8 100644
--- a/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.H
+++ b/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.H
@@ -25,13 +25,11 @@ namespace amrex
   {

   public:
-    DirichletConductivityDomainBC()
-      {
-      }
+    DirichletConductivityDomainBC();
+
+
+    virtual ~DirichletConductivityDomainBC();

-    virtual ~DirichletConductivityDomainBC()
-      {
-      }

     ///
     virtual void
@@ -59,13 +57,6 @@ namespace amrex
                    const Side::LoHiSide& a_side,
                    const bool&           a_useHomogeneous);

-    ///
-    virtual void
-    fillPhiGhost(FArrayBox&     a_phi,
-                 const Box&     a_valid,
-                 const Box&     a_domain,
-                 Real           a_dx,
-                 bool           a_homogeneous);
   private:
   };

diff --git a/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.cpp b/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.cpp
index af5d42c2ef3..979f1c62f25 100644
--- a/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.cpp
+++ b/Src/EBAMRElliptic/AMReX_DirichletConductivityDomainBC.cpp
@@ -14,13 +14,21 @@

 namespace amrex
 {
+/*****/
+  DirichletConductivityDomainBC::
+  DirichletConductivityDomainBC()
+  {
+  }
+/*****/
+  DirichletConductivityDomainBC::
+  ~DirichletConductivityDomainBC()
+  {
+  }
 /*****/
   void
   DirichletConductivityDomainBC::
   fillPhiGhost(FArrayBox&     a_phi,
                const Box&     a_valid,
-               const Box&     a_domain,
-               Real           a_dx,
                bool           a_homogeneous)
   {
     Box grownBox = a_valid;
@@ -34,14 +42,14 @@ namespace amrex
         choppedBox.grow(idir,-1);
         Box toRegion = EBArith::adjCellBox(choppedBox, idir, sit(), 1);

-        if(!a_domain.contains(toRegion))
+        if(!m_eblg.getDomain().contains(toRegion))
         {
           for (BoxIterator bit(toRegion); bit.ok(); ++bit)
           {
             const IntVect& iv = bit();
             //fake vof just to get the location
             VolIndex vof(iv, 0);
-            RealVect loc = EBArith::getVoFLocation(vof, a_dx, RealVect::Zero);
+            RealVect loc = EBArith::getVoFLocation(vof, m_dx, RealVect::Zero);
             int isign = sign(sit());
             IntVect ivneigh = iv - isign*BASISV(idir);
             Real value = bcvaluefunc(loc, idir, sit());
diff --git a/Src/EBAMRElliptic/AMReX_DirichletConductivityEBBC.H b/Src/EBAMRElliptic/AMReX_DirichletConductivityEBBC.H
index 4a6bed111a0..c249e2fd40b 100644
--- a/Src/EBAMRElliptic/AMReX_DirichletConductivityEBBC.H
+++ b/Src/EBAMRElliptic/AMReX_DirichletConductivityEBBC.H
@@ -113,7 +113,14 @@ namespace amrex
       }

     ///
-    virtual ~DirichletConductivityEBBCFactory();
+    virtual ~DirichletConductivityEBBCFactory()
+      {
+      }
+
+    void setOrder(int a_order)
+      {
+        m_order = a_order;
+      }

     ///
     virtual ConductivityBaseEBBC* new_object_ptr()
diff --git a/Src/EBAMRElliptic/AMReX_EBConductivityOp.H b/Src/EBAMRElliptic/AMReX_EBConductivityOp.H
index 84c46b9ce2c..9e639560719 100644
--- a/Src/EBAMRElliptic/AMReX_EBConductivityOp.H
+++ b/Src/EBAMRElliptic/AMReX_EBConductivityOp.H
@@ -346,8 +346,7 @@ namespace amrex
     virtual void AMRRestrict(FabArray<EBCellFAB>& a_resCoarse,
                              const FabArray<EBCellFAB>& a_residual,
                              const FabArray<EBCellFAB>& a_correction,
-                             const FabArray<EBCellFAB>& a_coarseCorrection,
-                             bool a_skip_res = false );
+                             const FabArray<EBCellFAB>& a_coarseCorrection);

     ///
     /** a_correction += I[2h->h](a_coarseCorrection) */
diff --git a/Src/EBAMRElliptic/AMReX_EBConductivityOp.cpp b/Src/EBAMRElliptic/AMReX_EBConductivityOp.cpp
index 681d6597750..013b50a0aa8 100644
--- a/Src/EBAMRElliptic/AMReX_EBConductivityOp.cpp
+++ b/Src/EBAMRElliptic/AMReX_EBConductivityOp.cpp
@@ -11,6 +11,7 @@

 #include "AMReX_EBConductivityOp.H"
 #include "AMReX_EBEllipticFort_F.H"
+#include "AMReX_IrregFABFactory.H"
 namespace amrex
 {

@@ -345,31 +346,29 @@ namespace amrex
     m_domainBC->setCoef(m_eblg,   fakeBeta ,  m_dx, RealVect::Zero,    m_bcoef);
     m_ebBC->setCoef(    m_eblg,   fakeBeta ,  m_dx, RealVect::Zero,    m_bcoef);

-    Real dxScale = 1.0/m_dx;
-
     LayoutData<BaseIVFAB<VoFStencil> >* fluxStencil = m_ebBC->getFluxStencil(0);
-
-    m_vofIterIrreg.define(     m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache
-    m_vofIterMulti.define(     m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache
-    m_alphaDiagWeight.define(  m_eblg.getDBL(), m_eblg.getDM());
-    m_betaDiagWeight.define(   m_eblg.getDBL(), m_eblg.getDM());
+    IrregFABFactory irregFact(m_eblg.getEBISL());
+    m_vofIterIrreg.define(    m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache
+    m_vofIterMulti.define(    m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache
+    m_alphaDiagWeight.define( m_eblg.getDBL(), m_eblg.getDM(), 1, 0, MFInfo(), irregFact);
+    m_betaDiagWeight.define(  m_eblg.getDBL(), m_eblg.getDM(), 1, 0, MFInfo(), irregFact);
     Box sideBoxLo[SpaceDim];
     Box sideBoxHi[SpaceDim];
     for (int idir = 0; idir < SpaceDim; idir++)
     {
-      Box domainBox = m_eblg.getDomain().domainBox();
+      Box domainBox = m_eblg.getDomain();
       sideBoxLo[idir] = adjCellLo(domainBox, idir, 1);
       sideBoxLo[idir].shift(idir,  1);
       sideBoxHi[idir] = adjCellHi(domainBox, idir, 1);
       sideBoxHi[idir].shift(idir, -1);
-      m_vofIterDomLo[idir].define( m_eblg.getDBL()); // vofiterator cache for domain lo
-      m_vofIterDomHi[idir].define( m_eblg.getDBL()); // vofiterator cache for domain hi
+      m_vofIterDomLo[idir].define( m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache for domain lo
+      m_vofIterDomHi[idir].define( m_eblg.getDBL(), m_eblg.getDM()); // vofiterator cache for domain hi
     }
     EBArith::getMultiColors(m_colors);

     EBCellFactory fact(m_eblg.getEBISL());
-    FabArray<EBCellFAB> phiProxy(m_eblg.getDBL(), , m_eblg.getDM(), SpaceDim, m_ghostPhi, MFInfo(), fact);
-    FabArray<EBCellFAB> rhsProxy(m_eblg.getDBL(), , m_eblg.getDM(), SpaceDim, m_ghostRHS, MFInfo(), fact);
+    FabArray<EBCellFAB> phiProxy(m_eblg.getDBL(), m_eblg.getDM(), SpaceDim, m_ghostPhi, MFInfo(), fact);
+    FabArray<EBCellFAB> rhsProxy(m_eblg.getDBL(), m_eblg.getDM(), SpaceDim, m_ghostRHS, MFInfo(), fact);

     for(MFIter mfi(m_eblg.getDBL(), m_eblg.getDM()); mfi.isValid(); ++mfi)
     {
@@ -381,8 +380,6 @@ namespace amrex
       IntVectSet multiIVS = ebisBox.getMultiCells(curBox);

       //cache the vofIterators
-      m_alphaDiagWeight[mfi].define(irregIVS,ebgraph, 1);
-      m_betaDiagWeight [mfi].define(irregIVS,ebgraph, 1);
       m_vofIterIrreg   [mfi].define(irregIVS,ebgraph);
       m_vofIterMulti   [mfi].define(multiIVS,ebgraph);

@@ -397,7 +394,7 @@ namespace amrex
       }

       VoFIterator &  vofit = m_vofIterIrreg[mfi];
-      const vector<VolIndex>& vofvec = vofit.getvector();
+      const vector<VolIndex>& vofvec = vofit.getVector();
       vector<VoFStencil> stenvec(vofvec.size());

       // cast from VolIndex to BaseIndex
@@ -407,7 +404,7 @@ namespace amrex

       for(int ivec = 0; ivec < vofvec.size(); ivec++)
       {
-        const VolIndex& vof = vofvec[ivec];
+        VolIndex  & vof     = (VolIndex &)(vofvec[ivec]);
         VoFStencil& vofsten = stenvec[ivec];

         //bcoef is included here in the flux consistent
@@ -483,7 +480,7 @@ namespace amrex
     if (m_hasFine)
     {
       int ncomp = 1;
-      m_fastFR.define(m_eblgFine, m_eblg, m_refToFine, ncomp, s_forceNoEBCF);
+      m_fastFR.define(m_eblgFine, m_eblg, m_refToFine, ncomp);
     }

   }
@@ -511,7 +508,7 @@ namespace amrex
           const FabArray<EBCellFAB>& a_rhs)
   {
     BL_PROFILE("EBConductivityOp::preCond");
-    EBLevelDataOps::assign(a_lhs, a_rhs);
+    EBLevelDataOps::assign(a_lhs, a_rhs, 1.0);
     EBLevelDataOps::scale(a_lhs, m_relCoef);

     relax(a_lhs, a_rhs, 40);
@@ -530,12 +527,11 @@ namespace amrex
     {
       if(a_homogeneousCFBC)
       {
-        m_cfInterp->coarseFineInterpH(phi,  0, 0, 1);
+        m_cfInterp.coarseFineInterpH(phi,  0, 0, 1);
       }
       else
       {
-        m_cfInterp->coarseFineInterp(phi, *a_phiCoar,  0, 0, 1);
-        //          dumpEBLevelGhost(&phi);
+        m_cfInterp.coarseFineInterp(phi, *a_phiCoar,  0, 0, 1);
       }
     }
     applyOp(a_lhs, a_phi, a_homogeneousPhysBC);
@@ -551,14 +547,13 @@ namespace amrex
     FabArray<EBCellFAB>&  phi = (FabArray<EBCellFAB>&) a_phi;
     {
       BL_PROFILE("ghostcell fills");
-      fillPhiGhost(a_phi, a_homogeneous);
+      fillPhiGhost(phi, a_homogeneous);
     }

     {
       BL_PROFILE("applying op without bcs");
-      for(MFIter mfi(m_eblg.getDBL(); mfi.getDM()); mfi.isValid(); ++mfi)
+      for(MFIter mfi(m_eblg.getDBL(), m_eblg.getDM()); mfi.isValid(); ++mfi)
       {
-
         applyOpRegular(  a_lhs[mfi], a_phi[mfi], a_homogeneous, mfi);
         applyOpIrregular(a_lhs[mfi], a_phi[mfi], a_homogeneous, mfi);
       }
@@ -570,7 +565,7 @@ namespace amrex
   fillPhiGhost(const FabArray<EBCellFAB>& a_phi, bool a_homog) const
   {
     BL_PROFILE("nwoebco::fillghostLD");
-    for(MFIter mfi(m_eblg.getDBL(); mfi.getDM()); mfi.isValid(); ++mfi)
+    for(MFIter mfi(m_eblg.getDBL(), m_eblg.getDM()); mfi.isValid(); ++mfi)
     {
       fillPhiGhost(a_phi[mfi], mfi, a_homog);
     }
@@ -587,7 +582,7 @@ namespace amrex
     EBCellFAB& phi = (EBCellFAB&) a_phi;
     ConductivityBaseDomainBC* condbc = dynamic_cast<ConductivityBaseDomainBC*>(&(*m_domainBC));
     Box grid = m_eblg.getDBL()[a_datInd];
-    Box domBox = m_eblg.getDomain().domainBox();
+    Box domBox = m_eblg.getDomain();
     if(condbc == NULL)
     {
       amrex::Error("dynamic cast failed");
@@ -595,7 +590,7 @@ namespace amrex
     if (!m_turnOffBCs)
     {
       FArrayBox& fab = phi.getFArrayBox();
-      condbc->fillPhiGhost(fab, grid, domBox, m_dx, a_homog);
+      condbc->fillPhiGhost(fab, grid, a_homog);
     }
     else
     {
@@ -663,9 +658,8 @@ namespace amrex
     if (!a_homogeneous)
     {
       const Real factor = m_beta/m_dx;
-      m_ebBC->applyEBFlux(a_lhs, a_phi, m_vofIterIrreg[a_datInd], (*m_eblg.getCFIVS()),
-                          a_datInd, RealVect::Zero, vectDx, factor,
-                          a_homogeneous, 0.0);
+      m_ebBC->applyEBFlux(a_lhs, a_phi, m_vofIterIrreg[a_datInd].getVector(),
+                          a_datInd, factor, a_homogeneous);
     }

     for (int idir = 0; idir < SpaceDim; idir++)
@@ -675,9 +669,8 @@ namespace amrex
       {
         Real flux;
         const VolIndex& vof = m_vofIterDomLo[idir][a_datInd]();
-        m_domainBC->getFaceFlux(flux,vof,comp,a_phi,
-                                RealVect::Zero,vectDx,idir,Side::Lo, a_datInd, 0.0,
-                                a_homogeneous);
+        m_domainBC->getFaceFlux(flux,vof, a_datInd, a_phi,
+                                idir,Side::Lo, a_homogeneous);

         //area gets multiplied in by bc operator
         a_lhs(vof,comp) -= flux*m_beta/m_dx;
@@ -686,9 +679,8 @@ namespace amrex
       {
         Real flux;
         const VolIndex& vof = m_vofIterDomHi[idir][a_datInd]();
-        m_domainBC->getFaceFlux(flux,vof,comp,a_phi,
-                                RealVect::Zero,vectDx,idir,Side::Hi,a_datInd,0.0,
-                                a_homogeneous);
+        m_domainBC->getFaceFlux(flux,vof, a_datInd, a_phi,
+                                idir,Side::Hi, a_homogeneous);

         //area gets multiplied in by bc operator
         a_lhs(vof,comp) += flux*m_beta/m_dx;
@@ -724,7 +716,7 @@ namespace amrex
     EBLevelGrid eblgCoFi;
     coarsen(eblgCoFi, m_eblg, a_refRat);

-    EBCellFactory ebcellfactCoFi(elgCoFi.getEBISL());
+    EBCellFactory ebcellfactCoFi(eblgCoFi.getEBISL());
     a_lhs.define(eblgCoFi.getDBL(), eblgCoFi.getDM(), ncomp, ghost, MFInfo(), ebcellfactCoFi);
   }
   //-------------------------------------------------------------------------------
@@ -734,7 +726,7 @@ namespace amrex
          const FabArray<EBCellFAB>& a_rhs)
   {
     BL_PROFILE("ebco::assign");
-    EBLevelDataOps::assign(a_lhs,a_rhs);
+    EBLevelDataOps::assign(a_lhs,a_rhs, 1.0);
   }
   //-------------------------------------------------------------------------------
   Real
@@ -791,7 +783,6 @@ namespace amrex

     maxNorm = localMaxNorm(a_rhs);

-    CH_START(t1);
 #ifdef BL_USE_MPI
     Real tmp = 1.;
     int result = MPI_Allreduce(&maxNorm, &tmp, 1, MPI_CH_REAL,
@@ -804,7 +795,6 @@ namespace amrex
 #endif
     //  Real volume=1.;
     //  EBLevelDataOps::gatherBroadCast(maxNorm, volume, 0);
-    CH_STOP(t1);

     return maxNorm;
   }
@@ -824,7 +814,7 @@ namespace amrex
   setToZero(FabArray<EBCellFAB>& a_lhs)
   {
     BL_PROFILE("ebco::setToZero");
-    EBLevelDataOps::setToZero(a_lhs);
+    EBLevelDataOps::setVal(a_lhs, 0.0);
   }
   //-------------------------------------------------------------------------------
   void
@@ -855,9 +845,9 @@ namespace amrex
         int                         a_iterations)
   {
     BL_PROFILE("nwoebco::relax");
-    BL_ASSERT(a_phi.isDefined());
-    BL_ASSERT(a_rhs.isDefined());
-    BL_ASSERT(a_phi.nGrow() >= IntVect::Unit);
+    BL_ASSERT(a_phi.nGrow() == m_ghostPhi);
+    BL_ASSERT(a_rhs.nGrow() == m_ghostRHS);
+    BL_ASSERT(a_phi.nComp() == 1);
     BL_ASSERT(a_phi.nComp() == a_rhs.nComp());

     // do first red, then black passes
@@ -867,12 +857,10 @@ namespace amrex
       {
         //after this lphi = L(phi)
         //this call contains bcs and exchange
-        if ((icolor == 0) || (!s_doLazyRelax))
-        {
-          BL_PROFILE("ghostfill and homogcfinterp");
-          fillPhiGhost(a_phi, true);
-          homogeneousCFInterp(a_phi);
-        }
+        BL_PROFILE("ghostfill and homogcfinterp");
+        fillPhiGhost(a_phi, true);
+        homogeneousCFInterp(a_phi);
+
         gsrbColor(a_phi, a_rhs, m_colors[icolor]);
       }
     }
@@ -886,7 +874,7 @@ namespace amrex
     BL_PROFILE("nwoebco::homog_cfinterp");
     if (m_hasCoar)
     {
-      m_cfInterp->coarseFineInterpH(a_phif,  0, 0, 1);
+      m_cfInterp.coarseFineInterpH(a_phif,  0, 0, 1);
     }
   }

@@ -972,23 +960,16 @@ namespace amrex
     bool homogeneous = true;

     EBCellFactory ebcellfactTL(m_eblg.getEBISL());
-    IntVect ghostVec = a_rhsThisLevel.nGrow();
+    int ghost = a_rhsThisLevel.nGrow();

-    resThisLevel.define(m_eblg.getDBL(), 1, ghostVec, ebcellfactTL);
+    resThisLevel.define(m_eblg.getDBL(), m_eblg.getDM(), 1, ghost, MFInfo(), ebcellfactTL);

     // Get the residual on the fine grid
     residual(resThisLevel,a_phiThisLevel,a_rhsThisLevel,homogeneous);

     // now use our nifty averaging operator
-    Interval variables(0, 0);
-    if (m_layoutChanged)
-    {
-      m_ebAverageMG.average(a_resCoar, resThisLevel, variables);
-    }
-    else
-    {
-      m_ebAverageMG.averageMG(a_resCoar, resThisLevel, variables);
-    }
+    m_ebAverageMG.average(a_resCoar, resThisLevel, 0, 0, 1);
+
   }
   //-------------------------------------------------------------------------------
   void EBConductivityOp::
@@ -996,15 +977,7 @@ namespace amrex
                    const FabArray<EBCellFAB>& a_correctCoar)
   {
     BL_PROFILE("EBConductivityOp::prolongIncrement");
-    Interval vars(0, 0);
-    if (m_layoutChanged)
-    {
-      m_ebInterpMG.pwcInterp(a_phiThisLevel, a_correctCoar, vars);
-    }
-    else
-    {
-      m_ebInterpMG.pwcInterpMG(a_phiThisLevel, a_correctCoar, vars);
-    }
+    m_ebInterpMG.interpolate(a_phiThisLevel, a_correctCoar, 0, 0, 1);
   }
   //-------------------------------------------------------------------------------
   int EBConductivityOp::
@@ -1028,25 +1001,19 @@ namespace amrex
               bool a_homogeneousPhysBC,
               AMRLevelOp<FabArray<EBCellFAB> >* a_finerOp)
   {
-    BL_PROFILERS("EBConductivityOp::AMRResidual");
-    BL_PROFILER("AMROperator", t1);
-    BL_PROFILER("axby", t2);
+    BL_PROFILE("EBConductivityOp::AMRResidual");
     BL_ASSERT(a_residual.nGrow() == m_ghostRHS);
     BL_ASSERT(a_rhs.nGrow() == m_ghostRHS);
     BL_ASSERT(a_residual.nComp() == 1);
     BL_ASSERT(a_phi.nComp() == 1);
     BL_ASSERT(a_rhs.nComp() == 1);

-    CH_START(t1);
     AMROperator(a_residual, a_phiFine, a_phi, a_phiCoar,
                 a_homogeneousPhysBC, a_finerOp);
-    CH_STOP(t1);

     //multiply by -1 so a_residual now holds -L(phi)
     //add in rhs so a_residual = rhs - L(phi)
-    CH_START(t2);
     axby(a_residual,a_residual,a_rhs,-1.0, 1.0);
-    CH_STOP(t2);
   }
   //-------------------------------------------------------------------------------
   void EBConductivityOp::
@@ -1057,27 +1024,20 @@ namespace amrex
               bool a_homogeneousPhysBC,
               AMRLevelOp<FabArray<EBCellFAB> >* a_finerOp)
   {
-    BL_PROFILERS("EBConductivityOp::AMROperator");
-    BL_PROFILER("applyOp", t1);
-    BL_PROFILER("reflux", t2);
+    BL_PROFILE("EBConductivityOp::AMROperator");
     BL_ASSERT(a_LofPhi.nGrow() == m_ghostRHS);
     BL_ASSERT(a_LofPhi.nComp() == 1);
     BL_ASSERT(a_phi.nComp() == 1);

     //apply the operator between this and the next coarser level.
-    CH_START(t1);
     applyOp(a_LofPhi, a_phi, &a_phiCoar,  a_homogeneousPhysBC, false);
-    CH_STOP(t1);
+

     //now reflux to enforce flux-matching from finer levels
     if (m_hasFine)
     {
       BL_ASSERT(a_finerOp != NULL);
-      CH_START(t2);
-
       reflux(a_LofPhi, a_phiFine, a_phi, a_finerOp);
-
-      CH_STOP(t2);
     }
   }
   //-------------------------------------------------------------------------------
@@ -1088,29 +1048,17 @@ namespace amrex
          const FabArray<EBCellFAB>& a_phi,
          AMRLevelOp<FabArray<EBCellFAB> >* a_finerOp)
   {
-    BL_PROFILERS("EBConductivityOp::fastReflux");
-    BL_PROFILER("setToZero",t2);
-    BL_PROFILER("incrementCoar",t3);
-    BL_PROFILER("incrementFine",t4);
-    BL_PROFILER("reflux_from_reg",t5);
-    Interval interv(0,0);
-
-    CH_START(t2);
+    BL_PROFILE("EBConductivityOp::reflux");
+
     m_fastFR.setToZero();
-    CH_STOP(t2);
-    CH_START(t3);
+
     incrementFRCoar(m_fastFR, a_phiFine, a_phi);
-    CH_STOP(t3);

-    CH_START(t4);
     incrementFRFine(m_fastFR, a_phiFine, a_phi, a_finerOp);
-    CH_STOP(t4);
-    CH_START(t5);

-    Real scale = 1.0/m_dx;
-    m_fastFR.reflux(a_residual, interv, scale);

-    CH_STOP(t5);
+    Real scale = 1.0/m_dx;
+    m_fastFR.reflux(a_residual, scale, 0, 0, 1);
   }
   //-------------------------------------------------------------------------------
   void
@@ -1203,13 +1151,13 @@ namespace amrex
     BL_ASSERT(a_phi.nComp() == 1);
     BL_ASSERT(m_hasFine);
     int ncomp = 1;
-    Interval interv(0,0);
+
     EBConductivityOp& finerEBAMROp = (EBConductivityOp& )(*a_finerOp);

     //ghost cells of phiFine need to be filled
     FabArray<EBCellFAB>& phiFine = (FabArray<EBCellFAB>&) a_phiFine;
-    finerEBAMROp.m_cfInterp->coarseFineInterp(phiFine, a_phi, 0, 0, 1);
-    phiFine.exchange(finerEBAMROp.m_exchangeCopier);
+    finerEBAMROp.m_cfInterp.coarseFineInterp(phiFine, a_phi, 0, 0, 1);
+    phiFine.FillBoundary();

     for(MFIter mfi_f(m_eblgFine.getDBL(), m_eblgFine.getDM()); mfi_f.isValid(); ++mfi_f)
     {
@@ -1220,7 +1168,8 @@ namespace amrex
       {
         for (SideIterator sit; sit.ok(); sit.next())
         {
-          Box fabBox = adjCellBox(boxFine, idir, sit(), 1);
+          Box fabBox=EBArith::adjCellBox(boxFine, idir, sit(), 1);
+
           fabBox.shift(idir, -sign(sit()));

           Box ghostedBox = fabBox;
@@ -1313,14 +1262,12 @@ namespace amrex
   AMRRestrict(FabArray<EBCellFAB>&       a_resCoar,
               const FabArray<EBCellFAB>& a_residual,
               const FabArray<EBCellFAB>& a_correction,
-              const FabArray<EBCellFAB>& a_coarCorrection,
-              bool a_skip_res )
+              const FabArray<EBCellFAB>& a_coarCorrection)
   {
     BL_PROFILE("EBConductivityOp::AMRRestrict");
     BL_ASSERT(a_residual.nGrow() == m_ghostRHS);
     BL_ASSERT(a_correction.nGrow() == m_ghostPhi);
     BL_ASSERT(a_coarCorrection.nGrow() == m_ghostPhi);
-    BL_ASSERT(!a_skip_res);

     BL_ASSERT(a_residual.nComp() == 1);
     BL_ASSERT(a_resCoar.nComp() == 1);
@@ -1331,9 +1278,9 @@ namespace amrex
     bool homogeneousCF =   false;

     EBCellFactory ebcellfactTL(m_eblg.getEBISL());
-    IntVect ghostVec = a_residual.nGrow();
+    int ghostVec = a_residual.nGrow();

-    resThisLevel.define(m_eblg.getDBL(), 1, ghostVec, ebcellfactTL);
+    resThisLevel.define(m_eblg.getDBL(), m_eblg.getDM(), 1, ghostVec, MFInfo(), ebcellfactTL);
     EBLevelDataOps::setVal(resThisLevel, 0.0);

     //API says that we must average(a_residual - L(correction, coarCorrection))
@@ -1342,8 +1289,7 @@ namespace amrex
     scale(resThisLevel,-1.0);

     //use our nifty averaging operator
-    Interval variables(0, 0);
-    m_ebAverage.average(a_resCoar, resThisLevel, variables);
+    m_ebAverage.average(a_resCoar, resThisLevel, 0, 0, 1);

   }
   //-------------------------------------------------------------------------------
@@ -1369,8 +1315,7 @@ namespace amrex
   {
     BL_PROFILE("EBConductivityOp::AMRProlong");
     //use cached interpolation object
-    Interval variables(0, 0);
-    m_ebInterp.pwcInterp(a_correction, a_coarCorrection, variables);
+    m_ebInterp.interpolate(a_correction, a_coarCorrection, 0, 0, 1);
   }
   //-------------------------------------------------------------------------------
   void
@@ -1389,9 +1334,9 @@ namespace amrex
     bool homogeneousCF   = false;

     EBCellFactory ebcellfactTL(m_eblg.getEBISL());
-    IntVect ghostVec = a_residual.nGrow();
+    int ghostVec = a_residual.nGrow();

-    lcorr.define(m_eblg.getDBL(), 1, ghostVec, ebcellfactTL);
+    lcorr.define(m_eblg.getDBL(), m_eblg.getDM(), 1, ghostVec, MFInfo(), ebcellfactTL);

     applyOp(lcorr, a_correction, &a_coarCorrection, homogeneousPhys, homogeneousCF);

diff --git a/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.H b/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.H
index 49b502cdbd7..068c167cc62 100644
--- a/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.H
+++ b/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.H
@@ -45,8 +45,8 @@ namespace amrex
                             const vector<int>                                   &  a_refRatio,
                             const shared_ptr<ConductivityBaseDomainBCFactory>   &  a_domainBCFactory,
                             const shared_ptr<ConductivityBaseEBBCFactory>       &  a_ebBcFactory,
-                            const IntVect                                       &  a_ghostCellsPhi,
-                            const IntVect                                       &  a_ghostCellsRhs,
+                            const int                                           &  a_ghostCellsPhi,
+                            const int                                           &  a_ghostCellsRhs,
                             int a_numLevels = -1);

@@ -70,6 +70,8 @@ namespace amrex
                    const int&  a_depth,
                    const bool  a_amrLevelOp);

+    static int s_testRef;
+    static int s_maxBoxSize;
   protected:

     vector<EBLevelGrid>                                  m_eblgs;
@@ -89,6 +91,7 @@ namespace amrex
     int                                                  m_ghostCellsRhs;
     int                                                  m_numLevels;
     vector<Real>                                         m_dx;
+
   private:
     ///weak construction bad
     EBConductivityOpFactory();
@@ -98,7 +101,6 @@ namespace amrex

     //copy constructor and operator= disallowed for all the usual reasons
     void operator=(const EBConductivityOpFactory& a_opin);
-
-
+  };
 }
 #endif
diff --git a/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.cpp b/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.cpp
index 936ba556ccb..4da37e251e2 100644
--- a/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.cpp
+++ b/Src/EBAMRElliptic/AMReX_EBConductivityOpFactory.cpp
@@ -13,6 +13,7 @@
 #include "AMReX_EBArith.H"
 #include "AMReX_EBConductivityOpFactory.H"
 #include "AMReX_EBCoarseAverage.H"
+#include "AMReX_ParmParse.H"

 namespace amrex
 {
@@ -22,12 +23,12 @@ namespace amrex

   //-----------------------------------------------------------------------
   void
-  nwoebcoCoarsenStuff(LevelData<EBCellFAB>               & a_acoefCoar,
-                      LevelData<EBFluxFAB>               & a_bcoefCoar,
+  nwoebcoCoarsenStuff(FabArray<EBCellFAB>               & a_acoefCoar,
+                      FabArray<EBFluxFAB>               & a_bcoefCoar,
                       const EBLevelGrid                  & a_eblgFine,
                       const EBLevelGrid                  & a_eblgCoar,
-                      const LevelData<EBCellFAB>         & a_acoefFine,
-                      const LevelData<EBFluxFAB>         & a_bcoefFine,
+                      const FabArray<EBCellFAB>         & a_acoefFine,
+                      const FabArray<EBFluxFAB>         & a_bcoefFine,
                       const int                          & a_refToDepth)
   {
     BL_ASSERT(a_refToDepth > 0);
@@ -37,8 +38,8 @@ namespace amrex

     if (a_refToDepth == 1)
     {
-      a_acoefCoar.copy(a_acoefFine 0, 0, 1, 0, 0);
-      a_bcoefCoar.copy(a_bcoefCoar 0, 0, 1, 0, 0);
+      a_acoefCoar.copy(a_acoefFine, 0, 0, 1, 0, 0);
+      a_bcoefCoar.copy(a_bcoefCoar, 0, 0, 1, 0, 0);
     }
     else
     {
@@ -52,7 +53,6 @@ namespace amrex
       //amrex::Warning("might want to figure out what harmonic averaging is in this context");
       averageOp.average( a_acoefCoar     ,  a_acoefFine     , 0, 0, 1);
       averageOp.average( a_bcoefCoar     ,  a_bcoefFine     , 0, 0, 1);
-      averageOp.average( a_bcoefCoarIrreg,  a_bcoefFineIrreg, 0, 0, 1);
     }
   }
   //-----------------------------------------------------------------------
@@ -60,43 +60,22 @@ namespace amrex
   {
   }
   //-----------------------------------------------------------------------
-  int
   EBConductivityOpFactory::
-  refToFiner(const ProblemDomain& a_domain) const
-  {
-    int retval = -1;
-    bool found = false;
-    for (int ilev = 0; ilev < m_eblgs.size(); ilev++)
-    {
-      if (m_eblgs[ilev].getDomain() == a_domain)
-      {
-        retval = m_refRatio[ilev];
-        found = true;
-      }
-    }
-    if (!found)
-    {
-      amrex::Error("Domain not found in AMR hierarchy");
-    }
-    return retval;
-  }
-  //-----------------------------------------------------------------------
-  EBConductivityOpFactory::
-  EBConductivityOpFactory(onst vector<EBLevelGrid>&                                   a_eblgs,
-                          const Real&                                                 a_alpha,
-                          const Real&                                                 a_beta,
-                          const vector<RefCountedPtr<LevelData<EBCellFAB> > >&        a_acoef,
-                          const vector<RefCountedPtr<LevelData<EBFluxFAB> > >&        a_bcoef,
-                          const Real&                                                 a_dxCoarse,
-                          const vector<int>&                                          a_refRatio,
-                          const RefCountedPtr<ConductivityBaseDomainBCFactory>&       a_domainBCFactory,
-                          const RefCountedPtr<ConductivityBaseEBBCFactory>    &       a_ebBCFactory,
-                          const int     &                                             a_ghostCellsPhi,
-                          const int     &                                             a_ghostCellsRhs,
+  EBConductivityOpFactory(const vector<EBLevelGrid>&                              a_eblgs,
+                          const Real&                                             a_alpha,
+                          const Real&                                             a_beta,
+                          const vector<shared_ptr<FabArray<EBCellFAB> > >&        a_acoef,
+                          const vector<shared_ptr<FabArray<EBFluxFAB> > >&        a_bcoef,
+                          const Real&                                             a_dxCoarse,
+                          const vector<int>&                                      a_refRatio,
+                          const shared_ptr<ConductivityBaseDomainBCFactory>&      a_domainBCFactory,
+                          const shared_ptr<ConductivityBaseEBBCFactory>    &      a_ebBCFactory,
+                          const int     &                                         a_ghostCellsPhi,
+                          const int     &                                         a_ghostCellsRhs,
                           int a_numLevels)
   {
     BL_ASSERT(a_eblgs.size() <= a_refRatio.size());
-    m_dataBased = false;
+
     m_ghostCellsRhs = a_ghostCellsRhs;
     m_ghostCellsPhi = a_ghostCellsPhi;
     m_acoef         = a_acoef;
@@ -134,9 +113,9 @@ namespace amrex
   //-----------------------------------------------------------------------
   EBConductivityOp*
   EBConductivityOpFactory::
-  MGnewOp(const ProblemDomain& a_domainFine,
-          int                  a_depth,
-          bool                 a_homoOnly)
+  MGnewOp(const Box& a_domainFine,
+          int        a_depth,
+          bool       a_homoOnly)
   {
     ParmParse pp;
     bool turn_off_mg = false;
@@ -151,9 +130,9 @@ namespace amrex
     int ref=-1;
     bool found = false;

-    RefCountedPtr<LevelData<EBCellFAB> >               acoef;
-    RefCountedPtr<LevelData<EBFluxFAB> >               bcoef;
-    RefCountedPtr<LevelData<BaseIVFAB<Real> > >   bcoefIrreg;
+    shared_ptr<FabArray<EBCellFAB> >               acoef;
+    shared_ptr<FabArray<EBFluxFAB> >               bcoef;
+    shared_ptr<FabArray<BaseIVFAB<Real> > >   bcoefIrreg;

     for (int ilev = 0; ilev < m_numLevels && !found; ilev++)
     {
@@ -177,7 +156,7 @@ namespace amrex
   //-----------------------------------------------------------------------
   EBConductivityOp*
   EBConductivityOpFactory::
-  createOperator(const int&  a_amrlevel,
+  createOperator(const int&  a_amrLevel,
                  const int&  a_depth,
                  const bool  a_amrLevelOp)
   {
@@ -196,17 +175,17 @@ namespace amrex

     if(a_amrLevelOp)
     {
-      eblg = m_eblgs[a_amrlevel];
+      eblg = m_eblgs[a_amrLevel];
       if(a_amrLevel > 0)
       {
-        eblgCoar = m_eblgs[a_amrlevel-1];
-        refToCoar = m_refRatio[a_amrlevel-1]
+        eblgCoar = m_eblgs[a_amrLevel-1];
+        refToCoar = m_refRatio[a_amrLevel-1];
         hasCoarser = true;
       }
       if(a_amrLevel < (m_numLevels - 1))
       {
-        eblgFine = m_eblgs[a_amrlevel+1];
-        refToFine = m_refRatio[a_amrlevel]
+        eblgFine = m_eblgs[a_amrLevel+1];
+        refToFine = m_refRatio[a_amrLevel];
         hasFiner = true;
       }
     }
@@ -215,11 +194,11 @@ namespace amrex
       //check to see if we are able to create an EBLG at this depth.   If not, return NULL
       if(a_depth == 0)
       {
-        eblg = m_eblgs[a_amrlevel];
+        eblg = m_eblgs[a_amrLevel];
       }
       else
       {
-        bool coarsenable = EBArith::createCoarserEBLG(eblg,  m_eblgs[a_amrlevel], refRatMG,  s_testRef, s_maxBoxSize);
+        bool coarsenable = EBArith::createCoarserEBLG(eblg,  m_eblgs[a_amrLevel], refRatMG,  s_testRef, s_maxBoxSize);
         if(!coarsenable)
         {
           return NULL;
@@ -228,26 +207,27 @@ namespace amrex
     }

     //now see if there is a coarser MG level
+    EBLevelGrid eblgCoarMG;
     bool hasCoarMG = EBArith::createCoarserEBLG(eblgCoarMG , eblg, 2, s_testRef, s_maxBoxSize);
-    Real          dxMGLevel = m_dx[a_amrlevel]*refRatMG;
+    Real          dxMGLevel = m_dx[a_amrLevel]*refRatMG;
     Real dxCoar = -1.0;
-    if (a_amrlevel > 0)
+    if (a_amrLevel > 0)
     {
-      dxCoar = m_dx[a_amrlevel-1];
+      dxCoar = m_dx[a_amrLevel-1];
     }

     shared_ptr<ConductivityBaseDomainBC>  domainBC(m_domainBCFactory->create());
-    shared_ptr<ConductivityBaseEBBC>      ebBC(m_ebbcFactory->create());
+    shared_ptr<ConductivityBaseEBBC>      ebBC(        m_ebBCFactory->create());
     shared_ptr<FabArray<EBCellFAB> >      acoef;
     shared_ptr<FabArray<EBFluxFAB> >      bcoef;

     //get coefficients
-    nwoebcoCoarsenStuff(acoef,
-                        bcoef,
-                        m_eblgs[a_amrlevel],
+    nwoebcoCoarsenStuff(*acoef,
+                        *bcoef,
+                        m_eblgs[a_amrLevel],
                         eblg,
-                        m_acoef[a_amrlevel],
-                        m_bcoef[a_amrlevel],
+                        *m_acoef[a_amrLevel],
+                        *m_bcoef[a_amrLevel],
                         refRatMG);

@@ -270,13 +250,14 @@ namespace amrex
                            acoef,
                            bcoef,
                            m_ghostCellsPhi,
-                           m_ghostCellsRHS);
-      }
-
+                           m_ghostCellsRhs);
+    return newOp;
+  }
+
   //-----------------------------------------------------------------------
   EBConductivityOp*
   EBConductivityOpFactory::
-  AMRnewOp(const ProblemDomain& a_domainFine)
+  AMRnewOp(const Box& a_domainFine)
   {
     //figure out which level we are at.
     int ref=-1;
diff --git a/Src/EBAMRElliptic/AMReX_EBSimpleSolver.H b/Src/EBAMRElliptic/AMReX_EBSimpleSolver.H
index 0e3f977646a..e0ac5d5fde5 100644
--- a/Src/EBAMRElliptic/AMReX_EBSimpleSolver.H
+++ b/Src/EBAMRElliptic/AMReX_EBSimpleSolver.H
@@ -14,7 +14,7 @@

 #include "AMReX_FabArray.H"
 #include "AMReX_LinearSolver.H"
-#include "AMReX_MultiGrid.H"
+#include "AMReX_EBMultiGrid.H"
 #include "AMReX_EBCellFAB.H"

 namespace amrex
diff --git a/Src/EBAMRElliptic/AMReX_EBSimpleSolver.cpp b/Src/EBAMRElliptic/AMReX_EBSimpleSolver.cpp
index e8f427080f2..86729c70c6f 100644
--- a/Src/EBAMRElliptic/AMReX_EBSimpleSolver.cpp
+++ b/Src/EBAMRElliptic/AMReX_EBSimpleSolver.cpp
@@ -55,7 +55,7 @@ namespace amrex
   void EBSimpleSolver::solve(FabArray<EBCellFAB>&       a_phi,
                              const FabArray<EBCellFAB>& a_rhs)
   {
-    CH_assert(m_isDefined);
+    BL_ASSERT(m_isDefined);

     m_operator->relax(a_phi,a_rhs,m_numSmooths);
   }
diff --git a/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.H b/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.H
index 5cd7e40d52d..541e0ca7cf1 100644
--- a/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.H
+++ b/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.H
@@ -21,16 +21,12 @@ namespace amrex
 /**
    Class to do Dirichlet boundary conditions on the domain for the conductivity operator.
 */
-class NeumannConductivityDomainBC: public ConductivityBaseDomainBC
-{
-public:
-  NeumannConductivityDomainBC()
-    {
-    }
+  class NeumannConductivityDomainBC: public ConductivityBaseDomainBC
+  {
+  public:
+    NeumannConductivityDomainBC();

-  virtual ~NeumannConductivityDomainBC()
-    {
-    }
+    virtual ~NeumannConductivityDomainBC();

     ///
     virtual void
@@ -58,36 +54,28 @@ public:
                    const Side::LoHiSide& a_side,
                    const bool&           a_useHomogeneous);

-    ///
-    virtual void
-    fillPhiGhost(FArrayBox&     a_phi,
-                 const Box&     a_valid,
-                 const Box&     a_domain,
-                 Real           a_dx,
-                 bool           a_homogeneous);
-
-private:
+  private:

-};
+  };

-class NeumannConductivityDomainBCFactory: public ConductivityBaseDomainBCFactory
-{
-public:
-  NeumannConductivityDomainBCFactory()
-    {
-    }
+  class NeumannConductivityDomainBCFactory: public ConductivityBaseDomainBCFactory
+  {
+  public:
+    NeumannConductivityDomainBCFactory()
+      {
+      }

-  virtual ~NeumannConductivityDomainBCFactory()
-    {
-    }
+    virtual ~NeumannConductivityDomainBCFactory()
+      {
+      }

-  ConductivityBaseDomainBC* new_object_ptr()
-    {
+    ConductivityBaseDomainBC* new_object_ptr()
+      {
         NeumannConductivityDomainBC* newBC = new NeumannConductivityDomainBC();
         return static_cast<ConductivityBaseDomainBC*>(newBC);
-    }
+      }

-};
+  };
 }
 #endif
diff --git a/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.cpp b/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.cpp
index 1d1d4b668a9..b5e74737e95 100644
--- a/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.cpp
+++ b/Src/EBAMRElliptic/AMReX_NeumannConductivityDomainBC.cpp
@@ -13,12 +13,20 @@
 #include "AMReX_EBArith.H"
 namespace amrex
 {
+  NeumannConductivityDomainBC::
+  NeumannConductivityDomainBC()
+  {
+  }
+
+  NeumannConductivityDomainBC::
+  ~NeumannConductivityDomainBC()
+  {
+  }
+
   void
   NeumannConductivityDomainBC::
   fillPhiGhost(FArrayBox&     a_phi,
                const Box&     a_valid,
-               const Box&     a_domain,
-               Real           a_dx,
                bool           a_homogeneous)
   {
     Box grownBox = a_valid;
@@ -32,19 +40,19 @@ namespace amrex
         choppedBox.grow(idir,-1);
         Box toRegion = EBArith::adjCellBox(choppedBox, idir, sit(), 1);

-        if(!a_domain.contains(toRegion))
+        if(!m_eblg.getDomain().contains(toRegion))
         {
           for (BoxIterator bit(toRegion); bit.ok(); ++bit)
           {
             const IntVect& iv = bit();
             //fake vof just to get the location
             VolIndex vof(iv, 0);
-            RealVect loc = EBArith::getVoFLocation(vof, a_dx, RealVect::Zero);
+            RealVect loc = EBArith::getVoFLocation(vof, m_dx, RealVect::Zero);
             int isign = sign(sit());
             IntVect ivneigh = iv - isign*BASISV(idir);
             Real value = bcvaluefunc(loc, idir, sit());
             if(a_homogeneous) value = 0;
-            a_phi(iv, 0) = a_phi(ivneigh, 0)  + a_dx*value;
+            a_phi(iv, 0) = a_phi(ivneigh, 0)  + m_dx*value;
           }
         }
       }
diff --git a/Src/EBAMRElliptic/AMReX_VCAggStencil.cpp b/Src/EBAMRElliptic/AMReX_VCAggStencil.cpp
index af81732784f..34756b9e94d 100644
--- a/Src/EBAMRElliptic/AMReX_VCAggStencil.cpp
+++ b/Src/EBAMRElliptic/AMReX_VCAggStencil.cpp
@@ -1,36 +1,36 @@
-#ifdef CH_LANG_CC
 /*
- *      _______              __
- *     / ___/ /  ___  __ _  / /  ___
- *    / /__/ _ \/ _ \/  V \/ _ \/ _ \
- *    \___/_//_/\___/_/_/_/_.__/\___/
- *    Please refer to Copyright.txt, in Chombo's root directory.
+ *       {_       {__       {__{_______              {__      {__
+ *      {_ __     {_ {__   {___{__    {__             {__   {__
+ *     {_  {__    {__ {__ { {__{__    {__     {__      {__ {__
+ *    {__   {__   {__  {__  {__{_ {__       {_   {__     {__
+ *   {______ {__  {__   {_  {__{__  {__    {_____ {__  {__ {__
+ *  {__       {__ {__       {__{__    {__  {_         {__   {__
+ * {__         {__{__       {__{__      {__  {____   {__      {__
+ *
  */
-#endif

+#include "AMReX_VCAggStencil.H"

-#include "VCAggStencil.H"
-
-#include "NamespaceHeader.H"
-
-/**************/
-VCAggStencil::
-VCAggStencil(const Vector<RefCountedPtr<BaseIndex>   > & a_dstVoFs,
-             const Vector<RefCountedPtr<BaseStencil> > & a_vofStencil,
-             const EBCellFAB                           & a_phiData,
-             const EBCellFAB                           & a_rhsData,
-             const EBCellFAB                           & a_relCoef,
-             const BaseIVFAB<Real>                     & a_alphaWt,
-             const int                                 & a_ncomp)
-  :AggStencil<EBCellFAB, EBCellFAB>(a_dstVoFs, a_vofStencil, a_phiData, a_rhsData)
+namespace amrex
 {
-  CH_TIME("VCAggSten.constructor");
-
-  m_phiAccess.resize(a_dstVoFs.size());
-  m_relAccess.resize(a_dstVoFs.size());
-  m_alpAccess.resize(a_dstVoFs.size());
-  m_iv.resize(a_dstVoFs.size());
-  for (int idst = 0; idst < a_dstVoFs.size(); idst++)
+/**************/
+  VCAggStencil::
+  VCAggStencil(const vector<shared_ptr<BaseIndex>   >    & a_dstVoFs,
+               const vector<shared_ptr<BaseStencil> >    & a_vofStencil,
+               const EBCellFAB                           & a_phiData,
+               const EBCellFAB                           & a_rhsData,
+               const EBCellFAB                           & a_relCoef,
+               const BaseIVFAB<Real>                     & a_alphaWt,
+               const int                                 & a_ncomp)
+    :AggStencil<EBCellFAB, EBCellFAB>(a_dstVoFs, a_vofStencil, a_phiData, a_rhsData)
+  {
+    BL_PROFILE("VCAggSten.constructor");
+
+    m_phiAccess.resize(a_dstVoFs.size());
+    m_relAccess.resize(a_dstVoFs.size());
+    m_alpAccess.resize(a_dstVoFs.size());
+    m_iv.resize(a_dstVoFs.size());
+    for (int idst = 0; idst < a_dstVoFs.size(); idst++)
     {
       const BaseIndex& dstVoF = *a_dstVoFs[idst];
       m_phiAccess[idst].dataID = a_phiData.dataType(dstVoF);
@@ -42,193 +42,189 @@ VCAggStencil(const Vector<RefCountedPtr<BaseIndex>   > & a_dstVoFs,

       VolIndex* vofPtr = dynamic_cast<VolIndex*>(&(*a_dstVoFs[idst]));
       if(vofPtr == NULL)
-        {
-          MayDay::Error("dynamic cast error--VCAggStencil just handles VolIndicies");
-        }
+      {
+        amrex::Error("dynamic cast error--VCAggStencil just handles VolIndicies");
+      }
       m_iv[idst] = vofPtr->gridIndex();
     }
-  m_cachePhi.resize( m_ebstencil.size(), Vector<Real>(a_ncomp, 0.));
-}
+    m_cachePhi.resize( m_ebstencil.size(), vector<Real>(a_ncomp, 0.));
+  }
 /************/
-void
-VCAggStencil::
-cachePhi(const EBCellFAB& a_phi) const
-{
-  CH_TIME("VCAggStencil::cachePhi");
-  Vector<const Real*> dataPtrsPhi(a_phi.numDataTypes());
-  for (int ivar = 0; ivar < a_phi.nComp(); ivar++)
+  void
+  VCAggStencil::
+  cachePhi(const EBCellFAB& a_phi) const
+  {
+    BL_PROFILE("VCAggStencil::cachePhi");
+    vector<const Real*> dataPtrsPhi(a_phi.numDataTypes());
+    for (int ivar = 0; ivar < a_phi.nComp(); ivar++)
     {
       for (int ivec = 0; ivec < dataPtrsPhi.size(); ivec++)
-        {
-          dataPtrsPhi[ivec] = a_phi.dataPtr(ivec, ivar);
-        }
+      {
+        dataPtrsPhi[ivec] = a_phi.dataPtr(ivec, ivar);
+      }

       for (int idst = 0; idst < m_ebstencil.size(); idst++)
-        {
-          const Real* phiPtr =  dataPtrsPhi[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
-          m_cachePhi[idst][ivar] = *phiPtr;
-        }
+      {
+        const Real* phiPtr =  dataPtrsPhi[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
+        m_cachePhi[idst][ivar] = *phiPtr;
+      }
     }
-}
+  }
 /**************/
-void
-VCAggStencil::
-uncachePhi(EBCellFAB& a_phi) const
-{
-  CH_TIME("VCAggSten::uncache");
-  Vector<Real*> dataPtrsPhi(a_phi.numDataTypes());
-  for (int ivar = 0; ivar < a_phi.nComp(); ivar++)
+  void
+  VCAggStencil::
+  uncachePhi(EBCellFAB& a_phi) const
+  {
+    BL_PROFILE("VCAggSten::uncache");
+    vector<Real*> dataPtrsPhi(a_phi.numDataTypes());
+    for (int ivar = 0; ivar < a_phi.nComp(); ivar++)
     {
       for (int ivec = 0; ivec < dataPtrsPhi.size(); ivec++)
-        {
-          dataPtrsPhi[ivec] = a_phi.dataPtr(ivec, ivar);
-        }
+      {
+        dataPtrsPhi[ivec] = a_phi.dataPtr(ivec, ivar);
+      }

       for (int idst = 0; idst < m_ebstencil.size(); idst++)
-        {
-          Real* phiPtr =  dataPtrsPhi[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
-          *phiPtr = m_cachePhi[idst][ivar];
-        }
+      {
+        Real* phiPtr =  dataPtrsPhi[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
+        *phiPtr = m_cachePhi[idst][ivar];
+      }
     }
-}
+  }
 /**************/
-void
-VCAggStencil::
-relax(EBCellFAB              & a_phi,
-      const EBCellFAB        & a_rhs,
-      const EBCellFAB        & a_relCoef,
-      const BaseIVFAB<Real>  & a_alphaWt,
-      const Real             & a_alpha,
-      const Real             & a_beta,
-      const int              & a_varDest,
-      const IntVect          & a_color)
-{
-  CH_TIME("VCAggSten::relax");
-  const int numtyperhs = a_rhs.numDataTypes();
-  const int numtypephi = a_phi.numDataTypes();
-  const int numtyperel = a_relCoef.numDataTypes();
-  const int numtypealp = a_alphaWt.numDataTypes();
+  void
+  VCAggStencil::
+  relax(EBCellFAB              & a_phi,
+        const EBCellFAB        & a_rhs,
+        const EBCellFAB        & a_relCoef,
+        const BaseIVFAB<Real>  & a_alphaWt,
+        const Real             & a_alpha,
+        const Real             & a_beta,
+        const int              & a_varDest,
+        const IntVect          & a_color)
+  {
+    BL_PROFILE("VCAggSten::relax");
+    const int numtyperhs = a_rhs.numDataTypes();
+    const int numtypephi = a_phi.numDataTypes();
+    const int numtyperel = a_relCoef.numDataTypes();
+    const int numtypealp = a_alphaWt.numDataTypes();

-  Vector<const Real*> dataPtrsRhs(numtyperhs);
-  Vector<const Real*> dataPtrsRel(numtyperel);
-  Vector<const Real*> dataPtrsAlp(numtypealp);
-  //phi is the source (what the stencil gets applied to)
-  //and the destination (where the answer goes).   For the
-  //source, we need  the variable to be zero because the stencil
-  //variable is taken into account in aggstencil
-  Vector<const Real*> dataPtrsSrc(numtypephi);
-  Vector<Real*>       dataPtrsDst(numtypephi);
-  int varDst = a_varDest;
-  int varSrc = 0;  //stencil variable taken into account in aggstencil
-  for (int ivec = 0; ivec < numtyperhs; ivec++)
+    vector<const Real*> dataPtrsRhs(numtyperhs);
+    vector<const Real*> dataPtrsRel(numtyperel);
+    vector<const Real*> dataPtrsAlp(numtypealp);
+    //phi is the source (what the stencil gets applied to)
+    //and the destination (where the answer goes).   For the
+    //source, we need  the variable to be zero because the stencil
+    //variable is taken into account in aggstencil
+    vector<const Real*> dataPtrsSrc(numtypephi);
+    vector<Real*>       dataPtrsDst(numtypephi);
+    int varDst = a_varDest;
+    int varSrc = 0;  //stencil variable taken into account in aggstencil
+    for (int ivec = 0; ivec < numtyperhs; ivec++)
     {
       //rhs has the same variable number as destination (in this case phi)
       dataPtrsRhs[ivec] = a_rhs.dataPtr(ivec, varDst);
     }
-  for (int ivec = 0; ivec < numtypealp; ivec++)
+    for (int ivec = 0; ivec < numtypealp; ivec++)
     {
       //alphaweight has the same variable number as destination (in this case phi)
       dataPtrsAlp[ivec] = a_alphaWt.dataPtr(ivec, varDst);
     }
-  for (int ivec = 0; ivec < numtypephi; ivec++)
+    for (int ivec = 0; ivec < numtypephi; ivec++)
     {
       dataPtrsSrc[ivec] = a_phi.dataPtr(ivec, varSrc);
     }
-  for (int ivec = 0; ivec < numtypephi; ivec++)
+    for (int ivec = 0; ivec < numtypephi; ivec++)
     {
       dataPtrsDst[ivec] = a_phi.dataPtr(ivec, varDst);
     }
-  for (int ivec = 0; ivec < numtypephi; ivec++)
+    for (int ivec = 0; ivec < numtypephi; ivec++)
     {
       //relaxation coeff has the same variable number as as destination (in this case phi)
       dataPtrsRel[ivec] = a_relCoef.dataPtr(ivec, varDst);
     }

-  for (int idst = 0; idst < m_ebstencil.size(); idst++)
+    for (int idst = 0; idst < m_ebstencil.size(); idst++)
     {
       const IntVect& iv = m_iv[idst];
       bool doThisVoF = true;
       for (int idir = 0; idir < SpaceDim; idir++)
+      {
+        if (iv[idir] % 2 != a_color[idir])
         {
-          if (iv[idir] % 2 != a_color[idir])
-            {
-              doThisVoF = false;
-              break;
-            }
+          doThisVoF = false;
+          break;
         }
+      }
       if(doThisVoF)
+      {
+        const Real* rhsiPtr =  dataPtrsRhs[m_dstAccess[idst].dataID] + m_dstAccess[idst].offset;
+        const Real& rhsi = *rhsiPtr;
+        const Real* relcoPtr =  dataPtrsRel[m_relAccess[idst].dataID] + m_relAccess[idst].offset;
+        const Real& relco = *relcoPtr;
+        const Real* alpWtPtr =  dataPtrsAlp[m_alpAccess[idst].dataID] + m_alpAccess[idst].offset;
+        const Real& alphaWeight = *alpWtPtr;
+
+
+        const stencil_t& ebstencil = m_ebstencil[idst];
+        Real lphi = 0;
+        for (int isten = 0; isten < ebstencil.size(); isten++)
         {
-          const Real* rhsiPtr =  dataPtrsRhs[m_dstAccess[idst].dataID] + m_dstAccess[idst].offset;
-          const Real& rhsi = *rhsiPtr;
-          const Real* relcoPtr =  dataPtrsRel[m_relAccess[idst].dataID] + m_relAccess[idst].offset;
-          const Real& relco = *relcoPtr;
-          const Real* alpWtPtr =  dataPtrsAlp[m_alpAccess[idst].dataID] + m_alpAccess[idst].offset;
-          const Real& alphaWeight = *alpWtPtr;
-
-
-          const stencil_t& ebstencil = m_ebstencil[idst];
-          Real lphi = 0;
-          for (int isten = 0; isten < ebstencil.size(); isten++)
-            {
-              const Real& weight = ebstencil[isten].second;
-              const long& offset = ebstencil[isten].first.offset;
-              const int & dataID = ebstencil[isten].first.dataID;
-              const Real& phiVal = *(dataPtrsSrc[dataID] + offset);
-              lphi += phiVal*weight;
-            }
-          Real* phiiPtr =  dataPtrsDst[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
-          Real& phii = *phiiPtr;
-          //multiply by beta and add in identity term
-          lphi = a_beta*lphi + a_alpha*alphaWeight*phii;
-
-          phii = phii + relco*(rhsi - lphi);
-          ch_flops()+=ebstencil.size()*2+5;
+          const Real& weight = ebstencil[isten].second;
+          const long& offset = ebstencil[isten].first.offset;
+          const int & dataID = ebstencil[isten].first.dataID;
+          const Real& phiVal = *(dataPtrsSrc[dataID] + offset);
+          lphi += phiVal*weight;
         }
+        Real* phiiPtr =  dataPtrsDst[m_phiAccess[idst].dataID] + m_phiAccess[idst].offset;
+        Real& phii = *phiiPtr;
+        //multiply by beta and add in identity term
+        lphi = a_beta*lphi + a_alpha*alphaWeight*phii;
+
+        phii = phii + relco*(rhsi - lphi);
+      }
     }
-  //the /ncolor is because this does one color at a time
-  int ncolor = D_TERM(2, *2, *2);
-  //ch_flops()+=(9*m_ebstencil.size())/ncolor;
-}
+  }

 /**************/
-void
-VCAggStencil::
-apply(EBCellFAB              & a_lph,
-      const EBCellFAB        & a_phi,
-      const BaseIVFAB<Real>  & a_alp, //alphaDiagWeight
-      const Real             & a_alpha,
-      const Real             & a_beta,
-      const int              & a_varDest,
-      const bool             & a_incrementOnly)
-{
-  CH_TIME("VCAggSten::apply");
-  //this makes lphi = divf
-  AggStencil<EBCellFAB,EBCellFAB>::apply(a_lph, a_phi, a_varDest, a_incrementOnly);
-
-  const int numtypelph = a_lph.numDataTypes();
-  const int numtypephi = a_phi.numDataTypes();
-  const int numtypealp = a_alp.numDataTypes();
+  void
+  VCAggStencil::
+  apply(EBCellFAB              & a_lph,
+        const EBCellFAB        & a_phi,
+        const BaseIVFAB<Real>  & a_alp, //alphaDiagWeight
+        const Real             & a_alpha,
+        const Real             & a_beta,
+        const int              & a_varDest,
+        const bool             & a_incrementOnly)
+  {
+    BL_PROFILE("VCAggSten::apply");
+    //this makes lphi = divf
+    AggStencil<EBCellFAB,EBCellFAB>::apply(a_lph, a_phi, a_varDest, a_incrementOnly);
+
+    const int numtypelph = a_lph.numDataTypes();
+    const int numtypephi = a_phi.numDataTypes();
+    const int numtypealp = a_alp.numDataTypes();

-  Vector<      Real*> dataPtrsLph(numtypelph);
-  Vector<const Real*> dataPtrsPhi(numtypephi);
-  Vector<const Real*> dataPtrsAlp(numtypealp);
-  //no stencils here so everything is on the same var
-  for (int ivec = 0; ivec < numtypelph; ivec++)
+    vector<      Real*> dataPtrsLph(numtypelph);
+    vector<const Real*> dataPtrsPhi(numtypephi);
+    vector<const Real*> dataPtrsAlp(numtypealp);
+    //no stencils here so everything is on the same var
+    for (int ivec = 0; ivec < numtypelph; ivec++)
     {
       dataPtrsLph[ivec] = a_lph.dataPtr(ivec, a_varDest);
     }
-  for (int ivec = 0; ivec < numtypealp; ivec++)
+    for (int ivec = 0; ivec < numtypealp; ivec++)
     {
       dataPtrsAlp[ivec] = a_alp.dataPtr(ivec, a_varDest);
     }
-  for (int ivec = 0; ivec < numtypephi; ivec++)
+    for (int ivec = 0; ivec < numtypephi; ivec++)
     {
       dataPtrsPhi[ivec] = a_phi.dataPtr(ivec, a_varDest);
     }

-  for (int idst = 0; idst < m_ebstencil.size(); idst++)
+    for (int idst = 0; idst < m_ebstencil.size(); idst++)
     {
       Real*        lphiPtr    =  dataPtrsLph[m_dstAccess[idst].dataID] + m_dstAccess[idst].offset;
       Real&           lphi    = *lphiPtr;
@@ -239,7 +235,6 @@ apply(EBCellFAB              & a_lph,
       //multiply by beta and add in identity term
       lphi = a_beta*lphi + a_alpha*alphaWeight*phii;
     }
-  ch_flops()+=m_ebstencil.size()*6;
+  }
 }

-#include "NamespaceFooter.H"
diff --git a/Src/EBAMRElliptic/Make.package b/Src/EBAMRElliptic/Make.package
index 13779f33317..261a40a3ff3 100644
--- a/Src/EBAMRElliptic/Make.package
+++ b/Src/EBAMRElliptic/Make.package
@@ -9,13 +9,14 @@ C$(EBAMRELLIPTIC_BASE)_headers += AMReX_ConductivityBaseDomainBC.H       AMReX_N
 C$(EBAMRELLIPTIC_BASE)_headers += AMReX_DirichletConductivityEBBC.H      AMReX_ConductivityBaseEBBC.H
 C$(EBAMRELLIPTIC_BASE)_headers += AMReX_DirichletConductivityDomainBC.H  AMReX_NeumannConductivityDomainBC.H
 C$(EBAMRELLIPTIC_BASE)_headers += AMReX_EBConductivityOpFactory.H        AMReX_EBConductivityOp.H
+C$(EBAMRELLIPTIC_BASE)_headers += AMReX_EBSimpleSolver.H AMReX_ConductivityBaseEBBC.H AMReX_VCAggStencil.H

 C$(EBAMRELLIPTIC_BASE)_sources += AMReX_DirichletConductivityDomainBC.cpp  AMReX_NeumannConductivityEBBC.cpp
 C$(EBAMRELLIPTIC_BASE)_sources += AMReX_DirichletConductivityEBBC.cpp	   AMReX_NeumannConductivityDomainBC.cpp
 C$(EBAMRELLIPTIC_BASE)_sources += AMReX_EBConductivityOp.cpp		   AMReX_EBConductivityOpFactory.cpp
-
+C$(EBAMRELLIPTIC_BASE)_sources += AMReX_EBSimpleSolver.cpp  AMReX_VCAggStencil.cpp
 F90$(EBAMRELLIPTIC_BASE)_headers += AMReX_EBEllipticFort_F.H
 F90$(EBAMRELLIPTIC_BASE)_sources += AMReX_EBEllipticFort.F90

diff --git a/Src/EBAMRTools/AMReX_DivergenceOp.H b/Src/EBAMRTools/AMReX_DivergenceOp.H
index 809abad23b9..8c3589d13f1 100644
--- a/Src/EBAMRTools/AMReX_DivergenceOp.H
+++ b/Src/EBAMRTools/AMReX_DivergenceOp.H
@@ -64,10 +64,11 @@ namespace amrex
                  const Real          & a_dx,
                  const int           & a_numComp,
                  const int           & a_ghostCellsInData,
+                 bool a_multiplyFluxByArea = true,
                  int a_redistRad = 1)
       {

-        define(a_eblg, a_dx, a_numComp, a_ghostCellsInData, a_redistRad);
+        define(a_eblg, a_dx, a_numComp, a_ghostCellsInData, a_multiplyFluxByArea, a_redistRad);
       }

     ///
@@ -78,6 +79,7 @@ namespace amrex
                 const Real          & a_dx,
                 const int           & a_numComp,
                 const int           & a_ghostCellsInData,
+                bool a_multiplyFluxByArea = true,
                 int a_redistRad = 1);

@@ -134,7 +136,7 @@ namespace amrex
     FabArray<IrregFAB>  m_massDiff;

     EBLevelRedist  m_eblevelRedist;
-
+    bool m_multiplyFluxByArea;
     EBNormalizeByVolumeFraction  m_normalizor;
     int m_nComp;
     Real m_dx;
diff --git a/Src/EBAMRTools/AMReX_DivergenceOp.cpp b/Src/EBAMRTools/AMReX_DivergenceOp.cpp
index 2d18fa1cb0f..08b68a4d832 100644
--- a/Src/EBAMRTools/AMReX_DivergenceOp.cpp
+++ b/Src/EBAMRTools/AMReX_DivergenceOp.cpp
@@ -33,10 +33,12 @@ namespace amrex
          const Real          & a_dx,
          const int           & a_nComp,
          const int           & a_ghostCellsInData,
+         bool a_multiplyFluxByArea,
          int a_redistRad)
   {
     m_isDefined = true;
     m_eblg          = a_eblg;
+    m_multiplyFluxByArea = a_multiplyFluxByArea;
     m_dx            = a_dx;
     m_nComp         = a_nComp;
     m_dataGhost     = a_ghostCellsInData;
@@ -127,7 +129,14 @@ namespace amrex
               IntVectSet cfivs;//empty--see comment above
               FaceStencil interpSten = EBArith::getInterpStencil(faces[iface], cfivs, ebis, domain);
               Real areaFrac = ebis.areaFrac(faces[iface]);
-              interpSten *= (isign*areaFrac/m_dx);
+              if(m_multiplyFluxByArea)
+              {
+                interpSten *= (isign*areaFrac/m_dx);
+              }
+              else
+              {
+                interpSten *= 1.0/(m_dx*m_dx);
+              }
               dirStencil += interpSten;
             }
           }
@@ -147,6 +156,7 @@ namespace amrex
                    int isrc, int idst, int inco,
                    bool a_trustRegDivF)
   {
+/**/
     BL_ASSERT(isDefined());
     BL_ASSERT(a_flux.nGrow() == m_dataGhost);
     BL_ASSERT(a_divF.nGrow() == m_dataGhost);
@@ -156,7 +166,11 @@ namespace amrex
       EBCellFAB       & divF = m_kappaDivergence[mfi];
       const EBFluxFAB & flux = a_flux[mfi];

-      if(!a_trustRegDivF)
+      if(a_trustRegDivF)
+      {
+        divF.copy(a_divF[mfi]);
+      }
+      else
       {
         BaseFab<Real>       &  regDivF = divF.getSingleValuedFAB();
         vector<const BaseFab<Real>*> regFlux(3, &(flux[0].getSingleValuedFAB()));
@@ -166,12 +180,16 @@ namespace amrex
         }
         const Box& grid = m_eblg.getDBL()[mfi];

+        int multiplyByArea = 0;
+        if(m_multiplyFluxByArea) multiplyByArea = 1;
+
         //first do everything as if it has no eb.
         ebfnd_divflux(BL_TO_FORTRAN_FAB(regDivF),
                       BL_TO_FORTRAN_FAB((*regFlux[0])),
                       BL_TO_FORTRAN_FAB((*regFlux[1])),
                       BL_TO_FORTRAN_FAB((*regFlux[2])),
                       BL_TO_FORTRAN_BOX(grid),
+                      &multiplyByArea,
                       &m_dx, &isrc, &idst, &inco);
       }
       //turn off increment only for bndry flux.  This sets the initial divergence at
@@ -211,6 +229,7 @@ namespace amrex
       m_eblevelRedist.increment(m_massDiff[mfi], mfi, idst, inco);
     }
     m_eblevelRedist.redistribute(a_divF, idst, inco);
+/**/
   }
   /************************************/
 }
diff --git a/Src/EBAMRTools/AMReX_EBFortND.F90 b/Src/EBAMRTools/AMReX_EBFortND.F90
index 7709111f3ae..9fbf1670ff0 100644
--- a/Src/EBAMRTools/AMReX_EBFortND.F90
+++ b/Src/EBAMRTools/AMReX_EBFortND.F90
@@ -583,14 +583,14 @@ subroutine ebfnd_divflux( &
        fluxfa1, fluxfa1_lo, fluxfa1_hi, fluxfa1_nco,  &
        fluxfa2, fluxfa2_lo, fluxfa2_hi, fluxfa2_nco,  &
        gridlo,gridhi, &
-       dx, isrc, idst, ncomp) &
+       multbyarea, dx, isrc, idst, ncomp) &
        bind(C, name="ebfnd_divflux")

     use amrex_fort_module, only : amrex_spacedim, c_real=>amrex_real

     implicit none

-    integer      :: iif,jjf,kkf,  ncomp, ivar, ivardivf, ivarflux
+    integer      :: iif,jjf,kkf,  ncomp, ivar, ivardivf, ivarflux, multbyarea
     integer      :: fluxfa0_nco
     integer      :: fluxfa1_nco
     integer      :: fluxfa2_nco
@@ -602,12 +602,18 @@ subroutine ebfnd_divflux( &
     integer      :: gridlo(0:2), gridhi(0:2)

     real(c_real) :: dx, xterm, yterm, zterm
-    real(c_real) :: fhix, flox
+    real(c_real) :: fhix, flox, denom
     real(c_real) :: divflux(divflux_lo(0):divflux_hi(0),divflux_lo(1):divflux_hi(1),divflux_lo(2):divflux_hi(2), 0:divflux_nco-1)
     real(c_real) :: fluxfa0(fluxfa0_lo(0):fluxfa0_hi(0),fluxfa0_lo(1):fluxfa0_hi(1),fluxfa0_lo(2):fluxfa0_hi(2), 0:fluxfa0_nco-1)
     real(c_real) :: fluxfa1(fluxfa1_lo(0):fluxfa1_hi(0),fluxfa1_lo(1):fluxfa1_hi(1),fluxfa1_lo(2):fluxfa1_hi(2), 0:fluxfa1_nco-1)
     real(c_real) :: fluxfa2(fluxfa2_lo(0):fluxfa2_hi(0),fluxfa2_lo(1):fluxfa2_hi(1),fluxfa2_lo(2):fluxfa2_hi(2), 0:fluxfa2_nco-1)

+    if(multbyarea .eq. 1) then
+       denom = one/dx
+    else
+       denom = one/dx/dx
+    endif
+
     do ivar = 0, ncomp-1
        ivarflux = isrc + ivar
        ivardivf = idst + ivar
@@ -624,7 +630,7 @@ subroutine ebfnd_divflux( &
 #if BL_SPACEDIM==3
                 zterm = fluxfa2(iif  , jjf  , kkf+1, ivarflux) - fluxfa2(iif, jjf, kkf, ivarflux)
 #endif
-                divflux(iif, jjf, kkf, ivardivf) = (xterm + yterm + zterm)/dx
+                divflux(iif, jjf, kkf, ivardivf) = (xterm + yterm + zterm)/denom

              enddo
diff --git a/Src/EBAMRTools/AMReX_EBFortND_F.H b/Src/EBAMRTools/AMReX_EBFortND_F.H
index 583a89f128e..bda3e614a6c 100644
--- a/Src/EBAMRTools/AMReX_EBFortND_F.H
+++ b/Src/EBAMRTools/AMReX_EBFortND_F.H
@@ -53,7 +53,7 @@
                        const amrex::Real* flx0, const int* flx0lo, const int* flx0hi, const int* incoflx0,
                        const amrex::Real* flx1, const int* flx1lo, const int* flx1hi, const int* incoflx1,
                        const amrex::Real* flx2, const int* flx2lo, const int* flx2hi, const int* incoflx2,
-                       const int*  gridlo, const int* gridhi,
+                       const int*  gridlo, const int* gridhi, const int* multibyarea,
                        const amrex::Real* dx, const int* isrc, const int* idst, const int* ncomp);

diff --git a/Src/EBAMRTools/AMReX_EBLevelDataOps.H b/Src/EBAMRTools/AMReX_EBLevelDataOps.H
index 70efbec1824..fd82555598a 100644
--- a/Src/EBAMRTools/AMReX_EBLevelDataOps.H
+++ b/Src/EBAMRTools/AMReX_EBLevelDataOps.H
@@ -131,6 +131,13 @@ namespace amrex
                       const Real& a_scale);

+    ///
+    /**
+    */
+    static void scale(FabArray<EBCellFAB>       & a_lhs,
+                      const FabArray<EBCellFAB> & a_scale);
+
+
     ///
     /**
        If comp < 0, set all components
diff --git a/Src/EBAMRTools/AMReX_EBLevelDataOps.cpp b/Src/EBAMRTools/AMReX_EBLevelDataOps.cpp
index e637d3a5706..d9d7c51c9a7 100644
--- a/Src/EBAMRTools/AMReX_EBLevelDataOps.cpp
+++ b/Src/EBAMRTools/AMReX_EBLevelDataOps.cpp
@@ -451,6 +451,19 @@ namespace amrex
       a_result[mfi] *= a_value;
     }
   }
+
+  //-----------------------------------------------------------------------
+  void
+  EBLevelDataOps::
+  scale(FabArray<EBCellFAB>       & a_result,
+        const FabArray<EBCellFAB> & a_value)
+  {
+    BL_PROFILE("EBLevelDataOps::scale_2");
+    for(MFIter mfi(a_result); mfi.isValid(); ++mfi)
+    {
+      a_result[mfi] *= a_value[mfi];
+    }
+  }
   //-----------------------------------------------------------------------
   void
   EBLevelDataOps::
diff --git a/Src/GeometryShop/AMReX_EBGraph.H b/Src/GeometryShop/AMReX_EBGraph.H
index 7f308e7af3f..2a76b6febd1 100644
--- a/Src/GeometryShop/AMReX_EBGraph.H
+++ b/Src/GeometryShop/AMReX_EBGraph.H
@@ -367,6 +367,11 @@ namespace amrex
       {
         return m_multiIVS;
       }
+
+    Box getFullRegion() const
+      {
+        return m_fullRegion;
+      }
   private:

     ///for serialization
@@ -374,7 +379,10 @@ namespace amrex

     ///box over which this graph is defined
     Box m_region;
-
+
+    ///box NOT intersected  with domain
+    Box m_fullRegion;
+
     ///computational domain at this level of refinement
     Box m_domain;

@@ -483,6 +491,13 @@ namespace amrex
       {
         return m_implem->numVoFs(a_iv);
       }
+
+    ///
+    Box getFullRegion() const
+      {
+        return m_implem->getFullRegion();
+      }
+
     ///
     /**
        Return true if every cell in the EBGraph is a regular cell.
@@ -794,12 +809,15 @@ namespace amrex

     ///
     /**
-       This resizes the BaseFab to cover getRegion
+       This resizes the BaseFab to cover the input region
        1 = regular
        0 = irregular
        -1 = covered
+
+       2 outside the domain
     */
-    void fillIntMask(BaseFab<int>& a_mask) const;
+    void fillIntMask(BaseFab<int>& a_mask,
+                     const Box   & a_subbox) const;

     ///
diff --git a/Src/GeometryShop/AMReX_EBGraph.cpp b/Src/GeometryShop/AMReX_EBGraph.cpp
index 55f3f6c58f0..fba85b1861b 100644
--- a/Src/GeometryShop/AMReX_EBGraph.cpp
+++ b/Src/GeometryShop/AMReX_EBGraph.cpp
@@ -402,6 +402,7 @@ namespace amrex

     m_tag = AllRegular;
     m_region = a_region;
+    m_fullRegion = a_region;
     m_irregIVS = IntVectSet();
     m_multiIVS = IntVectSet();
     m_mask.clear();
@@ -753,11 +754,16 @@ namespace amrex
     m_implem->fillMask(a_mask);
   }
   /*******************************/
-  void EBGraph::fillIntMask(BaseFab<int>& a_mask) const
+  void EBGraph::fillIntMask(BaseFab<int>& a_mask,
+                            const Box   & a_subbox) const
   {
-    Box interiorRegion = getRegion();
+    Box fullRegion = getFullRegion();
+    fullRegion &= a_subbox;
+    Box interiorRegion = fullRegion;
     interiorRegion &= getDomain();
-    a_mask.resize(interiorRegion, 1);
+
+    a_mask.resize(fullRegion, 1);
+    a_mask.setVal(2);
     for(BoxIterator boxit(interiorRegion); boxit.ok(); ++boxit)
     {
       const IntVect& iv = boxit();
@@ -1649,7 +1655,7 @@ namespace amrex
     retval += incrval;

     m_domain.linearOut(buf);
-    incrval = m_region.linearSize();
+    incrval = m_domain.linearSize();
     buf    += incrval;
     retval += incrval;

@@ -1712,7 +1718,7 @@ namespace amrex
     retval += incrval;

     m_domain.linearIn(buf);
-    incrval = m_region.linearSize();
+    incrval = m_domain.linearSize();
     buf    += incrval;
     retval += incrval;

diff --git a/Tools/Postprocessing/F_Src/GNUmakefile b/Tools/Postprocessing/F_Src/GNUmakefile
index efde7008d77..0e669ec2f55 100644
--- a/Tools/Postprocessing/F_Src/GNUmakefile
+++ b/Tools/Postprocessing/F_Src/GNUmakefile
@@ -99,8 +99,12 @@ programs += plt_compare_diff_grids.f90
 #programs += fcoarsen
 #programs += fwritecontents2d

-all: $(pnames)
+ifeq ($(DO_ALL), TRUE)
+  ptmp := $(wildcard f*.f90)
+  programs := $(basename $(ptmp))
+endif

+all: $(pnames)

 # probin stuff
 ifdef NEED_EOS_NETWORK
diff --git a/Tools/Postprocessing/F_Src/fdump.f90 b/Tools/Postprocessing/F_Src/fdump.f90
index d401cd10be5..de5bbe8a96c 100644
--- a/Tools/Postprocessing/F_Src/fdump.f90
+++ b/Tools/Postprocessing/F_Src/fdump.f90
@@ -9,7 +9,7 @@ program fdump
   use bl_IO_module
   use plotfile_module
   use multifab_module
-  use util_module
+  use box_util_module

   implicit none

diff --git a/Tests/EBAMRElliptic/exec/cond.inputs b/Tests/EBAMRElliptic/exec/cond.inputs
index e0ade9bd292..b35cd1de5cc 100644
--- a/Tests/EBAMRElliptic/exec/cond.inputs
+++ b/Tests/EBAMRElliptic/exec/cond.inputs
@@ -18,3 +18,6 @@ fill_ratio = 0.7
 buffer_size = 2

 which_geom = 5
+
+num_smooth = 4
+num_smooth_bottom = 27
diff --git a/Tests/EBAMRElliptic/exec/conductivitySolve.cpp b/Tests/EBAMRElliptic/exec/conductivitySolve.cpp
index e26d5240420..48d17ac5139 100644
--- a/Tests/EBAMRElliptic/exec/conductivitySolve.cpp
+++ b/Tests/EBAMRElliptic/exec/conductivitySolve.cpp
@@ -21,12 +21,14 @@
 #include "AMReX_SphereIF.H"
 #include "AMReX_EBDebugDump.H"
 #include "AMReX_MeshRefine.H"
-#include "AMReX_EBConducivityOp.H"
-#include "AMReX_EBConducivityOpFactory.H"
-#include "AMReX_DirichletConductivityEBBCFactory.H"
-#include "AMReX_DirichletConductivityDomainBCFactory.H"
-#include "AMReX_NeumannConductivityEBBCFactory.H"
-#include "AMReX_NeumannConductivityDomainBCFactory.H"
+#include "AMReX_EBConductivityOp.H"
+#include "AMReX_EBConductivityOpFactory.H"
+#include "AMReX_DirichletConductivityEBBC.H"
+#include "AMReX_DirichletConductivityDomainBC.H"
+#include "AMReX_NeumannConductivityEBBC.H"
+#include "AMReX_NeumannConductivityDomainBC.H"
+#include "AMReX_EBSimpleSolver.H"
+#include "AMReX_LinearSolver.H"

 namespace amrex
 {
@@ -151,14 +153,14 @@ namespace amrex
       amrex::Error("unknown domain_bc_type");
     }

-    if(ebbc_bc_type == 0)
+    if(eb_bc_type == 0)
     {
       pout() << "neumann eb bcs" << endl;
       NeumannConductivityEBBCFactory* neumptr = (new NeumannConductivityEBBCFactory());
       neumptr->setValue(0.);
       ebBCFact = shared_ptr<ConductivityBaseEBBCFactory>(static_cast<ConductivityBaseEBBCFactory*>(neumptr));
     }
-    else if(domain_bc_type == 1)
+    else if(eb_bc_type == 1)
     {
       int order_ebbc;
       pp.get("order_ebbc", order_ebbc);
@@ -180,6 +182,11 @@ namespace amrex
     vector<shared_ptr<FabArray<EBFluxFAB> > > bcoef(numLevels);
     for(int ilev = 0; ilev < numLevels; ilev++)
     {
+      const BoxArray           & ba = a_veblg[ilev].getDBL();
+      const DistributionMapping& dm = a_veblg[ilev].getDM();
+      EBCellFactory cellfact(a_veblg[ilev].getEBISL());
+      EBFluxFactory fluxfact(a_veblg[ilev].getEBISL());
+
       acoef[ilev] = shared_ptr<FabArray<EBCellFAB> >(new FabArray<EBCellFAB>(ba, dm, 1, 0, MFInfo(), cellfact));
       bcoef[ilev] = shared_ptr<FabArray<EBFluxFAB> >(new FabArray<EBFluxFAB>(ba, dm, 1, 0, MFInfo(), fluxfact));

@@ -189,7 +196,15 @@ namespace amrex

     EBConductivityOpFactory factory(a_veblg, alpha, beta, acoef, bcoef, a_params.coarsestDx, a_params.refRatio,
                                     domainBCFact, ebBCFact, a_nghost, a_nghost);
-    a_solver.define(a_params.coarsestDomain, factory, bottomSolverPtr, a_params.refRatio, enableLevelSolves, numLevels);
+
+    EBSimpleSolver* simple = new EBSimpleSolver();
+    int num_smooth_bottom = 10;
+    pp.query("num_smooth_bottom", num_smooth_bottom);
+    simple->setNumSmooths(num_smooth_bottom);
+    shared_ptr<LinearSolver<FabArray<EBCellFAB> > > bottomSolverPtr(static_cast<LinearSolver<FabArray<EBCellFAB> > *>(simple));
+
+    AMRLevelOpFactory<FabArray<EBCellFAB> >* factptr = static_cast<AMRLevelOpFactory<FabArray<EBCellFAB> >* >(&factory);
+    a_solver.define(a_params.coarsestDomain,*factptr, bottomSolverPtr, a_params.refRatio, enableLevelSolves, numLevels);
   }
   //----------------
   int conjuctionJunction()
@@ -228,7 +243,7 @@ namespace amrex

     solver.solve(phi, rhs, lbase, lmax);

-    writeEBPlotFile(string("phi.ebplt"), phi);
+//    writeEBPlotFile(string("phi.ebplt"), phi);

     return 0;
   }


Support prmtop files created by chamber (openmm/openmm#3416)

Support prmtop files created by chamber

Currently, prmtop files created using the CHAMBER tool are not supported in the software, which prevents users from utilizing these files for simulations. This limitation can be inconvenient for users who rely on CHAMBER-generated prmtop files as part of their workflows.

The expected behavior is that the software should support prmtop files created by CHAMBER, allowing users to load these files, create systems, and perform simulations without encountering errors. This enhancement would improve compatibility and provide a more seamless experience for users working with CHAMBER-generated files.

## IMPORTANT INSTRUCTIONS

1. If you edit a python file, you MUST run 'make PythonInstall' inside the build directory
2. If you edit a c++ file, you MUST run 'make -j4 && make install" inside the build directory

diff --git a/wrappers/python/openmm/app/amberprmtopfile.py b/wrappers/python/openmm/app/amberprmtopfile.py
index c8021ddb0e..5c6d280da3 100644
--- a/wrappers/python/openmm/app/amberprmtopfile.py
+++ b/wrappers/python/openmm/app/amberprmtopfile.py
@@ -6,7 +6,7 @@
 Biological Structures at Stanford, funded under the NIH Roadmap for
 Medical Research, grant U54 GM072970. See https://simtk.org.

-Portions copyright (c) 2012 Stanford University and the Authors.
+Portions copyright (c) 2012-2022 Stanford University and the Authors.
 Authors: Peter Eastman
 Contributors:

@@ -220,10 +220,6 @@ def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*u.nanome
         System
             the newly created System
         """
-        if self._prmtop.chamber:
-            raise ValueError("CHAMBER-style topology file detected. CHAMBER "
-                             "topologies are not supported -- use the native "
-                             "CHARMM files directly.")
         methodMap = {ff.NoCutoff:'NoCutoff',
                      ff.CutoffNonPeriodic:'CutoffNonPeriodic',
                      ff.CutoffPeriodic:'CutoffPeriodic',
diff --git a/wrappers/python/openmm/app/internal/amber_file_parser.py b/wrappers/python/openmm/app/internal/amber_file_parser.py
index 677cdb77c0..77a2f4d4bf 100644
--- a/wrappers/python/openmm/app/internal/amber_file_parser.py
+++ b/wrappers/python/openmm/app/internal/amber_file_parser.py
@@ -12,7 +12,7 @@
 Biological Structures at Stanford, funded under the NIH Roadmap for
 Medical Research, grant U54 GM072970. See https://simtk.org.

-Portions copyright (c) 2012-2014 Stanford University and the Authors.
+Portions copyright (c) 2012-2022 Stanford University and the Authors.
 Authors: Randall J. Radmer, John D. Chodera, Peter Eastman
 Contributors: Christoph Klein, Michael R. Shirts, Jason Swails, Kye Won Wang

@@ -42,7 +42,7 @@

 import os
 import re
-from math import ceil, cos, sin, asin, sqrt
+from math import ceil, cos, sin, asin, sqrt, pi
 import warnings

 try:
@@ -128,10 +128,6 @@ def __init__(self, inFilename):
                         tag, self._prmtopVersion = line.rstrip().split(None, 1)
                     elif line.startswith('%FLAG'):
                         tag, flag = line.rstrip().split(None, 1)
-                        if flag == 'CTITLE':
-                            raise TypeError('CHAMBER-style topology files are not supported here. '
-                                            'Consider using the CHARMM files directly with CharmmPsfFile '
-                                            'or ParmEd (where CHAMBER topologies are supported)')
                         self._flags.append(flag)
                         self._raw_data[flag] = []
                     elif line.startswith('%FORMAT'):
@@ -139,8 +135,12 @@ def __init__(self, inFilename):
                         index0=format.index('(')
                         index1=format.index(')')
                         format = format[index0+1:index1]
-                        m = FORMAT_RE_PATTERN.search(format)
-                        self._raw_format[self._flags[-1]] = (format, m.group(1), m.group(2), int(m.group(3)), m.group(4))
+                        try:
+                            m = FORMAT_RE_PATTERN.search(format)
+                            self._raw_format[self._flags[-1]] = (format, m.group(1), m.group(2), int(m.group(3)), m.group(4))
+                        except:
+                            # We couldn't parse the format, so just treat the whole line as a single string.
+                            self._raw_format[self._flags[-1]] = (format, 1, 'a', 80, '')
                     elif line.startswith('%COMMENT'):
                         continue
                 elif self._flags \
@@ -429,6 +429,30 @@ def getAngles(self):
                                 float(angleEquil[iType])))
         return self._angleList

+    def getUreyBradleys(self):
+        """Return list of atom pairs, K, and Rmin for each Urey-Bradley term"""
+        try:
+            return self._ureyBradleyList
+        except AttributeError:
+            pass
+        self._ureyBradleyList = []
+        if 'CHARMM_UREY_BRADLEY' in self._raw_data:
+            ureyBradleyPointers = self._raw_data["CHARMM_UREY_BRADLEY"]
+            forceConstant = self._raw_data["CHARMM_UREY_BRADLEY_FORCE_CONSTANT"]
+            equilValue = self._raw_data["CHARMM_UREY_BRADLEY_EQUIL_VALUE"]
+            forceConstConversionFactor = (units.kilocalorie_per_mole/(units.angstrom*units.angstrom)).conversion_factor_to(units.kilojoule_per_mole/(units.nanometer*units.nanometer))
+            lengthConversionFactor = units.angstrom.conversion_factor_to(units.nanometer)
+            for ii in range(0, len(ureyBradleyPointers), 3):
+                 if int(ureyBradleyPointers[ii]) < 0 or int(ureyBradleyPointers[ii+1]) < 0:
+                     raise Exception("Found negative Urey-Bradley atom pointers %s"
+                                     % ((ureyBradleyPointers[ii], ureyBradleyPointers[ii+1])))
+                 iType = int(ureyBradleyPointers[ii+2])-1
+                 self._ureyBradleyList.append((int(ureyBradleyPointers[ii])-1,
+                                    int(ureyBradleyPointers[ii+1])-1,
+                                    float(forceConstant[iType])*forceConstConversionFactor,
+                                    float(equilValue[iType])*lengthConversionFactor))
+        return self._ureyBradleyList
+
     def getDihedrals(self):
         """Return list of atom quads, K, phase and periodicity for each dihedral angle"""
         try:
@@ -459,14 +483,45 @@ def getDihedrals(self):
                                 int(0.5+float(periodicity[iType]))))
         return self._dihedralList

+    def getImpropers(self):
+        """Return list of atom quads, K, and phase for each improper torsion"""
+        try:
+            return self._improperList
+        except AttributeError:
+            pass
+        self._improperList = []
+        if 'CHARMM_IMPROPERS' in self._raw_data:
+            forceConstant = self._raw_data["CHARMM_IMPROPER_FORCE_CONSTANT"]
+            phase = self._raw_data["CHARMM_IMPROPER_PHASE"]
+            improperPointers = self._raw_data["CHARMM_IMPROPERS"]
+            forceConstConversionFactor = (units.kilocalorie_per_mole).conversion_factor_to(units.kilojoule_per_mole)
+            for ii in range(0,len(improperPointers),5):
+                 if int(improperPointers[ii])<0 or int(improperPointers[ii+1])<0:
+                     raise Exception("Found negative improper atom pointers %s"
+                                     % ((improperPointers[ii],
+                                        improperPointers[ii+1],
+                                        improperPointers[ii+2],
+                                        improperPointers[ii+3]),))
+                 iType = int(improperPointers[ii+4])-1
+                 self._improperList.append((int(improperPointers[ii])-1,
+                                    int(improperPointers[ii+1])-1,
+                                    abs(int(improperPointers[ii+2]))-1,
+                                    abs(int(improperPointers[ii+3]))-1,
+                                    float(forceConstant[iType])*forceConstConversionFactor,
+                                    float(phase[iType])))
+        return self._improperList
+
     def getNumMaps(self):
         """Return number of CMAPs. Return 0 if CMAP does not exist"""
         try:
             return self._numCMAP
         except AttributeError:
             pass
-        if "CMAP_COUNT" in self._raw_data.keys():
-            self._numCMAP=int(self._raw_data["CMAP_COUNT"][1])
+        flag = 'CMAP_COUNT'
+        if flag not in self._raw_data and self.chamber:
+            flag = 'CHARMM_CMAP_COUNT'
+        if flag in self._raw_data:
+            self._numCMAP = int(self._raw_data[flag][1])
             return self._numCMAP
         return 0

@@ -476,14 +531,19 @@ def getCMAPResolutions(self):
             return self._cmapResolution
         except AttributeError:
             pass
-        if "CMAP_RESOLUTION" in self._raw_data.keys():
-            self._cmapResolution=self._raw_data["CMAP_RESOLUTION"]
+        flag = 'CMAP_RESOLUTION'
+        if flag not in self._raw_data and self.chamber:
+            flag = 'CHARMM_CMAP_RESOLUTION'
+        if flag in self._raw_data:
+            self._cmapResolution=self._raw_data[flag]
             return self._cmapResolution
         return 0

     def getCMAPParameters(self, index):
         """Return list of CMAP energy values"""
-        flag="CMAP_PARAMETER_{:02d}".format(index)
+        flag = "CMAP_PARAMETER_{:02d}".format(index)
+        if flag not in self._raw_data and self.chamber:
+            flag = "CHARMM_CMAP_PARAMETER_{:02d}".format(index)
         return [float(pointer) for pointer in self._raw_data[flag]]

     def getCMAPDihedrals(self):
@@ -492,7 +552,10 @@ def getCMAPDihedrals(self):
             return self._cmapList
         except AttributeError:
             pass
-        cmapPointers = self._raw_data["CMAP_INDEX"]
+        flag = 'CMAP_INDEX'
+        if flag not in self._raw_data and self.chamber:
+            flag = 'CHARMM_CMAP_INDEX'
+        cmapPointers = self._raw_data[flag]
         self._cmapList=[]
         forceConstConversionFactor = (units.kilocalorie_per_mole).conversion_factor_to(units.kilojoule_per_mole)
         for ii in range(0,len(cmapPointers),6):
@@ -521,68 +584,45 @@ def get14Interactions(self):
                           +self._raw_data["DIHEDRALS_WITHOUT_HYDROGEN"]
         returnList=[]
         charges=self.getCharges()
-        try:
-            nonbondTerms = self.getNonbondTerms()
-        except NbfixPresent:
-            # We need to do the unit conversions here, since getNonbondTerms
-            # never finished and it has unit conversions in there
-            length_conv = units.angstrom.conversion_factor_to(units.nanometers)
-            ene_conv = units.kilocalories_per_mole.conversion_factor_to(
-                                units.kilojoules_per_mole)
+        length_conv = units.angstrom.conversion_factor_to(units.nanometers)
+        ene_conv = units.kilocalories_per_mole.conversion_factor_to(
+                            units.kilojoules_per_mole)
+        if self.chamber:
+            parm_acoef = [float(x) for x in self._raw_data['LENNARD_JONES_14_ACOEF']]
+            parm_bcoef = [float(x) for x in self._raw_data['LENNARD_JONES_14_BCOEF']]
+        else:
             parm_acoef = [float(x) for x in self._raw_data['LENNARD_JONES_ACOEF']]
             parm_bcoef = [float(x) for x in self._raw_data['LENNARD_JONES_BCOEF']]
-            nbidx = [int(x) for x in self._raw_data['NONBONDED_PARM_INDEX']]
-            numTypes = self.getNumTypes()
-            atomTypeIndexes=self._getAtomTypeIndexes()
-            for ii in range(0, len(dihedralPointers), 5):
-                if int(dihedralPointers[ii+2])>0 and int(dihedralPointers[ii+3])>0:
-                    iAtom = int(dihedralPointers[ii])//3
-                    lAtom = int(dihedralPointers[ii+3])//3
-                    iidx = int(dihedralPointers[ii+4]) - 1
-                    chargeProd = charges[iAtom]*charges[lAtom]
-                    typ1 = atomTypeIndexes[iAtom] - 1
-                    typ2 = atomTypeIndexes[lAtom] - 1
-                    idx = nbidx[numTypes*typ1+typ2] - 1
-                    if idx < 0: continue
-                    a = parm_acoef[idx]
-                    b = parm_bcoef[idx]
-                    try:
-                        epsilon = b * b / (4 * a) * ene_conv
-                        rMin = (2 * a / b) ** (1/6.0) * length_conv
-                    except ZeroDivisionError:
-                        rMin = 1
-                        epsilon = 0
-                    try:
-                        iScee = float(self._raw_data['SCEE_SCALE_FACTOR'][iidx])
-                    except KeyError:
-                        iScee = 1.2
-                    try:
-                        iScnb = float(self._raw_data['SCNB_SCALE_FACTOR'][iidx])
-                    except KeyError:
-                        iScnb = 2.0
-                    returnList.append((iAtom, lAtom, chargeProd, rMin, epsilon, iScee, iScnb))
-        else:
-            # This block gets hit if NbfixPresent is _not_ caught
-            for ii in range(0,len(dihedralPointers),5):
-                if int(dihedralPointers[ii+2])>0 and int(dihedralPointers[ii+3])>0:
-                    iAtom = int(dihedralPointers[ii])//3
-                    lAtom = int(dihedralPointers[ii+3])//3
-                    iidx = int(dihedralPointers[ii+4]) - 1
-                    chargeProd = charges[iAtom]*charges[lAtom]
-                    (rVdwI, epsilonI) = nonbondTerms[iAtom]
-                    (rVdwL, epsilonL) = nonbondTerms[lAtom]
-                    rMin = (rVdwI+rVdwL)
-                    epsilon = sqrt(epsilonI*epsilonL)
-                    try:
-                        iScee = float(self._raw_data["SCEE_SCALE_FACTOR"][iidx])
-                    except KeyError:
-                        iScee = 1.2
-                    try:
-                        iScnb = float(self._raw_data["SCNB_SCALE_FACTOR"][iidx])
-                    except KeyError:
-                        iScnb = 2.0
-
-                    returnList.append((iAtom, lAtom, chargeProd, rMin, epsilon, iScee, iScnb))
+        nbidx = [int(x) for x in self._raw_data['NONBONDED_PARM_INDEX']]
+        numTypes = self.getNumTypes()
+        atomTypeIndexes=self._getAtomTypeIndexes()
+        for ii in range(0, len(dihedralPointers), 5):
+            if int(dihedralPointers[ii+2])>0 and int(dihedralPointers[ii+3])>0:
+                iAtom = int(dihedralPointers[ii])//3
+                lAtom = int(dihedralPointers[ii+3])//3
+                iidx = int(dihedralPointers[ii+4]) - 1
+                chargeProd = charges[iAtom]*charges[lAtom]
+                typ1 = atomTypeIndexes[iAtom] - 1
+                typ2 = atomTypeIndexes[lAtom] - 1
+                idx = nbidx[numTypes*typ1+typ2] - 1
+                if idx < 0: continue
+                a = parm_acoef[idx]
+                b = parm_bcoef[idx]
+                try:
+                    epsilon = b * b / (4 * a) * ene_conv
+                    rMin = (2 * a / b) ** (1/6.0) * length_conv
+                except ZeroDivisionError:
+                    rMin = 1
+                    epsilon = 0
+                try:
+                    iScee = float(self._raw_data['SCEE_SCALE_FACTOR'][iidx])
+                except KeyError:
+                    iScee = 1.0 if self.chamber else 1.2
+                try:
+                    iScnb = float(self._raw_data['SCNB_SCALE_FACTOR'][iidx])
+                except KeyError:
+                    iScnb = 1.0 if self.chamber else 2.0
+                returnList.append((iAtom, lAtom, chargeProd, rMin, epsilon, iScee, iScnb))
         return returnList

     def getExcludedAtoms(self):
@@ -750,6 +790,15 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
         for (iAtom, jAtom, k, rMin) in prmtop.getBondsNoH():
             force.addBond(iAtom, jAtom, rMin, 2*k)
     system.addForce(force)
+
+    # Add Urey-Bradley terms.
+    if len(prmtop.getUreyBradleys()) > 0:
+        if verbose: print("Adding Urey-Bradley terms...")
+        force = mm.HarmonicBondForce()
+        force.setName('UreyBradleyForce')
+        for (iAtom, jAtom, k, rMin) in prmtop.getUreyBradleys():
+            force.addBond(iAtom, jAtom, rMin, 2*k)
+        system.addForce(force)

     # Add harmonic angles.
     if verbose: print("Adding angles...")
@@ -796,6 +845,17 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
         force.addTorsion(iAtom, jAtom, kAtom, lAtom, periodicity, phase, forceConstant)
     system.addForce(force)

+    # Add impropers.
+    if len(prmtop.getImpropers()) > 0:
+        if verbose: print("Adding impropers...")
+        force = mm.CustomTorsionForce(f'k*min(dtheta, 2*{pi}-dtheta)^2; dtheta = abs(theta-theta0)')
+        force.addPerTorsionParameter('k')
+        force.addPerTorsionParameter('theta0')
+        force.setName('ImproperTorsionForce')
+        for (iAtom, jAtom, kAtom, lAtom, forceConstant, phase) in prmtop.getImpropers():
+            force.addTorsion(iAtom, jAtom, kAtom, lAtom, (forceConstant, phase))
+        system.addForce(force)
+
     # Add CMAP info.
     ## Get mapSize and Resolutions
     numMap = prmtop.getNumMaps()

diff --git a/wrappers/python/tests/TestAmberPrmtopFile.py b/wrappers/python/tests/TestAmberPrmtopFile.py
index 1461e2a272..4473a2d86b 100644
--- a/wrappers/python/tests/TestAmberPrmtopFile.py
+++ b/wrappers/python/tests/TestAmberPrmtopFile.py
@@ -367,15 +367,31 @@ def test_with_dcd_reporter(self):
         os.remove(fname)

     def testChamber(self):
-        """ Tests that Chamber prmtops fail with proper error message """
-        self.assertRaises(TypeError, lambda: AmberPrmtopFile('systems/ala3_solv.parm7'))
-        try:
-            parm = AmberPrmtopFile('systems/ala3_solv.parm7')
-            # Should not make it past here
-            self.assertTrue(False)
-        except TypeError as e:
-            # Make sure it says something about chamber
-            self.assertTrue('chamber' in str(e).lower())
+        """Test a prmtop file created with Chamber."""
+        prmtop = AmberPrmtopFile('systems/ala3_solv.parm7')
+        crd = CharmmCrdFile('systems/ala3_solv.crd')
+        system = prmtop.createSystem()
+        for i,f in enumerate(system.getForces()):
+            f.setForceGroup(i)
+        integrator = VerletIntegrator(0.001)
+        context = Context(system, integrator, Platform.getPlatformByName('Reference'))
+        context.setPositions(crd.positions)
+
+        # Compare to energies computed with pytraj.energy_decomposition()
+
+        energy = context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
+        self.assertAlmostEqual(energy, -7806.981602, delta=5e-4*abs(energy))
+        components = {}
+        for i,f in enumerate(system.getForces()):
+            components[f.getName()] = context.getState(getEnergy=True, groups={i}).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
+        self.assertAlmostEqual(components['HarmonicBondForce'], 1.13242125)
+        self.assertAlmostEqual(components['HarmonicAngleForce'], 1.06880188)
+        self.assertAlmostEqual(components['UreyBradleyForce'], 0.06142407)
+        self.assertAlmostEqual(components['PeriodicTorsionForce'], 7.81143025)
+        self.assertAlmostEqual(components['ImproperTorsionForce'], 2.66453526e-14, delta=1e-6)
+        self.assertAlmostEqual(components['CMAPTorsionForce'], 0.12679003)
+        self.assertAlmostEqual(components['CustomNonbondedForce'], 909.28136359)
+        self.assertAlmostEqual(components['NonbondedForce'], -9007.16903192+277.35152722+3.35367163, delta=5e-4*abs(components['NonbondedForce']))

     def testGBneckRadii(self):
         """ Tests that GBneck radii limits are correctly enforced """