[cig-commits] commit: Change CellStokes* to Stokes* for filenames

Mercurial hg at geodynamics.org
Fri Feb 25 14:12:49 PST 2011


changeset:   13:fe2a9230921b
user:        Walter Landry <wlandry at caltech.edu>
date:        Fri Dec 31 12:10:26 2010 -0800
files:       CellStokesFACOps.C CellStokesFACOps.I CellStokesFACOps.h CellStokesFACSolver.C CellStokesFACSolver.I CellStokesFACSolver.h CellStokesHypreSolver.C CellStokesHypreSolver.I CellStokesHypreSolver.h FACStokes.h Makefile StokesFACOps.C StokesFACOps.I StokesFACOps.h StokesFACSolver.C StokesFACSolver.I StokesFACSolver.h StokesHypreSolver.C StokesHypreSolver.I StokesHypreSolver.h
description:
Change CellStokes* to Stokes* for filenames


diff -r a44a82f15794 -r fe2a9230921b CellStokesFACOps.C
--- a/CellStokesFACOps.C	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2830 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Operator class for cell-centered scalar Stokes using FAC 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesFACOps_C
-#define included_solv_CellStokesFACOps_C
-
-#include "CellStokesFACOps.h"
-
-#include IOMANIP_HEADER_FILE
-
-#include "SAMRAI/hier/BoundaryBoxUtils.h"
-#include "SAMRAI/geom/CartesianGridGeometry.h"
-#include "SAMRAI/geom/CartesianPatchGeometry.h"
-#include "SAMRAI/hier/Index.h"
-#include "SAMRAI/hier/Variable.h"
-#include "SAMRAI/hier/VariableDatabase.h"
-#include "SAMRAI/pdat/CellDoubleConstantRefine.h"
-#include "SAMRAI/pdat/CellVariable.h"
-#include "SAMRAI/pdat/OutersideData.h"
-#include "SAMRAI/pdat/OutersideVariable.h"
-#include "SAMRAI/hier/PatchData.h"
-#include "SAMRAI/pdat/SideVariable.h"
-#include "SAMRAI/solv/FACPreconditioner.h"
-#include "CellStokesHypreSolver.h"
-#include "SAMRAI/tbox/Array.h"
-#include "SAMRAI/tbox/MathUtilities.h"
-#include "SAMRAI/tbox/StartupShutdownManager.h"
-#include "SAMRAI/tbox/Timer.h"
-#include "SAMRAI/tbox/TimerManager.h"
-#include "SAMRAI/tbox/Utilities.h"
-#include "SAMRAI/tbox/MathUtilities.h"
-#include "SAMRAI/xfer/CoarsenAlgorithm.h"
-#include "SAMRAI/xfer/CoarsenOperator.h"
-#include "SAMRAI/xfer/CoarsenSchedule.h"
-#include "SAMRAI/xfer/RefineAlgorithm.h"
-#include "SAMRAI/xfer/RefineOperator.h"
-#include "SAMRAI/xfer/RefineSchedule.h"
-#include "SAMRAI/xfer/PatchLevelFullFillPattern.h"
-
-#ifndef SAMRAI_INLINE
-#include "CellStokesFACOps.I"
-#endif
-
-namespace SAMRAI {
-namespace solv {
-
-tbox::Pointer<pdat::CellVariable<double> >
-CellStokesFACOps::s_cell_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-tbox::Pointer<pdat::SideVariable<double> >
-CellStokesFACOps::s_flux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-tbox::Pointer<pdat::OutersideVariable<double> >
-CellStokesFACOps::s_oflux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-tbox::StartupShutdownManager::Handler
-CellStokesFACOps::s_finalize_handler(
-   0,
-   0,
-   0,
-   CellStokesFACOps::finalizeCallback,
-   tbox::StartupShutdownManager::priorityVariables);
-
-extern "C" {
-
-#ifdef __INTEL_COMPILER
-#pragma warning (disable:1419)
-#endif
-
-void F77_FUNC(compfluxvardc2d, COMPFLUXVARDC2D) (
-   double* xflux,
-   double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx);
-void F77_FUNC(compfluxcondc2d, COMPFLUXCONDC2D) (
-   double* xflux,
-   double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double & diff_coef,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx);
-void F77_FUNC(rbgswithfluxmaxvardcvarsf2d, RBGSWITHFLUXMAXVARDCVARSF2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxcondcvarsf2d, RBGSWITHFLUXMAXCONDCVARSF2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double & dc,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const double & scalar_field,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double & dc,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const double & scalar_field,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(compresvarsca2d, COMPRESVARSCA2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   double* residual,
-   const int* residualgi,
-   const int* residualgj,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx);
-void F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   double* residual,
-   const int* residualgi,
-   const int* residualgj,
-   const double & scalar_field,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* dx);
-void F77_FUNC(ewingfixfluxvardc2d, EWINGFIXFLUXVARDC2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* location_index,
-   const int* ratio_to_coarser,
-   const int* blower,
-   const int* bupper,
-   const double* dx);
-void F77_FUNC(ewingfixfluxcondc2d, EWINGFIXFLUXCONDC2D) (
-   const double* xflux,
-   const double* yflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const double & diff_coef,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* location_index,
-   const int* ratio_to_coarser,
-   const int* blower,
-   const int* bupper,
-   const double* dx);
-
-void F77_FUNC(compfluxvardc3d, COMPFLUXVARDC3D) (
-   double* xflux,
-   double* yflux,
-   double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const double* zdiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const int* dcgk,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx);
-void F77_FUNC(compfluxcondc3d, COMPFLUXCONDC3D) (
-   double* xflux,
-   double* yflux,
-   double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double & diff_coef,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx);
-void F77_FUNC(rbgswithfluxmaxvardcvarsf3d, RBGSWITHFLUXMAXVARDCVARSF3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const double* zdiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const int* dcgk,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   const int* scalar_field_gk,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxcondcvarsf3d, RBGSWITHFLUXMAXCONDCVARSF3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double & dc,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   const int* scalar_field_gk,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const double* zdiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const int* dcgk,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   const double & scalar_field,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double & dc,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   const double & scalar_field,
-   double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx,
-   const int* offset,
-   const double* maxres);
-void F77_FUNC(compresvarsca3d, COMPRESVARSCA3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   double* residual,
-   const int* residualgi,
-   const int* residualgj,
-   const int* residualgk,
-   const double* scalar_field,
-   const int* scalar_field_gi,
-   const int* scalar_field_gj,
-   const int* scalar_field_gk,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx);
-void F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* rhs,
-   const int* rhsgi,
-   const int* rhsgj,
-   const int* rhsgk,
-   double* residual,
-   const int* residualgi,
-   const int* residualgj,
-   const int* residualgk,
-   const double & scalar_field,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* dx);
-void F77_FUNC(ewingfixfluxvardc3d, EWINGFIXFLUXVARDC3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double* xdiff_coef,
-   const double* ydiff_coef,
-   const double* zdiff_coef,
-   const int* dcgi,
-   const int* dcgj,
-   const int* dcgk,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const int* location_index,
-   const int* ratio_to_coarser,
-   const int* blower,
-   const int* bupper,
-   const double* dx);
-void F77_FUNC(ewingfixfluxcondc3d, EWINGFIXFLUXCONDC3D) (
-   const double* xflux,
-   const double* yflux,
-   const double* zflux,
-   const int* fluxgi,
-   const int* fluxgj,
-   const int* fluxgk,
-   const double & diff_coef,
-   const double* soln,
-   const int* solngi,
-   const int* solngj,
-   const int* solngk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const int* location_index,
-   const int* ratio_to_coarser,
-   const int* blower,
-   const int* bupper,
-   const double* dx);
-
-}
-
-/*
- ********************************************************************
- * Constructor.                                                     *
- ********************************************************************
- */
-CellStokesFACOps::CellStokesFACOps(
-   const tbox::Dimension& dim,
-   const std::string& object_name,
-   tbox::Pointer<tbox::Database> database):
-   d_dim(dim),
-   d_object_name(object_name),
-   d_hierarchy(),
-   d_ln_min(-1),
-   d_ln_max(-1),
-   d_cf_boundary(),
-   d_stokes_spec(object_name + "::Stokes specs"),
-   d_smoothing_choice("redblack"),
-   d_coarse_solver_choice(
-#ifdef HAVE_HYPRE
-      "hypre"
-#else
-      "redblack"
-#endif
-
-      ),
-   d_cf_discretization("Ewing"),
-   d_prolongation_method("CONSTANT_REFINE"),
-   d_coarse_solver_tolerance(1.e-8),
-   d_coarse_solver_max_iterations(10),
-   d_residual_tolerance_during_smoothing(-1.0),
-   d_flux_id(-1),
-#ifdef HAVE_HYPRE
-   d_hypre_solver(dim,
-                  object_name + "::hypre_solver",
-                  database && database->isDatabase("hypre_solver") ?
-                  database->getDatabase("hypre_solver"):
-                     tbox::Pointer<tbox::Database>(NULL)),
-#endif
-   d_physical_bc_coef(NULL),
-   d_context(hier::VariableDatabase::getDatabase()
-             ->getContext(object_name + "::PRIVATE_CONTEXT")),
-   d_cell_scratch_id(-1),
-   d_flux_scratch_id(-1),
-   d_oflux_scratch_id(-1),
-   d_prolongation_refine_operator(),
-   d_prolongation_refine_algorithm(),
-   d_prolongation_refine_schedules(),
-   d_urestriction_coarsen_operator(),
-   d_urestriction_coarsen_algorithm(),
-   d_urestriction_coarsen_schedules(),
-   d_rrestriction_coarsen_operator(),
-   d_rrestriction_coarsen_algorithm(),
-   d_rrestriction_coarsen_schedules(),
-   d_flux_coarsen_operator(),
-   d_flux_coarsen_algorithm(),
-   d_flux_coarsen_schedules(),
-   d_ghostfill_refine_operator(),
-   d_ghostfill_refine_algorithm(),
-   d_ghostfill_refine_schedules(),
-   d_ghostfill_nocoarse_refine_operator(),
-   d_ghostfill_nocoarse_refine_algorithm(),
-   d_ghostfill_nocoarse_refine_schedules(),
-   d_bc_helper(dim,
-               d_object_name + "::bc helper"),
-   d_enable_logging(false),
-   d_preconditioner(NULL),
-   d_hopscell(),
-   d_hopsside()
-{
-
-   t_restrict_solution = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::restrictSolution()");
-   t_restrict_residual = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::restrictResidual()");
-   t_prolong = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::prolongErrorAndCorrect()");
-   t_smooth_error = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::smoothError()");
-   t_solve_coarsest = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::solveCoarsestLevel()");
-   t_compute_composite_residual = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::computeCompositeResidualOnLevel()");
-   t_compute_residual_norm = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesFACOps::computeResidualNorm()");
-
-   if (d_dim == tbox::Dimension(1) || d_dim > tbox::Dimension(3)) {
-      TBOX_ERROR("CellStokesFACOps : DIM == 1 or > 3 not implemented yet.\n");
-   }
-
-   if (s_cell_scratch_var[dim.getValue() - 1].isNull()) {
-      TBOX_ASSERT(s_cell_scratch_var[dim.getValue() - 1].isNull());
-      TBOX_ASSERT(s_cell_scratch_var[dim.getValue() - 1].isNull());
-
-      std::ostringstream ss;
-      ss << "CellStokesFACOps::private_cell_scratch" << dim.getValue();
-      s_cell_scratch_var[dim.getValue() - 1] = new pdat::CellVariable<double>
-            (dim, ss.str());
-      ss.str("");
-      ss << "CellStokesFACOps::private_flux_scratch" << dim.getValue();
-      s_flux_scratch_var[dim.getValue() - 1] = new pdat::SideVariable<double>
-            (dim, ss.str());
-      ss.str("");
-      ss << "CellStokesFACOps::private_oflux_scratch" << dim.getValue();
-      s_oflux_scratch_var[dim.getValue() - 1] = new pdat::OutersideVariable<double>
-            (dim, ss.str());
-   }
-
-   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
-   d_cell_scratch_id = vdb->
-      registerVariableAndContext(s_cell_scratch_var[dim.getValue() - 1],
-         d_context,
-         hier::IntVector::getOne(dim));
-   d_flux_scratch_id = vdb->
-      registerVariableAndContext(s_flux_scratch_var[dim.getValue() - 1],
-         d_context,
-         hier::IntVector::getZero(d_dim));
-   d_oflux_scratch_id = vdb->
-      registerVariableAndContext(s_oflux_scratch_var[dim.getValue() - 1],
-         d_context,
-         hier::IntVector::getZero(d_dim));
-
-   /*
-    * Some variables initialized by default are overriden by input.
-    */
-   if (database) {
-
-      d_coarse_solver_choice =
-         database->getStringWithDefault("coarse_solver_choice",
-            d_coarse_solver_choice);
-      d_coarse_solver_tolerance =
-         database->getDoubleWithDefault("coarse_solver_tolerance",
-            d_coarse_solver_tolerance);
-      d_coarse_solver_max_iterations =
-         database->getIntegerWithDefault("coarse_solver_max_iterations",
-            d_coarse_solver_max_iterations);
-      d_smoothing_choice =
-         database->getStringWithDefault("smoothing_choice",
-            d_smoothing_choice);
-
-      d_cf_discretization =
-         database->getStringWithDefault("cf_discretization",
-            d_cf_discretization);
-
-      d_prolongation_method =
-         database->getStringWithDefault("prolongation_method",
-            d_prolongation_method);
-
-      d_enable_logging =
-         database->getBoolWithDefault("enable_logging",
-            d_enable_logging);
-
-   }
-
-   /*
-    * Check input validity and correctness.
-    */
-   checkInputPatchDataIndices();
-
-}
-
-CellStokesFACOps::~CellStokesFACOps(
-   void)
-{
-}
-
-/*
- ************************************************************************
- * FACOperatorStrategy virtual initializeOperatorState function.  *
- *                                                                      *
- * Set internal variables to correspond to the solution passed in.      *
- * Look up transfer operators.                                          *
- ************************************************************************
- */
-
-void CellStokesFACOps::initializeOperatorState(
-   const SAMRAIVectorReal<double>& solution,
-   const SAMRAIVectorReal<double>& rhs)
-{
-   deallocateOperatorState();
-   int ln;
-   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
-
-   d_hierarchy = solution.getPatchHierarchy();
-   d_ln_min = solution.getCoarsestLevelNumber();
-   d_ln_max = solution.getFinestLevelNumber();
-   d_hopscell = new math::HierarchyCellDataOpsReal<double>(d_hierarchy,
-                                                           d_ln_min,
-                                                           d_ln_max);
-   d_hopsside = new math::HierarchySideDataOpsReal<double>(d_hierarchy,
-                                                           d_ln_min,
-                                                           d_ln_max);
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-
-   if (d_physical_bc_coef == NULL) {
-      /*
-       * It's an error not to have bc object set.
-       * Note that the bc object cannot be passed in through
-       * the argument because the interface is inherited.
-       */
-      TBOX_ERROR(
-         d_object_name << ": No physical bc object in\n"
-         <<
-         "CellStokesFACOps::initializeOperatorState\n"
-         << "You must use "
-         <<
-         "CellStokesFACOps::setPhysicalBcCoefObject\n"
-         <<
-         "to set one before calling initializeOperatorState\n");
-   }
-
-   if (solution.getNumberOfComponents() != 1) {
-      TBOX_WARNING(d_object_name
-         << ": Solution vector has multiple components.\n"
-         << "Solver is for component 0 only.\n");
-   }
-   if (rhs.getNumberOfComponents() != 1) {
-      TBOX_WARNING(d_object_name
-         << ": RHS vector has multiple components.\n"
-         << "Solver is for component 0 only.\n");
-   }
-
-   /*
-    * Make sure that solution and rhs data
-    *   are of correct type
-    *   are allocated
-    *   has sufficient ghost width
-    */
-   tbox::Pointer<hier::Variable> var;
-   {
-      vdb->mapIndexToVariable(rhs.getComponentDescriptorIndex(0),
-         var);
-      if (!var) {
-         TBOX_ERROR(d_object_name << ": RHS component does not\n"
-                                  << "correspond to a variable.\n");
-      }
-      tbox::Pointer<pdat::CellVariable<double> > cell_var = var;
-      if (!cell_var) {
-         TBOX_ERROR(d_object_name
-            << ": RHS variable is not cell-centered double\n");
-      }
-   }
-   {
-      vdb->mapIndexToVariable(solution.getComponentDescriptorIndex(0),
-         var);
-      if (!var) {
-         TBOX_ERROR(d_object_name << ": Solution component does not\n"
-                                  << "correspond to a variable.\n");
-      }
-      tbox::Pointer<pdat::CellVariable<double> > cell_var = var;
-      if (!cell_var) {
-         TBOX_ERROR(d_object_name
-            << ": Solution variable is not cell-centered double\n");
-      }
-   }
-   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
-      tbox::Pointer<hier::PatchLevel> level_ptr =
-         d_hierarchy->getPatchLevel(ln);
-      hier::PatchLevel& level = *level_ptr;
-      for (hier::PatchLevel::Iterator pi(level); pi; pi++) {
-         hier::Patch& patch = **pi;
-         tbox::Pointer<hier::PatchData> fd =
-            patch.getPatchData(rhs.getComponentDescriptorIndex(0));
-         if (fd) {
-            /*
-             * Some data checks can only be done if the data already exists.
-             */
-            tbox::Pointer<pdat::CellData<double> > cd = fd;
-            if (!cd) {
-               TBOX_ERROR(d_object_name
-                  << ": RHS data is not cell-centered double\n");
-            }
-            if (cd->getDepth() > 1) {
-               TBOX_WARNING(d_object_name
-                  << ": RHS data has multiple depths.\n"
-                  << "Solver is for depth 0 only.\n");
-            }
-         }
-         tbox::Pointer<hier::PatchData> ud =
-            patch.getPatchData(solution.getComponentDescriptorIndex(0));
-         if (ud) {
-            /*
-             * Some data checks can only be done if the data already exists.
-             */
-            tbox::Pointer<pdat::CellData<double> > cd = ud;
-            if (!cd) {
-               TBOX_ERROR(d_object_name
-                  << ": Solution data is not cell-centered double\n");
-            }
-            if (cd->getDepth() > 1) {
-               TBOX_WARNING(d_object_name
-                  << ": Solution data has multiple depths.\n"
-                  << "Solver is for depth 0 only.\n");
-            }
-            if (cd->getGhostCellWidth() < hier::IntVector::getOne(d_dim)) {
-               TBOX_ERROR(d_object_name
-                  << ": Solution data has insufficient ghost width\n");
-            }
-         }
-      }
-   }
-
-   /*
-    * Solution and rhs must have some similar properties.
-    */
-   if (rhs.getPatchHierarchy() != d_hierarchy
-       || rhs.getCoarsestLevelNumber() != d_ln_min
-       || rhs.getFinestLevelNumber() != d_ln_max) {
-      TBOX_ERROR(d_object_name << ": solution and rhs do not have\n"
-                               << "the same set of patch levels.\n");
-   }
-
-#endif
-
-   /*
-    * Initialize the coarse-fine boundary description for the
-    * hierarchy.
-    */
-   d_cf_boundary.resizeArray(d_hierarchy->getNumberOfLevels());
-
-   hier::IntVector max_gcw(d_dim, 1);
-   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
-      d_cf_boundary[ln] = new hier::CoarseFineBoundary(*d_hierarchy,
-                                                       ln,
-                                                       max_gcw);
-   }
-#ifdef HAVE_HYPRE
-   if (d_coarse_solver_choice == "hypre") {
-      d_hypre_solver.initializeSolverState(d_hierarchy, d_ln_min);
-      /*
-       * Share the boundary condition object with the hypre solver
-       * to make sure that boundary condition settings are consistent
-       * between the two objects.
-       */
-      d_hypre_solver.setPhysicalBcCoefObject(d_physical_bc_coef);
-      d_hypre_solver.setMatrixCoefficients(d_stokes_spec);
-   }
-#endif
-
-   /*
-    * Get the transfer operators.
-    * Flux coarsening is conservative.
-    * Cell (solution, error, etc) coarsening is conservative.
-    * Cell refinement from same level is constant refinement.
-    * Cell refinement from coarser level is chosen by the
-    *   choice of coarse-fine discretization, d_cf_discretization,
-    *   which should be set to either "Ewing" or one of the
-    *   acceptable strings for looking up the refine operator.
-    */
-   tbox::Pointer<geom::CartesianGridGeometry> geometry =
-      d_hierarchy->getGridGeometry();
-   tbox::Pointer<hier::Variable> variable;
-
-   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
-   d_prolongation_refine_operator =
-      geometry->lookupRefineOperator(variable,
-         d_prolongation_method);
-
-   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
-   d_urestriction_coarsen_operator =
-      d_rrestriction_coarsen_operator =
-         geometry->lookupCoarsenOperator(variable,
-            "CONSERVATIVE_COARSEN");
-
-   vdb->mapIndexToVariable(d_oflux_scratch_id, variable);
-   d_flux_coarsen_operator =
-      geometry->lookupCoarsenOperator(variable,
-         "CONSERVATIVE_COARSEN");
-
-   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
-   d_ghostfill_refine_operator =
-      geometry->lookupRefineOperator(variable,
-         d_cf_discretization == "Ewing" ?
-         "CONSTANT_REFINE" : d_cf_discretization);
-
-   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
-   d_ghostfill_nocoarse_refine_operator =
-      geometry->lookupRefineOperator(variable,
-         "CONSTANT_REFINE");
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (!d_prolongation_refine_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find prolongation refine operator");
-   }
-   if (!d_urestriction_coarsen_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find restriction coarsening operator");
-   }
-   if (!d_rrestriction_coarsen_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find restriction coarsening operator");
-   }
-   if (!d_flux_coarsen_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find flux coarsening operator");
-   }
-   if (!d_ghostfill_refine_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find ghost filling refinement operator");
-   }
-   if (!d_ghostfill_nocoarse_refine_operator) {
-      TBOX_ERROR(d_object_name
-         << ": Cannot find ghost filling refinement operator");
-   }
-#endif
-
-   for (ln = d_ln_min + 1; ln <= d_ln_max; ++ln) {
-      d_hierarchy->getPatchLevel(ln)->
-      allocatePatchData(d_oflux_scratch_id);
-   }
-
-   /*
-    * Make space for saving communication schedules.
-    * There is no need to delete the old schedules first
-    * because we have deallocated the solver state above.
-    */
-   d_prolongation_refine_schedules.resizeArray(d_ln_max + 1);
-   d_ghostfill_refine_schedules.resizeArray(d_ln_max + 1);
-   d_ghostfill_nocoarse_refine_schedules.resizeArray(d_ln_max + 1);
-   d_urestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
-   d_rrestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
-   d_flux_coarsen_schedules.resizeArray(d_ln_max + 1);
-
-   d_prolongation_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
-   d_urestriction_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
-   d_rrestriction_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
-   d_flux_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
-   d_ghostfill_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
-   d_ghostfill_nocoarse_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
-
-   d_prolongation_refine_algorithm->
-   registerRefine(d_cell_scratch_id,
-      solution.getComponentDescriptorIndex(0),
-      d_cell_scratch_id,
-      d_prolongation_refine_operator);
-   d_urestriction_coarsen_algorithm->
-   registerCoarsen(solution.getComponentDescriptorIndex(0),
-      solution.getComponentDescriptorIndex(0),
-      d_urestriction_coarsen_operator);
-   d_rrestriction_coarsen_algorithm->
-   registerCoarsen(rhs.getComponentDescriptorIndex(0),
-      rhs.getComponentDescriptorIndex(0),
-      d_rrestriction_coarsen_operator);
-   d_ghostfill_refine_algorithm->
-   registerRefine(solution.getComponentDescriptorIndex(0),
-      solution.getComponentDescriptorIndex(0),
-      solution.getComponentDescriptorIndex(0),
-      d_ghostfill_refine_operator);
-   d_flux_coarsen_algorithm->
-   registerCoarsen(((d_flux_id != -1) ? d_flux_id : d_flux_scratch_id),
-      d_oflux_scratch_id,
-      d_flux_coarsen_operator);
-   d_ghostfill_nocoarse_refine_algorithm->
-   registerRefine(solution.getComponentDescriptorIndex(0),
-      solution.getComponentDescriptorIndex(0),
-      solution.getComponentDescriptorIndex(0),
-      d_ghostfill_nocoarse_refine_operator);
-
-   for (int dest_ln = d_ln_min + 1; dest_ln <= d_ln_max; ++dest_ln) {
-
-      tbox::Pointer<xfer::PatchLevelFullFillPattern> fill_pattern(
-         new xfer::PatchLevelFullFillPattern());
-      d_prolongation_refine_schedules[dest_ln] =
-         d_prolongation_refine_algorithm->
-         createSchedule(fill_pattern,
-            d_hierarchy->getPatchLevel(dest_ln),
-            tbox::Pointer<hier::PatchLevel>(),
-            dest_ln - 1,
-            d_hierarchy,
-            &d_bc_helper);
-      if (!d_prolongation_refine_schedules[dest_ln]) {
-         TBOX_ERROR(d_object_name
-            << ": Cannot create a refine schedule for prolongation!\n");
-      }
-      d_ghostfill_refine_schedules[dest_ln] =
-         d_ghostfill_refine_algorithm->
-         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
-            dest_ln - 1,
-            d_hierarchy,
-            &d_bc_helper);
-      if (!d_ghostfill_refine_schedules[dest_ln]) {
-         TBOX_ERROR(d_object_name
-            << ": Cannot create a refine schedule for ghost filling!\n");
-      }
-      d_ghostfill_nocoarse_refine_schedules[dest_ln] =
-         d_ghostfill_nocoarse_refine_algorithm->
-         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
-            &d_bc_helper);
-      if (!d_ghostfill_nocoarse_refine_schedules[dest_ln]) {
-         TBOX_ERROR(
-            d_object_name
-            <<
-            ": Cannot create a refine schedule for ghost filling on bottom level!\n");
-      }
-   }
-   for (int dest_ln = d_ln_min; dest_ln < d_ln_max; ++dest_ln) {
-      d_urestriction_coarsen_schedules[dest_ln] =
-         d_urestriction_coarsen_algorithm->
-         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
-            d_hierarchy->getPatchLevel(dest_ln + 1));
-      if (!d_urestriction_coarsen_schedules[dest_ln]) {
-         TBOX_ERROR(d_object_name
-            << ": Cannot create a coarsen schedule for U restriction!\n");
-      }
-      d_rrestriction_coarsen_schedules[dest_ln] =
-         d_rrestriction_coarsen_algorithm->
-         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
-            d_hierarchy->getPatchLevel(dest_ln + 1));
-      if (!d_rrestriction_coarsen_schedules[dest_ln]) {
-         TBOX_ERROR(d_object_name
-            << ": Cannot create a coarsen schedule for R restriction!\n");
-      }
-      d_flux_coarsen_schedules[dest_ln] =
-         d_flux_coarsen_algorithm->
-         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
-            d_hierarchy->getPatchLevel(dest_ln + 1));
-      if (!d_flux_coarsen_schedules[dest_ln]) {
-         TBOX_ERROR(d_object_name
-            << ": Cannot create a coarsen schedule for flux transfer!\n");
-      }
-   }
-   d_ghostfill_nocoarse_refine_schedules[d_ln_min] =
-      d_ghostfill_nocoarse_refine_algorithm->
-      createSchedule(d_hierarchy->getPatchLevel(d_ln_min),
-         &d_bc_helper);
-   if (!d_ghostfill_nocoarse_refine_schedules[d_ln_min]) {
-      TBOX_ERROR(
-         d_object_name
-         <<
-         ": Cannot create a refine schedule for ghost filling on bottom level!\n");
-   }
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual deallocateOperatorState        *
- * function.  Deallocate internal hierarchy-dependent data.         *
- * State is allocated iff hierarchy is set.                         *
- ********************************************************************
- */
-
-void CellStokesFACOps::deallocateOperatorState()
-{
-   if (d_hierarchy) {
-      int ln;
-      for (ln = d_ln_min + 1; ln <= d_ln_max; ++ln) {
-         d_hierarchy->getPatchLevel(ln)->
-         deallocatePatchData(d_oflux_scratch_id);
-      }
-      d_cf_boundary.resizeArray(0);
-#ifdef HAVE_HYPRE
-      d_hypre_solver.deallocateSolverState();
-#endif
-      d_hierarchy.setNull();
-      d_ln_min = -1;
-      d_ln_max = -1;
-
-      d_prolongation_refine_algorithm.setNull();
-      d_prolongation_refine_schedules.setNull();
-
-      d_urestriction_coarsen_algorithm.setNull();
-      d_urestriction_coarsen_schedules.setNull();
-
-      d_rrestriction_coarsen_algorithm.setNull();
-      d_rrestriction_coarsen_schedules.setNull();
-
-      d_flux_coarsen_algorithm.setNull();
-      d_flux_coarsen_schedules.setNull();
-
-      d_ghostfill_refine_algorithm.setNull();
-      d_ghostfill_refine_schedules.setNull();
-
-      d_ghostfill_nocoarse_refine_algorithm.setNull();
-      d_ghostfill_nocoarse_refine_schedules.setNull();
-
-   }
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual postprocessOneCycle function.  *
- ********************************************************************
- */
-
-void CellStokesFACOps::postprocessOneCycle(
-   int fac_cycle_num,
-   const SAMRAIVectorReal<double>& current_soln,
-   const SAMRAIVectorReal<double>& residual)
-{
-   NULL_USE(current_soln);
-   NULL_USE(residual);
-
-   if (d_enable_logging) {
-      if (d_preconditioner) {
-         /*
-          * Output convergence progress.  This is probably only appropriate
-          * if the solver is NOT being used as a preconditioner.
-          */
-         double avg_factor, final_factor;
-         d_preconditioner->getConvergenceFactors(avg_factor, final_factor);
-         tbox::plog
-         << "iter=" << std::setw(4) << fac_cycle_num
-         << " resid=" << d_preconditioner->getResidualNorm()
-         << " net conv=" << d_preconditioner->getNetConvergenceFactor()
-         << " final conv=" << d_preconditioner->getNetConvergenceFactor()
-         << " avg conv=" << d_preconditioner->getAvgConvergenceFactor()
-         << std::endl;
-      }
-   }
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual restrictSolution function.     *
- * After restricting solution, update ghost cells of the affected   *
- * level.                                                           *
- ********************************************************************
- */
-
-void CellStokesFACOps::restrictSolution(
-   const SAMRAIVectorReal<double>& s,
-   SAMRAIVectorReal<double>& d,
-   int dest_ln) {
-
-   t_restrict_solution->start();
-
-   xeqScheduleURestriction(d.getComponentDescriptorIndex(0),
-      s.getComponentDescriptorIndex(0),
-      dest_ln);
-
-   d_bc_helper.setHomogeneousBc(false);
-   d_bc_helper.setTargetDataId(d.getComponentDescriptorIndex(0));
-
-   if (dest_ln == d_ln_min) {
-      xeqScheduleGhostFillNoCoarse(d.getComponentDescriptorIndex(0),
-         dest_ln);
-   } else {
-      xeqScheduleGhostFill(d.getComponentDescriptorIndex(0),
-         dest_ln);
-   }
-
-   t_restrict_solution->stop();
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual restrictresidual function.     *
- ********************************************************************
- */
-
-void CellStokesFACOps::restrictResidual(
-   const SAMRAIVectorReal<double>& s,
-   SAMRAIVectorReal<double>& d,
-   int dest_ln) {
-
-   t_restrict_residual->start();
-
-   xeqScheduleRRestriction(d.getComponentDescriptorIndex(0),
-      s.getComponentDescriptorIndex(0),
-      dest_ln);
-
-   t_restrict_residual->stop();
-}
-
-/*
- ***********************************************************************
- * FACOperatorStrategy virtual prolongErrorAndCorrect function.  *
- * After the prolongation, we set the physical boundary condition      *
- * for the correction, which is zero.  Other ghost cell values,        *
- * which are preset to zero, need not be set.                          *
- ***********************************************************************
- */
-
-void CellStokesFACOps::prolongErrorAndCorrect(
-   const SAMRAIVectorReal<double>& s,
-   SAMRAIVectorReal<double>& d,
-   int dest_ln) {
-
-   t_prolong->start();
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (s.getPatchHierarchy() != d_hierarchy
-       || d.getPatchHierarchy() != d_hierarchy) {
-      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
-         "internal state hierarchy.");
-   }
-#endif
-
-   tbox::Pointer<hier::PatchLevel> coarse_level =
-      d_hierarchy->getPatchLevel(dest_ln - 1);
-   tbox::Pointer<hier::PatchLevel> fine_level =
-      d_hierarchy->getPatchLevel(dest_ln);
-
-   /*
-    * Data is prolonged into the scratch space corresponding
-    * to index d_cell_scratch_id and allocated here.
-    */
-   fine_level->allocatePatchData(d_cell_scratch_id);
-
-   /*
-    * Refine solution into scratch space to fill the fine level
-    * interior in the scratch space, then use that refined data
-    * to correct the fine level error.
-    */
-   d_bc_helper.setTargetDataId(d_cell_scratch_id);
-   d_bc_helper.setHomogeneousBc(true);
-   const int src_index = s.getComponentDescriptorIndex(0);
-   xeqScheduleProlongation(d_cell_scratch_id,
-      src_index,
-      d_cell_scratch_id,
-      dest_ln);
-
-   /*
-    * Add the refined error in the scratch space
-    * to the error currently residing in the destination level.
-    */
-   math::HierarchyCellDataOpsReal<double>
-   hierarchy_math_ops(d_hierarchy, dest_ln, dest_ln);
-   const int dst_index = d.getComponentDescriptorIndex(0);
-   hierarchy_math_ops.add(dst_index, dst_index, d_cell_scratch_id);
-
-   fine_level->deallocatePatchData(d_cell_scratch_id);
-
-   t_prolong->stop();
-
-}
-
-/*
- ********************************************************************
- ********************************************************************
- */
-
-void CellStokesFACOps::smoothError(
-   SAMRAIVectorReal<double>& data,
-   const SAMRAIVectorReal<double>& residual,
-   int ln,
-   int num_sweeps)
-{
-
-   t_smooth_error->start();
-
-   checkInputPatchDataIndices();
-   if (d_smoothing_choice == "redblack") {
-      smoothErrorByRedBlack(data,
-         residual,
-         ln,
-         num_sweeps,
-         d_residual_tolerance_during_smoothing);
-   } else {
-      TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
-                               << d_smoothing_choice
-                               << "' in CellStokesFACOps.");
-   }
-
-   t_smooth_error->stop();
-}
-
-/*
- ********************************************************************
- * Workhorse function to smooth error using red-black               *
- * Gauss-Seidel iterations.                                         *
- ********************************************************************
- */
-
-void CellStokesFACOps::smoothErrorByRedBlack(
-   SAMRAIVectorReal<double>& data,
-   const SAMRAIVectorReal<double>& residual,
-   int ln,
-   int num_sweeps,
-   double residual_tolerance)
-{
-
-   checkInputPatchDataIndices();
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (data.getPatchHierarchy() != d_hierarchy
-       || residual.getPatchHierarchy() != d_hierarchy) {
-      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
-         "internal hierarchy.");
-   }
-#endif
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
-
-   const int data_id = data.getComponentDescriptorIndex(0);
-
-   const int flux_id = (d_flux_id != -1) ? d_flux_id : d_flux_scratch_id;
-
-   d_bc_helper.setTargetDataId(data_id);
-   d_bc_helper.setHomogeneousBc(true);
-   xeqScheduleGhostFillNoCoarse(data_id, ln);
-
-   if (ln > d_ln_min) {
-      /*
-       * Perform a one-time transfer of data from coarser level,
-       * to fill ghost boundaries that will not change through
-       * the smoothing loop.
-       */
-      xeqScheduleGhostFill(data_id, ln);
-   }
-
-   /*
-    * Smooth the number of sweeps specified or until
-    * the convergence is satisfactory.
-    */
-   int isweep;
-   double red_maxres, blk_maxres, maxres = 0;
-   red_maxres = blk_maxres = residual_tolerance + 1;
-   /*
-    * Instead of checking residual convergence globally,
-    * we check the not_converged flag.  This avoids possible
-    * round-off errors affecting different processes differently,
-    * leading to disagreement on whether to continue smoothing.
-    */
-   int not_converged = 1;
-   for (isweep = 0; isweep < num_sweeps && not_converged; ++isweep) {
-      red_maxres = blk_maxres = 0;
-
-      // Red sweep.
-      xeqScheduleGhostFillNoCoarse(data_id, ln);
-      for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
-         tbox::Pointer<hier::Patch> patch = *pi;
-
-         bool deallocate_flux_data_when_done = false;
-         if (flux_id == d_flux_scratch_id) {
-            /*
-             * Using internal temporary storage for flux.
-             * For each patch, make sure the internal
-             * side-centered data is allocated and note
-             * whether that data should be deallocated when done.
-             */
-            if (!patch->checkAllocated(flux_id)) {
-               patch->allocatePatchData(flux_id);
-               deallocate_flux_data_when_done = true;
-            }
-         }
-
-         tbox::Pointer<pdat::CellData<double> >
-         scalar_field_data = d_stokes_spec.cIsVariable() ?
-            patch->getPatchData(d_stokes_spec.getCPatchDataId()) :
-            tbox::Pointer<hier::PatchData>(NULL);
-         tbox::Pointer<pdat::CellData<double> >
-         err_data = data.getComponentPatchData(0, *patch);
-         tbox::Pointer<pdat::CellData<double> >
-         residual_data = residual.getComponentPatchData(0, *patch);
-         tbox::Pointer<pdat::SideData<double> >
-         flux_data = patch->getPatchData(flux_id);
-
-         computeFluxOnPatch(
-            *patch,
-            level->getRatioToCoarserLevel(),
-            *err_data,
-            *flux_data);
-
-         redOrBlackSmoothingOnPatch(*patch,
-            *flux_data,
-            *residual_data,
-            *err_data,
-            'r',
-            &red_maxres);
-
-         if (deallocate_flux_data_when_done) {
-            patch->deallocatePatchData(flux_id);
-         }
-      }        // End patch number *pi
-      xeqScheduleGhostFillNoCoarse(data_id, ln);
-
-      // Black sweep.
-      for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
-         tbox::Pointer<hier::Patch> patch = *pi;
-
-         bool deallocate_flux_data_when_done = false;
-         if (flux_id == d_flux_scratch_id) {
-            /*
-             * Using internal temporary storage for flux.
-             * For each patch, make sure the internal
-             * side-centered data is allocated and note
-             * whether that data should be deallocated when done.
-             */
-            if (!patch->checkAllocated(flux_id)) {
-               patch->allocatePatchData(flux_id);
-               deallocate_flux_data_when_done = true;
-            }
-         }
-
-         tbox::Pointer<pdat::CellData<double> >
-         scalar_field_data = d_stokes_spec.cIsVariable() ?
-            patch->getPatchData(d_stokes_spec.getCPatchDataId()) :
-            tbox::Pointer<hier::PatchData>(NULL);
-         tbox::Pointer<pdat::CellData<double> >
-         err_data = data.getComponentPatchData(0, *patch);
-         tbox::Pointer<pdat::CellData<double> >
-         residual_data = residual.getComponentPatchData(0, *patch);
-         tbox::Pointer<pdat::SideData<double> >
-         flux_data = patch->getPatchData(flux_id);
-
-         computeFluxOnPatch(
-            *patch,
-            level->getRatioToCoarserLevel(),
-            *err_data,
-            *flux_data);
-
-         redOrBlackSmoothingOnPatch(*patch,
-            *flux_data,
-            *residual_data,
-            *err_data,
-            'b',
-            &blk_maxres);
-
-         if (deallocate_flux_data_when_done) {
-            patch->deallocatePatchData(flux_id);
-         }
-      }        // End patch number *pi
-      xeqScheduleGhostFillNoCoarse(data_id, ln);
-      if (residual_tolerance >= 0.0) {
-         /*
-          * Check for early end of sweeps due to convergence
-          * only if it is numerically possible (user gave a
-          * non negative value for residual tolerance).
-          */
-         maxres = tbox::MathUtilities<double>::Max(red_maxres, blk_maxres);
-         not_converged = maxres > residual_tolerance;
-         const tbox::SAMRAI_MPI& mpi(d_hierarchy->getDomainMappedBoxLevel().getMPI());
-         if (mpi.getSize() > 1) {
-            mpi.AllReduce(&not_converged, 1, MPI_MAX);
-         }
-      }
-   }        // End sweep number isweep
-   if (d_enable_logging) tbox::plog
-      << d_object_name << " RBGS smoothing maxres = " << maxres << "\n"
-      << "  after " << isweep << " sweeps.\n";
-
-}
-
-/*
- ********************************************************************
- * Fix flux on coarse-fine boundaries computed from a               *
- * constant-refine interpolation of coarse level data.              *
- ********************************************************************
- */
-
-void CellStokesFACOps::ewingFixFlux(
-   const hier::Patch& patch,
-   const pdat::CellData<double>& soln_data,
-   pdat::SideData<double>& flux_data,
-   const hier::IntVector& ratio_to_coarser) const
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, soln_data, flux_data,
-      ratio_to_coarser);
-
-   const int patch_ln = patch.getPatchLevelNumber();
-   const hier::GlobalId id = patch.getGlobalId();
-   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
-      patch.getPatchGeometry();
-   const double* dx = patch_geom->getDx();
-   const hier::Box& patch_box(patch.getBox());
-   const hier::Index& plower = patch_box.lower();
-   const hier::Index& pupper = patch_box.upper();
-
-   const tbox::Array<hier::BoundaryBox>& bboxes =
-      d_cf_boundary[patch_ln]->getBoundaries(id, 1);
-   int bn, nboxes = bboxes.getSize();
-
-   if (d_stokes_spec.dIsVariable()) {
-
-      tbox::Pointer<pdat::SideData<double> > diffcoef_data;
-      diffcoef_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
-
-      for (bn = 0; bn < nboxes; ++bn) {
-         const hier::BoundaryBox& boundary_box = bboxes[bn];
-
-         TBOX_ASSERT(boundary_box.getBoundaryType() == 1);
-
-         const hier::Box& bdry_box = boundary_box.getBox();
-         const hier::Index& blower = bdry_box.lower();
-         const hier::Index& bupper = bdry_box.upper();
-         const int location_index = boundary_box.getLocationIndex();
-         if (d_dim == tbox::Dimension(2)) {
-            F77_FUNC(ewingfixfluxvardc2d, EWINGFIXFLUXVARDC2D) (
-               flux_data.getPointer(0), flux_data.getPointer(1),
-               &flux_data.getGhostCellWidth()[0],
-               &flux_data.getGhostCellWidth()[1],
-               diffcoef_data->getPointer(0), diffcoef_data->getPointer(1),
-               &diffcoef_data->getGhostCellWidth()[0],
-               &diffcoef_data->getGhostCellWidth()[1],
-               soln_data.getPointer(),
-               &soln_data.getGhostCellWidth()[0],
-               &soln_data.getGhostCellWidth()[1],
-               &plower[0], &pupper[0], &plower[1], &pupper[1],
-               &location_index,
-               &ratio_to_coarser[0],
-               &blower[0], &bupper[0],
-               dx);
-         } else if (d_dim == tbox::Dimension(3)) {
-            F77_FUNC(ewingfixfluxvardc3d, EWINGFIXFLUXVARDC3D) (
-               flux_data.getPointer(0),
-               flux_data.getPointer(1),
-               flux_data.getPointer(2),
-               &flux_data.getGhostCellWidth()[0],
-               &flux_data.getGhostCellWidth()[1],
-               &flux_data.getGhostCellWidth()[2],
-               diffcoef_data->getPointer(0),
-               diffcoef_data->getPointer(1),
-               diffcoef_data->getPointer(2),
-               &diffcoef_data->getGhostCellWidth()[0],
-               &diffcoef_data->getGhostCellWidth()[1],
-               &diffcoef_data->getGhostCellWidth()[2],
-               soln_data.getPointer(),
-               &soln_data.getGhostCellWidth()[0],
-               &soln_data.getGhostCellWidth()[1],
-               &soln_data.getGhostCellWidth()[2],
-               &plower[0], &pupper[0],
-               &plower[1], &pupper[1],
-               &plower[2], &pupper[2],
-               &location_index,
-               &ratio_to_coarser[0],
-               &blower[0], &bupper[0],
-               dx);
-         } else {
-            TBOX_ERROR("CellStokesFACOps : DIM > 3 not supported" << std::endl);
-         }
-
-      }
-   } else {
-
-      const double diffcoef_constant = d_stokes_spec.getDConstant();
-
-      for (bn = 0; bn < nboxes; ++bn) {
-         const hier::BoundaryBox& boundary_box = bboxes[bn];
-
-         TBOX_ASSERT(boundary_box.getBoundaryType() == 1);
-
-         const hier::Box& bdry_box = boundary_box.getBox();
-         const hier::Index& blower = bdry_box.lower();
-         const hier::Index& bupper = bdry_box.upper();
-         const int location_index = boundary_box.getLocationIndex();
-         if (d_dim == tbox::Dimension(2)) {
-            F77_FUNC(ewingfixfluxcondc2d, EWINGFIXFLUXCONDC2D) (
-               flux_data.getPointer(0), flux_data.getPointer(1),
-               &flux_data.getGhostCellWidth()[0],
-               &flux_data.getGhostCellWidth()[1],
-               diffcoef_constant,
-               soln_data.getPointer(),
-               &soln_data.getGhostCellWidth()[0],
-               &soln_data.getGhostCellWidth()[1],
-               &plower[0], &pupper[0],
-               &plower[1], &pupper[1],
-               &location_index,
-               &ratio_to_coarser[0],
-               &blower[0], &bupper[0],
-               dx);
-         } else if (d_dim == tbox::Dimension(3)) {
-            F77_FUNC(ewingfixfluxcondc3d, EWINGFIXFLUXCONDC3D) (
-               flux_data.getPointer(0),
-               flux_data.getPointer(1),
-               flux_data.getPointer(2),
-               &flux_data.getGhostCellWidth()[0],
-               &flux_data.getGhostCellWidth()[1],
-               &flux_data.getGhostCellWidth()[2],
-               diffcoef_constant,
-               soln_data.getPointer(),
-               &soln_data.getGhostCellWidth()[0],
-               &soln_data.getGhostCellWidth()[1],
-               &soln_data.getGhostCellWidth()[2],
-               &plower[0], &pupper[0],
-               &plower[1], &pupper[1],
-               &plower[2], &pupper[2],
-               &location_index,
-               &ratio_to_coarser[0],
-               &blower[0], &bupper[0],
-               dx);
-         }
-      }
-   }
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual solveCoarsestLevel             *
- * function                                                         *
- ********************************************************************
- */
-
-int CellStokesFACOps::solveCoarsestLevel(
-   SAMRAIVectorReal<double>& data,
-   const SAMRAIVectorReal<double>& residual,
-   int coarsest_ln) {
-
-   t_solve_coarsest->start();
-
-   checkInputPatchDataIndices();
-
-   int return_value = 0;
-
-   if (d_coarse_solver_choice == "jacobi") {
-      d_residual_tolerance_during_smoothing = d_coarse_solver_tolerance;
-      smoothError(data,
-         residual,
-         coarsest_ln,
-         d_coarse_solver_max_iterations);
-      d_residual_tolerance_during_smoothing = -1.0;
-   } else if (d_coarse_solver_choice == "redblack") {
-      d_residual_tolerance_during_smoothing = d_coarse_solver_tolerance;
-      smoothError(data,
-         residual,
-         coarsest_ln,
-         d_coarse_solver_max_iterations);
-      d_residual_tolerance_during_smoothing = -1.0;
-   } else if (d_coarse_solver_choice == "hypre") {
-#ifndef HAVE_HYPRE
-      TBOX_ERROR(d_object_name << ": Coarse level solver choice '"
-                               << d_coarse_solver_choice
-                               << "' unavailable in "
-                               << "scapCellStokesOps::solveCoarsestLevel.");
-#else
-      return_value = solveCoarsestLevel_HYPRE(data, residual, coarsest_ln);
-#endif
-   } else {
-      TBOX_ERROR(
-         d_object_name << ": Bad coarse level solver choice '"
-         << d_coarse_solver_choice
-         <<
-         "' in scapCellStokesOps::solveCoarsestLevel.");
-   }
-
-   xeqScheduleGhostFillNoCoarse(data.getComponentDescriptorIndex(0),
-      coarsest_ln);
-
-   t_solve_coarsest->stop();
-
-   return return_value;
-}
-
-#ifdef HAVE_HYPRE
-/*
- ********************************************************************
- * Solve coarsest level using Hypre                                 *
- * We only solve for the error, so we always use homogeneous bc.    *
- ********************************************************************
- */
-
-int CellStokesFACOps::solveCoarsestLevel_HYPRE(
-   SAMRAIVectorReal<double>& data,
-   const SAMRAIVectorReal<double>& residual,
-   int coarsest_ln) {
-
-   NULL_USE(coarsest_ln);
-
-#ifndef HAVE_HYPRE
-   TBOX_ERROR(d_object_name << ": Coarse level solver choice '"
-                            << d_coarse_solver_choice
-                            << "' unavailable in "
-                            << "CellStokesFACOps::solveCoarsestLevel.");
-
-   return 0;
-
-#else
-
-   checkInputPatchDataIndices();
-   d_hypre_solver.setStoppingCriteria(d_coarse_solver_max_iterations,
-      d_coarse_solver_tolerance);
-   const int solver_ret =
-      d_hypre_solver.solveSystem(
-         data.getComponentDescriptorIndex(0),
-         residual.getComponentDescriptorIndex(0),
-         true);
-   /*
-    * Present data on the solve.
-    * The Hypre solver returns 0 if converged.
-    */
-   if (d_enable_logging) tbox::plog
-      << d_object_name << " Hypre solve " << (solver_ret ? "" : "NOT ")
-      << "converged\n"
-      << "\titerations: " << d_hypre_solver.getNumberOfIterations() << "\n"
-      << "\tresidual: " << d_hypre_solver.getRelativeResidualNorm() << "\n";
-
-   return !solver_ret;
-
-#endif
-
-}
-#endif
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual                                *
- * computeCompositeResidualOnLevel function                         *
- ********************************************************************
- */
-
-void CellStokesFACOps::computeCompositeResidualOnLevel(
-   SAMRAIVectorReal<double>& residual,
-   const SAMRAIVectorReal<double>& solution,
-   const SAMRAIVectorReal<double>& rhs,
-   int ln,
-   bool error_equation_indicator) {
-
-   t_compute_composite_residual->start();
-
-   checkInputPatchDataIndices();
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (residual.getPatchHierarchy() != d_hierarchy
-       || solution.getPatchHierarchy() != d_hierarchy
-       || rhs.getPatchHierarchy() != d_hierarchy) {
-      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
-         "internal hierarchy.");
-   }
-#endif
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
-
-   /*
-    * Set up the bc helper so that when we use a refine schedule
-    * to fill ghosts, the correct data is operated on.
-    */
-   const int soln_id = solution.getComponentDescriptorIndex(0);
-   d_bc_helper.setTargetDataId(soln_id);
-   d_bc_helper.setHomogeneousBc(error_equation_indicator);
-
-   const int flux_id = (d_flux_id != -1) ? d_flux_id : d_flux_scratch_id;
-
-   /*
-    * Assumptions:
-    * 1. Data does not yet exist in ghost boundaries.
-    * 2. Residual data on next finer grid (if any)
-    *    has been computed already.
-    * 3. Flux data from next finer grid (if any) has
-    *    been computed but has not been coarsened to
-    *    this level.
-    *
-    * Steps:
-    * S1. Fill solution ghost data by refinement
-    *     or setting physical boundary conditions.
-    *     This also brings in information from coarser
-    *     to form the composite grid flux.
-    * S2. Compute flux on ln.
-    * S3. If next finer is available,
-    *     Coarsen flux data on next finer level,
-    *     overwriting flux computed from coarse data.
-    * S4. Compute residual data from flux.
-    */
-
-   /* S1. Fill solution ghost data. */
-   {
-      tbox::Pointer<xfer::RefineSchedule> ln_refine_schedule;
-      if (ln > d_ln_min) {
-         /* Fill from current, next coarser level and physical boundary */
-         xeqScheduleGhostFill(soln_id, ln);
-      } else {
-         /* Fill from current and physical boundary */
-         xeqScheduleGhostFillNoCoarse(soln_id, ln);
-      }
-   }
-
-   /*
-    * For the whole level, make sure the internal
-    * side-centered data is allocated and note
-    * whether that data should be deallocated when done.
-    * We do this for the whole level because the data
-    * undergoes transfer operations which require the
-    * whole level data.
-    */
-   bool deallocate_flux_data_when_done = false;
-   if (flux_id == d_flux_scratch_id) {
-      if (!level->checkAllocated(flux_id)) {
-         level->allocatePatchData(flux_id);
-         deallocate_flux_data_when_done = true;
-      }
-   }
-
-   /*
-    * S2. Compute flux on patches in level.
-    */
-   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
-      tbox::Pointer<hier::Patch> patch = *pi;
-
-      tbox::Pointer<pdat::CellData<double> >
-      soln_data = solution.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::CellData<double> >
-      rhs_data = rhs.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::CellData<double> >
-      residual_data = residual.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::SideData<double> >
-      flux_data = patch->getPatchData(flux_id);
-      computeFluxOnPatch(
-         *patch,
-         level->getRatioToCoarserLevel(),
-         *soln_data,
-         *flux_data);
-
-   }
-
-   /*
-    * S3. Coarsen oflux data from next finer level so that
-    * the computed flux becomes the composite grid flux.
-    */
-   if (ln < d_ln_max) {
-      xeqScheduleFluxCoarsen(flux_id, d_oflux_scratch_id, ln);
-   }
-
-   /*
-    * S4. Compute residual on patches in level.
-    */
-   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
-      tbox::Pointer<hier::Patch> patch = *pi;
-      tbox::Pointer<pdat::CellData<double> >
-      soln_data = solution.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::CellData<double> >
-      rhs_data = rhs.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::CellData<double> >
-      residual_data = residual.getComponentPatchData(0, *patch);
-      tbox::Pointer<pdat::SideData<double> >
-      flux_data = patch->getPatchData(flux_id);
-      computeResidualOnPatch(*patch,
-         *flux_data,
-         *soln_data,
-         *rhs_data,
-         *residual_data);
-
-      if (ln > d_ln_min) {
-         /*
-          * Save outerflux data so that next coarser level
-          *  can compute its coarse-fine composite flux.
-          *  This is not strictly needed in this "compute residual"
-          *  loop through the patches, but we put it here to
-          *  avoid writing another loop for it.
-          */
-         tbox::Pointer<pdat::OutersideData<double> >
-         oflux_data = patch->getPatchData(d_oflux_scratch_id);
-
-         TBOX_ASSERT(oflux_data);
-
-         oflux_data->copy(*flux_data);
-      }
-   }
-
-   if (deallocate_flux_data_when_done) {
-      level->deallocatePatchData(flux_id);
-   }
-
-   t_compute_composite_residual->stop();
-}
-
-/*
- ********************************************************************
- * FACOperatorStrategy virtual computeResidualNorm             *
- * function                                                         *
- ********************************************************************
- */
-
-double CellStokesFACOps::computeResidualNorm(
-   const SAMRAIVectorReal<double>& residual,
-   int fine_ln,
-   int coarse_ln)
-{
-
-   if (coarse_ln != residual.getCoarsestLevelNumber() ||
-       fine_ln != residual.getFinestLevelNumber()) {
-      TBOX_ERROR("CellStokesFACOps::computeResidualNorm() is not\n"
-         << "set up to compute residual except on the range of\n"
-         << "levels defining the vector.\n");
-   }
-   t_compute_residual_norm->start();
-   /*
-    * The residual vector was cloned from vectors that has
-    * the proper weights associated with them, so we do not
-    * have to explicitly weight the residuals.
-    *
-    * maxNorm: not good to use because Hypre's norm does not
-    *   correspond to it.  Also maybe too sensitive to spikes.
-    * L2Norm: maybe good.  But does not correspond to the
-    *   scale of the quantity.
-    * L1Norm: maybe good.  Correspond to scale of quantity,
-    *   but may be too insensitive to spikes.
-    * RMSNorm: maybe good.
-    */
-   double norm = residual.RMSNorm();
-   t_compute_residual_norm->stop();
-   return norm;
-}
-
-/*
- ********************************************************************
- * Compute the vector weight and put it at a specified patch data   *
- * index.                                                           *
- ********************************************************************
- */
-
-void CellStokesFACOps::computeVectorWeights(
-   tbox::Pointer<hier::PatchHierarchy> hierarchy,
-   int weight_id,
-   int coarsest_ln,
-   int finest_ln) const
-{
-   TBOX_ASSERT(!hierarchy.isNull());
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
-
-   if (coarsest_ln == -1) coarsest_ln = 0;
-   if (finest_ln == -1) finest_ln = hierarchy->getFinestLevelNumber();
-   if (finest_ln < coarsest_ln) {
-      TBOX_ERROR(d_object_name
-         << ": Illegal level number range.  finest_ln < coarsest_ln.");
-   }
-
-   int ln;
-   for (ln = finest_ln; ln >= coarsest_ln; --ln) {
-
-      /*
-       * On every level, first assign cell volume to vector weight.
-       */
-
-      tbox::Pointer<hier::PatchLevel> level =
-         hierarchy->getPatchLevel(ln);
-      for (hier::PatchLevel::Iterator p(level); p; p++) {
-         tbox::Pointer<hier::Patch> patch = *p;
-         tbox::Pointer<geom::CartesianPatchGeometry> patch_geometry =
-            patch->getPatchGeometry();
-         const double* dx = patch_geometry->getDx();
-         double cell_vol = dx[0];
-         if (d_dim > tbox::Dimension(1)) {
-            cell_vol *= dx[1];
-         }
-
-         if (d_dim > tbox::Dimension(2)) {
-            cell_vol *= dx[2];
-         }
-
-         tbox::Pointer<pdat::CellData<double> > w =
-            patch->getPatchData(weight_id);
-         if (!w) {
-            TBOX_ERROR(d_object_name
-               << ": weight id must refer to a pdat::CellVariable");
-         }
-         w->fillAll(cell_vol);
-      }
-
-      /*
-       * On all but the finest level, assign 0 to vector
-       * weight to cells covered by finer cells.
-       */
-
-      if (ln < finest_ln) {
-
-         /*
-          * First get the boxes that describe index space of the next finer
-          * level and coarsen them to describe corresponding index space
-          * at this level.
-          */
-
-         tbox::Pointer<hier::PatchLevel> next_finer_level =
-            hierarchy->getPatchLevel(ln + 1);
-         hier::BoxArray coarsened_boxes = next_finer_level->getBoxes();
-         hier::IntVector coarsen_ratio(next_finer_level->getRatioToLevelZero());
-         coarsen_ratio /= level->getRatioToLevelZero();
-         coarsened_boxes.coarsen(coarsen_ratio);
-
-         /*
-          * Then set vector weight to 0 wherever there is
-          * a nonempty intersection with the next finer level.
-          * Note that all assignments are local.
-          */
-
-         for (hier::PatchLevel::Iterator p(level); p; p++) {
-
-            tbox::Pointer<hier::Patch> patch = *p;
-            for (int i = 0; i < coarsened_boxes.getNumberOfBoxes(); i++) {
-
-               hier::Box coarse_box = coarsened_boxes[i];
-               hier::Box intersection = coarse_box * (patch->getBox());
-               if (!intersection.empty()) {
-                  tbox::Pointer<pdat::CellData<double> > w =
-                     patch->getPatchData(weight_id);
-                  w->fillAll(0.0, intersection);
-
-               }  // assignment only in non-empty intersection
-            }  // loop over coarsened boxes from finer level
-         }  // loop over patches in level
-      }  // all levels except finest
-   }  // loop over levels
-}
-
-/*
- ********************************************************************
- * Check the validity and correctness of input data for this class. *
- ********************************************************************
- */
-
-void CellStokesFACOps::checkInputPatchDataIndices() const {
-   /*
-    * Check input validity and correctness.
-    */
-   hier::VariableDatabase& vdb(*hier::VariableDatabase::getDatabase());
-
-   if (!d_stokes_spec.dIsConstant()
-       && d_stokes_spec.getDPatchDataId() != -1) {
-      tbox::Pointer<hier::Variable> var;
-      vdb.mapIndexToVariable(d_stokes_spec.getDPatchDataId(), var);
-      tbox::Pointer<pdat::SideVariable<double> > diffcoef_var = var;
-      if (!diffcoef_var) {
-         TBOX_ERROR(d_object_name
-            << ": Bad diffusion coefficient patch data index.");
-      }
-   }
-
-   if (!d_stokes_spec.cIsConstant() && !d_stokes_spec.cIsZero()) {
-      tbox::Pointer<hier::Variable> var;
-      vdb.mapIndexToVariable(d_stokes_spec.getCPatchDataId(), var);
-      tbox::Pointer<pdat::CellVariable<double> > scalar_field_var = var;
-      if (!scalar_field_var) {
-         TBOX_ERROR(d_object_name << ": Bad linear term patch data index.");
-      }
-   }
-
-   if (d_flux_id != -1) {
-      tbox::Pointer<hier::Variable> var;
-      vdb.mapIndexToVariable(d_flux_id, var);
-      tbox::Pointer<pdat::SideVariable<double> > flux_var = var;
-
-      TBOX_ASSERT(flux_var);
-   }
-
-}
-
-/*
- *******************************************************************
- *                                                                 *
- * AMR-unaware patch-centered computational kernels.               *
- *                                                                 *
- *******************************************************************
- */
-
-void CellStokesFACOps::computeFluxOnPatch(
-   const hier::Patch& patch,
-   const hier::IntVector& ratio_to_coarser_level,
-   const pdat::CellData<double>& w_data,
-   pdat::SideData<double>& Dgradw_data) const
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, ratio_to_coarser_level, w_data,
-      Dgradw_data);
-   TBOX_ASSERT(patch.inHierarchy());
-   TBOX_ASSERT(w_data.getGhostCellWidth() >=
-      hier::IntVector::getOne(ratio_to_coarser_level.getDim()));
-
-   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
-      patch.getPatchGeometry();
-   const hier::Box& box = patch.getBox();
-   const int* lower = &box.lower()[0];
-   const int* upper = &box.upper()[0];
-   const double* dx = patch_geom->getDx();
-
-   double D_value;
-   tbox::Pointer<pdat::SideData<double> > D_data;
-   if (d_stokes_spec.dIsConstant()) {
-      D_value = d_stokes_spec.getDConstant();
-   } else {
-      D_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
-   }
-
-   if (d_stokes_spec.dIsConstant()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(compfluxcondc2d, COMPFLUXCONDC2D) (
-            Dgradw_data.getPointer(0),
-            Dgradw_data.getPointer(1),
-            &Dgradw_data.getGhostCellWidth()[0],
-            &Dgradw_data.getGhostCellWidth()[1],
-            D_value,
-            w_data.getPointer(),
-            &w_data.getGhostCellWidth()[0],
-            &w_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(compfluxcondc3d, COMPFLUXCONDC3D) (
-            Dgradw_data.getPointer(0),
-            Dgradw_data.getPointer(1),
-            Dgradw_data.getPointer(2),
-            &Dgradw_data.getGhostCellWidth()[0],
-            &Dgradw_data.getGhostCellWidth()[1],
-            &Dgradw_data.getGhostCellWidth()[2],
-            D_value,
-            w_data.getPointer(),
-            &w_data.getGhostCellWidth()[0],
-            &w_data.getGhostCellWidth()[1],
-            &w_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx);
-      }
-   } else {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(compfluxvardc2d, COMPFLUXVARDC2D) (
-            Dgradw_data.getPointer(0),
-            Dgradw_data.getPointer(1),
-            &Dgradw_data.getGhostCellWidth()[0],
-            &Dgradw_data.getGhostCellWidth()[1],
-            D_data->getPointer(0),
-            D_data->getPointer(1),
-            &D_data->getGhostCellWidth()[0],
-            &D_data->getGhostCellWidth()[1],
-            w_data.getPointer(),
-            &w_data.getGhostCellWidth()[0],
-            &w_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx);
-      }
-      if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(compfluxvardc3d, COMPFLUXVARDC3D) (
-            Dgradw_data.getPointer(0),
-            Dgradw_data.getPointer(1),
-            Dgradw_data.getPointer(2),
-            &Dgradw_data.getGhostCellWidth()[0],
-            &Dgradw_data.getGhostCellWidth()[1],
-            &Dgradw_data.getGhostCellWidth()[2],
-            D_data->getPointer(0),
-            D_data->getPointer(1),
-            D_data->getPointer(2),
-            &D_data->getGhostCellWidth()[0],
-            &D_data->getGhostCellWidth()[1],
-            &D_data->getGhostCellWidth()[2],
-            w_data.getPointer(),
-            &w_data.getGhostCellWidth()[0],
-            &w_data.getGhostCellWidth()[1],
-            &w_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx);
-      }
-   }
-
-   const int patch_ln = patch.getPatchLevelNumber();
-
-   if (d_cf_discretization == "Ewing" && patch_ln > d_ln_min) {
-      ewingFixFlux(patch,
-         w_data,
-         Dgradw_data,
-         ratio_to_coarser_level);
-   }
-
-}
-
-void CellStokesFACOps::computeResidualOnPatch(
-   const hier::Patch& patch,
-   const pdat::SideData<double>& flux_data,
-   const pdat::CellData<double>& soln_data,
-   const pdat::CellData<double>& rhs_data,
-   pdat::CellData<double>& residual_data) const
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS5(d_dim, patch, flux_data, soln_data, rhs_data,
-      residual_data);
-
-   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
-      patch.getPatchGeometry();
-   const hier::Box& box = patch.getBox();
-   const int* lower = &box.lower()[0];
-   const int* upper = &box.upper()[0];
-   const double* dx = patch_geom->getDx();
-
-   tbox::Pointer<pdat::CellData<double> > scalar_field_data;
-   double scalar_field_constant;
-   if (d_stokes_spec.cIsVariable()) {
-      scalar_field_data =
-         patch.getPatchData(d_stokes_spec.getCPatchDataId());
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(compresvarsca2d, COMPRESVARSCA2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0], &lower[1], &upper[1],
-            dx);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(compresvarsca3d, COMPRESVARSCA3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            &residual_data.getGhostCellWidth()[2],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            &scalar_field_data->getGhostCellWidth()[2],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
-            dx);
-      }
-   } else if (d_stokes_spec.cIsConstant()) {
-      scalar_field_constant = d_stokes_spec.getCConstant();
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0], &lower[1], &upper[1],
-            dx);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            &residual_data.getGhostCellWidth()[2],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
-            dx);
-      }
-   } else {
-      scalar_field_constant = 0.0;
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0], &lower[1], &upper[1],
-            dx);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            residual_data.getPointer(),
-            &residual_data.getGhostCellWidth()[0],
-            &residual_data.getGhostCellWidth()[1],
-            &residual_data.getGhostCellWidth()[2],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
-            dx);
-      }
-   }
-}
-
-void CellStokesFACOps::redOrBlackSmoothingOnPatch(
-   const hier::Patch& patch,
-   const pdat::SideData<double>& flux_data,
-   const pdat::CellData<double>& rhs_data,
-   pdat::CellData<double>& soln_data,
-   char red_or_black,
-   double* p_maxres) const
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, flux_data, soln_data, rhs_data);
-   TBOX_ASSERT(red_or_black == 'r' || red_or_black == 'b');
-
-   const int offset = red_or_black == 'r' ? 0 : 1;
-   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
-      patch.getPatchGeometry();
-   const hier::Box& box = patch.getBox();
-   const int* lower = &box.lower()[0];
-   const int* upper = &box.upper()[0];
-   const double* dx = patch_geom->getDx();
-
-   tbox::Pointer<pdat::CellData<double> > scalar_field_data;
-   double scalar_field_constant;
-   tbox::Pointer<pdat::SideData<double> > diffcoef_data;
-   double diffcoef_constant;
-
-   if (d_stokes_spec.cIsVariable()) {
-      scalar_field_data =
-         patch.getPatchData(d_stokes_spec.getCPatchDataId());
-   } else if (d_stokes_spec.cIsConstant()) {
-      scalar_field_constant = d_stokes_spec.getCConstant();
-   } else {
-      scalar_field_constant = 0.0;
-   }
-   if (d_stokes_spec.dIsVariable()) {
-      diffcoef_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
-   } else {
-      diffcoef_constant = d_stokes_spec.getDConstant();
-   }
-
-   double maxres = 0.0;
-   if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsVariable()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxvardcvarsf2d, RBGSWITHFLUXMAXVARDCVARSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxvardcvarsf3d, RBGSWITHFLUXMAXVARDCVARSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            diffcoef_data->getPointer(2),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            &diffcoef_data->getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            &scalar_field_data->getGhostCellWidth()[2],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   } else if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsConstant()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            diffcoef_data->getPointer(2),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            &diffcoef_data->getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   } else if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsZero()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_data->getPointer(0),
-            diffcoef_data->getPointer(1),
-            diffcoef_data->getPointer(2),
-            &diffcoef_data->getGhostCellWidth()[0],
-            &diffcoef_data->getGhostCellWidth()[1],
-            &diffcoef_data->getGhostCellWidth()[2],
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsVariable()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxcondcvarsf2d, RBGSWITHFLUXMAXCONDCVARSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxcondcvarsf3d, RBGSWITHFLUXMAXCONDCVARSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            scalar_field_data->getPointer(),
-            &scalar_field_data->getGhostCellWidth()[0],
-            &scalar_field_data->getGhostCellWidth()[1],
-            &scalar_field_data->getGhostCellWidth()[2],
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsConstant()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            scalar_field_constant,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsZero()) {
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            dx,
-            &offset, &maxres);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
-            flux_data.getPointer(0),
-            flux_data.getPointer(1),
-            flux_data.getPointer(2),
-            &flux_data.getGhostCellWidth()[0],
-            &flux_data.getGhostCellWidth()[1],
-            &flux_data.getGhostCellWidth()[2],
-            diffcoef_constant,
-            rhs_data.getPointer(),
-            &rhs_data.getGhostCellWidth()[0],
-            &rhs_data.getGhostCellWidth()[1],
-            &rhs_data.getGhostCellWidth()[2],
-            0.0,
-            soln_data.getPointer(),
-            &soln_data.getGhostCellWidth()[0],
-            &soln_data.getGhostCellWidth()[1],
-            &soln_data.getGhostCellWidth()[2],
-            &lower[0], &upper[0],
-            &lower[1], &upper[1],
-            &lower[2], &upper[2],
-            dx,
-            &offset, &maxres);
-      }
-   }
-
-   *p_maxres = maxres;
-}
-
-void
-CellStokesFACOps::xeqScheduleProlongation(
-   int dst_id,
-   int src_id,
-   int scr_id,
-   int dest_ln)
-{
-   if (!d_prolongation_refine_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-   xfer::RefineAlgorithm refiner(d_dim);
-   refiner.
-   registerRefine(dst_id,
-      src_id,
-      scr_id,
-      d_prolongation_refine_operator);
-   refiner.
-   resetSchedule(d_prolongation_refine_schedules[dest_ln]);
-   d_prolongation_refine_schedules[dest_ln]->fillData(0.0);
-   d_prolongation_refine_algorithm->
-   resetSchedule(d_prolongation_refine_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::xeqScheduleURestriction(
-   int dst_id,
-   int src_id,
-   int dest_ln)
-{
-   if (!d_urestriction_coarsen_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-
-   xfer::CoarsenAlgorithm coarsener(d_dim);
-   coarsener.registerCoarsen(dst_id,
-      src_id,
-      d_urestriction_coarsen_operator);
-   coarsener.resetSchedule(d_urestriction_coarsen_schedules[dest_ln]);
-   d_urestriction_coarsen_schedules[dest_ln]->coarsenData();
-   d_urestriction_coarsen_algorithm->
-   resetSchedule(d_urestriction_coarsen_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::xeqScheduleRRestriction(
-   int dst_id,
-   int src_id,
-   int dest_ln)
-{
-   if (!d_rrestriction_coarsen_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-
-   xfer::CoarsenAlgorithm coarsener(d_dim);
-   coarsener.registerCoarsen(dst_id,
-      src_id,
-      d_rrestriction_coarsen_operator);
-   coarsener.resetSchedule(d_rrestriction_coarsen_schedules[dest_ln]);
-   d_rrestriction_coarsen_schedules[dest_ln]->coarsenData();
-   d_rrestriction_coarsen_algorithm->
-   resetSchedule(d_rrestriction_coarsen_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::xeqScheduleFluxCoarsen(
-   int dst_id,
-   int src_id,
-   int dest_ln)
-{
-   if (!d_flux_coarsen_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-
-   xfer::CoarsenAlgorithm coarsener(d_dim);
-   coarsener.registerCoarsen(dst_id,
-      src_id,
-      d_flux_coarsen_operator);
-
-   coarsener.resetSchedule(d_flux_coarsen_schedules[dest_ln]);
-   d_flux_coarsen_schedules[dest_ln]->coarsenData();
-   d_flux_coarsen_algorithm->
-   resetSchedule(d_flux_coarsen_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::xeqScheduleGhostFill(
-   int dst_id,
-   int dest_ln)
-{
-   if (!d_ghostfill_refine_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-   xfer::RefineAlgorithm refiner(d_dim);
-   refiner.
-   registerRefine(dst_id,
-      dst_id,
-      dst_id,
-      d_ghostfill_refine_operator);
-   refiner.
-   resetSchedule(d_ghostfill_refine_schedules[dest_ln]);
-   d_ghostfill_refine_schedules[dest_ln]->fillData(0.0);
-   d_ghostfill_refine_algorithm->
-   resetSchedule(d_ghostfill_refine_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::xeqScheduleGhostFillNoCoarse(
-   int dst_id,
-   int dest_ln)
-{
-   if (!d_ghostfill_nocoarse_refine_schedules[dest_ln]) {
-      TBOX_ERROR("Expected schedule not found.");
-   }
-   xfer::RefineAlgorithm refiner(d_dim);
-   refiner.
-   registerRefine(dst_id,
-      dst_id,
-      dst_id,
-      d_ghostfill_nocoarse_refine_operator);
-   refiner.
-   resetSchedule(d_ghostfill_nocoarse_refine_schedules[dest_ln]);
-   d_ghostfill_nocoarse_refine_schedules[dest_ln]->fillData(0.0);
-   d_ghostfill_nocoarse_refine_algorithm->
-   resetSchedule(d_ghostfill_nocoarse_refine_schedules[dest_ln]);
-}
-
-void
-CellStokesFACOps::finalizeCallback()
-{
-   for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
-      s_cell_scratch_var[d].setNull();
-      s_flux_scratch_var[d].setNull();
-      s_oflux_scratch_var[d].setNull();
-   }
-}
-
-}
-}
-#endif
diff -r a44a82f15794 -r fe2a9230921b CellStokesFACOps.I
--- a/CellStokesFACOps.I	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Operator class for solving scalar Stokes using FAC 
- *
- ************************************************************************/
-namespace SAMRAI {
-namespace solv {
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setPreconditioner(
-   const FACPreconditioner* preconditioner) {
-   d_preconditioner = preconditioner;
-}
-
-#ifdef HAVE_HYPRE
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setUseSMG(
-   bool use_smg)
-{
-   if (d_hierarchy) {
-      TBOX_ERROR(
-         d_object_name << ": setUseSMG(bool) may NOT be called\n"
-         <<
-         "while the solver state is initialized, as that\n"
-         << "would lead to a corrupted solver state.\n");
-   }
-   d_hypre_solver.setUseSMG(use_smg);
-}
-#endif
-
-/*
- ********************************************************************
- * Set the physical boundary condition object.                      *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setPhysicalBcCoefObject(
-   const RobinBcCoefStrategy* physical_bc_coef)
-{
-   d_physical_bc_coef = physical_bc_coef;
-   d_bc_helper.setCoefImplementation(physical_bc_coef);
-#ifdef HAVE_HYPRE
-   d_hypre_solver.setPhysicalBcCoefObject(d_physical_bc_coef);
-#endif
-}
-
-/*
- ********************************************************************
- * Set the object specifying the parameters of the Stokes equation *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setStokesSpecifications(
-   const StokesSpecifications& spec)
-{
-   d_stokes_spec = spec;
-}
-
-/*
- ********************************************************************
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::enableLogging(
-   bool enable_logging)
-{
-   d_enable_logging = enable_logging;
-}
-
-/*
- ********************************************************************
- * Set the patch data id for the flux.                              *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setFluxId(
-   int flux_id) {
-   d_flux_id = flux_id;
-#ifdef DEBUG_CHECK_ASSERTIONS
-   checkInputPatchDataIndices();
-#endif
-}
-
-/*
- ********************************************************************
- * Set the choice for smoothing algorithm.                          *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setSmoothingChoice(
-   const std::string& smoothing_choice)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (smoothing_choice != "redblack") {
-      TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
-                               << smoothing_choice
-                               << "' in CellStokesFACOps::setSmoothingChoice.");
-   }
-#endif
-   d_smoothing_choice = smoothing_choice;
-}
-
-/*
- ********************************************************************
- * Set the choice for the coarse level solver.                      *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setCoarsestLevelSolverChoice(
-   const std::string& choice) {
-#ifdef DEBUG_CHECK_ASSERTIONS
-#ifndef HAVE_HYPRE
-   if (choice == "hypre") {
-      TBOX_ERROR(d_object_name << ": HYPRe library is not available.\n");
-   }
-#endif
-#endif
-   if (choice == "redblack"
-       || choice == "hypre") {
-      d_coarse_solver_choice = choice;
-   } else {
-      TBOX_ERROR(
-         d_object_name << ": Bad coarse level solver choice '"
-         << choice
-         <<
-         "' in scapCellStokesOpsX::setCoarseLevelSolver.");
-   }
-}
-
-/*
- ********************************************************************
- * Set the tolerance for the coarse level solver.                   *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setCoarsestLevelSolverTolerance(
-   double tol) {
-   d_coarse_solver_tolerance = tol;
-}
-
-/*
- ********************************************************************
- * Set the tolerance for the coarse level solver.                   *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setCoarsestLevelSolverMaxIterations(
-   int max_iterations) {
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (max_iterations < 0) {
-      TBOX_ERROR(d_object_name << ": Invalid number of max iterations\n");
-   }
-#endif
-   d_coarse_solver_max_iterations = max_iterations;
-}
-
-/*
- ********************************************************************
- * Set the coarse-fine discretization method.                       *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setCoarseFineDiscretization(
-   const std::string& coarsefine_method) {
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (d_hierarchy) {
-      TBOX_ERROR(
-         d_object_name << ": Cannot change coarse-fine\n"
-         <<
-         "discretization method while operator state\n"
-         << "is initialized because that causes a\n"
-         << "corruption in the state.\n");
-   }
-#endif
-   d_cf_discretization = coarsefine_method;
-}
-
-/*
- ********************************************************************
- * Set the prolongation method                                      *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACOps::setProlongationMethod(
-   const std::string& prolongation_method) {
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (d_hierarchy) {
-      TBOX_ERROR(
-         d_object_name << ": Cannot change prolongation method\n"
-         <<
-         "while operator state is initialized because that\n"
-         << "causes a corruption in the state.\n");
-   }
-#endif
-   d_prolongation_method = prolongation_method;
-}
-
-}
-}
diff -r a44a82f15794 -r fe2a9230921b CellStokesFACOps.h
--- a/CellStokesFACOps.h	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1044 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Operator class for cell-centered scalar Stokes using FAC 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesFACOps
-#define included_solv_CellStokesFACOps
-
-#include "SAMRAI/SAMRAI_config.h"
-
-#include "SAMRAI/solv/CartesianRobinBcHelper.h"
-#include "SAMRAI/solv/FACPreconditioner.h"
-#include "SAMRAI/solv/FACOperatorStrategy.h"
-#include "SAMRAI/solv/RobinBcCoefStrategy.h"
-#include "CellStokesHypreSolver.h"
-#include "SAMRAI/solv/SAMRAIVectorReal.h"
-#include "StokesSpecifications.h"
-#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
-#include "SAMRAI/math/HierarchySideDataOpsReal.h"
-#include "SAMRAI/pdat/CellData.h"
-#include "SAMRAI/pdat/CellVariable.h"
-#include "SAMRAI/pdat/CellDoubleConstantRefine.h"
-#include "SAMRAI/pdat/OutersideData.h"
-#include "SAMRAI/pdat/OutersideVariable.h"
-#include "SAMRAI/pdat/SideData.h"
-#include "SAMRAI/pdat/SideVariable.h"
-#include "SAMRAI/xfer/CoarsenSchedule.h"
-#include "SAMRAI/xfer/RefineSchedule.h"
-#include "SAMRAI/xfer/CoarsenAlgorithm.h"
-#include "SAMRAI/xfer/CoarsenOperator.h"
-#include "SAMRAI/xfer/RefineAlgorithm.h"
-#include "SAMRAI/xfer/RefineOperator.h"
-#include "SAMRAI/hier/CoarseFineBoundary.h"
-#include "SAMRAI/hier/Patch.h"
-#include "SAMRAI/hier/PatchHierarchy.h"
-#include "SAMRAI/hier/PatchLevel.h"
-#include "SAMRAI/hier/IntVector.h"
-#include "SAMRAI/hier/Box.h"
-#include "SAMRAI/hier/VariableContext.h"
-#include "SAMRAI/tbox/Database.h"
-#include "SAMRAI/tbox/Pointer.h"
-#include "SAMRAI/tbox/Timer.h"
-
-#include <string>
-
-namespace SAMRAI {
-namespace solv {
-
-/*!
- * @brief FAC operator class to solve Stokes's equation on a SAMR grid,
- * using cell-centered, second-order finite-volume method, with Robin
- * boundary conditions.
- *
- * This class provides operators that are used by the FAC
- * preconditioner FACPreconditioner.
- * It is used to solve the scalar Stokes's equation using a cell-centered
- * second-order finite-volume discretization.
- * It is designed to provide all operations specific to
- * the scalar Stokes's equation,
- * @f[ \nabla \cdot D \nabla u + C u = f @f]
- * (see StokesSpecifications) where
- * - C, D and f are indpendent of u
- * - C is a cell-centered scalar field
- * - D is the @em diffusion @em coefficients, stored on faces
- * - f is a cell-centered scalar function
- *
- * You are left to provide the source function, initial guess, etc.,
- * by specifying them in specific forms.
- *
- * This class provides:
- * -# 5-point (second order), cell-centered stencil operations
- *    for the discrete Laplacian.
- * -# Red-black Gauss-Seidel smoothing.
- * -# Provisions for working Robin boundary conditions
- *    (see RobinBcCoefStrategy).
- *
- * This class is meant to provide the Stokes-specific operator
- * used by the FAC preconditioner, FACPreconditioner.
- * To use the preconditioner with this class, you will have to provide:
- * -# The solution vector SAMRAIVectorReal,
- *    with appropriate norm weighting for the cell-centered AMR mesh.
- *    This class provides the function computeVectorWeights()
- *    to help with computing the appropriate weights.
- *    Since this is for a scalar equation, only the first depth
- *    of the first component of the vectors are used.
- *    All other parts are ignored.
- * -# The source vector SAMRAIVectorReal for f.
- * -# A StokesSpecifications objects to specify
- *    the cell-centered scalar field C and the side-centered
- *    diffusion coefficients D
- * -# The boundary condition specifications in terms of the coefficients
- *    @f$ \alpha @f$, @f$ \beta @f$ and @f$ \gamma @f$ in the
- *    Robin formula @f$  \alpha u + \beta u_n = \gamma @f$ applied on the
- *    boundary faces.  See RobinBcCoefStrategy.
- *
- * This class allocates and deallocates only its own scratch data.
- * Other data that it manipuates are passed in as function arguments.
- * Hence, it owns none of the solution vectors, error vectors,
- * diffusion coefficient data, or any such things.
- *
- * Input Examples
- * @verbatim
- * coarse_solver_choice = "hypre"    // see setCoarsestLevelSolverChoice()
- * coarse_solver_tolerance = 1e-14   // see setCoarsestLevelSolverTolerance()
- * coarse_solver_max_iterations = 10 // see setCoarsestLevelSolverMaxIterations()
- * smoothing_choice = "redblack"     // see setSmoothingChoice()
- * cf_discretization = "Ewing"       // see setCoarseFineDiscretization()
- * prolongation_method = "LINEAR_REFINE" // see setProlongationMethod()
- * hypre_solver = { ... }            // tbox::Database for initializing Hypre solver
- * @endverbatim
- */
-class CellStokesFACOps:
-   public FACOperatorStrategy
-{
-
-public:
-   /*!
-    * @brief Constructor.
-    *
-    * If you want standard output and logging,
-    * pass in valid pointers for those streams.
-    * @param object_name Ojbect name
-    * @param database Input database
-    */
-   CellStokesFACOps(
-      const tbox::Dimension& dim,
-      const std::string& object_name = std::string(),
-      tbox::Pointer<tbox::Database> database =
-         tbox::Pointer<tbox::Database>(NULL));
-
-   /*!
-    * @brief Destructor.
-    *
-    * Deallocate internal data.
-    */
-   ~CellStokesFACOps(
-      void);
-
-   /*!
-    * @brief Set the scalar Stokes equation specifications.
-    */
-   void
-   setStokesSpecifications(
-      const StokesSpecifications& spec);
-
-   /*!
-    * @brief Enable logging.
-    *
-    * By default, logging is disabled.  The logging flag is
-    * propagated to the major components used by this class.
-    */
-   void
-   enableLogging(
-      bool enable_logging);
-
-   //@{
-   /*!
-    * @name Functions for setting solver mathematic algorithm controls
-    */
-
-   /*!
-    * @brief Set the choice of smoothing algorithms.
-    *
-    * Current smoothing choices are:
-    * - "redblack": Red-black Gauss-Seidel smoothing.
-    */
-   void
-   setSmoothingChoice(
-      const std::string& smoothing_choice);
-
-   /*!
-    * @brief Set coarse level solver.
-    *
-    * Select from these:
-    * - @c "redblack" (red-black smoothing until convergence--very slow!)
-    * - @c "hypre" (only if the HYPRE library is available).
-    */
-   void
-   setCoarsestLevelSolverChoice(
-      const std::string& choice);
-
-   /*!
-    * @brief Set tolerance for coarse level solve.
-    *
-    * If the coarse level solver requires a tolerance (currently, they all do),
-    * the specified value is used.
-    */
-   void
-   setCoarsestLevelSolverTolerance(
-      double tol);
-
-   /*!
-    * @brief Set max iterations for coarse level solve.
-    *
-    * If the coarse level solver requires a max iteration limit
-    * (currently, they all do), the specified value is used.
-    */
-   void
-   setCoarsestLevelSolverMaxIterations(
-      int max_iterations);
-
-   /*!
-    * @brief Set the coarse-fine boundary discretization method.
-    *
-    * Specify the @c op_name std::string which will be passed to
-    * xfer::Geometry::lookupRefineOperator() to get the operator
-    * for setting fine grid ghost cells from the coarse grid.
-    * Note that chosing this operator implicitly choses the
-    * discretization method at the coarse-fine boundary.
-    *
-    * There is one important instance where this std::string is
-    * @em not passed to xfer::Geometry::lookupRefineOperator.
-    * If this variable is set to "Ewing", Ewing's coarse-fine
-    * discretization is used (a constant refinement is performed,
-    * and the flux is later corrected to result in Ewing's scheme).
-    * For a reference to Ewing's discretization method, see
-    * "Local Refinement Techniques for Elliptic Problems on Cell-Centered
-    * Grids, I. Error Analysis", Mathematics of Computation, Vol. 56, No. 194,
-    * April 1991, pp. 437-461.
-    *
-    * @param coarsefine_method String selecting the coarse-fine discretization method.
-    */
-   void
-   setCoarseFineDiscretization(
-      const std::string& coarsefine_method);
-
-   /*!
-    * @brief Set the name of the prolongation method.
-    *
-    * Specify the @c op_name std::string which will be passed to
-    * xfer::Geometry::lookupRefineOperator() to get the operator
-    * for prolonging the coarse-grid correction.
-    *
-    * By default, "CONSTANT_REFINE" is used.  "LINEAR_REFINE" seems to
-    * to lead to faster convergence, but it does NOT satisfy the Galerkin
-    * condition.
-    *
-    * Prolonging using linear refinement requires a Robin bc
-    * coefficient implementation that is capable of delivering
-    * coefficients for non-hierarchy data, because linear refinement
-    * requires boundary conditions to be set on temporary levels.
-    *
-    * @param prolongation_method String selecting the coarse-fine
-    *        discretization method.
-    */
-   void
-   setProlongationMethod(
-      const std::string& prolongation_method);
-
-#ifdef HAVE_HYPRE
-   /*!
-    * @brief Set whether to use Hypre's PFMG algorithm instead of the
-    * SMG algorithm.
-    *
-    * This flag affects the Hypre solver (used to solve the coarsest level).
-    * The flag is used to select which of HYPRE's linear solver algorithms
-    * to use if true, the semicoarsening multigrid algorithm is used, and if
-    * false, the ``PF'' multigrid algorithm is used.
-    * By default, the SMG algorithm is used.
-    *
-    * This setting has effect only when Hypre is chosen for the coarsest
-    * level solver.  See setCoarsestLevelSolverChoice().
-    *
-    * Changing the algorithm must be done before initializing the solver
-    * state and must NOT be done while the state is initialized
-    * (the program will exit), as that would corrupt the state.
-    */
-   void
-   setUseSMG(
-      bool use_smg);
-#endif
-
-   //@}
-
-   //@{
-   /*!
-    * @name Functions for setting patch data indices and coefficients
-    */
-
-   /*!
-    * @brief Set the scratch patch data index for the flux.
-    *
-    * The use of this function is optional.
-    * The patch data index should be a pdat::SideData<DIM> type of variable.
-    * If the flux id is -1 (the default initial value), scratch space
-    * for the flux is allocated as needed and immediately deallocated
-    * afterward, level by level.  If you have space preallocated for
-    * flux and you would like that to be used, set flux id to the
-    * patch data index of that space.
-    */
-   void
-   setFluxId(
-      int flux_id);
-
-   //@}
-
-   /*!
-    * @brief Provide an implementation for getting the
-    * physical bc coefficients
-    *
-    * If your solution is fixed at the physical boundary
-    * ghost cell centers AND those cells have the correct
-    * values before entering solveSystem(), you may use a
-    * GhostCellRobinBcCoefs object.
-    *
-    * If your solution is @b not fixed at the ghost cell centers,
-    * the ghost cell values will change as the interior
-    * cell values change.  In those cases, the flexible
-    * Robin boundary conditions are applied.  You must
-    * call this function to provide the implementation for
-    * determining the boundary condition coefficients.
-    *
-    * @param physical_bc_coef tbox::Pointer to an object that can
-    *        set the Robin bc coefficients.
-    */
-   void
-   setPhysicalBcCoefObject(
-      const RobinBcCoefStrategy* physical_bc_coef);
-
-   //@{
-
-   /*!
-    * @name Functions for checking validity and correctness of state.
-    */
-
-   /*!
-    * @brief Check validity and correctness of input patch data indices.
-    *
-    * Descriptors checked:
-    * -# Diffusion coefficient (see setDiffcoefId())
-    * -# Flux (see setFluxId())
-    * -# Source (see setScalarFieldId())
-    */
-   void
-   checkInputPatchDataIndices() const;
-
-   //@}
-
-   /*!
-    * @brief Set weight appropriate for computing vector norms.
-    *
-    * If you this function to set the weights used when you
-    * SAMRAIVectorReal::addComponent, you can use the
-    * vector norm functions of SAMRAIVectorReal, and
-    * the weights will be used to blank out coarse grid
-    * regions under fine grids.
-    *
-    * The weights computed are specific to the cell-centered
-    * discretization used by this class.  The weight is equal
-    * to the cell volume if the cell has not been refined,
-    * and zero if it has.
-    *
-    * This function is state-independent.  All inputs are in
-    * the argument list.
-    *
-    * @param hierarchy Hierarchy configuration to compute weights for
-    * @param weight_id hier::Patch data index of the weight
-    * @param coarsest_ln Coarsest level number.  Must be included
-    *        in hierarchy.  Must not be greater than @c finest_ln.
-    *        Default to 0.
-    * @param finest_ln Finest level number.  Must be included
-    *        in hierarchy.  Must not be less than @c coarsest_ln.
-    *        Default to finest level in @c hierarchy.
-    */
-   void
-   computeVectorWeights(
-      tbox::Pointer<hier::PatchHierarchy> hierarchy,
-      int weight_id,
-      int coarsest_ln = -1,
-      int finest_ln = -1) const;
-
-   /*!
-    * @brief Set the FAC preconditioner that will be using this object.
-    *
-    * The FAC preconditioner is accessed to get convergence data during
-    * the cycle postprocessing step.  It is optional.
-    */
-   void
-   setPreconditioner(
-      const FACPreconditioner* preconditioner);
-
-   /*!
-    * @brief function to compute flux, using general diffusion
-    * coefficient data.
-    *
-    * Recall that this solver class discretizes the PDE
-    * @f[ \nabla \cdot D \nabla u + C u = f @f] on an AMR grid.  This member
-    * function allows users of this solver class to compute gradient
-    * terms, @f[ D \nabla w @f], in their code in a manner consistent with the
-    * solver discretization.   In particular, when solving PDE systems, it may
-    * be necessary to discretize the gradient operator appearing in equations
-    * not treated by the solver class in the same way as those treated by this
-    * class.  These funtions allow users to do this easily.  The divergence
-    * operator used in this solver is the standard sum of centered differences
-    * involving flux terms on the cell sides computed by these routines.
-    *
-    * Note that the patch must exist on a level in an AMR hierarchy so that
-    * the discretization can be computed properly at the coarse-fine interface.
-    * Stokes coefficients C and D must exist on the patch, if they are variable.
-    * Also, calling this function does not affect the internal solver state in any
-    * way.  However, the solver must be fully initialized before it is called and care
-    * should be exercised to pass arguments so that the solver solution quantity and
-    * other internal solver quantities are not adversely affected.
-    *
-    * @param patch patch on which computation will take place
-    * @param ratio_to_coarser_level refinement ratio from coarser level to level
-    *                               on which patch lives; if current patch level
-    *                               is level zero, this is ignored
-    * @param w_data cell-centered data
-    * @param Dgradw_data side-centered flux data (i.e., D (grad w))
-    */
-   void
-   computeFluxOnPatch(
-      const hier::Patch& patch,
-      const hier::IntVector& ratio_to_coarser_level,
-      const pdat::CellData<double>& w_data,
-      pdat::SideData<double>& Dgradw_data) const;
-
-   //@{ @name FACOperatorStrategy virtuals
-
-   virtual void
-   restrictSolution(
-      const SAMRAIVectorReal<double>& source,
-      SAMRAIVectorReal<double>& dest,
-      int dest_ln);
-   virtual void
-   restrictResidual(
-      const SAMRAIVectorReal<double>& source,
-      SAMRAIVectorReal<double>& dest,
-      int dest_ln);
-
-   virtual void
-   prolongErrorAndCorrect(
-      const SAMRAIVectorReal<double>& source,
-      SAMRAIVectorReal<double>& dest,
-      int dest_ln);
-
-   virtual void
-   smoothError(
-      SAMRAIVectorReal<double>& error,
-      const SAMRAIVectorReal<double>& residual,
-      int ln,
-      int num_sweeps);
-
-   virtual int
-   solveCoarsestLevel(
-      SAMRAIVectorReal<double>& error,
-      const SAMRAIVectorReal<double>& residual,
-      int coarsest_ln);
-
-   virtual void
-   computeCompositeResidualOnLevel(
-      SAMRAIVectorReal<double>& residual,
-      const SAMRAIVectorReal<double>& solution,
-      const SAMRAIVectorReal<double>& rhs,
-      int ln,
-      bool error_equation_indicator);
-
-   virtual double
-   computeResidualNorm(
-      const SAMRAIVectorReal<double>& residual,
-      int fine_ln,
-      int coarse_ln);
-
-   virtual void
-   initializeOperatorState(
-      const SAMRAIVectorReal<double>& solution,
-      const SAMRAIVectorReal<double>& rhs);
-
-   virtual void
-   deallocateOperatorState();
-
-   virtual void
-   postprocessOneCycle(
-      int fac_cycle_num,
-      const SAMRAIVectorReal<double>& current_soln,
-      const SAMRAIVectorReal<double>& residual);
-
-   //@}
-
-private:
-   //@{
-   /*!
-    * @name Private workhorse functions.
-    */
-
-   /*!
-    * @brief Red-black Gauss-Seidel error smoothing on a level.
-    *
-    * Smoothes on the residual equation @f$ Ae=r @f$ on a level.
-    *
-    * @param error error vector
-    * @param residual residual vector
-    * @param ln level number
-    * @param num_sweeps number of sweeps
-    * @param residual_tolerance the maximum residual considered to be
-    *        converged
-    */
-   void
-   smoothErrorByRedBlack(
-      SAMRAIVectorReal<double>& error,
-      const SAMRAIVectorReal<double>& residual,
-      int ln,
-      int num_sweeps,
-      double residual_tolerance = -1.0);
-
-   /*!
-    * @brief Solve the coarsest level using HYPRE
-    */
-   int
-   solveCoarsestLevel_HYPRE(
-      SAMRAIVectorReal<double>& error,
-      const SAMRAIVectorReal<double>& residual,
-      int ln);
-
-   /*!
-    * @brief Fix flux per Ewing's coarse-fine boundary treatment.
-    *
-    * Ewing's coarse-fine boundary treatment can be implemented
-    * using a constant refinement into the fine-grid ghost boundary,
-    * naively computing the flux using the constant-refined data then
-    * fixing up the flux to correct the error.
-    *
-    * To use this function
-    * -# you must use constant refinement to fill the fine level ghost cells
-    * -# the flux must first be computed and stored
-    *
-    * @param patch patch
-    * @param soln_data cell-centered solution data
-    * @param flux_data side-centered flux data
-    * @param diffcoef_data side-centered diffusion coefficient data
-    * @param cfb coarse-fine boundary object for the level
-    *        in which patch resides
-    * @param ratio_to_coarser Refinement ratio to the next coarser level.
-    */
-   void
-   ewingFixFlux(
-      const hier::Patch& patch,
-      const pdat::CellData<double>& soln_data,
-      pdat::SideData<double>& flux_data,
-      const hier::IntVector& ratio_to_coarser) const;
-
-   /*!
-    * @brief AMR-unaware function to compute residual on a single patch,
-    * with variable scalar field.
-    *
-    * @param patch patch
-    * @param flux_data side-centered flux data
-    * @param soln_data cell-centered solution data
-    * @param rhs_data cell-centered rhs data
-    * @param residual_data cell-centered residual data
-    */
-   void
-   computeResidualOnPatch(
-      const hier::Patch& patch,
-      const pdat::SideData<double>& flux_data,
-      const pdat::CellData<double>& soln_data,
-      const pdat::CellData<double>& rhs_data,
-      pdat::CellData<double>& residual_data) const;
-
-   /*!
-    * @brief AMR-unaware function to red or black smoothing on a single patch,
-    * for variable diffusion coefficient and variable scalar field.
-    *
-    * @param patch patch
-    * @param flux_data side-centered flux data
-    * @param rhs_data cell-centered rhs data
-    * @param scalar_field_data
-    *        cell-centered scalar field data
-    * @param soln_data cell-centered solution data
-    * @param red_or_black red-black switch.  Set to 'r' or 'b'.
-    * @param p_maxres max residual output.  Set to NULL to avoid computing.
-    */
-   void
-   redOrBlackSmoothingOnPatch(
-      const hier::Patch& patch,
-      const pdat::SideData<double>& flux_data,
-      const pdat::CellData<double>& rhs_data,
-      pdat::CellData<double>& soln_data,
-      char red_or_black,
-      double* p_maxres = NULL) const;
-
-   //@}
-
-   //@{ @name For executing, caching and resetting communication schedules.
-
-   /*!
-    * @brief Execute a refinement schedule
-    * for prolonging cell data.
-    *
-    * General notes regarding internal objects for communication:
-    * We maintain objects to support caching schedules to improve
-    * efficiency.  Communication is needed in 5 distinct tasks.
-    *   -# Prolongation
-    *   -# Restriction
-    *   -# Flux coarsening.  Changing the coarse grid flux to the
-    *      composite grid flux by coarsening the fine grid flux
-    *      at the coarse-fine boundaries.
-    *   -# Fill boundary data from other patches in the same level
-    *      and physical boundary condition.
-    *   -# Fill boundary data from same level, coarser levels
-    *      and physical boundary condition.
-    *
-    * For each task, we maintain a refine or coarsen operator,
-    * and a array of communication schedules (one for each
-    * destination level).
-    *
-    * The 5 member functions named @c xeqSchedule... execute
-    * communication schedules appropriate for five specific tasks.
-    * They use a cached schedule if possible or create and cache
-    * a new schedule if needed.  These functions and the data
-    * they manipulate are as follows:
-    * <ol>
-    *   <li> xeqScheduleProlongation():
-    *        d_prolongation_refine_operator
-    *        d_prolongation_refine_schedules
-    *   <li> xeqScheduleURestriction():
-    *        d_restriction_coarsen_operator,
-    *        d_urestriction_coarsen_schedules.
-    *   <li> xeqScheduleRRestriction():
-    *        d_restriction_coarsen_operator,
-    *        d_rrestriction_coarsen_schedules.
-    *   <li> xeqScheduleFluxCoarsen():
-    *        d_flux_coarsen_operator,
-    *        d_flux_coarsen_schedules.
-    *   <li> xeqScheduleGhostFill():
-    *        d_ghostfill_refine_operator,
-    *        d_ghostfill_refine_schedules.
-    *   <li> xeqScheduleGhostFillNoCoarse():
-    *        d_ghostfill_nocoarse_refine_operator,
-    *        d_ghostfill_nocoarse_refine_schedules.
-    * </ol>
-    *
-    * @return refinement schedule for prolongation
-    */
-   void
-   xeqScheduleProlongation(
-      int dst_id,
-      int src_id,
-      int scr_id,
-      int dest_ln);
-
-   /*!
-    * @brief Execute schedule for restricting solution to the specified
-    * level or reregister an existing one.
-    *
-    * See general notes for xeqScheduleProlongation().
-    *
-    * @return coarsening schedule for restriction
-    */
-   void
-   xeqScheduleURestriction(
-      int dst_id,
-      int src_id,
-      int dest_ln);
-
-   /*!
-    * @brief Execute schedule for restricting residual to the specified
-    * level or reregister an existing one.
-    *
-    * See general notes for xeqScheduleProlongation().
-    *
-    * @return coarsening schedule for restriction
-    */
-   void
-   xeqScheduleRRestriction(
-      int dst_id,
-      int src_id,
-      int dest_ln);
-
-   /*!
-    * @brief Execute schedule for coarsening flux to the specified
-    * level or reregister an existing one.
-    *
-    * See general notes for xeqScheduleProlongation().
-    *
-    * @return coarsening schedule for setting composite grid flux at
-    * coarse-fine boundaries.
-    */
-   void
-   xeqScheduleFluxCoarsen(
-      int dst_id,
-      int src_id,
-      int dest_ln);
-
-   /*!
-    * @brief Execute schedule for filling ghosts on the specified
-    * level or reregister an existing one.
-    *
-    * See general notes for xeqScheduleProlongation().
-    *
-    * @return refine schedule for filling ghost data from coarser level
-    * and physical bc.
-    */
-   void
-   xeqScheduleGhostFill(
-      int dst_id,
-      int dest_ln);
-
-   /*!
-    * @brief Execute schedule for filling ghosts on the specified
-    * level or reregister an existing one.
-    * This version does not get data from coarser levels.
-    *
-    * See general notes for xeqScheduleProlongation().
-    *
-    * This function is used for the bottom solve level, since it does
-    * not access data from any coarser level.  (Ghost data obtained
-    * from coarser level must have been placed there before solve begins!)
-    *
-    * @return refine schedule for filling ghost data from same level
-    * and physical bc.
-    */
-   void
-   xeqScheduleGhostFillNoCoarse(
-      int dst_id,
-      int dest_ln);
-
-   //@}
-
-   //! @brief Return the patch data index for cell scratch data.
-   int
-   registerCellScratch() const;
-   //! @brief Return the patch data index for flux scratch data.
-   int
-   registerFluxScratch() const;
-   //! @brief Return the patch data index for outerflux scratch data.
-   int
-   registerOfluxScratch() const;
-
-   //! @brief Free static variables at shutdown time.
-   static void
-   finalizeCallback();
-
-   /*!
-    * @brief Object dimension.
-    */
-   const tbox::Dimension d_dim;
-
-   /*!
-    * @brief Object name.
-    */
-   std::string d_object_name;
-
-   //@{ @name Hierarchy-dependent objects.
-
-   /*!
-    * @brief Reference hierarchy
-    *
-    * This variable is non-null between the initializeOperatorState()
-    * and deallocateOperatorState() calls.  It is not truly needed,
-    * because the hierarchy is obtainable through variables in most
-    * function argument lists.  We use it to enforce working on one
-    * hierarchy at a time.
-    */
-   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
-
-   /*!
-    * @brief Coarsest level for solve.
-    */
-   int d_ln_min;
-
-   /*!
-    * @brief Finest level for solve.
-    */
-   int d_ln_max;
-
-   /*!
-    * @brief Description of coarse-fine boundaries.
-    *
-    * There is one coarse-fine boundary object for each level.
-    * d_coarse_fine_boundary[i] is the description of
-    * the coarse-fine boundary between level i and level i-1.
-    * The coarse-fine boundary does not exist at the coarsest level,
-    * although the hier::CoarseFineBoundary object still exists (it
-    * should not contain any boxes).
-    *
-    * This array is initialized in initializeOperatorState() and
-    * deallocated in deallocateOperatorState().  When allocated,
-    * it is allocated for the index range [0,d_ln_max], though
-    * the range [0,d_ln_min-1] is not used.  This is okay because
-    * hier::CoarseFineBoundary is a light object before
-    * it is set for a level.
-    */
-   tbox::Array<tbox::Pointer<hier::CoarseFineBoundary> > d_cf_boundary;
-
-   //@}
-
-   //@{
-   /*!
-    * @name Private state variables for solution process.
-    */
-
-   /*!
-    * @brief Scalar Stokes equations specifications.
-    * @see setStokesSpecifications().
-    */
-   StokesSpecifications d_stokes_spec;
-
-   /*!
-    * @brief Smoothing choice.
-    * @see setSmoothingChoice.
-    */
-   std::string d_smoothing_choice;
-
-   /*!
-    * @brief Coarse level solver.
-    * @see setCoarsestLevelSolverChoice
-    */
-   std::string d_coarse_solver_choice;
-
-   /*!
-    * @brief Coarse-fine discretization method.
-    * @see setCoarseFineDiscretization().
-    */
-   std::string d_cf_discretization;
-
-   /*!
-    * @brief Coarse-fine discretization method.
-    *
-    * The name of the refinement operator used to prolong the
-    * coarse grid correction.
-    *
-    * @see setProlongationMethod()
-    */
-   std::string d_prolongation_method;
-
-   /*!
-    * @brief Tolerance specified to coarse solver
-    * @see setCoarsestLevelSolverTolerance()
-    */
-   double d_coarse_solver_tolerance;
-
-   /*!
-    * @brief Coarse level solver iteration limit.
-    * @see setCoarsestLevelSolverMaxIterations()
-    */
-   int d_coarse_solver_max_iterations;
-
-   /*!
-    * @brief Residual tolerance to govern smoothing.
-    *
-    * When we use one of the internal error smoothing functions
-    * and want to terminate the smoothing sweeps at a certain
-    * level of residual, this will be set to > 0.  If it is
-    * < 0, the smoothing function effectively ignores it.
-    *
-    * This variable is needed because some coarse-level solver
-    * simply runs the smoothing function until convergence.
-    * It sets this variable to > 0, calls the smoothing function,
-    * then resets it to < 0.
-    */
-   double d_residual_tolerance_during_smoothing;
-
-   /*!
-    * @brief Id of the flux.
-    *
-    * If set to -1, create and delete storage space on the fly.
-    * Else, user has provided space for flux.
-    *
-    * @see setFluxId
-    */
-   int d_flux_id;
-
-#ifdef HAVE_HYPRE
-   /*!
-    * @brief HYPRE coarse-level solver object.
-    */
-   CellStokesHypreSolver d_hypre_solver;
-#endif
-
-   /*!
-    * @brief Externally provided physical boundary condition object.
-    *
-    * see setPhysicalBcCoefObject()
-    */
-   const RobinBcCoefStrategy* d_physical_bc_coef;
-
-   //@}
-
-   //@{ @name Internal context and scratch data
-
-   static tbox::Pointer<pdat::CellVariable<double> >
-   s_cell_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-   static tbox::Pointer<pdat::SideVariable<double> >
-   s_flux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-   static tbox::Pointer<pdat::OutersideVariable<double> >
-   s_oflux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-   /*!
-    * @brief Default context of internally maintained hierarchy data.
-    */
-   tbox::Pointer<hier::VariableContext> d_context;
-
-   /*!
-    * @brief ID of the solution-like scratch data.
-    *
-    * Set in constructor and never changed.
-    * Corresponds to a pdat::CellVariable<double> named
-    * @c d_object_name+"::cell_scratch".
-    * Scratch data is allocated and removed as needed
-    * to reduce memory usage.
-    */
-   int d_cell_scratch_id;
-
-   /*!
-    * @brief ID of the side-centered scratch data.
-    *
-    * Set in constructor and never changed.
-    * Corresponds to a pdat::SideVariable<double> named
-    * @c d_object_name+"::flux_scratch".
-    *
-    * This data is allocated only as needed and deallocated
-    * immediately after use.
-    */
-   int d_flux_scratch_id;
-
-   /*!
-    * @brief ID of the outerside-centered scratch data.
-    *
-    * Set in constructor and never changed.
-    * Corresponds to a pdat::OutersideVariable<double> named
-    * @c d_object_name+"::oflux_scratch".
-    */
-   int d_oflux_scratch_id;
-
-   //@}
-
-   //@{
-   /*!
-    * @name Various refine and coarsen objects used internally.
-    */
-
-   //! @brief Error prolongation (refinement) operator.
-   tbox::Pointer<xfer::RefineOperator> d_prolongation_refine_operator;
-   tbox::Pointer<xfer::RefineAlgorithm> d_prolongation_refine_algorithm;
-   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
-   d_prolongation_refine_schedules;
-
-   //! @brief Solution restriction (coarsening) operator.
-   tbox::Pointer<xfer::CoarsenOperator> d_urestriction_coarsen_operator;
-   tbox::Pointer<xfer::CoarsenAlgorithm> d_urestriction_coarsen_algorithm;
-   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
-   d_urestriction_coarsen_schedules;
-
-   //! @brief Residual restriction (coarsening) operator.
-   tbox::Pointer<xfer::CoarsenOperator> d_rrestriction_coarsen_operator;
-   tbox::Pointer<xfer::CoarsenAlgorithm> d_rrestriction_coarsen_algorithm;
-   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
-   d_rrestriction_coarsen_schedules;
-
-   //! @brief Coarsen operator for outerflux-to-flux
-   tbox::Pointer<xfer::CoarsenOperator> d_flux_coarsen_operator;
-   tbox::Pointer<xfer::CoarsenAlgorithm> d_flux_coarsen_algorithm;
-   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
-   d_flux_coarsen_schedules;
-
-   //! @brief Refine operator for cell-like data from coarser level.
-   tbox::Pointer<xfer::RefineOperator> d_ghostfill_refine_operator;
-   tbox::Pointer<xfer::RefineAlgorithm> d_ghostfill_refine_algorithm;
-   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
-   d_ghostfill_refine_schedules;
-
-   //! @brief Refine operator for cell-like data from same level.
-   tbox::Pointer<xfer::RefineOperator> d_ghostfill_nocoarse_refine_operator;
-   tbox::Pointer<xfer::RefineAlgorithm> d_ghostfill_nocoarse_refine_algorithm;
-   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
-   d_ghostfill_nocoarse_refine_schedules;
-
-   //@}
-
-   /*!
-    * @brief Utility object employed in setting ghost cells and providing
-    * xfer::RefinePatchStrategy implementation.
-    *
-    * Since this class deals only in scalar variables having
-    * Robin boundary conditions, we take advantage of the corresponding
-    * implementation in CartesianRobinBcHelper.  Whenever
-    * we need an implementation of xfer::RefinePatchStrategy,
-    * this object is used.  Note that in the code, before we
-    * use this object to set ghost cell values, directly or
-    * indirectly by calling xfer::RefineSchedule::fillData(),
-    * we must tell d_bc_helper the patch data index we want
-    * to set and whether we are setting data with homogeneous
-    * boundary condition.
-    */
-   CartesianRobinBcHelper d_bc_helper;
-
-   //@{
-   /*!
-    * @name Non-essential objects used in outputs and debugging.
-    */
-
-   /*!
-    * @brief Logging flag.
-    */
-   bool d_enable_logging;
-
-   /*!
-    * @brief Preconditioner using this object.
-    *
-    * See setPreconditioner().
-    */
-   const FACPreconditioner* d_preconditioner;
-
-   /*!
-    * @brief Hierarchy cell operator used in debugging.
-    */
-   tbox::Pointer<math::HierarchyCellDataOpsReal<double> > d_hopscell;
-
-   /*!
-    * @brief Hierarchy side operator used in debugging.
-    */
-   tbox::Pointer<math::HierarchySideDataOpsReal<double> > d_hopsside;
-
-   /*!
-    * @brief Timers for performance measurement.
-    */
-   tbox::Pointer<tbox::Timer> t_restrict_solution;
-   tbox::Pointer<tbox::Timer> t_restrict_residual;
-   tbox::Pointer<tbox::Timer> t_prolong;
-   tbox::Pointer<tbox::Timer> t_smooth_error;
-   tbox::Pointer<tbox::Timer> t_solve_coarsest;
-   tbox::Pointer<tbox::Timer> t_compute_composite_residual;
-   tbox::Pointer<tbox::Timer> t_compute_residual_norm;
-
-   static tbox::StartupShutdownManager::Handler
-   s_finalize_handler;
-};
-
-}
-}
-
-#ifdef SAMRAI_INLINE
-#include "CellStokesFACOps.I"
-#endif
-
-#endif // included_solv_CellStokesFACOps
diff -r a44a82f15794 -r fe2a9230921b CellStokesFACSolver.C
--- a/CellStokesFACSolver.C	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,585 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   High-level solver (wrapper) for scalar stokes equation. 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesFACSolver_C
-#define included_solv_CellStokesFACSolver_C
-
-#include "SAMRAI/pdat/CellVariable.h"
-#include "CellStokesFACSolver.h"
-#include "SAMRAI/tbox/PIO.h"
-#include "SAMRAI/tbox/Utilities.h"
-#include "SAMRAI/tbox/StartupShutdownManager.h"
-
-#include IOMANIP_HEADER_FILE
-
-#ifndef SAMRAI_INLINE
-#include "CellStokesFACSolver.I"
-#endif
-
-namespace SAMRAI {
-namespace solv {
-
-/*
- *************************************************************************
- *                                                                       *
- * Initialize the static data members.                                   *
- *                                                                       *
- *************************************************************************
- */
-
-bool CellStokesFACSolver::s_initialized = 0;
-int CellStokesFACSolver::s_weight_id[SAMRAI::tbox::Dimension::
-                                      MAXIMUM_DIMENSION_VALUE];
-int CellStokesFACSolver::s_instance_counter[SAMRAI::tbox::Dimension::
-                                             MAXIMUM_DIMENSION_VALUE];
-
-/*
- *************************************************************************
- *                                                                       *
- * Constructor sets uninitialized solver state.                          *
- * Set default iteration and convergence parameters.                     *
- *                                                                       *
- * By default settings:                                                  *
- *   - Stokes equation specified has D=1, C=0.                          *
- *   - State is uninitialized                                            *
- *   - Logging is disabled                                               *
- *   - Context for internal data is set based on object name.            *
- *                                                                       *
- *************************************************************************
- */
-
-CellStokesFACSolver::CellStokesFACSolver(
-   const tbox::Dimension& dim,
-   const std::string& object_name,
-   tbox::Pointer<tbox::Database> database):
-   d_dim(dim),
-   d_object_name(object_name),
-   d_stokes_spec(object_name + "::stokes_spec"),
-   d_fac_ops(d_dim, object_name + "::fac_ops"),
-   d_fac_precond(object_name + "::fac_precond", d_fac_ops),
-   d_bc_object(NULL),
-   d_simple_bc(d_dim, object_name + "::bc"),
-   d_hierarchy(NULL),
-   d_ln_min(-1),
-   d_ln_max(-1),
-   d_context(hier::VariableDatabase::getDatabase()
-             ->getContext(object_name + "::CONTEXT")),
-   d_uv(NULL),
-   d_fv(NULL),
-   d_solver_is_initialized(false),
-   d_enable_logging(false)
-{
-
-   if (!s_initialized) {
-      initializeStatics();
-   }
-
-   setMaxCycles(10);
-   setResidualTolerance(1e-6);
-   setPresmoothingSweeps(1);
-   setPostsmoothingSweeps(1);
-   setCoarseFineDiscretization("Ewing");
-#ifdef HAVE_HYPRE
-   setCoarsestLevelSolverChoice("hypre");
-   setCoarsestLevelSolverTolerance(1e-10);
-   setCoarsestLevelSolverMaxIterations(20);
-   setUseSMG(true);
-#else
-   setCoarsestLevelSolverChoice("redblack");
-   setCoarsestLevelSolverTolerance(1e-8);
-   setCoarsestLevelSolverMaxIterations(500);
-#endif
-
-   /*
-    * Construct integer tag variables and add to variable database.  Note that
-    * variables and patch data indices are shared among all instances.
-    * The VariableDatabase holds the variables, once contructed and
-    * registered via the VariableDatabase::registerInternalSAMRAIVariable()
-    * function call.  Note that variables are registered and patch data indices
-    * are made only for the first time through the constructor.
-    */
-   hier::VariableDatabase* var_db = hier::VariableDatabase::getDatabase();
-
-   static std::string weight_variable_name("CellStokesFACSolver_weight");
-
-   tbox::Pointer<pdat::CellVariable<double> > weight = var_db->getVariable(
-         weight_variable_name);
-   if (weight.isNull()) {
-      weight = new pdat::CellVariable<double>(d_dim, weight_variable_name, 1);
-   }
-
-   if (s_weight_id[d_dim.getValue() - 1] < 0) {
-      s_weight_id[d_dim.getValue() - 1] = var_db->registerInternalSAMRAIVariable(
-            weight,
-            hier::IntVector::getZero(d_dim));
-   }
-
-   /*
-    * The default RobinBcCoefStrategy used,
-    * SimpleCellRobinBcCoefs only works with constant refine
-    * for prolongation.  So we use constant refinement
-    * for prolongation by default.
-    */
-   setProlongationMethod("CONSTANT_REFINE");
-
-   /*
-    * The FAC operator optionally uses the preconditioner
-    * to get data for logging.
-    */
-   d_fac_ops.setPreconditioner((const FACPreconditioner *)(&d_fac_precond));
-
-   if (database) {
-      getFromInput(database);
-   }
-
-   s_instance_counter[d_dim.getValue() - 1]++;
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Destructor for CellStokesFACSolver.                            *
- * Deallocate internal data.                                             *
- *                                                                       *
- *************************************************************************
- */
-
-CellStokesFACSolver::~CellStokesFACSolver()
-{
-   s_instance_counter[d_dim.getValue() - 1]--;
-
-   deallocateSolverState();
-
-   if (s_instance_counter[d_dim.getValue() - 1] == 0) {
-      hier::VariableDatabase::getDatabase()->
-      removeInternalSAMRAIVariablePatchDataIndex(s_weight_id[d_dim.getValue() - 1]);
-      s_weight_id[d_dim.getValue() - 1] = -1;
-   }
-}
-
-/*
- ********************************************************************
- * Set state from database                                          *
- *                                                                  *
- * Do not allow FAC preconditioner and Stokes FAC operators to be  *
- * set from database, as that may cause them to be inconsistent     *
- * with this object if user does not coordinate the inputs          *
- * correctly.  This is also why we don't allow direct access to     *
- * those objects.  The responsibility for maintaining consistency   *
- * lies in the public functions to set parameters, so use them      *
- * instead of setting the parameters directly in this function.     *
- ********************************************************************
- */
-
-void CellStokesFACSolver::getFromInput(
-   tbox::Pointer<tbox::Database> database)
-{
-   if (database) {
-      if (database->isBool("enable_logging")) {
-         bool logging = database->getBool("enable_logging");
-         enableLogging(logging);
-      }
-      if (database->isInteger("max_cycles")) {
-         int max_cycles = database->getInteger("max_cycles");
-         setMaxCycles(max_cycles);
-      }
-      if (database->isDouble("residual_tol")) {
-         double residual_tol = database->getDouble("residual_tol");
-         setResidualTolerance(residual_tol);
-      }
-      if (database->isInteger("num_pre_sweeps")) {
-         int num_pre_sweeps = database->getInteger("num_pre_sweeps");
-         setPresmoothingSweeps(num_pre_sweeps);
-      }
-      if (database->isInteger("num_post_sweeps")) {
-         int num_post_sweeps = database->getInteger("num_post_sweeps");
-         setPostsmoothingSweeps(num_post_sweeps);
-      }
-      if (database->isString("coarse_fine_discretization")) {
-         std::string s = database->getString("coarse_fine_discretization");
-         setCoarseFineDiscretization(s);
-      }
-      if (database->isString("prolongation_method")) {
-         std::string s = database->getString("prolongation_method");
-         setProlongationMethod(s);
-      }
-      if (database->isString("coarse_solver_choice")) {
-         std::string s = database->getString("coarse_solver_choice");
-         setCoarsestLevelSolverChoice(s);
-      }
-      if (database->isDouble("coarse_solver_tolerance")) {
-         double tol = database->getDouble("coarse_solver_tolerance");
-         setCoarsestLevelSolverTolerance(tol);
-      }
-      if (database->isInteger("coarse_solver_max_iterations")) {
-         int itr = database->getInteger("coarse_solver_max_iterations");
-         setCoarsestLevelSolverMaxIterations(itr);
-      }
-#ifdef HAVE_HYPRE
-      if (database->isBool("use_smg")) {
-         bool smg = database->getBool("use_smg");
-         setUseSMG(smg);
-      }
-#endif
-   }
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Prepare internal data for solve.                                      *
- * Allocate scratch data.  Create vectors for u and f                    *
- * required by the FACPreconditioner interface.                    *
- * Set up internal boundary condition object.                            *
- * Share data to coordinate with FAC preconditioner and                  *
- * Stokes FAC operator.                                                 *
- *                                                                       *
- *************************************************************************
- */
-
-void CellStokesFACSolver::initializeSolverState(
-   const int solution,
-   const int rhs,
-   tbox::Pointer<hier::PatchHierarchy> hierarchy,
-   const int coarse_level,
-   const int fine_level)
-{
-   TBOX_ASSERT(!hierarchy.isNull());
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
-
-   if (d_bc_object == NULL) {
-      TBOX_ERROR(
-         d_object_name << ": No BC coefficient strategy object!\n"
-         <<
-         "Use either setBoundaries or setPhysicalBcCoefObject\n"
-         << "to specify the boundary conidition.\n");
-   }
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (solution < 0 || rhs < 0) {
-      TBOX_ERROR(d_object_name << ": Bad patch data id.\n");
-   }
-#endif
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (!hierarchy) {
-      TBOX_ERROR(d_object_name << ": NULL hierarchy pointer not allowed\n"
-                               << "in inititialization.");
-   }
-#endif
-   d_hierarchy = hierarchy;
-
-   d_ln_min = coarse_level;
-   d_ln_max = fine_level;
-   if (d_ln_min == -1) {
-      d_ln_min = 0;
-   }
-   if (d_ln_max == -1) {
-      d_ln_max = d_hierarchy->getFinestLevelNumber();
-   }
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (d_ln_min < 0 || d_ln_max < 0 || d_ln_min > d_ln_max) {
-      TBOX_ERROR(d_object_name << ": Bad range of levels in\n"
-                               << "inititialization.\n");
-   }
-#endif
-
-   int ln;
-   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
-      d_hierarchy->getPatchLevel(ln)->allocatePatchData(s_weight_id[d_dim.getValue() - 1]);
-   }
-
-   d_fac_ops.computeVectorWeights(d_hierarchy,
-      s_weight_id[d_dim.getValue() - 1],
-      d_ln_min,
-      d_ln_max);
-
-   if (d_bc_object == &d_simple_bc) {
-      d_simple_bc.setHierarchy(d_hierarchy,
-         d_ln_min,
-         d_ln_max);
-      if (d_stokes_spec.dIsConstant()) {
-         d_simple_bc.setDiffusionCoefConstant(d_stokes_spec.getDConstant());
-      } else {
-         d_simple_bc.setDiffusionCoefId(d_stokes_spec.getDPatchDataId());
-      }
-   }
-
-   d_fac_ops.setStokesSpecifications(d_stokes_spec);
-
-   createVectorWrappers(solution, rhs);
-
-   d_fac_precond.initializeSolverState(*d_uv, *d_fv);
-
-   d_solver_is_initialized = true;
-}
-
-void CellStokesFACSolver::deallocateSolverState()
-{
-   if (d_hierarchy) {
-
-      d_fac_precond.deallocateSolverState();
-
-      /*
-       * Delete internally managed data.
-       */
-      int ln;
-      for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
-         d_hierarchy->getPatchLevel(ln)->deallocatePatchData(s_weight_id[d_dim.getValue()
-                                                                         - 1]);
-      }
-
-      d_hierarchy.setNull();
-      d_ln_min = -1;
-      d_ln_max = -1;
-      d_solver_is_initialized = false;
-
-      destroyVectorWrappers();
-
-   }
-}
-
-/*
- *************************************************************************
- * Enable logging and propagate logging flag to major components.        *
- *************************************************************************
- */
-
-void CellStokesFACSolver::enableLogging(
-   bool logging)
-{
-   d_enable_logging = logging;
-   d_fac_precond.enableLogging(d_enable_logging);
-   d_fac_ops.enableLogging(d_enable_logging);
-}
-
-void CellStokesFACSolver::setBoundaries(
-   const std::string& boundary_type,
-   const int fluxes,
-   const int flags,
-   int* bdry_types)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (d_bc_object != NULL && d_bc_object != &d_simple_bc) {
-      TBOX_ERROR(
-         d_object_name << ": Bad attempt to set boundary condition\n"
-         <<
-         "by using default bc object after it has been overriden.\n");
-   }
-#endif
-   d_simple_bc.setBoundaries(boundary_type,
-      fluxes,
-      flags,
-      bdry_types);
-   d_bc_object = &d_simple_bc;
-   d_fac_ops.setPhysicalBcCoefObject(d_bc_object);
-}
-
-void CellStokesFACSolver::setBcObject(
-   const RobinBcCoefStrategy* bc_object)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (!bc_object) {
-      TBOX_ERROR(d_object_name << ": NULL pointer for boundary condition\n"
-                               << "object.\n");
-   }
-#endif
-   d_bc_object = bc_object;
-   d_fac_ops.setPhysicalBcCoefObject(d_bc_object);
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Solve the linear system and report whether iteration converged.       *
- *                                                                       *
- * This version is for an initialized solver state.                      *
- * Before solving, set the final piece of the boundary condition,        *
- * which is not known until now, and initialize some internal            *
- * solver quantities.                                                    *
- *                                                                       *
- *************************************************************************
- */
-
-bool CellStokesFACSolver::solveSystem(
-   const int u,
-   const int f)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (!d_solver_is_initialized) {
-      TBOX_ERROR(
-         d_object_name << ".solveSystem(int,int): uninitialized\n"
-         <<
-         "solver state.  You must call initializeSolverState()\n"
-         <<
-         "before using this function.  Or you can use\n"
-         <<
-         "solveSystem(int,int,...) to initialize the solver,\n"
-         << "solve and deallocate the solver.\n");
-   }
-   if (u < 0 || f < 0) {
-      TBOX_ERROR(d_object_name << ": Bad patch data id.\n");
-   }
-#endif
-   if (d_bc_object == &d_simple_bc) {
-      /*
-       * Knowing that we are using the SimpelCellRobinBcCoefsX
-       * implementation of RobinBcCoefStrategy, we must save
-       * the ghost data in u before solving.
-       * The solver overwrites it, but SimpleCellRobinBcCoefs
-       * needs to get to access it repeatedly.
-       */
-      d_simple_bc.cacheDirichletData(u);
-   }
-
-   createVectorWrappers(u, f);
-   bool solver_rval;
-   solver_rval = d_fac_precond.solveSystem(*d_uv, *d_fv);
-
-   if (d_bc_object == &d_simple_bc) {
-      /*
-       * Restore the Dirichlet cell data that were overwritten by the
-       * solve process.  We do this to be backward compatible with the
-       * user code.
-       */
-      d_simple_bc.restoreDirichletData(u);
-   }
-
-   return solver_rval;
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Solve the linear system and report whether iteration converged.       *
- *                                                                       *
- * This version is for an uninitialized solver state.                    *
- * 1. Initialize the (currently uninitialized) solver state.             *
- * 2. Solve.                                                             *
- * 3. Deallocate the solver state.                                       *
- *                                                                       *
- *************************************************************************
- */
-
-bool CellStokesFACSolver::solveSystem(
-   const int u,
-   const int f,
-   tbox::Pointer<hier::PatchHierarchy> hierarchy,
-   int coarse_ln,
-   int fine_ln)
-{
-   TBOX_ASSERT(!hierarchy.isNull());
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
-
-   if (d_enable_logging) {
-      tbox::plog << "CellStokesFACSolver::solveSystem (" << d_object_name
-                 << ")\n";
-      d_stokes_spec.printClassData(tbox::plog);
-   }
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (d_solver_is_initialized) {
-      TBOX_ERROR(
-         d_object_name << ".solveSystem(int,int,...): initialized\n"
-         <<
-         "solver state.  This function can only used when the\n"
-         <<
-         "solver state is uninitialized.  You should deallocate\n"
-         <<
-         "the solver state or use solveSystem(int,int).\n");
-   }
-   if (!hierarchy) {
-      TBOX_ERROR(d_object_name << ".solveSystem(): Null hierarchy\n"
-                               << "specified.\n");
-   }
-#endif
-   initializeSolverState(u, f, hierarchy, coarse_ln, fine_ln);
-
-   bool solver_rval;
-   solver_rval = solveSystem(u, f);
-
-   deallocateSolverState();
-
-   return solver_rval;
-}
-
-void CellStokesFACSolver::createVectorWrappers(
-   int u,
-   int f) {
-
-   hier::VariableDatabase& vdb(*hier::VariableDatabase::getDatabase());
-   tbox::Pointer<hier::Variable> variable;
-
-   if (!d_uv || d_uv->getComponentDescriptorIndex(0) != u) {
-      d_uv.setNull();
-      d_uv = new SAMRAIVectorReal<double>(d_object_name + "::uv",
-                                          d_hierarchy,
-                                          d_ln_min,
-                                          d_ln_max);
-      vdb.mapIndexToVariable(u, variable);
-#ifdef DEBUG_CHECK_ASSERTIONS
-      if (!variable) {
-         TBOX_ERROR(d_object_name << ": No variable for patch data index "
-                                  << u << "\n");
-      }
-      tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
-      if (!cell_variable) {
-         TBOX_ERROR(d_object_name << ": hier::Patch data index " << u
-                                  << " is not a cell-double variable.\n");
-      }
-#endif
-      d_uv->addComponent(variable, u, s_weight_id[d_dim.getValue() - 1]);
-   }
-
-   if (!d_fv || d_fv->getComponentDescriptorIndex(0) != f) {
-      d_fv.setNull();
-      d_fv = new SAMRAIVectorReal<double>(d_object_name + "::fv",
-                                          d_hierarchy,
-                                          d_ln_min,
-                                          d_ln_max);
-      vdb.mapIndexToVariable(f, variable);
-#ifdef DEBUG_CHECK_ASSERTIONS
-      if (!variable) {
-         TBOX_ERROR(d_object_name << ": No variable for patch data index "
-                                  << f << "\n");
-      }
-      tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
-      if (!cell_variable) {
-         TBOX_ERROR(d_object_name << ": hier::Patch data index " << f
-                                  << " is not a cell-double variable.\n");
-      }
-#endif
-      d_fv->addComponent(variable, f, s_weight_id[d_dim.getValue() - 1]);
-   }
-}
-
-/*
- ***********************************************************************
- * Delete the vector wrappers.  Do not freeVectorComponents because    *
- * we do not control their data allocation.  The user does that.       *
- ***********************************************************************
- */
-void CellStokesFACSolver::destroyVectorWrappers() {
-   d_uv.setNull();
-   d_fv.setNull();
-}
-
-void CellStokesFACSolver::initializeStatics() {
-
-   for (int d = 0; d < SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
-      s_weight_id[d] = -1;
-      s_instance_counter[d] = -1;
-   }
-
-   s_initialized = 1;
-}
-
-}
-}
-#endif
diff -r a44a82f15794 -r fe2a9230921b CellStokesFACSolver.I
--- a/CellStokesFACSolver.I	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   High-level solver (wrapper) for scalar stokes equation. 
- *
- ************************************************************************/
-namespace SAMRAI {
-namespace solv {
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setDPatchDataId(
-   int id) {
-   d_stokes_spec.setDPatchDataId(id);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setDConstant(
-   double scalar) {
-   d_stokes_spec.setDConstant(scalar);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCPatchDataId(
-   int id) {
-   d_stokes_spec.setCPatchDataId(id);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCConstant(
-   double scalar) {
-// Disable Intel warning on real comparison
-#ifdef __INTEL_COMPILER
-#pragma warning (disable:1572)
-#endif
-   if (scalar == 0.0) {
-      d_stokes_spec.setCZero();
-   } else {
-      d_stokes_spec.setCConstant(scalar);
-   }
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setProlongationMethod(
-   const std::string& prolongation_method)
-{
-   d_fac_ops.setProlongationMethod(prolongation_method);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCoarsestLevelSolverChoice(
-   const std::string& choice)
-{
-   d_fac_ops.setCoarsestLevelSolverChoice(choice);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCoarsestLevelSolverTolerance(
-   double tol)
-{
-   d_fac_ops.setCoarsestLevelSolverTolerance(tol);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCoarsestLevelSolverMaxIterations(
-   int max_iterations)
-{
-   d_fac_ops.setCoarsestLevelSolverMaxIterations(max_iterations);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setCoarseFineDiscretization(
-   const std::string& coarsefine_method)
-{
-   d_fac_ops.setCoarseFineDiscretization(coarsefine_method);
-}
-
-#ifdef HAVE_HYPRE
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setUseSMG(
-   bool use_smg)
-{
-   if (d_solver_is_initialized) {
-      TBOX_ERROR(
-         d_object_name << ": setUseSMG(bool) may NOT be called\n"
-         <<
-         "while the solver state is initialized, as that\n"
-         << "would lead to a corrupted solver state.\n");
-   }
-   d_fac_ops.setUseSMG(use_smg);
-}
-#endif
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setPresmoothingSweeps(
-   int num_pre_sweeps) {
-   d_fac_precond.setPresmoothingSweeps(num_pre_sweeps);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setPostsmoothingSweeps(
-   int num_post_sweeps) {
-   d_fac_precond.setPostsmoothingSweeps(num_post_sweeps);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setMaxCycles(
-   int max_cycles) {
-   d_fac_precond.setMaxCycles(max_cycles);
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::setResidualTolerance(
-   double residual_tol) {
-   d_fac_precond.setResidualTolerance(residual_tol);
-}
-
-SAMRAI_INLINE_KEYWORD
-int CellStokesFACSolver::getNumberOfIterations() const
-{
-   return d_fac_precond.getNumberOfIterations();
-}
-
-SAMRAI_INLINE_KEYWORD
-double CellStokesFACSolver::getResidualNorm() const
-{
-   return d_fac_precond.getResidualNorm();
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesFACSolver::getConvergenceFactors(
-   double& avg_factor,
-   double& final_factor)
-const
-{
-   d_fac_precond.getConvergenceFactors(avg_factor, final_factor);
-}
-
-}
-}
diff -r a44a82f15794 -r fe2a9230921b CellStokesFACSolver.h
--- a/CellStokesFACSolver.h	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,660 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   High-level solver (wrapper) for scalar stokes equation. 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesFACSolver
-#define included_solv_CellStokesFACSolver
-
-#include "SAMRAI/SAMRAI_config.h"
-
-#include "SAMRAI/solv/FACPreconditioner.h"
-#include "CellStokesFACOps.h"
-#include "StokesSpecifications.h"
-#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
-#include "SAMRAI/tbox/Database.h"
-#include "SAMRAI/tbox/Pointer.h"
-
-namespace SAMRAI {
-namespace solv {
-
-/*!
- * @brief Class for solving scalar Stokes's equation on SAMR grid,
- * wrapping up lower-level components (FAC cycling, Stokes equation
- * operations and boundary conditions) in a single high-level interface.
- *
- * Note: this class provides a backward-compatible interface to
- * the soon-to-be obsolete StokesHierarchySolver<DIM> class.
- * Although this class hides the lower-level components (FAC cycling,
- * Stokes equation operations and boundary conditions), it is
- * perfectly acceptable to use those lower-level components directly.
- *
- * We solve the equation
- *    div(D grad(u)) + Cu = f
- * where D is a side-centered array and C is a cell-centered array.
- * u and f are also cell-centered.
- * Boundary conditions supported are Dirichlet, Neumann and mixed
- * (Dirichlet on some faces and Neumann on others).
- *
- * This class is a wrapper, providing a single class that coordinates
- * three major components: the FAC solver, the cell-centered Stokes
- * FAC operator and a default Robin bc coefficient implelemtation.
- * It is perfectly acceptable to use those classes outside of this
- * class.
- *
- * The underlying solver is an FAC solver using cell-centered
- * discretization.  The difference scheme is second-order
- * central-difference.  On coarse-fine boundaries within the
- * solution levels, the composite grid operator uses, by default,
- * the discretization method of Ewing, Lazarov and Vassilevski
- * ("Local Refinement Techniques for Elliptic Problems on
- * Cell-Centered Grids, I. Error Analysis", Mathematics of
- * Computation, Vol. 56, No. 194, April 1991, pp. 437-461).
- *
- * Typical use of this class is:
- * -# Construct a CellStokesFACSolver object, providing it
- *    the hierarchy and range of levels participating in the solve.
- * -# Set the parameters C and D using the functions named @c setC...
- *    and @c setD...  By default, D=1 and C=0 everywhere.
- * -# Call setBoundaries() to state the types boundary conditions,
- *    along with supplemental data for setting those boundary
- *    conditions.
- * -# Call initializeSolverState() to set up information
- *    internal to the solver.  This is step is not required
- *    but will save setup costs if you are making multiple
- *    solves.  This commits the object to the current hierarchy state
- *    and the specific @em types of boundary conditions you selected,
- *    It does NOT commit to the specific @em values of the boundary
- *    condition.  A hierarchy change (through adaption or other means)
- *    invalidates the state, thus you must reinitialize or
- *    deallocateSolverState() the state before another solve.
- * -# Solve the equation with solveSystem().  You provide the
- *    patch data indices for the solution u and the right hand
- *    side f.  u must have at least one ghost cell and where
- *    a Dirichlet boundary condition applies, those cells
- *    must be set to the value on the boundary.  If only Neumann
- *    boundary conditions are used, the ghost cell values
- *    do not matter.
- * -# Call deallocateSolverState() to free up internal resources,
- *    if initializeSolverState() was called before the solve.
- *
- * After the solve, information on the solve can be obtained
- * by calling one of these functions:
- * - getNumberOfIterations() gives the number of FAC cycles used.
- * - getConvergenceFactors() gives the average and final convergence
- *   factors for the solve.
- * - getResidualNorm() gives the final residual
- *
- * Finer solver controls can be set using the functions in this class.
- *
- * Object of this class can be set using input databases.
- * The following parameters can be set.  Each is shown with its
- * default value in the case where hypre is used.
- * @verbatim
- * enable_logging = TRUE // Bool flag to switch logging on/off
- * max_cycles = 10       // Integer number of max FAC cycles to use
- * residual_tol = 1.e-6  // Residual tolerance to solve for
- * num_pre_sweeps = 1    // Number of presmoothing sweeps to use
- * num_post_sweeps = 1   // Number of postsmoothing sweeps to use
- * coarse_fine_discretization = "Ewing" // Name of coarse-fine discretization
- * prolongation_method = "CONSTANT_REFINE" // Name of prolongation method
- * coarse_solver_choice = "hypre"  // Name of coarse level solver
- * coarse_solver_tolerance = 1e-10 // Coarse level tolerance
- * coarse_solver_max_iterations = 20 // Coarse level max iterations
- * use_smg = "FALSE"     // Whether to use hypre's smg solver
- *                       // (alternative is the pfmg solver)
- * @endverbatim
- *
- */
-class CellStokesFACSolver
-{
-
-public:
-   /*!
-    * @brief Construct a solver.
-    *
-    * If the database is not NULL, initial settings will be set
-    * using the database.
-    * The solver is uninitialized until initializeSolverState()
-    * is called.
-    *
-    * @param object_name Name of object used in outputs
-    * @param database tbox::Database for initialization (may be NULL)
-    */
-   CellStokesFACSolver(
-      const tbox::Dimension& dim,
-      const std::string& object_name,
-      tbox::Pointer<tbox::Database> database =
-         tbox::Pointer<tbox::Database>());
-
-   /*!
-    * @brief Destructor.
-    */
-   ~CellStokesFACSolver(
-      void);
-
-   /*!
-    * @brief Enable logging.
-    *
-    * To disable, pass in @c false.
-    */
-   void
-   enableLogging(
-      bool logging);
-
-   /*!
-    * @brief Solve Stokes's equation, assuming an uninitialized
-    * solver state.
-    *
-    * Here, u is the "solution" patch data index and f is the
-    * right hand side patch data index.
-    * The return value is true if the solver converged and false otherwise.
-    *
-    * This function is a wrapper.
-    * It simply initializes the solver state, call the
-    * solveSystem(const int,const int) for the initialized solver then
-    * deallocates the solver state.
-    *
-    * Upon return from this function,
-    * solution will contain the result of the solve.
-    *
-    * See initializeSolverState() for opportunities to save overhead
-    * when using multiple consecutive solves.
-    *
-    * @see solveSystem(const int,const int)
-    *
-    * @param solution hier::Patch data index for solution u
-    * @param rhs hier::Patch data index for right hand side f
-    * @param hierarchy The patch hierarchy to solve on
-    * @param coarse_ln The coarsest level in the solve.
-    * @param fine_ln The finest level in the solve.
-    *
-    * @return whether solver converged to specified level
-    *
-    * @see initializeSolverState
-    */
-   bool
-   solveSystem(
-      const int solution,
-      const int rhs,
-      tbox::Pointer<hier::PatchHierarchy> hierarchy,
-      int coarse_ln = -1,
-      int fine_ln = -1);
-
-   /*!
-    * @brief Solve Stokes's equation using the current solver state
-    * set by initializeSolverState().
-    *
-    * When the solver state has been initialized, this function may
-    * be called repeadedly with different values on the rhs.
-    * There is some cost savings for multiple solves when this
-    * is done.
-    *
-    * Before calling this function, the solution and
-    * right-hand-side quantities should be set properly by the user
-    * on all patch interiors on the range of levels covered by the
-    * FAC iteration.  All data for these patch data index should be allocated.
-    * Thus, the user is responsible for managing the
-    * storage for the solution and right-hand-side.
-    *
-    * @return whether solver converged to specified level
-    *
-    * @see solveSystem( const int, const int, tbox::Pointer< hier::PatchHierarchy >, int, int);
-    */
-   bool
-   solveSystem(
-      const int solution,
-      const int rhs);
-
-   /*!
-    * @brief Specify the boundary conditions that are to be used at the
-    * physical domain boundary.
-    *
-    * This method is used to set up the default SimpleCellRobinBcCoefs
-    * object for specifying boundary conditions.  Note that you may
-    * alternatively provide your own implementation of the Robin
-    * boundary condition coefficients using the setBcObject() method.
-    *
-    * The boundary conditions specified as the
-    * std::string argument "boundary_type."  The boundary type argument can be
-    * "Dirichlet", "Neumann", or "Mixed".
-    *
-    * If using Dirichlet boundary conditions, then before the solver is
-    * called, the storage for the unknown u
-    * must have a mapped_box_level of ghost cells at least one cell wide that includes
-    * the Dirichlet boundary values.
-    *
-    * If using Neumann boundary conditions, then before the solver is called,
-    * the outerface boundary flux data must be set for the Neumann conditions.
-    * The fluxes argument gives the patch data index of this flux
-    * data.
-    *
-    * The mixed boundary type is for a mixture of Dirichlet and Neumann
-    * boundary conditions are used at the physical domain boundary.
-    * The fluxes argument gives the patch data index of the outerface data
-    * that specifies the flux data for the Neumann conditions.  The flags
-    * array is an outerface data array of integer flags that specifies whether
-    * Dirichlet (flag == zero) or Neumann (flag == one) conditions are to be
-    * used at a particular cell boundary face.  Note that the flag data must
-    * be set before the matrix entries can be computed and the flux data
-    * must be set before the solver is called.  The bdry_types argument can
-    * be used if the boundary conditions are mixed but one or more of the
-    * faces of the physical boundary are entirely either Dirichlet or
-    * Neumann boundaries.  The bdry_types argument should be an array of
-    * 2*DIM integers, specifying the boundary conditions on each side of
-    * the physical domain.  It should be ordered {x_lo, x_hi, y_lo, y_hi,
-    * z_lo, z_hi}, with the values for each face being 0 for Dirichlet
-    * conditions, 1 for Neumann conditions, and 2 for mixed boundary
-    * conditions.  The bdry_type argument is never required, but if used
-    * it can sometimes make the StokesHYPRESolver class more efficient.
-    */
-
-   void
-   setBoundaries(
-      const std::string& boundary_type,
-      const int fluxes = -1,
-      const int flags = -1,
-      int* bdry_types = NULL);
-
-   /*!
-    * @brief Override internal implementation to set boundary condition
-    * coefficients with user-provided implementation.
-    *
-    * This function is used to override the default internal
-    * object for setting Robin boundary condition coefficients.
-    * You should override when you need to avoid the limitations
-    * of the SimpleCellRobinBcCoefs class or you prefer to
-    * use your own implementation.
-    *
-    * Note that an important limitation of the SimpleCellRobinBcCoefs
-    * class is the inability to support linear interpolation in
-    * the prolongation step.
-    *
-    * Once the boundary condition object is overwritten by this
-    * method, you must no longer call the setBoundaries() method.
-    */
-   void
-   setBcObject(
-      const RobinBcCoefStrategy* bc_object);
-
-   //!@{ @name Specifying PDE parameters
-
-   /*!
-    * @brief Set the patch data index for variable D.
-    *
-    * In addition, disregard any previous D
-    * specified by setDConstant().
-    */
-   void
-   setDPatchDataId(
-      int id);
-
-   /*!
-    * @brief Set the scalar value variable D.
-    *
-    * In addition, disregard any previous D
-    * specified by setDPatchDataId().
-    */
-   void
-   setDConstant(
-      double scalar);
-
-   /*!
-    * @brief Set the scalar value variable C.
-    *
-    * In addition, disregard any previous C
-    * specified by setCConstant().
-    */
-   void
-   setCPatchDataId(
-      int id);
-
-   /*!
-    * @brief Set the patch data index for variable C.
-    *
-    * In addition, disregard any previous C
-    * specified by setCConstant().
-    */
-   void
-   setCConstant(
-      double scalar);
-
-   //@}
-
-   //@{ @name Functions for setting solver mathematic algorithm controls
-
-   /*!
-    * @brief Set coarse level solver.
-    *
-    * Select from these:
-    * - @c "redblack"
-    * - @c "hypre" (only if the HYPRE library is available).
-    */
-   void
-   setCoarsestLevelSolverChoice(
-      const std::string& choice);
-
-   /*!
-    * @brief Set tolerance for coarse level solve.
-    *
-    * If the coarse level solver requires a tolerance
-    * (currently, they all do), the specified value is used.
-    */
-   void
-   setCoarsestLevelSolverTolerance(
-      double tol);
-
-   /*!
-    * @brief Set max iterations for coarse level solve.
-    *
-    * If the coarse level solver requires a max iteration limit
-    * (currently, they all do), the specified value is used.
-    */
-   void
-   setCoarsestLevelSolverMaxIterations(
-      int max_iterations);
-
-#ifdef HAVE_HYPRE
-   /*!
-    * @brief Set whether to use HYPRe's PFMG algorithm instead of the
-    * SMG algorithm.
-    *
-    * The flag is used to select which of HYPRE's linear solver algorithms
-    * to use if true, the semicoarsening multigrid algorithm is used, and if
-    * false, the ``PF'' multigrid algorithm is used.
-    * By default, the SMG algorithm is used.
-    *
-    * This setting has effect only when HYPRe is chosen for the coarsest
-    * level solver.  See setCoarsestLevelSolverChoice().
-    *
-    * Changing the algorithm must be done before setting up the matrix
-    * coefficients.
-    */
-   void
-   setUseSMG(
-      bool use_smg);
-#endif
-
-   /*!
-    * @brief Set the coarse-fine boundary discretization method.
-    *
-    * Specify the @c op_name std::string which will be passed to
-    * xfer::Geometry::lookupRefineOperator() to get the operator
-    * for setting fine grid ghost cells from the coarse grid.
-    * Note that chosing this operator implicitly choses the
-    * discretization method at the coarse-fine boundary.
-    *
-    * There is one important instance where this std::string is
-    * @em not passed to xfer::Geometry::lookupRefineOperator().
-    * If this variable is set to "Ewing", a constant refinement
-    * method is used along with Ewing's correction.
-    * For a reference to the correction method, see
-    * "Local Refinement Techniques for Elliptic Problems on Cell-Centered
-    * Grids, I. Error Analysis", Mathematics of Computation, Vol. 56, No. 194,
-    * April 1991, pp. 437-461.
-    *
-    * @param coarsefine_method String selecting the coarse-fine discretization method.
-    */
-   void
-   setCoarseFineDiscretization(
-      const std::string& coarsefine_method);
-
-   /*!
-    * @brief Set the name of the prolongation method.
-    *
-    * Specify the @c op_name std::string which will be passed to
-    * xfer::Geometry::lookupRefineOperator() to get the operator
-    * for prolonging the coarse-grid correction.
-    *
-    * By default, "CONSTANT_REFINE" is used.  "LINEAR_REFINE" seems to
-    * to lead to faster convergence, but it does NOT satisfy the Galerkin
-    * condition.
-    *
-    * Prolonging using linear refinement requires a Robin bc
-    * coefficient implementation that is capable of delivering
-    * coefficients for non-hierarchy data, because linear refinement
-    * requires boundary conditions to be set on temporary levels.
-    *
-    * @param prolongation_method String selecting the coarse-fine discretization method.
-    */
-   void
-   setProlongationMethod(
-      const std::string& prolongation_method);
-
-   /*!
-    * @brief Set the number of pre-smoothing sweeps during
-    * FAC iteration process.
-    *
-    * Presmoothing is applied during the fine-to-coarse phase of the
-    * iteration.  The default is to use one sweep.
-    *
-    * @param num_pre_sweeps Number of presmoothing sweeps
-    */
-   void
-   setPresmoothingSweeps(
-      int num_pre_sweeps);
-
-   /*!
-    * @brief Set the number of post-smoothing sweeps during
-    * FAC iteration process.
-    *
-    * Postsmoothing is applied during the coarse-to-fine phase of the
-    * iteration.  The default is to use one sweep.
-    *
-    * @param num_post_sweeps Number of postsmoothing sweeps
-    */
-   void
-   setPostsmoothingSweeps(
-      int num_post_sweeps);
-
-   /*!
-    * @brief Set the max number of iterations (cycles) to use per solve.
-    */
-   void
-   setMaxCycles(
-      int max_cycles);
-
-   /*!
-    * @brief Set the residual tolerance for stopping.
-    *
-    * If you want the prescribed maximum number of cycles to always be taken,
-    * set the residual tolerance to a negative number.
-    */
-   void
-   setResidualTolerance(
-      double residual_tol);
-
-   //@}
-
-   /*!
-    * @brief Prepare the solver's internal state for solving
-    *
-    * In the interest of efficiency, this class may prepare and
-    * cache some hierarchy-dependent objects.  Though it is not required,
-    * initializing the solver state makes for greater efficiency
-    * when you are doing multiple solves on the same system of
-    * equation.  If you do not initialize the state, it is initialized
-    * and deallocated each time you call solveSystem(const int, const int).
-    * The state must be reinitialized if the hierarchy or a boundary
-    * condition type changes.
-    *
-    * To unset the data set in this function,
-    * see deallocateSolverState().
-    *
-    * The @c solution and @c rhs patch data indices in the argument
-    * list are used to determine the @em form of the data you
-    * plan to use in the solve.  They need not be the same data
-    * you solve on, but they should be similar.  Both must represent
-    * cell-centered double data.  The solution must have at least one
-    * ghost cell width, though this is not checked in the initialize
-    * phase, because data is not required yet.
-    *
-    * @param solution solution patch data index for u
-    * @param rhs right hand side patch data index for f
-    * @param hierarchy The patch hierarchy to solve on
-    * @param coarse_level The coarsest level in the solve
-    * @param fine_level The finest level in the solve
-    */
-   void
-   initializeSolverState(
-      const int solution,
-      const int rhs,
-      tbox::Pointer<hier::PatchHierarchy> hierarchy,
-      const int coarse_level = -1,
-      const int fine_level = -1);
-
-   /*!
-    * @brief Remove the solver's internal state data
-    *
-    * Remove all hierarchy-dependent data set by initializeSolverState.
-    * It is safe to call deallocateSolverState() even state is already
-    * deallocated, but nothing is done in that case.
-    *
-    * @see initializeSolverState()
-    */
-   void
-   deallocateSolverState();
-
-   //@{
-   //! @name Functions to get data on last solve.
-
-   /*!
-    * @brief Return FAC iteration count from last (or current
-    * if there is one) FAC iteration process.
-    */
-   int
-   getNumberOfIterations() const;
-
-   /*!
-    * @brief Get average convergance rate and convergence rate of
-    * the last (or current if there is one) FAC solve.
-    *
-    * @param avg_factor average convergence factor over current FAC cycles
-    * @param final_factor convergence factor of the last FAC cycle
-    */
-   void
-   getConvergenceFactors(
-      double& avg_factor,
-      double& final_factor) const;
-
-   /*!
-    * @brief Return residual norm from the just-completed FAC iteration.
-    *
-    * The norm return value is computed as the maximum norm over all
-    * patch levels involved in the solve.  The value corresponds to the
-    * norm applied in the user-defined residual computation.
-    *
-    * The latest computed norm is the one returned.
-    */
-   double
-   getResidualNorm() const;
-
-   //@}
-
-private:
-   /*!
-    * @brief Set state using database
-    *
-    * See the class description for the parameters that can be set
-    * from a database.
-    *
-    * @param database Input database.  If a NULL pointer is given,
-    * nothing is done.
-    */
-   void
-   getFromInput(
-      tbox::Pointer<tbox::Database> database);
-
-   /*
-    * @brief Set @c d_uv and @c d_fv to vectors wrapping the data
-    * specified by patch data indices u and f.
-    */
-   void
-   createVectorWrappers(
-      int u,
-      int f);
-
-   /*
-    * @brief Destroy vector wrappers referenced to by @c d_uv and @c d_fv.
-    */
-   void
-   destroyVectorWrappers();
-
-   /*
-    * @brief Initialize static members
-    */
-   static void
-   initializeStatics();
-
-   const tbox::Dimension d_dim;
-
-   /*!
-    * @brief Object name.
-    */
-   std::string d_object_name;
-
-   /*!
-    * @brief Object holding the specifications of the Stokes equation.
-    */
-   StokesSpecifications d_stokes_spec;
-
-   /*!
-    * @brief FAC operator implementation corresponding to cell-centered
-    * Stokes discretization.
-    */
-   CellStokesFACOps d_fac_ops;
-
-   /*!
-    * @brief FAC preconditioner algorithm.
-    */
-   FACPreconditioner d_fac_precond;
-
-   /*!
-    * @brief Robin bc object in use.
-    */
-   const RobinBcCoefStrategy* d_bc_object;
-
-   /*
-    * @brief Default implementation of RobinBcCoefStrategy
-    */
-   SimpleCellRobinBcCoefs d_simple_bc;
-
-   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
-   int d_ln_min;
-   int d_ln_max;
-
-   /*!
-    * @brief Context for all internally maintained data.
-    */
-   tbox::Pointer<hier::VariableContext> d_context;
-   /*
-    * @brief Vector wrapper for solution.
-    * @see createVectorWrappers(), destroyVectorWrappers()
-    */
-   tbox::Pointer<SAMRAIVectorReal<double> > d_uv;
-   /*
-    * @brief Vector wrapper for source.
-    * @see createVectorWrappers(), destroyVectorWrappers()
-    */
-   tbox::Pointer<SAMRAIVectorReal<double> > d_fv;
-
-   bool d_solver_is_initialized;
-   bool d_enable_logging;
-
-   static bool s_initialized;
-   static int s_weight_id[SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-   static int s_instance_counter[SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-};
-
-}
-}
-
-#ifdef SAMRAI_INLINE
-#include "CellStokesFACSolver.I"
-#endif
-
-#endif  // included_solv_CellStokesFACSolver
diff -r a44a82f15794 -r fe2a9230921b CellStokesHypreSolver.C
--- a/CellStokesHypreSolver.C	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1590 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Hypre solver interface for diffusion-like elliptic problems. 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesHypreSolver_C
-#define included_solv_CellStokesHypreSolver_C
-
-#include "CellStokesHypreSolver.h"
-
-#ifdef HAVE_HYPRE
-
-#include "SAMRAI/geom/CartesianPatchGeometry.h"
-#include "SAMRAI/geom/CartesianGridGeometry.h"
-#include "SAMRAI/math/ArrayDataBasicOps.h"
-#include "SAMRAI/math/PatchSideDataBasicOps.h"
-#include "SAMRAI/pdat/ArrayData.h"
-#include "SAMRAI/pdat/CellIndex.h"
-#include "SAMRAI/pdat/CellIterator.h"
-#include "SAMRAI/pdat/FaceIndex.h"
-#include "SAMRAI/pdat/SideData.h"
-#include "SAMRAI/pdat/SideIndex.h"
-#include "SAMRAI/pdat/SideVariable.h"
-#include "SAMRAI/pdat/OuterfaceData.h"
-#include "SAMRAI/pdat/OutersideData.h"
-#include "SAMRAI/hier/BoundaryBoxUtils.h"
-#include "SAMRAI/hier/VariableDatabase.h"
-#include "SAMRAI/tbox/MathUtilities.h"
-#include "SAMRAI/tbox/SAMRAI_MPI.h"
-#include "SAMRAI/tbox/SAMRAIManager.h"
-#include "SAMRAI/tbox/PIO.h"
-#include "SAMRAI/tbox/Timer.h"
-#include "SAMRAI/tbox/TimerManager.h"
-#include "SAMRAI/tbox/StartupShutdownManager.h"
-#include "SAMRAI/tbox/Utilities.h"
-
-#include <cstdlib>
-
-#ifndef SAMRAI_INLINE
-#include "CellStokesHypreSolver.I"
-#endif
-
-extern "C" {
-
-#ifdef __INTEL_COMPILER
-#pragma warning (disable:1419)
-#endif
-
-void F77_FUNC(compdiagvariablec2d, COMPDIAGVARIABLEC2D) (
-   double* diag,
-   const double* c,
-   const double* offdiagi,
-   const double* offdiagj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(compdiagscalarc2d, COMPDIAGSCALARC2D) (
-   double* diag,
-   const double* c,
-   const double* offdiagi,
-   const double* offdiagj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(compdiagzeroc2d, COMPDIAGZEROC2D) (
-   double* diag,
-   const double* offdiagi,
-   const double* offdiagj,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(adjbdry2d, ADJBDRY2D) (
-   double* diag,
-   const double* offdiagi,
-   const double* offdiagj,
-   const int* pifirst, const int* pilast,
-   const int* pjfirst, const int* pjlast,
-   const double* acoef,
-   const double* bcoef,
-   const int* aifirst, const int* ailast,
-   const int* ajfirst, const int* ajlast,
-   const double* Ak0,
-   const int* kifirst, const int* kilast,
-   const int* kjfirst, const int* kjlast,
-   const int* lower, const int* upper,
-   const int* location,
-   const double* h);
-void F77_FUNC(adjbdryconstoffdiags2d, ADJBDRYCONSTOFFDIAGS2D) (
-   double* diag,
-   const double* offdiag,
-   const int* pifirst,
-   const int* pilast,
-   const int* pjfirst,
-   const int* pjlast,
-   const double* acoef,
-   const int* aifirst,
-   const int* ailast,
-   const int* ajfirst,
-   const int* ajlast,
-   const double* Ak0,
-   const int* kifirst,
-   const int* kilast,
-   const int* kjfirst,
-   const int* kjlast,
-   const int* lower, const int* upper,
-   const int* location,
-   const double* h);
-void F77_FUNC(adjustrhs2d, ADJUSTRHS2D) (double* rhs,
-   const int* rifirst,
-   const int* rilast,
-   const int* rjfirst,
-   const int* rjlast,
-   const double* Ak0,
-   const int* kifirst,
-   const int* kilast,
-   const int* kjfirst,
-   const int* kjlast,
-   const double* gcoef,
-   const int* aifirst,
-   const int* ailast,
-   const int* ajfirst,
-   const int* ajlast,
-   const int* lower, const int* upper,
-   const int* location);
-
-void F77_FUNC(compdiagvariablec3d, COMPDIAGVARIABLEC3D) (
-   double* diag,
-   const double* c,
-   const double* offdiagi,
-   const double* offdiagj,
-   const double* offdiagk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(compdiagscalarc3d, COMPDIAGSCALARC3D) (
-   double* diag,
-   const double* c,
-   const double* offdiagi,
-   const double* offdiagj,
-   const double* offdiagk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(compdiagzeroc3d, COMPDIAGZEROC3D) (
-   double* diag,
-   const double* offdiagi,
-   const double* offdiagj,
-   const double* offdiagk,
-   const int* ifirst,
-   const int* ilast,
-   const int* jfirst,
-   const int* jlast,
-   const int* kfirst,
-   const int* klast,
-   const double* cscale,
-   const double* dscale);
-void F77_FUNC(adjbdry3d, ADJBDRY3D) (
-   double* diag,
-   const double* offdiagi,
-   const double* offdiagj,
-   const double* offdiagk,
-   const int* pifirst,
-   const int* pilast,
-   const int* pjfirst,
-   const int* pjlast,
-   const int* pkfirst,
-   const int* pklast,
-   const double* acoef,
-   const double* bcoef,
-   const int* aifirst,
-   const int* ailast,
-   const int* ajfirst,
-   const int* ajlast,
-   const int* akfirst,
-   const int* aklast,
-   const double* Ak0,
-   const int* kifirst,
-   const int* kilast,
-   const int* kjfirst,
-   const int* kjlast,
-   const int* kkfirst,
-   const int* kklast,
-   const int* lower, const int* upper,
-   const int* location,
-   const double* h);
-void F77_FUNC(adjbdryconstoffdiags3d, ADJBDRYCONSTOFFDIAGS3D) (
-   double* diag,
-   const double* offdiag,
-   const int* pifirst,
-   const int* pilast,
-   const int* pjfirst,
-   const int* pjlast,
-   const int* pkfirst,
-   const int* pklast,
-   const double* acoef,
-   const int* aifirst,
-   const int* ailast,
-   const int* ajfirst,
-   const int* ajlast,
-   const int* akfirst,
-   const int* aklast,
-   const double* Ak0,
-   const int* kifirst,
-   const int* kilast,
-   const int* kjfirst,
-   const int* kjlast,
-   const int* kkfirst,
-   const int* kklast,
-   const int* lower, const int* upper,
-   const int* location,
-   const double* h);
-void F77_FUNC(adjustrhs3d, ADJUSTRHS3D) (double* rhs,
-   const int* rifirst,
-   const int* rilast,
-   const int* rjfirst,
-   const int* rjlast,
-   const int* rkfirst,
-   const int* rklast,
-   const double* Ak0,
-   const int* kifirst,
-   const int* kilast,
-   const int* kjfirst,
-   const int* kjlast,
-   const int* kkfirst,
-   const int* kklast,
-   const double* gcoef,
-   const int* aifirst,
-   const int* ailast,
-   const int* ajfirst,
-   const int* ajlast,
-   const int* akfirst,
-   const int* aklast,
-   const int* lower, const int* upper,
-   const int* location);
-
-}
-
-namespace SAMRAI {
-namespace solv {
-
-tbox::Pointer<pdat::OutersideVariable<double> >
-CellStokesHypreSolver::s_Ak0_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-
-tbox::StartupShutdownManager::Handler CellStokesHypreSolver::s_finalize_handler(
-   0,
-   0,
-   0,
-   CellStokesHypreSolver::finalizeCallback,
-   tbox::StartupShutdownManager::priorityVariables);
-
-/*
- *************************************************************************
- * Constructor                                                           *
- *************************************************************************
- */
-
-CellStokesHypreSolver::CellStokesHypreSolver(
-   const tbox::Dimension& dim,
-   const std::string& object_name,
-   tbox::Pointer<tbox::Database> database):
-   d_dim(dim),
-   d_object_name(object_name),
-   d_hierarchy(NULL),
-   d_ln(-1),
-   d_context(hier::VariableDatabase::getDatabase()->
-             getContext(object_name + "::context")),
-   d_cf_boundary(),
-   d_physical_bc_coef_strategy(&d_physical_bc_simple_case),
-   d_physical_bc_variable(NULL),
-   d_physical_bc_simple_case(dim, d_object_name + "::simple bc"),
-   d_cf_bc_coef(dim, object_name + "::coarse-fine bc coefs"),
-   d_coarsefine_bc_variable(NULL),
-   d_Ak0_id(-1),
-   d_soln_depth(0),
-   d_rhs_depth(0),
-   d_max_iterations(10),
-   d_relative_residual_tol(1e-10),
-   d_number_iterations(-1),
-   d_num_pre_relax_steps(1),
-   d_num_post_relax_steps(1),
-   d_relative_residual_norm(-1.0),
-   d_use_smg(false),
-   d_grid(NULL),
-   d_stencil(NULL),
-   d_matrix(NULL),
-   d_linear_rhs(NULL),
-   d_linear_sol(NULL),
-   d_mg_data(NULL),
-   d_print_solver_info(false)
-{
-   if (d_dim == tbox::Dimension(1) || d_dim > tbox::Dimension(3)) {
-      TBOX_ERROR(" CellStokesHypreSolver : DIM == 1 or > 3 not implemented");
-   }
-
-   t_solve_system = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesHypreSolver::solveSystem()");
-   t_set_matrix_coefficients = tbox::TimerManager::getManager()->
-      getTimer("solv::CellStokesHypreSolver::setMatrixCoefficients()");
-
-   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
-   if (s_Ak0_var[d_dim.getValue() - 1].isNull()) {
-      s_Ak0_var[d_dim.getValue() - 1] = new
-         pdat::OutersideVariable<double>(d_dim, d_object_name + "::Ak0", 1);
-   }
-   d_Ak0_id =
-      vdb->registerVariableAndContext(s_Ak0_var[d_dim.getValue() - 1],
-         d_context,
-         hier::IntVector::getZero(d_dim));
-   if (database) {
-      getFromInput(database);
-   }
-}
-
-/*
- ********************************************************************
- * Set state from database                                          *
- ********************************************************************
- */
-
-void CellStokesHypreSolver::getFromInput(
-   tbox::Pointer<tbox::Database> database)
-{
-   if (database) {
-      d_print_solver_info = database->getBoolWithDefault("print_solver_info",
-            d_print_solver_info);
-      d_max_iterations = database->getIntegerWithDefault("max_iterations",
-            d_max_iterations);
-      d_relative_residual_tol = database->getDoubleWithDefault(
-            "relative_residual_tol",
-            d_relative_residual_tol);
-      if (database->isDouble("residual_tol")) {
-         TBOX_ERROR("CellStokesHypreSolver input error.\n"
-            << "The parameter 'residual_tol' has been replaced\n"
-            << "by 'relative_residual_tol' to be more descriptive.\n"
-            << "Please change the parameter name in the input database.");
-      }
-      d_num_pre_relax_steps =
-         database->getIntegerWithDefault("num_pre_relax_steps",
-            d_num_pre_relax_steps);
-      if (d_num_pre_relax_steps < 0) {
-         TBOX_ERROR(d_object_name << ": Number of relaxation steps must be\n"
-                                  << "non-negative.\n");
-      }
-      d_num_post_relax_steps =
-         database->getIntegerWithDefault("num_post_relax_steps",
-            d_num_post_relax_steps);
-      if (d_num_post_relax_steps < 0) {
-         TBOX_ERROR(d_object_name << ": Number of relaxation steps must be\n"
-                                  << "non-negative.\n");
-      }
-      if (database->isBool("use_smg")) {
-         bool use_smg = database->getBool("use_smg");
-         if (use_smg != d_use_smg) {
-            setUseSMG(use_smg);
-         }
-      }
-   }
-}
-
-/*
- ********************************************************************
- * Initialize internal data for a given hierarchy level             *
- * After setting internal data, propagate the information           *
- * to the major algorithm objects.  Allocate data for               *
- * storing boundary condition-dependent quantities for              *
- * adding to souce term before solving.                             *
- ********************************************************************
- */
-
-void CellStokesHypreSolver::initializeSolverState(
-   tbox::Pointer<hier::PatchHierarchy> hierarchy,
-   int ln)
-{
-   TBOX_ASSERT(!hierarchy.isNull());
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
-
-   deallocateSolverState();
-
-   d_hierarchy = hierarchy;
-   d_ln = ln;
-
-   hier::IntVector max_gcw(d_dim, 1);
-   d_cf_boundary = new hier::CoarseFineBoundary(*d_hierarchy, d_ln, max_gcw);
-
-   d_physical_bc_simple_case.setHierarchy(d_hierarchy, d_ln, d_ln);
-
-   d_number_iterations = -1;
-   d_relative_residual_norm = -1.0;
-
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
-   level->allocatePatchData(d_Ak0_id);
-   allocateHypreData();
-}
-
-/*
- ********************************************************************
- * Deallocate data initialized by initializeSolverState             *
- ********************************************************************
- */
-
-void CellStokesHypreSolver::deallocateSolverState()
-{
-   if (d_hierarchy.isNull()) return;
-
-   d_cf_boundary->clear();
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
-   level->deallocatePatchData(d_Ak0_id);
-   deallocateHypreData();
-   d_hierarchy.setNull();
-   d_ln = -1;
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Allocate the HYPRE data structures that depend only on the level      *
- * and will not change (grid, stencil, matrix, and vectors).             *
- *                                                                       *
- *************************************************************************
- */
-void CellStokesHypreSolver::allocateHypreData()
-{
-   tbox::SAMRAI_MPI::Comm communicator = d_hierarchy->getDomainMappedBoxLevel().getMPI().getCommunicator();
-
-   /*
-    * Set up the grid data - only set grid data for local boxes
-    */
-
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
-   tbox::Pointer<geom::CartesianGridGeometry> grid_geometry =
-      d_hierarchy->getGridGeometry();
-   const hier::IntVector ratio = level->getRatioToLevelZero();
-   hier::IntVector periodic_shift =
-      grid_geometry->getPeriodicShift(ratio);
-
-   int periodic_flag[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
-   int d;
-   bool is_periodic = false;
-   for (d = 0; d < d_dim.getValue(); ++d) {
-      periodic_flag[d] = periodic_shift[d] != 0;
-      is_periodic = is_periodic || periodic_flag[d];
-   }
-
-   HYPRE_StructGridCreate(communicator, d_dim.getValue(), &d_grid);
-   for (hier::PatchLevel::Iterator p(level); p; p++) {
-      const hier::Box& box = (*p)->getBox();
-      hier::Index lower = box.lower();
-      hier::Index upper = box.upper();
-      HYPRE_StructGridSetExtents(d_grid, &lower[0], &upper[0]);
-   }
-
-#ifdef DEBUG_CHECK_ASSERTIONS
-   if (is_periodic) {
-      const hier::BoxArray& level_domain = level->getPhysicalDomain();
-      hier::Box domain_bound(level_domain[0]);
-      for (int i = 1; i < level_domain.size(); ++i) {
-         domain_bound.lower().min(level_domain[i].lower());
-         domain_bound.upper().max(level_domain[i].upper());
-      }
-      for (d = 0; d < d_dim.getValue(); ++d) {
-         if (periodic_flag[d] == true) {
-            int tmpi = 1;
-            unsigned int p_of_two;
-            for (p_of_two = 0; p_of_two < 8 * sizeof(p_of_two) - 1;
-                 ++p_of_two) {
-               if (tmpi == domain_bound.numberCells(d)) {
-                  break;
-               }
-               if (tmpi > domain_bound.numberCells(d)) {
-                  TBOX_ERROR(
-                     d_object_name << ": Hypre currently requires\n"
-                     <<
-                     "that grid size in periodic directions be\n"
-                     <<
-                     "powers of two.  (This requirement may go\n"
-                     <<
-                     "away in future versions of hypre.)\n"
-                     << "Size problem in direction "
-                     << d << "\n"
-                     << "Domain bound is "
-                     << domain_bound << ",\n"
-                     << "Size of "
-                     << domain_bound.numberCells() << "\n");
-               }
-               tmpi = tmpi ? tmpi << 1 : 1;
-            }
-         }
-      }
-   }
-#endif
-
-   HYPRE_StructGridSetPeriodic(d_grid, &periodic_shift[0]);
-   HYPRE_StructGridAssemble(d_grid);
-
-   {
-      /*
-       * Allocate stencil data and set stencil offsets
-       */
-
-      if (d_dim == tbox::Dimension(1)) {
-         const int stencil_size = 2;
-         int stencil_offsets[2][1] = {
-            { -1 }, { 0 }
-         };
-         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
-         for (int s = 0; s < stencil_size; s++) {
-            HYPRE_StructStencilSetElement(d_stencil, s,
-               stencil_offsets[s]);
-         }
-      } else if (d_dim == tbox::Dimension(2)) {
-         const int stencil_size = 3;
-         int stencil_offsets[3][2] = {
-            { -1, 0 }, { 0, -1 }, { 0, 0 }
-         };
-         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
-         for (int s = 0; s < stencil_size; s++) {
-            HYPRE_StructStencilSetElement(d_stencil, s,
-               stencil_offsets[s]);
-         }
-      } else if (d_dim == tbox::Dimension(3)) {
-         const int stencil_size = 4;
-         int stencil_offsets[4][3] = {
-            { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 }, { 0, 0, 0 }
-         };
-         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
-         for (int s = 0; s < stencil_size; s++) {
-            HYPRE_StructStencilSetElement(d_stencil, s,
-               stencil_offsets[s]);
-         }
-      }
-   }
-
-   {
-      int full_ghosts1[2 * 3] = { 1, 1, 0, 0, 0, 0 };
-      int no_ghosts1[2 * 3] = { 0, 0, 0, 0, 0, 0 };
-
-      int full_ghosts2[2 * 3] = { 1, 1, 1, 1, 0, 0 };
-      int no_ghosts2[2 * 3] = { 0, 0, 0, 0, 0, 0 };
-
-      int full_ghosts3[2 * 3] = { 1, 1, 1, 1, 1, 1 };
-      int no_ghosts3[2 * 3] = { 0, 0, 0, 0, 0, 0 };
-
-      /*
-       * Allocate the structured matrix
-       */
-
-      int* full_ghosts = NULL;
-      int* no_ghosts = NULL;
-
-      if (d_dim == tbox::Dimension(1)) {
-         full_ghosts = full_ghosts1;
-         no_ghosts = no_ghosts1;
-      } else if (d_dim == tbox::Dimension(2)) {
-         full_ghosts = full_ghosts2;
-         no_ghosts = no_ghosts2;
-      } else if (d_dim == tbox::Dimension(3)) {
-         full_ghosts = full_ghosts3;
-         no_ghosts = no_ghosts3;
-      } else {
-         TBOX_ERROR(
-            "CellStokesHypreSolver does not yet support dimension " << d_dim);
-      }
-
-      HYPRE_StructMatrixCreate(communicator,
-         d_grid,
-         d_stencil,
-         &d_matrix);
-      HYPRE_StructMatrixSetNumGhost(d_matrix, full_ghosts);
-      HYPRE_StructMatrixSetSymmetric(d_matrix, 1);
-      HYPRE_StructMatrixInitialize(d_matrix);
-
-      HYPRE_StructVectorCreate(communicator,
-         d_grid,
-         &d_linear_rhs);
-      HYPRE_StructVectorSetNumGhost(d_linear_rhs, no_ghosts);
-      HYPRE_StructVectorInitialize(d_linear_rhs);
-
-      HYPRE_StructVectorCreate(communicator,
-         d_grid,
-         &d_linear_sol);
-      HYPRE_StructVectorSetNumGhost(d_linear_sol, full_ghosts);
-      HYPRE_StructVectorInitialize(d_linear_sol);
-   }
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * The destructor deallocates solver data.                               *
- *                                                                       *
- *************************************************************************
- */
-
-CellStokesHypreSolver::~CellStokesHypreSolver()
-{
-   deallocateHypreData();
-
-   if (!d_hierarchy.isNull()) {
-      tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(0);
-      level->deallocatePatchData(d_Ak0_id);
-   }
-   hier::VariableDatabase* vdb =
-      hier::VariableDatabase::getDatabase();
-   vdb->removePatchDataIndex(d_Ak0_id);
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Deallocate HYPRE data and solver.  HYPRE requires that we             *
- * check whether HYPRE has already deallocated this data.                *
- * Note that the HYPRE solver, d_mg_data, was created at                 *
- * the end of setMatrixCoefficients.                                     *
- *                                                                       *
- *************************************************************************
- */
-
-void CellStokesHypreSolver::deallocateHypreData()
-{
-   if (d_stencil) {
-      HYPRE_StructStencilDestroy(d_stencil);
-      d_stencil = NULL;
-   }
-   if (d_grid) {
-      HYPRE_StructGridDestroy(d_grid);
-      d_grid = NULL;
-   }
-   if (d_matrix) {
-      HYPRE_StructMatrixDestroy(d_matrix);
-      d_matrix = NULL;
-   }
-   if (d_linear_rhs) {
-      HYPRE_StructVectorDestroy(d_linear_rhs);
-      d_linear_rhs = NULL;
-   }
-   if (d_linear_sol) {
-      HYPRE_StructVectorDestroy(d_linear_sol);
-      d_linear_sol = NULL;
-   }
-   destroyHypreSolver();
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Copy data into the HYPRE vector structures.                           *
- *                                                                       *
- *************************************************************************
- */
-
-void CellStokesHypreSolver::copyToHypre(
-   HYPRE_StructVector vector,
-   pdat::CellData<double>& src,
-   int depth,
-   const hier::Box& box)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, src, box);
-
-   for (pdat::CellIterator c(box); c; c++) {
-      hier::IntVector ic = c();
-      HYPRE_StructVectorSetValues(vector, &ic[0], src(c(), depth));
-   }
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Copy data out of the HYPRE vector structures.                         *
- *                                                                       *
- *************************************************************************
- */
-
-void CellStokesHypreSolver::copyFromHypre(
-   pdat::CellData<double>& dst,
-   int depth,
-   HYPRE_StructVector vector,
-   const hier::Box box)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, dst, box);
-
-   for (pdat::CellIterator c(box); c; c++) {
-      double value;
-      hier::IntVector ic = c();
-      HYPRE_StructVectorGetValues(vector, &ic[0], &value);
-      dst(c(), depth) = value;
-   }
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Set the matrix coefficients for the linear system.                    *
- * The matrix coefficients are dependent on the problem                  *
- * specification described by the StokesSpecificiations            *
- * object and by the boundary condition.                                 *
- *                                                                       *
- *************************************************************************
- */
-
-void CellStokesHypreSolver::setMatrixCoefficients(
-   const StokesSpecifications& spec)
-{
-   if (d_physical_bc_coef_strategy == NULL) {
-      TBOX_ERROR(
-         d_object_name << ": No BC coefficient strategy object!\n"
-         <<
-         "Use either setBoundaries or setPhysicalBcCoefObject\n"
-         <<
-         "to specify the boundary conidition.  Do it before\n"
-         << "calling setMatrixCoefficients.");
-   }
-
-   t_set_matrix_coefficients->start();
-
-   int i = 0;
-
-   tbox::Pointer<pdat::CellData<double> > C_data;
-   tbox::Pointer<pdat::SideData<double> > D_data;
-
-   /*
-    * Some computations can be done using high-level math objects.
-    * Define the math objects.
-    */
-   math::ArrayDataBasicOps<double> array_math;
-   math::PatchSideDataBasicOps<double> patch_side_math;
-
-   /*
-    * The value of the ghost cell based on the Robin boundary condition
-    * can be written as the sum of a constant, k0, plus a multiple of the
-    * internal cell value, k1*ui.  k1*ui depends on the value of u so it
-    * contributes to the product Au,
-    * while the constant k0 contributes the right hand side f.
-    * We save Ak0 = A*k0(a) to add to f when solving.
-    * We assume unit g here because we will multiply it in just before
-    * solving, thus allowing everything that does not affect A to change
-    * from solve to solve.
-    */
-   tbox::Pointer<pdat::OutersideData<double> > Ak0;
-
-   /*
-    * Loop over patches and set matrix entries for each patch.
-    */
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
-   const hier::IntVector no_ghosts(d_dim, 0);
-   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
-
-      hier::Patch& patch = **pi;
-
-      tbox::Pointer<geom::CartesianPatchGeometry> pg =
-         patch.getPatchGeometry();
-
-      const double* h = pg->getDx();
-
-      const hier::Box patch_box = patch.getBox();
-      const hier::Index patch_lo = patch_box.lower();
-      const hier::Index patch_up = patch_box.upper();
-
-      if (!spec.cIsZero() && !spec.cIsConstant()) {
-         C_data = patch.getPatchData(spec.getCPatchDataId());
-         if (C_data.isNull()) {
-            TBOX_ERROR(d_object_name << ": Invalid cell variable index "
-                                     << spec.getCPatchDataId()
-                                     << " for the C parameter.  It is not\n"
-                                     << "cell-centered double data.");
-         }
-      }
-
-      if (!spec.dIsConstant()) {
-         D_data = patch.getPatchData(spec.getDPatchDataId());
-         if (D_data.isNull()) {
-            TBOX_ERROR(d_object_name << ": Invalid cell variable index "
-                                     << spec.getDPatchDataId()
-                                     <<
-               " for diffusion coefficient.  It is not\n"
-                                     << "side-centered double data.");
-         }
-      }
-
-      Ak0 = patch.getPatchData(d_Ak0_id);
-
-      Ak0->fillAll(0.0);
-
-      pdat::CellData<double> diagonal(patch_box, 1, no_ghosts);
-
-      /*
-       * Set diagonals to zero so we can accumulate to it.
-       * Accumulation is used at boundaries to shift weights
-       * for ghost cells onto the diagonal.
-       */
-      diagonal.fillAll(0.0);
-
-      const tbox::Pointer<geom::CartesianPatchGeometry>
-      geometry = patch.getPatchGeometry();
-
-      const hier::Index ifirst = patch_box.lower();
-      const hier::Index ilast = patch_box.upper();
-
-      /*
-       * Storage for off-diagonal entries,
-       * which can be variable or constant.
-       */
-      pdat::SideData<double> off_diagonal(patch_box, 1, no_ghosts);
-
-      /*
-       * Compute all off-diagonal entries with no regard to BCs.
-       * These off-diagonal entries are simply D/(h*h), according
-       * to our central difference formula.
-       */
-      if (spec.dIsConstant()) {
-         for (i = 0; i < d_dim.getValue(); ++i) {
-            double dhh = spec.getDConstant() / (h[i] * h[i]);
-            pdat::ArrayData<double>& off_diag_array(off_diagonal.getArrayData(i));
-            off_diag_array.fill(dhh);
-         }
-      } else {
-         for (i = 0; i < d_dim.getValue(); ++i) {
-            hier::Box sbox(patch_box);
-            sbox.growUpper(i, 1);
-            array_math.scale(off_diagonal.getArrayData(i),
-               1.0 / (h[i] * h[i]),
-               D_data->getArrayData(i),
-               sbox);
-         }
-      }
-
-      /*
-       * Compute diagonal entries using off-diagonal contributions.
-       */
-      if (spec.cIsZero()) {
-         computeDiagonalEntries(diagonal,
-            off_diagonal,
-            patch_box);
-      } else if (spec.cIsConstant()) {
-         computeDiagonalEntries(diagonal,
-            spec.getCConstant(),
-            off_diagonal,
-            patch_box);
-      } else {
-         computeDiagonalEntries(diagonal,
-            *C_data,
-            off_diagonal,
-            patch_box);
-      }
-
-      /*
-       * Walk physical domain boundaries and adjust off-diagonals
-       * before computation of diagonal entries.
-       * The exterior cell's value is
-       * uo = ( h*gamma + ui*(beta-h*alpha/2) )/( beta+h*alpha/2 )
-       *   = k0 + k1*ui
-       * where k0 = h*gamma/( beta+h*alpha/2 )
-       * k1 = ( beta-h*alpha/2 )/( beta+h*alpha/2 )
-       * Split coupling between interior-exterior cells
-       * into two parts: interior-interior coupling (k1)
-       * and rhs contribution (k0).
-       */
-      {
-         const tbox::Array<hier::BoundaryBox>& surface_boxes =
-            pg->getCodimensionBoundaries(1);
-         const int n_bdry_boxes = surface_boxes.getSize();
-         for (int n = 0; n < n_bdry_boxes; ++n) {
-
-            const hier::BoundaryBox& boundary_box = surface_boxes[n];
-            if (boundary_box.getBoundaryType() != 1) {
-               TBOX_ERROR(
-                  d_object_name << ": Illegal boundary type in "
-                  <<
-                  "CellStokesHypreSolver::setMatrixCoefficients\n");
-            }
-            const hier::BoundaryBoxUtils bbu(boundary_box);
-            const int location_index = boundary_box.getLocationIndex();
-            const hier::BoundaryBox trimmed_boundary_box =
-               bbu.trimBoundaryBox(patch.getBox());
-            const hier::Box bccoef_box =
-               bbu.getSurfaceBoxFromBoundaryBox();
-            tbox::Pointer<pdat::ArrayData<double> >
-            acoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
-            tbox::Pointer<pdat::ArrayData<double> >
-            bcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
-            tbox::Pointer<pdat::ArrayData<double> >
-            gcoef_data(NULL);
-            static const double fill_time = 0.0;
-            d_physical_bc_coef_strategy->setBcCoefs(acoef_data,
-               bcoef_data,
-               gcoef_data,
-               d_physical_bc_variable,
-               patch,
-               boundary_box,
-               fill_time);
-            pdat::ArrayData<double>& Ak0_data =
-               Ak0->getArrayData(location_index / 2,
-                  location_index % 2);
-            adjustBoundaryEntries(diagonal,
-               off_diagonal,
-               patch_box,
-               *acoef_data,
-               *bcoef_data,
-               bccoef_box,
-               Ak0_data,
-               trimmed_boundary_box,
-               h);
-         }
-      }
-
-      /*
-       * Walk coarse-fine boundaries and adjust off-diagonals
-       * according data in ghost cells.
-       */
-      if (d_ln > 0) {
-         /*
-          * There are potentially coarse-fine boundaries to deal with.
-          */
-
-         tbox::Array<hier::BoundaryBox> surface_boxes;
-
-         if (d_dim == tbox::Dimension(2)) {
-            surface_boxes = d_cf_boundary->getEdgeBoundaries(pi->getGlobalId());
-         } else if (d_dim == tbox::Dimension(3)) {
-            surface_boxes = d_cf_boundary->getFaceBoundaries(pi->getGlobalId());
-         }
-
-         const int n_bdry_boxes = surface_boxes.getSize();
-         for (int n = 0; n < n_bdry_boxes; ++n) {
-
-            const hier::BoundaryBox& boundary_box = surface_boxes[n];
-            if (boundary_box.getBoundaryType() != 1) {
-               TBOX_ERROR(
-                  d_object_name << ": Illegal boundary type in "
-                  <<
-                  "CellStokesHypreSolver::setMatrixCoefficients\n");
-            }
-            const int location_index = boundary_box.getLocationIndex();
-            const hier::BoundaryBoxUtils bbu(boundary_box);
-            const hier::BoundaryBox trimmed_boundary_box =
-               bbu.trimBoundaryBox(patch.getBox());
-            const hier::Box bccoef_box =
-               bbu.getSurfaceBoxFromBoundaryBox();
-            tbox::Pointer<pdat::ArrayData<double> >
-            acoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
-            tbox::Pointer<pdat::ArrayData<double> >
-            bcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
-            tbox::Pointer<pdat::ArrayData<double> >
-            gcoef_data(NULL);
-            static const double fill_time = 0.0;
-            /*
-             * Reset invalid ghost data id to help detect use in setBcCoefs.
-             */
-            d_cf_bc_coef.setGhostDataId(-1, hier::IntVector::getZero(d_dim));
-            d_cf_bc_coef.setBcCoefs(acoef_data,
-               bcoef_data,
-               gcoef_data,
-               d_coarsefine_bc_variable,
-               patch,
-               boundary_box,
-               fill_time);
-            pdat::ArrayData<double>& Ak0_data =
-               Ak0->getArrayData(location_index / 2,
-                  location_index % 2);
-            adjustBoundaryEntries(diagonal,
-               off_diagonal,
-               patch_box,
-               *acoef_data,
-               *bcoef_data,
-               bccoef_box,
-               Ak0_data,
-               trimmed_boundary_box,
-               h);
-         }
-      }
-
-      /*
-       * Copy matrix entries to HYPRE matrix structure.  Note that
-       * we translate our temporary diagonal/off-diagonal storage into the
-       * HYPRE symmetric storage scheme for the stencil specified earlier.
-       */
-      const int stencil_size = d_dim.getValue() + 1;
-      int stencil_indices[stencil_size];
-      double mat_entries[stencil_size];
-
-      for (i = 0; i < stencil_size; i++) stencil_indices[i] = i;
-
-      pdat::CellIterator ic(patch_box);
-
-      /*
-       * To do: This loop uses inefficient high-level syntax.
-       * See if it can be replaced by a Fortran loop or if we
-       * can set matrix entries for an entire box at once.
-       */
-      for ( ; ic; ic++) {
-
-         hier::IntVector icell = ic();
-         pdat::SideIndex ixlower(ic(),
-                                 pdat::SideIndex::X,
-                                 pdat::SideIndex::Lower);
-         mat_entries[0] = (off_diagonal)(ixlower);
-
-         if (d_dim > tbox::Dimension(1)) {
-            pdat::SideIndex iylower(ic(),
-                                    pdat::SideIndex::Y,
-                                    pdat::SideIndex::Lower);
-            mat_entries[1] = (off_diagonal)(iylower);
-         }
-
-         if (d_dim > tbox::Dimension(2)) {
-            pdat::SideIndex izlower(ic(),
-                                    pdat::SideIndex::Z,
-                                    pdat::SideIndex::Lower);
-            // The "funny" indexing prevents a warning when compiling for
-            // DIM < 2.  This code is only reached if DIM > 2 when
-            // executing.
-            mat_entries[d_dim.getValue() > 2 ? 2 : 0] = (off_diagonal)(izlower);
-         }
-
-         mat_entries[d_dim.getValue()] = (diagonal)(ic());
-         HYPRE_StructMatrixSetValues(d_matrix, &icell[0],
-            stencil_size, stencil_indices,
-            mat_entries);
-      } // end cell loop
-
-   } // end patch loop
-
-   if (d_print_solver_info) {
-      HYPRE_StructMatrixPrint("mat_bA.out", d_matrix, 1);
-   }
-
-   HYPRE_StructMatrixAssemble(d_matrix);
-
-   if (d_print_solver_info) {
-      HYPRE_StructMatrixPrint("mat_aA.out", d_matrix, 1);
-   }
-
-   t_set_matrix_coefficients->stop();
-
-   setupHypreSolver();
-}
-
-/*
- **********************************************************************
- * Add g*A*k0(a) from physical boundaries to rhs.                     *
- * This operation is done for physical as well as cf boundaries,      *
- * so it is placed in a function.                                     *
- **********************************************************************
- */
-
-void CellStokesHypreSolver::add_gAk0_toRhs(
-   const hier::Patch& patch,
-   const tbox::Array<hier::BoundaryBox>& bdry_boxes,
-   const RobinBcCoefStrategy* robin_bc_coef,
-   pdat::CellData<double>& rhs)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, patch, rhs);
-
-   /*
-    * g*A*k0(a) is the storage for adjustments to be made to the rhs
-    * when we solve. This is the value of the weight of the ghost cell
-    * value for the interior cell, times k0.  It is independent of u,
-    * and so is moved to the rhs.  Before solving, g*A*k0(a) is added
-    * to rhs.
-    */
-   tbox::Pointer<pdat::OutersideData<double> > Ak0;
-
-   tbox::Pointer<geom::CartesianPatchGeometry> pg =
-      patch.getPatchGeometry();
-
-   Ak0 = patch.getPatchData(d_Ak0_id);
-
-   const int n_bdry_boxes = bdry_boxes.getSize();
-   for (int n = 0; n < n_bdry_boxes; ++n) {
-
-      const hier::BoundaryBox& boundary_box = bdry_boxes[n];
-#ifdef DEBUG_CHECK_ASSERTIONS
-      if (boundary_box.getBoundaryType() != 1) {
-         TBOX_ERROR(d_object_name << ": Illegal boundary type in "
-                                  << "CellStokesHypreSolver::add_gAk0_toRhs\n");
-      }
-#endif
-      const int location_index = boundary_box.getLocationIndex();
-      const hier::BoundaryBoxUtils bbu(boundary_box);
-      const hier::BoundaryBox trimmed_boundary_box =
-         bbu.trimBoundaryBox(patch.getBox());
-      const hier::Index& lower = trimmed_boundary_box.getBox().lower();
-      const hier::Index& upper = trimmed_boundary_box.getBox().upper();
-      const hier::Box& rhsbox = rhs.getArrayData().getBox();
-      const hier::Box& Ak0box = Ak0->getArrayData(location_index / 2,
-            location_index % 2).getBox();
-      const hier::Box bccoef_box = bbu.getSurfaceBoxFromBoundaryBox();
-      tbox::Pointer<pdat::ArrayData<double> >
-      acoef_data(NULL);
-      tbox::Pointer<pdat::ArrayData<double> >
-      bcoef_data(NULL);
-      tbox::Pointer<pdat::ArrayData<double> >
-      gcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
-      static const double fill_time = 0.0;
-      robin_bc_coef->setBcCoefs(acoef_data,
-         bcoef_data,
-         gcoef_data,
-         d_physical_bc_variable,
-         patch,
-         boundary_box,
-         fill_time);
-      /*
-       * Nomenclature for indices: cel=first-cell, gho=ghost,
-       * beg=beginning, end=ending.
-       */
-      if (d_dim == tbox::Dimension(2)) {
-         F77_FUNC(adjustrhs2d, ADJUSTRHS2D) (rhs.getPointer(d_rhs_depth),
-            &rhsbox.lower()[0],
-            &rhsbox.upper()[0],
-            &rhsbox.lower()[1],
-            &rhsbox.upper()[1],
-            Ak0->getPointer(location_index / 2, location_index % 2),
-            &Ak0box.lower()[0],
-            &Ak0box.upper()[0],
-            &Ak0box.lower()[1],
-            &Ak0box.upper()[1],
-            gcoef_data->getPointer(),
-            &bccoef_box.lower()[0],
-            &bccoef_box.upper()[0],
-            &bccoef_box.lower()[1],
-            &bccoef_box.upper()[1],
-            &lower[0], &upper[0],
-            &location_index);
-      } else if (d_dim == tbox::Dimension(3)) {
-         F77_FUNC(adjustrhs3d, ADJUSTRHS3D) (rhs.getPointer(d_rhs_depth),
-            &rhsbox.lower()[0],
-            &rhsbox.upper()[0],
-            &rhsbox.lower()[1],
-            &rhsbox.upper()[1],
-            &rhsbox.lower()[2],
-            &rhsbox.upper()[2],
-            Ak0->getPointer(location_index / 2, location_index % 2),
-            &Ak0box.lower()[0],
-            &Ak0box.upper()[0],
-            &Ak0box.lower()[1],
-            &Ak0box.upper()[1],
-            &Ak0box.lower()[2],
-            &Ak0box.upper()[2],
-            gcoef_data->getPointer(),
-            &bccoef_box.lower()[0],
-            &bccoef_box.upper()[0],
-            &bccoef_box.lower()[1],
-            &bccoef_box.upper()[1],
-            &bccoef_box.lower()[2],
-            &bccoef_box.upper()[2],
-            &lower[0], &upper[0],
-            &location_index);
-      }
-   }
-}
-
-/*
- *************************************************************************
- * Create the hypre solver and set it according to the current state.    *
- *************************************************************************
- */
-void CellStokesHypreSolver::setupHypreSolver()
-{
-   TBOX_ASSERT(d_mg_data == NULL);
-
-   tbox::SAMRAI_MPI::Comm communicator = d_hierarchy->getDomainMappedBoxLevel().getMPI().getCommunicator();
-
-   if (d_use_smg) {
-      HYPRE_StructSMGCreate(communicator, &d_mg_data);
-      HYPRE_StructSMGSetMemoryUse(d_mg_data, 0);
-      HYPRE_StructSMGSetMaxIter(d_mg_data, d_max_iterations);
-      HYPRE_StructSMGSetTol(d_mg_data, d_relative_residual_tol);
-      HYPRE_StructSMGSetLogging(d_mg_data, 1);
-      HYPRE_StructSMGSetNumPreRelax(d_mg_data,
-         d_num_pre_relax_steps);
-      HYPRE_StructSMGSetNumPostRelax(d_mg_data,
-         d_num_post_relax_steps);
-      HYPRE_StructSMGSetup(d_mg_data,
-         d_matrix,
-         d_linear_rhs,
-         d_linear_sol);
-   } else {
-      HYPRE_StructPFMGCreate(communicator, &d_mg_data);
-      HYPRE_StructPFMGSetMaxIter(d_mg_data, d_max_iterations);
-      HYPRE_StructPFMGSetTol(d_mg_data, d_relative_residual_tol);
-      HYPRE_StructPFMGSetLogging(d_mg_data, 1);
-      HYPRE_StructPFMGSetNumPreRelax(d_mg_data,
-         d_num_pre_relax_steps);
-      HYPRE_StructPFMGSetNumPostRelax(d_mg_data,
-         d_num_post_relax_steps);
-      HYPRE_StructPFMGSetup(d_mg_data,
-         d_matrix,
-         d_linear_rhs,
-         d_linear_sol);
-   }
-}
-
-void CellStokesHypreSolver::destroyHypreSolver()
-{
-   if (d_mg_data != NULL) {
-      if (d_use_smg) {
-         HYPRE_StructSMGDestroy(d_mg_data);
-      } else {
-         HYPRE_StructPFMGDestroy(d_mg_data);
-      }
-      d_mg_data = NULL;
-   }
-}
-
-/*
- *************************************************************************
- *                                                                       *
- * Solve the linear system.  This routine assumes that the boundary      *
- * conditions and the matrix coefficients have been specified.           *
- *                                                                       *
- *************************************************************************
- */
-
-int CellStokesHypreSolver::solveSystem(
-   const int u,
-   const int f,
-   bool homogeneous_bc)
-{
-   if (d_physical_bc_coef_strategy == NULL) {
-      TBOX_ERROR(
-         d_object_name << ": No BC coefficient strategy object!\n"
-         <<
-         "Use either setBoundaries or setPhysicalBcCoefObject\n"
-         <<
-         "to specify the boundary conidition.  Do it before\n"
-         << "calling solveSystem.");
-   }
-   // Tracer t("CellStokesHypreSolver::solveSystem");
-
-   t_solve_system->start();
-
-   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
-#ifdef DEBUG_CHECK_ASSERTIONS
-   TBOX_ASSERT(u >= 0);
-   TBOX_ASSERT(
-      u < level->getPatchDescriptor()->getMaxNumberRegisteredComponents());
-   TBOX_ASSERT(f >= 0);
-   TBOX_ASSERT(
-      f < level->getPatchDescriptor()->getMaxNumberRegisteredComponents());
-#endif
-
-   if (d_physical_bc_coef_strategy == &d_physical_bc_simple_case) {
-      /*
-       * If we are using the simple bc implementation, the final piece
-       * of information it requires is the Dirichlet boundary value
-       * set in the ghost cells.  Now that we have the ghost cell data,
-       * we can complete the boundary condition setup.
-       */
-      d_physical_bc_simple_case.cacheDirichletData(u);
-   }
-
-   /*
-    * Modify right-hand-side to account for boundary conditions and
-    * copy solution and right-hand-side to HYPRE structures.
-    */
-
-   const hier::IntVector no_ghosts(d_dim, 0);
-   const hier::IntVector ghosts(d_dim, 1);
-
-   /*
-    * At coarse-fine boundaries, we expect ghost cells to have correct
-    * values to be used in our bc, so u provides the ghost cell data.
-    * Assume that the user only provided data for the immediate first
-    * ghost cell, so pass zero for the number of extensions fillable.
-    */
-   d_cf_bc_coef.setGhostDataId(u, hier::IntVector::getZero(d_dim));
-
-   for (hier::PatchLevel::Iterator p(level); p; p++) {
-      tbox::Pointer<hier::Patch> patch = *p;
-
-      const hier::Box box = patch->getBox();
-
-      /*
-       * Set up variable data needed to prepare linear system solver.
-       */
-      tbox::Pointer<pdat::CellData<double> > u_data_ = patch->getPatchData(u);
-#ifdef DEBUG_CHECK_ASSERTIONS
-      TBOX_ASSERT(!u_data_.isNull());
-#endif
-      pdat::CellData<double>& u_data = *u_data_;
-      pdat::CellData<double> rhs_data(box, 1, no_ghosts);
-
-      /*
-       * Copy rhs and solution from the hierarchy into HYPRE structures.
-       * For rhs, add in the contribution from boundary conditions, if
-       * needed.  If boundary condition is homogenous, this only adds
-       * zero, so we skip it.
-       */
-      copyToHypre(d_linear_sol, u_data, d_soln_depth, box);
-      rhs_data.copy(*(patch->getPatchData(f)));
-      if (!homogeneous_bc) {
-         /*
-          * Add g*A*k0(a) from physical and coarse-fine boundaries to rhs.
-          */
-         add_gAk0_toRhs(*patch,
-            patch->getPatchGeometry()->getCodimensionBoundaries(1),
-            d_physical_bc_coef_strategy,
-            rhs_data);
-         add_gAk0_toRhs(*patch,
-            d_cf_boundary->getBoundaries(patch->getGlobalId(), 1),
-            &d_cf_bc_coef,
-            rhs_data);
-      }
-      copyToHypre(d_linear_rhs, rhs_data, d_rhs_depth, box);
-
-   } // end patch loop
-
-   /*
-    * Reset invalid ghost data id to help detect erroneous further use.
-    */
-   d_cf_bc_coef.setGhostDataId(-1, hier::IntVector::getZero(d_dim));
-
-   /*
-    * Finish assembly of the vectors
-    */
-   HYPRE_StructVectorAssemble(d_linear_sol);
-
-   HYPRE_StructVectorAssemble(d_linear_rhs);
-
-   /*
-    * Solve the system - zero means convergence
-    * Solve takes the same arguments as Setup
-    */
-
-   if (d_print_solver_info) {
-      HYPRE_StructVectorPrint("sol0.out", d_linear_sol, 1);
-      HYPRE_StructMatrixPrint("mat0.out", d_matrix, 1);
-      HYPRE_StructVectorPrint("rhs.out", d_linear_rhs, 1);
-   }
-
-   if (d_use_smg) {
-      // HYPRE_StructSMGSetMaxIter(d_mg_data, d_max_iterations);
-      HYPRE_StructSMGSetTol(d_mg_data, d_relative_residual_tol);
-      /* converge = */ HYPRE_StructSMGSolve(d_mg_data,
-         d_matrix,
-         d_linear_rhs,
-         d_linear_sol);
-   } else {
-      // HYPRE_StructPFMGSetMaxIter(d_mg_data, d_max_iterations);
-      HYPRE_StructPFMGSetTol(d_mg_data, d_relative_residual_tol);
-      /* converge = */ HYPRE_StructPFMGSolve(d_mg_data,
-         d_matrix,
-         d_linear_rhs,
-         d_linear_sol);
-   }
-
-   if (d_print_solver_info) {
-      HYPRE_StructMatrixPrint("mat.out", d_matrix, 1);
-      HYPRE_StructVectorPrint("sol.out", d_linear_sol, 1);
-   }
-
-   if (d_use_smg) {
-      HYPRE_StructSMGGetNumIterations(d_mg_data,
-         &d_number_iterations);
-      HYPRE_StructSMGGetFinalRelativeResidualNorm(d_mg_data,
-         &d_relative_residual_norm);
-   } else {
-      HYPRE_StructPFMGGetNumIterations(d_mg_data,
-         &d_number_iterations);
-      HYPRE_StructPFMGGetFinalRelativeResidualNorm(d_mg_data,
-         &d_relative_residual_norm);
-   }
-
-   /*
-    * Pull the solution vector out of the HYPRE structures
-    */
-   for (hier::PatchLevel::Iterator ip(level); ip; ip++) {
-      tbox::Pointer<hier::Patch> patch = *ip;
-      tbox::Pointer<pdat::CellData<double> > u_data_ = patch->getPatchData(u);
-      pdat::CellData<double>& u_data = *u_data_;
-      copyFromHypre(u_data,
-         d_soln_depth,
-         d_linear_sol,
-         patch->getBox());
-   }
-
-   t_solve_system->stop();
-
-   return d_relative_residual_norm <= d_relative_residual_tol;
-}
-
-void CellStokesHypreSolver::computeDiagonalEntries(
-   pdat::CellData<double>& diagonal,
-   const pdat::CellData<double>& C_data,
-   const pdat::SideData<double>& off_diagonal,
-   const hier::Box& patch_box)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim,
-      diagonal,
-      C_data,
-      off_diagonal,
-      patch_box);
-
-   const hier::Index patch_lo = patch_box.lower();
-   const hier::Index patch_up = patch_box.upper();
-   const double c = 1.0, d = 1.0;
-   if (d_dim == tbox::Dimension(2)) {
-      F77_FUNC(compdiagvariablec2d, COMPDIAGVARIABLEC2D) (diagonal.getPointer(),
-         C_data.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &c, &d);
-   } else if (d_dim == tbox::Dimension(3)) {
-      F77_FUNC(compdiagvariablec3d, COMPDIAGVARIABLEC3D) (diagonal.getPointer(),
-         C_data.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         off_diagonal.getPointer(2),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &patch_lo[2], &patch_up[2],
-         &c, &d);
-   }
-}
-
-void CellStokesHypreSolver::computeDiagonalEntries(
-   pdat::CellData<double>& diagonal,
-   const double C,
-   const pdat::SideData<double>& off_diagonal,
-   const hier::Box& patch_box)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS3(d_dim, diagonal, off_diagonal, patch_box);
-
-   const hier::Index patch_lo = patch_box.lower();
-   const hier::Index patch_up = patch_box.upper();
-   const double c = 1.0, d = 1.0;
-   if (d_dim == tbox::Dimension(2)) {
-      F77_FUNC(compdiagscalarc2d, COMPDIAGSCALARC2D) (diagonal.getPointer(),
-         &C,
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &c, &d);
-   } else if (d_dim == tbox::Dimension(3)) {
-      F77_FUNC(compdiagscalarc3d, COMPDIAGSCALARC3D) (diagonal.getPointer(),
-         &C,
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         off_diagonal.getPointer(2),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &patch_lo[2], &patch_up[2],
-         &c, &d);
-   } else {
-      TBOX_ERROR("CellStokesHypreSolver error...\n"
-         << "DIM > 3 not supported." << std::endl);
-   }
-}
-
-void CellStokesHypreSolver::computeDiagonalEntries(
-   pdat::CellData<double>& diagonal,
-   const pdat::SideData<double>& off_diagonal,
-   const hier::Box& patch_box)
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS3(d_dim, diagonal, off_diagonal, patch_box);
-
-   const hier::Index patch_lo = patch_box.lower();
-   const hier::Index patch_up = patch_box.upper();
-   const double c = 1.0, d = 1.0;
-   if (d_dim == tbox::Dimension(2)) {
-      F77_FUNC(compdiagzeroc2d, COMPDIAGZEROC2D) (diagonal.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &c, &d);
-   } else if (d_dim == tbox::Dimension(3)) {
-      F77_FUNC(compdiagzeroc3d, COMPDIAGZEROC3D) (diagonal.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         off_diagonal.getPointer(2),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &patch_lo[2], &patch_up[2],
-         &c, &d);
-   } else {
-      TBOX_ERROR("CellStokesHypreSolver error...\n"
-         << "DIM > 3 not supported." << std::endl);
-   }
-}
-
-void CellStokesHypreSolver::adjustBoundaryEntries(
-   pdat::CellData<double>& diagonal,
-   const pdat::SideData<double>& off_diagonal,
-   const hier::Box& patch_box,
-   const pdat::ArrayData<double>& acoef_data,
-   const pdat::ArrayData<double>& bcoef_data,
-   const hier::Box bccoef_box,
-   pdat::ArrayData<double>& Ak0_data,
-   const hier::BoundaryBox& trimmed_boundary_box,
-   const double h[tbox::Dimension::MAXIMUM_DIMENSION_VALUE])
-{
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS8(d_dim, diagonal, off_diagonal, patch_box,
-      acoef_data, bcoef_data,
-      bccoef_box, Ak0_data, trimmed_boundary_box);
-
-   const hier::Index patch_lo = patch_box.lower();
-   const hier::Index patch_up = patch_box.upper();
-   const int location_index = trimmed_boundary_box.getLocationIndex();
-   const hier::Index& lower = trimmed_boundary_box.getBox().lower();
-   const hier::Index& upper = trimmed_boundary_box.getBox().upper();
-   const hier::Box& Ak0_box = Ak0_data.getBox();
-   if (d_dim == tbox::Dimension(2)) {
-      F77_FUNC(adjbdry2d, ADJBDRY2D) (diagonal.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         acoef_data.getPointer(),
-         bcoef_data.getPointer(),
-         &bccoef_box.lower()[0],
-         &bccoef_box.upper()[0],
-         &bccoef_box.lower()[1],
-         &bccoef_box.upper()[1],
-         Ak0_data.getPointer(),
-         &Ak0_box.lower()[0],
-         &Ak0_box.upper()[0],
-         &Ak0_box.lower()[1],
-         &Ak0_box.upper()[1],
-         &lower[0], &upper[0],
-         &location_index, h);
-   } else if (d_dim == tbox::Dimension(3)) {
-      F77_FUNC(adjbdry3d, ADJBDRY3D) (diagonal.getPointer(),
-         off_diagonal.getPointer(0),
-         off_diagonal.getPointer(1),
-         off_diagonal.getPointer(2),
-         &patch_lo[0], &patch_up[0],
-         &patch_lo[1], &patch_up[1],
-         &patch_lo[2], &patch_up[2],
-         acoef_data.getPointer(),
-         bcoef_data.getPointer(),
-         &bccoef_box.lower()[0],
-         &bccoef_box.upper()[0],
-         &bccoef_box.lower()[1],
-         &bccoef_box.upper()[1],
-         &bccoef_box.lower()[2],
-         &bccoef_box.upper()[2],
-         Ak0_data.getPointer(),
-         &Ak0_box.lower()[0],
-         &Ak0_box.upper()[0],
-         &Ak0_box.lower()[1],
-         &Ak0_box.upper()[1],
-         &Ak0_box.lower()[2],
-         &Ak0_box.upper()[2],
-         &lower[0], &upper[0],
-         &location_index, h);
-   } else {
-      TBOX_ERROR("CellStokesHypreSolver error...\n"
-         << "DIM > 3 not supported." << std::endl);
-   }
-}
-
-void
-CellStokesHypreSolver::finalizeCallback()
-{
-   for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
-      s_Ak0_var[d].setNull();
-   }
-}
-
-}
-}
-
-#endif
-#endif
diff -r a44a82f15794 -r fe2a9230921b CellStokesHypreSolver.I
--- a/CellStokesHypreSolver.I	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Level solver for diffusion-like elliptic problems. 
- *
- ************************************************************************/
-namespace SAMRAI {
-namespace solv {
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setSolnIdDepth(
-   const int depth) {
-   d_soln_depth = depth;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setRhsIdDepth(
-   const int depth) {
-   d_rhs_depth = depth;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setUseSMG(
-   bool use_smg) {
-   d_use_smg = use_smg;
-}
-
-/*
- ********************************************************************
- * Specify bc using the default internal bc coefficient object.     *
- * Clear up data supporting external bc coefficient setter.         *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setBoundaries(
-   const std::string& boundary_type,
-   const int fluxes,
-   const int flags,
-   int* bdry_types)
-{
-   d_physical_bc_simple_case.setBoundaries(boundary_type,
-      fluxes,
-      flags,
-      bdry_types);
-   d_physical_bc_coef_strategy = &d_physical_bc_simple_case;
-   d_physical_bc_variable.setNull();
-}
-
-/*
- ********************************************************************
- * Set the physical boundary condition object.                      *
- ********************************************************************
- */
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setPhysicalBcCoefObject(
-   const RobinBcCoefStrategy* physical_bc_coef_strategy,
-   const tbox::Pointer<hier::Variable> variable)
-{
-   d_physical_bc_coef_strategy = physical_bc_coef_strategy;
-   d_physical_bc_variable = variable;
-}
-
-SAMRAI_INLINE_KEYWORD
-int CellStokesHypreSolver::getNumberOfIterations() const
-{
-   return d_number_iterations;
-}
-
-SAMRAI_INLINE_KEYWORD
-double CellStokesHypreSolver::getRelativeResidualNorm() const
-{
-   return d_relative_residual_norm;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setNumPreRelaxSteps(
-   const int steps)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   TBOX_ASSERT(!d_hierarchy.isNull());
-#endif
-   d_num_pre_relax_steps = steps;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setNumPostRelaxSteps(
-   const int steps)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   TBOX_ASSERT(!d_hierarchy.isNull());
-#endif
-   d_num_post_relax_steps = steps;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setPrintSolverInfo(
-   const bool print)
-{
-   d_print_solver_info = print;
-}
-
-SAMRAI_INLINE_KEYWORD
-void CellStokesHypreSolver::setStoppingCriteria(
-   const int max_iterations,
-   const double residual_tol)
-{
-#ifdef DEBUG_CHECK_ASSERTIONS
-   TBOX_ASSERT(max_iterations >= 0);
-   TBOX_ASSERT(residual_tol >= 0.0);
-#endif
-   d_max_iterations = max_iterations;
-   d_relative_residual_tol = residual_tol;
-}
-
-}
-}
diff -r a44a82f15794 -r fe2a9230921b CellStokesHypreSolver.h
--- a/CellStokesHypreSolver.h	Fri Dec 31 12:00:54 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-/*************************************************************************
- *
- * This file is part of the SAMRAI distribution.  For full copyright 
- * information, see COPYRIGHT and COPYING.LESSER. 
- *
- * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Hypre solver interface for diffusion-like elliptic problems. 
- *
- ************************************************************************/
-#ifndef included_solv_CellStokesHypreSolver
-#define included_solv_CellStokesHypreSolver
-
-#include "SAMRAI/SAMRAI_config.h"
-
-#ifdef HAVE_HYPRE
-
-#ifndef included_HYPRE_struct_ls
-/*
- * This might break things if F77_FUNC_ is different for hypre vs
- * SAMRAI autoconf detection.  But then C/C++ macros are totally
- * broken due to namespace collision as this example highlights so
- * resorting to hacks are necessary.
- */
-#ifdef F77_FUNC_
-#undef F77_FUNC_
-#endif
-#include "HYPRE_struct_ls.h"
-#define included_HYPRE_struct_ls
-#endif
-
-#include "SAMRAI/solv/GhostCellRobinBcCoefs.h"
-#include "SAMRAI/solv/RobinBcCoefStrategy.h"
-#include "StokesSpecifications.h"
-#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
-#include "SAMRAI/pdat/CellData.h"
-#include "SAMRAI/pdat/SideData.h"
-#include "SAMRAI/pdat/OutersideVariable.h"
-#include "SAMRAI/hier/BoxList.h"
-#include "SAMRAI/hier/CoarseFineBoundary.h"
-#include "SAMRAI/hier/PatchHierarchy.h"
-#include "SAMRAI/hier/PatchLevel.h"
-#include "SAMRAI/hier/VariableContext.h"
-#include "SAMRAI/tbox/Database.h"
-#include "SAMRAI/tbox/Pointer.h"
-
-#include <string>
-
-namespace SAMRAI {
-namespace solv {
-
-/*!
- * @brief Use the HYPRE preconditioner library to solve (the cell-centered)
- * Stokes's equation on a single level in a hierarchy.
- *
- * Class CellStokesHypreSolver uses the HYPRE preconditioner library
- * to solve linear equations of the form
- * @f$ \nabla ( D \nabla u ) + C u = f @f$, where
- * C is a cell-centered array, D is a face-centered array,
- * and u and f are cell-centered arrays
- * (see StokesSpecifications).
- * The discretization is the standard second order
- * finite difference stencil.
- *
- * Robin boundary conditions are used through the
- * interface class RobinBcCoefStrategy.
- * Periodic boundary conditions are not supported yet.
- *
- * The user must perform the following steps to use
- * CellStokesHypreSolver:
- * - Create a CellStokesHypreSolver object.
- * - Initialize CellStokesHypreSolver object with a patch hierarchy,
- *   using the function initializeSolverState().
- * - Use the functions setPhysicalBcCoefObject()
- *   to provide implementations of RobinBcCoefStrategy.
- *   (For most problems you can probably find a suitable
- *   implementation to use without implementing the
- *   strategy yourself.  See for example
- *   SimpleCellRobinBcCoefs and GhostCellRobinBcCoefs.)
- * - Set the matrix coefficients in the linear system,
- *   using the function setMatrixCoefficients().
- * - Specify the stopping criteria using setStoppingCriteria().
- * - Solve the linear system, passing in u and f as the patch
- *   indices of the solution and the right hand side, respectively.
- *
- * Sample parameters for initialization from database (and their
- * default values):
- * @verbatim
- *     print_solver_info = FALSE      // Whether to print some data for debugging
- *     max_iterations = 10            // Max iterations used by Hypre
- *     relative_residual_tol = 1.0e-8 // Residual tolerance used by Hypre
- *     num_pre_relax_steps = 1        // # of presmoothing steps used by Hypre
- *     num_post_relax_steps = 1       // # of postsmoothing steps used by Hypre
- *     use_smg = FALSE                // Whether to use hypre's smg solver
- *                                    // (alternative is the pfmg solver)
- * @endverbatim
- */
-
-class CellStokesHypreSolver
-{
-public:
-   /*!
-    * @brief Constructor.
-    *
-    * @param object_name Name of object.
-    * @param database tbox::Database for input.
-    */
-   CellStokesHypreSolver(
-      const tbox::Dimension& dim,
-      const std::string& object_name,
-      tbox::Pointer<tbox::Database> database =
-         tbox::Pointer<tbox::Database>(NULL));
-
-   /*!
-    * The Stokes destructor releases all internally managed data.
-    */
-   ~CellStokesHypreSolver();
-
-   /*!
-    * @brief Initialize to a given hierarchy.
-    *
-    * Initializer Stokes solver for a patch level in a hierarchy.
-    *
-    * @param hierarchy Hierarchy
-    * @param ln Level number
-    */
-   void
-   initializeSolverState(
-      tbox::Pointer<hier::PatchHierarchy> hierarchy,
-      int ln = 0);
-
-   /*!
-    * @brief Reset to an uninitialized state.
-    */
-   void
-   deallocateSolverState();
-
-   /*!
-    * @brief Set the matrix coefficients
-    *
-    * For information describing the Stokes equation parameters,
-    * see the light-weight StokesSpecifications class where
-    * you set the values of C and D.
-    *
-    * This method must be called before solveSystem().
-    */
-   void
-   setMatrixCoefficients(
-      const StokesSpecifications& spec);
-
-   /*!
-    * @brief Set default depth of the solution data involved in the solve.
-    *
-    * If the solution data has multiple depths,
-    * the solver uses just one depth at a time.
-    * The default depth is the first depth.
-    * Use this function to change it.
-    * This is not used to set the depth of the data (which is not
-    * controled by this class) but the depth used in the solve.
-    *
-    * Changing the depth after setting up the matrix is permissible,
-    * as the solution data does not affect the matrix.
-    */
-   void
-   setSolnIdDepth(
-      const int depth);
-
-   /*!
-    * @brief Set default depth of the rhs data involved in the solve.
-    *
-    * If the rhs data has multiple depths,
-    * the solver uses just one depth at a time.
-    * The default depth is the first depth.
-    * Use this function to change it.
-    * This is not used to set the depth of the data (which is not
-    * controled by this class) but the depth used in the solve.
-    *
-    * Changing the depth after setting up the matrix is permissible,
-    * as the rhs data does not affect the matrix.
-    */
-   void
-   setRhsIdDepth(
-      const int depth);
-
-   /*!
-    * @brief Set the stopping criteria (max iterations and residual
-    * tolerance) for the linear solver.
-    *
-    * @param max_iterations gives the maximum number of iterations
-    * @param relative_residual_tol the maximum error tolerance
-    */
-   void
-   setStoppingCriteria(
-      const int max_iterations = 10,
-      const double relative_residual_tol = 1.0e-6);
-
-   /*!
-    * @brief Solve the linear system Au=f.
-    *
-    * The solution u and the right hand side f are
-    * specified via patch indices on the patch hierarchy.
-    *
-    * Member functions getNumberOfIterations() return the iterations
-    * from the solver.
-    * Note that the matrix coefficients and boundary condition object
-    * must have been set up before this function is called.
-    * As long as the matrix coefficients do not change,
-    * this routine may be called repeatedly to solve any number of linear
-    * systems (with the right-hand side varying).
-    * If the boundary conditions or matrix coefficients are changed
-    * then function setMatrixCoefficients() must be called again.
-    *
-    * When computing the matrix coefficients in setMatrixCoefficients(),
-    * the inhomogeneous portion of the boundary condition (constant
-    * terms, independent of u and thus having no effect on the matrix)
-    * are saved and added to the source term, f,
-    * before performing the matrix solve.  In some situations, it may be
-    * useful to not add the inhomogeneous portion to f.  The flag argument
-    * @c homoegneous_bc is used for this.  (This is a sort of optimization,
-    * to avoid having to re-call setMatrixCoefficients() to change the
-    * inhomogeneous portion.)
-    *
-    * @param u Descriptor of cell-centered unknown variable.
-    * @param f Descriptor of cell-centered source variable.
-    * @param homogeneous_bc Whether homogeneous boundary conditions
-    *        are assumed.
-    *
-    * @return whether solver converged to specified level
-    */
-   int
-   solveSystem(
-      const int u,
-      const int f,
-      bool homogeneous_bc = false);
-
-   /*!
-    * @brief Return the number of iterations taken by the solver to converge.
-    *
-    * @return number of iterations taken by the solver to converge
-    */
-   int
-   getNumberOfIterations() const;
-
-   /*!
-    * @brief Set the number of pre-relax steps used by the Hypre solve.
-    */
-   void
-   setNumPreRelaxSteps(
-      const int steps);
-
-   /*!
-    * @brief Set the number of post-relax steps used by the Hypre solve.
-    */
-   void
-   setNumPostRelaxSteps(
-      const int steps);
-
-   /*!
-    * @brief Return the final residual norm returned by the Hypre solve.
-    * @return final residual norm returned by the Hypre solve.
-    */
-   double
-   getRelativeResidualNorm() const;
-
-   /*!
-    * @brief Set whether to use Hypre's PFMG algorithm instead of the
-    * SMG algorithm.
-    *
-    * The flag is used to select which of HYPRE's linear solver algorithms
-    * to use if true, the semicoarsening multigrid algorithm is used, and if
-    * false, the "PF" multigrid algorithm is used.
-    * By default, the SMG algorithm is used.
-    *
-    * Changing the algorithm must be done before setting up the matrix
-    * coefficients.
-    */
-   void
-   setUseSMG(
-      bool use_smg);
-
-   /*!
-    * @brief Specify boundary condition directly, without using
-    * a RobinBcCoefStrategy object.
-    *
-    * Use @em either setBoundaries() @em or setPhysicalBcCoefObject(),
-    * but not both.
-    *
-    * A SimpleCelBcCoef object is used to interpret and implement
-    * the specified boundary conditions.
-    * See SimpleCellRobinBcCoefs::setBoundaries()
-    * for an explanation of the arguments.
-    */
-   void
-   setBoundaries(
-      const std::string& boundary_type,
-      const int fluxes = -1,
-      const int flags = -1,
-      int* bdry_types = NULL);
-
-   /*!
-    * @brief Specify boundary condition through the use of a
-    * Robin boundary condition object.
-    *
-    * Use @em either setBoundaries() @em or setPhysicalBcCoefObject(),
-    * but not both.
-    *
-    * The Robin boundary condition object is used when setting
-    * the matrix coefficient and when solving the system.
-    * If your boundary conditions are fixed values at ghost
-    * cell centers, use the GhostCellRobinBcCoefs
-    * implementation of the RobinBcCoefStrategy strategy.
-    *
-    * @param physical_bc_coef_strategy tbox::Pointer a concrete
-    *        implementation of the Robin bc strategy.
-    * @param variable hier::Variable pointer to be passed
-    *        to RobinBcCoefStrategy::setBcCoefs(),
-    *        but otherwise unused by this class.
-    */
-   void
-   setPhysicalBcCoefObject(
-      const RobinBcCoefStrategy* physical_bc_coef_strategy,
-      const tbox::Pointer<hier::Variable> variable =
-         tbox::Pointer<hier::Variable>(NULL));
-
-   /*!
-    * @brief Set the flag for printing solver information.
-    *
-    * This optional function is used primarily for debugging.
-    *
-    * If set true, it will print the HYPRE matrix information
-    * to the following files:
-    *
-    * - mat_bA.out - before setting matrix coefficients in matrix assemble
-    * - mat_aA.out - after setting matrix coefficients in matrix assemble
-    * - sol0.out   - u before solve (i.e. for system Au = b)
-    * - sol.out    - u after solve
-    * - mat0.out   - A before solve
-    * - mat.out    - A after solve
-    * - rhs.out    - b before and after solve
-    *
-    * If this method is not called, or the flag is set false, no printing
-    * will occur.
-    */
-   void
-   setPrintSolverInfo(
-      const bool print);
-
-private:
-   /*!
-    * @brief Set state using database
-    *
-    * See the class description for the parameters that can be set
-    * from a database.
-    *
-    * @param database Input database.  If a NULL pointer is given,
-    * nothing is done.
-    */
-   void
-   getFromInput(
-      tbox::Pointer<tbox::Database> database);
-
-   void
-   setupHypreSolver();
-   void
-   destroyHypreSolver();
-   void
-   allocateHypreData();
-   void
-   deallocateHypreData();
-
-   void
-   copyToHypre(
-      HYPRE_StructVector vector,
-      pdat::CellData<double>& src,
-      int depth,
-      const hier::Box& box);
-   void
-   copyFromHypre(
-      pdat::CellData<double>& dst,
-      int depth,
-      HYPRE_StructVector vector,
-      const hier::Box box);
-
-   /*!
-    * @brief Add g*A*k0(a) from boundaries to rhs.
-    *
-    * Move the constant portion of the boundary condition
-    * contribution to the right hand side and add it to the existing rhs.
-    * This operation is done for physical as well as cf boundaries,
-    * so it is placed in a function.
-    *
-    * The boundary boxes given must be to either the physical
-    * boundary or coarse-fine boundary for the patch.  The
-    * bc coefficient implementation should correspond to the
-    * boundary being worked on.
-    */
-   void
-   add_gAk0_toRhs(
-      const hier::Patch& patch,
-      const tbox::Array<hier::BoundaryBox>& bdry_boxes,
-      const RobinBcCoefStrategy* robin_bc_coef,
-      pdat::CellData<double>& rhs);
-
-   //@{
-
-   /*!
-    * @name Dimension-independent functions to organize Fortran interface.
-    */
-
-   //! @brief Compute diagonal entries of the matrix when C is variable.
-   void
-   computeDiagonalEntries(
-      pdat::CellData<double>& diagonal,
-      const pdat::CellData<double>& C_data,
-      const pdat::SideData<double>& variable_off_diagonal,
-      const hier::Box& patch_box);
-   //! @brief Compute diagonal entries of the matrix when C is constant.
-   void
-   computeDiagonalEntries(
-      pdat::CellData<double>& diagonal,
-      const double C,
-      const pdat::SideData<double>& variable_off_diagonal,
-      const hier::Box& patch_box);
-   //! @brief Compute diagonal entries of the matrix when C is zero.
-   void
-   computeDiagonalEntries(
-      pdat::CellData<double>& diagonal,
-      const pdat::SideData<double>& variable_off_diagonal,
-      const hier::Box& patch_box);
-   /*!
-    * @brief Adjust boundary entries for variable off-diagonals.
-    *
-    * At the same time, save information that are needed to adjust
-    * the rhs.
-    */
-   void
-   adjustBoundaryEntries(
-      pdat::CellData<double>& diagonal,
-      const pdat::SideData<double>& variable_off_diagonal,
-      const hier::Box& patch_box,
-      const pdat::ArrayData<double>& acoef_data,
-      const pdat::ArrayData<double>& bcoef_data,
-      const hier::Box bccoef_box,
-      pdat::ArrayData<double>& Ak0_data,
-      const hier::BoundaryBox& trimmed_boundary_box,
-      const double h[tbox::Dimension::MAXIMUM_DIMENSION_VALUE]);
-
-   //@}
-
-   //! @brief Free static variables at shutdown time.
-   static void
-   finalizeCallback();
-
-   /*!
-    * @brief Object dimension.
-    */
-   const tbox::Dimension d_dim;
-
-   /*!
-    * @brief Object name.
-    */
-   std::string d_object_name;
-
-   /*!
-    * @brief Associated hierarchy.
-    */
-   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
-
-   /*!
-    * @brief Associated level number.
-    *
-    * Currently, this must be level number 0.
-    */
-   int d_ln;
-
-   /*!
-    * @brief Scratch context for this object.
-    */
-   tbox::Pointer<hier::VariableContext> d_context;
-
-   //@{ @name Boundary condition handling
-
-   /*!
-    * @brief The coarse-fine boundary description for level d_ln.
-    *
-    * The coarse-fine boundary is computed when the operator
-    * state is initialized.  It is used to allow solves on
-    * levels that are not the coarsest in the hierarchy.
-    */
-   tbox::Pointer<hier::CoarseFineBoundary> d_cf_boundary;
-
-   /*!
-    * @brief Robin boundary coefficient object for physical
-    * boundaries.
-    *
-    * If d_physical_bc_coef_strategy is set, use it, otherwise,
-    * use d_physical_bc_simple_case.
-    */
-   const RobinBcCoefStrategy* d_physical_bc_coef_strategy;
-   tbox::Pointer<hier::Variable> d_physical_bc_variable;
-
-   /*!
-    * @brief Implementation of Robin boundary conefficients
-    * for the case of simple boundary conditions.
-    */
-   SimpleCellRobinBcCoefs d_physical_bc_simple_case;
-
-   /*!
-    * @brief Robin boundary coefficient object for coarse-fine
-    * boundaries.
-    *
-    * This is a GhostCellRobinBcCoefs object because we
-    * expect the users to have the correct ghost cell values
-    * in the coarse-fine boundaries before solving.
-    */
-   GhostCellRobinBcCoefs d_cf_bc_coef;
-   tbox::Pointer<hier::Variable> d_coarsefine_bc_variable;
-
-   //@}
-
-   /*!
-    * @brief hier::Patch index of A*k0(a) quantity
-    *
-    * A*k0(a) is the quantity that is saved for
-    * later adding to the rhs.
-    *
-    * The Robin bc is expressed by the coefficients a and g
-    * on the boundary (see RobinBcCoefStrategy).
-    * This class uses a central difference approximation of
-    * the Robin bc, which results in the value at a ghost cell,
-    * uo, being writen as uo = g*k0(a) + k1(a)*ui, where ui is
-    * the first interior cell value, k0 and k1 depend on a as
-    * indicated.
-    *
-    * In setting up the Au=f system, the contribution of k1(a)*ui
-    * is incorporated into the product Au.  The contribution of
-    * A*g*k0(a) should be moved to the right hand side and saved for
-    * later adding to f.  However, the value of g is not provided
-    * until solve time.  Therefore, we save just A*k0(a) at the
-    * patch data index d_Ak0_id.
-    */
-   int d_Ak0_id;
-
-   static tbox::Pointer<pdat::OutersideVariable<double> > s_Ak0_var[tbox::
-                                                                    Dimension::
-                                                                    MAXIMUM_DIMENSION_VALUE];
-
-   /*!
-    * @brief Depth of the solution variable.
-    */
-   int d_soln_depth;
-
-   /*!
-    * @brief Depth of the rhs variable.
-    */
-   int d_rhs_depth;
-
-   int d_max_iterations;
-   double d_relative_residual_tol;
-
-   int d_number_iterations; // iterations in solver
-   int d_num_pre_relax_steps;  // pre-relax steps in solver
-   int d_num_post_relax_steps; // post-relax steps in solver
-   double d_relative_residual_norm;  // norm from solver
-
-   /*@
-    * @brief Flag to use SMG or PFMG (default)
-    */
-   bool d_use_smg;
-
-   //@{
-   //! @name Hypre object
-   //! @brief HYPRE grid
-   HYPRE_StructGrid d_grid;
-   //! @brief HYPRE stencil
-   HYPRE_StructStencil d_stencil;
-   //! @brief HYPRE structured matrix
-   HYPRE_StructMatrix d_matrix;
-   //! @brief Hypre RHS vector for linear solves
-   HYPRE_StructVector d_linear_rhs;
-   //! @brief Hypre solution vector
-   HYPRE_StructVector d_linear_sol;
-   //! @brief Hypre SMG solver data
-   HYPRE_StructSolver d_mg_data;
-   //@}
-
-   //@{
-
-   //! @name Variables for debugging and analysis.
-
-   /*!
-    * @brief Flag to print solver info
-    *
-    * See setPrintSolverInfo().
-    */
-   bool d_print_solver_info;
-
-   //@}
-
-   /*!
-    * @brief Timers for performance measurement.
-    */
-   tbox::Pointer<tbox::Timer> t_solve_system;
-   tbox::Pointer<tbox::Timer> t_set_matrix_coefficients;
-
-   static tbox::StartupShutdownManager::Handler s_finalize_handler;
-};
-
-}
-} // namespace SAMRAI
-
-#ifdef SAMRAI_INLINE
-#include "CellStokesHypreSolver.I"
-#endif
-
-#endif
-
-#endif
diff -r a44a82f15794 -r fe2a9230921b FACStokes.h
--- a/FACStokes.h	Fri Dec 31 12:00:54 2010 -0800
+++ b/FACStokes.h	Fri Dec 31 12:10:26 2010 -0800
@@ -10,7 +10,7 @@
 #ifndef included_FACStokes
 #define included_FACStokes
 
-#include "CellStokesFACSolver.h"
+#include "StokesFACSolver.h"
 #include "SAMRAI/pdat/CellVariable.h"
 #include "SAMRAI/tbox/Database.h"
 #include "SAMRAI/hier/Box.h"
diff -r a44a82f15794 -r fe2a9230921b Makefile
--- a/Makefile	Fri Dec 31 12:00:54 2010 -0800
+++ b/Makefile	Fri Dec 31 12:10:26 2010 -0800
@@ -29,8 +29,8 @@ CXX_OBJS      = main.o FACStokes/FACStok
 	FACStokes/packDerivedDataIntoDoubleBuffer.o \
 	FACStokes/resetHierarchyConfiguration.o \
 	FACStokes/setupPlotter.o \
-	FACStokes/solveStokes.o CellStokesFACOps.o \
-	CellStokesHypreSolver.o StokesSpecifications.o CellStokesFACSolver.o
+	FACStokes/solveStokes.o StokesFACOps.o \
+	StokesHypreSolver.o StokesSpecifications.o StokesFACSolver.o
 F_OBJS      = facpoisson2d.o facpoisson3d.o
 
 main:	$(CXX_OBJS) $(F_OBJS) $(LIBSAMRAIDEPEND)
diff -r a44a82f15794 -r fe2a9230921b StokesFACOps.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACOps.C	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,2830 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Operator class for cell-centered scalar Stokes using FAC 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesFACOps_C
+#define included_solv_StokesFACOps_C
+
+#include "StokesFACOps.h"
+
+#include IOMANIP_HEADER_FILE
+
+#include "SAMRAI/hier/BoundaryBoxUtils.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/Index.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+#include "SAMRAI/pdat/CellDoubleConstantRefine.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include "SAMRAI/pdat/OutersideData.h"
+#include "SAMRAI/pdat/OutersideVariable.h"
+#include "SAMRAI/hier/PatchData.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/solv/FACPreconditioner.h"
+#include "StokesHypreSolver.h"
+#include "SAMRAI/tbox/Array.h"
+#include "SAMRAI/tbox/MathUtilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+#include "SAMRAI/tbox/Timer.h"
+#include "SAMRAI/tbox/TimerManager.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/MathUtilities.h"
+#include "SAMRAI/xfer/CoarsenAlgorithm.h"
+#include "SAMRAI/xfer/CoarsenOperator.h"
+#include "SAMRAI/xfer/CoarsenSchedule.h"
+#include "SAMRAI/xfer/RefineAlgorithm.h"
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/xfer/RefineSchedule.h"
+#include "SAMRAI/xfer/PatchLevelFullFillPattern.h"
+
+#ifndef SAMRAI_INLINE
+#include "StokesFACOps.I"
+#endif
+
+namespace SAMRAI {
+namespace solv {
+
+tbox::Pointer<pdat::CellVariable<double> >
+CellStokesFACOps::s_cell_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+tbox::Pointer<pdat::SideVariable<double> >
+CellStokesFACOps::s_flux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+tbox::Pointer<pdat::OutersideVariable<double> >
+CellStokesFACOps::s_oflux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+tbox::StartupShutdownManager::Handler
+CellStokesFACOps::s_finalize_handler(
+   0,
+   0,
+   0,
+   CellStokesFACOps::finalizeCallback,
+   tbox::StartupShutdownManager::priorityVariables);
+
+extern "C" {
+
+#ifdef __INTEL_COMPILER
+#pragma warning (disable:1419)
+#endif
+
+void F77_FUNC(compfluxvardc2d, COMPFLUXVARDC2D) (
+   double* xflux,
+   double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx);
+void F77_FUNC(compfluxcondc2d, COMPFLUXCONDC2D) (
+   double* xflux,
+   double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double & diff_coef,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx);
+void F77_FUNC(rbgswithfluxmaxvardcvarsf2d, RBGSWITHFLUXMAXVARDCVARSF2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxcondcvarsf2d, RBGSWITHFLUXMAXCONDCVARSF2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double & dc,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const double & scalar_field,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double & dc,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const double & scalar_field,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(compresvarsca2d, COMPRESVARSCA2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   double* residual,
+   const int* residualgi,
+   const int* residualgj,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx);
+void F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   double* residual,
+   const int* residualgi,
+   const int* residualgj,
+   const double & scalar_field,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* dx);
+void F77_FUNC(ewingfixfluxvardc2d, EWINGFIXFLUXVARDC2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* location_index,
+   const int* ratio_to_coarser,
+   const int* blower,
+   const int* bupper,
+   const double* dx);
+void F77_FUNC(ewingfixfluxcondc2d, EWINGFIXFLUXCONDC2D) (
+   const double* xflux,
+   const double* yflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const double & diff_coef,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* location_index,
+   const int* ratio_to_coarser,
+   const int* blower,
+   const int* bupper,
+   const double* dx);
+
+void F77_FUNC(compfluxvardc3d, COMPFLUXVARDC3D) (
+   double* xflux,
+   double* yflux,
+   double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const double* zdiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const int* dcgk,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx);
+void F77_FUNC(compfluxcondc3d, COMPFLUXCONDC3D) (
+   double* xflux,
+   double* yflux,
+   double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double & diff_coef,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx);
+void F77_FUNC(rbgswithfluxmaxvardcvarsf3d, RBGSWITHFLUXMAXVARDCVARSF3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const double* zdiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const int* dcgk,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   const int* scalar_field_gk,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxcondcvarsf3d, RBGSWITHFLUXMAXCONDCVARSF3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double & dc,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   const int* scalar_field_gk,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const double* zdiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const int* dcgk,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   const double & scalar_field,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double & dc,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   const double & scalar_field,
+   double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx,
+   const int* offset,
+   const double* maxres);
+void F77_FUNC(compresvarsca3d, COMPRESVARSCA3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   double* residual,
+   const int* residualgi,
+   const int* residualgj,
+   const int* residualgk,
+   const double* scalar_field,
+   const int* scalar_field_gi,
+   const int* scalar_field_gj,
+   const int* scalar_field_gk,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx);
+void F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* rhs,
+   const int* rhsgi,
+   const int* rhsgj,
+   const int* rhsgk,
+   double* residual,
+   const int* residualgi,
+   const int* residualgj,
+   const int* residualgk,
+   const double & scalar_field,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* dx);
+void F77_FUNC(ewingfixfluxvardc3d, EWINGFIXFLUXVARDC3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double* xdiff_coef,
+   const double* ydiff_coef,
+   const double* zdiff_coef,
+   const int* dcgi,
+   const int* dcgj,
+   const int* dcgk,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const int* location_index,
+   const int* ratio_to_coarser,
+   const int* blower,
+   const int* bupper,
+   const double* dx);
+void F77_FUNC(ewingfixfluxcondc3d, EWINGFIXFLUXCONDC3D) (
+   const double* xflux,
+   const double* yflux,
+   const double* zflux,
+   const int* fluxgi,
+   const int* fluxgj,
+   const int* fluxgk,
+   const double & diff_coef,
+   const double* soln,
+   const int* solngi,
+   const int* solngj,
+   const int* solngk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const int* location_index,
+   const int* ratio_to_coarser,
+   const int* blower,
+   const int* bupper,
+   const double* dx);
+
+}
+
+/*
+ ********************************************************************
+ * Constructor.                                                     *
+ ********************************************************************
+ */
+CellStokesFACOps::CellStokesFACOps(
+   const tbox::Dimension& dim,
+   const std::string& object_name,
+   tbox::Pointer<tbox::Database> database):
+   d_dim(dim),
+   d_object_name(object_name),
+   d_hierarchy(),
+   d_ln_min(-1),
+   d_ln_max(-1),
+   d_cf_boundary(),
+   d_stokes_spec(object_name + "::Stokes specs"),
+   d_smoothing_choice("redblack"),
+   d_coarse_solver_choice(
+#ifdef HAVE_HYPRE
+      "hypre"
+#else
+      "redblack"
+#endif
+
+      ),
+   d_cf_discretization("Ewing"),
+   d_prolongation_method("CONSTANT_REFINE"),
+   d_coarse_solver_tolerance(1.e-8),
+   d_coarse_solver_max_iterations(10),
+   d_residual_tolerance_during_smoothing(-1.0),
+   d_flux_id(-1),
+#ifdef HAVE_HYPRE
+   d_hypre_solver(dim,
+                  object_name + "::hypre_solver",
+                  database && database->isDatabase("hypre_solver") ?
+                  database->getDatabase("hypre_solver"):
+                     tbox::Pointer<tbox::Database>(NULL)),
+#endif
+   d_physical_bc_coef(NULL),
+   d_context(hier::VariableDatabase::getDatabase()
+             ->getContext(object_name + "::PRIVATE_CONTEXT")),
+   d_cell_scratch_id(-1),
+   d_flux_scratch_id(-1),
+   d_oflux_scratch_id(-1),
+   d_prolongation_refine_operator(),
+   d_prolongation_refine_algorithm(),
+   d_prolongation_refine_schedules(),
+   d_urestriction_coarsen_operator(),
+   d_urestriction_coarsen_algorithm(),
+   d_urestriction_coarsen_schedules(),
+   d_rrestriction_coarsen_operator(),
+   d_rrestriction_coarsen_algorithm(),
+   d_rrestriction_coarsen_schedules(),
+   d_flux_coarsen_operator(),
+   d_flux_coarsen_algorithm(),
+   d_flux_coarsen_schedules(),
+   d_ghostfill_refine_operator(),
+   d_ghostfill_refine_algorithm(),
+   d_ghostfill_refine_schedules(),
+   d_ghostfill_nocoarse_refine_operator(),
+   d_ghostfill_nocoarse_refine_algorithm(),
+   d_ghostfill_nocoarse_refine_schedules(),
+   d_bc_helper(dim,
+               d_object_name + "::bc helper"),
+   d_enable_logging(false),
+   d_preconditioner(NULL),
+   d_hopscell(),
+   d_hopsside()
+{
+
+   t_restrict_solution = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::restrictSolution()");
+   t_restrict_residual = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::restrictResidual()");
+   t_prolong = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::prolongErrorAndCorrect()");
+   t_smooth_error = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::smoothError()");
+   t_solve_coarsest = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::solveCoarsestLevel()");
+   t_compute_composite_residual = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::computeCompositeResidualOnLevel()");
+   t_compute_residual_norm = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesFACOps::computeResidualNorm()");
+
+   if (d_dim == tbox::Dimension(1) || d_dim > tbox::Dimension(3)) {
+      TBOX_ERROR("CellStokesFACOps : DIM == 1 or > 3 not implemented yet.\n");
+   }
+
+   if (s_cell_scratch_var[dim.getValue() - 1].isNull()) {
+      TBOX_ASSERT(s_cell_scratch_var[dim.getValue() - 1].isNull());
+      TBOX_ASSERT(s_cell_scratch_var[dim.getValue() - 1].isNull());
+
+      std::ostringstream ss;
+      ss << "CellStokesFACOps::private_cell_scratch" << dim.getValue();
+      s_cell_scratch_var[dim.getValue() - 1] = new pdat::CellVariable<double>
+            (dim, ss.str());
+      ss.str("");
+      ss << "CellStokesFACOps::private_flux_scratch" << dim.getValue();
+      s_flux_scratch_var[dim.getValue() - 1] = new pdat::SideVariable<double>
+            (dim, ss.str());
+      ss.str("");
+      ss << "CellStokesFACOps::private_oflux_scratch" << dim.getValue();
+      s_oflux_scratch_var[dim.getValue() - 1] = new pdat::OutersideVariable<double>
+            (dim, ss.str());
+   }
+
+   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
+   d_cell_scratch_id = vdb->
+      registerVariableAndContext(s_cell_scratch_var[dim.getValue() - 1],
+         d_context,
+         hier::IntVector::getOne(dim));
+   d_flux_scratch_id = vdb->
+      registerVariableAndContext(s_flux_scratch_var[dim.getValue() - 1],
+         d_context,
+         hier::IntVector::getZero(d_dim));
+   d_oflux_scratch_id = vdb->
+      registerVariableAndContext(s_oflux_scratch_var[dim.getValue() - 1],
+         d_context,
+         hier::IntVector::getZero(d_dim));
+
+   /*
+    * Some variables initialized by default are overriden by input.
+    */
+   if (database) {
+
+      d_coarse_solver_choice =
+         database->getStringWithDefault("coarse_solver_choice",
+            d_coarse_solver_choice);
+      d_coarse_solver_tolerance =
+         database->getDoubleWithDefault("coarse_solver_tolerance",
+            d_coarse_solver_tolerance);
+      d_coarse_solver_max_iterations =
+         database->getIntegerWithDefault("coarse_solver_max_iterations",
+            d_coarse_solver_max_iterations);
+      d_smoothing_choice =
+         database->getStringWithDefault("smoothing_choice",
+            d_smoothing_choice);
+
+      d_cf_discretization =
+         database->getStringWithDefault("cf_discretization",
+            d_cf_discretization);
+
+      d_prolongation_method =
+         database->getStringWithDefault("prolongation_method",
+            d_prolongation_method);
+
+      d_enable_logging =
+         database->getBoolWithDefault("enable_logging",
+            d_enable_logging);
+
+   }
+
+   /*
+    * Check input validity and correctness.
+    */
+   checkInputPatchDataIndices();
+
+}
+
+CellStokesFACOps::~CellStokesFACOps(
+   void)
+{
+}
+
+/*
+ ************************************************************************
+ * FACOperatorStrategy virtual initializeOperatorState function.  *
+ *                                                                      *
+ * Set internal variables to correspond to the solution passed in.      *
+ * Look up transfer operators.                                          *
+ ************************************************************************
+ */
+
+void CellStokesFACOps::initializeOperatorState(
+   const SAMRAIVectorReal<double>& solution,
+   const SAMRAIVectorReal<double>& rhs)
+{
+   deallocateOperatorState();
+   int ln;
+   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
+
+   d_hierarchy = solution.getPatchHierarchy();
+   d_ln_min = solution.getCoarsestLevelNumber();
+   d_ln_max = solution.getFinestLevelNumber();
+   d_hopscell = new math::HierarchyCellDataOpsReal<double>(d_hierarchy,
+                                                           d_ln_min,
+                                                           d_ln_max);
+   d_hopsside = new math::HierarchySideDataOpsReal<double>(d_hierarchy,
+                                                           d_ln_min,
+                                                           d_ln_max);
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+
+   if (d_physical_bc_coef == NULL) {
+      /*
+       * It's an error not to have bc object set.
+       * Note that the bc object cannot be passed in through
+       * the argument because the interface is inherited.
+       */
+      TBOX_ERROR(
+         d_object_name << ": No physical bc object in\n"
+         <<
+         "CellStokesFACOps::initializeOperatorState\n"
+         << "You must use "
+         <<
+         "CellStokesFACOps::setPhysicalBcCoefObject\n"
+         <<
+         "to set one before calling initializeOperatorState\n");
+   }
+
+   if (solution.getNumberOfComponents() != 1) {
+      TBOX_WARNING(d_object_name
+         << ": Solution vector has multiple components.\n"
+         << "Solver is for component 0 only.\n");
+   }
+   if (rhs.getNumberOfComponents() != 1) {
+      TBOX_WARNING(d_object_name
+         << ": RHS vector has multiple components.\n"
+         << "Solver is for component 0 only.\n");
+   }
+
+   /*
+    * Make sure that solution and rhs data
+    *   are of correct type
+    *   are allocated
+    *   has sufficient ghost width
+    */
+   tbox::Pointer<hier::Variable> var;
+   {
+      vdb->mapIndexToVariable(rhs.getComponentDescriptorIndex(0),
+         var);
+      if (!var) {
+         TBOX_ERROR(d_object_name << ": RHS component does not\n"
+                                  << "correspond to a variable.\n");
+      }
+      tbox::Pointer<pdat::CellVariable<double> > cell_var = var;
+      if (!cell_var) {
+         TBOX_ERROR(d_object_name
+            << ": RHS variable is not cell-centered double\n");
+      }
+   }
+   {
+      vdb->mapIndexToVariable(solution.getComponentDescriptorIndex(0),
+         var);
+      if (!var) {
+         TBOX_ERROR(d_object_name << ": Solution component does not\n"
+                                  << "correspond to a variable.\n");
+      }
+      tbox::Pointer<pdat::CellVariable<double> > cell_var = var;
+      if (!cell_var) {
+         TBOX_ERROR(d_object_name
+            << ": Solution variable is not cell-centered double\n");
+      }
+   }
+   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
+      tbox::Pointer<hier::PatchLevel> level_ptr =
+         d_hierarchy->getPatchLevel(ln);
+      hier::PatchLevel& level = *level_ptr;
+      for (hier::PatchLevel::Iterator pi(level); pi; pi++) {
+         hier::Patch& patch = **pi;
+         tbox::Pointer<hier::PatchData> fd =
+            patch.getPatchData(rhs.getComponentDescriptorIndex(0));
+         if (fd) {
+            /*
+             * Some data checks can only be done if the data already exists.
+             */
+            tbox::Pointer<pdat::CellData<double> > cd = fd;
+            if (!cd) {
+               TBOX_ERROR(d_object_name
+                  << ": RHS data is not cell-centered double\n");
+            }
+            if (cd->getDepth() > 1) {
+               TBOX_WARNING(d_object_name
+                  << ": RHS data has multiple depths.\n"
+                  << "Solver is for depth 0 only.\n");
+            }
+         }
+         tbox::Pointer<hier::PatchData> ud =
+            patch.getPatchData(solution.getComponentDescriptorIndex(0));
+         if (ud) {
+            /*
+             * Some data checks can only be done if the data already exists.
+             */
+            tbox::Pointer<pdat::CellData<double> > cd = ud;
+            if (!cd) {
+               TBOX_ERROR(d_object_name
+                  << ": Solution data is not cell-centered double\n");
+            }
+            if (cd->getDepth() > 1) {
+               TBOX_WARNING(d_object_name
+                  << ": Solution data has multiple depths.\n"
+                  << "Solver is for depth 0 only.\n");
+            }
+            if (cd->getGhostCellWidth() < hier::IntVector::getOne(d_dim)) {
+               TBOX_ERROR(d_object_name
+                  << ": Solution data has insufficient ghost width\n");
+            }
+         }
+      }
+   }
+
+   /*
+    * Solution and rhs must have some similar properties.
+    */
+   if (rhs.getPatchHierarchy() != d_hierarchy
+       || rhs.getCoarsestLevelNumber() != d_ln_min
+       || rhs.getFinestLevelNumber() != d_ln_max) {
+      TBOX_ERROR(d_object_name << ": solution and rhs do not have\n"
+                               << "the same set of patch levels.\n");
+   }
+
+#endif
+
+   /*
+    * Initialize the coarse-fine boundary description for the
+    * hierarchy.
+    */
+   d_cf_boundary.resizeArray(d_hierarchy->getNumberOfLevels());
+
+   hier::IntVector max_gcw(d_dim, 1);
+   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
+      d_cf_boundary[ln] = new hier::CoarseFineBoundary(*d_hierarchy,
+                                                       ln,
+                                                       max_gcw);
+   }
+#ifdef HAVE_HYPRE
+   if (d_coarse_solver_choice == "hypre") {
+      d_hypre_solver.initializeSolverState(d_hierarchy, d_ln_min);
+      /*
+       * Share the boundary condition object with the hypre solver
+       * to make sure that boundary condition settings are consistent
+       * between the two objects.
+       */
+      d_hypre_solver.setPhysicalBcCoefObject(d_physical_bc_coef);
+      d_hypre_solver.setMatrixCoefficients(d_stokes_spec);
+   }
+#endif
+
+   /*
+    * Get the transfer operators.
+    * Flux coarsening is conservative.
+    * Cell (solution, error, etc) coarsening is conservative.
+    * Cell refinement from same level is constant refinement.
+    * Cell refinement from coarser level is chosen by the
+    *   choice of coarse-fine discretization, d_cf_discretization,
+    *   which should be set to either "Ewing" or one of the
+    *   acceptable strings for looking up the refine operator.
+    */
+   tbox::Pointer<geom::CartesianGridGeometry> geometry =
+      d_hierarchy->getGridGeometry();
+   tbox::Pointer<hier::Variable> variable;
+
+   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+   d_prolongation_refine_operator =
+      geometry->lookupRefineOperator(variable,
+         d_prolongation_method);
+
+   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+   d_urestriction_coarsen_operator =
+      d_rrestriction_coarsen_operator =
+         geometry->lookupCoarsenOperator(variable,
+            "CONSERVATIVE_COARSEN");
+
+   vdb->mapIndexToVariable(d_oflux_scratch_id, variable);
+   d_flux_coarsen_operator =
+      geometry->lookupCoarsenOperator(variable,
+         "CONSERVATIVE_COARSEN");
+
+   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+   d_ghostfill_refine_operator =
+      geometry->lookupRefineOperator(variable,
+         d_cf_discretization == "Ewing" ?
+         "CONSTANT_REFINE" : d_cf_discretization);
+
+   vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+   d_ghostfill_nocoarse_refine_operator =
+      geometry->lookupRefineOperator(variable,
+         "CONSTANT_REFINE");
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (!d_prolongation_refine_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find prolongation refine operator");
+   }
+   if (!d_urestriction_coarsen_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find restriction coarsening operator");
+   }
+   if (!d_rrestriction_coarsen_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find restriction coarsening operator");
+   }
+   if (!d_flux_coarsen_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find flux coarsening operator");
+   }
+   if (!d_ghostfill_refine_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find ghost filling refinement operator");
+   }
+   if (!d_ghostfill_nocoarse_refine_operator) {
+      TBOX_ERROR(d_object_name
+         << ": Cannot find ghost filling refinement operator");
+   }
+#endif
+
+   for (ln = d_ln_min + 1; ln <= d_ln_max; ++ln) {
+      d_hierarchy->getPatchLevel(ln)->
+      allocatePatchData(d_oflux_scratch_id);
+   }
+
+   /*
+    * Make space for saving communication schedules.
+    * There is no need to delete the old schedules first
+    * because we have deallocated the solver state above.
+    */
+   d_prolongation_refine_schedules.resizeArray(d_ln_max + 1);
+   d_ghostfill_refine_schedules.resizeArray(d_ln_max + 1);
+   d_ghostfill_nocoarse_refine_schedules.resizeArray(d_ln_max + 1);
+   d_urestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+   d_rrestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+   d_flux_coarsen_schedules.resizeArray(d_ln_max + 1);
+
+   d_prolongation_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
+   d_urestriction_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
+   d_rrestriction_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
+   d_flux_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
+   d_ghostfill_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
+   d_ghostfill_nocoarse_refine_algorithm = new xfer::RefineAlgorithm(d_dim);
+
+   d_prolongation_refine_algorithm->
+   registerRefine(d_cell_scratch_id,
+      solution.getComponentDescriptorIndex(0),
+      d_cell_scratch_id,
+      d_prolongation_refine_operator);
+   d_urestriction_coarsen_algorithm->
+   registerCoarsen(solution.getComponentDescriptorIndex(0),
+      solution.getComponentDescriptorIndex(0),
+      d_urestriction_coarsen_operator);
+   d_rrestriction_coarsen_algorithm->
+   registerCoarsen(rhs.getComponentDescriptorIndex(0),
+      rhs.getComponentDescriptorIndex(0),
+      d_rrestriction_coarsen_operator);
+   d_ghostfill_refine_algorithm->
+   registerRefine(solution.getComponentDescriptorIndex(0),
+      solution.getComponentDescriptorIndex(0),
+      solution.getComponentDescriptorIndex(0),
+      d_ghostfill_refine_operator);
+   d_flux_coarsen_algorithm->
+   registerCoarsen(((d_flux_id != -1) ? d_flux_id : d_flux_scratch_id),
+      d_oflux_scratch_id,
+      d_flux_coarsen_operator);
+   d_ghostfill_nocoarse_refine_algorithm->
+   registerRefine(solution.getComponentDescriptorIndex(0),
+      solution.getComponentDescriptorIndex(0),
+      solution.getComponentDescriptorIndex(0),
+      d_ghostfill_nocoarse_refine_operator);
+
+   for (int dest_ln = d_ln_min + 1; dest_ln <= d_ln_max; ++dest_ln) {
+
+      tbox::Pointer<xfer::PatchLevelFullFillPattern> fill_pattern(
+         new xfer::PatchLevelFullFillPattern());
+      d_prolongation_refine_schedules[dest_ln] =
+         d_prolongation_refine_algorithm->
+         createSchedule(fill_pattern,
+            d_hierarchy->getPatchLevel(dest_ln),
+            tbox::Pointer<hier::PatchLevel>(),
+            dest_ln - 1,
+            d_hierarchy,
+            &d_bc_helper);
+      if (!d_prolongation_refine_schedules[dest_ln]) {
+         TBOX_ERROR(d_object_name
+            << ": Cannot create a refine schedule for prolongation!\n");
+      }
+      d_ghostfill_refine_schedules[dest_ln] =
+         d_ghostfill_refine_algorithm->
+         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+            dest_ln - 1,
+            d_hierarchy,
+            &d_bc_helper);
+      if (!d_ghostfill_refine_schedules[dest_ln]) {
+         TBOX_ERROR(d_object_name
+            << ": Cannot create a refine schedule for ghost filling!\n");
+      }
+      d_ghostfill_nocoarse_refine_schedules[dest_ln] =
+         d_ghostfill_nocoarse_refine_algorithm->
+         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+            &d_bc_helper);
+      if (!d_ghostfill_nocoarse_refine_schedules[dest_ln]) {
+         TBOX_ERROR(
+            d_object_name
+            <<
+            ": Cannot create a refine schedule for ghost filling on bottom level!\n");
+      }
+   }
+   for (int dest_ln = d_ln_min; dest_ln < d_ln_max; ++dest_ln) {
+      d_urestriction_coarsen_schedules[dest_ln] =
+         d_urestriction_coarsen_algorithm->
+         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+            d_hierarchy->getPatchLevel(dest_ln + 1));
+      if (!d_urestriction_coarsen_schedules[dest_ln]) {
+         TBOX_ERROR(d_object_name
+            << ": Cannot create a coarsen schedule for U restriction!\n");
+      }
+      d_rrestriction_coarsen_schedules[dest_ln] =
+         d_rrestriction_coarsen_algorithm->
+         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+            d_hierarchy->getPatchLevel(dest_ln + 1));
+      if (!d_rrestriction_coarsen_schedules[dest_ln]) {
+         TBOX_ERROR(d_object_name
+            << ": Cannot create a coarsen schedule for R restriction!\n");
+      }
+      d_flux_coarsen_schedules[dest_ln] =
+         d_flux_coarsen_algorithm->
+         createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+            d_hierarchy->getPatchLevel(dest_ln + 1));
+      if (!d_flux_coarsen_schedules[dest_ln]) {
+         TBOX_ERROR(d_object_name
+            << ": Cannot create a coarsen schedule for flux transfer!\n");
+      }
+   }
+   d_ghostfill_nocoarse_refine_schedules[d_ln_min] =
+      d_ghostfill_nocoarse_refine_algorithm->
+      createSchedule(d_hierarchy->getPatchLevel(d_ln_min),
+         &d_bc_helper);
+   if (!d_ghostfill_nocoarse_refine_schedules[d_ln_min]) {
+      TBOX_ERROR(
+         d_object_name
+         <<
+         ": Cannot create a refine schedule for ghost filling on bottom level!\n");
+   }
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual deallocateOperatorState        *
+ * function.  Deallocate internal hierarchy-dependent data.         *
+ * State is allocated iff hierarchy is set.                         *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::deallocateOperatorState()
+{
+   if (d_hierarchy) {
+      int ln;
+      for (ln = d_ln_min + 1; ln <= d_ln_max; ++ln) {
+         d_hierarchy->getPatchLevel(ln)->
+         deallocatePatchData(d_oflux_scratch_id);
+      }
+      d_cf_boundary.resizeArray(0);
+#ifdef HAVE_HYPRE
+      d_hypre_solver.deallocateSolverState();
+#endif
+      d_hierarchy.setNull();
+      d_ln_min = -1;
+      d_ln_max = -1;
+
+      d_prolongation_refine_algorithm.setNull();
+      d_prolongation_refine_schedules.setNull();
+
+      d_urestriction_coarsen_algorithm.setNull();
+      d_urestriction_coarsen_schedules.setNull();
+
+      d_rrestriction_coarsen_algorithm.setNull();
+      d_rrestriction_coarsen_schedules.setNull();
+
+      d_flux_coarsen_algorithm.setNull();
+      d_flux_coarsen_schedules.setNull();
+
+      d_ghostfill_refine_algorithm.setNull();
+      d_ghostfill_refine_schedules.setNull();
+
+      d_ghostfill_nocoarse_refine_algorithm.setNull();
+      d_ghostfill_nocoarse_refine_schedules.setNull();
+
+   }
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual postprocessOneCycle function.  *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::postprocessOneCycle(
+   int fac_cycle_num,
+   const SAMRAIVectorReal<double>& current_soln,
+   const SAMRAIVectorReal<double>& residual)
+{
+   NULL_USE(current_soln);
+   NULL_USE(residual);
+
+   if (d_enable_logging) {
+      if (d_preconditioner) {
+         /*
+          * Output convergence progress.  This is probably only appropriate
+          * if the solver is NOT being used as a preconditioner.
+          */
+         double avg_factor, final_factor;
+         d_preconditioner->getConvergenceFactors(avg_factor, final_factor);
+         tbox::plog
+         << "iter=" << std::setw(4) << fac_cycle_num
+         << " resid=" << d_preconditioner->getResidualNorm()
+         << " net conv=" << d_preconditioner->getNetConvergenceFactor()
+         << " final conv=" << d_preconditioner->getNetConvergenceFactor()
+         << " avg conv=" << d_preconditioner->getAvgConvergenceFactor()
+         << std::endl;
+      }
+   }
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual restrictSolution function.     *
+ * After restricting solution, update ghost cells of the affected   *
+ * level.                                                           *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::restrictSolution(
+   const SAMRAIVectorReal<double>& s,
+   SAMRAIVectorReal<double>& d,
+   int dest_ln) {
+
+   t_restrict_solution->start();
+
+   xeqScheduleURestriction(d.getComponentDescriptorIndex(0),
+      s.getComponentDescriptorIndex(0),
+      dest_ln);
+
+   d_bc_helper.setHomogeneousBc(false);
+   d_bc_helper.setTargetDataId(d.getComponentDescriptorIndex(0));
+
+   if (dest_ln == d_ln_min) {
+      xeqScheduleGhostFillNoCoarse(d.getComponentDescriptorIndex(0),
+         dest_ln);
+   } else {
+      xeqScheduleGhostFill(d.getComponentDescriptorIndex(0),
+         dest_ln);
+   }
+
+   t_restrict_solution->stop();
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual restrictresidual function.     *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::restrictResidual(
+   const SAMRAIVectorReal<double>& s,
+   SAMRAIVectorReal<double>& d,
+   int dest_ln) {
+
+   t_restrict_residual->start();
+
+   xeqScheduleRRestriction(d.getComponentDescriptorIndex(0),
+      s.getComponentDescriptorIndex(0),
+      dest_ln);
+
+   t_restrict_residual->stop();
+}
+
+/*
+ ***********************************************************************
+ * FACOperatorStrategy virtual prolongErrorAndCorrect function.  *
+ * After the prolongation, we set the physical boundary condition      *
+ * for the correction, which is zero.  Other ghost cell values,        *
+ * which are preset to zero, need not be set.                          *
+ ***********************************************************************
+ */
+
+void CellStokesFACOps::prolongErrorAndCorrect(
+   const SAMRAIVectorReal<double>& s,
+   SAMRAIVectorReal<double>& d,
+   int dest_ln) {
+
+   t_prolong->start();
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (s.getPatchHierarchy() != d_hierarchy
+       || d.getPatchHierarchy() != d_hierarchy) {
+      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
+         "internal state hierarchy.");
+   }
+#endif
+
+   tbox::Pointer<hier::PatchLevel> coarse_level =
+      d_hierarchy->getPatchLevel(dest_ln - 1);
+   tbox::Pointer<hier::PatchLevel> fine_level =
+      d_hierarchy->getPatchLevel(dest_ln);
+
+   /*
+    * Data is prolonged into the scratch space corresponding
+    * to index d_cell_scratch_id and allocated here.
+    */
+   fine_level->allocatePatchData(d_cell_scratch_id);
+
+   /*
+    * Refine solution into scratch space to fill the fine level
+    * interior in the scratch space, then use that refined data
+    * to correct the fine level error.
+    */
+   d_bc_helper.setTargetDataId(d_cell_scratch_id);
+   d_bc_helper.setHomogeneousBc(true);
+   const int src_index = s.getComponentDescriptorIndex(0);
+   xeqScheduleProlongation(d_cell_scratch_id,
+      src_index,
+      d_cell_scratch_id,
+      dest_ln);
+
+   /*
+    * Add the refined error in the scratch space
+    * to the error currently residing in the destination level.
+    */
+   math::HierarchyCellDataOpsReal<double>
+   hierarchy_math_ops(d_hierarchy, dest_ln, dest_ln);
+   const int dst_index = d.getComponentDescriptorIndex(0);
+   hierarchy_math_ops.add(dst_index, dst_index, d_cell_scratch_id);
+
+   fine_level->deallocatePatchData(d_cell_scratch_id);
+
+   t_prolong->stop();
+
+}
+
+/*
+ ********************************************************************
+ ********************************************************************
+ */
+
+void CellStokesFACOps::smoothError(
+   SAMRAIVectorReal<double>& data,
+   const SAMRAIVectorReal<double>& residual,
+   int ln,
+   int num_sweeps)
+{
+
+   t_smooth_error->start();
+
+   checkInputPatchDataIndices();
+   if (d_smoothing_choice == "redblack") {
+      smoothErrorByRedBlack(data,
+         residual,
+         ln,
+         num_sweeps,
+         d_residual_tolerance_during_smoothing);
+   } else {
+      TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
+                               << d_smoothing_choice
+                               << "' in CellStokesFACOps.");
+   }
+
+   t_smooth_error->stop();
+}
+
+/*
+ ********************************************************************
+ * Workhorse function to smooth error using red-black               *
+ * Gauss-Seidel iterations.                                         *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::smoothErrorByRedBlack(
+   SAMRAIVectorReal<double>& data,
+   const SAMRAIVectorReal<double>& residual,
+   int ln,
+   int num_sweeps,
+   double residual_tolerance)
+{
+
+   checkInputPatchDataIndices();
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (data.getPatchHierarchy() != d_hierarchy
+       || residual.getPatchHierarchy() != d_hierarchy) {
+      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
+         "internal hierarchy.");
+   }
+#endif
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
+
+   const int data_id = data.getComponentDescriptorIndex(0);
+
+   const int flux_id = (d_flux_id != -1) ? d_flux_id : d_flux_scratch_id;
+
+   d_bc_helper.setTargetDataId(data_id);
+   d_bc_helper.setHomogeneousBc(true);
+   xeqScheduleGhostFillNoCoarse(data_id, ln);
+
+   if (ln > d_ln_min) {
+      /*
+       * Perform a one-time transfer of data from coarser level,
+       * to fill ghost boundaries that will not change through
+       * the smoothing loop.
+       */
+      xeqScheduleGhostFill(data_id, ln);
+   }
+
+   /*
+    * Smooth the number of sweeps specified or until
+    * the convergence is satisfactory.
+    */
+   int isweep;
+   double red_maxres, blk_maxres, maxres = 0;
+   red_maxres = blk_maxres = residual_tolerance + 1;
+   /*
+    * Instead of checking residual convergence globally,
+    * we check the not_converged flag.  This avoids possible
+    * round-off errors affecting different processes differently,
+    * leading to disagreement on whether to continue smoothing.
+    */
+   int not_converged = 1;
+   for (isweep = 0; isweep < num_sweeps && not_converged; ++isweep) {
+      red_maxres = blk_maxres = 0;
+
+      // Red sweep.
+      xeqScheduleGhostFillNoCoarse(data_id, ln);
+      for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
+         tbox::Pointer<hier::Patch> patch = *pi;
+
+         bool deallocate_flux_data_when_done = false;
+         if (flux_id == d_flux_scratch_id) {
+            /*
+             * Using internal temporary storage for flux.
+             * For each patch, make sure the internal
+             * side-centered data is allocated and note
+             * whether that data should be deallocated when done.
+             */
+            if (!patch->checkAllocated(flux_id)) {
+               patch->allocatePatchData(flux_id);
+               deallocate_flux_data_when_done = true;
+            }
+         }
+
+         tbox::Pointer<pdat::CellData<double> >
+         scalar_field_data = d_stokes_spec.cIsVariable() ?
+            patch->getPatchData(d_stokes_spec.getCPatchDataId()) :
+            tbox::Pointer<hier::PatchData>(NULL);
+         tbox::Pointer<pdat::CellData<double> >
+         err_data = data.getComponentPatchData(0, *patch);
+         tbox::Pointer<pdat::CellData<double> >
+         residual_data = residual.getComponentPatchData(0, *patch);
+         tbox::Pointer<pdat::SideData<double> >
+         flux_data = patch->getPatchData(flux_id);
+
+         computeFluxOnPatch(
+            *patch,
+            level->getRatioToCoarserLevel(),
+            *err_data,
+            *flux_data);
+
+         redOrBlackSmoothingOnPatch(*patch,
+            *flux_data,
+            *residual_data,
+            *err_data,
+            'r',
+            &red_maxres);
+
+         if (deallocate_flux_data_when_done) {
+            patch->deallocatePatchData(flux_id);
+         }
+      }        // End patch number *pi
+      xeqScheduleGhostFillNoCoarse(data_id, ln);
+
+      // Black sweep.
+      for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
+         tbox::Pointer<hier::Patch> patch = *pi;
+
+         bool deallocate_flux_data_when_done = false;
+         if (flux_id == d_flux_scratch_id) {
+            /*
+             * Using internal temporary storage for flux.
+             * For each patch, make sure the internal
+             * side-centered data is allocated and note
+             * whether that data should be deallocated when done.
+             */
+            if (!patch->checkAllocated(flux_id)) {
+               patch->allocatePatchData(flux_id);
+               deallocate_flux_data_when_done = true;
+            }
+         }
+
+         tbox::Pointer<pdat::CellData<double> >
+         scalar_field_data = d_stokes_spec.cIsVariable() ?
+            patch->getPatchData(d_stokes_spec.getCPatchDataId()) :
+            tbox::Pointer<hier::PatchData>(NULL);
+         tbox::Pointer<pdat::CellData<double> >
+         err_data = data.getComponentPatchData(0, *patch);
+         tbox::Pointer<pdat::CellData<double> >
+         residual_data = residual.getComponentPatchData(0, *patch);
+         tbox::Pointer<pdat::SideData<double> >
+         flux_data = patch->getPatchData(flux_id);
+
+         computeFluxOnPatch(
+            *patch,
+            level->getRatioToCoarserLevel(),
+            *err_data,
+            *flux_data);
+
+         redOrBlackSmoothingOnPatch(*patch,
+            *flux_data,
+            *residual_data,
+            *err_data,
+            'b',
+            &blk_maxres);
+
+         if (deallocate_flux_data_when_done) {
+            patch->deallocatePatchData(flux_id);
+         }
+      }        // End patch number *pi
+      xeqScheduleGhostFillNoCoarse(data_id, ln);
+      if (residual_tolerance >= 0.0) {
+         /*
+          * Check for early end of sweeps due to convergence
+          * only if it is numerically possible (user gave a
+          * non negative value for residual tolerance).
+          */
+         maxres = tbox::MathUtilities<double>::Max(red_maxres, blk_maxres);
+         not_converged = maxres > residual_tolerance;
+         const tbox::SAMRAI_MPI& mpi(d_hierarchy->getDomainMappedBoxLevel().getMPI());
+         if (mpi.getSize() > 1) {
+            mpi.AllReduce(&not_converged, 1, MPI_MAX);
+         }
+      }
+   }        // End sweep number isweep
+   if (d_enable_logging) tbox::plog
+      << d_object_name << " RBGS smoothing maxres = " << maxres << "\n"
+      << "  after " << isweep << " sweeps.\n";
+
+}
+
+/*
+ ********************************************************************
+ * Fix flux on coarse-fine boundaries computed from a               *
+ * constant-refine interpolation of coarse level data.              *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::ewingFixFlux(
+   const hier::Patch& patch,
+   const pdat::CellData<double>& soln_data,
+   pdat::SideData<double>& flux_data,
+   const hier::IntVector& ratio_to_coarser) const
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, soln_data, flux_data,
+      ratio_to_coarser);
+
+   const int patch_ln = patch.getPatchLevelNumber();
+   const hier::GlobalId id = patch.getGlobalId();
+   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
+      patch.getPatchGeometry();
+   const double* dx = patch_geom->getDx();
+   const hier::Box& patch_box(patch.getBox());
+   const hier::Index& plower = patch_box.lower();
+   const hier::Index& pupper = patch_box.upper();
+
+   const tbox::Array<hier::BoundaryBox>& bboxes =
+      d_cf_boundary[patch_ln]->getBoundaries(id, 1);
+   int bn, nboxes = bboxes.getSize();
+
+   if (d_stokes_spec.dIsVariable()) {
+
+      tbox::Pointer<pdat::SideData<double> > diffcoef_data;
+      diffcoef_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
+
+      for (bn = 0; bn < nboxes; ++bn) {
+         const hier::BoundaryBox& boundary_box = bboxes[bn];
+
+         TBOX_ASSERT(boundary_box.getBoundaryType() == 1);
+
+         const hier::Box& bdry_box = boundary_box.getBox();
+         const hier::Index& blower = bdry_box.lower();
+         const hier::Index& bupper = bdry_box.upper();
+         const int location_index = boundary_box.getLocationIndex();
+         if (d_dim == tbox::Dimension(2)) {
+            F77_FUNC(ewingfixfluxvardc2d, EWINGFIXFLUXVARDC2D) (
+               flux_data.getPointer(0), flux_data.getPointer(1),
+               &flux_data.getGhostCellWidth()[0],
+               &flux_data.getGhostCellWidth()[1],
+               diffcoef_data->getPointer(0), diffcoef_data->getPointer(1),
+               &diffcoef_data->getGhostCellWidth()[0],
+               &diffcoef_data->getGhostCellWidth()[1],
+               soln_data.getPointer(),
+               &soln_data.getGhostCellWidth()[0],
+               &soln_data.getGhostCellWidth()[1],
+               &plower[0], &pupper[0], &plower[1], &pupper[1],
+               &location_index,
+               &ratio_to_coarser[0],
+               &blower[0], &bupper[0],
+               dx);
+         } else if (d_dim == tbox::Dimension(3)) {
+            F77_FUNC(ewingfixfluxvardc3d, EWINGFIXFLUXVARDC3D) (
+               flux_data.getPointer(0),
+               flux_data.getPointer(1),
+               flux_data.getPointer(2),
+               &flux_data.getGhostCellWidth()[0],
+               &flux_data.getGhostCellWidth()[1],
+               &flux_data.getGhostCellWidth()[2],
+               diffcoef_data->getPointer(0),
+               diffcoef_data->getPointer(1),
+               diffcoef_data->getPointer(2),
+               &diffcoef_data->getGhostCellWidth()[0],
+               &diffcoef_data->getGhostCellWidth()[1],
+               &diffcoef_data->getGhostCellWidth()[2],
+               soln_data.getPointer(),
+               &soln_data.getGhostCellWidth()[0],
+               &soln_data.getGhostCellWidth()[1],
+               &soln_data.getGhostCellWidth()[2],
+               &plower[0], &pupper[0],
+               &plower[1], &pupper[1],
+               &plower[2], &pupper[2],
+               &location_index,
+               &ratio_to_coarser[0],
+               &blower[0], &bupper[0],
+               dx);
+         } else {
+            TBOX_ERROR("CellStokesFACOps : DIM > 3 not supported" << std::endl);
+         }
+
+      }
+   } else {
+
+      const double diffcoef_constant = d_stokes_spec.getDConstant();
+
+      for (bn = 0; bn < nboxes; ++bn) {
+         const hier::BoundaryBox& boundary_box = bboxes[bn];
+
+         TBOX_ASSERT(boundary_box.getBoundaryType() == 1);
+
+         const hier::Box& bdry_box = boundary_box.getBox();
+         const hier::Index& blower = bdry_box.lower();
+         const hier::Index& bupper = bdry_box.upper();
+         const int location_index = boundary_box.getLocationIndex();
+         if (d_dim == tbox::Dimension(2)) {
+            F77_FUNC(ewingfixfluxcondc2d, EWINGFIXFLUXCONDC2D) (
+               flux_data.getPointer(0), flux_data.getPointer(1),
+               &flux_data.getGhostCellWidth()[0],
+               &flux_data.getGhostCellWidth()[1],
+               diffcoef_constant,
+               soln_data.getPointer(),
+               &soln_data.getGhostCellWidth()[0],
+               &soln_data.getGhostCellWidth()[1],
+               &plower[0], &pupper[0],
+               &plower[1], &pupper[1],
+               &location_index,
+               &ratio_to_coarser[0],
+               &blower[0], &bupper[0],
+               dx);
+         } else if (d_dim == tbox::Dimension(3)) {
+            F77_FUNC(ewingfixfluxcondc3d, EWINGFIXFLUXCONDC3D) (
+               flux_data.getPointer(0),
+               flux_data.getPointer(1),
+               flux_data.getPointer(2),
+               &flux_data.getGhostCellWidth()[0],
+               &flux_data.getGhostCellWidth()[1],
+               &flux_data.getGhostCellWidth()[2],
+               diffcoef_constant,
+               soln_data.getPointer(),
+               &soln_data.getGhostCellWidth()[0],
+               &soln_data.getGhostCellWidth()[1],
+               &soln_data.getGhostCellWidth()[2],
+               &plower[0], &pupper[0],
+               &plower[1], &pupper[1],
+               &plower[2], &pupper[2],
+               &location_index,
+               &ratio_to_coarser[0],
+               &blower[0], &bupper[0],
+               dx);
+         }
+      }
+   }
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual solveCoarsestLevel             *
+ * function                                                         *
+ ********************************************************************
+ */
+
+int CellStokesFACOps::solveCoarsestLevel(
+   SAMRAIVectorReal<double>& data,
+   const SAMRAIVectorReal<double>& residual,
+   int coarsest_ln) {
+
+   t_solve_coarsest->start();
+
+   checkInputPatchDataIndices();
+
+   int return_value = 0;
+
+   if (d_coarse_solver_choice == "jacobi") {
+      d_residual_tolerance_during_smoothing = d_coarse_solver_tolerance;
+      smoothError(data,
+         residual,
+         coarsest_ln,
+         d_coarse_solver_max_iterations);
+      d_residual_tolerance_during_smoothing = -1.0;
+   } else if (d_coarse_solver_choice == "redblack") {
+      d_residual_tolerance_during_smoothing = d_coarse_solver_tolerance;
+      smoothError(data,
+         residual,
+         coarsest_ln,
+         d_coarse_solver_max_iterations);
+      d_residual_tolerance_during_smoothing = -1.0;
+   } else if (d_coarse_solver_choice == "hypre") {
+#ifndef HAVE_HYPRE
+      TBOX_ERROR(d_object_name << ": Coarse level solver choice '"
+                               << d_coarse_solver_choice
+                               << "' unavailable in "
+                               << "scapCellStokesOps::solveCoarsestLevel.");
+#else
+      return_value = solveCoarsestLevel_HYPRE(data, residual, coarsest_ln);
+#endif
+   } else {
+      TBOX_ERROR(
+         d_object_name << ": Bad coarse level solver choice '"
+         << d_coarse_solver_choice
+         <<
+         "' in scapCellStokesOps::solveCoarsestLevel.");
+   }
+
+   xeqScheduleGhostFillNoCoarse(data.getComponentDescriptorIndex(0),
+      coarsest_ln);
+
+   t_solve_coarsest->stop();
+
+   return return_value;
+}
+
+#ifdef HAVE_HYPRE
+/*
+ ********************************************************************
+ * Solve coarsest level using Hypre                                 *
+ * We only solve for the error, so we always use homogeneous bc.    *
+ ********************************************************************
+ */
+
+int CellStokesFACOps::solveCoarsestLevel_HYPRE(
+   SAMRAIVectorReal<double>& data,
+   const SAMRAIVectorReal<double>& residual,
+   int coarsest_ln) {
+
+   NULL_USE(coarsest_ln);
+
+#ifndef HAVE_HYPRE
+   TBOX_ERROR(d_object_name << ": Coarse level solver choice '"
+                            << d_coarse_solver_choice
+                            << "' unavailable in "
+                            << "CellStokesFACOps::solveCoarsestLevel.");
+
+   return 0;
+
+#else
+
+   checkInputPatchDataIndices();
+   d_hypre_solver.setStoppingCriteria(d_coarse_solver_max_iterations,
+      d_coarse_solver_tolerance);
+   const int solver_ret =
+      d_hypre_solver.solveSystem(
+         data.getComponentDescriptorIndex(0),
+         residual.getComponentDescriptorIndex(0),
+         true);
+   /*
+    * Present data on the solve.
+    * The Hypre solver returns 0 if converged.
+    */
+   if (d_enable_logging) tbox::plog
+      << d_object_name << " Hypre solve " << (solver_ret ? "" : "NOT ")
+      << "converged\n"
+      << "\titerations: " << d_hypre_solver.getNumberOfIterations() << "\n"
+      << "\tresidual: " << d_hypre_solver.getRelativeResidualNorm() << "\n";
+
+   return !solver_ret;
+
+#endif
+
+}
+#endif
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual                                *
+ * computeCompositeResidualOnLevel function                         *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::computeCompositeResidualOnLevel(
+   SAMRAIVectorReal<double>& residual,
+   const SAMRAIVectorReal<double>& solution,
+   const SAMRAIVectorReal<double>& rhs,
+   int ln,
+   bool error_equation_indicator) {
+
+   t_compute_composite_residual->start();
+
+   checkInputPatchDataIndices();
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (residual.getPatchHierarchy() != d_hierarchy
+       || solution.getPatchHierarchy() != d_hierarchy
+       || rhs.getPatchHierarchy() != d_hierarchy) {
+      TBOX_ERROR(d_object_name << ": Vector hierarchy does not match\n"
+         "internal hierarchy.");
+   }
+#endif
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
+
+   /*
+    * Set up the bc helper so that when we use a refine schedule
+    * to fill ghosts, the correct data is operated on.
+    */
+   const int soln_id = solution.getComponentDescriptorIndex(0);
+   d_bc_helper.setTargetDataId(soln_id);
+   d_bc_helper.setHomogeneousBc(error_equation_indicator);
+
+   const int flux_id = (d_flux_id != -1) ? d_flux_id : d_flux_scratch_id;
+
+   /*
+    * Assumptions:
+    * 1. Data does not yet exist in ghost boundaries.
+    * 2. Residual data on next finer grid (if any)
+    *    has been computed already.
+    * 3. Flux data from next finer grid (if any) has
+    *    been computed but has not been coarsened to
+    *    this level.
+    *
+    * Steps:
+    * S1. Fill solution ghost data by refinement
+    *     or setting physical boundary conditions.
+    *     This also brings in information from coarser
+    *     to form the composite grid flux.
+    * S2. Compute flux on ln.
+    * S3. If next finer is available,
+    *     Coarsen flux data on next finer level,
+    *     overwriting flux computed from coarse data.
+    * S4. Compute residual data from flux.
+    */
+
+   /* S1. Fill solution ghost data. */
+   {
+      tbox::Pointer<xfer::RefineSchedule> ln_refine_schedule;
+      if (ln > d_ln_min) {
+         /* Fill from current, next coarser level and physical boundary */
+         xeqScheduleGhostFill(soln_id, ln);
+      } else {
+         /* Fill from current and physical boundary */
+         xeqScheduleGhostFillNoCoarse(soln_id, ln);
+      }
+   }
+
+   /*
+    * For the whole level, make sure the internal
+    * side-centered data is allocated and note
+    * whether that data should be deallocated when done.
+    * We do this for the whole level because the data
+    * undergoes transfer operations which require the
+    * whole level data.
+    */
+   bool deallocate_flux_data_when_done = false;
+   if (flux_id == d_flux_scratch_id) {
+      if (!level->checkAllocated(flux_id)) {
+         level->allocatePatchData(flux_id);
+         deallocate_flux_data_when_done = true;
+      }
+   }
+
+   /*
+    * S2. Compute flux on patches in level.
+    */
+   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
+      tbox::Pointer<hier::Patch> patch = *pi;
+
+      tbox::Pointer<pdat::CellData<double> >
+      soln_data = solution.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::CellData<double> >
+      rhs_data = rhs.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::CellData<double> >
+      residual_data = residual.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::SideData<double> >
+      flux_data = patch->getPatchData(flux_id);
+      computeFluxOnPatch(
+         *patch,
+         level->getRatioToCoarserLevel(),
+         *soln_data,
+         *flux_data);
+
+   }
+
+   /*
+    * S3. Coarsen oflux data from next finer level so that
+    * the computed flux becomes the composite grid flux.
+    */
+   if (ln < d_ln_max) {
+      xeqScheduleFluxCoarsen(flux_id, d_oflux_scratch_id, ln);
+   }
+
+   /*
+    * S4. Compute residual on patches in level.
+    */
+   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
+      tbox::Pointer<hier::Patch> patch = *pi;
+      tbox::Pointer<pdat::CellData<double> >
+      soln_data = solution.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::CellData<double> >
+      rhs_data = rhs.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::CellData<double> >
+      residual_data = residual.getComponentPatchData(0, *patch);
+      tbox::Pointer<pdat::SideData<double> >
+      flux_data = patch->getPatchData(flux_id);
+      computeResidualOnPatch(*patch,
+         *flux_data,
+         *soln_data,
+         *rhs_data,
+         *residual_data);
+
+      if (ln > d_ln_min) {
+         /*
+          * Save outerflux data so that next coarser level
+          *  can compute its coarse-fine composite flux.
+          *  This is not strictly needed in this "compute residual"
+          *  loop through the patches, but we put it here to
+          *  avoid writing another loop for it.
+          */
+         tbox::Pointer<pdat::OutersideData<double> >
+         oflux_data = patch->getPatchData(d_oflux_scratch_id);
+
+         TBOX_ASSERT(oflux_data);
+
+         oflux_data->copy(*flux_data);
+      }
+   }
+
+   if (deallocate_flux_data_when_done) {
+      level->deallocatePatchData(flux_id);
+   }
+
+   t_compute_composite_residual->stop();
+}
+
+/*
+ ********************************************************************
+ * FACOperatorStrategy virtual computeResidualNorm             *
+ * function                                                         *
+ ********************************************************************
+ */
+
+double CellStokesFACOps::computeResidualNorm(
+   const SAMRAIVectorReal<double>& residual,
+   int fine_ln,
+   int coarse_ln)
+{
+
+   if (coarse_ln != residual.getCoarsestLevelNumber() ||
+       fine_ln != residual.getFinestLevelNumber()) {
+      TBOX_ERROR("CellStokesFACOps::computeResidualNorm() is not\n"
+         << "set up to compute residual except on the range of\n"
+         << "levels defining the vector.\n");
+   }
+   t_compute_residual_norm->start();
+   /*
+    * The residual vector was cloned from vectors that has
+    * the proper weights associated with them, so we do not
+    * have to explicitly weight the residuals.
+    *
+    * maxNorm: not good to use because Hypre's norm does not
+    *   correspond to it.  Also maybe too sensitive to spikes.
+    * L2Norm: maybe good.  But does not correspond to the
+    *   scale of the quantity.
+    * L1Norm: maybe good.  Correspond to scale of quantity,
+    *   but may be too insensitive to spikes.
+    * RMSNorm: maybe good.
+    */
+   double norm = residual.RMSNorm();
+   t_compute_residual_norm->stop();
+   return norm;
+}
+
+/*
+ ********************************************************************
+ * Compute the vector weight and put it at a specified patch data   *
+ * index.                                                           *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::computeVectorWeights(
+   tbox::Pointer<hier::PatchHierarchy> hierarchy,
+   int weight_id,
+   int coarsest_ln,
+   int finest_ln) const
+{
+   TBOX_ASSERT(!hierarchy.isNull());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
+
+   if (coarsest_ln == -1) coarsest_ln = 0;
+   if (finest_ln == -1) finest_ln = hierarchy->getFinestLevelNumber();
+   if (finest_ln < coarsest_ln) {
+      TBOX_ERROR(d_object_name
+         << ": Illegal level number range.  finest_ln < coarsest_ln.");
+   }
+
+   int ln;
+   for (ln = finest_ln; ln >= coarsest_ln; --ln) {
+
+      /*
+       * On every level, first assign cell volume to vector weight.
+       */
+
+      tbox::Pointer<hier::PatchLevel> level =
+         hierarchy->getPatchLevel(ln);
+      for (hier::PatchLevel::Iterator p(level); p; p++) {
+         tbox::Pointer<hier::Patch> patch = *p;
+         tbox::Pointer<geom::CartesianPatchGeometry> patch_geometry =
+            patch->getPatchGeometry();
+         const double* dx = patch_geometry->getDx();
+         double cell_vol = dx[0];
+         if (d_dim > tbox::Dimension(1)) {
+            cell_vol *= dx[1];
+         }
+
+         if (d_dim > tbox::Dimension(2)) {
+            cell_vol *= dx[2];
+         }
+
+         tbox::Pointer<pdat::CellData<double> > w =
+            patch->getPatchData(weight_id);
+         if (!w) {
+            TBOX_ERROR(d_object_name
+               << ": weight id must refer to a pdat::CellVariable");
+         }
+         w->fillAll(cell_vol);
+      }
+
+      /*
+       * On all but the finest level, assign 0 to vector
+       * weight to cells covered by finer cells.
+       */
+
+      if (ln < finest_ln) {
+
+         /*
+          * First get the boxes that describe index space of the next finer
+          * level and coarsen them to describe corresponding index space
+          * at this level.
+          */
+
+         tbox::Pointer<hier::PatchLevel> next_finer_level =
+            hierarchy->getPatchLevel(ln + 1);
+         hier::BoxArray coarsened_boxes = next_finer_level->getBoxes();
+         hier::IntVector coarsen_ratio(next_finer_level->getRatioToLevelZero());
+         coarsen_ratio /= level->getRatioToLevelZero();
+         coarsened_boxes.coarsen(coarsen_ratio);
+
+         /*
+          * Then set vector weight to 0 wherever there is
+          * a nonempty intersection with the next finer level.
+          * Note that all assignments are local.
+          */
+
+         for (hier::PatchLevel::Iterator p(level); p; p++) {
+
+            tbox::Pointer<hier::Patch> patch = *p;
+            for (int i = 0; i < coarsened_boxes.getNumberOfBoxes(); i++) {
+
+               hier::Box coarse_box = coarsened_boxes[i];
+               hier::Box intersection = coarse_box * (patch->getBox());
+               if (!intersection.empty()) {
+                  tbox::Pointer<pdat::CellData<double> > w =
+                     patch->getPatchData(weight_id);
+                  w->fillAll(0.0, intersection);
+
+               }  // assignment only in non-empty intersection
+            }  // loop over coarsened boxes from finer level
+         }  // loop over patches in level
+      }  // all levels except finest
+   }  // loop over levels
+}
+
+/*
+ ********************************************************************
+ * Check the validity and correctness of input data for this class. *
+ ********************************************************************
+ */
+
+void CellStokesFACOps::checkInputPatchDataIndices() const {
+   /*
+    * Check input validity and correctness.
+    */
+   hier::VariableDatabase& vdb(*hier::VariableDatabase::getDatabase());
+
+   if (!d_stokes_spec.dIsConstant()
+       && d_stokes_spec.getDPatchDataId() != -1) {
+      tbox::Pointer<hier::Variable> var;
+      vdb.mapIndexToVariable(d_stokes_spec.getDPatchDataId(), var);
+      tbox::Pointer<pdat::SideVariable<double> > diffcoef_var = var;
+      if (!diffcoef_var) {
+         TBOX_ERROR(d_object_name
+            << ": Bad diffusion coefficient patch data index.");
+      }
+   }
+
+   if (!d_stokes_spec.cIsConstant() && !d_stokes_spec.cIsZero()) {
+      tbox::Pointer<hier::Variable> var;
+      vdb.mapIndexToVariable(d_stokes_spec.getCPatchDataId(), var);
+      tbox::Pointer<pdat::CellVariable<double> > scalar_field_var = var;
+      if (!scalar_field_var) {
+         TBOX_ERROR(d_object_name << ": Bad linear term patch data index.");
+      }
+   }
+
+   if (d_flux_id != -1) {
+      tbox::Pointer<hier::Variable> var;
+      vdb.mapIndexToVariable(d_flux_id, var);
+      tbox::Pointer<pdat::SideVariable<double> > flux_var = var;
+
+      TBOX_ASSERT(flux_var);
+   }
+
+}
+
+/*
+ *******************************************************************
+ *                                                                 *
+ * AMR-unaware patch-centered computational kernels.               *
+ *                                                                 *
+ *******************************************************************
+ */
+
+void CellStokesFACOps::computeFluxOnPatch(
+   const hier::Patch& patch,
+   const hier::IntVector& ratio_to_coarser_level,
+   const pdat::CellData<double>& w_data,
+   pdat::SideData<double>& Dgradw_data) const
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, ratio_to_coarser_level, w_data,
+      Dgradw_data);
+   TBOX_ASSERT(patch.inHierarchy());
+   TBOX_ASSERT(w_data.getGhostCellWidth() >=
+      hier::IntVector::getOne(ratio_to_coarser_level.getDim()));
+
+   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
+      patch.getPatchGeometry();
+   const hier::Box& box = patch.getBox();
+   const int* lower = &box.lower()[0];
+   const int* upper = &box.upper()[0];
+   const double* dx = patch_geom->getDx();
+
+   double D_value;
+   tbox::Pointer<pdat::SideData<double> > D_data;
+   if (d_stokes_spec.dIsConstant()) {
+      D_value = d_stokes_spec.getDConstant();
+   } else {
+      D_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
+   }
+
+   if (d_stokes_spec.dIsConstant()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(compfluxcondc2d, COMPFLUXCONDC2D) (
+            Dgradw_data.getPointer(0),
+            Dgradw_data.getPointer(1),
+            &Dgradw_data.getGhostCellWidth()[0],
+            &Dgradw_data.getGhostCellWidth()[1],
+            D_value,
+            w_data.getPointer(),
+            &w_data.getGhostCellWidth()[0],
+            &w_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(compfluxcondc3d, COMPFLUXCONDC3D) (
+            Dgradw_data.getPointer(0),
+            Dgradw_data.getPointer(1),
+            Dgradw_data.getPointer(2),
+            &Dgradw_data.getGhostCellWidth()[0],
+            &Dgradw_data.getGhostCellWidth()[1],
+            &Dgradw_data.getGhostCellWidth()[2],
+            D_value,
+            w_data.getPointer(),
+            &w_data.getGhostCellWidth()[0],
+            &w_data.getGhostCellWidth()[1],
+            &w_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx);
+      }
+   } else {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(compfluxvardc2d, COMPFLUXVARDC2D) (
+            Dgradw_data.getPointer(0),
+            Dgradw_data.getPointer(1),
+            &Dgradw_data.getGhostCellWidth()[0],
+            &Dgradw_data.getGhostCellWidth()[1],
+            D_data->getPointer(0),
+            D_data->getPointer(1),
+            &D_data->getGhostCellWidth()[0],
+            &D_data->getGhostCellWidth()[1],
+            w_data.getPointer(),
+            &w_data.getGhostCellWidth()[0],
+            &w_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx);
+      }
+      if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(compfluxvardc3d, COMPFLUXVARDC3D) (
+            Dgradw_data.getPointer(0),
+            Dgradw_data.getPointer(1),
+            Dgradw_data.getPointer(2),
+            &Dgradw_data.getGhostCellWidth()[0],
+            &Dgradw_data.getGhostCellWidth()[1],
+            &Dgradw_data.getGhostCellWidth()[2],
+            D_data->getPointer(0),
+            D_data->getPointer(1),
+            D_data->getPointer(2),
+            &D_data->getGhostCellWidth()[0],
+            &D_data->getGhostCellWidth()[1],
+            &D_data->getGhostCellWidth()[2],
+            w_data.getPointer(),
+            &w_data.getGhostCellWidth()[0],
+            &w_data.getGhostCellWidth()[1],
+            &w_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx);
+      }
+   }
+
+   const int patch_ln = patch.getPatchLevelNumber();
+
+   if (d_cf_discretization == "Ewing" && patch_ln > d_ln_min) {
+      ewingFixFlux(patch,
+         w_data,
+         Dgradw_data,
+         ratio_to_coarser_level);
+   }
+
+}
+
+void CellStokesFACOps::computeResidualOnPatch(
+   const hier::Patch& patch,
+   const pdat::SideData<double>& flux_data,
+   const pdat::CellData<double>& soln_data,
+   const pdat::CellData<double>& rhs_data,
+   pdat::CellData<double>& residual_data) const
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS5(d_dim, patch, flux_data, soln_data, rhs_data,
+      residual_data);
+
+   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
+      patch.getPatchGeometry();
+   const hier::Box& box = patch.getBox();
+   const int* lower = &box.lower()[0];
+   const int* upper = &box.upper()[0];
+   const double* dx = patch_geom->getDx();
+
+   tbox::Pointer<pdat::CellData<double> > scalar_field_data;
+   double scalar_field_constant;
+   if (d_stokes_spec.cIsVariable()) {
+      scalar_field_data =
+         patch.getPatchData(d_stokes_spec.getCPatchDataId());
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(compresvarsca2d, COMPRESVARSCA2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0], &lower[1], &upper[1],
+            dx);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(compresvarsca3d, COMPRESVARSCA3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            &residual_data.getGhostCellWidth()[2],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            &scalar_field_data->getGhostCellWidth()[2],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
+            dx);
+      }
+   } else if (d_stokes_spec.cIsConstant()) {
+      scalar_field_constant = d_stokes_spec.getCConstant();
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0], &lower[1], &upper[1],
+            dx);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            &residual_data.getGhostCellWidth()[2],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
+            dx);
+      }
+   } else {
+      scalar_field_constant = 0.0;
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(compresconsca2d, COMPRESCONSCA2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0], &lower[1], &upper[1],
+            dx);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(compresconsca3d, COMPRESCONSCA3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            residual_data.getPointer(),
+            &residual_data.getGhostCellWidth()[0],
+            &residual_data.getGhostCellWidth()[1],
+            &residual_data.getGhostCellWidth()[2],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0], &lower[1], &upper[1], &lower[2], &upper[2],
+            dx);
+      }
+   }
+}
+
+void CellStokesFACOps::redOrBlackSmoothingOnPatch(
+   const hier::Patch& patch,
+   const pdat::SideData<double>& flux_data,
+   const pdat::CellData<double>& rhs_data,
+   pdat::CellData<double>& soln_data,
+   char red_or_black,
+   double* p_maxres) const
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim, patch, flux_data, soln_data, rhs_data);
+   TBOX_ASSERT(red_or_black == 'r' || red_or_black == 'b');
+
+   const int offset = red_or_black == 'r' ? 0 : 1;
+   tbox::Pointer<geom::CartesianPatchGeometry> patch_geom =
+      patch.getPatchGeometry();
+   const hier::Box& box = patch.getBox();
+   const int* lower = &box.lower()[0];
+   const int* upper = &box.upper()[0];
+   const double* dx = patch_geom->getDx();
+
+   tbox::Pointer<pdat::CellData<double> > scalar_field_data;
+   double scalar_field_constant;
+   tbox::Pointer<pdat::SideData<double> > diffcoef_data;
+   double diffcoef_constant;
+
+   if (d_stokes_spec.cIsVariable()) {
+      scalar_field_data =
+         patch.getPatchData(d_stokes_spec.getCPatchDataId());
+   } else if (d_stokes_spec.cIsConstant()) {
+      scalar_field_constant = d_stokes_spec.getCConstant();
+   } else {
+      scalar_field_constant = 0.0;
+   }
+   if (d_stokes_spec.dIsVariable()) {
+      diffcoef_data = patch.getPatchData(d_stokes_spec.getDPatchDataId());
+   } else {
+      diffcoef_constant = d_stokes_spec.getDConstant();
+   }
+
+   double maxres = 0.0;
+   if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsVariable()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxvardcvarsf2d, RBGSWITHFLUXMAXVARDCVARSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxvardcvarsf3d, RBGSWITHFLUXMAXVARDCVARSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            diffcoef_data->getPointer(2),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            &diffcoef_data->getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            &scalar_field_data->getGhostCellWidth()[2],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   } else if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsConstant()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            diffcoef_data->getPointer(2),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            &diffcoef_data->getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   } else if (d_stokes_spec.dIsVariable() && d_stokes_spec.cIsZero()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxvardcconsf2d, RBGSWITHFLUXMAXVARDCCONSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxvardcconsf3d, RBGSWITHFLUXMAXVARDCCONSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_data->getPointer(0),
+            diffcoef_data->getPointer(1),
+            diffcoef_data->getPointer(2),
+            &diffcoef_data->getGhostCellWidth()[0],
+            &diffcoef_data->getGhostCellWidth()[1],
+            &diffcoef_data->getGhostCellWidth()[2],
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsVariable()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxcondcvarsf2d, RBGSWITHFLUXMAXCONDCVARSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxcondcvarsf3d, RBGSWITHFLUXMAXCONDCVARSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            scalar_field_data->getPointer(),
+            &scalar_field_data->getGhostCellWidth()[0],
+            &scalar_field_data->getGhostCellWidth()[1],
+            &scalar_field_data->getGhostCellWidth()[2],
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsConstant()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            scalar_field_constant,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   } else if (!d_stokes_spec.dIsVariable() && d_stokes_spec.cIsZero()) {
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(rbgswithfluxmaxcondcconsf2d, RBGSWITHFLUXMAXCONDCCONSF2D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            dx,
+            &offset, &maxres);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(rbgswithfluxmaxcondcconsf3d, RBGSWITHFLUXMAXCONDCCONSF3D) (
+            flux_data.getPointer(0),
+            flux_data.getPointer(1),
+            flux_data.getPointer(2),
+            &flux_data.getGhostCellWidth()[0],
+            &flux_data.getGhostCellWidth()[1],
+            &flux_data.getGhostCellWidth()[2],
+            diffcoef_constant,
+            rhs_data.getPointer(),
+            &rhs_data.getGhostCellWidth()[0],
+            &rhs_data.getGhostCellWidth()[1],
+            &rhs_data.getGhostCellWidth()[2],
+            0.0,
+            soln_data.getPointer(),
+            &soln_data.getGhostCellWidth()[0],
+            &soln_data.getGhostCellWidth()[1],
+            &soln_data.getGhostCellWidth()[2],
+            &lower[0], &upper[0],
+            &lower[1], &upper[1],
+            &lower[2], &upper[2],
+            dx,
+            &offset, &maxres);
+      }
+   }
+
+   *p_maxres = maxres;
+}
+
+void
+CellStokesFACOps::xeqScheduleProlongation(
+   int dst_id,
+   int src_id,
+   int scr_id,
+   int dest_ln)
+{
+   if (!d_prolongation_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+   xfer::RefineAlgorithm refiner(d_dim);
+   refiner.
+   registerRefine(dst_id,
+      src_id,
+      scr_id,
+      d_prolongation_refine_operator);
+   refiner.
+   resetSchedule(d_prolongation_refine_schedules[dest_ln]);
+   d_prolongation_refine_schedules[dest_ln]->fillData(0.0);
+   d_prolongation_refine_algorithm->
+   resetSchedule(d_prolongation_refine_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::xeqScheduleURestriction(
+   int dst_id,
+   int src_id,
+   int dest_ln)
+{
+   if (!d_urestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+
+   xfer::CoarsenAlgorithm coarsener(d_dim);
+   coarsener.registerCoarsen(dst_id,
+      src_id,
+      d_urestriction_coarsen_operator);
+   coarsener.resetSchedule(d_urestriction_coarsen_schedules[dest_ln]);
+   d_urestriction_coarsen_schedules[dest_ln]->coarsenData();
+   d_urestriction_coarsen_algorithm->
+   resetSchedule(d_urestriction_coarsen_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::xeqScheduleRRestriction(
+   int dst_id,
+   int src_id,
+   int dest_ln)
+{
+   if (!d_rrestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+
+   xfer::CoarsenAlgorithm coarsener(d_dim);
+   coarsener.registerCoarsen(dst_id,
+      src_id,
+      d_rrestriction_coarsen_operator);
+   coarsener.resetSchedule(d_rrestriction_coarsen_schedules[dest_ln]);
+   d_rrestriction_coarsen_schedules[dest_ln]->coarsenData();
+   d_rrestriction_coarsen_algorithm->
+   resetSchedule(d_rrestriction_coarsen_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::xeqScheduleFluxCoarsen(
+   int dst_id,
+   int src_id,
+   int dest_ln)
+{
+   if (!d_flux_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+
+   xfer::CoarsenAlgorithm coarsener(d_dim);
+   coarsener.registerCoarsen(dst_id,
+      src_id,
+      d_flux_coarsen_operator);
+
+   coarsener.resetSchedule(d_flux_coarsen_schedules[dest_ln]);
+   d_flux_coarsen_schedules[dest_ln]->coarsenData();
+   d_flux_coarsen_algorithm->
+   resetSchedule(d_flux_coarsen_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::xeqScheduleGhostFill(
+   int dst_id,
+   int dest_ln)
+{
+   if (!d_ghostfill_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+   xfer::RefineAlgorithm refiner(d_dim);
+   refiner.
+   registerRefine(dst_id,
+      dst_id,
+      dst_id,
+      d_ghostfill_refine_operator);
+   refiner.
+   resetSchedule(d_ghostfill_refine_schedules[dest_ln]);
+   d_ghostfill_refine_schedules[dest_ln]->fillData(0.0);
+   d_ghostfill_refine_algorithm->
+   resetSchedule(d_ghostfill_refine_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::xeqScheduleGhostFillNoCoarse(
+   int dst_id,
+   int dest_ln)
+{
+   if (!d_ghostfill_nocoarse_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+   }
+   xfer::RefineAlgorithm refiner(d_dim);
+   refiner.
+   registerRefine(dst_id,
+      dst_id,
+      dst_id,
+      d_ghostfill_nocoarse_refine_operator);
+   refiner.
+   resetSchedule(d_ghostfill_nocoarse_refine_schedules[dest_ln]);
+   d_ghostfill_nocoarse_refine_schedules[dest_ln]->fillData(0.0);
+   d_ghostfill_nocoarse_refine_algorithm->
+   resetSchedule(d_ghostfill_nocoarse_refine_schedules[dest_ln]);
+}
+
+void
+CellStokesFACOps::finalizeCallback()
+{
+   for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
+      s_cell_scratch_var[d].setNull();
+      s_flux_scratch_var[d].setNull();
+      s_oflux_scratch_var[d].setNull();
+   }
+}
+
+}
+}
+#endif
diff -r a44a82f15794 -r fe2a9230921b StokesFACOps.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACOps.I	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,213 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Operator class for solving scalar Stokes using FAC 
+ *
+ ************************************************************************/
+namespace SAMRAI {
+namespace solv {
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setPreconditioner(
+   const FACPreconditioner* preconditioner) {
+   d_preconditioner = preconditioner;
+}
+
+#ifdef HAVE_HYPRE
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setUseSMG(
+   bool use_smg)
+{
+   if (d_hierarchy) {
+      TBOX_ERROR(
+         d_object_name << ": setUseSMG(bool) may NOT be called\n"
+         <<
+         "while the solver state is initialized, as that\n"
+         << "would lead to a corrupted solver state.\n");
+   }
+   d_hypre_solver.setUseSMG(use_smg);
+}
+#endif
+
+/*
+ ********************************************************************
+ * Set the physical boundary condition object.                      *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setPhysicalBcCoefObject(
+   const RobinBcCoefStrategy* physical_bc_coef)
+{
+   d_physical_bc_coef = physical_bc_coef;
+   d_bc_helper.setCoefImplementation(physical_bc_coef);
+#ifdef HAVE_HYPRE
+   d_hypre_solver.setPhysicalBcCoefObject(d_physical_bc_coef);
+#endif
+}
+
+/*
+ ********************************************************************
+ * Set the object specifying the parameters of the Stokes equation *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setStokesSpecifications(
+   const StokesSpecifications& spec)
+{
+   d_stokes_spec = spec;
+}
+
+/*
+ ********************************************************************
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::enableLogging(
+   bool enable_logging)
+{
+   d_enable_logging = enable_logging;
+}
+
+/*
+ ********************************************************************
+ * Set the patch data id for the flux.                              *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setFluxId(
+   int flux_id) {
+   d_flux_id = flux_id;
+#ifdef DEBUG_CHECK_ASSERTIONS
+   checkInputPatchDataIndices();
+#endif
+}
+
+/*
+ ********************************************************************
+ * Set the choice for smoothing algorithm.                          *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setSmoothingChoice(
+   const std::string& smoothing_choice)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (smoothing_choice != "redblack") {
+      TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
+                               << smoothing_choice
+                               << "' in CellStokesFACOps::setSmoothingChoice.");
+   }
+#endif
+   d_smoothing_choice = smoothing_choice;
+}
+
+/*
+ ********************************************************************
+ * Set the choice for the coarse level solver.                      *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setCoarsestLevelSolverChoice(
+   const std::string& choice) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+#ifndef HAVE_HYPRE
+   if (choice == "hypre") {
+      TBOX_ERROR(d_object_name << ": HYPRe library is not available.\n");
+   }
+#endif
+#endif
+   if (choice == "redblack"
+       || choice == "hypre") {
+      d_coarse_solver_choice = choice;
+   } else {
+      TBOX_ERROR(
+         d_object_name << ": Bad coarse level solver choice '"
+         << choice
+         <<
+         "' in scapCellStokesOpsX::setCoarseLevelSolver.");
+   }
+}
+
+/*
+ ********************************************************************
+ * Set the tolerance for the coarse level solver.                   *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setCoarsestLevelSolverTolerance(
+   double tol) {
+   d_coarse_solver_tolerance = tol;
+}
+
+/*
+ ********************************************************************
+ * Set the tolerance for the coarse level solver.                   *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setCoarsestLevelSolverMaxIterations(
+   int max_iterations) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (max_iterations < 0) {
+      TBOX_ERROR(d_object_name << ": Invalid number of max iterations\n");
+   }
+#endif
+   d_coarse_solver_max_iterations = max_iterations;
+}
+
+/*
+ ********************************************************************
+ * Set the coarse-fine discretization method.                       *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setCoarseFineDiscretization(
+   const std::string& coarsefine_method) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_hierarchy) {
+      TBOX_ERROR(
+         d_object_name << ": Cannot change coarse-fine\n"
+         <<
+         "discretization method while operator state\n"
+         << "is initialized because that causes a\n"
+         << "corruption in the state.\n");
+   }
+#endif
+   d_cf_discretization = coarsefine_method;
+}
+
+/*
+ ********************************************************************
+ * Set the prolongation method                                      *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACOps::setProlongationMethod(
+   const std::string& prolongation_method) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_hierarchy) {
+      TBOX_ERROR(
+         d_object_name << ": Cannot change prolongation method\n"
+         <<
+         "while operator state is initialized because that\n"
+         << "causes a corruption in the state.\n");
+   }
+#endif
+   d_prolongation_method = prolongation_method;
+}
+
+}
+}
diff -r a44a82f15794 -r fe2a9230921b StokesFACOps.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACOps.h	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,1044 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Operator class for cell-centered scalar Stokes using FAC 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesFACOps
+#define included_solv_StokesFACOps
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/solv/CartesianRobinBcHelper.h"
+#include "SAMRAI/solv/FACPreconditioner.h"
+#include "SAMRAI/solv/FACOperatorStrategy.h"
+#include "SAMRAI/solv/RobinBcCoefStrategy.h"
+#include "StokesHypreSolver.h"
+#include "SAMRAI/solv/SAMRAIVectorReal.h"
+#include "StokesSpecifications.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/math/HierarchySideDataOpsReal.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include "SAMRAI/pdat/CellDoubleConstantRefine.h"
+#include "SAMRAI/pdat/OutersideData.h"
+#include "SAMRAI/pdat/OutersideVariable.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/xfer/CoarsenSchedule.h"
+#include "SAMRAI/xfer/RefineSchedule.h"
+#include "SAMRAI/xfer/CoarsenAlgorithm.h"
+#include "SAMRAI/xfer/CoarsenOperator.h"
+#include "SAMRAI/xfer/RefineAlgorithm.h"
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/hier/CoarseFineBoundary.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/hier/PatchHierarchy.h"
+#include "SAMRAI/hier/PatchLevel.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/VariableContext.h"
+#include "SAMRAI/tbox/Database.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/tbox/Timer.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace solv {
+
+/*!
+ * @brief FAC operator class to solve Stokes's equation on a SAMR grid,
+ * using cell-centered, second-order finite-volume method, with Robin
+ * boundary conditions.
+ *
+ * This class provides operators that are used by the FAC
+ * preconditioner FACPreconditioner.
+ * It is used to solve the scalar Stokes's equation using a cell-centered
+ * second-order finite-volume discretization.
+ * It is designed to provide all operations specific to
+ * the scalar Stokes's equation,
+ * @f[ \nabla \cdot D \nabla u + C u = f @f]
+ * (see StokesSpecifications) where
+ * - C, D and f are indpendent of u
+ * - C is a cell-centered scalar field
+ * - D is the @em diffusion @em coefficients, stored on faces
+ * - f is a cell-centered scalar function
+ *
+ * You are left to provide the source function, initial guess, etc.,
+ * by specifying them in specific forms.
+ *
+ * This class provides:
+ * -# 5-point (second order), cell-centered stencil operations
+ *    for the discrete Laplacian.
+ * -# Red-black Gauss-Seidel smoothing.
+ * -# Provisions for working Robin boundary conditions
+ *    (see RobinBcCoefStrategy).
+ *
+ * This class is meant to provide the Stokes-specific operator
+ * used by the FAC preconditioner, FACPreconditioner.
+ * To use the preconditioner with this class, you will have to provide:
+ * -# The solution vector SAMRAIVectorReal,
+ *    with appropriate norm weighting for the cell-centered AMR mesh.
+ *    This class provides the function computeVectorWeights()
+ *    to help with computing the appropriate weights.
+ *    Since this is for a scalar equation, only the first depth
+ *    of the first component of the vectors are used.
+ *    All other parts are ignored.
+ * -# The source vector SAMRAIVectorReal for f.
+ * -# A StokesSpecifications objects to specify
+ *    the cell-centered scalar field C and the side-centered
+ *    diffusion coefficients D
+ * -# The boundary condition specifications in terms of the coefficients
+ *    @f$ \alpha @f$, @f$ \beta @f$ and @f$ \gamma @f$ in the
+ *    Robin formula @f$  \alpha u + \beta u_n = \gamma @f$ applied on the
+ *    boundary faces.  See RobinBcCoefStrategy.
+ *
+ * This class allocates and deallocates only its own scratch data.
+ * Other data that it manipuates are passed in as function arguments.
+ * Hence, it owns none of the solution vectors, error vectors,
+ * diffusion coefficient data, or any such things.
+ *
+ * Input Examples
+ * @verbatim
+ * coarse_solver_choice = "hypre"    // see setCoarsestLevelSolverChoice()
+ * coarse_solver_tolerance = 1e-14   // see setCoarsestLevelSolverTolerance()
+ * coarse_solver_max_iterations = 10 // see setCoarsestLevelSolverMaxIterations()
+ * smoothing_choice = "redblack"     // see setSmoothingChoice()
+ * cf_discretization = "Ewing"       // see setCoarseFineDiscretization()
+ * prolongation_method = "LINEAR_REFINE" // see setProlongationMethod()
+ * hypre_solver = { ... }            // tbox::Database for initializing Hypre solver
+ * @endverbatim
+ */
+class CellStokesFACOps:
+   public FACOperatorStrategy
+{
+
+public:
+   /*!
+    * @brief Constructor.
+    *
+    * If you want standard output and logging,
+    * pass in valid pointers for those streams.
+    * @param object_name Ojbect name
+    * @param database Input database
+    */
+   CellStokesFACOps(
+      const tbox::Dimension& dim,
+      const std::string& object_name = std::string(),
+      tbox::Pointer<tbox::Database> database =
+         tbox::Pointer<tbox::Database>(NULL));
+
+   /*!
+    * @brief Destructor.
+    *
+    * Deallocate internal data.
+    */
+   ~CellStokesFACOps(
+      void);
+
+   /*!
+    * @brief Set the scalar Stokes equation specifications.
+    */
+   void
+   setStokesSpecifications(
+      const StokesSpecifications& spec);
+
+   /*!
+    * @brief Enable logging.
+    *
+    * By default, logging is disabled.  The logging flag is
+    * propagated to the major components used by this class.
+    */
+   void
+   enableLogging(
+      bool enable_logging);
+
+   //@{
+   /*!
+    * @name Functions for setting solver mathematic algorithm controls
+    */
+
+   /*!
+    * @brief Set the choice of smoothing algorithms.
+    *
+    * Current smoothing choices are:
+    * - "redblack": Red-black Gauss-Seidel smoothing.
+    */
+   void
+   setSmoothingChoice(
+      const std::string& smoothing_choice);
+
+   /*!
+    * @brief Set coarse level solver.
+    *
+    * Select from these:
+    * - @c "redblack" (red-black smoothing until convergence--very slow!)
+    * - @c "hypre" (only if the HYPRE library is available).
+    */
+   void
+   setCoarsestLevelSolverChoice(
+      const std::string& choice);
+
+   /*!
+    * @brief Set tolerance for coarse level solve.
+    *
+    * If the coarse level solver requires a tolerance (currently, they all do),
+    * the specified value is used.
+    */
+   void
+   setCoarsestLevelSolverTolerance(
+      double tol);
+
+   /*!
+    * @brief Set max iterations for coarse level solve.
+    *
+    * If the coarse level solver requires a max iteration limit
+    * (currently, they all do), the specified value is used.
+    */
+   void
+   setCoarsestLevelSolverMaxIterations(
+      int max_iterations);
+
+   /*!
+    * @brief Set the coarse-fine boundary discretization method.
+    *
+    * Specify the @c op_name std::string which will be passed to
+    * xfer::Geometry::lookupRefineOperator() to get the operator
+    * for setting fine grid ghost cells from the coarse grid.
+    * Note that chosing this operator implicitly choses the
+    * discretization method at the coarse-fine boundary.
+    *
+    * There is one important instance where this std::string is
+    * @em not passed to xfer::Geometry::lookupRefineOperator.
+    * If this variable is set to "Ewing", Ewing's coarse-fine
+    * discretization is used (a constant refinement is performed,
+    * and the flux is later corrected to result in Ewing's scheme).
+    * For a reference to Ewing's discretization method, see
+    * "Local Refinement Techniques for Elliptic Problems on Cell-Centered
+    * Grids, I. Error Analysis", Mathematics of Computation, Vol. 56, No. 194,
+    * April 1991, pp. 437-461.
+    *
+    * @param coarsefine_method String selecting the coarse-fine discretization method.
+    */
+   void
+   setCoarseFineDiscretization(
+      const std::string& coarsefine_method);
+
+   /*!
+    * @brief Set the name of the prolongation method.
+    *
+    * Specify the @c op_name std::string which will be passed to
+    * xfer::Geometry::lookupRefineOperator() to get the operator
+    * for prolonging the coarse-grid correction.
+    *
+    * By default, "CONSTANT_REFINE" is used.  "LINEAR_REFINE" seems to
+    * to lead to faster convergence, but it does NOT satisfy the Galerkin
+    * condition.
+    *
+    * Prolonging using linear refinement requires a Robin bc
+    * coefficient implementation that is capable of delivering
+    * coefficients for non-hierarchy data, because linear refinement
+    * requires boundary conditions to be set on temporary levels.
+    *
+    * @param prolongation_method String selecting the coarse-fine
+    *        discretization method.
+    */
+   void
+   setProlongationMethod(
+      const std::string& prolongation_method);
+
+#ifdef HAVE_HYPRE
+   /*!
+    * @brief Set whether to use Hypre's PFMG algorithm instead of the
+    * SMG algorithm.
+    *
+    * This flag affects the Hypre solver (used to solve the coarsest level).
+    * The flag is used to select which of HYPRE's linear solver algorithms
+    * to use if true, the semicoarsening multigrid algorithm is used, and if
+    * false, the ``PF'' multigrid algorithm is used.
+    * By default, the SMG algorithm is used.
+    *
+    * This setting has effect only when Hypre is chosen for the coarsest
+    * level solver.  See setCoarsestLevelSolverChoice().
+    *
+    * Changing the algorithm must be done before initializing the solver
+    * state and must NOT be done while the state is initialized
+    * (the program will exit), as that would corrupt the state.
+    */
+   void
+   setUseSMG(
+      bool use_smg);
+#endif
+
+   //@}
+
+   //@{
+   /*!
+    * @name Functions for setting patch data indices and coefficients
+    */
+
+   /*!
+    * @brief Set the scratch patch data index for the flux.
+    *
+    * The use of this function is optional.
+    * The patch data index should be a pdat::SideData<DIM> type of variable.
+    * If the flux id is -1 (the default initial value), scratch space
+    * for the flux is allocated as needed and immediately deallocated
+    * afterward, level by level.  If you have space preallocated for
+    * flux and you would like that to be used, set flux id to the
+    * patch data index of that space.
+    */
+   void
+   setFluxId(
+      int flux_id);
+
+   //@}
+
+   /*!
+    * @brief Provide an implementation for getting the
+    * physical bc coefficients
+    *
+    * If your solution is fixed at the physical boundary
+    * ghost cell centers AND those cells have the correct
+    * values before entering solveSystem(), you may use a
+    * GhostCellRobinBcCoefs object.
+    *
+    * If your solution is @b not fixed at the ghost cell centers,
+    * the ghost cell values will change as the interior
+    * cell values change.  In those cases, the flexible
+    * Robin boundary conditions are applied.  You must
+    * call this function to provide the implementation for
+    * determining the boundary condition coefficients.
+    *
+    * @param physical_bc_coef tbox::Pointer to an object that can
+    *        set the Robin bc coefficients.
+    */
+   void
+   setPhysicalBcCoefObject(
+      const RobinBcCoefStrategy* physical_bc_coef);
+
+   //@{
+
+   /*!
+    * @name Functions for checking validity and correctness of state.
+    */
+
+   /*!
+    * @brief Check validity and correctness of input patch data indices.
+    *
+    * Descriptors checked:
+    * -# Diffusion coefficient (see setDiffcoefId())
+    * -# Flux (see setFluxId())
+    * -# Source (see setScalarFieldId())
+    */
+   void
+   checkInputPatchDataIndices() const;
+
+   //@}
+
+   /*!
+    * @brief Set weight appropriate for computing vector norms.
+    *
+    * If you this function to set the weights used when you
+    * SAMRAIVectorReal::addComponent, you can use the
+    * vector norm functions of SAMRAIVectorReal, and
+    * the weights will be used to blank out coarse grid
+    * regions under fine grids.
+    *
+    * The weights computed are specific to the cell-centered
+    * discretization used by this class.  The weight is equal
+    * to the cell volume if the cell has not been refined,
+    * and zero if it has.
+    *
+    * This function is state-independent.  All inputs are in
+    * the argument list.
+    *
+    * @param hierarchy Hierarchy configuration to compute weights for
+    * @param weight_id hier::Patch data index of the weight
+    * @param coarsest_ln Coarsest level number.  Must be included
+    *        in hierarchy.  Must not be greater than @c finest_ln.
+    *        Default to 0.
+    * @param finest_ln Finest level number.  Must be included
+    *        in hierarchy.  Must not be less than @c coarsest_ln.
+    *        Default to finest level in @c hierarchy.
+    */
+   void
+   computeVectorWeights(
+      tbox::Pointer<hier::PatchHierarchy> hierarchy,
+      int weight_id,
+      int coarsest_ln = -1,
+      int finest_ln = -1) const;
+
+   /*!
+    * @brief Set the FAC preconditioner that will be using this object.
+    *
+    * The FAC preconditioner is accessed to get convergence data during
+    * the cycle postprocessing step.  It is optional.
+    */
+   void
+   setPreconditioner(
+      const FACPreconditioner* preconditioner);
+
+   /*!
+    * @brief function to compute flux, using general diffusion
+    * coefficient data.
+    *
+    * Recall that this solver class discretizes the PDE
+    * @f[ \nabla \cdot D \nabla u + C u = f @f] on an AMR grid.  This member
+    * function allows users of this solver class to compute gradient
+    * terms, @f[ D \nabla w @f], in their code in a manner consistent with the
+    * solver discretization.   In particular, when solving PDE systems, it may
+    * be necessary to discretize the gradient operator appearing in equations
+    * not treated by the solver class in the same way as those treated by this
+    * class.  These funtions allow users to do this easily.  The divergence
+    * operator used in this solver is the standard sum of centered differences
+    * involving flux terms on the cell sides computed by these routines.
+    *
+    * Note that the patch must exist on a level in an AMR hierarchy so that
+    * the discretization can be computed properly at the coarse-fine interface.
+    * Stokes coefficients C and D must exist on the patch, if they are variable.
+    * Also, calling this function does not affect the internal solver state in any
+    * way.  However, the solver must be fully initialized before it is called and care
+    * should be exercised to pass arguments so that the solver solution quantity and
+    * other internal solver quantities are not adversely affected.
+    *
+    * @param patch patch on which computation will take place
+    * @param ratio_to_coarser_level refinement ratio from coarser level to level
+    *                               on which patch lives; if current patch level
+    *                               is level zero, this is ignored
+    * @param w_data cell-centered data
+    * @param Dgradw_data side-centered flux data (i.e., D (grad w))
+    */
+   void
+   computeFluxOnPatch(
+      const hier::Patch& patch,
+      const hier::IntVector& ratio_to_coarser_level,
+      const pdat::CellData<double>& w_data,
+      pdat::SideData<double>& Dgradw_data) const;
+
+   //@{ @name FACOperatorStrategy virtuals
+
+   virtual void
+   restrictSolution(
+      const SAMRAIVectorReal<double>& source,
+      SAMRAIVectorReal<double>& dest,
+      int dest_ln);
+   virtual void
+   restrictResidual(
+      const SAMRAIVectorReal<double>& source,
+      SAMRAIVectorReal<double>& dest,
+      int dest_ln);
+
+   virtual void
+   prolongErrorAndCorrect(
+      const SAMRAIVectorReal<double>& source,
+      SAMRAIVectorReal<double>& dest,
+      int dest_ln);
+
+   virtual void
+   smoothError(
+      SAMRAIVectorReal<double>& error,
+      const SAMRAIVectorReal<double>& residual,
+      int ln,
+      int num_sweeps);
+
+   virtual int
+   solveCoarsestLevel(
+      SAMRAIVectorReal<double>& error,
+      const SAMRAIVectorReal<double>& residual,
+      int coarsest_ln);
+
+   virtual void
+   computeCompositeResidualOnLevel(
+      SAMRAIVectorReal<double>& residual,
+      const SAMRAIVectorReal<double>& solution,
+      const SAMRAIVectorReal<double>& rhs,
+      int ln,
+      bool error_equation_indicator);
+
+   virtual double
+   computeResidualNorm(
+      const SAMRAIVectorReal<double>& residual,
+      int fine_ln,
+      int coarse_ln);
+
+   virtual void
+   initializeOperatorState(
+      const SAMRAIVectorReal<double>& solution,
+      const SAMRAIVectorReal<double>& rhs);
+
+   virtual void
+   deallocateOperatorState();
+
+   virtual void
+   postprocessOneCycle(
+      int fac_cycle_num,
+      const SAMRAIVectorReal<double>& current_soln,
+      const SAMRAIVectorReal<double>& residual);
+
+   //@}
+
+private:
+   //@{
+   /*!
+    * @name Private workhorse functions.
+    */
+
+   /*!
+    * @brief Red-black Gauss-Seidel error smoothing on a level.
+    *
+    * Smoothes on the residual equation @f$ Ae=r @f$ on a level.
+    *
+    * @param error error vector
+    * @param residual residual vector
+    * @param ln level number
+    * @param num_sweeps number of sweeps
+    * @param residual_tolerance the maximum residual considered to be
+    *        converged
+    */
+   void
+   smoothErrorByRedBlack(
+      SAMRAIVectorReal<double>& error,
+      const SAMRAIVectorReal<double>& residual,
+      int ln,
+      int num_sweeps,
+      double residual_tolerance = -1.0);
+
+   /*!
+    * @brief Solve the coarsest level using HYPRE
+    */
+   int
+   solveCoarsestLevel_HYPRE(
+      SAMRAIVectorReal<double>& error,
+      const SAMRAIVectorReal<double>& residual,
+      int ln);
+
+   /*!
+    * @brief Fix flux per Ewing's coarse-fine boundary treatment.
+    *
+    * Ewing's coarse-fine boundary treatment can be implemented
+    * using a constant refinement into the fine-grid ghost boundary,
+    * naively computing the flux using the constant-refined data then
+    * fixing up the flux to correct the error.
+    *
+    * To use this function
+    * -# you must use constant refinement to fill the fine level ghost cells
+    * -# the flux must first be computed and stored
+    *
+    * @param patch patch
+    * @param soln_data cell-centered solution data
+    * @param flux_data side-centered flux data
+    * @param diffcoef_data side-centered diffusion coefficient data
+    * @param cfb coarse-fine boundary object for the level
+    *        in which patch resides
+    * @param ratio_to_coarser Refinement ratio to the next coarser level.
+    */
+   void
+   ewingFixFlux(
+      const hier::Patch& patch,
+      const pdat::CellData<double>& soln_data,
+      pdat::SideData<double>& flux_data,
+      const hier::IntVector& ratio_to_coarser) const;
+
+   /*!
+    * @brief AMR-unaware function to compute residual on a single patch,
+    * with variable scalar field.
+    *
+    * @param patch patch
+    * @param flux_data side-centered flux data
+    * @param soln_data cell-centered solution data
+    * @param rhs_data cell-centered rhs data
+    * @param residual_data cell-centered residual data
+    */
+   void
+   computeResidualOnPatch(
+      const hier::Patch& patch,
+      const pdat::SideData<double>& flux_data,
+      const pdat::CellData<double>& soln_data,
+      const pdat::CellData<double>& rhs_data,
+      pdat::CellData<double>& residual_data) const;
+
+   /*!
+    * @brief AMR-unaware function to red or black smoothing on a single patch,
+    * for variable diffusion coefficient and variable scalar field.
+    *
+    * @param patch patch
+    * @param flux_data side-centered flux data
+    * @param rhs_data cell-centered rhs data
+    * @param scalar_field_data
+    *        cell-centered scalar field data
+    * @param soln_data cell-centered solution data
+    * @param red_or_black red-black switch.  Set to 'r' or 'b'.
+    * @param p_maxres max residual output.  Set to NULL to avoid computing.
+    */
+   void
+   redOrBlackSmoothingOnPatch(
+      const hier::Patch& patch,
+      const pdat::SideData<double>& flux_data,
+      const pdat::CellData<double>& rhs_data,
+      pdat::CellData<double>& soln_data,
+      char red_or_black,
+      double* p_maxres = NULL) const;
+
+   //@}
+
+   //@{ @name For executing, caching and resetting communication schedules.
+
+   /*!
+    * @brief Execute a refinement schedule
+    * for prolonging cell data.
+    *
+    * General notes regarding internal objects for communication:
+    * We maintain objects to support caching schedules to improve
+    * efficiency.  Communication is needed in 5 distinct tasks.
+    *   -# Prolongation
+    *   -# Restriction
+    *   -# Flux coarsening.  Changing the coarse grid flux to the
+    *      composite grid flux by coarsening the fine grid flux
+    *      at the coarse-fine boundaries.
+    *   -# Fill boundary data from other patches in the same level
+    *      and physical boundary condition.
+    *   -# Fill boundary data from same level, coarser levels
+    *      and physical boundary condition.
+    *
+    * For each task, we maintain a refine or coarsen operator,
+    * and a array of communication schedules (one for each
+    * destination level).
+    *
+    * The 5 member functions named @c xeqSchedule... execute
+    * communication schedules appropriate for five specific tasks.
+    * They use a cached schedule if possible or create and cache
+    * a new schedule if needed.  These functions and the data
+    * they manipulate are as follows:
+    * <ol>
+    *   <li> xeqScheduleProlongation():
+    *        d_prolongation_refine_operator
+    *        d_prolongation_refine_schedules
+    *   <li> xeqScheduleURestriction():
+    *        d_restriction_coarsen_operator,
+    *        d_urestriction_coarsen_schedules.
+    *   <li> xeqScheduleRRestriction():
+    *        d_restriction_coarsen_operator,
+    *        d_rrestriction_coarsen_schedules.
+    *   <li> xeqScheduleFluxCoarsen():
+    *        d_flux_coarsen_operator,
+    *        d_flux_coarsen_schedules.
+    *   <li> xeqScheduleGhostFill():
+    *        d_ghostfill_refine_operator,
+    *        d_ghostfill_refine_schedules.
+    *   <li> xeqScheduleGhostFillNoCoarse():
+    *        d_ghostfill_nocoarse_refine_operator,
+    *        d_ghostfill_nocoarse_refine_schedules.
+    * </ol>
+    *
+    * @return refinement schedule for prolongation
+    */
+   void
+   xeqScheduleProlongation(
+      int dst_id,
+      int src_id,
+      int scr_id,
+      int dest_ln);
+
+   /*!
+    * @brief Execute schedule for restricting solution to the specified
+    * level or reregister an existing one.
+    *
+    * See general notes for xeqScheduleProlongation().
+    *
+    * @return coarsening schedule for restriction
+    */
+   void
+   xeqScheduleURestriction(
+      int dst_id,
+      int src_id,
+      int dest_ln);
+
+   /*!
+    * @brief Execute schedule for restricting residual to the specified
+    * level or reregister an existing one.
+    *
+    * See general notes for xeqScheduleProlongation().
+    *
+    * @return coarsening schedule for restriction
+    */
+   void
+   xeqScheduleRRestriction(
+      int dst_id,
+      int src_id,
+      int dest_ln);
+
+   /*!
+    * @brief Execute schedule for coarsening flux to the specified
+    * level or reregister an existing one.
+    *
+    * See general notes for xeqScheduleProlongation().
+    *
+    * @return coarsening schedule for setting composite grid flux at
+    * coarse-fine boundaries.
+    */
+   void
+   xeqScheduleFluxCoarsen(
+      int dst_id,
+      int src_id,
+      int dest_ln);
+
+   /*!
+    * @brief Execute schedule for filling ghosts on the specified
+    * level or reregister an existing one.
+    *
+    * See general notes for xeqScheduleProlongation().
+    *
+    * @return refine schedule for filling ghost data from coarser level
+    * and physical bc.
+    */
+   void
+   xeqScheduleGhostFill(
+      int dst_id,
+      int dest_ln);
+
+   /*!
+    * @brief Execute schedule for filling ghosts on the specified
+    * level or reregister an existing one.
+    * This version does not get data from coarser levels.
+    *
+    * See general notes for xeqScheduleProlongation().
+    *
+    * This function is used for the bottom solve level, since it does
+    * not access data from any coarser level.  (Ghost data obtained
+    * from coarser level must have been placed there before solve begins!)
+    *
+    * @return refine schedule for filling ghost data from same level
+    * and physical bc.
+    */
+   void
+   xeqScheduleGhostFillNoCoarse(
+      int dst_id,
+      int dest_ln);
+
+   //@}
+
+   //! @brief Return the patch data index for cell scratch data.
+   int
+   registerCellScratch() const;
+   //! @brief Return the patch data index for flux scratch data.
+   int
+   registerFluxScratch() const;
+   //! @brief Return the patch data index for outerflux scratch data.
+   int
+   registerOfluxScratch() const;
+
+   //! @brief Free static variables at shutdown time.
+   static void
+   finalizeCallback();
+
+   /*!
+    * @brief Object dimension.
+    */
+   const tbox::Dimension d_dim;
+
+   /*!
+    * @brief Object name.
+    */
+   std::string d_object_name;
+
+   //@{ @name Hierarchy-dependent objects.
+
+   /*!
+    * @brief Reference hierarchy
+    *
+    * This variable is non-null between the initializeOperatorState()
+    * and deallocateOperatorState() calls.  It is not truly needed,
+    * because the hierarchy is obtainable through variables in most
+    * function argument lists.  We use it to enforce working on one
+    * hierarchy at a time.
+    */
+   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
+
+   /*!
+    * @brief Coarsest level for solve.
+    */
+   int d_ln_min;
+
+   /*!
+    * @brief Finest level for solve.
+    */
+   int d_ln_max;
+
+   /*!
+    * @brief Description of coarse-fine boundaries.
+    *
+    * There is one coarse-fine boundary object for each level.
+    * d_coarse_fine_boundary[i] is the description of
+    * the coarse-fine boundary between level i and level i-1.
+    * The coarse-fine boundary does not exist at the coarsest level,
+    * although the hier::CoarseFineBoundary object still exists (it
+    * should not contain any boxes).
+    *
+    * This array is initialized in initializeOperatorState() and
+    * deallocated in deallocateOperatorState().  When allocated,
+    * it is allocated for the index range [0,d_ln_max], though
+    * the range [0,d_ln_min-1] is not used.  This is okay because
+    * hier::CoarseFineBoundary is a light object before
+    * it is set for a level.
+    */
+   tbox::Array<tbox::Pointer<hier::CoarseFineBoundary> > d_cf_boundary;
+
+   //@}
+
+   //@{
+   /*!
+    * @name Private state variables for solution process.
+    */
+
+   /*!
+    * @brief Scalar Stokes equations specifications.
+    * @see setStokesSpecifications().
+    */
+   StokesSpecifications d_stokes_spec;
+
+   /*!
+    * @brief Smoothing choice.
+    * @see setSmoothingChoice.
+    */
+   std::string d_smoothing_choice;
+
+   /*!
+    * @brief Coarse level solver.
+    * @see setCoarsestLevelSolverChoice
+    */
+   std::string d_coarse_solver_choice;
+
+   /*!
+    * @brief Coarse-fine discretization method.
+    * @see setCoarseFineDiscretization().
+    */
+   std::string d_cf_discretization;
+
+   /*!
+    * @brief Coarse-fine discretization method.
+    *
+    * The name of the refinement operator used to prolong the
+    * coarse grid correction.
+    *
+    * @see setProlongationMethod()
+    */
+   std::string d_prolongation_method;
+
+   /*!
+    * @brief Tolerance specified to coarse solver
+    * @see setCoarsestLevelSolverTolerance()
+    */
+   double d_coarse_solver_tolerance;
+
+   /*!
+    * @brief Coarse level solver iteration limit.
+    * @see setCoarsestLevelSolverMaxIterations()
+    */
+   int d_coarse_solver_max_iterations;
+
+   /*!
+    * @brief Residual tolerance to govern smoothing.
+    *
+    * When we use one of the internal error smoothing functions
+    * and want to terminate the smoothing sweeps at a certain
+    * level of residual, this will be set to > 0.  If it is
+    * < 0, the smoothing function effectively ignores it.
+    *
+    * This variable is needed because some coarse-level solver
+    * simply runs the smoothing function until convergence.
+    * It sets this variable to > 0, calls the smoothing function,
+    * then resets it to < 0.
+    */
+   double d_residual_tolerance_during_smoothing;
+
+   /*!
+    * @brief Id of the flux.
+    *
+    * If set to -1, create and delete storage space on the fly.
+    * Else, user has provided space for flux.
+    *
+    * @see setFluxId
+    */
+   int d_flux_id;
+
+#ifdef HAVE_HYPRE
+   /*!
+    * @brief HYPRE coarse-level solver object.
+    */
+   CellStokesHypreSolver d_hypre_solver;
+#endif
+
+   /*!
+    * @brief Externally provided physical boundary condition object.
+    *
+    * see setPhysicalBcCoefObject()
+    */
+   const RobinBcCoefStrategy* d_physical_bc_coef;
+
+   //@}
+
+   //@{ @name Internal context and scratch data
+
+   static tbox::Pointer<pdat::CellVariable<double> >
+   s_cell_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+   static tbox::Pointer<pdat::SideVariable<double> >
+   s_flux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+   static tbox::Pointer<pdat::OutersideVariable<double> >
+   s_oflux_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+   /*!
+    * @brief Default context of internally maintained hierarchy data.
+    */
+   tbox::Pointer<hier::VariableContext> d_context;
+
+   /*!
+    * @brief ID of the solution-like scratch data.
+    *
+    * Set in constructor and never changed.
+    * Corresponds to a pdat::CellVariable<double> named
+    * @c d_object_name+"::cell_scratch".
+    * Scratch data is allocated and removed as needed
+    * to reduce memory usage.
+    */
+   int d_cell_scratch_id;
+
+   /*!
+    * @brief ID of the side-centered scratch data.
+    *
+    * Set in constructor and never changed.
+    * Corresponds to a pdat::SideVariable<double> named
+    * @c d_object_name+"::flux_scratch".
+    *
+    * This data is allocated only as needed and deallocated
+    * immediately after use.
+    */
+   int d_flux_scratch_id;
+
+   /*!
+    * @brief ID of the outerside-centered scratch data.
+    *
+    * Set in constructor and never changed.
+    * Corresponds to a pdat::OutersideVariable<double> named
+    * @c d_object_name+"::oflux_scratch".
+    */
+   int d_oflux_scratch_id;
+
+   //@}
+
+   //@{
+   /*!
+    * @name Various refine and coarsen objects used internally.
+    */
+
+   //! @brief Error prolongation (refinement) operator.
+   tbox::Pointer<xfer::RefineOperator> d_prolongation_refine_operator;
+   tbox::Pointer<xfer::RefineAlgorithm> d_prolongation_refine_algorithm;
+   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+   d_prolongation_refine_schedules;
+
+   //! @brief Solution restriction (coarsening) operator.
+   tbox::Pointer<xfer::CoarsenOperator> d_urestriction_coarsen_operator;
+   tbox::Pointer<xfer::CoarsenAlgorithm> d_urestriction_coarsen_algorithm;
+   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+   d_urestriction_coarsen_schedules;
+
+   //! @brief Residual restriction (coarsening) operator.
+   tbox::Pointer<xfer::CoarsenOperator> d_rrestriction_coarsen_operator;
+   tbox::Pointer<xfer::CoarsenAlgorithm> d_rrestriction_coarsen_algorithm;
+   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+   d_rrestriction_coarsen_schedules;
+
+   //! @brief Coarsen operator for outerflux-to-flux
+   tbox::Pointer<xfer::CoarsenOperator> d_flux_coarsen_operator;
+   tbox::Pointer<xfer::CoarsenAlgorithm> d_flux_coarsen_algorithm;
+   tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+   d_flux_coarsen_schedules;
+
+   //! @brief Refine operator for cell-like data from coarser level.
+   tbox::Pointer<xfer::RefineOperator> d_ghostfill_refine_operator;
+   tbox::Pointer<xfer::RefineAlgorithm> d_ghostfill_refine_algorithm;
+   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+   d_ghostfill_refine_schedules;
+
+   //! @brief Refine operator for cell-like data from same level.
+   tbox::Pointer<xfer::RefineOperator> d_ghostfill_nocoarse_refine_operator;
+   tbox::Pointer<xfer::RefineAlgorithm> d_ghostfill_nocoarse_refine_algorithm;
+   tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+   d_ghostfill_nocoarse_refine_schedules;
+
+   //@}
+
+   /*!
+    * @brief Utility object employed in setting ghost cells and providing
+    * xfer::RefinePatchStrategy implementation.
+    *
+    * Since this class deals only in scalar variables having
+    * Robin boundary conditions, we take advantage of the corresponding
+    * implementation in CartesianRobinBcHelper.  Whenever
+    * we need an implementation of xfer::RefinePatchStrategy,
+    * this object is used.  Note that in the code, before we
+    * use this object to set ghost cell values, directly or
+    * indirectly by calling xfer::RefineSchedule::fillData(),
+    * we must tell d_bc_helper the patch data index we want
+    * to set and whether we are setting data with homogeneous
+    * boundary condition.
+    */
+   CartesianRobinBcHelper d_bc_helper;
+
+   //@{
+   /*!
+    * @name Non-essential objects used in outputs and debugging.
+    */
+
+   /*!
+    * @brief Logging flag.
+    */
+   bool d_enable_logging;
+
+   /*!
+    * @brief Preconditioner using this object.
+    *
+    * See setPreconditioner().
+    */
+   const FACPreconditioner* d_preconditioner;
+
+   /*!
+    * @brief Hierarchy cell operator used in debugging.
+    */
+   tbox::Pointer<math::HierarchyCellDataOpsReal<double> > d_hopscell;
+
+   /*!
+    * @brief Hierarchy side operator used in debugging.
+    */
+   tbox::Pointer<math::HierarchySideDataOpsReal<double> > d_hopsside;
+
+   /*!
+    * @brief Timers for performance measurement.
+    */
+   tbox::Pointer<tbox::Timer> t_restrict_solution;
+   tbox::Pointer<tbox::Timer> t_restrict_residual;
+   tbox::Pointer<tbox::Timer> t_prolong;
+   tbox::Pointer<tbox::Timer> t_smooth_error;
+   tbox::Pointer<tbox::Timer> t_solve_coarsest;
+   tbox::Pointer<tbox::Timer> t_compute_composite_residual;
+   tbox::Pointer<tbox::Timer> t_compute_residual_norm;
+
+   static tbox::StartupShutdownManager::Handler
+   s_finalize_handler;
+};
+
+}
+}
+
+#ifdef SAMRAI_INLINE
+#include "CellStokesFACOps.I"
+#endif
+
+#endif // included_solv_CellStokesFACOps
diff -r a44a82f15794 -r fe2a9230921b StokesFACSolver.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACSolver.C	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,585 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   High-level solver (wrapper) for scalar stokes equation. 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesFACSolver_C
+#define included_solv_StokesFACSolver_C
+
+#include "SAMRAI/pdat/CellVariable.h"
+#include "StokesFACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+#ifndef SAMRAI_INLINE
+#include "StokesFACSolver.I"
+#endif
+
+namespace SAMRAI {
+namespace solv {
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Initialize the static data members.                                   *
+ *                                                                       *
+ *************************************************************************
+ */
+
+bool CellStokesFACSolver::s_initialized = 0;
+int CellStokesFACSolver::s_weight_id[SAMRAI::tbox::Dimension::
+                                      MAXIMUM_DIMENSION_VALUE];
+int CellStokesFACSolver::s_instance_counter[SAMRAI::tbox::Dimension::
+                                             MAXIMUM_DIMENSION_VALUE];
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Constructor sets uninitialized solver state.                          *
+ * Set default iteration and convergence parameters.                     *
+ *                                                                       *
+ * By default settings:                                                  *
+ *   - Stokes equation specified has D=1, C=0.                          *
+ *   - State is uninitialized                                            *
+ *   - Logging is disabled                                               *
+ *   - Context for internal data is set based on object name.            *
+ *                                                                       *
+ *************************************************************************
+ */
+
+CellStokesFACSolver::CellStokesFACSolver(
+   const tbox::Dimension& dim,
+   const std::string& object_name,
+   tbox::Pointer<tbox::Database> database):
+   d_dim(dim),
+   d_object_name(object_name),
+   d_stokes_spec(object_name + "::stokes_spec"),
+   d_fac_ops(d_dim, object_name + "::fac_ops"),
+   d_fac_precond(object_name + "::fac_precond", d_fac_ops),
+   d_bc_object(NULL),
+   d_simple_bc(d_dim, object_name + "::bc"),
+   d_hierarchy(NULL),
+   d_ln_min(-1),
+   d_ln_max(-1),
+   d_context(hier::VariableDatabase::getDatabase()
+             ->getContext(object_name + "::CONTEXT")),
+   d_uv(NULL),
+   d_fv(NULL),
+   d_solver_is_initialized(false),
+   d_enable_logging(false)
+{
+
+   if (!s_initialized) {
+      initializeStatics();
+   }
+
+   setMaxCycles(10);
+   setResidualTolerance(1e-6);
+   setPresmoothingSweeps(1);
+   setPostsmoothingSweeps(1);
+   setCoarseFineDiscretization("Ewing");
+#ifdef HAVE_HYPRE
+   setCoarsestLevelSolverChoice("hypre");
+   setCoarsestLevelSolverTolerance(1e-10);
+   setCoarsestLevelSolverMaxIterations(20);
+   setUseSMG(true);
+#else
+   setCoarsestLevelSolverChoice("redblack");
+   setCoarsestLevelSolverTolerance(1e-8);
+   setCoarsestLevelSolverMaxIterations(500);
+#endif
+
+   /*
+    * Construct integer tag variables and add to variable database.  Note that
+    * variables and patch data indices are shared among all instances.
+    * The VariableDatabase holds the variables, once contructed and
+    * registered via the VariableDatabase::registerInternalSAMRAIVariable()
+    * function call.  Note that variables are registered and patch data indices
+    * are made only for the first time through the constructor.
+    */
+   hier::VariableDatabase* var_db = hier::VariableDatabase::getDatabase();
+
+   static std::string weight_variable_name("CellStokesFACSolver_weight");
+
+   tbox::Pointer<pdat::CellVariable<double> > weight = var_db->getVariable(
+         weight_variable_name);
+   if (weight.isNull()) {
+      weight = new pdat::CellVariable<double>(d_dim, weight_variable_name, 1);
+   }
+
+   if (s_weight_id[d_dim.getValue() - 1] < 0) {
+      s_weight_id[d_dim.getValue() - 1] = var_db->registerInternalSAMRAIVariable(
+            weight,
+            hier::IntVector::getZero(d_dim));
+   }
+
+   /*
+    * The default RobinBcCoefStrategy used,
+    * SimpleCellRobinBcCoefs only works with constant refine
+    * for prolongation.  So we use constant refinement
+    * for prolongation by default.
+    */
+   setProlongationMethod("CONSTANT_REFINE");
+
+   /*
+    * The FAC operator optionally uses the preconditioner
+    * to get data for logging.
+    */
+   d_fac_ops.setPreconditioner((const FACPreconditioner *)(&d_fac_precond));
+
+   if (database) {
+      getFromInput(database);
+   }
+
+   s_instance_counter[d_dim.getValue() - 1]++;
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Destructor for CellStokesFACSolver.                            *
+ * Deallocate internal data.                                             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+CellStokesFACSolver::~CellStokesFACSolver()
+{
+   s_instance_counter[d_dim.getValue() - 1]--;
+
+   deallocateSolverState();
+
+   if (s_instance_counter[d_dim.getValue() - 1] == 0) {
+      hier::VariableDatabase::getDatabase()->
+      removeInternalSAMRAIVariablePatchDataIndex(s_weight_id[d_dim.getValue() - 1]);
+      s_weight_id[d_dim.getValue() - 1] = -1;
+   }
+}
+
+/*
+ ********************************************************************
+ * Set state from database                                          *
+ *                                                                  *
+ * Do not allow FAC preconditioner and Stokes FAC operators to be  *
+ * set from database, as that may cause them to be inconsistent     *
+ * with this object if user does not coordinate the inputs          *
+ * correctly.  This is also why we don't allow direct access to     *
+ * those objects.  The responsibility for maintaining consistency   *
+ * lies in the public functions to set parameters, so use them      *
+ * instead of setting the parameters directly in this function.     *
+ ********************************************************************
+ */
+
+void CellStokesFACSolver::getFromInput(
+   tbox::Pointer<tbox::Database> database)
+{
+   if (database) {
+      if (database->isBool("enable_logging")) {
+         bool logging = database->getBool("enable_logging");
+         enableLogging(logging);
+      }
+      if (database->isInteger("max_cycles")) {
+         int max_cycles = database->getInteger("max_cycles");
+         setMaxCycles(max_cycles);
+      }
+      if (database->isDouble("residual_tol")) {
+         double residual_tol = database->getDouble("residual_tol");
+         setResidualTolerance(residual_tol);
+      }
+      if (database->isInteger("num_pre_sweeps")) {
+         int num_pre_sweeps = database->getInteger("num_pre_sweeps");
+         setPresmoothingSweeps(num_pre_sweeps);
+      }
+      if (database->isInteger("num_post_sweeps")) {
+         int num_post_sweeps = database->getInteger("num_post_sweeps");
+         setPostsmoothingSweeps(num_post_sweeps);
+      }
+      if (database->isString("coarse_fine_discretization")) {
+         std::string s = database->getString("coarse_fine_discretization");
+         setCoarseFineDiscretization(s);
+      }
+      if (database->isString("prolongation_method")) {
+         std::string s = database->getString("prolongation_method");
+         setProlongationMethod(s);
+      }
+      if (database->isString("coarse_solver_choice")) {
+         std::string s = database->getString("coarse_solver_choice");
+         setCoarsestLevelSolverChoice(s);
+      }
+      if (database->isDouble("coarse_solver_tolerance")) {
+         double tol = database->getDouble("coarse_solver_tolerance");
+         setCoarsestLevelSolverTolerance(tol);
+      }
+      if (database->isInteger("coarse_solver_max_iterations")) {
+         int itr = database->getInteger("coarse_solver_max_iterations");
+         setCoarsestLevelSolverMaxIterations(itr);
+      }
+#ifdef HAVE_HYPRE
+      if (database->isBool("use_smg")) {
+         bool smg = database->getBool("use_smg");
+         setUseSMG(smg);
+      }
+#endif
+   }
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Prepare internal data for solve.                                      *
+ * Allocate scratch data.  Create vectors for u and f                    *
+ * required by the FACPreconditioner interface.                    *
+ * Set up internal boundary condition object.                            *
+ * Share data to coordinate with FAC preconditioner and                  *
+ * Stokes FAC operator.                                                 *
+ *                                                                       *
+ *************************************************************************
+ */
+
+void CellStokesFACSolver::initializeSolverState(
+   const int solution,
+   const int rhs,
+   tbox::Pointer<hier::PatchHierarchy> hierarchy,
+   const int coarse_level,
+   const int fine_level)
+{
+   TBOX_ASSERT(!hierarchy.isNull());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
+
+   if (d_bc_object == NULL) {
+      TBOX_ERROR(
+         d_object_name << ": No BC coefficient strategy object!\n"
+         <<
+         "Use either setBoundaries or setPhysicalBcCoefObject\n"
+         << "to specify the boundary conidition.\n");
+   }
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (solution < 0 || rhs < 0) {
+      TBOX_ERROR(d_object_name << ": Bad patch data id.\n");
+   }
+#endif
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (!hierarchy) {
+      TBOX_ERROR(d_object_name << ": NULL hierarchy pointer not allowed\n"
+                               << "in inititialization.");
+   }
+#endif
+   d_hierarchy = hierarchy;
+
+   d_ln_min = coarse_level;
+   d_ln_max = fine_level;
+   if (d_ln_min == -1) {
+      d_ln_min = 0;
+   }
+   if (d_ln_max == -1) {
+      d_ln_max = d_hierarchy->getFinestLevelNumber();
+   }
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_ln_min < 0 || d_ln_max < 0 || d_ln_min > d_ln_max) {
+      TBOX_ERROR(d_object_name << ": Bad range of levels in\n"
+                               << "inititialization.\n");
+   }
+#endif
+
+   int ln;
+   for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
+      d_hierarchy->getPatchLevel(ln)->allocatePatchData(s_weight_id[d_dim.getValue() - 1]);
+   }
+
+   d_fac_ops.computeVectorWeights(d_hierarchy,
+      s_weight_id[d_dim.getValue() - 1],
+      d_ln_min,
+      d_ln_max);
+
+   if (d_bc_object == &d_simple_bc) {
+      d_simple_bc.setHierarchy(d_hierarchy,
+         d_ln_min,
+         d_ln_max);
+      if (d_stokes_spec.dIsConstant()) {
+         d_simple_bc.setDiffusionCoefConstant(d_stokes_spec.getDConstant());
+      } else {
+         d_simple_bc.setDiffusionCoefId(d_stokes_spec.getDPatchDataId());
+      }
+   }
+
+   d_fac_ops.setStokesSpecifications(d_stokes_spec);
+
+   createVectorWrappers(solution, rhs);
+
+   d_fac_precond.initializeSolverState(*d_uv, *d_fv);
+
+   d_solver_is_initialized = true;
+}
+
+void CellStokesFACSolver::deallocateSolverState()
+{
+   if (d_hierarchy) {
+
+      d_fac_precond.deallocateSolverState();
+
+      /*
+       * Delete internally managed data.
+       */
+      int ln;
+      for (ln = d_ln_min; ln <= d_ln_max; ++ln) {
+         d_hierarchy->getPatchLevel(ln)->deallocatePatchData(s_weight_id[d_dim.getValue()
+                                                                         - 1]);
+      }
+
+      d_hierarchy.setNull();
+      d_ln_min = -1;
+      d_ln_max = -1;
+      d_solver_is_initialized = false;
+
+      destroyVectorWrappers();
+
+   }
+}
+
+/*
+ *************************************************************************
+ * Enable logging and propagate logging flag to major components.        *
+ *************************************************************************
+ */
+
+void CellStokesFACSolver::enableLogging(
+   bool logging)
+{
+   d_enable_logging = logging;
+   d_fac_precond.enableLogging(d_enable_logging);
+   d_fac_ops.enableLogging(d_enable_logging);
+}
+
+void CellStokesFACSolver::setBoundaries(
+   const std::string& boundary_type,
+   const int fluxes,
+   const int flags,
+   int* bdry_types)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_bc_object != NULL && d_bc_object != &d_simple_bc) {
+      TBOX_ERROR(
+         d_object_name << ": Bad attempt to set boundary condition\n"
+         <<
+         "by using default bc object after it has been overriden.\n");
+   }
+#endif
+   d_simple_bc.setBoundaries(boundary_type,
+      fluxes,
+      flags,
+      bdry_types);
+   d_bc_object = &d_simple_bc;
+   d_fac_ops.setPhysicalBcCoefObject(d_bc_object);
+}
+
+void CellStokesFACSolver::setBcObject(
+   const RobinBcCoefStrategy* bc_object)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (!bc_object) {
+      TBOX_ERROR(d_object_name << ": NULL pointer for boundary condition\n"
+                               << "object.\n");
+   }
+#endif
+   d_bc_object = bc_object;
+   d_fac_ops.setPhysicalBcCoefObject(d_bc_object);
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Solve the linear system and report whether iteration converged.       *
+ *                                                                       *
+ * This version is for an initialized solver state.                      *
+ * Before solving, set the final piece of the boundary condition,        *
+ * which is not known until now, and initialize some internal            *
+ * solver quantities.                                                    *
+ *                                                                       *
+ *************************************************************************
+ */
+
+bool CellStokesFACSolver::solveSystem(
+   const int u,
+   const int f)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (!d_solver_is_initialized) {
+      TBOX_ERROR(
+         d_object_name << ".solveSystem(int,int): uninitialized\n"
+         <<
+         "solver state.  You must call initializeSolverState()\n"
+         <<
+         "before using this function.  Or you can use\n"
+         <<
+         "solveSystem(int,int,...) to initialize the solver,\n"
+         << "solve and deallocate the solver.\n");
+   }
+   if (u < 0 || f < 0) {
+      TBOX_ERROR(d_object_name << ": Bad patch data id.\n");
+   }
+#endif
+   if (d_bc_object == &d_simple_bc) {
+      /*
+       * Knowing that we are using the SimpelCellRobinBcCoefsX
+       * implementation of RobinBcCoefStrategy, we must save
+       * the ghost data in u before solving.
+       * The solver overwrites it, but SimpleCellRobinBcCoefs
+       * needs to get to access it repeatedly.
+       */
+      d_simple_bc.cacheDirichletData(u);
+   }
+
+   createVectorWrappers(u, f);
+   bool solver_rval;
+   solver_rval = d_fac_precond.solveSystem(*d_uv, *d_fv);
+
+   if (d_bc_object == &d_simple_bc) {
+      /*
+       * Restore the Dirichlet cell data that were overwritten by the
+       * solve process.  We do this to be backward compatible with the
+       * user code.
+       */
+      d_simple_bc.restoreDirichletData(u);
+   }
+
+   return solver_rval;
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Solve the linear system and report whether iteration converged.       *
+ *                                                                       *
+ * This version is for an uninitialized solver state.                    *
+ * 1. Initialize the (currently uninitialized) solver state.             *
+ * 2. Solve.                                                             *
+ * 3. Deallocate the solver state.                                       *
+ *                                                                       *
+ *************************************************************************
+ */
+
+bool CellStokesFACSolver::solveSystem(
+   const int u,
+   const int f,
+   tbox::Pointer<hier::PatchHierarchy> hierarchy,
+   int coarse_ln,
+   int fine_ln)
+{
+   TBOX_ASSERT(!hierarchy.isNull());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
+
+   if (d_enable_logging) {
+      tbox::plog << "CellStokesFACSolver::solveSystem (" << d_object_name
+                 << ")\n";
+      d_stokes_spec.printClassData(tbox::plog);
+   }
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_solver_is_initialized) {
+      TBOX_ERROR(
+         d_object_name << ".solveSystem(int,int,...): initialized\n"
+         <<
+         "solver state.  This function can only used when the\n"
+         <<
+         "solver state is uninitialized.  You should deallocate\n"
+         <<
+         "the solver state or use solveSystem(int,int).\n");
+   }
+   if (!hierarchy) {
+      TBOX_ERROR(d_object_name << ".solveSystem(): Null hierarchy\n"
+                               << "specified.\n");
+   }
+#endif
+   initializeSolverState(u, f, hierarchy, coarse_ln, fine_ln);
+
+   bool solver_rval;
+   solver_rval = solveSystem(u, f);
+
+   deallocateSolverState();
+
+   return solver_rval;
+}
+
+void CellStokesFACSolver::createVectorWrappers(
+   int u,
+   int f) {
+
+   hier::VariableDatabase& vdb(*hier::VariableDatabase::getDatabase());
+   tbox::Pointer<hier::Variable> variable;
+
+   if (!d_uv || d_uv->getComponentDescriptorIndex(0) != u) {
+      d_uv.setNull();
+      d_uv = new SAMRAIVectorReal<double>(d_object_name + "::uv",
+                                          d_hierarchy,
+                                          d_ln_min,
+                                          d_ln_max);
+      vdb.mapIndexToVariable(u, variable);
+#ifdef DEBUG_CHECK_ASSERTIONS
+      if (!variable) {
+         TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                                  << u << "\n");
+      }
+      tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
+      if (!cell_variable) {
+         TBOX_ERROR(d_object_name << ": hier::Patch data index " << u
+                                  << " is not a cell-double variable.\n");
+      }
+#endif
+      d_uv->addComponent(variable, u, s_weight_id[d_dim.getValue() - 1]);
+   }
+
+   if (!d_fv || d_fv->getComponentDescriptorIndex(0) != f) {
+      d_fv.setNull();
+      d_fv = new SAMRAIVectorReal<double>(d_object_name + "::fv",
+                                          d_hierarchy,
+                                          d_ln_min,
+                                          d_ln_max);
+      vdb.mapIndexToVariable(f, variable);
+#ifdef DEBUG_CHECK_ASSERTIONS
+      if (!variable) {
+         TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                                  << f << "\n");
+      }
+      tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
+      if (!cell_variable) {
+         TBOX_ERROR(d_object_name << ": hier::Patch data index " << f
+                                  << " is not a cell-double variable.\n");
+      }
+#endif
+      d_fv->addComponent(variable, f, s_weight_id[d_dim.getValue() - 1]);
+   }
+}
+
+/*
+ ***********************************************************************
+ * Delete the vector wrappers.  Do not freeVectorComponents because    *
+ * we do not control their data allocation.  The user does that.       *
+ ***********************************************************************
+ */
+void CellStokesFACSolver::destroyVectorWrappers() {
+   d_uv.setNull();
+   d_fv.setNull();
+}
+
+void CellStokesFACSolver::initializeStatics() {
+
+   for (int d = 0; d < SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
+      s_weight_id[d] = -1;
+      s_instance_counter[d] = -1;
+   }
+
+   s_initialized = 1;
+}
+
+}
+}
+#endif
diff -r a44a82f15794 -r fe2a9230921b StokesFACSolver.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACSolver.I	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   High-level solver (wrapper) for scalar stokes equation. 
+ *
+ ************************************************************************/
+namespace SAMRAI {
+namespace solv {
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setDPatchDataId(
+   int id) {
+   d_stokes_spec.setDPatchDataId(id);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setDConstant(
+   double scalar) {
+   d_stokes_spec.setDConstant(scalar);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCPatchDataId(
+   int id) {
+   d_stokes_spec.setCPatchDataId(id);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCConstant(
+   double scalar) {
+// Disable Intel warning on real comparison
+#ifdef __INTEL_COMPILER
+#pragma warning (disable:1572)
+#endif
+   if (scalar == 0.0) {
+      d_stokes_spec.setCZero();
+   } else {
+      d_stokes_spec.setCConstant(scalar);
+   }
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setProlongationMethod(
+   const std::string& prolongation_method)
+{
+   d_fac_ops.setProlongationMethod(prolongation_method);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCoarsestLevelSolverChoice(
+   const std::string& choice)
+{
+   d_fac_ops.setCoarsestLevelSolverChoice(choice);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCoarsestLevelSolverTolerance(
+   double tol)
+{
+   d_fac_ops.setCoarsestLevelSolverTolerance(tol);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCoarsestLevelSolverMaxIterations(
+   int max_iterations)
+{
+   d_fac_ops.setCoarsestLevelSolverMaxIterations(max_iterations);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setCoarseFineDiscretization(
+   const std::string& coarsefine_method)
+{
+   d_fac_ops.setCoarseFineDiscretization(coarsefine_method);
+}
+
+#ifdef HAVE_HYPRE
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setUseSMG(
+   bool use_smg)
+{
+   if (d_solver_is_initialized) {
+      TBOX_ERROR(
+         d_object_name << ": setUseSMG(bool) may NOT be called\n"
+         <<
+         "while the solver state is initialized, as that\n"
+         << "would lead to a corrupted solver state.\n");
+   }
+   d_fac_ops.setUseSMG(use_smg);
+}
+#endif
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setPresmoothingSweeps(
+   int num_pre_sweeps) {
+   d_fac_precond.setPresmoothingSweeps(num_pre_sweeps);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setPostsmoothingSweeps(
+   int num_post_sweeps) {
+   d_fac_precond.setPostsmoothingSweeps(num_post_sweeps);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setMaxCycles(
+   int max_cycles) {
+   d_fac_precond.setMaxCycles(max_cycles);
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::setResidualTolerance(
+   double residual_tol) {
+   d_fac_precond.setResidualTolerance(residual_tol);
+}
+
+SAMRAI_INLINE_KEYWORD
+int CellStokesFACSolver::getNumberOfIterations() const
+{
+   return d_fac_precond.getNumberOfIterations();
+}
+
+SAMRAI_INLINE_KEYWORD
+double CellStokesFACSolver::getResidualNorm() const
+{
+   return d_fac_precond.getResidualNorm();
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesFACSolver::getConvergenceFactors(
+   double& avg_factor,
+   double& final_factor)
+const
+{
+   d_fac_precond.getConvergenceFactors(avg_factor, final_factor);
+}
+
+}
+}
diff -r a44a82f15794 -r fe2a9230921b StokesFACSolver.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesFACSolver.h	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,660 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   High-level solver (wrapper) for scalar stokes equation. 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesFACSolver
+#define included_solv_StokesFACSolver
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/solv/FACPreconditioner.h"
+#include "StokesFACOps.h"
+#include "StokesSpecifications.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/tbox/Database.h"
+#include "SAMRAI/tbox/Pointer.h"
+
+namespace SAMRAI {
+namespace solv {
+
+/*!
+ * @brief Class for solving scalar Stokes's equation on SAMR grid,
+ * wrapping up lower-level components (FAC cycling, Stokes equation
+ * operations and boundary conditions) in a single high-level interface.
+ *
+ * Note: this class provides a backward-compatible interface to
+ * the soon-to-be obsolete StokesHierarchySolver<DIM> class.
+ * Although this class hides the lower-level components (FAC cycling,
+ * Stokes equation operations and boundary conditions), it is
+ * perfectly acceptable to use those lower-level components directly.
+ *
+ * We solve the equation
+ *    div(D grad(u)) + Cu = f
+ * where D is a side-centered array and C is a cell-centered array.
+ * u and f are also cell-centered.
+ * Boundary conditions supported are Dirichlet, Neumann and mixed
+ * (Dirichlet on some faces and Neumann on others).
+ *
+ * This class is a wrapper, providing a single class that coordinates
+ * three major components: the FAC solver, the cell-centered Stokes
+ * FAC operator and a default Robin bc coefficient implelemtation.
+ * It is perfectly acceptable to use those classes outside of this
+ * class.
+ *
+ * The underlying solver is an FAC solver using cell-centered
+ * discretization.  The difference scheme is second-order
+ * central-difference.  On coarse-fine boundaries within the
+ * solution levels, the composite grid operator uses, by default,
+ * the discretization method of Ewing, Lazarov and Vassilevski
+ * ("Local Refinement Techniques for Elliptic Problems on
+ * Cell-Centered Grids, I. Error Analysis", Mathematics of
+ * Computation, Vol. 56, No. 194, April 1991, pp. 437-461).
+ *
+ * Typical use of this class is:
+ * -# Construct a CellStokesFACSolver object, providing it
+ *    the hierarchy and range of levels participating in the solve.
+ * -# Set the parameters C and D using the functions named @c setC...
+ *    and @c setD...  By default, D=1 and C=0 everywhere.
+ * -# Call setBoundaries() to state the types boundary conditions,
+ *    along with supplemental data for setting those boundary
+ *    conditions.
+ * -# Call initializeSolverState() to set up information
+ *    internal to the solver.  This is step is not required
+ *    but will save setup costs if you are making multiple
+ *    solves.  This commits the object to the current hierarchy state
+ *    and the specific @em types of boundary conditions you selected,
+ *    It does NOT commit to the specific @em values of the boundary
+ *    condition.  A hierarchy change (through adaption or other means)
+ *    invalidates the state, thus you must reinitialize or
+ *    deallocateSolverState() the state before another solve.
+ * -# Solve the equation with solveSystem().  You provide the
+ *    patch data indices for the solution u and the right hand
+ *    side f.  u must have at least one ghost cell and where
+ *    a Dirichlet boundary condition applies, those cells
+ *    must be set to the value on the boundary.  If only Neumann
+ *    boundary conditions are used, the ghost cell values
+ *    do not matter.
+ * -# Call deallocateSolverState() to free up internal resources,
+ *    if initializeSolverState() was called before the solve.
+ *
+ * After the solve, information on the solve can be obtained
+ * by calling one of these functions:
+ * - getNumberOfIterations() gives the number of FAC cycles used.
+ * - getConvergenceFactors() gives the average and final convergence
+ *   factors for the solve.
+ * - getResidualNorm() gives the final residual
+ *
+ * Finer solver controls can be set using the functions in this class.
+ *
+ * Object of this class can be set using input databases.
+ * The following parameters can be set.  Each is shown with its
+ * default value in the case where hypre is used.
+ * @verbatim
+ * enable_logging = TRUE // Bool flag to switch logging on/off
+ * max_cycles = 10       // Integer number of max FAC cycles to use
+ * residual_tol = 1.e-6  // Residual tolerance to solve for
+ * num_pre_sweeps = 1    // Number of presmoothing sweeps to use
+ * num_post_sweeps = 1   // Number of postsmoothing sweeps to use
+ * coarse_fine_discretization = "Ewing" // Name of coarse-fine discretization
+ * prolongation_method = "CONSTANT_REFINE" // Name of prolongation method
+ * coarse_solver_choice = "hypre"  // Name of coarse level solver
+ * coarse_solver_tolerance = 1e-10 // Coarse level tolerance
+ * coarse_solver_max_iterations = 20 // Coarse level max iterations
+ * use_smg = "FALSE"     // Whether to use hypre's smg solver
+ *                       // (alternative is the pfmg solver)
+ * @endverbatim
+ *
+ */
+class CellStokesFACSolver
+{
+
+public:
+   /*!
+    * @brief Construct a solver.
+    *
+    * If the database is not NULL, initial settings will be set
+    * using the database.
+    * The solver is uninitialized until initializeSolverState()
+    * is called.
+    *
+    * @param object_name Name of object used in outputs
+    * @param database tbox::Database for initialization (may be NULL)
+    */
+   CellStokesFACSolver(
+      const tbox::Dimension& dim,
+      const std::string& object_name,
+      tbox::Pointer<tbox::Database> database =
+         tbox::Pointer<tbox::Database>());
+
+   /*!
+    * @brief Destructor.
+    */
+   ~CellStokesFACSolver(
+      void);
+
+   /*!
+    * @brief Enable logging.
+    *
+    * To disable, pass in @c false.
+    */
+   void
+   enableLogging(
+      bool logging);
+
+   /*!
+    * @brief Solve Stokes's equation, assuming an uninitialized
+    * solver state.
+    *
+    * Here, u is the "solution" patch data index and f is the
+    * right hand side patch data index.
+    * The return value is true if the solver converged and false otherwise.
+    *
+    * This function is a wrapper.
+    * It simply initializes the solver state, call the
+    * solveSystem(const int,const int) for the initialized solver then
+    * deallocates the solver state.
+    *
+    * Upon return from this function,
+    * solution will contain the result of the solve.
+    *
+    * See initializeSolverState() for opportunities to save overhead
+    * when using multiple consecutive solves.
+    *
+    * @see solveSystem(const int,const int)
+    *
+    * @param solution hier::Patch data index for solution u
+    * @param rhs hier::Patch data index for right hand side f
+    * @param hierarchy The patch hierarchy to solve on
+    * @param coarse_ln The coarsest level in the solve.
+    * @param fine_ln The finest level in the solve.
+    *
+    * @return whether solver converged to specified level
+    *
+    * @see initializeSolverState
+    */
+   bool
+   solveSystem(
+      const int solution,
+      const int rhs,
+      tbox::Pointer<hier::PatchHierarchy> hierarchy,
+      int coarse_ln = -1,
+      int fine_ln = -1);
+
+   /*!
+    * @brief Solve Stokes's equation using the current solver state
+    * set by initializeSolverState().
+    *
+    * When the solver state has been initialized, this function may
+    * be called repeadedly with different values on the rhs.
+    * There is some cost savings for multiple solves when this
+    * is done.
+    *
+    * Before calling this function, the solution and
+    * right-hand-side quantities should be set properly by the user
+    * on all patch interiors on the range of levels covered by the
+    * FAC iteration.  All data for these patch data index should be allocated.
+    * Thus, the user is responsible for managing the
+    * storage for the solution and right-hand-side.
+    *
+    * @return whether solver converged to specified level
+    *
+    * @see solveSystem( const int, const int, tbox::Pointer< hier::PatchHierarchy >, int, int);
+    */
+   bool
+   solveSystem(
+      const int solution,
+      const int rhs);
+
+   /*!
+    * @brief Specify the boundary conditions that are to be used at the
+    * physical domain boundary.
+    *
+    * This method is used to set up the default SimpleCellRobinBcCoefs
+    * object for specifying boundary conditions.  Note that you may
+    * alternatively provide your own implementation of the Robin
+    * boundary condition coefficients using the setBcObject() method.
+    *
+    * The boundary conditions specified as the
+    * std::string argument "boundary_type."  The boundary type argument can be
+    * "Dirichlet", "Neumann", or "Mixed".
+    *
+    * If using Dirichlet boundary conditions, then before the solver is
+    * called, the storage for the unknown u
+    * must have a mapped_box_level of ghost cells at least one cell wide that includes
+    * the Dirichlet boundary values.
+    *
+    * If using Neumann boundary conditions, then before the solver is called,
+    * the outerface boundary flux data must be set for the Neumann conditions.
+    * The fluxes argument gives the patch data index of this flux
+    * data.
+    *
+    * The mixed boundary type is for a mixture of Dirichlet and Neumann
+    * boundary conditions are used at the physical domain boundary.
+    * The fluxes argument gives the patch data index of the outerface data
+    * that specifies the flux data for the Neumann conditions.  The flags
+    * array is an outerface data array of integer flags that specifies whether
+    * Dirichlet (flag == zero) or Neumann (flag == one) conditions are to be
+    * used at a particular cell boundary face.  Note that the flag data must
+    * be set before the matrix entries can be computed and the flux data
+    * must be set before the solver is called.  The bdry_types argument can
+    * be used if the boundary conditions are mixed but one or more of the
+    * faces of the physical boundary are entirely either Dirichlet or
+    * Neumann boundaries.  The bdry_types argument should be an array of
+    * 2*DIM integers, specifying the boundary conditions on each side of
+    * the physical domain.  It should be ordered {x_lo, x_hi, y_lo, y_hi,
+    * z_lo, z_hi}, with the values for each face being 0 for Dirichlet
+    * conditions, 1 for Neumann conditions, and 2 for mixed boundary
+    * conditions.  The bdry_type argument is never required, but if used
+    * it can sometimes make the StokesHYPRESolver class more efficient.
+    */
+
+   void
+   setBoundaries(
+      const std::string& boundary_type,
+      const int fluxes = -1,
+      const int flags = -1,
+      int* bdry_types = NULL);
+
+   /*!
+    * @brief Override internal implementation to set boundary condition
+    * coefficients with user-provided implementation.
+    *
+    * This function is used to override the default internal
+    * object for setting Robin boundary condition coefficients.
+    * You should override when you need to avoid the limitations
+    * of the SimpleCellRobinBcCoefs class or you prefer to
+    * use your own implementation.
+    *
+    * Note that an important limitation of the SimpleCellRobinBcCoefs
+    * class is the inability to support linear interpolation in
+    * the prolongation step.
+    *
+    * Once the boundary condition object is overwritten by this
+    * method, you must no longer call the setBoundaries() method.
+    */
+   void
+   setBcObject(
+      const RobinBcCoefStrategy* bc_object);
+
+   //!@{ @name Specifying PDE parameters
+
+   /*!
+    * @brief Set the patch data index for variable D.
+    *
+    * In addition, disregard any previous D
+    * specified by setDConstant().
+    */
+   void
+   setDPatchDataId(
+      int id);
+
+   /*!
+    * @brief Set the scalar value variable D.
+    *
+    * In addition, disregard any previous D
+    * specified by setDPatchDataId().
+    */
+   void
+   setDConstant(
+      double scalar);
+
+   /*!
+    * @brief Set the scalar value variable C.
+    *
+    * In addition, disregard any previous C
+    * specified by setCConstant().
+    */
+   void
+   setCPatchDataId(
+      int id);
+
+   /*!
+    * @brief Set the patch data index for variable C.
+    *
+    * In addition, disregard any previous C
+    * specified by setCConstant().
+    */
+   void
+   setCConstant(
+      double scalar);
+
+   //@}
+
+   //@{ @name Functions for setting solver mathematic algorithm controls
+
+   /*!
+    * @brief Set coarse level solver.
+    *
+    * Select from these:
+    * - @c "redblack"
+    * - @c "hypre" (only if the HYPRE library is available).
+    */
+   void
+   setCoarsestLevelSolverChoice(
+      const std::string& choice);
+
+   /*!
+    * @brief Set tolerance for coarse level solve.
+    *
+    * If the coarse level solver requires a tolerance
+    * (currently, they all do), the specified value is used.
+    */
+   void
+   setCoarsestLevelSolverTolerance(
+      double tol);
+
+   /*!
+    * @brief Set max iterations for coarse level solve.
+    *
+    * If the coarse level solver requires a max iteration limit
+    * (currently, they all do), the specified value is used.
+    */
+   void
+   setCoarsestLevelSolverMaxIterations(
+      int max_iterations);
+
+#ifdef HAVE_HYPRE
+   /*!
+    * @brief Set whether to use HYPRe's PFMG algorithm instead of the
+    * SMG algorithm.
+    *
+    * The flag is used to select which of HYPRE's linear solver algorithms
+    * to use if true, the semicoarsening multigrid algorithm is used, and if
+    * false, the ``PF'' multigrid algorithm is used.
+    * By default, the SMG algorithm is used.
+    *
+    * This setting has effect only when HYPRe is chosen for the coarsest
+    * level solver.  See setCoarsestLevelSolverChoice().
+    *
+    * Changing the algorithm must be done before setting up the matrix
+    * coefficients.
+    */
+   void
+   setUseSMG(
+      bool use_smg);
+#endif
+
+   /*!
+    * @brief Set the coarse-fine boundary discretization method.
+    *
+    * Specify the @c op_name std::string which will be passed to
+    * xfer::Geometry::lookupRefineOperator() to get the operator
+    * for setting fine grid ghost cells from the coarse grid.
+    * Note that chosing this operator implicitly choses the
+    * discretization method at the coarse-fine boundary.
+    *
+    * There is one important instance where this std::string is
+    * @em not passed to xfer::Geometry::lookupRefineOperator().
+    * If this variable is set to "Ewing", a constant refinement
+    * method is used along with Ewing's correction.
+    * For a reference to the correction method, see
+    * "Local Refinement Techniques for Elliptic Problems on Cell-Centered
+    * Grids, I. Error Analysis", Mathematics of Computation, Vol. 56, No. 194,
+    * April 1991, pp. 437-461.
+    *
+    * @param coarsefine_method String selecting the coarse-fine discretization method.
+    */
+   void
+   setCoarseFineDiscretization(
+      const std::string& coarsefine_method);
+
+   /*!
+    * @brief Set the name of the prolongation method.
+    *
+    * Specify the @c op_name std::string which will be passed to
+    * xfer::Geometry::lookupRefineOperator() to get the operator
+    * for prolonging the coarse-grid correction.
+    *
+    * By default, "CONSTANT_REFINE" is used.  "LINEAR_REFINE" seems to
+    * to lead to faster convergence, but it does NOT satisfy the Galerkin
+    * condition.
+    *
+    * Prolonging using linear refinement requires a Robin bc
+    * coefficient implementation that is capable of delivering
+    * coefficients for non-hierarchy data, because linear refinement
+    * requires boundary conditions to be set on temporary levels.
+    *
+    * @param prolongation_method String selecting the coarse-fine discretization method.
+    */
+   void
+   setProlongationMethod(
+      const std::string& prolongation_method);
+
+   /*!
+    * @brief Set the number of pre-smoothing sweeps during
+    * FAC iteration process.
+    *
+    * Presmoothing is applied during the fine-to-coarse phase of the
+    * iteration.  The default is to use one sweep.
+    *
+    * @param num_pre_sweeps Number of presmoothing sweeps
+    */
+   void
+   setPresmoothingSweeps(
+      int num_pre_sweeps);
+
+   /*!
+    * @brief Set the number of post-smoothing sweeps during
+    * FAC iteration process.
+    *
+    * Postsmoothing is applied during the coarse-to-fine phase of the
+    * iteration.  The default is to use one sweep.
+    *
+    * @param num_post_sweeps Number of postsmoothing sweeps
+    */
+   void
+   setPostsmoothingSweeps(
+      int num_post_sweeps);
+
+   /*!
+    * @brief Set the max number of iterations (cycles) to use per solve.
+    */
+   void
+   setMaxCycles(
+      int max_cycles);
+
+   /*!
+    * @brief Set the residual tolerance for stopping.
+    *
+    * If you want the prescribed maximum number of cycles to always be taken,
+    * set the residual tolerance to a negative number.
+    */
+   void
+   setResidualTolerance(
+      double residual_tol);
+
+   //@}
+
+   /*!
+    * @brief Prepare the solver's internal state for solving
+    *
+    * In the interest of efficiency, this class may prepare and
+    * cache some hierarchy-dependent objects.  Though it is not required,
+    * initializing the solver state makes for greater efficiency
+    * when you are doing multiple solves on the same system of
+    * equation.  If you do not initialize the state, it is initialized
+    * and deallocated each time you call solveSystem(const int, const int).
+    * The state must be reinitialized if the hierarchy or a boundary
+    * condition type changes.
+    *
+    * To unset the data set in this function,
+    * see deallocateSolverState().
+    *
+    * The @c solution and @c rhs patch data indices in the argument
+    * list are used to determine the @em form of the data you
+    * plan to use in the solve.  They need not be the same data
+    * you solve on, but they should be similar.  Both must represent
+    * cell-centered double data.  The solution must have at least one
+    * ghost cell width, though this is not checked in the initialize
+    * phase, because data is not required yet.
+    *
+    * @param solution solution patch data index for u
+    * @param rhs right hand side patch data index for f
+    * @param hierarchy The patch hierarchy to solve on
+    * @param coarse_level The coarsest level in the solve
+    * @param fine_level The finest level in the solve
+    */
+   void
+   initializeSolverState(
+      const int solution,
+      const int rhs,
+      tbox::Pointer<hier::PatchHierarchy> hierarchy,
+      const int coarse_level = -1,
+      const int fine_level = -1);
+
+   /*!
+    * @brief Remove the solver's internal state data
+    *
+    * Remove all hierarchy-dependent data set by initializeSolverState.
+    * It is safe to call deallocateSolverState() even state is already
+    * deallocated, but nothing is done in that case.
+    *
+    * @see initializeSolverState()
+    */
+   void
+   deallocateSolverState();
+
+   //@{
+   //! @name Functions to get data on last solve.
+
+   /*!
+    * @brief Return FAC iteration count from last (or current
+    * if there is one) FAC iteration process.
+    */
+   int
+   getNumberOfIterations() const;
+
+   /*!
+    * @brief Get average convergance rate and convergence rate of
+    * the last (or current if there is one) FAC solve.
+    *
+    * @param avg_factor average convergence factor over current FAC cycles
+    * @param final_factor convergence factor of the last FAC cycle
+    */
+   void
+   getConvergenceFactors(
+      double& avg_factor,
+      double& final_factor) const;
+
+   /*!
+    * @brief Return residual norm from the just-completed FAC iteration.
+    *
+    * The norm return value is computed as the maximum norm over all
+    * patch levels involved in the solve.  The value corresponds to the
+    * norm applied in the user-defined residual computation.
+    *
+    * The latest computed norm is the one returned.
+    */
+   double
+   getResidualNorm() const;
+
+   //@}
+
+private:
+   /*!
+    * @brief Set state using database
+    *
+    * See the class description for the parameters that can be set
+    * from a database.
+    *
+    * @param database Input database.  If a NULL pointer is given,
+    * nothing is done.
+    */
+   void
+   getFromInput(
+      tbox::Pointer<tbox::Database> database);
+
+   /*
+    * @brief Set @c d_uv and @c d_fv to vectors wrapping the data
+    * specified by patch data indices u and f.
+    */
+   void
+   createVectorWrappers(
+      int u,
+      int f);
+
+   /*
+    * @brief Destroy vector wrappers referenced to by @c d_uv and @c d_fv.
+    */
+   void
+   destroyVectorWrappers();
+
+   /*
+    * @brief Initialize static members
+    */
+   static void
+   initializeStatics();
+
+   const tbox::Dimension d_dim;
+
+   /*!
+    * @brief Object name.
+    */
+   std::string d_object_name;
+
+   /*!
+    * @brief Object holding the specifications of the Stokes equation.
+    */
+   StokesSpecifications d_stokes_spec;
+
+   /*!
+    * @brief FAC operator implementation corresponding to cell-centered
+    * Stokes discretization.
+    */
+   CellStokesFACOps d_fac_ops;
+
+   /*!
+    * @brief FAC preconditioner algorithm.
+    */
+   FACPreconditioner d_fac_precond;
+
+   /*!
+    * @brief Robin bc object in use.
+    */
+   const RobinBcCoefStrategy* d_bc_object;
+
+   /*
+    * @brief Default implementation of RobinBcCoefStrategy
+    */
+   SimpleCellRobinBcCoefs d_simple_bc;
+
+   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
+   int d_ln_min;
+   int d_ln_max;
+
+   /*!
+    * @brief Context for all internally maintained data.
+    */
+   tbox::Pointer<hier::VariableContext> d_context;
+   /*
+    * @brief Vector wrapper for solution.
+    * @see createVectorWrappers(), destroyVectorWrappers()
+    */
+   tbox::Pointer<SAMRAIVectorReal<double> > d_uv;
+   /*
+    * @brief Vector wrapper for source.
+    * @see createVectorWrappers(), destroyVectorWrappers()
+    */
+   tbox::Pointer<SAMRAIVectorReal<double> > d_fv;
+
+   bool d_solver_is_initialized;
+   bool d_enable_logging;
+
+   static bool s_initialized;
+   static int s_weight_id[SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+   static int s_instance_counter[SAMRAI::tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+};
+
+}
+}
+
+#ifdef SAMRAI_INLINE
+#include "StokesFACSolver.I"
+#endif
+
+#endif  // included_solv_CellStokesFACSolver
diff -r a44a82f15794 -r fe2a9230921b StokesHypreSolver.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesHypreSolver.C	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,1590 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Hypre solver interface for diffusion-like elliptic problems. 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesHypreSolver_C
+#define included_solv_StokesHypreSolver_C
+
+#include "StokesHypreSolver.h"
+
+#ifdef HAVE_HYPRE
+
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/math/ArrayDataBasicOps.h"
+#include "SAMRAI/math/PatchSideDataBasicOps.h"
+#include "SAMRAI/pdat/ArrayData.h"
+#include "SAMRAI/pdat/CellIndex.h"
+#include "SAMRAI/pdat/CellIterator.h"
+#include "SAMRAI/pdat/FaceIndex.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/SideIndex.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/pdat/OuterfaceData.h"
+#include "SAMRAI/pdat/OutersideData.h"
+#include "SAMRAI/hier/BoundaryBoxUtils.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+#include "SAMRAI/tbox/MathUtilities.h"
+#include "SAMRAI/tbox/SAMRAI_MPI.h"
+#include "SAMRAI/tbox/SAMRAIManager.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Timer.h"
+#include "SAMRAI/tbox/TimerManager.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+#include "SAMRAI/tbox/Utilities.h"
+
+#include <cstdlib>
+
+#ifndef SAMRAI_INLINE
+#include "StokesHypreSolver.I"
+#endif
+
+extern "C" {
+
+#ifdef __INTEL_COMPILER
+#pragma warning (disable:1419)
+#endif
+
+void F77_FUNC(compdiagvariablec2d, COMPDIAGVARIABLEC2D) (
+   double* diag,
+   const double* c,
+   const double* offdiagi,
+   const double* offdiagj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(compdiagscalarc2d, COMPDIAGSCALARC2D) (
+   double* diag,
+   const double* c,
+   const double* offdiagi,
+   const double* offdiagj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(compdiagzeroc2d, COMPDIAGZEROC2D) (
+   double* diag,
+   const double* offdiagi,
+   const double* offdiagj,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(adjbdry2d, ADJBDRY2D) (
+   double* diag,
+   const double* offdiagi,
+   const double* offdiagj,
+   const int* pifirst, const int* pilast,
+   const int* pjfirst, const int* pjlast,
+   const double* acoef,
+   const double* bcoef,
+   const int* aifirst, const int* ailast,
+   const int* ajfirst, const int* ajlast,
+   const double* Ak0,
+   const int* kifirst, const int* kilast,
+   const int* kjfirst, const int* kjlast,
+   const int* lower, const int* upper,
+   const int* location,
+   const double* h);
+void F77_FUNC(adjbdryconstoffdiags2d, ADJBDRYCONSTOFFDIAGS2D) (
+   double* diag,
+   const double* offdiag,
+   const int* pifirst,
+   const int* pilast,
+   const int* pjfirst,
+   const int* pjlast,
+   const double* acoef,
+   const int* aifirst,
+   const int* ailast,
+   const int* ajfirst,
+   const int* ajlast,
+   const double* Ak0,
+   const int* kifirst,
+   const int* kilast,
+   const int* kjfirst,
+   const int* kjlast,
+   const int* lower, const int* upper,
+   const int* location,
+   const double* h);
+void F77_FUNC(adjustrhs2d, ADJUSTRHS2D) (double* rhs,
+   const int* rifirst,
+   const int* rilast,
+   const int* rjfirst,
+   const int* rjlast,
+   const double* Ak0,
+   const int* kifirst,
+   const int* kilast,
+   const int* kjfirst,
+   const int* kjlast,
+   const double* gcoef,
+   const int* aifirst,
+   const int* ailast,
+   const int* ajfirst,
+   const int* ajlast,
+   const int* lower, const int* upper,
+   const int* location);
+
+void F77_FUNC(compdiagvariablec3d, COMPDIAGVARIABLEC3D) (
+   double* diag,
+   const double* c,
+   const double* offdiagi,
+   const double* offdiagj,
+   const double* offdiagk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(compdiagscalarc3d, COMPDIAGSCALARC3D) (
+   double* diag,
+   const double* c,
+   const double* offdiagi,
+   const double* offdiagj,
+   const double* offdiagk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(compdiagzeroc3d, COMPDIAGZEROC3D) (
+   double* diag,
+   const double* offdiagi,
+   const double* offdiagj,
+   const double* offdiagk,
+   const int* ifirst,
+   const int* ilast,
+   const int* jfirst,
+   const int* jlast,
+   const int* kfirst,
+   const int* klast,
+   const double* cscale,
+   const double* dscale);
+void F77_FUNC(adjbdry3d, ADJBDRY3D) (
+   double* diag,
+   const double* offdiagi,
+   const double* offdiagj,
+   const double* offdiagk,
+   const int* pifirst,
+   const int* pilast,
+   const int* pjfirst,
+   const int* pjlast,
+   const int* pkfirst,
+   const int* pklast,
+   const double* acoef,
+   const double* bcoef,
+   const int* aifirst,
+   const int* ailast,
+   const int* ajfirst,
+   const int* ajlast,
+   const int* akfirst,
+   const int* aklast,
+   const double* Ak0,
+   const int* kifirst,
+   const int* kilast,
+   const int* kjfirst,
+   const int* kjlast,
+   const int* kkfirst,
+   const int* kklast,
+   const int* lower, const int* upper,
+   const int* location,
+   const double* h);
+void F77_FUNC(adjbdryconstoffdiags3d, ADJBDRYCONSTOFFDIAGS3D) (
+   double* diag,
+   const double* offdiag,
+   const int* pifirst,
+   const int* pilast,
+   const int* pjfirst,
+   const int* pjlast,
+   const int* pkfirst,
+   const int* pklast,
+   const double* acoef,
+   const int* aifirst,
+   const int* ailast,
+   const int* ajfirst,
+   const int* ajlast,
+   const int* akfirst,
+   const int* aklast,
+   const double* Ak0,
+   const int* kifirst,
+   const int* kilast,
+   const int* kjfirst,
+   const int* kjlast,
+   const int* kkfirst,
+   const int* kklast,
+   const int* lower, const int* upper,
+   const int* location,
+   const double* h);
+void F77_FUNC(adjustrhs3d, ADJUSTRHS3D) (double* rhs,
+   const int* rifirst,
+   const int* rilast,
+   const int* rjfirst,
+   const int* rjlast,
+   const int* rkfirst,
+   const int* rklast,
+   const double* Ak0,
+   const int* kifirst,
+   const int* kilast,
+   const int* kjfirst,
+   const int* kjlast,
+   const int* kkfirst,
+   const int* kklast,
+   const double* gcoef,
+   const int* aifirst,
+   const int* ailast,
+   const int* ajfirst,
+   const int* ajlast,
+   const int* akfirst,
+   const int* aklast,
+   const int* lower, const int* upper,
+   const int* location);
+
+}
+
+namespace SAMRAI {
+namespace solv {
+
+tbox::Pointer<pdat::OutersideVariable<double> >
+CellStokesHypreSolver::s_Ak0_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+tbox::StartupShutdownManager::Handler CellStokesHypreSolver::s_finalize_handler(
+   0,
+   0,
+   0,
+   CellStokesHypreSolver::finalizeCallback,
+   tbox::StartupShutdownManager::priorityVariables);
+
+/*
+ *************************************************************************
+ * Constructor                                                           *
+ *************************************************************************
+ */
+
+CellStokesHypreSolver::CellStokesHypreSolver(
+   const tbox::Dimension& dim,
+   const std::string& object_name,
+   tbox::Pointer<tbox::Database> database):
+   d_dim(dim),
+   d_object_name(object_name),
+   d_hierarchy(NULL),
+   d_ln(-1),
+   d_context(hier::VariableDatabase::getDatabase()->
+             getContext(object_name + "::context")),
+   d_cf_boundary(),
+   d_physical_bc_coef_strategy(&d_physical_bc_simple_case),
+   d_physical_bc_variable(NULL),
+   d_physical_bc_simple_case(dim, d_object_name + "::simple bc"),
+   d_cf_bc_coef(dim, object_name + "::coarse-fine bc coefs"),
+   d_coarsefine_bc_variable(NULL),
+   d_Ak0_id(-1),
+   d_soln_depth(0),
+   d_rhs_depth(0),
+   d_max_iterations(10),
+   d_relative_residual_tol(1e-10),
+   d_number_iterations(-1),
+   d_num_pre_relax_steps(1),
+   d_num_post_relax_steps(1),
+   d_relative_residual_norm(-1.0),
+   d_use_smg(false),
+   d_grid(NULL),
+   d_stencil(NULL),
+   d_matrix(NULL),
+   d_linear_rhs(NULL),
+   d_linear_sol(NULL),
+   d_mg_data(NULL),
+   d_print_solver_info(false)
+{
+   if (d_dim == tbox::Dimension(1) || d_dim > tbox::Dimension(3)) {
+      TBOX_ERROR(" CellStokesHypreSolver : DIM == 1 or > 3 not implemented");
+   }
+
+   t_solve_system = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesHypreSolver::solveSystem()");
+   t_set_matrix_coefficients = tbox::TimerManager::getManager()->
+      getTimer("solv::CellStokesHypreSolver::setMatrixCoefficients()");
+
+   hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
+   if (s_Ak0_var[d_dim.getValue() - 1].isNull()) {
+      s_Ak0_var[d_dim.getValue() - 1] = new
+         pdat::OutersideVariable<double>(d_dim, d_object_name + "::Ak0", 1);
+   }
+   d_Ak0_id =
+      vdb->registerVariableAndContext(s_Ak0_var[d_dim.getValue() - 1],
+         d_context,
+         hier::IntVector::getZero(d_dim));
+   if (database) {
+      getFromInput(database);
+   }
+}
+
+/*
+ ********************************************************************
+ * Set state from database                                          *
+ ********************************************************************
+ */
+
+void CellStokesHypreSolver::getFromInput(
+   tbox::Pointer<tbox::Database> database)
+{
+   if (database) {
+      d_print_solver_info = database->getBoolWithDefault("print_solver_info",
+            d_print_solver_info);
+      d_max_iterations = database->getIntegerWithDefault("max_iterations",
+            d_max_iterations);
+      d_relative_residual_tol = database->getDoubleWithDefault(
+            "relative_residual_tol",
+            d_relative_residual_tol);
+      if (database->isDouble("residual_tol")) {
+         TBOX_ERROR("CellStokesHypreSolver input error.\n"
+            << "The parameter 'residual_tol' has been replaced\n"
+            << "by 'relative_residual_tol' to be more descriptive.\n"
+            << "Please change the parameter name in the input database.");
+      }
+      d_num_pre_relax_steps =
+         database->getIntegerWithDefault("num_pre_relax_steps",
+            d_num_pre_relax_steps);
+      if (d_num_pre_relax_steps < 0) {
+         TBOX_ERROR(d_object_name << ": Number of relaxation steps must be\n"
+                                  << "non-negative.\n");
+      }
+      d_num_post_relax_steps =
+         database->getIntegerWithDefault("num_post_relax_steps",
+            d_num_post_relax_steps);
+      if (d_num_post_relax_steps < 0) {
+         TBOX_ERROR(d_object_name << ": Number of relaxation steps must be\n"
+                                  << "non-negative.\n");
+      }
+      if (database->isBool("use_smg")) {
+         bool use_smg = database->getBool("use_smg");
+         if (use_smg != d_use_smg) {
+            setUseSMG(use_smg);
+         }
+      }
+   }
+}
+
+/*
+ ********************************************************************
+ * Initialize internal data for a given hierarchy level             *
+ * After setting internal data, propagate the information           *
+ * to the major algorithm objects.  Allocate data for               *
+ * storing boundary condition-dependent quantities for              *
+ * adding to souce term before solving.                             *
+ ********************************************************************
+ */
+
+void CellStokesHypreSolver::initializeSolverState(
+   tbox::Pointer<hier::PatchHierarchy> hierarchy,
+   int ln)
+{
+   TBOX_ASSERT(!hierarchy.isNull());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS1(d_dim, *hierarchy);
+
+   deallocateSolverState();
+
+   d_hierarchy = hierarchy;
+   d_ln = ln;
+
+   hier::IntVector max_gcw(d_dim, 1);
+   d_cf_boundary = new hier::CoarseFineBoundary(*d_hierarchy, d_ln, max_gcw);
+
+   d_physical_bc_simple_case.setHierarchy(d_hierarchy, d_ln, d_ln);
+
+   d_number_iterations = -1;
+   d_relative_residual_norm = -1.0;
+
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
+   level->allocatePatchData(d_Ak0_id);
+   allocateHypreData();
+}
+
+/*
+ ********************************************************************
+ * Deallocate data initialized by initializeSolverState             *
+ ********************************************************************
+ */
+
+void CellStokesHypreSolver::deallocateSolverState()
+{
+   if (d_hierarchy.isNull()) return;
+
+   d_cf_boundary->clear();
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
+   level->deallocatePatchData(d_Ak0_id);
+   deallocateHypreData();
+   d_hierarchy.setNull();
+   d_ln = -1;
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Allocate the HYPRE data structures that depend only on the level      *
+ * and will not change (grid, stencil, matrix, and vectors).             *
+ *                                                                       *
+ *************************************************************************
+ */
+void CellStokesHypreSolver::allocateHypreData()
+{
+   tbox::SAMRAI_MPI::Comm communicator = d_hierarchy->getDomainMappedBoxLevel().getMPI().getCommunicator();
+
+   /*
+    * Set up the grid data - only set grid data for local boxes
+    */
+
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
+   tbox::Pointer<geom::CartesianGridGeometry> grid_geometry =
+      d_hierarchy->getGridGeometry();
+   const hier::IntVector ratio = level->getRatioToLevelZero();
+   hier::IntVector periodic_shift =
+      grid_geometry->getPeriodicShift(ratio);
+
+   int periodic_flag[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+   int d;
+   bool is_periodic = false;
+   for (d = 0; d < d_dim.getValue(); ++d) {
+      periodic_flag[d] = periodic_shift[d] != 0;
+      is_periodic = is_periodic || periodic_flag[d];
+   }
+
+   HYPRE_StructGridCreate(communicator, d_dim.getValue(), &d_grid);
+   for (hier::PatchLevel::Iterator p(level); p; p++) {
+      const hier::Box& box = (*p)->getBox();
+      hier::Index lower = box.lower();
+      hier::Index upper = box.upper();
+      HYPRE_StructGridSetExtents(d_grid, &lower[0], &upper[0]);
+   }
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (is_periodic) {
+      const hier::BoxArray& level_domain = level->getPhysicalDomain();
+      hier::Box domain_bound(level_domain[0]);
+      for (int i = 1; i < level_domain.size(); ++i) {
+         domain_bound.lower().min(level_domain[i].lower());
+         domain_bound.upper().max(level_domain[i].upper());
+      }
+      for (d = 0; d < d_dim.getValue(); ++d) {
+         if (periodic_flag[d] == true) {
+            int tmpi = 1;
+            unsigned int p_of_two;
+            for (p_of_two = 0; p_of_two < 8 * sizeof(p_of_two) - 1;
+                 ++p_of_two) {
+               if (tmpi == domain_bound.numberCells(d)) {
+                  break;
+               }
+               if (tmpi > domain_bound.numberCells(d)) {
+                  TBOX_ERROR(
+                     d_object_name << ": Hypre currently requires\n"
+                     <<
+                     "that grid size in periodic directions be\n"
+                     <<
+                     "powers of two.  (This requirement may go\n"
+                     <<
+                     "away in future versions of hypre.)\n"
+                     << "Size problem in direction "
+                     << d << "\n"
+                     << "Domain bound is "
+                     << domain_bound << ",\n"
+                     << "Size of "
+                     << domain_bound.numberCells() << "\n");
+               }
+               tmpi = tmpi ? tmpi << 1 : 1;
+            }
+         }
+      }
+   }
+#endif
+
+   HYPRE_StructGridSetPeriodic(d_grid, &periodic_shift[0]);
+   HYPRE_StructGridAssemble(d_grid);
+
+   {
+      /*
+       * Allocate stencil data and set stencil offsets
+       */
+
+      if (d_dim == tbox::Dimension(1)) {
+         const int stencil_size = 2;
+         int stencil_offsets[2][1] = {
+            { -1 }, { 0 }
+         };
+         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
+         for (int s = 0; s < stencil_size; s++) {
+            HYPRE_StructStencilSetElement(d_stencil, s,
+               stencil_offsets[s]);
+         }
+      } else if (d_dim == tbox::Dimension(2)) {
+         const int stencil_size = 3;
+         int stencil_offsets[3][2] = {
+            { -1, 0 }, { 0, -1 }, { 0, 0 }
+         };
+         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
+         for (int s = 0; s < stencil_size; s++) {
+            HYPRE_StructStencilSetElement(d_stencil, s,
+               stencil_offsets[s]);
+         }
+      } else if (d_dim == tbox::Dimension(3)) {
+         const int stencil_size = 4;
+         int stencil_offsets[4][3] = {
+            { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 }, { 0, 0, 0 }
+         };
+         HYPRE_StructStencilCreate(d_dim.getValue(), stencil_size, &d_stencil);
+         for (int s = 0; s < stencil_size; s++) {
+            HYPRE_StructStencilSetElement(d_stencil, s,
+               stencil_offsets[s]);
+         }
+      }
+   }
+
+   {
+      int full_ghosts1[2 * 3] = { 1, 1, 0, 0, 0, 0 };
+      int no_ghosts1[2 * 3] = { 0, 0, 0, 0, 0, 0 };
+
+      int full_ghosts2[2 * 3] = { 1, 1, 1, 1, 0, 0 };
+      int no_ghosts2[2 * 3] = { 0, 0, 0, 0, 0, 0 };
+
+      int full_ghosts3[2 * 3] = { 1, 1, 1, 1, 1, 1 };
+      int no_ghosts3[2 * 3] = { 0, 0, 0, 0, 0, 0 };
+
+      /*
+       * Allocate the structured matrix
+       */
+
+      int* full_ghosts = NULL;
+      int* no_ghosts = NULL;
+
+      if (d_dim == tbox::Dimension(1)) {
+         full_ghosts = full_ghosts1;
+         no_ghosts = no_ghosts1;
+      } else if (d_dim == tbox::Dimension(2)) {
+         full_ghosts = full_ghosts2;
+         no_ghosts = no_ghosts2;
+      } else if (d_dim == tbox::Dimension(3)) {
+         full_ghosts = full_ghosts3;
+         no_ghosts = no_ghosts3;
+      } else {
+         TBOX_ERROR(
+            "CellStokesHypreSolver does not yet support dimension " << d_dim);
+      }
+
+      HYPRE_StructMatrixCreate(communicator,
+         d_grid,
+         d_stencil,
+         &d_matrix);
+      HYPRE_StructMatrixSetNumGhost(d_matrix, full_ghosts);
+      HYPRE_StructMatrixSetSymmetric(d_matrix, 1);
+      HYPRE_StructMatrixInitialize(d_matrix);
+
+      HYPRE_StructVectorCreate(communicator,
+         d_grid,
+         &d_linear_rhs);
+      HYPRE_StructVectorSetNumGhost(d_linear_rhs, no_ghosts);
+      HYPRE_StructVectorInitialize(d_linear_rhs);
+
+      HYPRE_StructVectorCreate(communicator,
+         d_grid,
+         &d_linear_sol);
+      HYPRE_StructVectorSetNumGhost(d_linear_sol, full_ghosts);
+      HYPRE_StructVectorInitialize(d_linear_sol);
+   }
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * The destructor deallocates solver data.                               *
+ *                                                                       *
+ *************************************************************************
+ */
+
+CellStokesHypreSolver::~CellStokesHypreSolver()
+{
+   deallocateHypreData();
+
+   if (!d_hierarchy.isNull()) {
+      tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(0);
+      level->deallocatePatchData(d_Ak0_id);
+   }
+   hier::VariableDatabase* vdb =
+      hier::VariableDatabase::getDatabase();
+   vdb->removePatchDataIndex(d_Ak0_id);
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Deallocate HYPRE data and solver.  HYPRE requires that we             *
+ * check whether HYPRE has already deallocated this data.                *
+ * Note that the HYPRE solver, d_mg_data, was created at                 *
+ * the end of setMatrixCoefficients.                                     *
+ *                                                                       *
+ *************************************************************************
+ */
+
+void CellStokesHypreSolver::deallocateHypreData()
+{
+   if (d_stencil) {
+      HYPRE_StructStencilDestroy(d_stencil);
+      d_stencil = NULL;
+   }
+   if (d_grid) {
+      HYPRE_StructGridDestroy(d_grid);
+      d_grid = NULL;
+   }
+   if (d_matrix) {
+      HYPRE_StructMatrixDestroy(d_matrix);
+      d_matrix = NULL;
+   }
+   if (d_linear_rhs) {
+      HYPRE_StructVectorDestroy(d_linear_rhs);
+      d_linear_rhs = NULL;
+   }
+   if (d_linear_sol) {
+      HYPRE_StructVectorDestroy(d_linear_sol);
+      d_linear_sol = NULL;
+   }
+   destroyHypreSolver();
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Copy data into the HYPRE vector structures.                           *
+ *                                                                       *
+ *************************************************************************
+ */
+
+void CellStokesHypreSolver::copyToHypre(
+   HYPRE_StructVector vector,
+   pdat::CellData<double>& src,
+   int depth,
+   const hier::Box& box)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, src, box);
+
+   for (pdat::CellIterator c(box); c; c++) {
+      hier::IntVector ic = c();
+      HYPRE_StructVectorSetValues(vector, &ic[0], src(c(), depth));
+   }
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Copy data out of the HYPRE vector structures.                         *
+ *                                                                       *
+ *************************************************************************
+ */
+
+void CellStokesHypreSolver::copyFromHypre(
+   pdat::CellData<double>& dst,
+   int depth,
+   HYPRE_StructVector vector,
+   const hier::Box box)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, dst, box);
+
+   for (pdat::CellIterator c(box); c; c++) {
+      double value;
+      hier::IntVector ic = c();
+      HYPRE_StructVectorGetValues(vector, &ic[0], &value);
+      dst(c(), depth) = value;
+   }
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Set the matrix coefficients for the linear system.                    *
+ * The matrix coefficients are dependent on the problem                  *
+ * specification described by the StokesSpecificiations            *
+ * object and by the boundary condition.                                 *
+ *                                                                       *
+ *************************************************************************
+ */
+
+void CellStokesHypreSolver::setMatrixCoefficients(
+   const StokesSpecifications& spec)
+{
+   if (d_physical_bc_coef_strategy == NULL) {
+      TBOX_ERROR(
+         d_object_name << ": No BC coefficient strategy object!\n"
+         <<
+         "Use either setBoundaries or setPhysicalBcCoefObject\n"
+         <<
+         "to specify the boundary conidition.  Do it before\n"
+         << "calling setMatrixCoefficients.");
+   }
+
+   t_set_matrix_coefficients->start();
+
+   int i = 0;
+
+   tbox::Pointer<pdat::CellData<double> > C_data;
+   tbox::Pointer<pdat::SideData<double> > D_data;
+
+   /*
+    * Some computations can be done using high-level math objects.
+    * Define the math objects.
+    */
+   math::ArrayDataBasicOps<double> array_math;
+   math::PatchSideDataBasicOps<double> patch_side_math;
+
+   /*
+    * The value of the ghost cell based on the Robin boundary condition
+    * can be written as the sum of a constant, k0, plus a multiple of the
+    * internal cell value, k1*ui.  k1*ui depends on the value of u so it
+    * contributes to the product Au,
+    * while the constant k0 contributes the right hand side f.
+    * We save Ak0 = A*k0(a) to add to f when solving.
+    * We assume unit g here because we will multiply it in just before
+    * solving, thus allowing everything that does not affect A to change
+    * from solve to solve.
+    */
+   tbox::Pointer<pdat::OutersideData<double> > Ak0;
+
+   /*
+    * Loop over patches and set matrix entries for each patch.
+    */
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
+   const hier::IntVector no_ghosts(d_dim, 0);
+   for (hier::PatchLevel::Iterator pi(*level); pi; pi++) {
+
+      hier::Patch& patch = **pi;
+
+      tbox::Pointer<geom::CartesianPatchGeometry> pg =
+         patch.getPatchGeometry();
+
+      const double* h = pg->getDx();
+
+      const hier::Box patch_box = patch.getBox();
+      const hier::Index patch_lo = patch_box.lower();
+      const hier::Index patch_up = patch_box.upper();
+
+      if (!spec.cIsZero() && !spec.cIsConstant()) {
+         C_data = patch.getPatchData(spec.getCPatchDataId());
+         if (C_data.isNull()) {
+            TBOX_ERROR(d_object_name << ": Invalid cell variable index "
+                                     << spec.getCPatchDataId()
+                                     << " for the C parameter.  It is not\n"
+                                     << "cell-centered double data.");
+         }
+      }
+
+      if (!spec.dIsConstant()) {
+         D_data = patch.getPatchData(spec.getDPatchDataId());
+         if (D_data.isNull()) {
+            TBOX_ERROR(d_object_name << ": Invalid cell variable index "
+                                     << spec.getDPatchDataId()
+                                     <<
+               " for diffusion coefficient.  It is not\n"
+                                     << "side-centered double data.");
+         }
+      }
+
+      Ak0 = patch.getPatchData(d_Ak0_id);
+
+      Ak0->fillAll(0.0);
+
+      pdat::CellData<double> diagonal(patch_box, 1, no_ghosts);
+
+      /*
+       * Set diagonals to zero so we can accumulate to it.
+       * Accumulation is used at boundaries to shift weights
+       * for ghost cells onto the diagonal.
+       */
+      diagonal.fillAll(0.0);
+
+      const tbox::Pointer<geom::CartesianPatchGeometry>
+      geometry = patch.getPatchGeometry();
+
+      const hier::Index ifirst = patch_box.lower();
+      const hier::Index ilast = patch_box.upper();
+
+      /*
+       * Storage for off-diagonal entries,
+       * which can be variable or constant.
+       */
+      pdat::SideData<double> off_diagonal(patch_box, 1, no_ghosts);
+
+      /*
+       * Compute all off-diagonal entries with no regard to BCs.
+       * These off-diagonal entries are simply D/(h*h), according
+       * to our central difference formula.
+       */
+      if (spec.dIsConstant()) {
+         for (i = 0; i < d_dim.getValue(); ++i) {
+            double dhh = spec.getDConstant() / (h[i] * h[i]);
+            pdat::ArrayData<double>& off_diag_array(off_diagonal.getArrayData(i));
+            off_diag_array.fill(dhh);
+         }
+      } else {
+         for (i = 0; i < d_dim.getValue(); ++i) {
+            hier::Box sbox(patch_box);
+            sbox.growUpper(i, 1);
+            array_math.scale(off_diagonal.getArrayData(i),
+               1.0 / (h[i] * h[i]),
+               D_data->getArrayData(i),
+               sbox);
+         }
+      }
+
+      /*
+       * Compute diagonal entries using off-diagonal contributions.
+       */
+      if (spec.cIsZero()) {
+         computeDiagonalEntries(diagonal,
+            off_diagonal,
+            patch_box);
+      } else if (spec.cIsConstant()) {
+         computeDiagonalEntries(diagonal,
+            spec.getCConstant(),
+            off_diagonal,
+            patch_box);
+      } else {
+         computeDiagonalEntries(diagonal,
+            *C_data,
+            off_diagonal,
+            patch_box);
+      }
+
+      /*
+       * Walk physical domain boundaries and adjust off-diagonals
+       * before computation of diagonal entries.
+       * The exterior cell's value is
+       * uo = ( h*gamma + ui*(beta-h*alpha/2) )/( beta+h*alpha/2 )
+       *   = k0 + k1*ui
+       * where k0 = h*gamma/( beta+h*alpha/2 )
+       * k1 = ( beta-h*alpha/2 )/( beta+h*alpha/2 )
+       * Split coupling between interior-exterior cells
+       * into two parts: interior-interior coupling (k1)
+       * and rhs contribution (k0).
+       */
+      {
+         const tbox::Array<hier::BoundaryBox>& surface_boxes =
+            pg->getCodimensionBoundaries(1);
+         const int n_bdry_boxes = surface_boxes.getSize();
+         for (int n = 0; n < n_bdry_boxes; ++n) {
+
+            const hier::BoundaryBox& boundary_box = surface_boxes[n];
+            if (boundary_box.getBoundaryType() != 1) {
+               TBOX_ERROR(
+                  d_object_name << ": Illegal boundary type in "
+                  <<
+                  "CellStokesHypreSolver::setMatrixCoefficients\n");
+            }
+            const hier::BoundaryBoxUtils bbu(boundary_box);
+            const int location_index = boundary_box.getLocationIndex();
+            const hier::BoundaryBox trimmed_boundary_box =
+               bbu.trimBoundaryBox(patch.getBox());
+            const hier::Box bccoef_box =
+               bbu.getSurfaceBoxFromBoundaryBox();
+            tbox::Pointer<pdat::ArrayData<double> >
+            acoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
+            tbox::Pointer<pdat::ArrayData<double> >
+            bcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
+            tbox::Pointer<pdat::ArrayData<double> >
+            gcoef_data(NULL);
+            static const double fill_time = 0.0;
+            d_physical_bc_coef_strategy->setBcCoefs(acoef_data,
+               bcoef_data,
+               gcoef_data,
+               d_physical_bc_variable,
+               patch,
+               boundary_box,
+               fill_time);
+            pdat::ArrayData<double>& Ak0_data =
+               Ak0->getArrayData(location_index / 2,
+                  location_index % 2);
+            adjustBoundaryEntries(diagonal,
+               off_diagonal,
+               patch_box,
+               *acoef_data,
+               *bcoef_data,
+               bccoef_box,
+               Ak0_data,
+               trimmed_boundary_box,
+               h);
+         }
+      }
+
+      /*
+       * Walk coarse-fine boundaries and adjust off-diagonals
+       * according data in ghost cells.
+       */
+      if (d_ln > 0) {
+         /*
+          * There are potentially coarse-fine boundaries to deal with.
+          */
+
+         tbox::Array<hier::BoundaryBox> surface_boxes;
+
+         if (d_dim == tbox::Dimension(2)) {
+            surface_boxes = d_cf_boundary->getEdgeBoundaries(pi->getGlobalId());
+         } else if (d_dim == tbox::Dimension(3)) {
+            surface_boxes = d_cf_boundary->getFaceBoundaries(pi->getGlobalId());
+         }
+
+         const int n_bdry_boxes = surface_boxes.getSize();
+         for (int n = 0; n < n_bdry_boxes; ++n) {
+
+            const hier::BoundaryBox& boundary_box = surface_boxes[n];
+            if (boundary_box.getBoundaryType() != 1) {
+               TBOX_ERROR(
+                  d_object_name << ": Illegal boundary type in "
+                  <<
+                  "CellStokesHypreSolver::setMatrixCoefficients\n");
+            }
+            const int location_index = boundary_box.getLocationIndex();
+            const hier::BoundaryBoxUtils bbu(boundary_box);
+            const hier::BoundaryBox trimmed_boundary_box =
+               bbu.trimBoundaryBox(patch.getBox());
+            const hier::Box bccoef_box =
+               bbu.getSurfaceBoxFromBoundaryBox();
+            tbox::Pointer<pdat::ArrayData<double> >
+            acoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
+            tbox::Pointer<pdat::ArrayData<double> >
+            bcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
+            tbox::Pointer<pdat::ArrayData<double> >
+            gcoef_data(NULL);
+            static const double fill_time = 0.0;
+            /*
+             * Reset invalid ghost data id to help detect use in setBcCoefs.
+             */
+            d_cf_bc_coef.setGhostDataId(-1, hier::IntVector::getZero(d_dim));
+            d_cf_bc_coef.setBcCoefs(acoef_data,
+               bcoef_data,
+               gcoef_data,
+               d_coarsefine_bc_variable,
+               patch,
+               boundary_box,
+               fill_time);
+            pdat::ArrayData<double>& Ak0_data =
+               Ak0->getArrayData(location_index / 2,
+                  location_index % 2);
+            adjustBoundaryEntries(diagonal,
+               off_diagonal,
+               patch_box,
+               *acoef_data,
+               *bcoef_data,
+               bccoef_box,
+               Ak0_data,
+               trimmed_boundary_box,
+               h);
+         }
+      }
+
+      /*
+       * Copy matrix entries to HYPRE matrix structure.  Note that
+       * we translate our temporary diagonal/off-diagonal storage into the
+       * HYPRE symmetric storage scheme for the stencil specified earlier.
+       */
+      const int stencil_size = d_dim.getValue() + 1;
+      int stencil_indices[stencil_size];
+      double mat_entries[stencil_size];
+
+      for (i = 0; i < stencil_size; i++) stencil_indices[i] = i;
+
+      pdat::CellIterator ic(patch_box);
+
+      /*
+       * To do: This loop uses inefficient high-level syntax.
+       * See if it can be replaced by a Fortran loop or if we
+       * can set matrix entries for an entire box at once.
+       */
+      for ( ; ic; ic++) {
+
+         hier::IntVector icell = ic();
+         pdat::SideIndex ixlower(ic(),
+                                 pdat::SideIndex::X,
+                                 pdat::SideIndex::Lower);
+         mat_entries[0] = (off_diagonal)(ixlower);
+
+         if (d_dim > tbox::Dimension(1)) {
+            pdat::SideIndex iylower(ic(),
+                                    pdat::SideIndex::Y,
+                                    pdat::SideIndex::Lower);
+            mat_entries[1] = (off_diagonal)(iylower);
+         }
+
+         if (d_dim > tbox::Dimension(2)) {
+            pdat::SideIndex izlower(ic(),
+                                    pdat::SideIndex::Z,
+                                    pdat::SideIndex::Lower);
+            // The "funny" indexing prevents a warning when compiling for
+            // DIM < 2.  This code is only reached if DIM > 2 when
+            // executing.
+            mat_entries[d_dim.getValue() > 2 ? 2 : 0] = (off_diagonal)(izlower);
+         }
+
+         mat_entries[d_dim.getValue()] = (diagonal)(ic());
+         HYPRE_StructMatrixSetValues(d_matrix, &icell[0],
+            stencil_size, stencil_indices,
+            mat_entries);
+      } // end cell loop
+
+   } // end patch loop
+
+   if (d_print_solver_info) {
+      HYPRE_StructMatrixPrint("mat_bA.out", d_matrix, 1);
+   }
+
+   HYPRE_StructMatrixAssemble(d_matrix);
+
+   if (d_print_solver_info) {
+      HYPRE_StructMatrixPrint("mat_aA.out", d_matrix, 1);
+   }
+
+   t_set_matrix_coefficients->stop();
+
+   setupHypreSolver();
+}
+
+/*
+ **********************************************************************
+ * Add g*A*k0(a) from physical boundaries to rhs.                     *
+ * This operation is done for physical as well as cf boundaries,      *
+ * so it is placed in a function.                                     *
+ **********************************************************************
+ */
+
+void CellStokesHypreSolver::add_gAk0_toRhs(
+   const hier::Patch& patch,
+   const tbox::Array<hier::BoundaryBox>& bdry_boxes,
+   const RobinBcCoefStrategy* robin_bc_coef,
+   pdat::CellData<double>& rhs)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS2(d_dim, patch, rhs);
+
+   /*
+    * g*A*k0(a) is the storage for adjustments to be made to the rhs
+    * when we solve. This is the value of the weight of the ghost cell
+    * value for the interior cell, times k0.  It is independent of u,
+    * and so is moved to the rhs.  Before solving, g*A*k0(a) is added
+    * to rhs.
+    */
+   tbox::Pointer<pdat::OutersideData<double> > Ak0;
+
+   tbox::Pointer<geom::CartesianPatchGeometry> pg =
+      patch.getPatchGeometry();
+
+   Ak0 = patch.getPatchData(d_Ak0_id);
+
+   const int n_bdry_boxes = bdry_boxes.getSize();
+   for (int n = 0; n < n_bdry_boxes; ++n) {
+
+      const hier::BoundaryBox& boundary_box = bdry_boxes[n];
+#ifdef DEBUG_CHECK_ASSERTIONS
+      if (boundary_box.getBoundaryType() != 1) {
+         TBOX_ERROR(d_object_name << ": Illegal boundary type in "
+                                  << "CellStokesHypreSolver::add_gAk0_toRhs\n");
+      }
+#endif
+      const int location_index = boundary_box.getLocationIndex();
+      const hier::BoundaryBoxUtils bbu(boundary_box);
+      const hier::BoundaryBox trimmed_boundary_box =
+         bbu.trimBoundaryBox(patch.getBox());
+      const hier::Index& lower = trimmed_boundary_box.getBox().lower();
+      const hier::Index& upper = trimmed_boundary_box.getBox().upper();
+      const hier::Box& rhsbox = rhs.getArrayData().getBox();
+      const hier::Box& Ak0box = Ak0->getArrayData(location_index / 2,
+            location_index % 2).getBox();
+      const hier::Box bccoef_box = bbu.getSurfaceBoxFromBoundaryBox();
+      tbox::Pointer<pdat::ArrayData<double> >
+      acoef_data(NULL);
+      tbox::Pointer<pdat::ArrayData<double> >
+      bcoef_data(NULL);
+      tbox::Pointer<pdat::ArrayData<double> >
+      gcoef_data(new pdat::ArrayData<double>(bccoef_box, 1));
+      static const double fill_time = 0.0;
+      robin_bc_coef->setBcCoefs(acoef_data,
+         bcoef_data,
+         gcoef_data,
+         d_physical_bc_variable,
+         patch,
+         boundary_box,
+         fill_time);
+      /*
+       * Nomenclature for indices: cel=first-cell, gho=ghost,
+       * beg=beginning, end=ending.
+       */
+      if (d_dim == tbox::Dimension(2)) {
+         F77_FUNC(adjustrhs2d, ADJUSTRHS2D) (rhs.getPointer(d_rhs_depth),
+            &rhsbox.lower()[0],
+            &rhsbox.upper()[0],
+            &rhsbox.lower()[1],
+            &rhsbox.upper()[1],
+            Ak0->getPointer(location_index / 2, location_index % 2),
+            &Ak0box.lower()[0],
+            &Ak0box.upper()[0],
+            &Ak0box.lower()[1],
+            &Ak0box.upper()[1],
+            gcoef_data->getPointer(),
+            &bccoef_box.lower()[0],
+            &bccoef_box.upper()[0],
+            &bccoef_box.lower()[1],
+            &bccoef_box.upper()[1],
+            &lower[0], &upper[0],
+            &location_index);
+      } else if (d_dim == tbox::Dimension(3)) {
+         F77_FUNC(adjustrhs3d, ADJUSTRHS3D) (rhs.getPointer(d_rhs_depth),
+            &rhsbox.lower()[0],
+            &rhsbox.upper()[0],
+            &rhsbox.lower()[1],
+            &rhsbox.upper()[1],
+            &rhsbox.lower()[2],
+            &rhsbox.upper()[2],
+            Ak0->getPointer(location_index / 2, location_index % 2),
+            &Ak0box.lower()[0],
+            &Ak0box.upper()[0],
+            &Ak0box.lower()[1],
+            &Ak0box.upper()[1],
+            &Ak0box.lower()[2],
+            &Ak0box.upper()[2],
+            gcoef_data->getPointer(),
+            &bccoef_box.lower()[0],
+            &bccoef_box.upper()[0],
+            &bccoef_box.lower()[1],
+            &bccoef_box.upper()[1],
+            &bccoef_box.lower()[2],
+            &bccoef_box.upper()[2],
+            &lower[0], &upper[0],
+            &location_index);
+      }
+   }
+}
+
+/*
+ *************************************************************************
+ * Create the hypre solver and set it according to the current state.    *
+ *************************************************************************
+ */
+void CellStokesHypreSolver::setupHypreSolver()
+{
+   TBOX_ASSERT(d_mg_data == NULL);
+
+   tbox::SAMRAI_MPI::Comm communicator = d_hierarchy->getDomainMappedBoxLevel().getMPI().getCommunicator();
+
+   if (d_use_smg) {
+      HYPRE_StructSMGCreate(communicator, &d_mg_data);
+      HYPRE_StructSMGSetMemoryUse(d_mg_data, 0);
+      HYPRE_StructSMGSetMaxIter(d_mg_data, d_max_iterations);
+      HYPRE_StructSMGSetTol(d_mg_data, d_relative_residual_tol);
+      HYPRE_StructSMGSetLogging(d_mg_data, 1);
+      HYPRE_StructSMGSetNumPreRelax(d_mg_data,
+         d_num_pre_relax_steps);
+      HYPRE_StructSMGSetNumPostRelax(d_mg_data,
+         d_num_post_relax_steps);
+      HYPRE_StructSMGSetup(d_mg_data,
+         d_matrix,
+         d_linear_rhs,
+         d_linear_sol);
+   } else {
+      HYPRE_StructPFMGCreate(communicator, &d_mg_data);
+      HYPRE_StructPFMGSetMaxIter(d_mg_data, d_max_iterations);
+      HYPRE_StructPFMGSetTol(d_mg_data, d_relative_residual_tol);
+      HYPRE_StructPFMGSetLogging(d_mg_data, 1);
+      HYPRE_StructPFMGSetNumPreRelax(d_mg_data,
+         d_num_pre_relax_steps);
+      HYPRE_StructPFMGSetNumPostRelax(d_mg_data,
+         d_num_post_relax_steps);
+      HYPRE_StructPFMGSetup(d_mg_data,
+         d_matrix,
+         d_linear_rhs,
+         d_linear_sol);
+   }
+}
+
+void CellStokesHypreSolver::destroyHypreSolver()
+{
+   if (d_mg_data != NULL) {
+      if (d_use_smg) {
+         HYPRE_StructSMGDestroy(d_mg_data);
+      } else {
+         HYPRE_StructPFMGDestroy(d_mg_data);
+      }
+      d_mg_data = NULL;
+   }
+}
+
+/*
+ *************************************************************************
+ *                                                                       *
+ * Solve the linear system.  This routine assumes that the boundary      *
+ * conditions and the matrix coefficients have been specified.           *
+ *                                                                       *
+ *************************************************************************
+ */
+
+int CellStokesHypreSolver::solveSystem(
+   const int u,
+   const int f,
+   bool homogeneous_bc)
+{
+   if (d_physical_bc_coef_strategy == NULL) {
+      TBOX_ERROR(
+         d_object_name << ": No BC coefficient strategy object!\n"
+         <<
+         "Use either setBoundaries or setPhysicalBcCoefObject\n"
+         <<
+         "to specify the boundary conidition.  Do it before\n"
+         << "calling solveSystem.");
+   }
+   // Tracer t("CellStokesHypreSolver::solveSystem");
+
+   t_solve_system->start();
+
+   tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(d_ln);
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(u >= 0);
+   TBOX_ASSERT(
+      u < level->getPatchDescriptor()->getMaxNumberRegisteredComponents());
+   TBOX_ASSERT(f >= 0);
+   TBOX_ASSERT(
+      f < level->getPatchDescriptor()->getMaxNumberRegisteredComponents());
+#endif
+
+   if (d_physical_bc_coef_strategy == &d_physical_bc_simple_case) {
+      /*
+       * If we are using the simple bc implementation, the final piece
+       * of information it requires is the Dirichlet boundary value
+       * set in the ghost cells.  Now that we have the ghost cell data,
+       * we can complete the boundary condition setup.
+       */
+      d_physical_bc_simple_case.cacheDirichletData(u);
+   }
+
+   /*
+    * Modify right-hand-side to account for boundary conditions and
+    * copy solution and right-hand-side to HYPRE structures.
+    */
+
+   const hier::IntVector no_ghosts(d_dim, 0);
+   const hier::IntVector ghosts(d_dim, 1);
+
+   /*
+    * At coarse-fine boundaries, we expect ghost cells to have correct
+    * values to be used in our bc, so u provides the ghost cell data.
+    * Assume that the user only provided data for the immediate first
+    * ghost cell, so pass zero for the number of extensions fillable.
+    */
+   d_cf_bc_coef.setGhostDataId(u, hier::IntVector::getZero(d_dim));
+
+   for (hier::PatchLevel::Iterator p(level); p; p++) {
+      tbox::Pointer<hier::Patch> patch = *p;
+
+      const hier::Box box = patch->getBox();
+
+      /*
+       * Set up variable data needed to prepare linear system solver.
+       */
+      tbox::Pointer<pdat::CellData<double> > u_data_ = patch->getPatchData(u);
+#ifdef DEBUG_CHECK_ASSERTIONS
+      TBOX_ASSERT(!u_data_.isNull());
+#endif
+      pdat::CellData<double>& u_data = *u_data_;
+      pdat::CellData<double> rhs_data(box, 1, no_ghosts);
+
+      /*
+       * Copy rhs and solution from the hierarchy into HYPRE structures.
+       * For rhs, add in the contribution from boundary conditions, if
+       * needed.  If boundary condition is homogenous, this only adds
+       * zero, so we skip it.
+       */
+      copyToHypre(d_linear_sol, u_data, d_soln_depth, box);
+      rhs_data.copy(*(patch->getPatchData(f)));
+      if (!homogeneous_bc) {
+         /*
+          * Add g*A*k0(a) from physical and coarse-fine boundaries to rhs.
+          */
+         add_gAk0_toRhs(*patch,
+            patch->getPatchGeometry()->getCodimensionBoundaries(1),
+            d_physical_bc_coef_strategy,
+            rhs_data);
+         add_gAk0_toRhs(*patch,
+            d_cf_boundary->getBoundaries(patch->getGlobalId(), 1),
+            &d_cf_bc_coef,
+            rhs_data);
+      }
+      copyToHypre(d_linear_rhs, rhs_data, d_rhs_depth, box);
+
+   } // end patch loop
+
+   /*
+    * Reset invalid ghost data id to help detect erroneous further use.
+    */
+   d_cf_bc_coef.setGhostDataId(-1, hier::IntVector::getZero(d_dim));
+
+   /*
+    * Finish assembly of the vectors
+    */
+   HYPRE_StructVectorAssemble(d_linear_sol);
+
+   HYPRE_StructVectorAssemble(d_linear_rhs);
+
+   /*
+    * Solve the system - zero means convergence
+    * Solve takes the same arguments as Setup
+    */
+
+   if (d_print_solver_info) {
+      HYPRE_StructVectorPrint("sol0.out", d_linear_sol, 1);
+      HYPRE_StructMatrixPrint("mat0.out", d_matrix, 1);
+      HYPRE_StructVectorPrint("rhs.out", d_linear_rhs, 1);
+   }
+
+   if (d_use_smg) {
+      // HYPRE_StructSMGSetMaxIter(d_mg_data, d_max_iterations);
+      HYPRE_StructSMGSetTol(d_mg_data, d_relative_residual_tol);
+      /* converge = */ HYPRE_StructSMGSolve(d_mg_data,
+         d_matrix,
+         d_linear_rhs,
+         d_linear_sol);
+   } else {
+      // HYPRE_StructPFMGSetMaxIter(d_mg_data, d_max_iterations);
+      HYPRE_StructPFMGSetTol(d_mg_data, d_relative_residual_tol);
+      /* converge = */ HYPRE_StructPFMGSolve(d_mg_data,
+         d_matrix,
+         d_linear_rhs,
+         d_linear_sol);
+   }
+
+   if (d_print_solver_info) {
+      HYPRE_StructMatrixPrint("mat.out", d_matrix, 1);
+      HYPRE_StructVectorPrint("sol.out", d_linear_sol, 1);
+   }
+
+   if (d_use_smg) {
+      HYPRE_StructSMGGetNumIterations(d_mg_data,
+         &d_number_iterations);
+      HYPRE_StructSMGGetFinalRelativeResidualNorm(d_mg_data,
+         &d_relative_residual_norm);
+   } else {
+      HYPRE_StructPFMGGetNumIterations(d_mg_data,
+         &d_number_iterations);
+      HYPRE_StructPFMGGetFinalRelativeResidualNorm(d_mg_data,
+         &d_relative_residual_norm);
+   }
+
+   /*
+    * Pull the solution vector out of the HYPRE structures
+    */
+   for (hier::PatchLevel::Iterator ip(level); ip; ip++) {
+      tbox::Pointer<hier::Patch> patch = *ip;
+      tbox::Pointer<pdat::CellData<double> > u_data_ = patch->getPatchData(u);
+      pdat::CellData<double>& u_data = *u_data_;
+      copyFromHypre(u_data,
+         d_soln_depth,
+         d_linear_sol,
+         patch->getBox());
+   }
+
+   t_solve_system->stop();
+
+   return d_relative_residual_norm <= d_relative_residual_tol;
+}
+
+void CellStokesHypreSolver::computeDiagonalEntries(
+   pdat::CellData<double>& diagonal,
+   const pdat::CellData<double>& C_data,
+   const pdat::SideData<double>& off_diagonal,
+   const hier::Box& patch_box)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(d_dim,
+      diagonal,
+      C_data,
+      off_diagonal,
+      patch_box);
+
+   const hier::Index patch_lo = patch_box.lower();
+   const hier::Index patch_up = patch_box.upper();
+   const double c = 1.0, d = 1.0;
+   if (d_dim == tbox::Dimension(2)) {
+      F77_FUNC(compdiagvariablec2d, COMPDIAGVARIABLEC2D) (diagonal.getPointer(),
+         C_data.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &c, &d);
+   } else if (d_dim == tbox::Dimension(3)) {
+      F77_FUNC(compdiagvariablec3d, COMPDIAGVARIABLEC3D) (diagonal.getPointer(),
+         C_data.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         off_diagonal.getPointer(2),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &patch_lo[2], &patch_up[2],
+         &c, &d);
+   }
+}
+
+void CellStokesHypreSolver::computeDiagonalEntries(
+   pdat::CellData<double>& diagonal,
+   const double C,
+   const pdat::SideData<double>& off_diagonal,
+   const hier::Box& patch_box)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS3(d_dim, diagonal, off_diagonal, patch_box);
+
+   const hier::Index patch_lo = patch_box.lower();
+   const hier::Index patch_up = patch_box.upper();
+   const double c = 1.0, d = 1.0;
+   if (d_dim == tbox::Dimension(2)) {
+      F77_FUNC(compdiagscalarc2d, COMPDIAGSCALARC2D) (diagonal.getPointer(),
+         &C,
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &c, &d);
+   } else if (d_dim == tbox::Dimension(3)) {
+      F77_FUNC(compdiagscalarc3d, COMPDIAGSCALARC3D) (diagonal.getPointer(),
+         &C,
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         off_diagonal.getPointer(2),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &patch_lo[2], &patch_up[2],
+         &c, &d);
+   } else {
+      TBOX_ERROR("CellStokesHypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void CellStokesHypreSolver::computeDiagonalEntries(
+   pdat::CellData<double>& diagonal,
+   const pdat::SideData<double>& off_diagonal,
+   const hier::Box& patch_box)
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS3(d_dim, diagonal, off_diagonal, patch_box);
+
+   const hier::Index patch_lo = patch_box.lower();
+   const hier::Index patch_up = patch_box.upper();
+   const double c = 1.0, d = 1.0;
+   if (d_dim == tbox::Dimension(2)) {
+      F77_FUNC(compdiagzeroc2d, COMPDIAGZEROC2D) (diagonal.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &c, &d);
+   } else if (d_dim == tbox::Dimension(3)) {
+      F77_FUNC(compdiagzeroc3d, COMPDIAGZEROC3D) (diagonal.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         off_diagonal.getPointer(2),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &patch_lo[2], &patch_up[2],
+         &c, &d);
+   } else {
+      TBOX_ERROR("CellStokesHypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void CellStokesHypreSolver::adjustBoundaryEntries(
+   pdat::CellData<double>& diagonal,
+   const pdat::SideData<double>& off_diagonal,
+   const hier::Box& patch_box,
+   const pdat::ArrayData<double>& acoef_data,
+   const pdat::ArrayData<double>& bcoef_data,
+   const hier::Box bccoef_box,
+   pdat::ArrayData<double>& Ak0_data,
+   const hier::BoundaryBox& trimmed_boundary_box,
+   const double h[tbox::Dimension::MAXIMUM_DIMENSION_VALUE])
+{
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS8(d_dim, diagonal, off_diagonal, patch_box,
+      acoef_data, bcoef_data,
+      bccoef_box, Ak0_data, trimmed_boundary_box);
+
+   const hier::Index patch_lo = patch_box.lower();
+   const hier::Index patch_up = patch_box.upper();
+   const int location_index = trimmed_boundary_box.getLocationIndex();
+   const hier::Index& lower = trimmed_boundary_box.getBox().lower();
+   const hier::Index& upper = trimmed_boundary_box.getBox().upper();
+   const hier::Box& Ak0_box = Ak0_data.getBox();
+   if (d_dim == tbox::Dimension(2)) {
+      F77_FUNC(adjbdry2d, ADJBDRY2D) (diagonal.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         acoef_data.getPointer(),
+         bcoef_data.getPointer(),
+         &bccoef_box.lower()[0],
+         &bccoef_box.upper()[0],
+         &bccoef_box.lower()[1],
+         &bccoef_box.upper()[1],
+         Ak0_data.getPointer(),
+         &Ak0_box.lower()[0],
+         &Ak0_box.upper()[0],
+         &Ak0_box.lower()[1],
+         &Ak0_box.upper()[1],
+         &lower[0], &upper[0],
+         &location_index, h);
+   } else if (d_dim == tbox::Dimension(3)) {
+      F77_FUNC(adjbdry3d, ADJBDRY3D) (diagonal.getPointer(),
+         off_diagonal.getPointer(0),
+         off_diagonal.getPointer(1),
+         off_diagonal.getPointer(2),
+         &patch_lo[0], &patch_up[0],
+         &patch_lo[1], &patch_up[1],
+         &patch_lo[2], &patch_up[2],
+         acoef_data.getPointer(),
+         bcoef_data.getPointer(),
+         &bccoef_box.lower()[0],
+         &bccoef_box.upper()[0],
+         &bccoef_box.lower()[1],
+         &bccoef_box.upper()[1],
+         &bccoef_box.lower()[2],
+         &bccoef_box.upper()[2],
+         Ak0_data.getPointer(),
+         &Ak0_box.lower()[0],
+         &Ak0_box.upper()[0],
+         &Ak0_box.lower()[1],
+         &Ak0_box.upper()[1],
+         &Ak0_box.lower()[2],
+         &Ak0_box.upper()[2],
+         &lower[0], &upper[0],
+         &location_index, h);
+   } else {
+      TBOX_ERROR("CellStokesHypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void
+CellStokesHypreSolver::finalizeCallback()
+{
+   for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
+      s_Ak0_var[d].setNull();
+   }
+}
+
+}
+}
+
+#endif
+#endif
diff -r a44a82f15794 -r fe2a9230921b StokesHypreSolver.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesHypreSolver.I	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,121 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Level solver for diffusion-like elliptic problems. 
+ *
+ ************************************************************************/
+namespace SAMRAI {
+namespace solv {
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setSolnIdDepth(
+   const int depth) {
+   d_soln_depth = depth;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setRhsIdDepth(
+   const int depth) {
+   d_rhs_depth = depth;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setUseSMG(
+   bool use_smg) {
+   d_use_smg = use_smg;
+}
+
+/*
+ ********************************************************************
+ * Specify bc using the default internal bc coefficient object.     *
+ * Clear up data supporting external bc coefficient setter.         *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setBoundaries(
+   const std::string& boundary_type,
+   const int fluxes,
+   const int flags,
+   int* bdry_types)
+{
+   d_physical_bc_simple_case.setBoundaries(boundary_type,
+      fluxes,
+      flags,
+      bdry_types);
+   d_physical_bc_coef_strategy = &d_physical_bc_simple_case;
+   d_physical_bc_variable.setNull();
+}
+
+/*
+ ********************************************************************
+ * Set the physical boundary condition object.                      *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setPhysicalBcCoefObject(
+   const RobinBcCoefStrategy* physical_bc_coef_strategy,
+   const tbox::Pointer<hier::Variable> variable)
+{
+   d_physical_bc_coef_strategy = physical_bc_coef_strategy;
+   d_physical_bc_variable = variable;
+}
+
+SAMRAI_INLINE_KEYWORD
+int CellStokesHypreSolver::getNumberOfIterations() const
+{
+   return d_number_iterations;
+}
+
+SAMRAI_INLINE_KEYWORD
+double CellStokesHypreSolver::getRelativeResidualNorm() const
+{
+   return d_relative_residual_norm;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setNumPreRelaxSteps(
+   const int steps)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!d_hierarchy.isNull());
+#endif
+   d_num_pre_relax_steps = steps;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setNumPostRelaxSteps(
+   const int steps)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!d_hierarchy.isNull());
+#endif
+   d_num_post_relax_steps = steps;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setPrintSolverInfo(
+   const bool print)
+{
+   d_print_solver_info = print;
+}
+
+SAMRAI_INLINE_KEYWORD
+void CellStokesHypreSolver::setStoppingCriteria(
+   const int max_iterations,
+   const double residual_tol)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(max_iterations >= 0);
+   TBOX_ASSERT(residual_tol >= 0.0);
+#endif
+   d_max_iterations = max_iterations;
+   d_relative_residual_tol = residual_tol;
+}
+
+}
+}
diff -r a44a82f15794 -r fe2a9230921b StokesHypreSolver.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StokesHypreSolver.h	Fri Dec 31 12:10:26 2010 -0800
@@ -0,0 +1,617 @@
+/*************************************************************************
+ *
+ * This file is part of the SAMRAI distribution.  For full copyright 
+ * information, see COPYRIGHT and COPYING.LESSER. 
+ *
+ * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
+ * Description:   Hypre solver interface for diffusion-like elliptic problems. 
+ *
+ ************************************************************************/
+#ifndef included_solv_StokesHypreSolver
+#define included_solv_StokesHypreSolver
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#ifdef HAVE_HYPRE
+
+#ifndef included_HYPRE_struct_ls
+/*
+ * This might break things if F77_FUNC_ is different for hypre vs
+ * SAMRAI autoconf detection.  But then C/C++ macros are totally
+ * broken due to namespace collision as this example highlights so
+ * resorting to hacks are necessary.
+ */
+#ifdef F77_FUNC_
+#undef F77_FUNC_
+#endif
+#include "HYPRE_struct_ls.h"
+#define included_HYPRE_struct_ls
+#endif
+
+#include "SAMRAI/solv/GhostCellRobinBcCoefs.h"
+#include "SAMRAI/solv/RobinBcCoefStrategy.h"
+#include "StokesSpecifications.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/OutersideVariable.h"
+#include "SAMRAI/hier/BoxList.h"
+#include "SAMRAI/hier/CoarseFineBoundary.h"
+#include "SAMRAI/hier/PatchHierarchy.h"
+#include "SAMRAI/hier/PatchLevel.h"
+#include "SAMRAI/hier/VariableContext.h"
+#include "SAMRAI/tbox/Database.h"
+#include "SAMRAI/tbox/Pointer.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace solv {
+
+/*!
+ * @brief Use the HYPRE preconditioner library to solve (the cell-centered)
+ * Stokes's equation on a single level in a hierarchy.
+ *
+ * Class CellStokesHypreSolver uses the HYPRE preconditioner library
+ * to solve linear equations of the form
+ * @f$ \nabla ( D \nabla u ) + C u = f @f$, where
+ * C is a cell-centered array, D is a face-centered array,
+ * and u and f are cell-centered arrays
+ * (see StokesSpecifications).
+ * The discretization is the standard second order
+ * finite difference stencil.
+ *
+ * Robin boundary conditions are used through the
+ * interface class RobinBcCoefStrategy.
+ * Periodic boundary conditions are not supported yet.
+ *
+ * The user must perform the following steps to use
+ * CellStokesHypreSolver:
+ * - Create a CellStokesHypreSolver object.
+ * - Initialize CellStokesHypreSolver object with a patch hierarchy,
+ *   using the function initializeSolverState().
+ * - Use the functions setPhysicalBcCoefObject()
+ *   to provide implementations of RobinBcCoefStrategy.
+ *   (For most problems you can probably find a suitable
+ *   implementation to use without implementing the
+ *   strategy yourself.  See for example
+ *   SimpleCellRobinBcCoefs and GhostCellRobinBcCoefs.)
+ * - Set the matrix coefficients in the linear system,
+ *   using the function setMatrixCoefficients().
+ * - Specify the stopping criteria using setStoppingCriteria().
+ * - Solve the linear system, passing in u and f as the patch
+ *   indices of the solution and the right hand side, respectively.
+ *
+ * Sample parameters for initialization from database (and their
+ * default values):
+ * @verbatim
+ *     print_solver_info = FALSE      // Whether to print some data for debugging
+ *     max_iterations = 10            // Max iterations used by Hypre
+ *     relative_residual_tol = 1.0e-8 // Residual tolerance used by Hypre
+ *     num_pre_relax_steps = 1        // # of presmoothing steps used by Hypre
+ *     num_post_relax_steps = 1       // # of postsmoothing steps used by Hypre
+ *     use_smg = FALSE                // Whether to use hypre's smg solver
+ *                                    // (alternative is the pfmg solver)
+ * @endverbatim
+ */
+
+class CellStokesHypreSolver
+{
+public:
+   /*!
+    * @brief Constructor.
+    *
+    * @param object_name Name of object.
+    * @param database tbox::Database for input.
+    */
+   CellStokesHypreSolver(
+      const tbox::Dimension& dim,
+      const std::string& object_name,
+      tbox::Pointer<tbox::Database> database =
+         tbox::Pointer<tbox::Database>(NULL));
+
+   /*!
+    * The Stokes destructor releases all internally managed data.
+    */
+   ~CellStokesHypreSolver();
+
+   /*!
+    * @brief Initialize to a given hierarchy.
+    *
+    * Initializer Stokes solver for a patch level in a hierarchy.
+    *
+    * @param hierarchy Hierarchy
+    * @param ln Level number
+    */
+   void
+   initializeSolverState(
+      tbox::Pointer<hier::PatchHierarchy> hierarchy,
+      int ln = 0);
+
+   /*!
+    * @brief Reset to an uninitialized state.
+    */
+   void
+   deallocateSolverState();
+
+   /*!
+    * @brief Set the matrix coefficients
+    *
+    * For information describing the Stokes equation parameters,
+    * see the light-weight StokesSpecifications class where
+    * you set the values of C and D.
+    *
+    * This method must be called before solveSystem().
+    */
+   void
+   setMatrixCoefficients(
+      const StokesSpecifications& spec);
+
+   /*!
+    * @brief Set default depth of the solution data involved in the solve.
+    *
+    * If the solution data has multiple depths,
+    * the solver uses just one depth at a time.
+    * The default depth is the first depth.
+    * Use this function to change it.
+    * This is not used to set the depth of the data (which is not
+    * controled by this class) but the depth used in the solve.
+    *
+    * Changing the depth after setting up the matrix is permissible,
+    * as the solution data does not affect the matrix.
+    */
+   void
+   setSolnIdDepth(
+      const int depth);
+
+   /*!
+    * @brief Set default depth of the rhs data involved in the solve.
+    *
+    * If the rhs data has multiple depths,
+    * the solver uses just one depth at a time.
+    * The default depth is the first depth.
+    * Use this function to change it.
+    * This is not used to set the depth of the data (which is not
+    * controled by this class) but the depth used in the solve.
+    *
+    * Changing the depth after setting up the matrix is permissible,
+    * as the rhs data does not affect the matrix.
+    */
+   void
+   setRhsIdDepth(
+      const int depth);
+
+   /*!
+    * @brief Set the stopping criteria (max iterations and residual
+    * tolerance) for the linear solver.
+    *
+    * @param max_iterations gives the maximum number of iterations
+    * @param relative_residual_tol the maximum error tolerance
+    */
+   void
+   setStoppingCriteria(
+      const int max_iterations = 10,
+      const double relative_residual_tol = 1.0e-6);
+
+   /*!
+    * @brief Solve the linear system Au=f.
+    *
+    * The solution u and the right hand side f are
+    * specified via patch indices on the patch hierarchy.
+    *
+    * Member functions getNumberOfIterations() return the iterations
+    * from the solver.
+    * Note that the matrix coefficients and boundary condition object
+    * must have been set up before this function is called.
+    * As long as the matrix coefficients do not change,
+    * this routine may be called repeatedly to solve any number of linear
+    * systems (with the right-hand side varying).
+    * If the boundary conditions or matrix coefficients are changed
+    * then function setMatrixCoefficients() must be called again.
+    *
+    * When computing the matrix coefficients in setMatrixCoefficients(),
+    * the inhomogeneous portion of the boundary condition (constant
+    * terms, independent of u and thus having no effect on the matrix)
+    * are saved and added to the source term, f,
+    * before performing the matrix solve.  In some situations, it may be
+    * useful to not add the inhomogeneous portion to f.  The flag argument
+    * @c homoegneous_bc is used for this.  (This is a sort of optimization,
+    * to avoid having to re-call setMatrixCoefficients() to change the
+    * inhomogeneous portion.)
+    *
+    * @param u Descriptor of cell-centered unknown variable.
+    * @param f Descriptor of cell-centered source variable.
+    * @param homogeneous_bc Whether homogeneous boundary conditions
+    *        are assumed.
+    *
+    * @return whether solver converged to specified level
+    */
+   int
+   solveSystem(
+      const int u,
+      const int f,
+      bool homogeneous_bc = false);
+
+   /*!
+    * @brief Return the number of iterations taken by the solver to converge.
+    *
+    * @return number of iterations taken by the solver to converge
+    */
+   int
+   getNumberOfIterations() const;
+
+   /*!
+    * @brief Set the number of pre-relax steps used by the Hypre solve.
+    */
+   void
+   setNumPreRelaxSteps(
+      const int steps);
+
+   /*!
+    * @brief Set the number of post-relax steps used by the Hypre solve.
+    */
+   void
+   setNumPostRelaxSteps(
+      const int steps);
+
+   /*!
+    * @brief Return the final residual norm returned by the Hypre solve.
+    * @return final residual norm returned by the Hypre solve.
+    */
+   double
+   getRelativeResidualNorm() const;
+
+   /*!
+    * @brief Set whether to use Hypre's PFMG algorithm instead of the
+    * SMG algorithm.
+    *
+    * The flag is used to select which of HYPRE's linear solver algorithms
+    * to use if true, the semicoarsening multigrid algorithm is used, and if
+    * false, the "PF" multigrid algorithm is used.
+    * By default, the SMG algorithm is used.
+    *
+    * Changing the algorithm must be done before setting up the matrix
+    * coefficients.
+    */
+   void
+   setUseSMG(
+      bool use_smg);
+
+   /*!
+    * @brief Specify boundary condition directly, without using
+    * a RobinBcCoefStrategy object.
+    *
+    * Use @em either setBoundaries() @em or setPhysicalBcCoefObject(),
+    * but not both.
+    *
+    * A SimpleCelBcCoef object is used to interpret and implement
+    * the specified boundary conditions.
+    * See SimpleCellRobinBcCoefs::setBoundaries()
+    * for an explanation of the arguments.
+    */
+   void
+   setBoundaries(
+      const std::string& boundary_type,
+      const int fluxes = -1,
+      const int flags = -1,
+      int* bdry_types = NULL);
+
+   /*!
+    * @brief Specify boundary condition through the use of a
+    * Robin boundary condition object.
+    *
+    * Use @em either setBoundaries() @em or setPhysicalBcCoefObject(),
+    * but not both.
+    *
+    * The Robin boundary condition object is used when setting
+    * the matrix coefficient and when solving the system.
+    * If your boundary conditions are fixed values at ghost
+    * cell centers, use the GhostCellRobinBcCoefs
+    * implementation of the RobinBcCoefStrategy strategy.
+    *
+    * @param physical_bc_coef_strategy tbox::Pointer a concrete
+    *        implementation of the Robin bc strategy.
+    * @param variable hier::Variable pointer to be passed
+    *        to RobinBcCoefStrategy::setBcCoefs(),
+    *        but otherwise unused by this class.
+    */
+   void
+   setPhysicalBcCoefObject(
+      const RobinBcCoefStrategy* physical_bc_coef_strategy,
+      const tbox::Pointer<hier::Variable> variable =
+         tbox::Pointer<hier::Variable>(NULL));
+
+   /*!
+    * @brief Set the flag for printing solver information.
+    *
+    * This optional function is used primarily for debugging.
+    *
+    * If set true, it will print the HYPRE matrix information
+    * to the following files:
+    *
+    * - mat_bA.out - before setting matrix coefficients in matrix assemble
+    * - mat_aA.out - after setting matrix coefficients in matrix assemble
+    * - sol0.out   - u before solve (i.e. for system Au = b)
+    * - sol.out    - u after solve
+    * - mat0.out   - A before solve
+    * - mat.out    - A after solve
+    * - rhs.out    - b before and after solve
+    *
+    * If this method is not called, or the flag is set false, no printing
+    * will occur.
+    */
+   void
+   setPrintSolverInfo(
+      const bool print);
+
+private:
+   /*!
+    * @brief Set state using database
+    *
+    * See the class description for the parameters that can be set
+    * from a database.
+    *
+    * @param database Input database.  If a NULL pointer is given,
+    * nothing is done.
+    */
+   void
+   getFromInput(
+      tbox::Pointer<tbox::Database> database);
+
+   void
+   setupHypreSolver();
+   void
+   destroyHypreSolver();
+   void
+   allocateHypreData();
+   void
+   deallocateHypreData();
+
+   void
+   copyToHypre(
+      HYPRE_StructVector vector,
+      pdat::CellData<double>& src,
+      int depth,
+      const hier::Box& box);
+   void
+   copyFromHypre(
+      pdat::CellData<double>& dst,
+      int depth,
+      HYPRE_StructVector vector,
+      const hier::Box box);
+
+   /*!
+    * @brief Add g*A*k0(a) from boundaries to rhs.
+    *
+    * Move the constant portion of the boundary condition
+    * contribution to the right hand side and add it to the existing rhs.
+    * This operation is done for physical as well as cf boundaries,
+    * so it is placed in a function.
+    *
+    * The boundary boxes given must be to either the physical
+    * boundary or coarse-fine boundary for the patch.  The
+    * bc coefficient implementation should correspond to the
+    * boundary being worked on.
+    */
+   void
+   add_gAk0_toRhs(
+      const hier::Patch& patch,
+      const tbox::Array<hier::BoundaryBox>& bdry_boxes,
+      const RobinBcCoefStrategy* robin_bc_coef,
+      pdat::CellData<double>& rhs);
+
+   //@{
+
+   /*!
+    * @name Dimension-independent functions to organize Fortran interface.
+    */
+
+   //! @brief Compute diagonal entries of the matrix when C is variable.
+   void
+   computeDiagonalEntries(
+      pdat::CellData<double>& diagonal,
+      const pdat::CellData<double>& C_data,
+      const pdat::SideData<double>& variable_off_diagonal,
+      const hier::Box& patch_box);
+   //! @brief Compute diagonal entries of the matrix when C is constant.
+   void
+   computeDiagonalEntries(
+      pdat::CellData<double>& diagonal,
+      const double C,
+      const pdat::SideData<double>& variable_off_diagonal,
+      const hier::Box& patch_box);
+   //! @brief Compute diagonal entries of the matrix when C is zero.
+   void
+   computeDiagonalEntries(
+      pdat::CellData<double>& diagonal,
+      const pdat::SideData<double>& variable_off_diagonal,
+      const hier::Box& patch_box);
+   /*!
+    * @brief Adjust boundary entries for variable off-diagonals.
+    *
+    * At the same time, save information that are needed to adjust
+    * the rhs.
+    */
+   void
+   adjustBoundaryEntries(
+      pdat::CellData<double>& diagonal,
+      const pdat::SideData<double>& variable_off_diagonal,
+      const hier::Box& patch_box,
+      const pdat::ArrayData<double>& acoef_data,
+      const pdat::ArrayData<double>& bcoef_data,
+      const hier::Box bccoef_box,
+      pdat::ArrayData<double>& Ak0_data,
+      const hier::BoundaryBox& trimmed_boundary_box,
+      const double h[tbox::Dimension::MAXIMUM_DIMENSION_VALUE]);
+
+   //@}
+
+   //! @brief Free static variables at shutdown time.
+   static void
+   finalizeCallback();
+
+   /*!
+    * @brief Object dimension.
+    */
+   const tbox::Dimension d_dim;
+
+   /*!
+    * @brief Object name.
+    */
+   std::string d_object_name;
+
+   /*!
+    * @brief Associated hierarchy.
+    */
+   tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
+
+   /*!
+    * @brief Associated level number.
+    *
+    * Currently, this must be level number 0.
+    */
+   int d_ln;
+
+   /*!
+    * @brief Scratch context for this object.
+    */
+   tbox::Pointer<hier::VariableContext> d_context;
+
+   //@{ @name Boundary condition handling
+
+   /*!
+    * @brief The coarse-fine boundary description for level d_ln.
+    *
+    * The coarse-fine boundary is computed when the operator
+    * state is initialized.  It is used to allow solves on
+    * levels that are not the coarsest in the hierarchy.
+    */
+   tbox::Pointer<hier::CoarseFineBoundary> d_cf_boundary;
+
+   /*!
+    * @brief Robin boundary coefficient object for physical
+    * boundaries.
+    *
+    * If d_physical_bc_coef_strategy is set, use it, otherwise,
+    * use d_physical_bc_simple_case.
+    */
+   const RobinBcCoefStrategy* d_physical_bc_coef_strategy;
+   tbox::Pointer<hier::Variable> d_physical_bc_variable;
+
+   /*!
+    * @brief Implementation of Robin boundary conefficients
+    * for the case of simple boundary conditions.
+    */
+   SimpleCellRobinBcCoefs d_physical_bc_simple_case;
+
+   /*!
+    * @brief Robin boundary coefficient object for coarse-fine
+    * boundaries.
+    *
+    * This is a GhostCellRobinBcCoefs object because we
+    * expect the users to have the correct ghost cell values
+    * in the coarse-fine boundaries before solving.
+    */
+   GhostCellRobinBcCoefs d_cf_bc_coef;
+   tbox::Pointer<hier::Variable> d_coarsefine_bc_variable;
+
+   //@}
+
+   /*!
+    * @brief hier::Patch index of A*k0(a) quantity
+    *
+    * A*k0(a) is the quantity that is saved for
+    * later adding to the rhs.
+    *
+    * The Robin bc is expressed by the coefficients a and g
+    * on the boundary (see RobinBcCoefStrategy).
+    * This class uses a central difference approximation of
+    * the Robin bc, which results in the value at a ghost cell,
+    * uo, being writen as uo = g*k0(a) + k1(a)*ui, where ui is
+    * the first interior cell value, k0 and k1 depend on a as
+    * indicated.
+    *
+    * In setting up the Au=f system, the contribution of k1(a)*ui
+    * is incorporated into the product Au.  The contribution of
+    * A*g*k0(a) should be moved to the right hand side and saved for
+    * later adding to f.  However, the value of g is not provided
+    * until solve time.  Therefore, we save just A*k0(a) at the
+    * patch data index d_Ak0_id.
+    */
+   int d_Ak0_id;
+
+   static tbox::Pointer<pdat::OutersideVariable<double> > s_Ak0_var[tbox::
+                                                                    Dimension::
+                                                                    MAXIMUM_DIMENSION_VALUE];
+
+   /*!
+    * @brief Depth of the solution variable.
+    */
+   int d_soln_depth;
+
+   /*!
+    * @brief Depth of the rhs variable.
+    */
+   int d_rhs_depth;
+
+   int d_max_iterations;
+   double d_relative_residual_tol;
+
+   int d_number_iterations; // iterations in solver
+   int d_num_pre_relax_steps;  // pre-relax steps in solver
+   int d_num_post_relax_steps; // post-relax steps in solver
+   double d_relative_residual_norm;  // norm from solver
+
+   /*@
+    * @brief Flag to use SMG or PFMG (default)
+    */
+   bool d_use_smg;
+
+   //@{
+   //! @name Hypre object
+   //! @brief HYPRE grid
+   HYPRE_StructGrid d_grid;
+   //! @brief HYPRE stencil
+   HYPRE_StructStencil d_stencil;
+   //! @brief HYPRE structured matrix
+   HYPRE_StructMatrix d_matrix;
+   //! @brief Hypre RHS vector for linear solves
+   HYPRE_StructVector d_linear_rhs;
+   //! @brief Hypre solution vector
+   HYPRE_StructVector d_linear_sol;
+   //! @brief Hypre SMG solver data
+   HYPRE_StructSolver d_mg_data;
+   //@}
+
+   //@{
+
+   //! @name Variables for debugging and analysis.
+
+   /*!
+    * @brief Flag to print solver info
+    *
+    * See setPrintSolverInfo().
+    */
+   bool d_print_solver_info;
+
+   //@}
+
+   /*!
+    * @brief Timers for performance measurement.
+    */
+   tbox::Pointer<tbox::Timer> t_solve_system;
+   tbox::Pointer<tbox::Timer> t_set_matrix_coefficients;
+
+   static tbox::StartupShutdownManager::Handler s_finalize_handler;
+};
+
+}
+} // namespace SAMRAI
+
+#ifdef SAMRAI_INLINE
+#include "StokesHypreSolver.I"
+#endif
+
+#endif
+
+#endif



More information about the CIG-COMMITS mailing list